>_

Claude Code Auto Mode Skips Edit Hooks: I Tested It [2026]

Robin||7 min
claude-codeauto-modehookspermissionsmeasurement
Claude Code auto mode edit hooks test - file edits routed through Bash instead of Edit and Write, PostToolUse hook matcher Edit|Write not firing, CLAUDE_CODE_THRIFTY_SONIC opt-out, bashEditDiff, Opus 5.5, Claude Code 2.1.284, permission modes, primeline-ai/evolving-lite

Claude Code auto mode changes the way your files get edited, and a hook you wrote for edits may never see them. I tested it on Claude Code 2.1.284 with Opus 5.5. Every time Bash was allowed, the model made the edit through the Bash tool instead of Edit or Write. That was 10 of 10 runs. A hook matched on Edit|Write saw none of the 5 edits it was watching. The file changed every time. The hook was just not told.

This is not new. It was reported on August 18 in GitHub issue #87575 and discussed on Hacker News and in a Reddit PSA. What I add is a measurement on Claude Code 2.1.284, plus a test of both fixes. One hook in my open-source plugin primeline-ai/evolving-lite uses exactly this matcher.

Claude Code auto mode in 40 seconds: Bash edits, silent hook, two fixes

The video is code, not a video model. Opus 5.5 wrote it as HTML and GSAP after studying the motion-graphics examples going around this month, and HyperFrames recorded it frame by frame.

Why does Claude Code auto mode edit files with sed instead of the Edit tool?

People keep asking this one, in words like "why does Claude write Python scripts to change the code". According to the system prompt text quoted in the issue, this mode tells the model to read files with cat or sed -n and change them with sed, heredocs or short scripts, instead of Read, Edit or Write. In my runs the model did exactly that. The edit still lands, but it arrives as a shell command.

That matters because a lot keys on the tool name. A hook with the matcher Edit|Write only runs when the tool is Edit or Write. When the same change arrives as sed -i, the matcher never matches. The issue reports more side effects, including /rewind not undoing Bash edits. I did not test those.

How I tested auto mode edits

Every run was a fresh headless claude -p session with no MCP servers and none of my own plugins or settings. I used two small tasks: first a 2 line file with one word to replace and one line to add, then a 30 line file with one word to replace. The hook runs loaded one settings file that held only the test hooks. Between arms I changed only the permission mode or the opt-out switch. In the main test the two arms ran alternately, four runs each, so a change on Anthropic's side is an unlikely explanation.

Claude Code auto mode test results - which tool made the file edit, auto mode 10 of 10 edits through Bash when Bash was allowed, with CLAUDE_CODE_THRIFTY_SONIC=0 9 of 9 through Edit or Write, acceptEdits 3 of 3 through Write, Opus 5.5, Claude Code 2.1.284
Same model, same build. Only the permission mode or the opt-out switch changed. (click to expand)

All 23 edits were correct. The edits were not worse, they came through a different door.

What happens when the auto mode classifier is down?

There was one more auto mode run. The safety check that approves commands in this mode returned "gave no verdict (error), so auto mode cannot determine the safety of Bash". Bash was blocked for that call, and the model fell back to Read and Edit on its own. That run is left out of the 10, because it shows an outage, not a choice. The same error message is in a Reddit thread from this week. In my one run the edit still landed, and the Edit|Write hook fired.

This test does not cover larger tasks, other machines, or the interactive terminal. The issue was filed against an older build, 2.1.234, so I expect the same there, but I did not measure it.

Which hooks miss edits in auto mode?

Hooks whose matcher names only Edit or Write. I registered a PostToolUse hook on Edit|Write that logs one line each time it fires, and a second one on Bash. The Edit|Write hook saw none of the 5 Bash edits in the hook runs. It fired once, in the run where the safety check was down and the model used Edit. With the opt-out switch it saw 6 of 6. I measured PostToolUse only. PreToolUse uses the same matcher, so I expect the same gap, but I did not test it.

Hooks that also list Bash keep firing, but they get a command string that you would have to parse yourself, unless they read the diff from fix 2. For what hooks can and cannot block, see Claude Code hooks: automate your workflow, and for why a hook that runs is not a hook that enforces, this enforcement test.

Claude Code auto mode hook test - PostToolUse hook matched on Edit|Write saw 0 of 5 Bash edits, 6 of 6 with CLAUDE_CODE_THRIFTY_SONIC=0, a Bash hook reading bashEditDiff got the changed file in 2 of 2 runs, Opus 5.5
An Edit|Write hook only sees what arrives as Edit or Write. Both fixes below brought the edit back into view. (click to expand)

This lives in primeline-ai/evolving-lite - the self-evolving Claude Code plugin. Free, MIT, no build step.

Two fixes for auto mode hooks, both tested

The first fix brings edits back to Edit and Write while the session stays in the same mode. The second leaves the Bash edits alone and lets a Bash hook see what they changed. I tested both on the same build.

Fix 1: turn off the Bash-first behaviour

