Skip to content

Releases: Digital-Threads/token-pilot

v0.46.0

13 Jun 15:34
b45f6c8

Choose a tag to compare

UserPromptSubmit per-turn reinforcement hook

Re-injects a one-line token-pilot anchor on every user message so the mandatory-tool rules don't decay out of attention over a long session (caveman-style). additionalContext only, never blocks the prompt. Toggles: sessionStart.enabled, TOKEN_PILOT_BYPASS=1, TOKEN_PILOT_PROMPT_REMINDER=0.

Security

npm audit fix cleared all transitive runtime advisories (hono/qs/path-to-regexp/fast-uri/ip-address/express-rate-limit) pulled via the MCP SDK HTTP stack — production audit now reports 0 vulnerabilities. CI audit gate scoped to production deps.

Full changelog: see CHANGELOG.md

v0.45.1 — refuse multi-repo workspace parent (cross-project index bleed)

11 Jun 17:04
44f89ea

Choose a tag to compare

Fixed — refuse a multi-repo workspace parent (cross-project index bleed)

start.sh always passes an explicit project root, so startServer's git-root narrowing (the !explicitRoot branch) never runs. When a session launches from a non-git workspace parent that nests several project repos (e.g. /work/loom holding token-pilot, loom-host, aimux, …), the raw parent was used verbatim and ast-index indexed every sibling into one index — find_usages / read_symbol then bled matches across unrelated projects (or returned symbol not found). isDangerousRoot only caught system/home dirs, so the parent slipped through.

New guard isMultiRepoParent(root) (core/validation.ts): a non-git directory with ≥2 immediate child git repos. On match, ast-index is disabled (skipAstIndex) and a warning tells the user to set CLAUDE_PROJECT_DIR to the specific project — fail safe instead of bleeding. Wired into startServer and the server.ts MCP-roots auto-detect. Single-repo roots, monorepos, and roots that are themselves a git repo are unaffected.

PR #45.

v0.45.0 — adoption fixes: full default + tool-error visibility

11 Jun 04:24

Choose a tag to compare

Changed — default tool profile is now full (adoption fix)

The advice surface (rules, SessionStart/PostToolUse banners, the pre-edit hook)
references read_for_edit, batch reads, test_summary etc. unconditionally,
but the old default (edit) and any trimmed profile hide some of those — so the
model calls a hidden tool, hits No such tool available, and falls back to raw
Read/Bash. Those dead round-trips cost far more than the ~2k tokens the trim
saved. Default is now full (advertise everything); trimmed profiles stay
opt-in via TOKEN_PILOT_PROFILE=nav|edit|minimal. When a trimmed profile is
active the SessionStart banner now prepends a caveat naming what's hidden.

The profile recommender no longer pushes a trim: it used to suggest
TOKEN_PILOT_PROFILE=nav for read-heavy usage and print an "apply to
.mcp.json" snippet — users applied it, then the next edit session hit the
trimmed-away read_for_edit / read_range / batch reads. It now always
recommends full. And token-pilot doctor loudly flags an explicit trimmed
profile, names the hidden tools, and tells you to remove it.

Added — tool failures are logged (no more silent breakage)

createServer's tool dispatch now writes handler exceptions / validation errors
(and unknown-tool names that reach the server) to ~/.token-pilot/hook-errors.jsonl,
visible via token-pilot errors. Previously tp breakage vanished while telemetry
reported "all ok". (No such tool available is rejected at the Claude Code layer
before reaching us and stays invisible by design — the full default removes its
main source.)

Fixed — read_section is docs-only

Clarified that read_section reads Markdown/YAML/JSON/CSV by heading/key/row —
not code by line/symbol (use read_range / read_symbol). Removed its
misleading placement under "Batch variants" in the SessionStart banner.

Added — bounded-read leak closed (gate on read span, not bound presence)

