Blog

Claude Code Recovery: Safe Mode, /cd, and Fallback

Markdown

Diagnosing Claude Code with safe mode, the /cd command, fallback models, and settings recovery. The order of checks and original limitations.

Read full article

Practical materials on working with agents: Ailoot documentation.

What Changes in Claude Code in June 2026?

Key takeaways

On June 8, 2026, in Claude Code v2.1.169, Anthropic added the --safe-mode flag and the /cd command. Two days earlier, v2.1.166 introduced fallback models, up to 3 in a chain. These three features address the most common pain point for vibe coders: “everything has gone down, I don’t know who’s to blame, and I don’t want to lose an hour reinstalling.”

Previously, when Claude Code started behaving strangely—an endless spinner, a crash on startup, the agent ignoring rules in CLAUDE.md, a hook silently not firing—there was only one way out: manually comment out sections of .claude/settings.json, disable MCP servers one by one, or, in the worst case, delete ~/.claude and reinstall. In one described case, ~/.claude was deleted and the MCP server setup, which had taken an hour and a half to assemble, was lost. It later became clear that one line in CLAUDE.md was to blame, and it could have been found in 10 seconds—but that only became clear after a full recovery.

In June 2026, Anthropic rolled out three mechanisms that change this scenario. In brief, what arrived and when:

VersionDateWhat arrived
2.1.166June 6, 2026fallbackModel setting + --fallback-model flag for interactive sessions
2.1.169June 8, 2026--safe-mode flag and CLAUDE_CODE_SAFE_MODE environment variable, /cd command
2.1.176June 12, 2026Fix: /cd and worktree switching stopped showing the old git branch

Below, each mechanism is explained step by step, along with the order in which to apply them when a Claude Code session goes off track.

What Breaks Claude Code Most Often?

Key takeaways

Based on the described experience, Claude Code typically breaks for vibe coders because of four things: an overgrown CLAUDE.md with contradictory rules, a hook with the wrong exit code, an MCP server that fails silently, and overlapping settings across three levels of settings.json. There is one culprit, diagnosis takes minutes, and panic drives people to reach for rm -rf immediately.

In the example described, CLAUDE.md was initially put together in 80 lines—and it worked for a month. In the second month, it became noticeable that once a week Claude would violate every rule that had been set: touch .env, run git push --force, poke around in node_modules. Not maliciously—it simply forgot. Once, .gitignore was deleted, and the reason was not immediately clear. This scenario is covered in more detail in the guide to CLAUDE.md.

When CLAUDE.md grows to 400+ lines, it starts silently causing trouble: it takes up a significant part of the context window at session startup and dilutes important instructions among secondary ones. Claude still formally reads the file, so from the outside it looks like “the rules are there, but they don’t work”—a typical sign of an overgrown contract.

Hooks are the second common source. Claude Code hooks have a nuance that Anthropic does not emphasize:

That is, sys.exit(1) in a Python hook (or any Unix-conventional “failed with an error”) will not stop Claude. Only code 2 is blocking. In the described case, the hook was considered a “hard prohibition,” but in practice it logged a complaint and allowed the action.

MCP servers are the third layer, and they break in their own way too.

The symptom often looks the same: MCP commands are available, but return failed without a traceback. For more on configuring MCP and adding servers with claude mcp add, see the separate guide.

The fourth source is the three-tier settings.json hierarchy. You have ~/.claude/settings.json (user level), .claude/settings.json at the project root (project), .claude/settings.local.json (local), and optionally managed settings from a corporate administrator. They are combined according to priority rules. When someone adds an MCP server at the project level while you have a similar entry with a different launch configuration at the user level, a silent conflict results, which looks like “Claude Code is broken.”

How Does --safe-mode Work, and What Does It Disable?

Key takeaways

claude --safe-mode launches Claude Code with customizations fully disabled: CLAUDE.md, plugins, skills, hooks, MCP servers, user commands, agents, output styles, workflows, and keybindings. Authorization, model selection, built-in tools, and permissions remain. This is a diagnostic tool: if the problem disappears in safe mode, one of the layers you added is to blame.

