Oh My Pi: Hashline Editing In A General-Purpose Agent
Oh My Pi is one of the few repos here that treats file editing as a first-class research problem. Its answer is hashline: a default edit mode where the model targets anchored lines instead of reproducing big chunks of source text, while the runtime validates, previews, rebases, and batches those edits in a more structured way than plain search-and-replace.
Why It Matters
A lot of coding agents improve edits by piling on more fuzzy matching. Oh My Pi goes in a different direction. It changes the address space. The model does not primarily say "replace this literal block." It points at anchored lines that were already shown by the read tool.
That changes both cost and failure behavior. The model spends fewer tokens repeating code, and the runtime can distinguish between stale anchors, malformed edit syntax, and true semantic mistakes instead of collapsing everything into "search string not found."
The Anchor Format
In packages/coding-agent/src/edit/line-hash.ts, each
visible source line is rendered as LINE+HASH|TEXT. The
hash is only two letters long, but it is chosen from a stable set of
647 single-token BPE bigrams so the anchor stays compact in model
context.
The details are more careful than they first look. Lines with real alphanumeric content hash independently of the line number so the same content can survive small shifts. Punctuation-only lines can mix in the line number to avoid a sea of identical anchors.
export function computeLineHash(idx: number, line: string): string {
line = line.replace(/\r/g, "").trimEnd();
if (line.replace(/[\s{}]/g, "").length === 0) {
return structuralBigram(idx);
}
const seed = /[\p{L}\p{N}]/u.test(line) ? 0 : idx;
return HL_BIGRAMS[Bun.hash.xxHash32(line, seed) % HL_BIGRAMS_COUNT];
}
Not just hashes
Oh My Pi anchors are line number plus hash. Dirac pushes further toward pure hash-addressed editing. Oh My Pi keeps one foot in the line-oriented world while making drift harder to miss.
Hashline Is The Default, Not An Experiment
This is not a side tool hidden behind a flag. In
src/utils/edit-mode.ts, the default edit mode is
hashline. In the settings schema,
readHashLines is enabled by default, which means the
normal read path already formats file output for hashline edits.
| Setting | Default | Consequence |
|---|---|---|
edit.mode |
hashline |
The main edit tool speaks anchors by default |
readHashLines |
true |
Read output is already shaped for anchor reuse |
edit.hashlineAutoDropPureInsertDuplicates |
false |
Duplicate-boundary cleanup exists, but it stays explicit and configurable |
How A Hashline Edit Executes
The execution path in src/edit/modes/hashline.ts is where
the design becomes interesting. Multi-section edits are split by
@PATH, same-path sections are merged so earlier sub-edits
do not invalidate later anchors, and multi-file batches are validated
before any partial mutation lands.
The runtime then applies edits against normalized file content, restores the original line endings and BOM, emits a compact diff preview, and can auto-rebase a stale anchor within a small search window when the same hash uniquely appears nearby.
if (sections.length === 1) return executeHashlineSection(...);
for (const section of sections) await preflightHashlineSection(...);
for (const section of sections) {
results.push({ path: section.path, result: await executeHashlineSection(...) });
}
Preflight first
Multi-file edits are validated before mutation so one bad section does not leave the repo half-applied.
Limited rebase
The code allows a small nearby rebase window instead of falling all the way back to fuzzy substring matching.
Compare It To The Rest
| Repo | Main edit idea | Where it gets reliability |
|---|---|---|
| Dirac | Hash-anchored edits as the primary worldview | Stable anchors and batch application discipline |
| Oh My Pi | Line-plus-hash anchors inside a multi-mode edit tool | Compact anchors, preflight validation, nearby rebasing, and benchmark-driven prompt/runtime iteration |
| OpenCode | Exact edits plus a large fallback stack | Nine matching layers and alternative edit surfaces |
| Cline | Search/replace with layered forgiveness | Whitespace and formatting fallbacks |
| Pi Mono | Exact replacement with guardrails | Unique matching, multi-edit batching, and file queues |
The key distinction is this: Dirac feels like a deliberate alternative
to line-number editing itself. Oh My Pi feels like a broad agent that
decided its default edit dialect should be anchor-first, while still
keeping replace, patch, vim,
and apply_patch as other edit modes.
Why The Repo Is Worth Studying
The editing story is stronger because the repo supports it everywhere
else. There are prompt helpers that compute real anchors, settings and
previews shaped around hashline, a dedicated
typescript-edit-benchmark package, and benchmark scripts
specifically for the hashline variant. That is a much more serious
loop than dropping a new edit syntax into a prompt and hoping it wins.
In other words, Oh My Pi is not interesting because hashes are cool. It is interesting because the team keeps tuning the whole surrounding system until the hashes actually help.
What I Would Steal From It
Change the address space
If exact replace keeps failing, the answer might be better references, not just more tolerant matching.
Keep rebasing narrow
Nearby rebase hints are useful. Giant fallback ladders often turn into silent guesswork.
Benchmark edit formats
Oh My Pi treats separator choice, preview behavior, and edit-mode syntax as measurable engineering questions.
Unify prompts and runtime
Prompt helpers, read formatting, and edit validation all speak the same anchor language.