Claude ignores CLAUDE.md, hooks don't fire? Debugging Claude Code configuration
TL;DR
Most Claude Code configuration problems are a file in the wrong place, bad matcher syntax or an override from another file. Debug in three steps: see what loaded, test with --safe-mode or a clean config, then read the --debug log.
You write a rule in CLAUDE.md and Claude ignores it. You add a hook and it never fires. You install an MCP server and its tools never appear. Most of the time this isn't a Claude Code bug: the file didn't load, it loaded from somewhere other than you expected, or another file overrode it. The official docs have a full configuration troubleshooting process; here's a condensed version to use right away.
Step 1: see what actually loaded
| Command | Shows |
|---|---|
/context | Everything in context: system prompt, tools, MCP, memory files, skills, conversation |
/memory | Where your CLAUDE.md and auto memory files live |
/skills, /hooks, /mcp | Active skills, hooks and MCP servers |
/permissions | Allow/deny rules in effect |
/status | Active settings sources, whether managed settings apply |
/doctor | Full checkup: install health, invalid settings, unused extensions, with proposed fixes |
If /context shows CLAUDE.md loaded but Claude still doesn't follow a rule, the problem is usually the wording: a vague rule, two files that conflict, or a file so long that individual rules get diluted.
The most common configuration mistakes
| Symptom | Cause | Fix |
|---|---|---|
| Hook never fires | matcher is a JSON array, or lowercase "bash" | One string with |: "Edit|Write"; capitalised tool names |
| Hook never fires | Defined in a standalone hooks file | Put it under the "hooks" key in settings.json |
| Global permissions/hooks ignored | Written to ~/.claude.json | Write to ~/.claude/settings.json (two different files) |
| A settings.json value seems ignored | Overridden by settings.local.json | Check precedence: local → project → user |
| Skill doesn't appear | File at .claude/skills/name.md | Must be a folder: .claude/skills/name/SKILL.md |
| MCP servers in .mcp.json never load | File inside .claude/, or uses a servers key | Put it at the repo root under mcpServers |
| MCP server fails from some directories | Relative paths | Use absolute paths |
| Subagent ignores CLAUDE.md | Explore and Plan don't load CLAUDE.md | Restate the instruction in the delegating prompt |
Step 2: test with a clean configuration
claude --safe-mode # disables CLAUDE.md, skills, plugins, hooks, MCP, custom commands
# Fully clean: a fresh config directory, no project configuration
mkdir -p ~/claude-clean/empty && cd ~/claude-clean/empty
CLAUDE_CONFIG_DIR=~/claude-clean/config claude --setting-sources user
If the problem disappears in safe mode, the cause is one of your customisations; re-enable them one by one to narrow it down. If it persists, check managed settings (/status) and environment variables.
Step 3: read the detailed log
claude --debug: logs every hook event, which matchers were checked, and exit codes.claude --debug=mcp: see MCP server stderr in~/.claude/debug/<session-id>.txt.
Caveats
- CLAUDE.md is guidance, not a fence: for things that must never happen, use permissions or hooks.
- Bash rules match the command string, not the program: denying
Bash(rm *)doesn't block/bin/rm; you need a hook or the sandbox.
How to apply it
- Dev: Make a habit of running
/contextand/hooksright after changing configuration. - Tech Lead: Put the "common mistakes" table above in your internal wiki; run
claude doctorduring onboarding. - PM: When someone reports "Claude ignores our rule", ask first: does that rule show up in
/context?
Sources & references
- Debug your configuration — Claude Code Docs