[Bug] Claude Code prefers shell commands over Edit tool for file mutations, hiding changes from transcript

Status Open
Reported on v2.1.226
Maintainer reply None cached
Activity 1 comment · opened Aug 9, 2026

Bug Description
Subject: Claude Code frequently mutates files with shell commands (sed / inline Python) instead of the Edit tool, which makes the change invisible in the conversation Summary Claude Code has a built-in Edit tool that renders the change inline as "old → new". It also has Bash, and it regularly chooses Bash to modify source files — a sed invocation, an inline Python script, a heredoc rewrite. When it does, the transcript shows nothing but: Ran 1 shell command The file changed. I cannot see how. As a reviewer I'm left with two bad options: trust it, or leave the conversation and diff the file myself. I'd like the built-in edit tools to be the default path for mutating files, and shell-based mutation to be the exception that has to justify itself. Concrete example I asked Claude Code to rewrite a ~17-line section of a Markdown file. It wrote an inline Python script that replaced that line range, then reported "done." My screen showed Ran 2 shell commands and nothing else. I had to explicitly ask "show me what you changed" before I could review anything — at which point it produced a diff -u against a backup, and the change turned out to be fine. But I only learned that by asking. Seventeen lines. This is well within what Edit handles comfortably. Nothing about the task called for a script. Why this matters 1. Review cost is silently transferred to the user. Edit puts the diff where I'm already looking. A shell mutation puts it nowhere. Multiply that across a session and I'm either rubber-stamping changes I haven't seen, or doing the model's presentation work by hand. 2. Shell substitution is mechanical substitution. A regex replace across a file does not read the surrounding code, does not weigh each site individually, and cannot notice that site #7 means something different from sites #1–6. The visibility problem and the correctness problem have the same root: nobody looked at each spot. 3. Switching languages is not a fix. "I won't use sed, I'll write a Python script instead" is the same behavior. The criterion isn't which binary was invoked — it's whether the change is visible in the conversation and whether each site was considered individually. Both tools fail both tests. 4. Editing via the tool forces comprehension; scripting via line numbers does not. Edit requires the file to have been read. A line-range splice does not require understanding anything but the boundaries. The read-first flow routinely surfaces adjacent problems — a stale statement two paragraphs down, a duplicate elsewhere. Splice-and-paste finds nothing beyond its own window. 5. It's unsettling to watch. I've been a working programmer for over a decade and have never once used sed. I don't know its escaping rules and I can't audit its behavior at a glance. An opaque command mutating my source files, with no diff shown, is not something I can meaningfully approve. 6. It surfaces at the worst moment. The pattern shows up most often right after a rename, or after Edit returns "File has not been read yet" a few times in a row. The model treats the error as an obstacle to route around with a shell command, when the error message is in fact telling it exactly what to do (read the file first). So the shell path gets taken precisely when the model is already confused about file state — the worst possible time to stop showing its work. What I'd like Model behavior: - Default to Edit / MultiEdit / Write for any file mutation. Reach for shell-based editing only when the change is genuinely large and mechanical (hundreds of sites across many files), and say why. - When a shell-based mutation is justified, show the resulting diff in the conversation afterwards. "Done" is not an acceptable report for an invisible change. - Never treat an Edit tool error as a reason to switch to shell. The error usually states the remedy. Product-level fix (this would solve it regardless of model behavior): - When a Bash command modifies files inside the workspace, render a diff for those files in the transcript automatically — the same way Edit already does. The tool layer knows the before/after state; it could simply show it. - Optionally, surface a hint or a confirmation when a shell command is about to write to a tracked source file, similar to how other destructive operations are handled. Why I think this is worth fixing The visible-diff behavior of Edit is one of the things that makes Claude Code reviewable in the first place. Every shell-based mutation is a hole in that guarantee, and the holes are invisible by construction — I only notice when I happen to ask. For a tool whose value proposition is "an assistant you can supervise while it writes production code," changes that can't be seen are changes that can't be supervised.

Environment Info

  • Platform: darwin
  • Terminal: xterm-256color
  • Version: 2.1.226
  • Feedback ID: 0602461a-992c-4ee2-a5c0-88d963d1c822

Errors

[]

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