name: edit-file description: Modify an existing file by replacing a unique substring with the edit_file tool. Cheaper and safer than rewriting the whole file with write_file when you only need to change a few lines.
edit-file
edit_file swaps an exact substring inside an existing file. Always
prefer it over write_file when modifying an existing file — you
emit just the diff instead of re-typing the whole file, which is
cheaper in tokens and impossible to corrupt with stray whitespace
changes elsewhere.
Schema
{
"path": "string, non-empty",
"old_string": "string, non-empty",
"new_string": "string",
"replace_all": "boolean (default false)"
}
path(required). Path to an existing regular file. Symlinks are followed; the target must also be a regular file.old_string(required). Literal substring to replace. Must appear exactly once in the file unlessreplace_allis true — the uniqueness check is what makes the tool safe.new_string(required). Replacement substring. Must differ fromold_string(no-op edits are rejected).replace_all(optional, defaultfalse). Replace every occurrence. Use for renames / refactors where you do want to hit every site.
Result shape
{
"path": "/data/workspace/main.rs",
"replacements": 1,
"bytes_written": 1842
}
Diff card surfaced to the user
After every successful edit_file write the host emits a structured
diff card to the originating channel — same path, same +/-
gutters every code review tool uses. You don't need to summarise the
change in prose; the user already sees it. Save your tokens for
explaining why, not what.
How to use it
read_filefirst. Pull the file (or the relevant region viashellwithgrep -n/sed -n) so you can see the exact byte sequence you want to swap.- Include enough surrounding context to disambiguate. If the
line you want to change appears elsewhere in the file, expand
old_stringto include the function header, a unique comment, or the line before / after — whatever it takes to make the match unique. The tool will reject ambiguous matches with a message telling you how many times it saw your string, so the "include more context" iteration is short. - For renames, use
replace_all: true. Renaming a symbol, shifting a path, bumping a version string — anything where you genuinely want every occurrence rewritten. - For brand-new files, use
write_fileinstead.edit_filerefuses to create files (that'swrite_file's job).
Errors you should expect
not found—old_stringdoesn't match anywhere. Re-read_filethe relevant region and copy the exact bytes.matches N times— ambiguous. Add surrounding context until the match is unique, or setreplace_allif you wanted them all.must differ—old_stringandnew_stringwere the same. Probably a paste error.not a regular file— path is a directory or a symlink to a non-file (e.g. a socket).not foundat the path level — file doesn't exist. Usewrite_fileto create it.
Atomicity guarantees
The write goes through a sibling temp file in the same directory,
fsyncs, then rename(2). A crash mid-write leaves the original
untouched. The file's mode (permissions) survives the swap; owner
does not necessarily (chown needs caps the container doesn't have).
When to prefer other tools
- Creating a new file:
write_file. - Appending without changing existing content:
write_filewithappend: true. - Multi-line in-place edit driven by a regex:
shellwithsed -i -E '...'.edit_fileis literal-string-only by design. - Bulk find-and-replace across many files: loop
edit_filecalls, one per file. The tool is one-file-per-call.