Debug your configuration
Work out why a CLAUDE.md rule, setting, hook, MCP server or skill isn't taking effect, using /context, /doctor, /hooks, /mcp and a clean test session.
When Claude ignores an instruction or a feature you set up never appears, it is almost always one of three things: the file never loaded, it loaded from somewhere other than where you think, or another file overrode it. The fix is to stop guessing and look at what Claude Code actually loaded. This page walks through the commands that show you that, then a table of the mistakes I see most often.
For problems with installing, signing in or reaching the network, go to Troubleshoot installation and login instead.
Step 1: see what is in context
Run /context first. It breaks the current context window down by category: system prompt, system tools, MCP tools, custom subagents (with the file each one came from), memory files, skills and conversation messages. If your CLAUDE.md, a rule file or a skill description isn't listed, it didn't load, and no amount of rewording will help.
The skills section of /context includes bundled skills too, which /skills leaves out.
Then drill into the category you care about:
| Command | What it tells you |
|---|---|
/memory | Which memory files exist at user and project scope, with links to open each one, plus the auto memory folder and its on/off toggle |
/skills | Skills found in project, user and plugin locations |
/hooks | Every hook registered for this session, grouped by event |
/mcp | Each MCP server, its connection status and whether you've approved it here |
/permissions | The allow and deny rules actually in force after merging |
/status | Which settings sources are active, including whether managed settings apply |
/doctor | A health check: install problems, invalid settings files, unused extensions, duplicate subagent names in one directory, and checked-in CLAUDE.md content Claude could work out from the code anyway. It proposes fixes |
/debug [issue] | Turns on debug logging for the session and asks Claude to diagnose the issue from the log and your settings paths |
Note:
CLAUDE.mdfiles in subdirectories load on demand, when Claude works in that part of the tree, so they won't show in/contextat the start of a session. That's expected.
Loaded but ignored
If /context shows the file but Claude still doesn't follow a rule, the problem is the wording, not the loading. Adherence drops when a rule can be read two ways, when two files contradict each other, or when the file has grown so long that each line gets less attention. I keep mine short and specific; Memory covers how to write instructions that stick.
Remember what each mechanism is for. CLAUDE.md is guidance: "we use pnpm, tests live next to source". If something must never happen, guidance isn't enough. Use permissions or a hook, which enforce the rule regardless of what Claude decides.
Step 2: check which setting wins
Settings merge across four scopes. Managed settings, when present, apply first and can't be overridden. Of the rest, the narrower scope wins: local beats project, project beats user. Some keys can also be set by a command-line flag or an environment variable, which acts as one more override layer. So when a value seems to be ignored, the usual story is that something closer to the session set it differently.
claude doctorfrom your shell lists invalid settings files without starting a session./doctorinside a session does the full check and offers fixes./statusshows which sources are in effect.
Settings explains the precedence for each scope in detail.
Step 3: check MCP servers
Open /mcp. A server can be defined perfectly and still give you no tools:
- Never approved. Servers in a project's
.mcp.jsonneed a one-time approval. If you dismissed the prompt, the server stays off until you approve it in/mcp. - Failed to start. Shown as failed in
/mcp. Relative paths incommandorargsare the classic cause, because they resolve against the directory you launchedclaudefrom, not the folder containing.mcp.json. - Connected with zero tools. The process started but returned no tool list. Choose Reconnect. If the count stays at zero, start Claude Code with
claude --debug=mcpand read the server's stderr in~/.claude/debug/<session-id>.txt.
MCP covers scopes and file locations.
Step 4: check hooks
Run /hooks. If your hook isn't listed, it didn't load. The two common reasons:
- It lives in a standalone file. Project and user hooks belong under the
"hooks"key of a settings file. Only plugins read a separatehooks/hooks.json. - Its
matcheris a JSON array. That's invalid; Claude Code reports it as an invalid setting at startup and inclaude doctor. If the bad matcher sits underPreToolUseorPermissionRequest, the rest of that file's hooks fail to load as well.
If the hook is listed but never fires, look at the matcher:
- Match several tools with one string and a
|, as in"Edit|Write". From v2.1.191 a comma works the same way ("Edit,Write"); on older versions a comma was treated as regex text and matched nothing. - Tool names are case-sensitive and capitalised:
Bash,Edit,Write,Read. A matcher of"bash"silently matches nothing.
Edits to settings.json apply to the running session after a short file-stability delay, even if you created the file or the .claude/ folder after the session started (versions before v2.1.257 missed a .claude/ folder created mid-session). If /hooks still shows the old definition, run it again to refresh.
Still nothing? Start with claude --debug, trigger the tool, and read the log. It records each event, which matchers were tested, and every hook's exit code and output. The hooks reference documents the log format and the hooks guide covers common failure patterns.
Step 5: test against a clean setup
claude --safe-mode starts a session with every customisation off: CLAUDE.md, skills, plugins, hooks, MCP servers, custom commands and custom agents. Login, model choice, built-in tools and permissions still work. If the problem vanishes in safe mode, one of those customisations is the cause and the steps above will find it.
Safe mode still honours your organisation's managed hooks and settings policy, though managed plugins, skills, CLAUDE.md and MCP servers are switched off.
If the problem survives safe mode, or you suspect the settings files themselves, go one step further and run with an empty configuration directory from a folder with no project config:
mkdir -p ~/scratch/empty-project && cd ~/scratch/empty-project
CLAUDE_CONFIG_DIR="$HOME/scratch/claude-blank" claude
You'll see the first-run screens (theme picker and so on), which proves the blank directory is in use, and you'll need to log in again. Later launches with the same directory skip onboarding. Managed settings still apply, because Claude Code reads MDM profiles, registry policy and managed-settings.json from outside the config directory and fetches server-managed settings again once you're signed in.
Then interpret the result:
- Problem gone: the cause is in your real
~/.claudeor the project's.claudefiles. Copy files into the blank directory one at a time, or launch from your project, until it comes back. - Problem still there: it's outside your own configuration. Check
/statusfor managed settings, look for environment variables that affect Claude Code, then try Troubleshooting.
Common causes at a glance
| Symptom | Likely cause | Fix |
|---|---|---|
| Hook never fires | matcher written as an array | Use one string, for example "Edit|Write" |
| Hook never fires | Comma-separated matcher on a version older than v2.1.191 | Use |, or update |
| Hook never fires | Lowercase tool name such as "bash" | Capitalise: Bash, Edit, Write, Read |
| Hook never fires | Hooks in a separate file | Put them under "hooks" in settings.json |
| Global permissions or hooks ignored | Added to ~/.claude.json | That file holds app state. Use ~/.claude/settings.json for permissions, hooks and env |
A settings.json value has no effect | Same key set in settings.local.json | Local overrides project, both override user |
Skill missing from /skills | Written as .claude/skills/name.md | Use a folder: .claude/skills/name/SKILL.md |
| Skill listed but Claude never uses it | disable-model-invocation: true, or a description that doesn't match how you ask | Check for the "user-only" badge in /skills, or rewrite the description |
Subdirectory CLAUDE.md seems ignored | It loads on demand, not at startup | Expected. Before v2.1.288 only the Read tool triggered loading |
Subagent ignores CLAUDE.md | Built-in Explore and Plan skip it; a custom agent may set omitClaudeMd | Restate the rule in the delegating prompt, remove omitClaudeMd, or put the rule in the agent's own body |
| Cleanup never runs at session end | No SessionEnd hook | Add one in settings.json |
.mcp.json servers never load | File is inside .claude/, or servers sit under servers instead of mcpServers | Put .mcp.json at the repo root with an mcpServers key |
mcpServers in settings.json ignored | settings.json doesn't read that key | Use .mcp.json, or claude mcp add --scope user |
| Project MCP server added but absent | Approval prompt dismissed | Approve it in /mcp |
| MCP server fails from some folders | Relative path in command or args | Use absolute paths for scripts; npx and uvx on PATH are fine |
| MCP server missing environment variables | Not set in its config entry, or stripped from the subprocess environment | Set them in the server's own env block in .mcp.json |
Bash(rm *) deny doesn't stop /bin/rm or find -delete | Bash rules match the command text, not the program | Use a PreToolUse hook or the sandbox for a hard guarantee |