The switch is CLAUDE_CODE_THRIFTY_SONIC=0. A user named knobik posted it in the issue on the day it opened. Another user, oconnorjoseph, showed it also works from the env block of a settings file, which a team can check in once. It worked both ways for me: 7 of 7 runs with the shell variable and 2 of 2 with the settings file. The edits went through Edit or Write, and the session still reported auto mode.

json
{
  "env": {
    "CLAUDE_CODE_THRIFTY_SONIC": "0"
  }
}

The catch: this variable is not documented, and the commenter who found it calls the Bash-first behaviour an A/B experiment. In issue #88041 another user adds two warnings. Leaving it unset is not the same as 0. And because it is an experiment flag, it may switch off other things bundled into the same experiment. The name or the effect can change without notice, so re-test after updates.

Fix 2: read bashEditDiff in a Bash hook

This one is documented. Since v2.1.269, a PostToolUse hook on Bash can receive the files a command changed in tool_response.bashEditDiff. The hooks documentation says this is recorded when Claude Code directs Claude to edit through Bash. It is recorded in every mode if you turn on bashEditDiffEnabled. In my test a Bash hook got the changed file and lines in 2 of 2 runs, and nothing for read-only cat calls.

json
{
  "hooks": {
    "PostToolUse": [
      { "matcher": "Bash", "hooks": [{ "type": "command", "command": "python3 your-hook.py" }] }
    ]
  }
}

Limits from the docs: it covers changes in a Git repository, and ignored files and submodules are not listed. It is also a PostToolUse field, so it only helps after the edit. A PreToolUse guard that should stop an edit still gets only the command string.

Why does Claude Code do this?

Anthropic has not explained it in the issue. It has 15 comments and none are marked as coming from the Anthropic team. My guess is cost: Bash is one small tool, while Read, Edit and Write each carry a schema. One commenter asks Anthropic to keep the behaviour for that reason and to add an opt-out toggle. That is fair. The Bash route may cost you nothing if you have no hooks and no /rewind.

Auto mode became the default for Pro, Max and Team plans in August, so many people run it without having chosen it.

Check your own setup in two minutes

List every hook whose matcher names Edit or Write but not Bash. In my test such a hook missed all 5 Bash edits. In Evolving Lite there is one, the PostToolUse Write|Edit entry in hooks/hooks.json that calls artifact-registration-enforcer.py. I did not run that script in this test, but its matcher is the one I measured. If you run the plugin in auto mode, add the CLAUDE_CODE_THRIFTY_SONIC env line from fix 1.

Then run one edit and look at the tool name in the transcript. If it says Bash, your Edit or Write hooks were skipped for that edit. The same kind of quiet gap shows up elsewhere, as in my test of hooks that fail in runs.

The plugin is at primeline-ai/evolving-lite, and it installs in one clone.

FAQ

Does Claude Code auto mode always edit files through Bash?+
In my test on Claude Code 2.1.284 with Opus 5.5, every run where Bash was allowed made the edit through Bash, 10 of 10. In one extra run the safety check returned no verdict, Bash was blocked, and the model fell back to Edit. So it holds whenever Bash is available, on the tasks I tested.
How do I make hooks fire on edits again?+
Two ways. Set CLAUDE_CODE_THRIFTY_SONIC to 0 in your shell or in the env block of settings.json, which brought Edit and Write back in 9 of 9 runs. Or add a PostToolUse hook on Bash that reads tool_response.bashEditDiff, which is documented and needs v2.1.269 or later.
Is CLAUDE_CODE_THRIFTY_SONIC documented by Anthropic?+
No. A user posted it in GitHub issue 87575, and it works on Claude Code 2.1.284 in my tests, but it is not in the official documentation. Treat it as a switch that can change or disappear in any update, and re-test it after upgrading.
Why does Claude write Python scripts or sed commands to change code?+
In auto mode, Claude Code's own system prompt tells the model to change files with sed, heredocs or short scripts instead of the Edit and Write tools. In my test it did that in every run where Bash was allowed, 10 of 10. The edits were correct, they just bypass anything keyed on Edit or Write.
What happens when the auto mode classifier is down?+
Bash calls get blocked with the message that the classifier gave no verdict. In the one run where this happened to me, the model fell back to Read and Edit on its own, the edit was correct, and the Edit|Write hook fired. One run is a single observation, not a rule.
Can a PreToolUse hook just block sed and force the Edit tool?+
I did not test it. A user in GitHub issue 88041 reports that when a hook blocks sed and asks for Edit, subagents stall and ask the parent agent which instruction wins. The opt-out switch or a bashEditDiff hook avoids that conflict, because neither fights the system prompt.
How do I stop Claude Code from starting in auto mode?+
Set permissions.defaultMode in settings.json to acceptEdits or default. With acceptEdits the model used Read and Write in 3 of 3 of my runs and never edited through Bash. You can also switch modes during a session with Shift+Tab.

>_ Get the free Claude Code guide

>_ No spam. Unsubscribe anytime.

>_ Related