What you will be able to do
- Pick the right built-in command (/doctor, /mcp, /hooks, /permissions, /status, /debug) to inspect a misbehaving setup
- Diagnose MCP servers that never load, fail to start, or list zero tools, and read their stderr from the debug log
- Fix the common reasons hooks never fire and settings seem to be ignored
- Isolate a faulty customisation with a clean config directory or safe mode, and handle memory and search problems
1.Inspect what Claude Code actually loaded
When settings don't apply, hooks don't fire or MCP servers don't load, the first question is what Claude Code actually resolved, not what you believe you configured. Each area has a built-in command that shows its live state. Use these before editing any file. They tell you whether the problem is a missing entry, an entry that was rejected, or an entry that is overridden by something with higher precedence.
| Command | Shows |
|---|---|
| /doctor | Installation health, invalid settings files, unused extensions, duplicate subagent names, with proposed fixes |
| /mcp | Connected MCP servers and their status |
| /hooks | Active hook configurations |
| /permissions | Resolved allow and deny rules currently in effect |
| /status | Active settings sources, including whether managed settings are in effect |
| /debug [issue] | Enables debug logging and prompts Claude to diagnose using the log output and settings paths |
/status matters in team deployments. If an organisation pushes managed settings, a local file may seem to be ignored simply because a managed setting takes priority. Check the active sources before assuming your file is broken.
2.MCP servers: never loaded, failed, or empty
MCP problems show up in three distinct ways, and each has its own cause. If the server never appears at all, the config is usually in the wrong place. Project servers belong in .mcp.json at the repository root, under the mcpServers key. Common mistakes are putting the file inside .claude/, using VS Code's top-level servers key, or adding mcpServers to settings.json, which does not read that key. A project server that is configured correctly also stays disabled until someone approves it. If the one-time approval prompt was dismissed, approve the server from /mcp.
If the server shows as failed, suspect the launch command. Relative paths in command or args resolve against the directory you started Claude Code from, not against the location of .mcp.json. That is why a server can work from one directory and fail from another. Use absolute paths for local scripts. Executables on PATH, such as npx or uvx, work as they are. If the server starts without the environment variables it needs, set them per server in its .mcp.json entry. If the server shows as connected but lists zero tools, it started but is not returning a tool list. Select Reconnect in /mcp. If the count stays at zero, turn on MCP debug logging and read the server's own stderr.
| What /mcp shows | Likely cause | Next step |
|---|---|---|
| Server missing | File under .claude/, servers key instead of mcpServers, or mcpServers in settings.json | Move config to .mcp.json at the repo root under mcpServers |
| Server disabled | One-time project approval was dismissed | Approve it from /mcp |
| failed | Relative path in command or args | Use absolute paths for local scripts |
| Connected, zero tools | Server not returning a tool list | Reconnect, then run claude --debug=mcp and read stderr |
An admin sets model: claude-opus-4-8 in the project's .claude/settings.json so the whole team defaults to Opus. One engineer's sessions keep starting on Sonnet instead, and /status confirms project settings are being read. What is the most likely explanation?
Correct answer: A — The engineer has the same model key set in .claude/settings.local.json, which overrides the project-level settings.json.
- A. Correct. Among local, project, and user scopes, the closer scope (local) overrides the broader one (project). A model key duplicated in settings.local.json would take precedence over the project's settings.json even though /status confirms project settings loaded.
- B. Incorrect. The absence of an environment variable does not prevent Claude Code from reading a project-level setting; settings.json values apply without requiring a matching environment variable.
- C. Incorrect. There is no documented behavior where an older version silently ignores the model key; a stale or invalid model reference produces an explicit error rather than silent fallback to a different model.
- D. Incorrect. There is no time-based restriction limiting settings.json defaults to projects created after the setting was added; settings apply to the project directory regardless of when the file was written.
Sources1
3.Why hooks never fire and settings seem ignored
Hook failures are usually silent, which makes them hard to spot. A matcher is a single string, with | separating tool names, as in "Edit|Write". A JSON array is a schema error: Claude Code rejects the whole user, project or local settings file, so no hook from that file appears in /hooks. Matching is case-sensitive, so "bash" matches nothing, and a misspelled tool name fails the same quiet way. Hooks must also sit under the hooks key in settings.json. Only plugins load a separate hooks/hooks.json.
~/.claude.json and ~/.claude/settings.json are different files. The first holds app state and UI toggles. Permissions, hooks and env belong in the second. Precedence can also hide a value: settings.local.json overrides settings.json, and both override the user-level ~/.claude/settings.json. Finally, remember what a permission rule can and cannot guarantee. A Bash(rm *) deny rule matches the literal command string, so it does not block /bin/rm or find -delete. For a hard guarantee, use a PreToolUse hook or the sandbox.
Sources1
4.Isolate the culprit, then report it
If inspection doesn't reveal the cause, remove variables. Starting Claude Code with a throwaway configuration directory shows whether your personal config is responsible. Managed settings still apply in that clean session, and you will be asked to log in again. Restarting with claude --safe-mode turns off all customisations for the session, which quickly shows whether a plugin, MCP server or hook is the source. It is also a useful first step for high CPU or memory use.
cd /tmp && CLAUDE_CONFIG_DIR=/tmp/claude-clean claudeFor slowness and memory growth, reduce what the session is holding. Use /compact with a focus that drops large output, /clear when earlier conversation is no longer needed, or move work on large files to a subagent so it runs in its own context window. If search is not finding files, a common fix is to install your system ripgrep and tell Claude Code to use it instead of the built-in copy.
{
"env": {
"USE_BUILTIN_RIPGREP": "0"
}
}When you escalate, share only what is safe to share. For a memory problem, attach only the -diagnostics.json file to a GitHub issue. It contains the statistics without any conversation content or credentials. /feedback sends a report straight to Anthropic.
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.You can define a team's project MCP servers under an mcpServers key in .claude/settings.json.Why is that wrong?
settings.json does not read mcpServers. Project servers go in .mcp.json at the repository root, and user-scoped servers are added with claude mcp add --scope user.
Covered in MCP servers: never loaded, failed, or empty
2.~/.claude.json is the global settings file, so permissions and hooks added there apply to every session.Why is that wrong?
~/.claude.json holds app state and UI toggles only. Permissions, hooks and env must go in ~/.claude/settings.json.
3.A Bash(rm *) deny rule reliably stops the agent from deleting files.Why is that wrong?
Bash rules match the literal command string, so /bin/rm or find -delete get past them. Use a PreToolUse hook or the sandbox for a hard guarantee.
Practise it for real
Work through the configuration debugging sequence on your own Claude Code install, from inspection to isolation.
1.In a session, run /doctor and then /mcp.
Why: /doctor finds invalid settings files and install problems, and /mcp shows each server's status, so you know which area is at fault before changing anything.
You should see: A setup report with proposed fixes, and a list of MCP servers each shown as connected, failed or awaiting approval.
2.Run /status and /permissions.
Why: Settings that seem ignored are often overridden by a higher-precedence source or by managed settings.
You should see: The active settings sources, including whether managed settings are in effect, and the resolved allow and deny rules.
3.If a server lists zero tools, start claude --debug=mcp and open ~/.claude/debug/<session-id>.txt.
Why: The server's own stderr shows why it is not returning a tool list.
You should see: The MCP server's stderr output in the debug log.
4.Run cd /tmp && CLAUDE_CONFIG_DIR=/tmp/claude-clean claude, then separately claude --safe-mode.
Why: The clean directory rules out your personal config, and safe mode turns off all plugins, MCP servers and hooks.
You should see: A login prompt in the clean session, where managed settings still apply. If the problem disappears in safe mode, one of your customisations is the cause.
Stuck? Get a nudge
Change one variable at a time. If safe mode fixes it, re-enable customisations one by one until the problem comes back.
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.https://code.claude.com/docs/en/debug-your-configOfficial docs
“Active settings sources, including whether managed settings are in effect”
↩︎ Inspect what Claude Code actually loaded“Relative file paths in command or args are a frequent cause, since they resolve against the directory you launched Claude Code from”
↩︎ MCP servers: never loaded, failed, or empty“run claude --debug=mcp and read the server’s stderr in the debug log at ~/.claude/debug/<session-id>.txt”
↩︎ MCP servers: never loaded, failed, or empty“Project-scoped servers in .mcp.json require a one-time approval.”
↩︎ MCP servers: never loaded, failed, or empty“A misspelled tool name produces a matcher that matches nothing, so the hook fails silently.”
↩︎ Why hooks never fire and settings seem ignored“settings.local.json overrides settings.json, and both override ~/.claude/settings.json.”
↩︎ Why hooks never fire and settings seem ignored“Managed settings still apply if your organization deploys them.”
↩︎ Isolate the culprit, then report it“Project MCP config goes at the repository root as .mcp.json, not inside .claude/, with servers under the mcpServers key.”
↩︎ Exam trap 1“~/.claude.json holds app state and UI toggles. permissions, hooks, and env belong in ~/.claude/settings.json.”
↩︎ Exam trap 2“Bash rules match the literal command string, not the underlying executable”
↩︎ Exam trap 3 - 2.https://code.claude.com/docs/en/troubleshootingOfficial docs
“Run /doctor for a setup checkup and /mcp to check MCP server status”
↩︎ Inspect what Claude Code actually loaded“Restart with claude --safe-mode to check whether a plugin, MCP server, or hook is the source.”
↩︎ Isolate the culprit, then report it“attach only the -diagnostics.json file, which carries the statistics behind the printed summary and no conversation content or credentials”
↩︎ Isolate the culprit, then report it“Move the large-file work to a subagent so it runs in a separate context window”
↩︎ Isolate the culprit, then report it