npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-better-edit

v2.5.0

Published

Hash-anchored read/edit/undo tools for pi-coding-agent. Every line gets a unique 3-char hash (A-Za-z0-9) that stays stable across edits; stale or ambiguous anchors are rejected, never fuzzy-matched. Undo persists across restarts.

Readme


What is pi-better-edit? A high-precision file editing extension for pi-coding-agent that replaces volatile line numbers and token-wasting code echoes with immutable, content-addressed 3-character line hashes (szJ│code).

Core Philosophy: Local compute is free; the model's context window is the most precious resource. By shifting verification, snapshotting, and alignment to the host, pi-better-edit slashes output tokens by 40–60%, auto-rebases external file drift (e.g., Prettier, Git), and eliminates silent miswrites without forcing full-file re-reads.


Why You Need It

The 3 Fatal Editing Traps of Autonomous Coding Agents

File editing is the #1 point of failure for autonomous agents. Traditional tools break down in three distinct ways:

| Fatal Trap in Traditional Tools | Why It Breaks Agents | How pi-better-edit Solves It | | --- | --- | --- | | str_replace Token Bleed | Must re-type 30+ lines of unchanged code just to change 1 line ($O(S+R)$), burning expensive output tokens (billed ~5–6× input). | $O(R)$ Payloads: Sends only two 3-char hashes (anchor_from, anchor_to) + replacement. Cuts output tokens by 40–60%. | | Line-Number Coordinate Rot | Inserting 1 line shifts all line numbers below it. Agents suffer off-by-one errors or must repeatedly re-read the file. | Position-Independent Anchors: Line hashes follow content, not line coordinates. Exterior shifts auto-rebase cleanly. | | Silent Miswrites & Drift | Duplicate lines match the wrong function; external formatters (Prettier) or git updates cause blind overwrites or fatal errors. | Line-Identity MVCC: Unique anchors via coprime probing; format-tolerant whitespace hashing; fail-closed reject-and-serve. |


Core Pillars

1. 🪙 Token Economics (40–60% Context Savings)

  • $O(R)$ Edit Payloads: The model emits only { "anchor_from": "a1b", "anchor_to": "c3d", "replace_with": "..." }, never regurgitating existing code.
  • Self-Serving Diffs: Every applied edit returns fresh anchors in the post-edit diff — zero re-read roundtrips to chain edits.
  • Disjoint Multi-Window Reads: Query up to 16 disjoint slices (windows: [{offset, limit}, ...]) in one turn instead of dumping 2,000 lines into context.
  • Zero-Token Auto-Rebase: Non-conflicting shifts resolve locally via $O(m \log m)$ Patience LIS alignment — 0 tokens, 0 retries.
  • Atomic Multi-Item Batches: Apply up to 32 same-file edits in one tool call; overlapping spans abort atomically before touching disk.

2. 🛡️ Resistance to External Writes (Drift & Concurrency)

  • Auto-Formatter Immunity: Strips ASCII whitespace before hashing. Prettier, Black, and ESLint format-on-save passes never rotate anchors.
  • Exterior Shift Auto-Rebase: External edits, git checkouts, or background processes outside the edit span rebase seamlessly without agent intervention.
  • Fail-Closed Reject-and-Serve: Contested interior spans fail closed without disk corruption and immediately return fresh on-disk rows in the error ([E_STALE_RANGE], [E_UNVERIFIED_RANGE]) — recovering in exactly 1 turn.
  • Session-Keyed Leases: Leases are isolated per session (served_leases), preventing cross-agent race conditions or state pollution.

3. 🎯 Zero Silent Miswrites (Formal MVCC)

  • Decoupled Line Identity: Every line is tracked by an immutable, monotonic line_id in CAS snapshot storage, not ephemeral coordinates.
  • Collision-Free Anchors: Coprime bitset probing ensures duplicate lines in a file receive distinct, unambiguous 3-character hashes.
  • No Heuristic Guessing (ADR-0016): Retires fuzzy matching. If an anchor cannot be unambiguously resolved via lease lineage, it fails closed safely.
  • Persisted Undo: undo_last_edit restores exact file content, BOM, line endings, and original anchors, persisting across session restarts.

