jev compact

September 20, 2026 · View on GitHub

Shrink an agent transcript without summarizing anything. Jev decides, per old tool call, whether the call and whether its full output still matter. Stale results are cut to a short head plus a note, stale calls are removed, everything else is returned exactly as it was. User and assistant text is never touched.

jev compact [transcript] [options]

When to use

Before handing a long session to another agent, to audit what a compaction would drop, or as the engine behind the Claude Code plugin's compaction hook, which replaces the built-in summary in-session. Summaries are lossy: a path, an exact error, or a constraint can vanish. This never rewrites, only deletes what Jev says is no longer needed, and the assistant can always re-run a tool.

Input

FormExample
Claude Code session log@~/.claude/projects/<project>/<session>.jsonl
Messages JSON[{"role","text","toolUses":[{"tool_use_id","tool","input"}],"toolResults":[{"tool_use_id","text"}]}]; text and toolUses may be omitted

Options

OptionMeaningDefault
-g, --goal <text>The ongoing task, so Jev knows what still matterslast three user prompts
--keep-threshold <p>Keep a call or result when Jev's probability is at least this0.5
--preserve-recent <n>Newest messages never touched; the first is always kept6
--max-state-tokens <n>Budget for the history sent to Jev25000
--max-request-tokens <n>Budget for history plus one batch of questions30000
--truncate-head <n>Characters kept from a dropped result before its note300
--min-reduction <p>Below this ratio the result is worth_it: false0.25
--concurrency <n>Question batches in flight at once, 1 to 644
-o, --out <path>Write the compacted transcript as messages JSON
--fail-on <list>Exit 2 on low-reductionnone

How it fits Jev's 32k window

Jev never sees the raw transcript. The state is the whole conversation with every tool output replaced by a one-line note (ok, 4213 chars (omitted)). If that exceeds the budget it is shrunk in stages: tool inputs truncated, long texts abridged, old messages collapsed to a note, old calls reduced to one line, old call-less messages left out. Questions (two per candidate call) are split across as many requests as needed, each resending the same state. They run concurrently, at most --concurrency at a time (default 4), because every request in flight carries another copy of the state. Compressing the state never changes the output; it only shapes what Jev reads to decide. Token counts are estimates calibrated slightly above Jev's real counts.

Output

reduction, worth_it, stats (messages and chars before and after, kept/truncated/dropped/pinned counts, state tokens and stage, requests, ms), decisions[] (id, tool, action, keepCall, keepResult), messages (the compacted transcript).

Example

jev compact @session.jsonl --out compacted.json
61% smaller  528 → 341 messages · 1,204,311 → 470,902 chars
209 tool calls: 58 kept · 71 results truncated · 77 calls dropped · 3 pinned · state ~24944 tokens (old messages collapsed) in 5 request(s), 2140 ms

Call  Tool  Action    P(call)  P(result)
----  ----  --------  -------  ---------
t1    Bash  truncate  0.91     0.12
t2    Read  drop      0.08     0.03

In-session use: see plugin/hooks/README.md. Adapted from fast-jev-compaction (MIT).