File Editing
How agents read, modify, and create files — the core of what makes a coding agent.
The Read→Edit Coupling
Every agent couples its read format to its edit format. What the model sees when reading determines how it must specify edits:
| Agent | Read Format | Edit Addressing | Edit Mechanism |
|---|---|---|---|
| Codex | raw (via shell) | Context lines (3 before/after) | apply_patch — custom diff |
| Cline | LINE_NUMBER→CONTENT | exact old_text match OR insert_line | edit_file + apply_patch |
| Goose | (MCP extension) | (extension-dependent) | (extension-dependent) |
| Grok Build | LINE:HASH:CTX→CONTENT | Anchor-based (22:abc:rst) | Hashline edit (atomic batch) |
| Grok Build (alt) | LINE_NUMBER→CONTENT | exact old_string match | search_replace |
| OpenCode/Kilocode | raw with line numbers | exact oldString match | edit with replaceAll |
| Pi | raw with line numbers | exact old_text match | edit tool |
| Qwen Code | cat -n format | exact old_string match | edit |
Three Families of Edit Strategy
1. Exact String Match (most common)
Used by: Cline, OpenCode, Kilocode, Qwen Code, Pi, Grok Build (search_replace)
edit(path, old_string, new_string)
old_stringmust match exactly once in the file → replaced withnew_stringold_string = ""ornull→ create new file- Failure mode: ambiguous match (appears 0 or >1 times)
- Mitigation:
replaceAllflag, or “add surrounding lines to make unique” - Advantage: simple model burden — just copy the text to change
- Disadvantage: fails silently on repeated patterns (e.g., multiple
return null;)
2. Diff/Patch Language
Used by: Codex, Cline (apply_patch)
*** Begin Patch
*** Update File: src/app.py
@@ def greet():
-print("Hi")
+print("Hello, world!")
*** End Patch
- Custom mini-language with
*** Begin Patch,@@ context,+/-lines - Addresses via context (like git diff) not exact match
- Can express multi-hunk, multi-file changes in a single tool call
- Failure mode: context doesn’t match current file state
- Advantage: batch efficiency, familiar to models trained on diffs
- Disadvantage: custom parser needed, ambiguous context possible
3. Anchor-Based (Grok Build hashline)
Read output: 22:abc:rst→ const x = 1;
Edit input: anchor="22:abc:rst", new_content=" const x = 2;"
- Each line gets a content-derived hash anchor
- Three schemes: ContentOnly (hash of line), ChunkFingerprint (hash + chunk context), CheckpointChain (hash + checkpoint chain)
- Atomic batch semantics: if any anchor is stale, ALL edits in batch rejected
- Stale anchor → error includes fresh anchors → model retries immediately
- Advantage: robust to concurrent edits, line insertions/deletions above don’t break refs
- Disadvantage: anchor churn after edits, more token overhead in read output, complex protocol
File Creation
Every agent handles “create new file” separately from “edit existing”:
| Agent | Method |
|---|---|
| Codex | *** Add File: <path> in patch language |
| Cline/OpenCode/Qwen | old_string = null/empty + new_string = full content |
| Grok Build | old_string = "" creates file |
| Pi | Separate write tool for full-file creation |
Read-Before-Write Enforcement
Most agents require or encourage reading before editing:
- OpenCode/Kilocode: Edit tool errors if the file hasn’t been read first in the conversation
- Grok Build: Prompt says “Read the file with
readbefore editing it” - Qwen Code: Same enforcement as OpenCode
- Codex: No enforcement — patch can be applied blind (context matching validates)
- Pi: No enforcement but prompted to “validate at the end”
Architectural Tradeoffs
| Dimension | Exact Match | Diff/Patch | Anchor |
|---|---|---|---|
| Token efficiency | Medium (repeat old text) | High (only context + changes) | Low (anchors on every line) |
| Reliability on repeated code | Poor | Medium (context helps) | Strong |
| Multi-edit atomicity | One-at-a-time | Batched in one call | Atomic batch |
| Model cognitive burden | Low (just copy text) | Medium (learn format) | Medium (learn anchor protocol) |
| Robustness to concurrent edits | Poor (line shifts break) | Poor (context shifts) | Strong (anchors survive shifts) |
| Failure recovery | Re-read and retry | Re-read and retry | Fresh anchors in error response |