You've been using Claude Code for a while, and the things Claude keeps getting wrong all go into CLAUDE.md. And it works.
But CLAUDE.md is only one of the places your instructions can live, and not always the best one. This first part of our Claude Code basics series walks through the others, one at a time, and shows which job each one takes off CLAUDE.md. By the end, your CLAUDE.md is short again and every instruction lives where it works best. Everything here follows Anthropic's official Claude Code documentation.
CLAUDE.md: the file you already know
CLAUDE.md is a markdown file Claude reads at the start of every session. It's the right home for things Claude should know every time: build commands, conventions, project layout, and "always do X" rules.
One thing to keep in mind from the start: Claude treats CLAUDE.md as advice, not as rules it must obey. The memory docs describe it as context that Claude reads and tries to follow. That's the reason several features below exist.
You can have more than one
CLAUDE.md files can live in several places, and Claude combines them:
~/.claude/CLAUDE.md: your personal preferences, for every project on your machine../CLAUDE.md(or./.claude/CLAUDE.md): the project file you share with your team through git../CLAUDE.local.md: your personal notes for this one project. Add it to.gitignore.- A
CLAUDE.mdinside a subfolder, such aspackages/api/CLAUDE.md. These don't load at startup. Claude picks them up when it reads files in that folder.
That last one helps in bigger repositories. Frontend conventions can sit in the frontend folder and only show up when Claude works there.
Setting up Claude Code for a whole team, or building AI tools on top of Claude? Get in touch, we do this for clients every week.
Two small tricks
- Hidden notes. Claude Code strips HTML comments like
<!-- why this rule exists -->before Claude sees the file. Leave notes for your teammates for free. /contextshows whichCLAUDE.mdand rules files actually loaded. If a file isn't listed there, Claude can't see it.
Keep it under 200 lines
Everything Claude loads uses up its context window, the working memory for your conversation. Longer files use more of it, and Claude follows them less reliably. That's why the docs recommend keeping each CLAUDE.md under 200 lines. The best practices guide offers a simple test for every line: "Would removing this cause Claude to make mistakes?" If not, cut it.
So where does everything else go? That's the rest of this article.
Rules files: instructions that load only where they matter
Now you're probably tempted to put every rule for every part of the project into CLAUDE.md. There's a smarter way: the .claude/rules/ folder.
Each file in it covers one topic, like testing.md or api-design.md. A rule without extra settings loads at startup, just like CLAUDE.md. The useful part is path-scoped rules: add a paths field at the top, and the rule only loads when Claude reads a matching file.
---
paths:
- "src/api/**/*.ts"
---
# API Development Rules
- All API endpoints must include input validation
- Use the standard error response format
- Include OpenAPI documentation comments
Save that as .claude/rules/api.md. The pattern means "any .ts file anywhere under src/api/". When Claude works on your React components, these API rules stay out of the way. When it opens a file under src/api/, they appear.
Two more details from the rules docs:
- Subfolders work, so
.claude/rules/frontend/and.claude/rules/backend/are fine. ~/.claude/rules/holds personal rules that apply to every project on your machine.
The rule of thumb: CLAUDE.md for what's true everywhere, rules files for what's true in one part of the codebase.
Hooks: when something must happen every time
Remember, CLAUDE.md is advice. "Always run the formatter after editing" is something Claude will usually do. For anything that has to happen every single time, there are hooks.
A hook is a command that Claude Code itself runs at a fixed moment, such as right after Claude edits a file. Claude doesn't decide whether it runs. It just runs.
This hook, from the hooks guide, runs Prettier on every file Claude edits. It goes in .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
In plain words: after (PostToolUse) Claude edits or writes a file (Edit|Write), format that file. Claude Code hands the hook details about the edit as JSON, and jq, a small command-line tool you may need to install, pulls out the file path. It assumes Prettier is already set up in your project.
You don't have to write these by hand. Ask Claude: "Write a hook that runs eslint after every file edit." Once it works, delete "remember to run the formatter" from your CLAUDE.md.
Hooks also cost nothing in the context window. They run outside the conversation and add nothing unless they print output back to Claude. Run /hooks to see every hook you have.
Permissions: when something must never happen
Hooks make sure something always happens. Permission rules make sure something never happens, or never happens without your okay. Instead of writing "never push to main" in CLAUDE.md and hoping, you write a rule.
Each rule names a tool and a pattern. Bash(npm run *) means "any terminal command that starts with npm run". Read(./.env) means "the .env file in this folder".
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)"
],
"ask": [
"Bash(git push *)"
],
"deny": [
"Read(./.env)"
]
}
}
With this, Claude runs your npm scripts and commits without asking, checks with you before every push, and can't read or edit your .env file. It goes in the same .claude/settings.json as your hooks, as another key inside the same outer braces.
Claude Code checks the lists in a fixed order: deny first, then ask, then allow. A deny rule always wins, even over a more specific allow rule.
One honest caveat: a rule matches the text of a command. Claude could still reach the same result another way, for example through a script. If you need a hard boundary, turn on the sandbox, which limits what any command can touch. Run /permissions to see every rule and where it came from.
Skills: instructions that wait until they're needed
Some instructions are long, and you only need them now and then: a release checklist, how to fix a GitHub issue end to end, or your API style guide. Put them in CLAUDE.md and you pay for them in every session.
Put them in a skill instead. A skill is a folder with a SKILL.md file, inside .claude/skills/ (shared with your team) or ~/.claude/skills/ (just for you). The trick is how it loads. Only the short description is always in context. The full instructions load when you use the skill, so a long skill costs almost nothing until then.
This example is from the best practices guide. Save it as .claude/skills/fix-issue/SKILL.md:
---
name: fix-issue
description: Fix a GitHub issue
disable-model-invocation: true
---
Analyze and fix the GitHub issue: $ARGUMENTS.
1. Use `gh issue view` to get the issue details
2. Understand the problem described in the issue
3. Search the codebase for relevant files
4. Implement the necessary changes to fix the issue
5. Write and run tests to verify the fix
6. Ensure code passes linting and type checking
7. Create a descriptive commit message
8. Push and create a PR
Now /fix-issue 1234 runs the whole procedure. $ARGUMENTS is replaced with whatever you type after the command, here 1234. Step one needs the GitHub CLI (gh) installed.
disable-model-invocation: true means only you can start this skill. Without it, Claude can also load a skill on its own when your request matches the description. Keep that line for anything that changes things outside your code, like pushing or deploying. You don't want Claude deciding to deploy because the code looks ready.
Two more things worth knowing about skills:
- Custom slash commands are now skills. Old files in
.claude/commands/keep working. - A simple trigger for writing one: the third time you paste the same procedure into chat, turn it into a skill.
Subagents: a helper with its own memory
Some jobs are side work: "search the codebase for every place we handle refunds" or "review this change for security issues". Done in your main conversation, Claude reads dozens of files, and they all crowd the context window you need for the actual task.
A subagent is a helper with its own, separate context window. It does the digging and sends back only a summary. Your main conversation stays clean.
Claude Code comes with built-in ones, like Explore, a fast agent that searches code without changing it. You can also define your own in .claude/agents/. This one is adapted from the best practices guide:
---
name: security-reviewer
description: Reviews code for security vulnerabilities
tools: Read, Grep, Glob
model: opus
---
You are a senior security engineer. Review code for:
- Injection vulnerabilities (SQL, XSS, command injection)
- Authentication and authorization flaws
- Secrets or credentials in code
- Insecure data handling
Provide specific line references and suggested fixes.
tools limits what the subagent can do: this one can read and search files, but can't edit anything. model picks which Claude model runs it. Then ask: "Use the security-reviewer subagent to check this code." Claude can also pick it on its own when your request matches its description.
The subagents docs are clear about when this pays off. Use a subagent when a task produces lots of output you don't need to keep, when you want to limit which tools the work can use, or when you want a fresh reviewer that didn't write the code. Skip it for quick changes, for work that needs a lot of back and forth, or when speed matters.
The key limitation: a subagent doesn't see your conversation. It doesn't know what you discussed, which files Claude already read, or which skills you used, and it doesn't get your main session's auto memory. Whatever it needs has to be in the request.
More Claude Code basics worth knowing
These don't replace anything in CLAUDE.md, but they change how a session feels. All come from the best practices guide:
- Plan mode. Press
Shift+Tabuntil you see "plan mode on". Claude reads and plans without changing anything. PressCtrl+Gto edit the plan yourself. Skip it for small fixes: if you could describe the change in one sentence, just ask for it. - Rewind. Press
Esctwice (or run/rewind) to go back to an earlier point and restore the conversation, the code, or both. It only undoes edits Claude made directly. Changes from terminal commands stay, so keep using git. /clearafter two failed corrections. If you've corrected Claude twice on the same thing, the context is full of wrong attempts. Start fresh with a better prompt instead./btwfor side questions. The answer never enters your conversation history, so checking a quick detail doesn't cost context.- Let Claude interview you. For bigger features, ask Claude to interview you first and write a spec, then start a fresh session to build it.
Using this setup on a real team
Here's how it fits together when more than one person works in the repository.
What to do:
- Commit
CLAUDE.mdand everything in.claude/exceptsettings.local.json. The whole team gets the same setup, and it improves every time someone fixes it. KeepCLAUDE.local.mdout of git too. - Treat
CLAUDE.mdlike code. When Claude repeats a mistake, that's aCLAUDE.mdedit, not a one-off correction in chat.
What to avoid:
- Contradicting yourself. If two files disagree, Claude may follow either one. Review your
CLAUDE.mdfiles and rules now and then. - Shouting everywhere. Adding "IMPORTANT" to one line helps it stand out. Adding it to 20 lines means none of them stand out.
When not to bother: you don't need all of this on day one. The docs suggest adding each feature when you hit its trigger:
| When this happens | Add this |
|---|---|
| Claude gets a convention or command wrong twice | A line in CLAUDE.md |
| A rule only matters in one folder | A path-scoped rule |
| Something must happen every time | A hook |
| Claude should never do something | A deny rule |
| You paste the same procedure a third time | A skill |
| A side task floods your conversation | A subagent |
Wrapping up
Most people only use CLAUDE.md. It's a good start, but each feature above takes a job off it, so it can shrink back to the few facts Claude needs every time. The less you load by default, the better Claude follows what's left.
Start small: open your CLAUDE.md, find the longest section, and ask which of these features it really belongs in.
If you're connecting Claude to your own tools next, our guide to building a custom MCP server in TypeScript is a good follow-up.
Want help rolling out Claude Code across your team, or building a product on top of Claude? Get in touch.





