BLOG

fast-jev-compaction Teardown: Making Claude Code's Compaction Give Up Summarization

Kael Zhang
Claude Code上下文压缩AI Agent
广告 · Advertisement

Technical Teardown: Analyzing AI Technical Frameworks—Description, Analysis, Technical Assessment, Value Judgment, Implementation. Author: Yongliang


On September 19, 2026, tamaratran/fast-jev-compaction had 3,206 stars on GitHub (as of September 19), was written in TypeScript, under the MIT license, and the repository was created on September 17, 2026—two days ago. The npm package version is 0.2.0, the Claude Code plugin manifest is 0.3.0, the entire repo has 25 files, and the source code plus hooks plus tests total about 1850 lines. The core src is about 960 lines, with the largest single file compact.ts at 309 lines. Claude Code’s context compaction defaults to letting the model write a summary to replace old history—summaries are lossy, as file paths, precise errors, and constraints can all be lost. This plugin does not write summaries, it only performs deletion; deleted content either disappears in pairs or is preserved in full. This article breaks it down into six aspects: what it is, where the pain lies, how the mechanism works, three places in the source code worth seeing, boundaries and costs, and whether it’s worth it.

1. What Is This

fast-jev-compaction is a Claude Code plugin: it takes over the context compaction step, swapping “write summary” for “pairwise adjudication.” In the compressed history, there are no longer paragraphs retold by the model; every tool call has only three outcomes—fully preserved, keep the call but drop the result, or both the call and result disappear. The judgment basis is not a piece of text, but two probabilities.

To understand it, you must first recognize the model it depends on. Jev is a commercial model from TypeSafe, with a product line called “system one”: it does not generate text word by word, but outputs a probability for a given string of questions, allowing agents to branch quickly. At forks in the road like “which sentence should follow which” or “which result should stay in context,” it directly gives a number. Jev itself is a new thing that is three days old—in these three days, at least 5 jev-series repos have popped up on GitHub, with browser-use/jev-ultrafast gaining 5,487 stars as one of the fastest growing. A model driving a string of supporting projects shows that the direction of “using probabilistic models to make lightweight decisions for agents” is gaining traction, and fast-jev-compaction is the most complete engineering sample in this wave. TypeSafe has not publicized Jev’s internal design; this article only discusses how this plugin uses its interface, not inventing an architecture for it.

2. The Real Pain Point It Solves

Long-session agents have limited context windows and must compress when nearly full. The mainstream approach is LLM summarization: let the model read the old history and write a condensed version to replace the original text. The essence of summarization is letting the model take notes for its future self—what to remember and what to drop is decided by a generative process, and errors leave no trace. File paths might be rewritten as approximate paths, precise error messages might be summarized as “there was an error,” and user constraints (“don’t touch this file”) might be lost during condensation. More troublesome is that after compression there is no way to verify what was lost; when the model modifies the wrong file three hours later based on an incorrect summary, it’s hard to trace the blame back to that compression.

This plugin’s breakdown of the pain point is very calm: the bulk of context is not chat text, but tool calls and tool results—a single file read is thousands of characters, a single test output is tens of thousands, and after dozens of rounds they consume 90% of the space. What really needs judging is “is this call still important for what comes next.” This is a multiple-choice question, not an essay question. Multiple-choice questions can be handed to a model that outputs probabilities, and the answers can be archived item by item. Essays can fabricate; multiple-choice is at least honest.

3. Mechanism: From Pairing to Reconstruction

3.1 Pairing and Pinned

The first step is to split the conversation into adjudicatable units. Each tool_use and its corresponding tool_result are paired by tool_use_id—when deleting, the call and result move together, so reconstruction won’t produce a dangling result without a call. The first message and the latest preserveRecentMessages messages (default 6) are marked as pinned, never processed, ensuring the beginning and the present of the session are always complete.

3.2 Building the State Sent to Jev

The state sent to Jev is the complete conversation, oldest first. All tool results are replaced with a short note (like ok, 4213 chars (omitted)), telling Jev “there was a successful read here, original text 4213 characters”; tool inputs are fully serialized into the state; user and assistant text is fully preserved, not summarized. The state itself has a volume limit maxStateTokens (default 25000). If exceeded, it degrades in stages: tool inputs are truncated to 1000, then 200, then 60 characters; long text keeps the first 400 and last 150 characters; if that’s not enough, the oldest messages are folded into [… N chars omitted …], and old tool calls are compressed into one line (like t12 Read file_path=src/a.ts → ok 480ch); pinned messages are touched last. If all stages are passed and it still doesn’t fit, an exception is thrown directly, not forced in. Token count is character estimation: about 1 token per 6 letters, numbers count half, other symbols about 1 each—not a real tokenizer, cheap, and introduces no tokenization dependency.

3.3 Two Noul Questions and Batching

For each non-pinned call, the plugin asks Jev two questions. call_X: “Knowing this call was initiated and with what input, is it still important for what comes next.” result_X: “Does this result need the original text preserved, can re-running the tool not replace it.” Both are noul type—Jev doesn’t return text, just spits out a probability for each question.

