Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

AgentRead FormatEdit AddressingEdit Mechanism
Codexraw (via shell)Context lines (3 before/after)apply_patch — custom diff
ClineLINE_NUMBER→CONTENTexact old_text match OR insert_lineedit_file + apply_patch
Goose(MCP extension)(extension-dependent)(extension-dependent)
Grok BuildLINE:HASH:CTX→CONTENTAnchor-based (22:abc:rst)Hashline edit (atomic batch)
Grok Build (alt)LINE_NUMBER→CONTENTexact old_string matchsearch_replace
OpenCode/Kilocoderaw with line numbersexact oldString matchedit with replaceAll
Piraw with line numbersexact old_text matchedit tool
Qwen Codecat -n formatexact old_string matchedit

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_string must match exactly once in the file → replaced with new_string
  • old_string = "" or null → create new file
  • Failure mode: ambiguous match (appears 0 or >1 times)
  • Mitigation: replaceAll flag, 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”:

AgentMethod
Codex*** Add File: <path> in patch language
Cline/OpenCode/Qwenold_string = null/empty + new_string = full content
Grok Buildold_string = "" creates file
PiSeparate 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 read before 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

DimensionExact MatchDiff/PatchAnchor
Token efficiencyMedium (repeat old text)High (only context + changes)Low (anchors on every line)
Reliability on repeated codePoorMedium (context helps)Strong
Multi-edit atomicityOne-at-a-timeBatched in one callAtomic batch
Model cognitive burdenLow (just copy text)Medium (learn format)Medium (learn anchor protocol)
Robustness to concurrent editsPoor (line shifts break)Poor (context shifts)Strong (anchors survive shifts)
Failure recoveryRe-read and retryRe-read and retryFresh anchors in error response