PreToolUse:Read passed any offset/limit Read straight through, so
Read(file, limit=2000) (Claude Code's default page) pulled a whole big file
hook-free and un-counted in the adaptive burn signal — the #1 invisible
leak. The hook now measures the span a Read actually pulls
(effectiveReadSpanLines) and applies the same deny threshold: a default-page
or offset-no-limit read of a big file denies with a structural summary, while a
genuinely narrow slice (limit < threshold) still passes. Cost estimates are
scaled by the span so bounded denies don't over-report savings.

Added — parent_session_id capture in SubagentStop (groundwork)

A subagent's MCP server runs with CLAUDE_CODE_SESSION_ID = the agent
session, so subagent savings get tagged with that id and the statusline's
main-session badge drops them (savings look flat when subagents do the reading).
SubagentStop now captures parent_session_id (which CC ships in the payload),
enabling a future child→parent rollup in the badge. Additive/no-op when absent.

Security — vitest 3.2.4 → 3.2.6

Patches GHSA-5xrq-8626-4rwp (Vitest UI arbitrary file read/exec, critical).
Dev-only dependency; shipped runtime deps unchanged. The other 32 Dependabot
alerts were already resolved (installed transitive versions at/above the
patched version) and auto-close on re-scan.

Docs

Fable-5 economic positioning in the README — savings are in tokens, value is in
tokens × price; keep the premium thread lean.

v0.42.3 — statusline TP-only by default

05 Jun 13:35
aa6a32b

Choose a tag to compare

install-statusline now installs just the [TP] badge by default instead of the caveman+TP chain. --chain opts into both. An existing chain switches to TP-only (drops the caveman badge); caveman's own statusLine is never replaced without --chain/--force. 1355/1355 tests.

v0.42.2 — statusline reads cwd (fix blank badge)

05 Jun 13:12
0bc74d8

Choose a tag to compare

tp-statusline.sh read only workspace.current_dir, but Claude Code 2.1.165 sends a top-level cwd. When it did, the badge went blank. Now reads both. 1350/1350 tests.

v0.42.1 — statusline shows cumulative savings

05 Jun 12:50
c61b019

Choose a tag to compare

Fixes the bare [TP] badge. tp-statusline.sh filtered savings by current session, so fresh sessions showed nothing. Now sums the whole project's saved tokens — a live-growing total. 1349/1349 tests.

v0.42.0 — one-command statusline setup

05 Jun 12:35
aea1c2e

Choose a tag to compare

token-pilot install-statusline wires the additive savings badge into settings.json — no hand-editing JSON. Non-destructive: never clobbers a statusLine you set for caveman or custom (upgrades caveman-only/tp-only to the chain wrapper so both badges show; --force to replace a custom one). The badge live-updates and sits alongside the session name, unlike the removed sessionTitle. 1349/1349 tests.

v0.41.1 — stop overwriting the session name

05 Jun 12:27
d152ddb

Choose a tag to compare

v0.36.0's [TP] Nk saved window-title badge used sessionTitle, which OVERWRITES Claude Code's session name — intrusive. Removed it. The cumulative-savings badge lives in the additive statusline instead (hooks/tp-statusline.sh, the same channel caveman uses), so it sits alongside the session name instead of replacing it. 1333/1333 tests.

v0.41.0 — SubagentStop budget feedback (env-gated, CC 2.1.163+)

05 Jun 06:33
6b0ddd7

Choose a tag to compare

CC 2.1.163 lets Stop/SubagentStop hooks return additionalContext. TOKEN_PILOT_SUBAGENT_FEEDBACK=1 makes SubagentStop emit a wind-down note when an active token-pilot workflow is at ≥90% of its budget — so a hundred-agent /workflow run stops before blowing the ceiling.

Default OFF, requires CC 2.1.163+ (older CC labels the return a hook error — verified against the 2.1.161 bundle before shipping). Telemetry-only default path unchanged. 1333/1333 tests.

v0.40.0 — task telemetry via SubagentStop (root cause fixed)

04 Jun 07:26
6c02272

Choose a tag to compare

Resolves the multi-release "0 task events" mystery with a clean in-session proof.

Proof: fresh 0.39.3 session — dispatched a real subagent → 0 events; same session Read-deny → 1 event written. So PostToolUse:Task does not fire for the dispatch tool (the whole history explained). async was never the cause.

Fix: capture via SubagentStop — CC's canonical subagent-completion event, fires once per subagent. New hook-subagent-stop writes event:"task" with subagent_type=agent_type (adoption signal) + best-effort transcript tokens. PostToolUse:Task kept as secondary.

1328/1328 tests pass. Verified e2e against dist.