Most CLAUDE.md files I see are a folder map and a naming convention. That is close to the least valuable thing you can hand an agent, because it already infers structure from the repo. What it cannot infer are the rules that must never break, and the reasons behind them.
An agent will happily write code that compiles, passes types, and quietly violates a security or data invariant. A file map does nothing to stop that. A list of invariants with reasons does.
Here is the shape that has worked for me on Next.js + SQLite SaaS projects.
Encode invariants, with the reason
Not "put queries in lib/db." Instead:
- All writes go through a server action or route handler, and auth is checked there. The client is untrusted; the server is the only enforceable boundary.
- Every user-owned query includes an ownership predicate. SQLite has no row-level security, so this one line is the only thing stopping cross-tenant reads. Forgetting it is a silent data leak, not an error the agent will ever see.
- Never grant access or money state from a success URL, only from a verified server event.
The "and the reason" part matters. Claude follows a rule it understands far more reliably than one it takes on faith.
The SQLite gotcha worth stating outright (I normally run Postgres)
I build on Postgres, where row-level security is a backstop: even if a query forgets its ownership filter, RLS can stop the cross-tenant read. SQLite has none. So on SQLite, "an ownership predicate on every user-scoped query" is not style advice, it is your entire multi-tenant boundary. If it is not stated as an invariant in the CLAUDE.md, an agent will eventually write a query without it and nothing will complain. (On Postgres, keep the predicate and keep RLS. Belt and suspenders.)
Tell it how to work, not just what to build
Invariants describe the destination. They do not stop the agent getting there in one giant, unreviewable leap. So the other half of a good CLAUDE.md is the working method.
Mine is phase-gated micro-stepping, and the key move is that the agent does not authorise its own progress:
- Work runs in phases (scope, build, verify, review, fix, ship) with a human checkpoint between each. The agent stops at every boundary, reports, and waits for an explicit go phrase. "looks good" does not advance it.
- The build phase is itself micro-stepped: one section at a time, with a typecheck, test, and pitfall scan after each, then a commit and a stop.
- A circuit breaker: if it cannot get a check green in about five tries, it stops and reports instead of looping forever.
- Defensive commits before multi-file changes, full implementations only (no // TODO stubs), and a tight state-summary handoff so a fresh session resumes without re-reading the repo.
A broken invariant shows up immediately in a small gated step; a big autonomous diff buries it. This is the part of a CLAUDE.md almost nobody writes, and it is the part that most changes how the agent behaves.
Add a "danger paths to test" section
The highest-leverage block. These are the flows that cost you money or data when they break, and the ones agents skip because they are boring:
- signup / login / logout
- protected route redirect when unauthenticated
- CRUD authorization (user A cannot touch user B's rows)
- migration on a fresh database
- migration on an existing database
- seed command run twice (no duplicates)
- production build
- first run after clone with only .env.example
Ending the file with "before you call this done, prove these still pass" turns the agent from a confident code generator into something closer to a careful engineer.
The full file
Complete, opinionated CLAUDE.md for a Next.js + SQLite SaaS (Drizzle, server actions, the Next 16 caching rules, security baseline, the micro-stepping method, anti-patterns with reasons, and the danger-paths checklist). https://gist.github.com/HalbonLabs/485186f4b2846bb1d13d2240651df21d
I build production Next.js templates for a living (Template Empire), so I think about this as "what stops a buyer's first clone from breaking," which turns out to be the same question as "what should the agent never get wrong." The deeper standards behind it are public: templateempire.io/standards
What invariants are in your CLAUDE.md that you would not ship without?
Top comments (0)