README.md

September 18, 2026 · View on GitHub

cursor-clijev-compaction ⚡

TypeSafe Jev-scored context recovery for Cursor CLI (agent). Verbatim facts, zero user hook mutations.

License: MIT Node >=18 pnpm Cursor CLI only Vitest passing

ArchitectureDecision SpaceQuickstartUsageWhy It MovesCodebaseEvidence & LimitsSecurity

Give it Cursor CLI execution history. TypeSafe Jev scores each tool call and result with atomic noul questions.
Kept tool facts survive native compaction verbatim; stale outputs drop without losing code constraints.

Built strictly for the Cursor CLI (agent binary).
Zero modifications to ~/.cursor/hooks.json. Pure opt-in via agent --plugin-dir or cursor-jev agent.


Architecture

Cursor's preCompact hook is purely observational (user_message only) and cannot replace or suppress native compact. cursor-clijev-compaction bridges this limitation by capturing tool I/O, scoring state with TypeSafe Jev, and re-injecting kept facts into the next turn.

flowchart LR
  subgraph capture[1. Capture]
    tool[postToolUse / postToolUseFailure] --> store[(.data/conv_id/tools.jsonl)]
  end

  subgraph score[2. Score]
    preCompact[preCompact hook] --> merge[Merge transcript + store]
    merge --> fitter[Fit state <= 25k tokens]
    fitter --> jev[TypeSafe Jev System One]
    jev --> sidecar[(.data/conv_id/sidecar.json)]
  end

  subgraph inject[3. Recovery]
    sidecar --> stopHook[stop hook: followup_message]
    sidecar --> resumeHook[sessionStart hook: additional_context]
  end

  store -.-> merge

Native summarization still runs. Instead of losing vital file paths, test failures, and constraints to LLM summary drift, the assistant receives a high-density, verbatim recovery block right after compaction finishes.

The decision space