Anthropic’s original wording in the v2.1.169 changelog reads:

Added the --safe-mode flag (and CLAUDE_CODE_SAFE_MODE) to launch Claude Code with customizations disabled (CLAUDE.md, plugins, skills, hooks, MCP servers) for diagnostics.

— Anthropic Claude Code Changelog, https://code.claude.com/docs/en/changelog

Anthropic clarifies in the model-config documentation:

To check whether customizations are to blame, start a session with claude --safe-mode, which disables CLAUDE.md, skills, MCP servers, and hooks. Git status and directory names are not considered customizations and remain available.

— Anthropic Docs - Model configuration, https://code.claude.com/docs/en/model-config

This is a diagnostic tool, not a “clean environment.” Safe mode helps answer one question: is the problem in Claude Code’s out-of-the-box behavior, or in the added customizations? This is part of context engineering—managing what Claude sees and does not see at any given moment. If everything works in safe mode, it is clear that the layers need to be checked using a binary search. If it does not work, the problem is with the installation itself, authorization, the network, or the infrastructure, and then it makes sense to look at claude doctor and the logs.

What safe mode disables (Anthropic’s official list—5 main layers):

  • CLAUDE.md at all levels (user / project)
  • Plugins
  • Skills
  • Hooks
  • MCP servers

What remains working:

  • Authorization (your OAuth session or API key)
  • Model selection (--model sonnet, --model opus)
  • Built-in tools (Read, Write, Bash, Grep, and so on)
  • Permissions
  • Git status
  • Directory names

An important detail: safe mode does not disable managed/policy settings from a corporate administrator. If you work in a team where Bedrock GovCloud or an MDM config sets availableModels, those restrictions remain—safe mode disables only your customizations, not corporate policies.

How to Isolate a Layer and Find the Culprit in 60 Seconds?

Key takeaways

Step 1: run claude --safe-mode in the same folder where things were going wrong. If it works, the issue is in your customizations, and then you enable them one by one: CLAUDE.md -> hooks -> MCP -> skills. If it does not work even in safe mode, the problem is with auth, the version, the network, or the OS. In that case, run claude doctor for automatic diagnostics, without touching rm -rf.

A diagnostic scenario for when Claude Code has “stopped listening.” The minimum version for all commands below is Claude Code v2.1.169. If yours is older, update first (npm update -g @anthropic-ai/claude-code or Anthropic’s native installer).

  1. Open the same folder where things were going wrong.
  2. Run claude --safe-mode.
  3. If it starts cleanly, check your original request. Did it work? Then one of the layers is to blame. Go to step 4.
  4. If it is still broken in safe mode, do not touch the configs. Run claude doctor first; check auth, version, and conflicting installations.

Once safe mode starts cleanly, enable layers one at a time, starting with the most likely culprit. The order based on the described experience:

  1. CLAUDE.md. Run claude without safe mode, but temporarily rename the file: mv CLAUDE.md CLAUDE.md.bak. If it works, that file is the cause. Then you can do a binary search: keep half the lines and check.
  2. Hooks. Open .claude/settings.json and temporarily set [] in the hooks section. Restart claude. Does it work? Then one of the hooks is to blame. Enable them one by one.
  3. MCP servers. Similarly, in ~/.claude.json or .claude/settings.json, set the mcpServers section to an empty object temporarily, restart, and check.
  4. Skills. Move .claude/skills/ to a temporary folder. Launch and check.

What “temporary renaming” means: files are not deleted during diagnosis. mv or git stash let you restore everything with one command if that layer turns out not to be the culprit.

How to Switch the Working Folder with /cd Without Losing Context?

Key takeaways

The /cd <path> command in Claude Code 2.1.169+ switches the working folder in the active session without losing the prompt cache. Useful when the current project’s config is broken: you can move to a clean folder, check that Claude works, and return. Before, you had to close the session and start again.

From the v2.1.169 changelog on June 8:

