AI Briefing/Blog
CLAUDE.md·October 1, 2026·8 min read

Claude Code in Practice, Part 1: Short CLAUDE.md, Strict Permissions

The three CLAUDE.md files, auto memory, settings.json permissions, and the commands worth memorizing. Step by step, for a real team.

The best CLAUDE.md on your team is probably the shortest one. Not the one /init generated, and not the one everyone added a line to after a bad day.

That sounds backwards, but Anthropic sets a ceiling too. Claude Code’s auto memory loads into each session only up to 200 lines or 25KB, whichever comes first. Matt Pocock put out a video titled simply “Never Run claude /init”. And in February 2026 someone at techloom compressed their CLAUDE.md by 60–70%, then ran a benchmark and found the file helps less than the community assumes.

Meanwhile, the file is becoming a default. bun init creates a CLAUDE.md automatically when it detects the Claude CLI, and per the September changelog, Claude Code reads AGENTS.md if there’s no CLAUDE.md. So you’ll have one of these files either way. The only question is whether it works for you or against you.

This is part 1 of a series: setting up for a real team. Files, memory, permissions, commands. Hooks, skills, and MCP wait for part 2.

01 · Map the three levels before writing a line

Claude Code loads CLAUDE.md from three levels, and each one belongs to someone different:

Above that sits an organization (managed) layer that IT distributes and you can’t override. And a CLAUDE.md in a subdirectory loads when Claude works on files there, which pays off nicely in a monorepo.

If the repo already uses AGENTS.md (the standard from OpenAI, Google, Cursor and others, donated to the Linux Foundation in December 2025), don’t duplicate it. An import is enough:

CLAUDE.md
@AGENTS.md
## Claude-specific
- Use plan mode before any change that touches more than one package.

So how do you know what actually loaded? /memory inside the session lists every file that came in and opens them for editing. Run it once on a new hire’s machine. Often you’ll find a ~/.claude/CLAUDE.md from some old project nobody remembers.

How the mechanism works
How the mechanism works

02 · Run /init, then delete half

/init scans the repo and writes a draft. It’s not bad, it’s long. Every time I’ve run it I got something reasonable and bloated. Pocock is right in principle: every line there goes into context on every message, every day. But you don’t need to give up /init, you need to edit after it.

What to cut: the directory layout (Claude sees it on its own), the dependency list (there’s a package.json), three paragraphs about what the project does. What to keep: the exact commands and whatever can’t be guessed. You should end up with something like:

CLAUDE.md
# payments-api
## Commands
- Test one file: `pnpm vitest run path/to/file.test.ts`
- Full check before commit: `pnpm lint && pnpm typecheck && pnpm test`
- Local DB: `docker compose up -d db` (port 5433, not 5432)
## Not obvious from the code
- Money is integer agorot. Never floats, never `toFixed`.
- Migrations: add a new file. Never edit a merged migration.
- `src/legacy/` is frozen. Read it, don't change it.
## When you are done
- Run the full check. If it fails, fix the code, not the test.

Notice what’s missing. No “write clean code”, no “you are a senior engineer”. What Claude needs is the command that tells it whether it got it right. Boris Cherny from the Claude Code team estimates that giving Claude a way to check itself improves results 2–3x. The full check line is worth more than every style paragraph in the file.

03 · Filter: what goes in, what stays out

Anthropic’s docs give the simplest test: CLAUDE.md is for the things you’d otherwise explain over and over. And one more line worth pinning next to your screen:

The more specific and concise your instructions, the more consistently Claude follows them.

— Claude Code Docs, How Claude remembers your project

In practice, a line goes in if Claude can’t infer it from the code (port 5433, agorot), or if it fixes a mistake that keeps recurring. Not one that happened once.

Stays out: style rules the linter already enforces, secrets, and instructions that only apply to some of the files. Those last ones go in .claude/rules/, and they load only when Claude touches matching files:

.claude/rules/api.md
---
paths:
- "src/api/**/*.ts"
---
- Every handler validates input with the zod schema next to it.
- Errors go through `toProblemJson()`, never a raw throw.

Alex Jacobs wrote a post in August called “I am morally opposed to updating my Claude.md”. It’s funny, but the point is serious. The file turns into an archive of grievances: every line written in a moment of frustration, with no expiry date, while the model improves every four months and the rules stay frozen on what it did wrong last spring.

My take: I agree with Jacobs’s diagnosis, not his conclusion. The fix isn’t to stop writing, it’s to write every line like code: with a reviewer, and a willingness to delete it. A rule nobody is willing to delete is a rule nobody has tested.