Quick Start

Installation

# From npm
pi install npm:pi-better-edit

# From GitHub
pi install git:github.com/Rianico/pi-better-edit

# From local directory
pi install /path/to/pi-better-edit

Zero configuration required. pi automatically activates the extension on start.

| Runtime Requirement | Supported Version | | --- | --- | | Node.js | ≥ 22.19.0 | | pi-coding-agent | ≥ 0.75.0 (peer dependency) |

How It Works

1. Read the file

read returns each line prefixed by a stable 3-character hash anchor:

ve7│function hello() {
szJ│  console.log("world");
kQm│}

2. Apply an edit

edit targets inclusive anchor bounds using the canonical named-object payload:

{
  "file": "src/main.ts",
  "edits": [
    {
      "anchor_from": "szJ",
      "anchor_to": "szJ",
      "replace_with": "  console.log('hi');\n"
    }
  ]
}

3. Receive the diff with fresh anchors

The tool applies the edit and returns a unified diff showing fresh anchors for subsequent edits—eliminating the need for follow-up read calls:

- szJ │   console.log("world");
+ a3m │   console.log('hi');
  kQm │ }

4. Batch multiple edits atomically

Batch up to 32 edits to the same file in a single transaction. If any edit fails or overlaps, none write:

{
  "file": "src/main.ts",
  "edits": [
    { "anchor_from": "a1b", "anchor_to": "a1b", "replace_with": "// Header comment\n" },
    { "anchor_from": "c3d", "anchor_to": "c3d", "replace_with": "  return true;\n" }
  ]
}

Systematic Architecture

pi-better-edit v2 replaces ad-hoc string matching and heuristic healing with a formal Multi-Version Concurrency Control (MVCC) architecture.

┌──────────────────────────────────────────────────────────────────────────────────┐
│                                STORAGE TIER                                      │
│  src/hash-store.ts & src/snapshot-store/                                         │
│  - file_snapshots: CAS snapshots (snapshot_id, path, snapshot_hash, line_count)  │
│  - line_lineage: Coordinate authority (snapshot_id, line_number) -> (line_id)    │
│  - line_id_counters: Monotonic integer block allocator per path                  │
│  - served_leases: Session-keyed immutable leases (session_id, path, anchor)      │
│  - file_undo: Snapshot-pinned undo history surviving restarts                    │
└────────────────────────────────────────┬─────────────────────────────────────────┘
                                         │
┌────────────────────────────────────────▼─────────────────────────────────────────┐
│                                SESSION TIER                                      │
│  src/served-session/session.ts                                                   │
│  - Leases: Granted on read, diff, rejection fresh-reads, and undo                │
│  - Immutability: Leases are strictly READ-ONLY during edit resolution            │
│  - Re-Serve Upsert: Atomic upsert updates leases when presentation changes       │
└────────────────────────────────────────┬─────────────────────────────────────────┘
                                         │
┌────────────────────────────────────────▼─────────────────────────────────────────┐
│                       RESOLUTION & REBASE TIER                                   │
│  src/hashline/lease-resolve.ts & src/hashline/served-verification.ts             │
│  - On-Demand CAS Materialization: Materializes current disk state                │
│  - Patience LIS Pin Backbone: O(m log m) non-crossing line alignment             │
│  - Minimal Displacement Tie-Breaking: Deterministic unique pairing               │
│  - Span Contiguity Gate: Asserts interior span is not torn                       │
└────────────────────────────────────────┬─────────────────────────────────────────┘
                                         │