Questions are batched by volume. maxRequestTokens defaults to 30000 (Jev’s single request limit is 32000), minus the quota occupied by state and minus 20 tokens for request envelope overhead, the remaining budget is how many questions a batch can carry. The state is resent in full for every batch; all questions in a batch are merged into one request, and batches are sent concurrently with answers merged. The larger the state, the fewer questions fit in a batch; in extreme cases, a request is needed for every few questions—this is a cost inherent to the design, expanded in the boundaries section.

3.4 Decision and Reconstruction

The decision rules can be written in one line. decideCall judges in order: pinned is directly kept; if keepResult is greater than or equal to the threshold (default 0.5), keep the pair; otherwise, if keepCall is greater than or equal to the threshold, keep the call itself, truncate the result to the first truncateHeadChars (default 300) characters, and attach a note—the note explains how many characters were truncated, whether it was an error, and that the tool can be re-run if needed; if neither probability passes, the call and result are deleted in pairs.

Reconstruction is done by applyDecisions: messages with all content dropped are removed entirely, untouched messages are returned as-is (same object, zero copy), and partially modified messages are replaced in place. The input and output process is structured decisions plus verifiable statistics (counts of each decision type, character count before and after compression, estimated token count of state, which degradation stage was used, how many requests were sent), not a piece of prose.

4. Three Places in the Source Code Worth Seeing

4.1 Batching and Decision Functions in compact.ts

compact.ts is 309 lines, the largest file in the repo, and the main trunk has just four functions. questionsFor (compact.ts:56) generates two noul questions for each call, encoding the tool name, call id, and result character count into the question text so Jev has grounds for judgment. batchCalls (compact.ts:73) handles batching, with a transparent budget algorithm: maxRequestTokens minus state minus 20, fill if it fits; if a single call’s questions themselves exceed the budget, it means the state is too big, and it throws an exception with the error explicitly stating “state occupied about how much of the 30000”. decideCall (compact.ts:101) is the shortest section in the book—pinned, keepResult threshold, keepCall threshold, else delete, four lines. applyDecisions (compact.ts:149 onwards) is responsible for reconstruction, with comments writing out the invariants very clearly: deleted calls disappear along with results, deleted results keep a bounded head and a note, messages with all content dropped are removed, untouched messages return the original object.

4.2 Endpoints and Noul Parsing in request.ts

request.ts is only 80 lines, the entirety of the interface contract. SYSTEM_ONE_URL points to https://api.typesafe.ai/v1/systemone, default model name jev-latest. buildJevRequest packs model, state, and questions into a POST. parseJevResponse does strict validation on the response body: throws if HTTP is not ok, throws if JSON parsing fails, throws if answers field is missing. noulAnswer takes the noul field of a single answer; if missing, not a number, or not finite, it throws. There isn’t a single silent error tolerance in the entire file—all failures become exceptions passed up, letting the caller decide the fallback.

4.3 Hook Trigger Conditions

hooks/fast-jev.ts is a thin adapter layer receiving from Claude Code. function hooks is an early feature of Claude Code 2.1.274+, requiring opt-in in settings.json first; after enabling, the plugin is called back at turn.complete, checks current context usage, and only triggers compression when compactAtPercent (default 60%) is reached. After triggering, it estimates a round first; if the compression ratio is less than minReductionRatio (default 25%), it doesn’t replace history—it doesn’t do a free round of judgment that isn’t worth it. Any exception—Jev service down, malformed answers, missing TYPESAFE_API_KEY, state doesn’t fit—doesn’t force it, falling back to Claude Code’s built-in summary compression. Configuration can go entirely through the plugin’s userConfig: thresholds, number of items to keep, truncation length, model name are all editable item by item.

5. Boundaries and Costs

The official Limitations are four items, recorded verbatim. First, it only processes tool calls, text messages are never shortened in the output (they are only abbreviated in the state seen by Jev)—if your context is bloated by chat text, this plugin can’t help. Second, token count is character estimation, not a real tokenizer, so budget judgment has偏差. Third, the original sentence is worth remembering fully: “a probability is not proof that it is safe to delete, the assistant can always re-run the tool”—the 0.5 threshold is an empirical line, not a safety line. Fourth, the state is resent in full per request; when history is near the limit, a request is needed for every few questions, and token cost rises linearly with history length—heavy users need to know how to do this math.

Three doubts, written only as doubts not as absolutes. Decision quality relies entirely on the probability calibration of Jev, this one commercial model; the repo has no integrated test benchmark numbers, the README has no benchmark table, and there is no third-party verifiable metric for whether compression is good. The plugin ecosystem is tightly coupled with the Claude Code version; function hooks itself is an early feature of 2.1.274+, and if the interface moves, the plugin must follow. The repo has only two days of history, and long-session performance in production hasn’t been verified by anyone; two days and 3,206 stars is concept heat, not a stability endorsement.

