AGENTS.md
Repo guidance for agentic coding agents working in /Users/fortune/MUTX.
Rule Files
No
.cursorrulesfile exists.No files exist under
.cursor/rules/.No
.github/copilot-instructions.mdfile exists.
Repo Map
app/: Next.js 14 App Router frontend.app/api/: Next.js route handlers that proxy or handle website requests.components/: shared React UI components.lib/: shared TypeScript utilities; currentlylib/utils.tsonly.src/api/: FastAPI backend, models, services, middleware, and integrations.cli/: Click-based Python CLI.sdk/mutx/: Python SDK package.tests/api/: pytest API tests.tests/website.spec.ts: Playwright smoke tests.infrastructure/: Terraform, Ansible, monitoring, and related Make targets.
Ground Truth And Known Drift
Trust source code and config over README/docs when they disagree.
FastAPI routes are mounted at plain prefixes like
/auth,/agents, and/deployments; there is no global/v1backend prefix.docs/api/AGENTS.mdis stale:POST /agentsno longer acceptsuser_idfrom the request body, and auth dependencies are attached.Parts of the SDK and older docs still assume
/v1routes; check the live route code before copying examples.Frontend linting is currently broken:
next lintand directeslintboth fail with the checked-in ESLint 10 plus.eslintrc.jsonsetup.npm run buildworks because it usesnext build --no-lint.tests/conftest.pyis stale againstsrc/api/models/models.py; pytest collects tests, but runtime execution currently fails because fixtures still passusernameandhashed_passwordtoUser.tests/website.spec.tshitshttps://mutx.devdirectly; treat Playwright as production smoke testing unless you rewrite it.scripts/test.shruns the current trusted validation baseline instead ofnpm test, which does not exist inpackage.json.
Setup And Environment
CI uses Node 20 for frontend checks.
CI uses Python 3.11 for backend checks; root package requires
>=3.10, SDK declares>=3.9.Common bootstrap:
Full local stack:
./dev.shBackend only:
uvicorn src.api.main:app --reload --port 8000Frontend only:
npm run dev
Build, Lint, And Test Commands
Frontend
npm run buildperforms a production build and type validation, but skips lint via--no-lint.npm run lintis the intended lint command, but it currently fails with the checked-in dependency/config combination.There is no reliable single-file frontend lint command until ESLint is migrated to flat config or downgraded.
Python checks
If
rufforblackis missing, install dev extras withpip install -e ".[dev]".
Pytest API tests
Single-test shape:
path/to/test_file.py::TestClass::test_name.Current reality: collection works, but execution is failing because fixtures do not match the current
Usermodel.
Playwright smoke tests
tests/website.spec.tsis the only Playwright spec right now.The spec hardcodes
https://mutx.dev, so it exercises production rather than a local dev server.
Infrastructure
Direct Terraform also works, for example
terraform -chdir=infrastructure/terraform plan ....
Code Style
Make minimal, targeted changes; do not do repo-wide cleanup unless asked.
Preserve file-local style when the repo is inconsistent.
Prefer source code and config over prose docs.
Keep website/frontend behavior in
app/and backend control-plane behavior insrc/api/.If you change API routes or payloads, check the CLI, SDK, docs, and tests for drift.
Imports
TypeScript: group external and Next imports before local
@/imports.TypeScript: prefer
@/aliases over deep relative imports in app code.TypeScript: keep type-only imports explicit when useful, for example
import { type Sql } from 'postgres'.Python: prefer stdlib, then third-party, then local imports in new files, but do not churn existing files just to reorder imports.
Python backend package-boundary imports usually use absolute
from src.api...imports.Avoid wildcard imports.
TypeScript and Next.js
tsconfig.jsonhasstrict: true; prefer explicit props, exported helper signatures, and narrow unions overany.Use PascalCase for React components and exported types.
Use camelCase for variables, functions, and local helpers.
App code usually uses 2-space indentation, single quotes, and no semicolons.
Some non-app files, especially Playwright specs, use semicolons; preserve the local file style instead of normalizing everything.
Use default exports for
page.tsx,layout.tsx, and route modules that require them; otherwise prefer named exports.Add
'use client'only when hooks, browser APIs, or client-side libraries require it.Keep Tailwind classes inline in JSX; there is no separate styling abstraction here.
Reuse existing helpers like
cn()fromlib/utils.tsinstead of reimplementing class merging.In
app/api/**/route.ts, validate early, branch on auth/input quickly, and returnNextResponse.json(...)with explicit status codes.When proxying upstream API calls, preserve upstream status codes when possible and surface concise JSON errors.
Keep raw exceptions out of user-facing UI; store friendly error strings in component state.
Python API
Use 4-space indentation and keep lines within the 100-character Black/Ruff target.
Add type hints to public functions, async route handlers, and schema/model-facing code.
Use snake_case for modules, functions, variables, and fixtures.
Use PascalCase for classes, Pydantic schemas, SQLAlchemy models, and enums.
Prefer Pydantic v2 style with
model_config = ConfigDict(...)for new schemas.SQLAlchemy models use typed
Mapped[...]andmapped_column(...); follow that pattern in new model fields.Keep FastAPI route handlers thin: validate inputs, load dependencies, call services/helpers, and return schemas or serialized payloads.
Use
HTTPExceptionfor expected 400/401/403/404 cases.Use
logging.getLogger(__name__)for backend logging; do not add ad hocprint(...)calls.Preserve async DB patterns:
AsyncSession,await db.execute(...),await db.commit(), andawait db.refresh(...).Be careful with blocking I/O inside async code.
CLI and SDK
CLI commands live under Click groups; follow existing
@click.groupand@click.commandpatterns.Keep CLI output concise and human-readable with
click.echo.For CLI failures, prefer actionable
click.echo(..., err=True)messages over raw tracebacks.CLI code currently branches on
response.status_code; follow that local pattern unless you are intentionally refactoring the file.SDK classes are thin wrappers around JSON payloads; keep them small and ergonomic.
SDK methods generally call
response.raise_for_status()and then wrapresponse.json()into typed objects; keep that pattern.Watch for route drift: parts of the SDK still default to
/v1URLs even though the backend currently exposes unversioned routes.
Tests and validation
Pytest tests are class-based
pytest-asynciotests usingAsyncClientwithASGITransportand in-memory SQLite fixtures.Playwright tests are smoke-style and currently target production.
There is no
npm testscript inpackage.json.Good backend validation:
ruff check src/api/routes/agents.py,./.venv/bin/python -m pytest tests/api/test_agents.py::TestCreateAgent::test_create_agent_success -q, andpython -m compileall src/api.Good frontend validation:
npm run buildandnpx playwright test tests/website.spec.ts -g "homepage loads and has working waitlist".If you change infra code, use the matching
make -C infrastructure ...target instead of ad hoc commands when possible.
CIPHER / OpenCode Operating Model
CIPHER is the orchestrator: priorities, continuity, roadmap, queue health, and truth checks.
OpenCode is the executor: code changes, validation, branch management, PR creation, and issue follow-through.
Canonical repo path:
/Users/fortune/MUTXPreferred OpenCode session:
ses_32248211cffeU1XmfngaGDmd9a
OpenCode / Autonomous Execution
OpenCode is authorized to operate in high-agency mode on this repo.
Prefer speed, momentum, and continuous shipping over conservative permission friction when the work is recoverable through git history, branches, PRs, or reverts.
PR-first always. Never merge directly to
mainunless Fortune explicitly asks.Every PR should get a comment tagging
@codex please review.Empty queue is a failure state: never allow both open issues and open PRs to hit zero at the same time.
Zero open PRs while open issues exist is also a failure state: convert the top issue into a live PR or draft PR immediately.
Backlog creation is incomplete until at least one issue is actively becoming a PR.
If the queue gets thin, open the next roadmap-backed issues immediately.
If a merge wave lands, create the next roadmap-backed issues before the queue goes flat.
If
ROADMAP.mdis stale, update it like a senior engineer / CTO.Update
ROADMAP.mdafter meaningful merge waves, priority changes, newly obvious bottlenecks, or when a roadmap item is effectively complete.Fix CI or fix the code, but do not normalize living in red.
Keep changes small, reviewable, and truthful.
Do not claim success without matching repo-native validation.
Prefer the canonical repo path first; if external worktrees are used, keep them purposeful and short-lived.
Default autonomous loop: inspect → execute → validate → PR → tag
@codex→ report → repeat.
Reporting Contract
Always report back with:
Task
Changed files
Validation
PR
Issue
Blockers
Next
Defaults
Trust source over docs.
Prefer the smallest correct change.
Do not fix unrelated style drift.
Keep docs honest if you touch them.
Call out broken scripts or config instead of assuming they work.
Last updated