┌────────────────────────────────────────▼─────────────────────────────────────────┐
│                                MUTATION TIER                                     │
│  src/mutation-engine/pipeline.ts & src/hashline/apply.ts                         │
│  - Working Buffer: Preceding delta rebase for multi-item batches                 │
│  - WAL Lineage Commit: Atomically commits final snapshot and updates leases      │
│  - Fail-Closed Intercepts: Rejections emit fresh read ranges                     │
└──────────────────────────────────────────────────────────────────────────────────┘

1. Immutable Line Identity & Leases

  • Every line has an immutable surrogate key (line_id) allocated from a monotonic counter (line_id_counters).
  • When lines are delivered to an agent via read, diffs, or fresh-read rejections, a session-scoped lease (served_leases) binds (session_id, file_path, anchor) -> line_id.
  • During an edit, lease lookups are strictly read-only. An edit cannot re-stamp or guess a lease.

2. Multi-Version Snapshot Lineage

  • Content-addressed CAS snapshots (file_snapshots) track each materialized file version.
  • line_lineage maps each line coordinate to its immutable line_id, 32-bit canon hash, and verbatim presentation anchor.
  • When disk content shifts externally, the tool pairs the latest snapshot ($S_{latest}$) with disk using Patience LIS alignment, preserving identities for surviving lines and allocating fresh IDs only for novel lines.

3. Patience LIS Pin Backbone ($O(m \log m)$)

  • Uniquely matching anchor pins form candidate pairs.
  • The engine computes the Longest Increasing Subsequence (LIS) via patience sorting in $O(m \log m)$ time.
  • Multiple maximal LIS candidates are disambiguated by minimal total displacement ($\sum |p_i - c_i|$).
  • Contested symmetric swaps (e.g. equal-length function swaps) or ambiguous duplicate blocks fail closed, marking affected lines as retired rather than guessing.

4. Working Buffer with Preceding Deltas

  • Multi-item batches (edits: [e_0, e_1, ...]) resolve their baseline coordinates $s'_k$ in the current snapshot.
  • Active in-memory buffer positions are computed by accounting strictly for preceding edits: $$\Delta_k = \sum_{j < k, s'{end, j} < s'{start, k}} \left( |R_j| - (s'{end, j} - s'{start, j} + 1) \right)$$
  • If any two edit items overlap or nest, the batch aborts atomically ([E_BATCH_ABORT]) before modifying disk.

5. Unified Span Verification (ADR-0023)

  • resolveLeasedEdit verifies the entire span against line_lineage before touching disk.
  • Canon evidence is file-scoped and verified via 32-bit digests (canon_hash), eliminating duplicate plaintext storage.

Tools

| Tool | Parameters | Description | | --- | --- | --- | | read | file, offset (1-based), limit, windows (optional) | Returns file content formatted as HASH│content. Lines >200KB are replaced with a marker hint. windows: [{offset, limit}, …] reads up to 16 disjoint ranges in one turn: each renders under === Lines A-B of N === and every shown line is leased, so anchors from all of them work in one edit. | | read_skill | file | Reads file content as plain text without hash prefixes or lease recording (ideal for prompts, docs, and skills). | | edit | file, edits, mode (optional) | Applies single or batched edits atomically. Each edit targets anchor_from and anchor_to inclusive. mode: "literal" declares verbatim text. | | undo_last_edit | file | Restores the previous file state, BOM, line endings, and original anchors. Persists across restarts. |

Payload Contract

{
  "file": "src/example.ts",
  "edits": [
    {
      "anchor_from": "a1b",
      "anchor_to": "c3d",
      "replace_with": "const status = 'ready';\n"
    }
  ],
  "mode": "general"
}
  • file: Path to the target text file (must be a file, never a directory).
  • edits: Array of 1 to 32 edit items. An empty replace_with string deletes the targeted range.
  • mode: "general" (default) refuses text containing served anchor prefixes; "literal" allows verbatim insertion of lines beginning with HASH│.

Interoperability with pi-lens