6. Value and Suitable Audience

This is a new solution to the old problem of “context compression”—turning the summary essay question into a multiple-choice question, at the cost of outsourcing decision-making to a commercial probabilistic model. The suitable people are very clear: those who use Claude Code for long sessions every day and have been burned by summaries dropping context, the cost to try it is low, just an npm package and environment variable; those doing agent engineering or researching context management, this repo’s 1850 lines can be read in one evening, it’s a clean sample of stuffing a probabilistic model into an agent’s decision loop. The unsuitable people are equally clear: those who don’t want to send conversation data to third-party APIs—the state is the full conversation, including your code and errors; those whose sessions aren’t long and built-in summaries are enough; teams that need verifiable compression quality guarantees, the README has no benchmarks, so this guarantee can’t be given right now.

Author’s view: if you don’t use Jev, can this idea be ported? Most likely yes. The essence of noul questions is scoring a set of options; any small model that can output logits can do it—run a 3B-level small model locally, output the “yes” probability for the two questions call_X and result_X, replacing Jev’s remote call, data doesn’t leave the machine, call cost drops to zero, the price is that calibration quality isn’t guaranteed and thresholds must be tuned yourself. What this project is really worth taking away might not be the plugin itself, but this way of questioning: compressing context doesn’t require the model to write an essay, make it do multiple-choice, then execute by probability threshold.

Conclusion

fast-jev-compaction uses about 1850 lines of code to answer a question: must context compaction write a summary? Its answer is no. Tool calls occupy the bulk of long-session context, “keep or delete” is a multiple-choice question that can be answered by a model like Jev that outputs option probabilities. In the source code, this judgment is very concrete: calls are paired by tool_use_id, the first and latest 6 are pinned and never processed, state is built completely with tool results replaced by short notes and degrading in four stages if over limit, each call is asked two noul questions, batched concurrently by 30000 token budget, adjudicated by 0.5 threshold into keep / drop_result / drop_call three tiers, reconstruction ensures no dangling results; on the hook side, it checks 60% usage at turn.complete to trigger, abandons replacement if compression ratio is under 25%, and falls back to built-in summary on failure. The costs are also clear: tokens are estimated, probability is not proof of deletion safety, state is resent in full, quality has no benchmark numbers. Two days, 3,206 stars, the rise is concept heat, and it is tied to the same boat as Jev, this three-day-old new thing—for those doing agent context management, this is source code worth reading; for ordinary users, wait for it to run a few versions.

References

  • tamaratran/fast-jev-compaction README (Positioning, configuration table, Limitations, Claude Code plugin instructions, function hooks version requirements)
  • Source code (local clone): src/compact.ts (DEFAULT_OPTIONS, questionsFor, batchCalls, decideCall, applyDecisions), src/state.ts (collectToolCalls, estimateTokens, fitState, INPUT_CHARS=[1000,200,60], TEXT_HEAD=400/TEXT_TAIL=150), src/request.ts (SYSTEM_ONE_URL, DEFAULT_MODEL, buildJevRequest, parseJevResponse, noulAnswer), hooks/fast-jev.ts (compactAtPercent, minReductionRatio, exception fallback)
  • Repo data: 3,206★, MIT, created 2026-09-17, npm 0.2.0, plugin manifest 0.3.0, 25 files about 1850 lines (as of 2026-09-19)
广告 · Advertisement

Frequently Asked Questions

What does fast-jev-compaction do?

A Claude Code plugin: takes over the context compaction step, does not write summaries, only performs deletion. Each tool_use and tool_result are paired by tool_use_id. After compaction, every tool call has only three outcomes: fully preserved, keep the call but drop the result (result truncated to first 300 chars with a note), or both the call and result disappear. The repo has 25 files and about 1850 lines of TypeScript, created on 2026-09-17, gaining 3,206 stars in two days.

How does its adjudication mechanism work?

The state sent to Jev (TypeSafe's commercial probabilistic model) is the complete conversation: tool results are replaced with a short note, tool inputs are fully serialized, and text is fully preserved. If over 25,000 tokens, it degrades in four stages. For each non-pinned call, two noul questions are asked: is it important to know this call was initiated, and is the original result text essential to keep. Batches are processed concurrently based on a 30,000 token budget. If keepResult probability is over 0.5, the pair is kept; otherwise, if keepCall is over 0.5, the call is kept and the result truncated; if neither passes, the pair is deleted. The first message and the latest 6 messages are pinned and never processed.

What are the costs and boundaries compared to the official summary compression?

There are four costs: token count is character estimation not a real tokenizer; "a probability is not proof that it is safe to delete," the 0.5 threshold is an empirical line not a safety line; the state is resent in full per request, so when history is near the limit, a request is needed for every few questions; there are no third-party benchmark numbers for compression quality, and the repo has only two days of history and is tightly coupled with Claude Code's early hook interface. The state is the full conversation including code and errors, so it is not suitable for those who do not want to send data to third-party APIs.