Skip to content

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:

CommandWhat it tells you
/memoryWhich memory files exist at user and project scope, with links to open each one, plus the auto memory folder and its on/off toggle
/skillsSkills found in project, user and plugin locations
/hooksEvery hook registered for this session, grouped by event
/mcpEach MCP server, its connection status and whether you've approved it here
/permissionsThe allow and deny rules actually in force after merging
/statusWhich settings sources are active, including whether managed settings apply
/doctorA 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.md files in subdirectories load on demand, when Claude works in that part of the tree, so they won't show in /context at 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 doctor from your shell lists invalid settings files without starting a session.
  • /doctor inside a session does the full check and offers fixes.
  • /status shows 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.json need 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 in command or args are the classic cause, because they resolve against the directory you launched claude from, 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=mcp and 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 separate hooks/hooks.json.
  • Its matcher is a JSON array. That's invalid; Claude Code reports it as an invalid setting at startup and in claude doctor. If the bad matcher sits under PreToolUse or PermissionRequest, 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 ~/.claude or the project's .claude files. 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 /status for managed settings, look for environment variables that affect Claude Code, then try Troubleshooting.

Common causes at a glance

SymptomLikely causeFix
Hook never firesmatcher written as an arrayUse one string, for example "Edit|Write"
Hook never firesComma-separated matcher on a version older than v2.1.191Use |, or update
Hook never firesLowercase tool name such as "bash"Capitalise: Bash, Edit, Write, Read
Hook never firesHooks in a separate filePut them under "hooks" in settings.json
Global permissions or hooks ignoredAdded to ~/.claude.jsonThat file holds app state. Use ~/.claude/settings.json for permissions, hooks and env
A settings.json value has no effectSame key set in settings.local.jsonLocal overrides project, both override user
Skill missing from /skillsWritten as .claude/skills/name.mdUse a folder: .claude/skills/name/SKILL.md
Skill listed but Claude never uses itdisable-model-invocation: true, or a description that doesn't match how you askCheck for the "user-only" badge in /skills, or rewrite the description
Subdirectory CLAUDE.md seems ignoredIt loads on demand, not at startupExpected. Before v2.1.288 only the Read tool triggered loading
Subagent ignores CLAUDE.mdBuilt-in Explore and Plan skip it; a custom agent may set omitClaudeMdRestate the rule in the delegating prompt, remove omitClaudeMd, or put the rule in the agent's own body
Cleanup never runs at session endNo SessionEnd hookAdd one in settings.json
.mcp.json servers never loadFile is inside .claude/, or servers sit under servers instead of mcpServersPut .mcp.json at the repo root with an mcpServers key
mcpServers in settings.json ignoredsettings.json doesn't read that keyUse .mcp.json, or claude mcp add --scope user
Project MCP server added but absentApproval prompt dismissedApprove it in /mcp
MCP server fails from some foldersRelative path in command or argsUse absolute paths for scripts; npx and uvx on PATH are fine
MCP server missing environment variablesNot set in its config entry, or stripped from the subprocess environmentSet them in the server's own env block in .mcp.json
Bash(rm *) deny doesn't stop /bin/rm or find -deleteBash rules match the command text, not the programUse a PreToolUse hook or the sandbox for a hard guarantee