Added the /cd command to switch the session to a new working folder without resetting the prompt cache mid-session.

— Anthropic Claude Code Changelog, https://code.claude.com/docs/en/changelog

Why this is useful when fixing things. Suppose you are in the project folder ~/work/myapp, and Claude Code is behaving strangely. Before, the only way to check “is it working at all?” was to close the session, move to another folder, and start again. You lost the context, history, and warmed prompt cache. Now:

# In the same session:
/cd ~/sandbox/test

Claude switches to the new folder and reads its CLAUDE.md (if any) as a message, not as a replacement system prompt—that is, the cache is preserved. If everything works in ~/sandbox/test, it is clear that the problem was in the config for ~/work/myapp.

On June 12, v2.1.176 fixed one unpleasant regression—/cd showed the old git branch until a full restart. If your version is older, either update or simply ignore git status for the first few messages after switching—it will catch up.

How to Configure Fallback Models for a 529?

Key takeaways

In v2.1.166, Anthropic added fallbackModel—a chain of up to 3 models tried in sequence when the primary is overloaded or unavailable. The chain is triggered only by overloaded and non-retryable server errors. Authorization, billing, rate-limit, and transport errors do not trigger the fallback chain—they follow the regular retry logic.

In the scenario described, a long task runs on Opus in a project once a week; after 10 minutes, the API returns 529 Overloaded and the session crashes. Before, you had to either wait or switch manually to Sonnet with --model sonnet and lose all the warmed context. In a large business/ with a second-brain setup, this takes about twenty minutes of work. Now there is a proper mechanism.

The exact quote from the official documentation:

When the primary model is overloaded, unavailable, or returns another non-retryable server error, Claude Code can switch to a fallback model instead of failing the request. Authorization, billing, rate-limit, request size, and transport errors never trigger switching—they follow the regular retry and error-handling path.

— Anthropic Docs - Model configuration, https://code.claude.com/docs/en/model-config

And separately, how the chain works:

Configure one or more fallback models, and Claude Code tries them in order, showing a notification when it switches. The switch applies only to the current turn—the next message tries the primary model again. Chains are limited to three models after deduplication; additional entries are ignored.

— Anthropic Docs - Model configuration, https://code.claude.com/docs/en/model-config

Two ways to configure it. Through the CLI:

claude --fallback-model sonnet,haiku

Through ~/.claude/settings.json:

{
  "fallbackModel": ["claude-sonnet-4-6", "claude-haiku-4-5"]
}

A separate nuance about rate limits. Anthropic deliberately does not send a 429 error through the chain, so that you cannot bypass the request limit by switching to the next model. Fallback works only when the primary model is overloaded, unavailable, or returns a non-retryable server error (for example, 529 Overloaded). Rate limits use the regular retry logic and backoff.

One more nuance—on June 12, v2.1.174 fixed a regression: compaction had not respected --fallback-model. If you have a long session and it compacts while overloaded, before this fix the fallback model was not called. If you work with long sessions (/compact, /loop overnight), update to at least v2.1.174.

What to Fix When CLAUDE.md, a Hook, MCP, or a Skill Is to Blame?

Key takeaways

When safe mode identifies the layer to blame, the fix differs by layer. For CLAUDE.md, use a binary search or revert to a ready-made template under 200 lines. For a hook, check the exit code (2 blocks, 1 does not) and the logic. For MCP, remove one server and check. For a skill, check SKILL.md for contradictions with CLAUDE.md.

Specific strategies for each layer.

If CLAUDE.md Is to Blame

Open the file and check its size. Based on the described experience, keep the active CLAUDE.md to no more than 200 lines; move the rest into routers and supporting documents alongside the project (the full second-brain structure is in the guide to the second brain). If you have 400+ lines, it is almost certainly to blame. Steps:

  1. Make a backup: cp CLAUDE.md CLAUDE.md.full.
  2. Revert to a short working template. A ready-made one is in the “How to Configure CLAUDE.md” guide.
  3. Restart Claude Code. Check.
  4. If it works, restore rules in small blocks of 10–20 lines, checking after each block.
  5. Find the block that breaks behavior. Rewrite it as a hook with the correct exit code (exit codes for hooks are covered in the next subsection of this H2).