pi-better-edit composes with pi-lens diagnostics, formatting, and its read-before-edit guard:

  • Read expansion: pi-lens widens a partial read (limit <= 100) to the enclosing symbol or markdown heading section (cap 300 lines, 200 ms budget, disabled by --no-lsp); a read without limit is never widened. Anchors always describe the rows actually served, so failure triage counts served rows rather than the requested window. To keep the requested window, pass limit > 100, read the whole file, or start pi with --no-lsp.
  • Format and autofix: pi-lens' deferred agent_end format and autofix passes rewrite files outside the model's turn. A whitespace-only rewrite is absorbed by the whitespace-insensitive canon (ADR-0005), so anchors survive; a real fix rotates the affected anchors, and the next edit fails closed with [E_STALE_RANGE] or [E_TARGET_LOST] and serves the current rows.
  • Guard compatibility: every served row (reads, multi-window reads, reject-and-serve payloads, post-edit diffs) is reported to pi-lens through its read bridge, so retries and chained edits satisfy the read-before-edit guard without manual re-reads.
  • Overlapping reports are merged by pi-lens and are expected, not a bug.
  • Opt-in: /pi-better-edit lens (auto by default when pi-lens is detected, else off; override via PI_BETTER_EDIT_LENS_BRIDGE=auto|on|off). Core editing never depends on pi-lens — with the bridge off or absent, behavior is unchanged.

Error and Warning Contract

pi-better-edit enforces a strict, machine-actionable diagnostic contract (ADR-0021):

  • [E_*] indicates an edit rejection — nothing was written to disk.
  • [W_*] indicates an applied mutation with an informational warning.
  • Range-family rejections carry structured details.cause values (retirement, never-served, served-range staleness) — never-served on a leased span means a boundary row, because an unread interior between two leased boundaries is accepted (ADR-0024).

Domain Rejections ([E_*])

| Error Code | Description | Remedy / Agent Action | | --- | --- | --- | | [E_BAD_PAYLOAD] | Payload fails schema validation (missing fields, wrong types). | Correct payload structure to match { file, edits } schema. | | [E_MALFORMED_ANCHOR] | Anchor is not a bare 3-char string (e.g. includes │ or diff prefixes). | Pass bare 3-char anchor (e.g. "szJ") and retry. | | [E_STALE_ANCHOR] | Anchor no longer resolves to its leased identity in the file. | Retry using the fresh rows provided in the rejection. | | [E_UNKNOWN_ANCHOR] | Anchor has no active lease in any file for this session. | Re-read the file to establish fresh anchor leases. | | [E_FOREIGN_ANCHOR] | Anchor is leased for a different file than the targeted one. | Ensure anchors match the target file path. | | [E_STALE_RANGE] | A line in the edit range changed on disk, or a boundary line was never served (an unread interior between leased boundaries applies, ADR-0024). | Current range served as a fresh read; decide next edit from fresh rows. | | [E_UNVERIFIED_RANGE] | One boundary lease retired while surviving bound is live and unshifted. | Named window served as fresh read; decide next edit from fresh rows. | | [E_TARGET_LOST] | Target line identity deleted or reordered without a stable anchor bound. | Range cannot be served; re-read file and re-target. | | [E_SUSPICIOUS_TEXT] | Replacement text contains a line matching a served HASH│ anchor. | Strip copied tool output anchors or pass mode: "literal". | | [E_BATCH_ABORT] | Two or more items in the batch target overlapping or nested spans. | Merge overlapping spans into a single item or split into separate calls. | | [E_NOOP_LOOP] | Identical edit producing no changes submitted 3 consecutive times. | Inspect current range; range already contains target content. | | [E_EMPTY_RANGE] | Edit would result in an empty non-empty file. | Use write to truncate or delete file contents. | | [E_NOT_FOUND] | Target file does not exist on disk. | Verify path using ls and retry with corrected path. | | [E_ACCESS] | Target file is unreadable, unwritable, or in a symlink loop. | Correct permissions or resolve symlink loop. | | [E_UNSUPPORTED_FILE] | Target path is a directory, binary file, image, or UTF-16/32 text. | Hashline editing only targets UTF-8 text files. | | [E_UNDO_STALE] | Target file was modified or deleted after the last edit. | Undo refused to prevent data loss; re-read file. | | [E_UNDO_UNAVAILABLE] | Undo state could not be persisted to SQLite store. | Edit was refused and file unchanged; retry edit. | | [E_LARGE_FILE] | File exceeds the 238,328-line ceiling of 3-char base62 space. | Use write or non-hashline tools for very large files. | | [E_UNKNOWN] | Unexpected filesystem or invariant failure. | Check error message details. |

