Working With AI Agents
How an AI coding agent should orient itself in this codebase, what to read first, what proves a change, and what it must never do.
This page is written for an AI coding agent (Claude Code, Codex, Cursor or similar) that has been pointed at the repository, and for the person pointing it. AGENTS.md at the repository root carries the short version and links here.
Orientation, in Order
- Read
README.mdfor the architecture and the spec index. - Read
docs/LAYOUT.mdanddocs/COPY.md. They are short and every page follows them. - Read
docs/HANDBOOK.mdfor the services, environment variables, jobs and runbooks. - Read
lib/audiences.tsandproxy.tsto understand roles and the route gate. - For the feature you are touching, read
lib/<domain>/first, thencomponents/<domain>/, then the page underapp/. - Read the tests beside the code. They say what the code promises.
How to Find Things
- A page: its address maps to
app/<group>/<path>/page.tsx. Route groups are(public),(dashboard)and(settings). - A navigation entry or a route's audience:
lib/nav-config.ts,lib/settings-nav.ts,lib/page-tabs.ts. - A piece of copy a tester quoted: grep the exact string; it is in a component or in
lib/email/registry.ts. - An intake question:
lib/apply/questions.ts(and the editable registry underlib/content/). - Where an answer lands on a profile:
lib/applications/seed-profile.tsandmap-member.ts. - An email:
lib/email/registry.tsfor the template,lib/email/templates.tsfor the send function, the caller by grepping the function name. - A scheduled job:
app/api/cron/<name>/route.ts. - A table's shape:
supabase/migrations/(grep the table name).
What Proves a Change
npx tsc --noEmit
npm test
git diff -U0 | grep -P "\x{2014}|\x{2013}" # must be emptyThen git fetch origin && git rebase origin/main and push as a fast-forward. If the headless browser cannot load a page behind sign-in (Clerk's widget needs a real origin), say so in the ticket and describe what was verified instead.
Rules an Agent Must Keep
- Never print or commit a secret.
.env.localis ignored; read variable names only. Never paste a key into a ticket, a log line, a test or a doc. - Never run
npx shadcn add --overwriteornpx shadcn apply. Hand patches incomponents/uiwould be lost and a test would fail. - Use npm, never Bun or pnpm, in the app. The docs site uses npm too.
- Compose with Base UI, not Radix.
render={<X />}andnativeButton={false}when a button renders a link. - No em or en dashes anywhere, including code comments and commit messages.
- US spelling, Title Case headings, sentence-case sentences.
- Every write checks the role on the server. Hiding a button is not access control.
- Fill gaps, never overwrite when seeding from application answers.
- Never force-push
main. Rebase and fast-forward. - Linear is read by the client. Write every comment for them: how it works now, how it was checked, no commercial detail, no blame.
- Do not touch production data from a script without saying so first in the conversation, and never delete member rows to "clean up" without a named ticket asking for it.
Working With the Connectors
In Claude Code the useful connectors are Linear (issues, comments, attachments), Supabase (read-only queries, applying a migration), and Vercel (deployments, logs, domains). When a connector drops, a script with LINEAR_API_KEY from .env.local reaches Linear's GraphQL API, and Supabase reads work with @supabase/supabase-js from a temporary script under scripts/. SQL needs the connector or the dashboard.
Closing a Ticket
Write a comment with three short parts: How it works now, What was wrong, Checked (what was run and what could not be verified from here). Mark it Done. Leave the ticket open if the proof needs a person on a phone or a fresh production record, and say what they should do.
What the Agent Panel in the App Is
Unrelated to coding agents: the OS Agent inside the platform is an admin assistant that reads members, sessions, events and counts through OpenRouter. It is described under Matching and AI.

