Claude code safe mode starts a session with every customization you supplied switched off — CLAUDE.md, skills, plugins, hooks, MCP servers, custom commands, agents, output styles, workflows, themes and keybindings. It is a troubleshooting flag for a broken configuration, not a security boundary. We measured it on Claude Code 2.1.258 against this repository on 2026-09-02: it removed 6,140 tokens of context and left the entire built-in tool surface untouched, which means the agent could still run the same commands it could a moment earlier. The Claude Code guide covers the session model this flag sits inside.
Key takeaways
- Safe mode removed 6,140 of 27,949 prompt tokens (22.0%) in our project — all of it configuration, none of it capability.
- The built-in block was byte-identical in both runs: default and safe mode both read the same 17,648-token cached prefix, so no tool was added or removed.
- Safe mode is not a sandbox.
--restrictedproduced a 14,711-token prompt by removing the command-running tools — 7,098 tokens below safe mode, and the only one of the three flags that reduces what the agent can do to your machine. - The saving is almost entirely a cold-cache effect: 52.3% cheaper on the first turn, 13.7% cheaper once the cache is warm.
--disable-slash-commandsmade the prompt 2,126 tokens larger, not smaller — reproduced three times.
The short answer
Safe mode answers one question: is my own configuration the problem? You reach for it when Claude Code starts behaving strangely after you added a hook, an MCP server or a skill, and you want a known-good baseline in one keystroke rather than by bisecting a config tree.
claude --safe-mode # Sets CLAUDE_CODE_SAFE_MODE=1 for the session.
What it does not do is constrain the agent. Anthropic's CLI reference is explicit that auth, model selection, built-in tools and permissions all work normally under the flag, and admin-managed policy settings still apply. Every measurement below confirms it.
What safe mode turns off, measured in tokens
We ran one non-interactive turn per mode against the same prompt and read the token counts out of --output-format json. Prompt size is input_tokens + cache_creation_input_tokens + cache_read_input_tokens. Every figure was reproduced at least twice and came back identical to the token.
claude --safe-mode -p "Reply with the single word: ok" --output-format json --model haiku # → "cache_creation_input_tokens": 4151 # → "cache_read_input_tokens": 17648 # → "input_tokens": 10
The project under test is this site: a 8,377-byte CLAUDE.md, two project agents, two project MCP servers, a 4,263-byte .claude/settings.local.json, plus eleven user-level skills and one plugin marketplace.
| Mode | Prompt tokens | Change |
|---|---|---|
| default | 27,949 | baseline |
--disable-slash-commands | 30,075 | +2,126 |
--strict-mcp-config | 27,772 | −177 |
--setting-sources=user | 25,385 | −2,564 |
--safe-mode | 21,809 | −6,140 |
--restricted | 14,711 | −13,238 |
--tools "" | 10,240 | −17,709 |
The number that matters is not the 6,140. It is the row below it. --restricted removes another 7,098 tokens that safe mode leaves in place, and those tokens are the tool definitions — Bash, the file editors, WebFetch. Safe mode does not touch them.