Applied Warnings ([W_*])

| Warning Code | Audience | Description | | --- | --- | --- | | [W_NEVER_SERVED_SHAPE] | [MODEL] | Replacement line starts with an anchor-shaped token never served. Applied verbatim. | | [W_SERVED_PREFIX_MISMATCH] | [MODEL] | Replacement line starts with a served anchor but content differs. Applied verbatim. | | [W_REVERSED_ANCHORS] | [USER] | anchor_from and anchor_to were provided in reverse order. Swapped and applied cleanly. | | [W_UNICODE_LITERAL] | [USER] | Literal \uDDDD sequence detected in replacement. Applied verbatim. | | [W_LITERAL_BYPASS] | [USER] | Served hash echo check bypassed via explicit mode: "literal". | | [W_NOOP] | [USER] | Edit produced no file changes; warning emitted on 2nd occurrence. |


Comparison

Capability Comparison

| Feature | pi-better-edit v2 | @oh-my-pi/hashline | Traditional str_replace | | --- | --- | --- | --- | | Addressing Model | 3-char content-addressed anchors | File tag + line numbers | Verbatim code strings | | Line Identity | Immutable MVCC line_id | Coordinate line numbers | None (text matching) | | Exterior Shift Tolerance | Auto-rebases (0 tokens, 0 retries) | Model must recalculate line numbers | Fails if surrounding context shifts | | Duplicate Line Safety | Collision-resolved unique anchors | Ambiguous position-based indexing | Prone to matching wrong instance | | Concurrent Disk Drift | Fail-closed reject-and-serve | Tag mismatch / best-effort 3-way merge | Silent overwrite or blind failure | | Batch Support | Atomic up to 32 items with delta shifts | Multi-section patch preflight | Sequential individual calls | | Undo Persistence | Survives restarts (CAS snapshot pinned) | None | None | | Session Isolation | Session-keyed leases (served_leases) | None | N/A | | Deterministic Battery | 27/27 pass rate | 10/10 library seam | N/A |

Edge Case Behavior

| Edge Case Scenario | pi-better-edit v2 | @oh-my-pi/hashline | | --- | --- | --- | | Wrong Coordinate / Off-by-one | Impossible: Anchors bind to line_id; verified against lineage before writing. | Possible: Wrong line number against a valid tag silently mutates the wrong code. | | Lines Inserted Above Target | Auto-rebases cleanly: Identity is decoupled from coordinates. | Every edit renumbers: Agent must track offsets. | | Deleted Function Guard Target (Probe E) | Fail-closed intercept: Rejects edit; zero code corruption. | Tag mismatch / merge hazard. | | Equal-Length Symmetric Function Swap (Probe K)| Fail-closed intercept: Contested reorder retires safely. | Applies to wrong block or requires manual recovery. | | Batch Items Overlap | Atomic abort ([E_BATCH_ABORT]); nothing written. | Preflight validation failure. |


Reproducible Benchmarks

All claims are backed by deterministic verification batteries and reproducible benchmarks.

1. Deterministic Tool Battery (27 Scenarios)

The tool battery executes 27 complex edge-case scenarios (concurrent exterior inserts, duplicate function blocks, interior modifications, symmetric reorders, foreign-anchor isolation, BOM preservation, and batch interactions) without LLM sampling:

