My Global CLAUDE.md: The Rules I've Built Up Over Time
Claude Code does something that annoys me. I correct it. Next session — fresh context, no memory of the last one — it does the exact same thing again. The third time it happens, I stop re-typing the correction into the chat and write it down once, permanently, in a file that every session reads before it does anything.
That file is ~/.claude/CLAUDE.md, and over months it has quietly become the most useful thing in my setup: a record of every way an AI agent has burned me, turned into a standing instruction so it can’t burn me the same way twice.
This is the whole file, rule by rule, with the scar behind each one. Steal what’s useful.
What this file actually is
There are three places agent rules can live, and people conflate them constantly:
- Project root (
./CLAUDE.md) — facts about this codebase. Its conventions, its stack, how to run its tests. - Subdirectory rule files (
app/Models/CLAUDE.md,tests/CLAUDE.md) — rules scoped to the kind of code in that folder. I wrote a whole post on why these beat one giant root file. - Global (
~/.claude/CLAUDE.md) — me. How I want any agent to work, on any project, forever.
This post is about the last one. Nothing in it is specific to a single repo. It’s my working style — the habits I’d want from any collaborator — encoded once and applied everywhere I open Claude Code.
Project files describe the code. The global file describes how you want to be worked with. Don’t mix them.
The one rule about writing rules
The global file loads into context on every session, before a single useful token is spent. That makes it expensive in the only currency that matters: attention. A 600-line global file is a 600-line tax on every task, and most of it gets skimmed.
So the bar for adding a rule is high. Each line in mine earned its place by something going wrong at least twice — never a hypothetical, never “this seems like good practice.” If I can’t point to the specific session where its absence cost me, it doesn’t go in.
A good rule is a scar. If nothing actually went wrong, you don’t need the rule yet.
With that said, here’s what’s in there.
The working relationship
These three set the default posture: do the work, think for yourself, but don’t wander.
## Ask when unclear
- If the request is genuinely ambiguous or you're materially uncertain,
ask one sharp question instead of guessing or hedging.
## Execute directives fully
- Do exactly what was asked, cleanly and completely. Don't substitute a
scoped-down "safer alternative."
- Build in real safety mechanics (transactions, ordering, expand/contract
migrations); skip generic "this is dangerous" hedging.
- State concrete blockers as facts and handle them. Push back only on real
correctness problems, not taste or deploy nerves.
## Don't chase unrelated test failures
- Don't expand scope to fix pre-existing failures unrelated to your change.
Once proven pre-existing: verify only what you touched, commit, note the
failure plainly.
The one that earns its keep most often is “don’t substitute a scoped-down safer alternative.” Ask an agent to do something with real consequences — a migration, a bulk update, a refactor across many files — and its instinct is to quietly do a smaller, safer-looking version and present that as if it were what you asked. I don’t want the timid version. I want the actual thing, built with actual safety mechanics. The difference between “this is dangerous, are you sure?” and a real transaction with a rollback path is the difference between a hedge and an engineer.
“Don’t chase unrelated test failures” exists because agents are compulsive tidiers. You ask for one change, the suite has three pre-existing reds, and now your one-line fix is a 40-file diff touching things you never meant to touch. Prove the failure predates you, note it, move on.
Don’t let it near git carelessly
This is the section I’d hand to anyone, untouched.
## Git: stage explicitly
- Stage only files you touched, by explicit path. Never `git add -A` /
`git add .`.
- Check `git status --porcelain` before every commit; unstage any foreign file.
- Re-check `git rev-parse HEAD` vs `origin/main` before history surgery —
session-start HEAD may have moved.
- Prefer `rm`/Edit over `git rm` for files you're replacing, so deletions
stay unstaged. Stage at your own commit time.
- Recover a tangled graph by branching from current HEAD, not rewriting commits.
git add -A is the single most dangerous habit an agent has. It sweeps up whatever happens to be in your working tree — a half-finished experiment, a .env, a debug script — and commits it alongside the intended change. Stage by explicit path, every time. Everything else here is downstream of one principle: the agent should only ever commit the exact files it knowingly touched, and it should recover from mistakes by moving forward (a new branch) rather than rewriting history under your feet.
Don’t let it destroy anything
## No destructive DB ops without approval
- Never run `migrate:fresh`, `Schema::drop`, `migrate:rollback` on create
migrations, or any destructive DB op without explicit approval.
- Missing column that exists in the create migration → just
`php artisan migrate`; don't drop/recreate.
- `make -n` / `--dry-run` is NOT safe for recipes referencing `$(MAKE)` —
GNU make runs those lines for real even under `-n`. Read the Makefile to
inspect; don't dry-run it.
## One-time operations
- One-time backfills/migrations leave no permanent infra (no audit tables, no
`*:revert` commands). Capture pre-op state as a disposable snapshot (e.g.
JSON dumped + downloaded locally); write a throwaway restore script only if
a revert is ever needed.
migrate:fresh drops every table. An agent reaching for it to fix a missing column is the kind of thing you only need to witness once. The fix is almost always smaller than the agent thinks — a missing column that’s already in the create migration just needs migrate, not a teardown.
The make --dry-run line is the most specific scar in the file, and the most satisfying to have written down. make -n is supposed to print commands without running them — except recursive make ($(MAKE)) executes those sub-make lines for real even under -n. I learned that the expensive way. Now the agent reads the Makefile instead of trusting a dry run that isn’t dry.
“One-time operations leave no permanent infra” is about taste, not safety. When I ask for a backfill, I don’t want a permanent audit_log table and a backfill:revert command cluttering the codebase forever. Snapshot the before-state to a disposable JSON file, run the thing, delete the scaffolding.
Don’t trust — verify
## Verify before relying
- Verify an identifier exists before using it — icon names, enum values,
library/API symbols, route names. Don't assume from convention.
- A package's presence in the manifest (composer.json/package.json) is not
proof it's used. Confirm it's registered/referenced before recommending or
relying on it.
## Investigate in the right place
- Investigate live issues against the environment where they occur (usually
production), not the local DB of seeded/fake data. Confirm the target env
before querying.
This is the antidote to confident hallucination. Models are superb at producing a plausible icon name (heroicon-o-sparkles, surely that exists?) or assuming a package in composer.json is wired up just because it’s installed. Plausible is not the same as present. Check that the symbol actually exists before building on it.
“Investigate in the right place” catches a subtler failure: an agent debugging a production issue against the local database full of seeded fake data, then confidently declaring the bug fixed because the fake data doesn’t reproduce it. Confirm which environment you’re actually looking at first.
Testing taste
## Testing taste
- Don't test framework behavior. Only test non-trivial branching, business
rules, and error-prone edge cases.
- Test functionality, never presentation. Don't assert on layout, displayed
copy, labels, nav items, headings, element order, or CSS classes — those
are change-detectors. Assert behavior, persisted data, validation,
record-level scoping/authorization, and side effects.
- Trivial label/copy/wording rename → edit, update any assertion referencing
the old string, commit. No test-suite run.
Left alone, agents write tons of tests — and most of them are change-detectors: assert the button says “Save”, assert the heading is an <h1>, assert the nav has five items. The moment you rename anything, they all break, and they never caught a real bug. I want tests that assert behavior — what got persisted, who’s allowed to see it, what happens at the edges — not tests that screenshot the current copy and call it coverage.
Patterns I keep repeating
One rule here isn’t a guardrail at all — it’s a design opinion I was tired of re-explaining on every project.
## Exposing data to an LLM/agent
- Build a filterable/faceted search primitive (free-text + composable facets,
returns total/truncated, decision-relevant fields per row) — not many
per-record lookups or a bespoke per-question tool. Per-record tools are for
drill-down only.
Whenever I give an agent access to a dataset, the naive design is one tool per question — getUserByEmail, getOrdersForUser, getRefundsThisMonth — and it never ends. The design that actually works is a single faceted search primitive: free-text plus composable filters, returning the decision-relevant fields and a truncation flag. One tool the agent can compose against, instead of fifty it has to choose between. Writing it down once means I get the right shape on the first try every time.
Memory hygiene
The last section is the file keeping itself honest.
## Memory hygiene
- Save only durable, recurring knowledge. Skip one-offs.
- Save the general rule, not the war story. One-line index hooks; detail in
the topic file.
- Prune shipped projects and resolved one-offs — the index loads every session.
Because the global file loads on every session, it has a natural tendency to bloat — every interesting one-off feels worth saving in the moment. This section is the rule against that: save the general rule, not the specific war story, and prune anything that’s shipped or resolved. The file has to stay short enough that the agent actually reads all of it.
Build your own, don’t copy mine
You’re welcome to take any of these. But the real value isn’t my list — it’s the habit that produced it.
The next time you correct the agent on something you’ve corrected before, don’t just fix it and move on. Write the rule.
Start empty. Every time you catch yourself typing the same correction a second time, promote it to a line in your global file. Keep each rule to the general principle. Prune ruthlessly — if a rule hasn’t earned its keep in a month, it’s costing you attention it isn’t repaying. In a few weeks you’ll have a file that makes every agent, on every project, work the way you already wish they did — without you having to say it again.
The best part: it compounds silently. You stop noticing the mistakes that used to cost you ten minutes a session, because they simply stopped happening.