The usual mistake with Claude Code configuration is a good instruction filed in the wrong place. Two questions tell you where it belongs.
Claude Code reads its configuration from a handful of files, and each file answers two questions at once: what kind of thing is this, and who should get it. Get both right and the file path follows. Get either wrong and you end up with a formatting rule nobody else receives, a secret committed to the repository, or a “never do this” that Claude is free to ignore.
Read the requirement and listen for its verb. “Prefer” and “follow our conventions” are advice. “When I ask for” is a procedure. “Every time”, “always” and “must never” are guarantees, and a guarantee cannot live in a file that Claude merely reads.
Project conventions, build commands, architecture notes. Claude loads it at the start of a session and generally follows it, but it is context, not enforcement. The model decides.
Markdown files with a paths: list of glob patterns in their
frontmatter. A rule for db/migrations/** loads when Claude
reads a matching file, so it costs no context the rest of the time. A
rule with no paths loads unconditionally, like CLAUDE.md.
A repeatable task you, or Claude, can call by name.
.claude/skills/deploy/SKILL.md creates /deploy.
The older .claude/commands/deploy.md creates the same
/deploy. Command files still work, with the same frontmatter
as Skills except name and paths, but new work
should be a skill. If both exist under one name, the skill runs.
Shell commands that run at fixed points in the session, defined in a
settings file. A PostToolUse hook on file edits runs the
formatter whether or not Claude remembered to. A PreToolUse
hook that exits with code 2 blocks the tool call outright.
Hooks are deterministic. That is the whole difference from CLAUDE.md.
allow, ask and deny rules in a
settings file, such as Read(./.env) under deny.
They govern what Claude may do at all, not what it should prefer to do.
Tools and data from outside Claude Code: an issue tracker, a database, an internal API. Configured per scope, with its own file layout, which is where most of the traps are.
The pairing to hold on to is CLAUDE.md against hooks and permissions.
“Never commit to main” written in CLAUDE.md is a request. The same
sentence as a deny rule or a PreToolUse hook is a fact about the
system. When a requirement says it must hold “regardless of” what
the model does, only the second one answers it.
There are three audiences, and every mechanism above has a file for most of them.
Above all three sits managed configuration, set by an organisation and deployed to system paths. You rarely write it, but it outranks everything you do write.
| What it is | ProjectCommitted · the whole team | LocalNot committed · you, this project | UserHome directory · you, every project |
|---|---|---|---|
| Instructions | ./CLAUDE.md./.claude/CLAUDE.md |
./CLAUDE.local.md |
~/.claude/CLAUDE.md |
| Path-scoped rules | .claude/rules/*.md |
— | ~/.claude/rules/*.md |
| Skills and commands | .claude/skills/<name>/SKILL.md.claude/commands/<name>.md |
— | ~/.claude/skills/<name>/SKILL.md~/.claude/commands/<name>.md |
| Settings, hooks, permissions | .claude/settings.json |
.claude/settings.local.jsonGit-ignored by default. |
~/.claude/settings.json |
| MCP servers | .mcp.jsonAt the repository root. --scope project |
~/.claude.jsonUnder this project’s entry, in your home directory, not the repo. --scope local, the default. |
~/.claude.jsonTop-level mcpServers. --scope user |
The shaded cell is the one to memorise. For every other mechanism,
“local” means a file in the project folder. For MCP servers it
means an entry in ~/.claude.json, and it is what
claude mcp add gives you if you name no scope at all.
Read the map as a lookup. “A formatter hook for the team” is row
four, column one: .claude/settings.json. “An MCP server I
am trying out” is row five, and either local or user depending on
whether the experiment is tied to this project. Anything described as shared
team tooling belongs in the project column.
Scopes overlap, so each mechanism needs a tie-break. They do not all use the same one, and the differences are worth knowing precisely.
settings.local.jsonsettings.jsonsettings.jsonPermission lists merge across files rather than replacing each other, and a deny at any level wins.
Claude Code connects once, using the winning definition whole. Fields from lower sources are not merged in.
The inversion: for settings the project file beats your user file, but a personal skill beats a project skill of the same name.
A project-scoped MCP server lives in .mcp.json, which is
committed, which means a token pasted into it is a token pasted into the
repository. The file supports environment variable expansion instead:
${VAR}, or ${VAR:-default} with a fallback, in
command, args, env, url
and headers.
// .mcp.json: committed, shared, no secrets in it { "mcpServers": { "tracker": { "type": "http", "url": "${TRACKER_URL:-https://tracker.example.com}/mcp", "headers": { "Authorization": "Bearer ${TRACKER_TOKEN}" } } } }
Everyone on the team gets the same server; each of them supplies their own token. That is the shape of the right answer whenever a requirement combines “shared” with “credentials”.
There are three ways to give Claude context, and the choice turns on reusability, specificity, and whether the next session will need it too.
@path/to/file in the prompt when a
specific file is what Claude needs for this task. The file’s full
content goes into the conversation straight away, without waiting for
Claude to decide to read it. An @ directory gives a file
listing, not contents, and @server:resource pulls in an MCP
resource. None of it carries into the next session.
@path
syntax, so a long conventions document can stay in docs/ and
still load at launch.
The trap is the look-alike syntax. @docs/api.md typed in a
prompt is a one-off inclusion. The same line inside CLAUDE.md is a standing
import that every future session pays for in context.
One side effect is easy to miss: an @ file reference also adds
the CLAUDE.md files from that file’s directory and its parent
directories. Point at @packages/billing/invoice.ts and the
billing package’s own CLAUDE.md comes along with it.
context: fork is for
By default a skill runs inside your conversation: it sees what you have
discussed and whatever it reads stays in your context afterwards. Adding
context: fork to a skill’s frontmatter runs it in an
isolated subagent instead. The skill’s content becomes that
subagent’s prompt, it does not inherit the conversation history, and an
agent: key can choose which subagent type runs it, such as
Explore or Plan.
Reach for it when a skill does a lot of self-contained reading, or when it should not be swayed by the session: a code review that ought to judge the diff rather than the argument you just made for it. Leave it off when the skill genuinely needs what the conversation already knows.
Decide the mechanism and the file before opening each one.
.claude/settings.json“Every” makes it a guarantee, so not CLAUDE.md. “Everyone” makes it project scope, so not your user settings.
/release-notes command available in every repository you work in.~/.claude/skills/release-notes/SKILL.mdA procedure invoked on demand, for you, across projects. ~/.claude/commands/release-notes.md also works; Skills are the current form.
.mcp.json${TRACKER_TOKEN}Shared tooling is project scope. The token comes from each person’s environment, never from the committed file.
.claude/rules/migrations.mdpaths: ["db/migrations/**"]Advice, but only for some files. Putting it in CLAUDE.md works and spends context on every task that never touches a migration.
.env files.Read(./.env).claude/settings.json“Must never” is a boundary. A line in CLAUDE.md asking Claude not to read it is not one.
claude mcp add --scope local~/.claude.jsonPersonal and tied to one project. It never touches .mcp.json, so teammates never see it. If the experiment should follow you to every project, use --scope user.
Checked against the Claude Code documentation on memory, settings, skills, hooks, MCP and file references, September 2026.
For the practice half, ExamGauge has 1523 original practice items across four Claude certification exams, scored on the real 100–1000 scale against the 720 cut. The diagnostic is free and needs no card.