| Test Suite | Result | Silent Data Loss | | --- | :---: | :---: | | pi-better-edit v2 | 27/27 | 0 |

Reproduce locally:

pnpm run eval

2. Practical Coding-Agent Benchmark

Measures a realistic refactoring workflow in pi with model thinking enabled (opencode-go/gpt-5.6-luna), testing recovery from external drift:

| Editing Tool | Tool Calls | Total Tokens | Token Savings vs Baseline | Correctness | | --- | :---: | :---: | :---: | :---: | | OMP Patch Wrapper | 6 | 28,467 | Baseline | ✅ | | pi-better-edit v2 | 3 (fewest) | 12,593 | -55.8% | ✅ |

Reproduce locally:

pnpm run benchmark:practical

3. Theoretical Envelope Savings

Measures raw payload serialization overhead across a pinned 12-edit corpus:

  • Single edit: -40.0% token overhead vs str_replace.
  • Multi-item batch: -42.7% token overhead vs str_replace.

Reproduce locally:

pnpm run benchmark:tokens

4. Independent Benchmark: Explicit Edit Benchmark

Explicit Edit Benchmark is an independent, community-run dataset that scores harnesses and Pi editing extensions on the same 226 byte-exact edit tasks (replacements, insertions, deletions, moves, copies, unicode, large files). It is maintained by alexshpunt, not by this project, and every observation ships with its configuration.

| Published pi-better-edit arm | Value | | --- | --- | | Quality score | 95.9% | | First-attempt exact | 94.7% | | Exact after recovery | 99.6% | | Coverage | 226 tasks · Pi 0.85.1 · gpt-5.6-luna, low reasoning |

Scope. That arm is pinned to [email protected] — the retired 1.x heuristic era — so the score describes the predecessor architecture, not the MVCC v2 line. It updates here when the benchmark pin moves to 2.x.


How Anchors Work

  1. Whitespace Canonicalization: Each line is stripped of ASCII whitespace ([ \t\r\n]) before hashing. External formatting passes (prettier, black, eslint --fix) do not alter line hashes. Token-level edits (quotes, semicolons, variable names) rotate the hash.
  2. xxHash32 & Base62 Space: Canonical lines are hashed using xxHash32 and mapped to 3-character base62 strings (A-Za-z0-9), providing $62^3 = 238,328$ unique anchors.
  3. Collision-Free Coprime Probing: When duplicate lines occur in a file, collision resolution probes using a stride coprime to the hash space ($62^2 + 62 + 1 = 3,907$). Every line in a file receives a unique anchor.
  4. SQLite WAL CAS Storage: Line hashes and snapshots are persisted in ~/.config/pi-better-edit/hash-store.sqlite (honoring XDG_CONFIG_HOME). Snapshot retention is governed by proportional LRU vacuuming under a 50MB budget.

Upgrading from 1.x

Version 2.0 represents a major architectural upgrade from heuristic healing to formal MVCC:

  1. Heuristic Healing Deleted (ADR-0016): Heuristic guessing of relocated anchors (tryHealOrphanedSpan) is completely removed to eliminate silent miswrites on duplicate code.
  2. Boundary Rule Replaces E_UNSERVED_RANGE (ADR-0020): The old E_UNSERVED_RANGE code is retired. If one boundary lease is retired while the other survives unshifted, the tool emits [E_UNVERIFIED_RANGE] with a fresh read. If both bounds are lost, it emits [E_TARGET_LOST].
  3. Unified Diagnostic Contract (ADR-0021): Rejections use [E_*]; successful mutations with caveats use [W_*]. Structured diagnoses live in details.cause.
  4. Additive Store Migration: The SQLite schema migrates additively from version 6 to 7. Existing project files are untouched.

Development

# Install dependencies
pnpm install

# Run unit and integration tests
pnpm test

# Run quality checks
pnpm run lint
pnpm run format
pnpm run typecheck

# Run evaluation batteries
pnpm run eval

License

MIT

Acknowledgments