CLAUDE.md & the Dev Workflow
Published Jul 11, 2026
Every codebase accumulates tribal knowledge: the deploy step that must not have a trailing slash, the config flag that wipes the database, the layout bug that keeps coming back. Usually that knowledge lives in senior engineers' heads and Slack scrollback. Praxis924 puts it in one file — CLAUDE.md — that is read first, every session, by both the humans and the AI assistants working the repo. It is institutional memory as code: every rule maps to a real incident, so the same mistake is never made twice.
The problem
The naive approach is to trust that people (and AI agents) will "just know" the traps. They don't. A new contributor rebuilds the Nginx config and reintroduces a trailing slash in proxy_pass — every /api/v1/* call 404s and /learn goes dark. An assistant hand-rolls a fixed inset-0 overlay inside a backdrop-blur bar, and the drawer peeks from a corner instead of covering the screen — a bug that shipped roughly seventeen times. Someone runs docker compose down -v to "reset" and drops the volume holding every learner's progress.
These are not exotic failures. They are the same failures, recurring, because the knowledge that would prevent them isn't where the work happens. Documentation in a wiki nobody opens has zero enforcement. Convention-by-code-review only catches what a reviewer remembers that day.
The design
CLAUDE.md is a plain-Markdown operating manual at the repo root, loaded into context at the start of every AI session and read first by humans. Its authority is explicit: the instructions override default behavior. It is organized so a reader can act, not just admire — what the project is, how to run it, the domain model, key flows, and then the load-bearing sections: Gotchas / conventions and Don't nuke prod.
The core rule is that every entry earns its place by pointing at a real incident. A convention with no scar tissue behind it is noise; a convention that says "this exact miss broke the notes drawer" is a rule you obey.
1- Nginx `/api` trailing-slash trap: proxy_pass http://127.0.0.1:8000; — NO
2 trailing slash. A trailing slash rewrites /api/v1/* → /v1/* and every API
3 call 404s (this caused the /learn "Not Found" outage). It lives on the host,
4 so a server rebuild can silently reintroduce it — re-copy the committed file.
5
6- Overlays: reuse the primitives, don't hand-roll. A hand-built fixed inset-0
7 overlay shipped the same layout bug ~17 times. New overlays use <SidePanel> /
8 <Modal>, which bake in the portal-to-body that a backdrop-blur ancestor breaks.Paired with the manual are slash commands in .claude/commands/ — executable shortcuts for the routines the manual describes: rebuild (rebuild + health-check the stack), logs (tail backend logs), db-reset (the destructive one, clearly flagged dev-only), and verify-generation (an end-to-end smoke test of the lesson pipeline). The manual tells you the rule; the command lets you follow it without re-deriving the invocation.
1# The manual documents the flow; the command encodes it.
2/rebuild backend # up -d --build backend, then health-check
3/verify-generation # admin login → create → generate → assert `generated`Finally, OpenSpec enforces a verify-first, decide-before-you-build culture: agree on what to build (a proposal + delta specs + tasks) before writing code, then implement against it. The manual's sharpest cultural rule is that a green build is not proof of correctness.
Warning: next build type-checks; it says nothing about layout. "The build passes" is not "it works." For anything visual, reason through a 375px width or drive the running app.
The gotchas
The manual's own gotcha table is the model — each row is a trap, its consequence, and the fix.
| Trap | What it breaks | The fix |
|---|---|---|
Trailing slash in proxy_pass | Every /api/v1/* 404s; /learn outage | Re-copy the committed Nginx config; no trailing slash |
docker compose down -v on the server | Drops the volume → wipes learner progress | Dev-only; never on prod |
Hand-rolled fixed inset-0 overlay | Drawer peeks from a corner (shipped ~17×) | Use <SidePanel> / <Modal> primitives |
flex-col scroll child without min-h-0 | Sticky footer pushed off-screen | flex-1 min-h-0 overflow-y-auto on the body |
Altering a table via create_all | Schema drift; migration crashes mid-deploy | New tables auto-create; alters use Alembic |
Build it yourself
The minimal version is one Markdown file and a discipline:
- Create
CLAUDE.mdat the repo root. State up front that it is authoritative and read first. - Write only three things well: what the project is, how to run it, and the gotchas. Keep the gotchas section fed by incidents — after any "we shipped that bug again," add a rule that names the incident.
- Add a
.claude/commands/folder with one file per routine you type more than twice (rebuild,logs). - Make the destructive commands loud. A
db-resetthat drops volumes gets a warning banner, not a quiet mention.
What changes at scale
As the team and repo grow, split the monolith into scoped CLAUDE.md files per package so context stays relevant. Add a lint or CI check that fails when a model changes without a matching Alembic migration — Praxis924 already gates this with a migration-drift check and a CD preflight that aborts on an unstamped database rather than crashing mid-deploy. Promote the "verify-first" rule from prose into tooling: a verify skill that drives the running app, and OpenSpec proposals that force a design decision to exist before code does. The file stays the front door; the enforcement moves into the pipeline.