Observed
When asked to modify a file the user knows exists on disk, i generates a prose-style shell snippet as if it were being pasted into a bash function, rather than reading the file and producing an executable command that edits the real file in place.
Reproduction
i "update my agi alias in my .zshrc file to allow the flag '--profile <profile-name>' where when present it will set CLAUDE_CONFIG_DIR=\$HOME/.claude-<profile-name> before the claude command that it currently runs. If not present it will not set the CLAUDE_CONFIG_DIR variable and will run the command like it currently does."
What i produced (from [p] preview):
interpreter: zsh
| if [[ "$@" == *"--profile"* ]]; then
| profile_name=$(echo "$@" | grep -oP '(?<=--profile )[^ ]+')
| export CLAUDE_CONFIG_DIR="/Users/coreyrdean/.claude-$profile_name"
| fi
| exec claude $@
This is not an executable edit. It is a prose transliteration of the user's prompt into zsh-ish code. Running it would not touch ~/.zshrc; it would just define those lines in the current shell for the duration of the call. The user's existing agi alias is never read, never parsed, never replaced.
Expected
Given a request of the form "modify file X to do Y":
i should use read_file on the referenced file (~/.zshrc) to discover the current definition of agi.
- Use
which / env_get HOME / os_info as needed to resolve the path and the current alias body.
- Produce an executable command that rewrites the file in place — likely a
sed -i, a small awk script, or a heredoc append — conditioned on the real current state.
- The preview should show a command that will actually modify
~/.zshrc, not a snippet in a quote block.
Where this lives
The natural-language path is cmdIntent in internal/cli/intent.go. It runs eng.Run(...) with the user prompt and the standard tool catalog (internal/tools/tools.go:85-90), which already includes read_file, list_dir, grep, find_files, env_get, cwd. The tools exist; the model is just not using them for file-edit requests.
Probable fix surface:
- The top-level
intent system prompt (whatever is fed to engine.Run from cmdIntent — check internal/engine/engine.go) needs an explicit rule: when the user's request references a file path they say exists (~/.zshrc, ~/.config/..., ./foo.conf), the model MUST read_file it before generating an edit command. Generating a script body without first reading the target is a bug.
- The proposal's risk/runtime slots should probably reflect that an actual in-place file mutation happened, not a no-op script.
- Consider adding an explicit "file edit" mode or approach where the engine refuses to emit a script that mentions a filesystem path without having read that path.
Related
AGENTS.md learned preference: "Every natural-language subcommand (...) must be agentic: run a read-only tool-call loop that discovers binaries on the user's $PATH, lists/reads files, invokes --help/man, uses grep/rg, find/fd, web fetch, and other non-mutating shell calls to gather context iteratively until ready — never describe what would need to be checked instead of checking it." This issue is a direct violation of that rule for file-edit requests.
Acceptance
A command shaped like "modify file X to do Y" with X pointing at a real file should, in the preview pane, show a command whose execution would actually change X on disk, grounded in X's current contents. The model should have called read_file (observable in -v output) before producing that command.
Observed
When asked to modify a file the user knows exists on disk,
igenerates a prose-style shell snippet as if it were being pasted into a bash function, rather than reading the file and producing an executable command that edits the real file in place.Reproduction
What
iproduced (from[p] preview):This is not an executable edit. It is a prose transliteration of the user's prompt into zsh-ish code. Running it would not touch
~/.zshrc; it would just define those lines in the current shell for the duration of the call. The user's existingagialias is never read, never parsed, never replaced.Expected
Given a request of the form "modify file X to do Y":
ishould useread_fileon the referenced file (~/.zshrc) to discover the current definition ofagi.which/env_get HOME/os_infoas needed to resolve the path and the current alias body.sed -i, a smallawkscript, or a heredoc append — conditioned on the real current state.~/.zshrc, not a snippet in a quote block.Where this lives
The natural-language path is
cmdIntentininternal/cli/intent.go. It runseng.Run(...)with the user prompt and the standard tool catalog (internal/tools/tools.go:85-90), which already includesread_file,list_dir,grep,find_files,env_get,cwd. The tools exist; the model is just not using them for file-edit requests.Probable fix surface:
intentsystem prompt (whatever is fed toengine.RunfromcmdIntent— checkinternal/engine/engine.go) needs an explicit rule: when the user's request references a file path they say exists (~/.zshrc,~/.config/...,./foo.conf), the model MUSTread_fileit before generating an edit command. Generating a script body without first reading the target is a bug.Related
AGENTS.mdlearned preference: "Every natural-language subcommand (...) must be agentic: run a read-only tool-call loop that discovers binaries on the user's $PATH, lists/reads files, invokes --help/man, uses grep/rg, find/fd, web fetch, and other non-mutating shell calls to gather context iteratively until ready — never describe what would need to be checked instead of checking it." This issue is a direct violation of that rule for file-edit requests.Acceptance
A command shaped like "modify file X to do Y" with
Xpointing at a real file should, in the preview pane, show a command whose execution would actually changeXon disk, grounded inX's current contents. The model should have calledread_file(observable in-voutput) before producing that command.