Every line was written on a bad day and none were ever deleted. The problem is no expiry date, not too many rules (credit: Alex Jacobs)
Every line was written on a bad day and none were ever deleted. The problem is no expiry date, not too many rules (credit: Alex Jacobs)

04 · Auto memory: let Claude write, then read after it

Beyond what you write, there’s auto memory: notes Claude writes to itself when you correct it. It’s per-repo, shared across worktrees, and loads into each session up to 200 lines or 25KB. Anything past that simply doesn’t get in.

Boris’s tip, ending a correction with “Update CLAUDE.md so you don’t repeat this”, works. Claude really is good at phrasing rules for itself. That said, don’t let it write straight into the team’s CLAUDE.md without anyone seeing. Let it write, and have it go through a PR like any other change. That way another human reads the line before it becomes law.

And once a month, a cleanup. This is the prompt we run, read-only, without touching files. What comes out is a list. What you do: delete, run the next task, and see whether anything breaks. It’s the cheapest eval there is.

05 · settings.json: what’s allowed without asking

This is where we move from requests to enforcement. The docs say explicitly that Claude treats CLAUDE.md as context, not enforced configuration. A deny list in settings.json, on the other hand, is checked before every tool call. Four files, per the docs:

File Applies to In git?
~/.claude/settings.json You, in every project No
.claude/settings.json Everyone working on the project Yes, commit it
.claude/settings.local.json You, in this project No
managed-settings.json The whole org, no override Distributed by IT

Start with deny, not allow. First what must not be read, then commands with no undo:

.claude/settings.json
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(git push --force:*)",
"Bash(git push -f:*)"
],
"ask": ["Bash(git push:*)"],
"allow": [
"Bash(pnpm test:*)",
"Bash(pnpm lint)",
"Bash(git diff:*)"
]
}
}

Add allow entries after a week, based on what you approved by hand ten times. /permissions shows what’s active right now and which file it came from.

Got a line in CLAUDE.md that starts with NEVER? Move it here. Just remember deny matches on prefix, so git push origin +main still gets through. That’s what hooks are for, and we’ll get to them in part 2.

The same force-push line: in CLAUDE.md it's a request the model weighs, in deny it's a block before execution. The docs say so explicitly (Claude Code Docs)
The same force-push line: in CLAUDE.md it’s a request the model weighs, in deny it’s a block before execution. The docs say so explicitly (Claude Code Docs)

06 · Commands and shortcuts to keep at your fingertips

And beyond those, a command of your own. Every markdown file in .claude/commands/ becomes a slash command for the whole team. The review everyone phrases differently? One file:

.claude/commands/review.md
Review the diff against main (`git diff main...HEAD`).
Check only: missing tests, money handled as floats, edits to merged migrations.
Output a list: file:line, problem, suggested fix. No praise, no summary.

Then /review, the same for everyone. When this should be a skill rather than a command is also part 2.

Takeaways

Sources

  1. How Claude remembers your project - Claude Code Docs
  2. Settings files and precedence - Claude Code Docs
  3. Best practices for Claude Code - Claude Code Docs
  4. Claude Code now reads AGENTS.md if there is no Claude.md · 2026-09-18
  5. Claude Code as a Daily Driver: Claude.md, Skills, Subagents, Plugins, and MCPs · 2026-05-27
  6. I am morally opposed to updating my Claude.md · 2026-08-20
  7. Compress Your Claude.md: Cut 60-70% of System Prompt Bloat in Claude Code · 2026-02-24
  8. `bun init` automatically creates a Claude.md file by default · 2026-07-28
  9. AGENTS.md, SKILL.md, DESIGN.md: How AI Instructions Split into Three Layers | AWS Builder Center

How this was made: drafted by our agent from 9 sources, edited and approved by Koby Almog.

More terms

All terms →

AI-native engineering: writing code isn't the bottleneck anymore, verifying it is

What AI-native engineering is, what Meta and Anthropic actually did, and why the work moved from writing code to verifying it. With an AGENTS.md to copy.

Since coding: five years after Copilot, and what to change on your team on Monday

The model is the least important call when working with coding agents. Six steps: permissions, a devbox per task, AGENTS.md, proof in the PR, measurement.

Top coding: the list that went stale in 106 days

On June 8 Opus 4.8 scored 88.6%. By September 22 Claude Code ran a different model. What happened to coding agent rankings, and what to pin this week.