If a Hook Is to Blame

The main question is whether the exit code is correct. Claude Code hooks use:

  • Exit 0 — all good; the action proceeds.
  • Exit 1 — an error, but non-blocking. Claude carries on as if nothing happened.
  • Exit 2 — a blocking error. Only this actually stops the action.

If you wrote sys.exit(1) or exit 1 in a shell hook, thinking you were blocking, that code works as a warning log in Claude Code, without stopping the action. Change it to 2. For details on hooks and how to configure them without this pitfall, see the separate guide.

The second common case is a hook returning invalid JSON on stdout. Claude Code parses the hook response as JSON, and if there is junk in it (a log, progress marker, emoji), the hook is considered failed and the action proceeds. Rule: stdout is JSON only; everything else goes to stderr.

The third is a hook reading something from ~/.claude/ that safe mode has hidden. This is a normal scenario; fix it not by patching the hook, but by checking os.environ.get('CLAUDE_CODE_SAFE_MODE') at the start and exiting with 0.

If an MCP Server Is to Blame

Symptoms: MCP commands are available, but return failed without a clear traceback. Steps:

  1. Run claude mcp list—which servers are defined?
  2. Disable servers one by one in ~/.claude.json: rename the key claude-server-A to _claude-server-A (this deactivates it without deleting it).
  3. Restart claude. Check which calls work.
  4. Once you find the server to blame, check its log: claude mcp logs <name>.
  5. If it is a third-party server (@modelcontextprotocol/server-postgres and similar), check whether it has a recent release. The MCP ecosystem is still in turmoil; servers regularly break with Claude Code updates.

If you encounter “crashes on startup, and only with two MCPs,” compare behavior in safe mode without MCP.

If a Skill Is to Blame

A skill is SKILL.md plus code in .claude/skills/<name>/. Symptoms: Claude ignores the skill, applies it at the wrong time, or applies it but produces junk. Steps:

  1. Open SKILL.md. Check the description—it should be 1–2 sentences and specifically describe when to use it. If it says “a universal helper for everything,” Claude does not understand when to invoke it.
  2. Check for contradictions with CLAUDE.md. If CLAUDE.md says “always write tests,” but the skill description says “use for quick prototyping without tests,” there is a conflict.
  3. If the skill uses external commands (npm, python, git), check that they are available in the systemwide PATH. A skill has its own minimal environment.

What to Do if Safe Mode Did Not Help: Diagnose and Preserve State Before Repair

Key takeaways

If safe mode also fails, the remaining possibilities include installation, authorization, network, or infrastructure. Run claude doctor and inspect its evidence. An inconclusive report does not justify deleting settings or sessions: preserve and verify the full state first, then repair only the diagnosed installation.

User-state removal is not a diagnostic shortcut. Use the checks below to identify the fault; if they are inconclusive, preserve the evidence and investigate further. Any installation repair starts with a verified backup and keeps the existing account and credential-store identity. Order:

  1. claude doctor — automatic diagnostics. Anthropic writes in its documentation:

If claude --version works but something else is going wrong, run claude doctor to generate an automatic diagnostic report.

— Anthropic Docs - Troubleshoot installation, https://code.claude.com/docs/en/troubleshoot-install
  1. Check for conflicting installations. Many people have both an npm global version and the native installer installed at the same time:

Multiple Claude Code installations can lead to version mismatches or unexpected behavior.

— Anthropic Docs - Troubleshoot installation, https://code.claude.com/docs/en/troubleshoot-install
  1. Check whether ANTHROPIC_API_KEY is intercepting your OAuth session. This is a common cause of “nothing works, the key expired”:

When `ANTHROPIC_API_KEY` is set and you have confirmed it, Claude Code uses that key instead of your subscription OAuth credentials.

