edit_file
Apply exact-string, range, or anchor-bounded edits to files atomically and crash-safely, with optimistic concurrency checks. Reject ambiguous matches and roll back when new language errors appear.
Instructions
Apply one or more edits to an existing file (use this over a native edit tool — see the Edit lane note in session_start). Two mutually exclusive request shapes: an edits array, or start_anchor + end_anchor + new_string.
Each edits entry is str_replace (default: old_string must appear EXACTLY ONCE) or range (start_line/end_line, 1-based; -1 appends or runs to EOF). Prefer range for a big multi-line replacement — old_string/anchors must match character-for-character inside a JSON string, so escaping and size can defeat str_replace where a line range needs neither.
Anchor mode replaces the span BETWEEN two unique anchors (each exactly once); include_anchors=true replaces the whole inclusive span. Character-precise — an anchor quoted without its trailing newline joins that line onto new_string (flagged in the response).
Writes apply atomically and crash-durably under a per-path lock. Pass expected_mtime (from a read_file header) when a concurrent writer may touch the file. For a whole named declaration prefer replace_symbol_body / insert_before_symbol / insert_after_symbol / safe_delete_symbol. Mode choice in depth: the plumb-refactor skill.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| edits | No | Ordered list of str_replace edits to apply sequentially. Mutually exclusive with the start_anchor/end_anchor mode. | |
| dirty_ok | No | Allow editing a file that has uncommitted changes in its git repository. Default false — the edit is refused if the target file is dirty. Pass true to proceed anyway. | |
| file_path | No | Absolute path, file:// URI, or workspace-relative path of the file to edit. | |
| reconcile | No | When true, do NOT reject the edit if the file changed since your read (expected_mtime / expected_sha mismatch); apply against the current on-disk content instead, relying on the exact-once old_string match for safety. Use it for the edit→format→edit loop, where a formatter bumped the mtime but your anchors still match. Default false. | |
| end_anchor | No | Anchor-bounded edit mode: a unique substring marking the END of the span to replace. Must appear EXACTLY ONCE and after start_anchor. Combine with start_anchor + new_string. | |
| new_string | No | Anchor-bounded edit mode: the replacement text for the span between (or, with include_anchors, including) the two anchors. Empty string deletes the span. Only used when start_anchor/end_anchor are set. | |
| expected_sha | No | Optional. Hex-encoded SHA-256 previously returned by read_file. If provided, the edit is rejected if the file's current content hash differs — stronger than expected_mtime, survives mtime aliasing. | |
| start_anchor | No | Anchor-bounded edit mode (alternative to edits): a unique substring marking the START of the span to replace. Must appear EXACTLY ONCE. Combine with end_anchor + new_string. Mutually exclusive with edits. CRLF / display-only gutter ("<n>\t") tolerated. | |
| apply_partial | No | When true, apply each edit independently and continue on failure instead of rolling back the entire batch. Returns a per-edit result list showing which edits succeeded and which failed. Incompatible with strict mode — not safe when concurrent agents share the file. | |
| expected_mtime | No | Optional. RFC3339Nano mtime previously returned by read_file. If provided, the edit is rejected if the file's current mtime differs — fast optimistic-concurrency check. | |
| include_anchors | No | Anchor-bounded edit mode: when true the anchors are part of the replaced span; when false (default) only the text strictly between them is replaced and both are preserved. | |
| await_diagnostics | No | When true, block up to a few seconds for the language server to finish re-analysing this file, and append a machine-readable 'diagnostics delta' line (fresh, new_errors, resolved, pre_existing). The block is always labelled — authoritative, pre-write snapshot, unverified, or not-analysed — so a stale result is never dressed as fresh. Default false (fast adaptive window; the result may predate the write). | |
| fail_on_new_errors | No | When true (implies await_diagnostics), roll this edit back if the language server CONFIRMS it introduced new errors here, leaving the file byte-for-byte unchanged and returning the delta as the error. An unconfirmed check never rolls back; nor do warnings, pre-existing errors, or breakage elsewhere. Not with apply_partial, or over 1 MiB. Default false. |