Where the 6,140 tokens come from
Running the same probe in an empty directory separates project configuration from user configuration, because an empty directory has none of the former.
| Where the session ran | default | --safe-mode |
|---|---|---|
| this project | 27,949 | 21,809 |
| an empty directory | 25,285 | 21,699 |
That gives a clean attribution, and it closes exactly:
- Project customizations — 2,664 tokens.
CLAUDE.md, the two agents, the two MCP servers and.claude/settings.local.json, obtained as 27,949 − 25,285. - User customizations — 3,586 tokens. The eleven skills, the plugin marketplace and
~/.claude/settings.json, obtained as 25,285 − 21,699. - Residue safe mode does not remove — 110 tokens. Safe mode in the project still costs 110 more than safe mode in an empty directory, because the working directory and git status sections of the system prompt are machine facts rather than customizations.
2,664 + 3,586 − 110 = 6,140, which is the measured delta to the token. npm run check:safe-mode asserts that identity, so if a future release moves one of those layers the arithmetic stops closing and the check fails.
npm run check:safe-mode # → --safe-mode 21809 tokens -6140 # → All 8 safe-mode guards passed.
If you want a narrower cut than safe mode's, --setting-sources removes one scope at a time, and which settings file wins measures what each of those scopes was contributing in the first place.
The practical reading: most of what safe mode drops is not in your repository. Two thirds of it came from user-level skills and plugins installed once and forgotten. If safe mode changes your session dramatically and your CLAUDE.md is small, look at ~/.claude before you look at the project.
Safe mode is not a sandbox
The phrase "claude sandbox" attaches itself to this flag constantly, and it points at the wrong one. Three flags get conflated, and they trade in different directions. If what you actually want is a session that cannot write, the read-only tool list is declared per command rather than per flag — /security-review is the clearest example.
| Flag | Drops your config | Drops tools | Prompt tokens |
|---|---|---|---|
--safe-mode | yes | no | 21,809 |
--restricted | user, project, local settings only | yes | 14,711 |
--bare | nearly everything | hooks, LSP, discovery | did not run |
--restricted is the one with a security shape. It removes the built-in tools that run commands or code, removes WebFetch unless --tools names them, confines the file tools to the working directories, refuses bypassPermissions, and requires a person or the configured permission handler to approve writes to settings, git and tool-configuration files. That is a capability boundary. Safe mode is a configuration reset.
If your reason for reaching for safe mode is "I do not want this agent running commands", the flag you want is --restricted, or a deny rule — see Claude Code permissions for how deny rules outrank everything else in the evaluation order.
When to start a session in safe mode
- A hook or plugin broke the session. This is the flag's actual job. Start in safe mode, confirm the behaviour disappears, then re-enable one surface at a time with
--setting-sourcesor--strict-mcp-config. Worth knowing before you go hunting: an untrusted workspace ignores itspermissions.allowrules and runs its hook commands anyway, so safe mode is also the fastest way to open someone else's checkout without executing what is in its settings file. - You are reproducing a bug for an issue report. A safe-mode transcript is the closest thing to a clean-room reproduction that does not involve a second machine.
- You want to know what your config is costing you. The delta is the number, and 6,140 tokens on every single request is not nothing.
- Someone else's repository is behaving oddly. Safe mode ignores their
CLAUDE.mdand their MCP servers without you having to read either first — and their PreToolUse hooks, which can allow a call the permission system would have refused.
It is a poor fit for cost control. On a cold prompt cache the first turn fell from $0.0235 to $0.0112, a 52.3% saving that looks compelling until the cache warms: the same comparison on a warm cache was $0.00395 against $0.00341, a 13.7% saving. Prompt caching, as Anthropic's caching documentation describes, makes stable context nearly free to re-read, and a CLAUDE.md is about as stable as context gets. Trimming it for cost reasons is covered properly in context window management.
What did not work
Two results went the wrong way, and both are more useful than the ones that behaved.
--bare never reached the API. It is documented to skip hooks, LSP, plugin sync, auto-memory and CLAUDE.md discovery — a smaller session than safe mode on paper. It refused to start:
claude --bare -p "Reply with the single word: ok" --model haiku # → Not logged in · Please run /login # → exit 1
This is documented behaviour rather than a defect: in bare mode Anthropic auth is strictly ANTHROPIC_API_KEY or apiKeyHelper, and OAuth and the keychain are never read. On a subscription seat with no API key exported, the flag cannot authenticate at all. If you are on a Pro or Max plan, --bare is not available to you without separate API credentials, and no amount of configuration on the Claude Code side changes that.
--disable-slash-commands made the prompt bigger. Disabling every skill should remove the skill listing and shrink the prompt. It did the opposite, by 2,126 tokens, and it did it three times in a row against a default session that measured 27,949 three times in a row.
claude --disable-slash-commands -p "Reply with the single word: ok" --output-format json --model haiku # → 30075 total prompt tokens (default: 27949)
We do not know the mechanism and are not going to guess at one. The measurement is stable and reproducible, and the operational conclusion is narrow but firm: do not reach for --disable-slash-commands as a context-saving measure, because on this machine and this version it costs context rather than saving it. If you want skills gone and the prompt smaller, safe mode is what does that.
Best practices
- Use safe mode as a bisect, not a destination. Confirm the problem disappears, then re-enable surfaces one at a time until it returns. The flag tells you whether your config is at fault;
--strict-mcp-configand--setting-sourcestell you which part. - Measure your own delta once. Run the JSON probe with and without the flag in your main repository. The number is specific to your configuration and it applies to every request you make.
- Reach for
--restrictedwhen you mean containment. It is the only one of the three that removes the tools that touch your machine. - Keep the managed tier in mind. Policy settings survive safe mode by design, so a safe-mode session is still governed by whatever your organisation set. That is a feature.
- Check
~/.claudebefore the repository. Two thirds of our 6,140 tokens came from user-level installs, not from anything committed.
Common mistakes
- Treating safe mode as a sandbox. It disables your config and leaves Bash, file edits and network access entirely intact. An agent in safe mode can still delete files and still push to a remote. The word "safe" is about the configuration being known-good, not about the blast radius.
- Using it to cut token spend. The 52.3% headline is a cold-cache artifact. Warm, it is 13.7%, and you have given up every rule that makes the agent useful in your codebase to get it.
- Assuming it disables permissions. It does not, in either direction. A
denyrule you rely on still applies; anallowrule you rely on also still applies. - Concluding your CLAUDE.md is fine because safe mode changed nothing. If the behaviour survives safe mode, the cause is in the built-in surface, the model, or the prompt — and why Claude ignores CLAUDE.md is the more useful diagnosis path from there.
Conclusion
Start a session with --safe-mode when you suspect your own configuration, and treat the result as a diagnosis rather than a fix: it cost us 6,140 tokens of context and bought a clean baseline. Do not reach for it when you want the agent constrained — --restricted is the flag that removes command-running tools, and a deny rule is the one that survives a session restart. If you are on a subscription plan, note that --bare is closed to you entirely. Next, read Claude Code permissions for the boundaries that actually hold.
Frequently asked questions
What does Claude Code safe mode actually disable?
Is Claude Code safe mode a sandbox?
How much context does --safe-mode save?
Does safe mode make Claude Code cheaper?
What is the difference between --safe-mode, --restricted and --bare?
Muhammad Kashif
Founder and editor of Devventa, covering AI coding assistants, Next.js and the modern AI development stack.