Every non-pinned tool call generates two atomic noul questions sent to TypeSafe Jev System One (POST https://api.typesafe.ai/v1/systemone, model jev-latest):

  1. call_<id>: Should knowing this call was made (and its input arguments) stay in context?
  2. result_<id>: Should the full output stay in history verbatim, or can the assistant re-run it if needed?
flowchart TD
  call[Tool Call Evaluation] --> jev[Jev noul answers]
  jev --> gate{Keep Threshold >= 0.5}
  gate -->|keepResult >= 0.5| keep[Action: keep verbatim]
  gate -->|keepCall >= 0.5| truncate[Action: drop_result, keep call + head chars]
  gate -->|< 0.5 both| drop[Action: drop_call completely]

Deterministic Policy

  • Pinned boundary: The initial prompt and the newest messages (preserveRecentMessages, default 6) are pinned and never dropped.
  • State fitting: Fits conversation history into a 25,000 token budget through 6 progressive stages (input truncation, head/tail text abridging, old message collapse, call one-liners, call merging).
  • Request budgeting: Batches questions concurrently so state + questions never exceed 30,000 tokens (safely within Jev's 32k ceiling).

Try it

1. Setup

git clone https://github.com/kleosr/cursor-clijev-compaction.git
cd cursor-clijev-compaction
pnpm install
pnpm build
export TYPESAFE_API_KEY=your_typesafe_key
cursor-jev doctor
cursor-jev agent --

Same TypeSafe key as the Claude plugin. cursor-jev agent starts Cursor CLI with --plugin-dir and forwards TYPESAFE_API_KEY into the agent process so hooks can score with jev-latest. It never writes ~/.cursor/hooks.json.

2. Run with Cursor CLI (agent)

Use the cursor-jev wrapper. It executes agent --plugin-dir <this-repo> without touching any global configuration:

# Interactive agent session
cursor-jev agent --

# Non-interactive script / CI invocation
cursor-jev agent -- -p "fix flaky test in tests/auth.test.ts"

# Resume an existing session
cursor-jev agent -- --resume

Alternatively, invoke Cursor's native agent CLI directly by passing the plugin flag:

export TYPESAFE_API_KEY=your_typesafe_key
agent --plugin-dir /path/to/cursor-clijev-compaction

3. Offline Compactor

Inspect and score past Cursor transcripts offline without running the agent loop:

cursor-jev compact ./tests/fixtures/cursor-with-result.jsonl

Needs TYPESAFE_API_KEY. Prints JSON (messages, decisions, stats). Does not call Cursor. Without a key it exits 1 — there is no fake scorer.

Use the library

The core engine is self-contained and exported as an ESM package:

import { compact, compactMessages, type Message } from 'cursor-clijev-compaction';

const transcript: Message[] = [
  { role: 'user', text: 'Fix the failing test. Never touch src/auth.ts', toolUses: [] },
  {
    role: 'assistant',
    text: '',
    toolUses: [{ tool_use_id: 'tool_1', tool: 'Read', input: { path: 'tests/a.test.ts' } }],
  },
  {
    role: 'user',
    text: '',
    toolUses: [],
    toolResults: [{ tool_use_id: 'tool_1', text: 'AssertionError: expected 1 to be 2' }],
  },
];

// Single call against TypeSafe System One
const result = await compactMessages(transcript, {
  apiKey: process.env.TYPESAFE_API_KEY,
  preserveRecentMessages: 2,
});

console.log(result.decisions);
// [ { id: 't1', tool: 'Read', action: 'keep', reason: 'kept', keepCall: 0.92, keepResult: 0.88 } ]

console.log(result.stats);
// { calls: 1, kept: 1, resultsDropped: 0, callsDropped: 0, ms: 340, ... }

There is no stub scorer and no custom transport in the product path. compactMessages always calls TypeSafe Jev (jev-latest) at POST https://api.typesafe.ai/v1/systemone. Without TYPESAFE_API_KEY, that call is skipped in Cursor CLI hooks (native compact continues) and cursor-jev compact exits 1.

Why it moves

  • Never touches user configuration. Zero writes to ~/.cursor/hooks.json, workspace hooks, or CLI configs. No destructive installer.
  • Verbatim fact recovery. Standard LLM summaries discard exact compiler outputs, diffs, and constraints. Jev decisions selectively preserve full text where it matters.
  • Resolves Cursor's missing-result gap. Cursor JSONL transcripts often serialize tool_use without matching tool_result blocks. Our postToolUse hook captures outputs directly to guarantee full context.
  • Tokenizer-free state fitting. Calibrated character-class token estimation prevents budget overflow under Jev's 32k token limit without WASM binary dependencies.
  • Fail-open Cursor CLI. Missing TYPESAFE_API_KEY, TypeSafe downtime, or a history that will not fit skip scoring and print JSON. Native compact still runs (failClosed: false). cursor-jev compact (offline) fails closed without a key.
  • Loop-breaker protection. The stop hook enforces loop_limit: 1 so recovery messages never trigger recursive agent loops.

Small enough to read

The codebase is lean, strictly typed, and free of decorative abstractions:

FileJobLines
src/cli.tsCLI wrapper (agent --plugin-dir), doctor, and offline compact~160
src/agent.tsResolve Cursor CLI agent on PATH or %LOCALAPPDATA%\cursor-agent~20
src/compact.tsDecision logic, question batching, and transcript rebuilding~250
src/hook.tsHook lifecycle router (postToolUse, preCompact, stop, sessionStart)~200
src/inject.tsMarkdown recovery payload generator with byte budget enforcement~90
src/jev.tsTypeSafe System One client (POST /v1/systemone, jev-latest)~110
src/paths.tsPath resolvers for .data/<conversation_id>/ and CURSOR_JEV_HOME~50
src/payload.tsRobust extraction for Cursor hook stdin schemas~110
src/state.tsSix-stage state fitting under the 25k token ceiling~240
src/store.tsAppend-only tool capture store & transcript merging~110
src/tokens.tsFast character-class token estimator~25
src/transcript.tsStreaming Cursor JSONL transcript parser~160
src/types.tsData models, hook schemas, and Jev protocol interfaces~130

Evidence and limits

Verification

pnpm test
pnpm typecheck
  • Vitest: TypeSafe client contract (POST https://api.typesafe.ai/v1/systemone, Authorization: Bearer, jev-latest noul answers), store merge, hook stdin/stdout, wrapper --plugin-dir, doctor, and no-key fail-open for Cursor CLI.
  • Safety: cursor-jev install exits 2 and never creates ~/.cursor/hooks.json.

Honest Limits

  • Cursor CLI only: Built exclusively for the agent command-line binary. Does not run in Cursor IDE Agent Chat, Cmd+K, Tab completions, or remote Cloud Agents.
  • Observational preCompact: Cursor CLI does not allow plugins to replace the compact summary in-flight (unlike Claude Code's session.compact). Kept facts are injected on the immediately following turn.
  • Local store: Tool outputs are cached in .data/<conversation_id>/ within this repository (or CURSOR_JEV_HOME). Never written to ~/.cursor.
  • TypeSafe only: Scoring is always TypeSafe Jev (jev-latest). No stub, Ollama, or custom asker in the product path. TYPESAFE_API_KEY is required to score (docs).

Development

# Run unit and integration tests
pnpm test

# Run strict TypeScript compiler verification
pnpm typecheck

# Build ESM artifacts to dist/
pnpm build

TypeSafe Jev DocumentationCursor CLI ReferenceAgent Plugins Standard