edit_file
Apply precise edits to existing files with exact-match validation and atomic, crash-durable writes, supporting string replacements, line ranges, and anchor-bounded rewrites.
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 request shapes (mutually exclusive): pass an edits array, OR start_anchor + end_anchor + new_string. In the edits array, each edit is one of two modes: (1) str_replace (default): old_string must appear EXACTLY ONCE — rejected if absent or ambiguous. (2) range: start_line/end_line (1-based) replace that line span with new_string; start_line: -1 appends at end of file, end_line: -1 runs through the last line (the clean way to delete a block or append, no anchor needed). Anchor mode replaces the span BETWEEN two unique anchors with new_string — each anchor must match EXACTLY ONCE and end_anchor must follow start_anchor; include_anchors=false (default) keeps the anchors and rewrites only the text between them, include_anchors=true replaces the whole inclusive span. Ideal for rewriting a block whose interior changes but whose stable boundary lines do not. CRLF is tolerated; edits apply sequentially in memory then write atomically and crash-durably (temp file fsynced + rename + parent-dir fsync) under a per-path lock. Pass expected_mtime (from a read_file header) to guarantee the file is unchanged since you read it. For a SOLE agent doing a burst of sequential edits to one file, OMITTING expected_mtime is the blessed fast path: the EXACTLY-ONCE old_string match is itself the safety check, so you need not thread the fresh mtime each edit returns through the next one (reach for expected_mtime/expected_sha only when a concurrent writer may touch the file). If the call fails with a transport/connection error, the atomic temp+rename guarantees the file is either fully updated or untouched — never partially written; re-read to see which. Replacing, inserting around, or deleting an entire named declaration? Prefer replace_symbol_body / insert_before_symbol / insert_after_symbol / safe_delete_symbol — addressed by name_path, no coordinates to compute.
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(gofumpt/golangci-lint --fix)→edit loop, where a formatter bumped the mtime but your anchors still match. Default false (the mtime guard stays strict). | |
| 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 themselves are part of the replaced span (the whole inclusive span becomes new_string); when false (default) only the text strictly between the anchors is replaced and the anchors are preserved as boundaries. | |
| await_diagnostics | No | When true, block up to a few seconds for the language server to finish re-analysing this file and report an authoritative post-write result — a clean fresh pass is stated explicitly. Use it for a trustworthy "did my change compile?" answer instead of shelling out to a build. Default false (fast adaptive window; the result may predate the write). |