— Anthropic Docs - Troubleshoot installation, https://code.claude.com/docs/en/troubleshoot-install

Solution: unset ANTHROPIC_API_KEY in the current shell session or remove it from ~/.zshrc / ~/.bashrc.

  1. Repair only the installation that diagnostics identify; preserve all user state first. A failure in safe mode or an inconclusive doctor report does not establish that user data must be removed. Stop all Claude sessions and other writers before making a consistent backup. Keep the same Unix account, HOME, operating-system credential store, and Anthropic account; do not rotate keys or create a replacement identity.

The following backup example is for Linux with GNU tar. On macOS or Windows use a backup tool that preserves that platform’s ACLs, extended attributes, links, and metadata, and verify restoration before proceeding; do not assume GNU-only flags work there. The archive contains credentials and session transcripts: keep it private and outside repositories.

# Run as the same user who owns the Claude state, after stopping writers.
set -eu
umask 077
backup_dir=$(mktemp -d "$HOME/.claude-recovery-XXXXXXXX")
set --
if [ -e "$HOME/.claude" ] || [ -L "$HOME/.claude" ]; then
  set -- "$@" .claude
fi
if [ -e "$HOME/.claude.json" ] || [ -L "$HOME/.claude.json" ]; then
  set -- "$@" .claude.json
fi
[ "$#" -gt 0 ] || exit 1
tar --acls --xattrs --numeric-owner -cpf "$backup_dir/claude-state.tar" -C "$HOME" "$@"
tar --acls --xattrs --compare -f "$backup_dir/claude-state.tar" -C "$HOME"
sha256sum "$backup_dir/claude-state.tar" > "$backup_dir/claude-state.sha256"
(cd "$backup_dir" && sha256sum -c claude-state.sha256)
mkdir "$backup_dir/restore-check"
tar --acls --xattrs -xpf "$backup_dir/claude-state.tar" -C "$backup_dir/restore-check"
tar --acls --xattrs --compare -f "$backup_dir/claude-state.tar" -C "$backup_dir/restore-check"
printf 'Verified recovery directory: %s\n' "$backup_dir"

All commands must succeed. The archive covers the entire existing .claude tree, including ignored/untracked sessions and plugin state, and .claude.json, not just git-tracked settings. If either path is a symlink or data lives in a separate configured location, stop and include the resolved target in the same verified backup; archiving a link alone does not back up its target. The archive does not contain macOS Keychain or another external credential store, so keep those identities in place.

If diagnostics specifically identify the legacy local installation as the conflicting copy, move just that installation into the private recovery directory, rather than deleting the configuration and sessions:

# Use the verified backup_dir from the previous block.
if [ -d "$HOME/.claude/local" ]; then
  mv "$HOME/.claude/local" "$backup_dir/legacy-local"
fi

Remove an npm installation only if diagnostics identify it as the conflicting install and you intend to retain the native one. Then use the documented native installer, without deleting .claude or .claude.json:

curl -fsSL https://claude.ai/install.sh | bash
claude --version
claude doctor

On Windows, the native installation command remains:

irm https://claude.ai/install.ps1 | iex

Restore separately. Stop writers again. Check the archive checksum and extract into an empty recovery directory as above; compare it successfully before using the files. If the moved legacy installation must be restored, first confirm that $HOME/.claude/local does not exist, then move $backup_dir/legacy-local back to that exact path. Restore a diagnosed settings file from the verified extraction only after preserving any current replacement; do not overlay the whole tree blindly. Sessions, MCP settings, and the original identity remain preserved. A git snapshot alone does not cover ignored/untracked transcripts, credentials, or filesystem metadata.

What Should You NOT Do When Claude Code Is Broken?

Key takeaways

Six anti-patterns found in the described support cases: changing keys before diagnosis, doing a full reset as the first step, panicking over a UI error in a hook, raising a hook’s exit code before fixing the logic, editing CLAUDE.md without a safe-mode safeguard, and believing that “Claude fixes its own MCP.” Each costs hours, and none is necessary.

