excise

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: MIT

README

CI Go License Release Stars Go report

tagline


30-second demo · click to play · or see docs/demo.cast in this repo


What is Excise?

Anthropic's own documentation observes that more than two corrections in a single Claude Code session reliably poisons the trajectory — the agent starts fighting ghosts of the cut-off path you abandoned. The fix today is /clear (lose all context) or /compact (lose nuance). Excise is the missing third option: a single-binary CLI that opens an interactive picker over the session JSONL on disk, lets you cut the three turns that took the agent down the dead end, and writes the file back with snapshot-and-undo safety.

        before              after
    ┌──────────────┐    ┌──────────────┐
    │ user         │    │ user         │
    │ assistant    │    │ assistant    │
    │ user         │ ─▶ │   (excised)  │
    │ assistant ✗  │    │   (excised)  │
    │ user         │    │ user         │
    │ assistant ✓  │    │ assistant ✓  │
    └──────────────┘    └──────────────┘

The primitive Excise(Session, set<turn_id>) -> Session' preserves four invariants: (1) removing a tool_use turn also removes its paired tool_result, (2) removing a tool_result warns about the surviving owner, (3) ordering and stable ids are preserved, (4) writes are atomic (snapshot, write-to-tmp, rename).

Table of contents

Install

# via go
go install github.com/SuperMarioYL/excise/cmd/excise@latest

# via homebrew (after the tap is published — see BUILD_SETUP_NEXT_STEPS.md)
brew install supermarioyl/tap/excise

# from source
git clone https://github.com/SuperMarioYL/excise && cd excise
go build -o ./excise ./cmd/excise

Excise ships as a single ~8 MB static binary. No runtime, no daemon, no network call.

Quick start

# Zero-arg: auto-discover the newest Claude Code session and open the picker
excise

# Render the turn table, no edits
excise list

# Open the picker on a specific session file
excise pick ~/.claude/projects/-home-me-app/SESSION-UUID.jsonl

# Non-interactive cut: remove turns 5-7 and 9
excise cut 5-7,9 ~/.claude/projects/-home-me-app/SESSION-UUID.jsonl

# Same, but for a Cursor session
excise --tool=cursor cut 12-14 "~/Library/Application Support/Cursor/User/globalStorage/state.vscdb"

# Restore the most recent snapshot
excise rollback --list
excise rollback <snapshot-id>

In the TUI:

key action
j / move down
k / move up
g / G jump to top / bottom
space / x toggle mark on current turn
d mark + move down
enter commit the cut
q / ctrl+c abort without changes

The header live-updates turns: 42 → 39 tokens: ~18.2k → ~12.4k as you mark.

Commands

excise [path]                      open the TUI (auto-discover if no path)
excise list [path]                 print the turn table (no edits)
excise pick [path]                 open the TUI (alias for the bare command)
excise cut <range> [path]          non-interactive; e.g. "5-7,9"
excise rollback --list             list every snapshot, newest first
excise rollback <snapshot-id>      restore one snapshot

global flags:
  --tool       auto|claude|cursor   transcript format (default: auto)
  --session    PATH                 explicit session path
  --force                           proceed despite dependency warnings
  --dry-run                         show the diff but do not write
  -y, --yes                         skip the confirmation prompt

How dependency-aware cutting works

A Claude Code (or Cursor) turn that issues a tool call creates a downstream tool_result turn. If you cut the tool call but leave its result behind, the agent's next turn references a tool_use_id that no longer exists and the model gets confused.

Excise builds a dependency graph from every tool_use.idtool_result.tool_use_id edge, computes the transitive closure of your marked set, and (a) pulls every dependent result into the cut automatically (invariant 1), and (b) warns when your selection would orphan a tool_result whose owner survives (invariant 2). Pass --force to override the warning.

Snapshots and rollback

Every commit copies the source file to:

~/.excise/snapshots/<session-id>/<rfc3339-timestamp>.jsonl.gz

and appends a JSON line to ~/.excise/edit_log.jsonl recording what was removed, when, and why. Snapshots older than 30 days are auto-pruned on the next commit so the directory stays bounded.

excise rollback <snapshot-id> restores byte-for-byte. The original destination is read from the edit log; override with --to <path> if you moved the session file.

Supported transcript formats

Tool Path Read Write
Claude Code ~/.claude/projects/<dir>/<uuid>.jsonl yes atomic rewrite of the original
Cursor ~/Library/Application Support/Cursor/User/globalStorage/state.vscdb yes (via sqlite3 CLI, read-only) side-car .excised.jsonl to avoid corrupting an open db
Cursor (fixture export) *.jsonl of {"composerId":...,"bubble":{...}} lines yes atomic rewrite

sqlite3 is required only for the Cursor sqlite branch. macOS ships it; on Linux: apt install sqlite3. The Cursor writer deliberately refuses to mutate state.vscdb while Cursor is running — v0.2 will add a "Cursor must be closed" guard and a direct write path.

Architecture

┌────────────────────────────┐
│  cmd/excise/main.go        │  cobra CLI: excise [pick|list|cut|rollback]
└────────────┬───────────────┘
             │
   ┌─────────┴────────────────────────────┐
   ▼                                      ▼
internal/session                     internal/tui
  loader.go      Tool / Turn model     model.go   pure state + token math
  claude.go      Claude JSONL          picker.go  hand-rolled stdin driver
  cursor.go      Cursor sqlite+jsonl   bubbletea.go  real terminal UI
  dependency.go  tool-call graph       diff.go    before/after summary
  writer.go      WriterFor() dispatch
                    │
                    ▼
            internal/safety
              backup.go    snapshot + edit_log + rollback

One binary, no daemon, no IPC.

Roadmap

  • v0.2 — direct state.vscdb writes with a "Cursor closed?" guard; support for multi-composer Cursor windows.
  • v0.3 — Codex / Aider / Cline support behind the same primitive.
  • v0.4excise grep <regex> to mark by content match.
  • v0.5 — a "session debugger" sidecar that lets you inspect tool-call graphs without cutting anything.

Out of scope (on purpose)

  • Web UI or hosted service. CLI/TUI only.
  • Automatic poisoned-turn detection. You pick — we do not call an LLM.
  • Prompt-cache reconciliation. Editing invalidates the cache; you accept the cost.
  • A Claude Code plugin. We operate on the on-disk file between sessions.
  • Cloud sync, account system, team features.
  • Cross-tool session portability — that is cli-continues' niche, not ours.
  • Telemetry of any kind, including opt-in.

Every refusal above keeps the demo under 30 seconds.

Contributing

Bug reports and PRs welcome. Please run go test -race ./... before submitting. The hot path you most likely want to change is internal/session/claude.go (schema tolerance) or internal/safety/backup.go (snapshot policy). Anything bigger, open an issue first so we can agree on scope.

License

MIT © 2026 SuperMarioYL

Directories

Path Synopsis
cmd
excise command
Command excise — surgical context editing for coding-agent transcripts.
Command excise — surgical context editing for coding-agent transcripts.
internal
safety
Package safety implements the snapshot, edit-log, and rollback machinery that turns Excise from a "hope you backed up" knife into a "git for your agent transcript" pair of operations.
Package safety implements the snapshot, edit-log, and rollback machinery that turns Excise from a "hope you backed up" knife into a "git for your agent transcript" pair of operations.
session
Package session loads, mutates, and writes coding-agent transcripts.
Package session loads, mutates, and writes coding-agent transcripts.
tui
Package tui implements the bubbletea interactive picker for Excise.
Package tui implements the bubbletea interactive picker for Excise.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL