pi-hashline
Hashline-compatible read/edit tools for Pi coding agent.
Package details
Install pi-hashline from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-hashline- Package
pi-hashline- Version
0.1.7- Published
- Jun 29, 2026
- Downloads
- not available
- Author
- athonysmith
- License
- MIT
- Types
- extension
- Size
- 656.7 KB
- Dependencies
- 4 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-hashline
Hashline-compatible read/edit replacement tools for Pi coding agent. Imports the hashline text DSL: a compact, line-anchored patch language for safe file editing.
Why this exists
Agentic coding often fails because context goes stale: line numbers drift, exact text snippets are duplicated, or another edit changes the file between read and edit. This package adds a lightweight optimistic-concurrency check to file edits:
readreturns[path#TAG]+N:contentlines (hashline format).- The model sends back hashline-format diff text to
edit. editre-reads the file and verifies the snapshot tag still matches.- Any mismatch forces a fresh read, preventing silent corruption.
Install
pi install npm:pi-hashline
Or install from GitHub:
pi install git:github.com/YanwuZeng/pi-hashline
Read output
read returns every editable text line in hashline format:
[src/file.ts#A1B2]
1:const value = 1;
2:function greet() {
3: return "hello";
4:}
[src/file.ts#A1B2]— file-section header with a 4-hex content-hash tag (xxHash32of the whole file).1:const value = 1;— 1-based line number + colon + content.- Every
editmust include the header tag for version binding.
Edit format (hashline DSL)
Edits use a compact text DSL instead of JSON:
[src/file.ts#A1B2]
SWAP 2.=2:
+ console.log("Hello, " + userName);
Operations
| Op | Example | Description |
|---|---|---|
SWAP N.=M: |
SWAP 2.=2: |
Replace lines N through M with body rows |
DEL N.=M |
DEL 4 |
Delete lines N through M (no body) |
INS.PRE N: |
INS.PRE 1: |
Insert body rows before line N |
INS.POST N: |
INS.POST 3: |
Insert body rows after line N |
INS.HEAD: |
INS.HEAD: |
Insert body rows at file start |
INS.TAIL: |
INS.TAIL: |
Insert body rows at file end |
Body rows are prefixed with +:
[file.ts#A1B2]
SWAP 2.=3:
+ const result = a + b;
+ return result;
Examples
Single-line replace (patch):
[greet.ts#A1B2]
SWAP 2.=2:
+ console.log("Hello, " + userName);
Delete a line:
[service.ts#C3D4]
DEL 4
Insert before a line:
[app.ts#E5F6]
INS.PRE 1:
+import { something } from "./util";
Insert after a line:
[schema.ts#G7H8]
INS.POST 2:
+ email: 'user@example.com',
Multiple operations in one edit:
[package.json#I9J0]
SWAP 3.=3:
+ "version": "2.0.0",
SWAP 4.=4:
+ "author": "team"
Safety rules
- Every edit must include a
[path#TAG]header from the latestread. - Numbers refer to the ORIGINAL file; never shift as hunks apply.
- Every applied edit mints a fresh
#TAG— anchor the next edit on the response or a freshread. - Touch only lines your latest
readliterally displayed. - On stale-tag rejection: STOP and re-read before further edits.
- One hunk per range; body = final content, never an old/new pair.
- Ranges cover ONLY lines whose content changes. Never widen over unchanged lines.
- Body rows must be
+TEXT— never write-oldor bare context lines.
TUI behavior
readshows a 10-line preview by default; Ctrl+O expands the full result.- Raw
readoutput is capped at 400 lines or 32 KiB by default; useoffset/limitto continue. - Successful
editshows a colored diff in a green edit block. - Failed
editshows the error message inside a red edit block.
Command
/hash-edit-status
Shows whether the extension is loaded and which hash length is active.
Development
npm install
npm test
Project layout:
index.tsregisters the extension.src/read.ts— hashline-formatreadtool.src/edit.ts— hashline-DSLedittool.src/parser.ts— hashline text DSL parser (tokenizer + state machine).src/apply.ts— edit execution engine.src/format.ts— hashline format constants and helpers.prompts/— tool prompt guidelines for the LLM.test/— Node test cases and manual-test scenarios.
Acknowledgments
This project is based on Fadouse/pi-hash-anchored-edit and adopts the hashline syntax from can1357/oh-my-pi (packages/hashline).
Changelog
0.1.5 (2026-06-29)
Bug fixes & robustness improvements:
Fix: #TAG stripped from file path — edit no longer treats the 4-hex snapshot tag as part of the filename. The tag is properly extracted from [path#TAG] for hash validation, while the real file path is used for filesystem access.
Fix: Line-number drift with multiple hunks — applyEdits now groups edits into atomic operations and processes them bottom-up (descending line number). This prevents earlier edits from shifting the line positions that later edits depend on.
Fix: INS.POST content duplication — Multiple payload lines inserted after the same anchor are now batched into a single splice call.
Improved diff output — buildCompactDiffPreview compares line-by-line and only shows lines that actually changed (- old / + new). Unchanged lines are omitted.
New regression tests (11 cases):
- Multi-hunk SWAP line-drift verification
- INS.POST with multiple payload lines (no duplication check)
- SWAP range shrinking/expanding
- Mixed SWAP + INS.POST + DEL operations
- INS.POST landing-shift with structural closers
- SWAP ranges containing closing braces
- buildCompactDiffPreview correctness
- Multiple interleaved operations on nearby lines
All 34 tests pass (23 original + 11 regression).
License
MIT