Don’t Change Keys Before Diagnosis

“Authorization does not work” is in 90% of cases either ANTHROPIC_API_KEY intercepting the subscription, a hook UI bug, or a failed MCP. Rotating keys will fix none of these, but will cause another hour of downtime: you have to revoke the old key, issue a new one, re-sign CI with it, and update the variables in production. Run claude --safe-mode first. Does it work? Then the issue is in the customizations; there is no need to touch the keys.

Don’t Do a Full Reset Before Safe Mode

Safe mode provides an isolated environment in 1 second. Deleting .claude can destroy sessions, MCP configuration, and other untracked state. Diagnose first, verify a private backup, and use a reversible move only for the installation or configuration layer actually implicated.

Don’t Panic Over a UI Error in a Hook

Before fixing anything, check whether the hook actually ran (via a log to stderr or an explicit print), rather than relying on the visual indicator.

Don’t Raise a Hook’s Exit Code Before Fixing the Logic

When your blocking hook does not block, it is tempting to set exit 2 and call it done. This is a working patch, but it hides another problem: if the block did not work for a month, then everything the hook was supposed to prohibit went through. First go through the git log and find out exactly what slipped through. Then add the block. Otherwise, a closed block does not undo what happened before it.

Don’t Edit the Production CLAUDE.md Without a Safe-Mode Safeguard

In the described case: you edit CLAUDE.md, Claude starts behaving strangely, you run git diff and see that someone also added an MCP server and a hook to the repo that evening. You blame your edit, revert it, and Claude still behaves strangely. Rule: before git revert, run claude --safe-mode. If the problem persists in safe mode, your edit had nothing to do with it; there is no need to revert.

Don’t Believe “Claude Fixes Its Own MCP”

A typical scenario: you ask Claude to “add a certain tool to the MCP server,” Claude rewrites the working config, everything breaks, and then Claude spends several turns debugging the damage it caused—and in the process burns through the session quota. When MCP is broken, get the config manually; do not leave it to the agent. Part of its tool arsenal also runs on MCP, and a broken MCP means a broken diagnostician.

Where to Go After You’ve Fixed It?

Key takeaways

Once you have restored Claude Code, add prevention so it does not break again. At minimum: disableBypassPermissionsMode: "disable" in user settings, hooks that block .env and git push --force, and a sandbox for long autonomous runs. The prevention guide is its counterpart.

After analyzing the incident, do not return to work immediately. First add prevention so the incident does not recur. You can lose hours on a second brain (the business/ folder with the project structure) and CLAUDE.md, and restoring them manually is difficult—that is a strong reason. Minimum set:

  1. ~/.claude/settings.json with permissions.disableBypassPermissionsMode: "disable"—an architectural prohibition on bypass mode, so an accidentally launched --dangerously-skip-permissions simply will not work.
  2. Hooks for Read(./env*), Bash(git push --force), Write(./node_modules/**)—things that must be caught at the level of law, not wishes.
  3. Sandbox config for long autonomous runs (/loop, /schedule).
  4. /compact with your own rules for what to discard from context, so Claude does not consume itself.

The full four-layer protection scheme is in the guide “How to Configure Claude Code So It Does Not Break Your Project Overnight”. One guide covers prevention before launching /loop; the other covers recovery after /loop has already broken something. A logical pair.

Sources

Practical materials: Ailoot documentation.

More materials and tools: Ailoot.

More details

Questions about Claude Code Recovery: Safe Mode, /cd, and Fallback | Ailoot

Does a failure in safe mode mean I should delete ~/.claude?

No. It still leaves installation, authorization, network, and infrastructure causes to investigate. An inconclusive doctor report is not evidence that settings or sessions must be removed; repair only the diagnosed layer.

What must be preserved before installation repair?

Stop writers and back up the complete Claude state, including sessions, plugin/MCP configuration, ignored files, and filesystem metadata. Verify checksum and extraction before proceeding, keep the existing account and credential store, and restore only the diagnosed layer without blindly overwriting current state.

All articles