Treat CLAUDE.md like a constitution: hard bans, behavior rules, default decisions. 92 commits in 5 days, zero drift.
I shipped 92 commits in 5 days and put a product into production (github.com/defi-io/smarts). No blowups, no rollbacks, no big refactors. The reason isn't that Claude is some kind of genius. It's the 565-line CLAUDE.md sitting in the project root.
This post is about how to write a CLAUDE.md that works as a constitution, and what happens after you do.
A lot of people write CLAUDE.md like a README — what the project is, how to run it. That's a waste.
A README is for humans. CLAUDE.md is for Claude. Claude auto-loads it at the start of every session. Every line you put in there becomes a precondition on every decision Claude makes after.
Write CLAUDE.md README-style and you get this: Claude knows roughly what the project is, knows how to run the tests, but makes every technical decision from scratch.
Write it constitution-style and you get this: Claude knows which roads are closed, which conventions are mandatory, which way to default at every fork, and when to stop and ask.
The difference: the first will "helpfully" pull in a new dependency, add an abstraction layer, tweak the Gemfile. The second won't.
The project I've been building is called smarts.md — a platform that generates live docs and MCP servers for smart contracts. Its CLAUDE.md is 565 lines, in these sections:
1. Project identity (5 lines)
2. Product core (one-line definition + structural differences vs. competitors)
3. Tech stack (hard constraints, YAML format)
4. Forbidden list (explicit ❌ items)
5. Scope (MVP hard boundaries)
6. Architecture (with ASCII diagram)
7. Directory layout (per-file responsibilities)
8. Ruby coding conventions (with do/don't snippets)
9. Caching strategy (as a table)
10. Testing requirements
11. Deployment details
12. Git workflow
13. Claude Code usage rules (behavior instructions)
14. 90-day milestones
15. Core principles
None of these are decoration. Below I'll pick a few and explain why they're written the way they are.
Mine looks like this:
❌ No TypeScript / Node.js services
❌ No ethers.js / web3.js
❌ No Sidekiq (use Solid Queue)
❌ No React / Vue / Svelte (use Hotwire)
❌ No Redis (Solid Cache / Solid Queue / Solid Cable cover everything)
❌ No unverified contracts (Etherscan-verified only)
❌ No Solana / Bitcoin / Move (EVM only)
This is a Web3 project. The Web3 default is TypeScript + ethers.js + Redis + React. I'm going against that. I have my reasons, but Claude doesn't know them. Without a forbidden list, Claude will base recommendations on the "industry common sense" buried in its training data — and that's almost certainly going to be the TypeScript path.
With the forbidden list, Claude stops asking "should we add a Node service to run web3.js?" That road is closed by default.
The key to the forbidden list: every entry must be explicit and absolute. Don't write "try to avoid TypeScript." Write "no TypeScript." Anything fuzzy gets treated as negotiable.
The last big section of CLAUDE.md is "Claude Code usage rules":
### When I say "start working on X"
1. First check whether CLAUDE.md's constraints allow this approach
2. Then check existing code for related implementations (don't re-invent)
3. Open a new branch before writing
4. Run tests after the implementation is done
5. Don't auto-commit — once code is written and tests pass, stop
and report. Wait for me to explicitly say "commit"
### When I say "I have an idea"
Don't write code immediately. First:
1. Confirm understanding (paraphrase back)
2. Evaluate against CLAUDE.md constraints
3. Point out potential issues or better alternatives
4. Wait for my confirmation before acting
### When facing a technical fork
When CLAUDE.md doesn't specify:
1. Default to the more Rails-native option
2. Default to the option with fewer dependencies
3. Default to the option that lets a solo dev iterate faster
4. When in doubt, stop and ask
This part matters ten times more than "use snake_case."
Code style Claude can pick up by reading the code. But "when to stop and ask," "when you hear 'I have an idea,' paraphrase first instead of writing code immediately" — these are behavior patterns. Code alone doesn't teach them.
The most important line: which way to default at a fork. That single rule decides what Claude does when you're not in the room (when you just say "start working on X" and walk away). Write it down clearly and you can let it work unsupervised.
The top of CLAUDE.md says:
This document is the project's "source of truth." It auto-loads at the start of every Claude Code session. When changing technical decisions, change this file first; code follows.
This is a workflow contract. When I want to switch some technical choice — say, upgrade the primary AI model from gpt-5-mini to gpt-5 — step one is not to edit the initializer. Step one is editing this section of CLAUDE.md:
ai:
fast: gpt-5-mini # before
fast: gpt-5 # after
Then I let Claude read CLAUDE.md and update the code to match.
Why? Because if you change a value in code while CLAUDE.md lags behind, the next time Claude reads CLAUDE.md it sees the old value and "helpfully" reverts your code. The conflict comes from a single point of failure — CLAUDE.md falling out of sync. The constitution lagging behind reality is how civil wars start.
Treating CLAUDE.md as a constitution means: it always runs ahead of the code.
smarts.md, 5 days, 92 commits:
Average PR lifetime: 30 minutes. No big refactors. No "wait, that direction was wrong, roll it back."
Not because Claude is magic. Because it spent every session running on a 565-line track. It knew not to pull in TypeScript, knew Solid Queue was the queue, knew view functions cache for 60 seconds, knew every service must implement a call class method, knew to wait for me before committing.
Strip half of those constraints away and you get: 30 minutes a day explaining "why we're not using X," 5 minutes reviewing the dependency it "helpfully" added, and a Gemfile that slowly falls apart.
Don't start from a blank file. Start from the most recent decision that hurt.
If lately Claude's been "always pulling in new dependencies," write the forbidden list.
If it's "keeps changing the architecture," write the architecture diagram + "new microservices, database swaps, etc. require explicit approval."
If it's "won't write tests," write "what must be unit-tested."
If it's "commits too aggressively," write "don't auto-commit, wait for explicit instruction."
Each pain point earns one entry. Don't add anything else.
Three months in you'll have a 500-line CLAUDE.md, where every line is backed by a specific "I don't want it doing that again." That document beats any template, because it's tuned to your project, your workflow, and your team (even if the team is just you).
A constitution doesn't get written all at once. It crystallizes from specific conflicts, one at a time.
Source: github.com/defi-io/smarts