token-pilot 0.34.3 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Token Pilot \u2014 save 60-90% tokens when AI reads code",
9
- "version": "0.34.3"
9
+ "version": "0.35.0"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "token-pilot",
14
14
  "source": "./",
15
15
  "description": "Reduces token consumption by 60-90% via AST-aware lazy file reading, structural symbol navigation, and cross-session tool-usage analytics. 22 MCP tools + 19 subagents + budget watchdog hooks.",
16
- "version": "0.34.3",
16
+ "version": "0.35.0",
17
17
  "author": {
18
18
  "name": "Digital-Threads"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "token-pilot",
3
- "version": "0.34.3",
3
+ "version": "0.35.0",
4
4
  "description": "Saves 60-90% tokens on AI code reading. AST-aware lazy reads, symbol navigation, find_usages, structural git diff/log, edit-safety guard, Task-routing matcher, cross-session telemetry (errors + diagnostics), 25 tp-* subagents tiered to haiku/sonnet/opus with budget watchdog.",
5
5
  "author": {
6
6
  "name": "Digital-Threads",
package/README.md CHANGED
@@ -154,6 +154,84 @@ quality-of-life notes for the newer ones.
154
154
  the MCP server entry. The skill list, the agent list, and the LSP
155
155
  list are all auto-discovered from the canonical sub-folders.
156
156
 
157
+ ## Power-user — undocumented Claude Code features that pair with token-pilot
158
+
159
+ These fields come from reverse-engineering `@anthropic-ai/claude-code@2.1.87`
160
+ source (see the May 2026 Habr write-up). They work today but are
161
+ not in the official Claude Code docs, so use at your own risk.
162
+
163
+ ### Persistent agent memory (`memory: project`)
164
+
165
+ Every relevant tp-\* agent (onboard, debugger, pr-reviewer,
166
+ history-explorer, audit-scanner) now ships with `memory: project`
167
+ in its frontmatter. Claude Code persists the agent's working notes
168
+ in the project so the agent gets faster on repeat invocations —
169
+ `tp-onboard` remembers your layout, `tp-pr-reviewer` remembers your
170
+ flagged patterns, etc. v0.35.0+.
171
+
172
+ ### Required MCP gating (`requiredMcpServers`)
173
+
174
+ Every tp-\* agent declares `requiredMcpServers: ["token-pilot"]`.
175
+ Claude Code refuses to load the agent when the MCP server isn't
176
+ configured, so a stale install never produces a "tools not found"
177
+ loop. v0.35.0+.
178
+
179
+ ### Bootstrap-once hook (`once: true`)
180
+
181
+ The plugin ships a SessionStart hook flagged `once: true` —
182
+ Claude Code runs it once per project then auto-removes the entry.
183
+ It surfaces friendly hints when `install-agents` or
184
+ `install-ast-index` hasn't been run yet. v0.35.0+.
185
+
186
+ ### Async telemetry (`async: true`)
187
+
188
+ PostToolUse hooks (Bash, Task) are marked `async: true` so they
189
+ no longer add wall-clock to the hot path — telemetry writes fire
190
+ in the background.
191
+
192
+ ### Auto-mode permissions (user-side)
193
+
194
+ If you want full auto-approval for safe commands, the YOLO
195
+ classifier reads natural-language environment descriptions:
196
+
197
+ ```json
198
+ {
199
+ "autoMode": {
200
+ "allow": ["Bash(git status)", "Bash(npm test)", "Read", "Grep"],
201
+ "soft_deny": ["Bash(git push *)", "Bash(rm *)", "Write(.env)"],
202
+ "environmentDescription":
203
+ "This is a development laptop. Read-only ops are safe; deny anything touching credentials or production."
204
+ }
205
+ }
206
+ ```
207
+
208
+ token-pilot's enforcement still runs on top (raw Read on large files
209
+ is denied first, regardless of autoMode).
210
+
211
+ ### Permission rule syntax cheat-sheet
212
+
213
+ ```
214
+ Bash(npm *) # wildcard after "npm "
215
+ Bash(git commit *) # specific subcommand
216
+ Read(*.ts) # extension
217
+ Read(src/**/*.ts) # recursive + extension
218
+ Write(src/**) # recursive all files
219
+ mcp__token-pilot # all token-pilot MCP tools
220
+ mcp__token-pilot__smart_read # one specific MCP tool
221
+ ```
222
+
223
+ `*` matches inside word boundaries (shell-glob); `**` is recursive.
224
+ The `if` field on hooks uses the same syntax.
225
+
226
+ ### Experimental: transparent Read rewrite
227
+
228
+ Set `TOKEN_PILOT_HOOK_REWRITE=1` to swap the "deny + suggest" Read
229
+ hook behaviour for an `updatedInput` rewrite — Claude Code's
230
+ undocumented field that silently bounds the Read to its first 200
231
+ lines instead of bouncing the call. The structural summary still
232
+ rides along in `additionalContext`. Default OFF because the field
233
+ is undocumented and may change.
234
+
157
235
  ## Troubleshooting
158
236
 
159
237
  ```bash
@@ -9,8 +9,11 @@ tools:
9
9
  - mcp__token-pilot__read_symbol
10
10
  - Bash
11
11
  model: haiku
12
- token_pilot_version: "0.34.3"
12
+ token_pilot_version: "0.35.0"
13
13
  token_pilot_body_hash: dd184501203fa7f3c73f419c4ffbe33c4be75400cb64a7a51733a3fe23f6e085
14
+ requiredMcpServers:
15
+ - "token-pilot"
16
+ color: blue
14
17
  ---
15
18
 
16
19
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -11,8 +11,13 @@ tools:
11
11
  - Grep
12
12
  - Read
13
13
  model: sonnet
14
- token_pilot_version: "0.34.3"
14
+ token_pilot_version: "0.35.0"
15
15
  token_pilot_body_hash: d172f600bf32277ea6eb4cbbee4542ddd698a986dcd96997d33930561964569b
16
+ requiredMcpServers:
17
+ - "token-pilot"
18
+ memory: project
19
+ color: red
20
+ omitClaudeMd: true
16
21
  ---
17
22
 
18
23
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -8,8 +8,11 @@ tools:
8
8
  - mcp__token-pilot__test_summary
9
9
  - mcp__token-pilot__outline
10
10
  - Bash
11
- token_pilot_version: "0.34.3"
11
+ token_pilot_version: "0.35.0"
12
12
  token_pilot_body_hash: de64a406b5176de19f7422619c7de7949b1f28865f225402c9cea9255f377428
13
+ requiredMcpServers:
14
+ - "token-pilot"
15
+ color: purple
13
16
  ---
14
17
 
15
18
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -13,8 +13,11 @@ tools:
13
13
  - Edit
14
14
  - Glob
15
15
  model: sonnet
16
- token_pilot_version: "0.34.3"
16
+ token_pilot_version: "0.35.0"
17
17
  token_pilot_body_hash: 68b32af2dacd82ebe52c4eec93edb903d452688274c3065218270627c564d8b0
18
+ requiredMcpServers:
19
+ - "token-pilot"
20
+ color: green
18
21
  ---
19
22
 
20
23
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -11,8 +11,11 @@ tools:
11
11
  - Grep
12
12
  - Read
13
13
  model: sonnet
14
- token_pilot_version: "0.34.3"
14
+ token_pilot_version: "0.35.0"
15
15
  token_pilot_body_hash: d9b7f5b7ae6f4ae21305c775361bcab097cc774370a6d976c093571d46d55021
16
+ requiredMcpServers:
17
+ - "token-pilot"
18
+ color: red
16
19
  ---
17
20
 
18
21
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -12,8 +12,12 @@ tools:
12
12
  - Read
13
13
  - Bash
14
14
  model: sonnet
15
- token_pilot_version: "0.34.3"
15
+ token_pilot_version: "0.35.0"
16
16
  token_pilot_body_hash: 052413de8d92377edcde6ae5c823f5378db304baccfa29e8866467f42553a500
17
+ requiredMcpServers:
18
+ - "token-pilot"
19
+ memory: project
20
+ color: yellow
17
21
  ---
18
22
 
19
23
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -9,8 +9,11 @@ tools:
9
9
  - Bash
10
10
  - Read
11
11
  model: haiku
12
- token_pilot_version: "0.34.3"
12
+ token_pilot_version: "0.35.0"
13
13
  token_pilot_body_hash: e14dc57493d816f8c2e017963e2ef5f66bea50fd0b805a80e8a0d97c968427e7
14
+ requiredMcpServers:
15
+ - "token-pilot"
16
+ color: purple
14
17
  ---
15
18
 
16
19
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -13,8 +13,11 @@ tools:
13
13
  - Edit
14
14
  - Glob
15
15
  model: haiku
16
- token_pilot_version: "0.34.3"
16
+ token_pilot_version: "0.35.0"
17
17
  token_pilot_body_hash: 57d741794ab40e31a7ac49c68ea39a9088f5827cdef866ce81bfca1b7c9180cf
18
+ requiredMcpServers:
19
+ - "token-pilot"
20
+ color: green
18
21
  ---
19
22
 
20
23
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -10,8 +10,12 @@ tools:
10
10
  - Bash
11
11
  - Read
12
12
  model: haiku
13
- token_pilot_version: "0.34.3"
13
+ token_pilot_version: "0.35.0"
14
14
  token_pilot_body_hash: 7b70fa76a60e3c58a1de4f56c32c0f166424137e203a0cf1c8654e7c9235d904
15
+ requiredMcpServers:
16
+ - "token-pilot"
17
+ memory: project
18
+ color: blue
15
19
  ---
16
20
 
17
21
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -12,8 +12,11 @@ tools:
12
12
  - mcp__token-pilot__read_symbols
13
13
  - Read
14
14
  model: sonnet
15
- token_pilot_version: "0.34.3"
15
+ token_pilot_version: "0.35.0"
16
16
  token_pilot_body_hash: 351a987e11eba63852f5431a16d8eb53104f4f689f82fdcc5a2bf4db948ba92f
17
+ requiredMcpServers:
18
+ - "token-pilot"
19
+ color: blue
17
20
  ---
18
21
 
19
22
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -8,8 +8,11 @@ tools:
8
8
  - mcp__token-pilot__read_symbol
9
9
  - Bash
10
10
  model: inherit
11
- token_pilot_version: "0.34.3"
11
+ token_pilot_version: "0.35.0"
12
12
  token_pilot_body_hash: de5722bfea374eaab096c1ae635c37879e7a91370ee3cd0532f4240be03c91eb
13
+ requiredMcpServers:
14
+ - "token-pilot"
15
+ color: yellow
13
16
  ---
14
17
 
15
18
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -13,8 +13,11 @@ tools:
13
13
  - Edit
14
14
  - Bash
15
15
  model: sonnet
16
- token_pilot_version: "0.34.3"
16
+ token_pilot_version: "0.35.0"
17
17
  token_pilot_body_hash: 375a824d0d847bb5453ec594c7a62ad566ee7e4d92717b0473f771f1a0477c60
18
+ requiredMcpServers:
19
+ - "token-pilot"
20
+ color: orange
18
21
  ---
19
22
 
20
23
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -11,8 +11,11 @@ tools:
11
11
  - Grep
12
12
  - Glob
13
13
  model: sonnet
14
- token_pilot_version: "0.34.3"
14
+ token_pilot_version: "0.35.0"
15
15
  token_pilot_body_hash: 0334de1bf99b431b65359637d125cda7c44c6f780eb92c57cc538715b1939536
16
+ requiredMcpServers:
17
+ - "token-pilot"
18
+ color: orange
16
19
  ---
17
20
 
18
21
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -10,8 +10,12 @@ tools:
10
10
  - mcp__token-pilot__smart_read
11
11
  - mcp__token-pilot__smart_read_many
12
12
  - mcp__token-pilot__read_section
13
- token_pilot_version: "0.34.3"
13
+ token_pilot_version: "0.35.0"
14
14
  token_pilot_body_hash: 832e95633fbc8e9b0c10f3e540a327d4be062fb4b3f17a6cce6be13f414e2927
15
+ requiredMcpServers:
16
+ - "token-pilot"
17
+ memory: project
18
+ color: blue
15
19
  ---
16
20
 
17
21
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -11,8 +11,11 @@ tools:
11
11
  - Bash
12
12
  - Read
13
13
  model: sonnet
14
- token_pilot_version: "0.34.3"
14
+ token_pilot_version: "0.35.0"
15
15
  token_pilot_body_hash: b61f06380d80798fa2e49d37bcba0653495bee04dd6bdbc1feff9a75607b0508
16
+ requiredMcpServers:
17
+ - "token-pilot"
18
+ color: yellow
16
19
  ---
17
20
 
18
21
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -11,8 +11,12 @@ tools:
11
11
  - mcp__token-pilot__read_for_edit
12
12
  - Read
13
13
  model: sonnet
14
- token_pilot_version: "0.34.3"
14
+ token_pilot_version: "0.35.0"
15
15
  token_pilot_body_hash: f83f50d05b4f70285ae7afed2b1a406fc436df56e61a0aedbfb31edc7f2b6e66
16
+ requiredMcpServers:
17
+ - "token-pilot"
18
+ memory: project
19
+ color: red
16
20
  ---
17
21
 
18
22
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -8,8 +8,11 @@ tools:
8
8
  - mcp__token-pilot__outline
9
9
  - mcp__token-pilot__read_symbol
10
10
  model: sonnet
11
- token_pilot_version: "0.34.3"
11
+ token_pilot_version: "0.35.0"
12
12
  token_pilot_body_hash: c5f6fc122c89e16e5cf774045f92169ee3468555320b898171ba13eca5323550
13
+ requiredMcpServers:
14
+ - "token-pilot"
15
+ color: orange
13
16
  ---
14
17
 
15
18
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -9,8 +9,11 @@ tools:
9
9
  - mcp__token-pilot__module_info
10
10
  - Bash
11
11
  model: sonnet
12
- token_pilot_version: "0.34.3"
12
+ token_pilot_version: "0.35.0"
13
13
  token_pilot_body_hash: 8ef3c3341cbfed4eb8dd130126a9683edc57e378c92ff0ca764d584fd941c55c
14
+ requiredMcpServers:
15
+ - "token-pilot"
16
+ color: red
14
17
  ---
15
18
 
16
19
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
package/agents/tp-run.md CHANGED
@@ -16,8 +16,11 @@ tools:
16
16
  - Glob
17
17
  - Bash
18
18
  model: haiku
19
- token_pilot_version: "0.34.3"
19
+ token_pilot_version: "0.35.0"
20
20
  token_pilot_body_hash: 2b08618d34a61f00aafccbda9fed6d83243296dedb83440edbd2d5c28bb6dbc4
21
+ requiredMcpServers:
22
+ - "token-pilot"
23
+ color: gray
21
24
  ---
22
25
 
23
26
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -9,8 +9,11 @@ tools:
9
9
  - mcp__token-pilot__session_budget
10
10
  - Bash
11
11
  - Read
12
- token_pilot_version: "0.34.3"
12
+ token_pilot_version: "0.35.0"
13
13
  token_pilot_body_hash: 529374ed728f5eed5b758b3be3da65624783c0bf0c1a253d7d661a843eb5f767
14
+ requiredMcpServers:
15
+ - "token-pilot"
16
+ color: blue
14
17
  ---
15
18
 
16
19
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -11,8 +11,11 @@ tools:
11
11
  - Read
12
12
  - Grep
13
13
  model: sonnet
14
- token_pilot_version: "0.34.3"
14
+ token_pilot_version: "0.35.0"
15
15
  token_pilot_body_hash: a60f6ae110eb3138064bce074e8ba26fa0ce5f4659df1624a9d9d3646803391b
16
+ requiredMcpServers:
17
+ - "token-pilot"
18
+ color: purple
16
19
  ---
17
20
 
18
21
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -9,8 +9,11 @@ tools:
9
9
  - Read
10
10
  - Write
11
11
  model: sonnet
12
- token_pilot_version: "0.34.3"
12
+ token_pilot_version: "0.35.0"
13
13
  token_pilot_body_hash: c7a4e8b39228fd5158528f389c924c5ff2d98c4b9b05ee0106d54a26c5dc1350
14
+ requiredMcpServers:
15
+ - "token-pilot"
16
+ color: orange
14
17
  ---
15
18
 
16
19
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -10,8 +10,11 @@ tools:
10
10
  - mcp__token-pilot__test_summary
11
11
  - Glob
12
12
  - Grep
13
- token_pilot_version: "0.34.3"
13
+ token_pilot_version: "0.35.0"
14
14
  token_pilot_body_hash: be81eed53a3720d146cf89e4a14a7a56577633f7c84c234c412ab70d64c05b11
15
+ requiredMcpServers:
16
+ - "token-pilot"
17
+ color: red
15
18
  ---
16
19
 
17
20
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -8,8 +8,11 @@ tools:
8
8
  - mcp__token-pilot__find_usages
9
9
  - mcp__token-pilot__read_symbol
10
10
  model: sonnet
11
- token_pilot_version: "0.34.3"
11
+ token_pilot_version: "0.35.0"
12
12
  token_pilot_body_hash: 362ecf4cb03b059421ea26933473700900073dc38b3a7fe271208dfb1ae14f90
13
+ requiredMcpServers:
14
+ - "token-pilot"
15
+ color: red
13
16
  ---
14
17
 
15
18
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -13,8 +13,11 @@ tools:
13
13
  - Edit
14
14
  - Bash
15
15
  model: sonnet
16
- token_pilot_version: "0.34.3"
16
+ token_pilot_version: "0.35.0"
17
17
  token_pilot_body_hash: 269f2fe22ff4517c277d3f56ca67d8a5527b93290ab21079a83ba7af22c1b5a9
18
+ requiredMcpServers:
19
+ - "token-pilot"
20
+ color: yellow
18
21
  ---
19
22
 
20
23
  You are a token-pilot agent (`tp-<name>`). Your defining contract:
@@ -17,7 +17,7 @@
17
17
  * Everything else passes through untouched — a real project root like
18
18
  * `/home/user/my-project` or `./subdir` goes to startServer as before.
19
19
  */
20
- export declare const KNOWN_COMMANDS: readonly ["hook-read", "hook-edit", "hook-pre-bash", "hook-pre-grep", "hook-pre-task", "hook-post-bash", "hook-post-task", "hook-session-start", "install-hook", "uninstall-hook", "install-ast-index", "doctor", "bless-agents", "unbless-agents", "install-agents", "uninstall-agents", "stats", "tool-audit", "save-doc", "list-docs", "init", "migrate-hooks", "errors", "--version", "-v", "--help", "-h"];
20
+ export declare const KNOWN_COMMANDS: readonly ["hook-read", "hook-edit", "hook-pre-bash", "hook-pre-grep", "hook-pre-task", "hook-post-bash", "hook-post-task", "hook-session-start", "hook-bootstrap", "install-hook", "uninstall-hook", "install-ast-index", "doctor", "bless-agents", "unbless-agents", "install-agents", "uninstall-agents", "stats", "tool-audit", "save-doc", "list-docs", "init", "migrate-hooks", "errors", "--version", "-v", "--help", "-h"];
21
21
  export interface TypoGuardResult {
22
22
  kind: "pass-through" | "typo";
23
23
  suggestion?: string;
@@ -32,6 +32,9 @@ export const KNOWN_COMMANDS = [
32
32
  "hook-post-bash",
33
33
  "hook-post-task",
34
34
  "hook-session-start",
35
+ // v0.35.0 — one-shot project setup hook (uses Claude Code's
36
+ // undocumented `once: true` SessionStart flag).
37
+ "hook-bootstrap",
35
38
  "install-hook",
36
39
  "uninstall-hook",
37
40
  "install-ast-index",
@@ -67,11 +67,21 @@ export function isStaleTokenPilotHookCommand(cmd) {
67
67
  * reverts: shell-expanded `command` remains the safe, portable form
68
68
  * for every Claude Code version we know of. When Claude Code docs
69
69
  * confirm the env-expansion rules for `args`, we can revisit.
70
+ *
71
+ * v0.35.0 — `extras` lets callers attach undocumented Claude Code
72
+ * fields surfaced by reverse-engineering the 2.1.87 source:
73
+ * - `async: true` — non-blocking; ideal for telemetry-only
74
+ * PostToolUse hooks that just log events
75
+ * - `once: true` — runs exactly once per project, auto-removes
76
+ * on success; for first-session bootstrap
77
+ * - `statusMessage` — UI hint while the hook runs
78
+ * All are additive and ignored by older Claude Code versions.
70
79
  */
71
- function hookEntry(action, options) {
80
+ function hookEntry(action, options, extras = {}) {
72
81
  return {
73
82
  type: "command",
74
83
  command: buildHookCommand(action, options),
84
+ ...extras,
75
85
  };
76
86
  }
77
87
  function createHookConfig(options) {
@@ -104,6 +114,15 @@ function createHookConfig(options) {
104
114
  },
105
115
  ],
106
116
  SessionStart: [
117
+ {
118
+ hooks: [
119
+ // v0.35.0 — once-only bootstrap (project setup hints)
120
+ hookEntry("hook-bootstrap", options, {
121
+ once: true,
122
+ statusMessage: "Bootstrapping token-pilot...",
123
+ }),
124
+ ],
125
+ },
107
126
  {
108
127
  hooks: [hookEntry("hook-session-start", options)],
109
128
  },
@@ -111,11 +130,12 @@ function createHookConfig(options) {
111
130
  PostToolUse: [
112
131
  {
113
132
  matcher: "Bash",
114
- hooks: [hookEntry("hook-post-bash", options)],
133
+ // v0.35.0 — async: true keeps telemetry off the hot path
134
+ hooks: [hookEntry("hook-post-bash", options, { async: true })],
115
135
  },
116
136
  {
117
137
  matcher: "Task",
118
- hooks: [hookEntry("hook-post-task", options)],
138
+ hooks: [hookEntry("hook-post-task", options, { async: true })],
119
139
  },
120
140
  ],
121
141
  },
@@ -264,10 +264,21 @@ export async function handleSessionStart(opts) {
264
264
  catch {
265
265
  /* silent — telemetry nudge is strictly opt-in */
266
266
  }
267
+ // v0.35.0 — watchPaths is an undocumented SessionStart return key
268
+ // (surfaced by reverse-engineering @anthropic-ai/claude-code@2.1.87).
269
+ // Claude Code watches these paths and re-fires FileChanged so a
270
+ // second active session picks up new snapshots / errors emitted by
271
+ // another worker without manual polling. Additive — older Claude
272
+ // Code versions ignore the key.
273
+ const watchPaths = [
274
+ ".token-pilot/snapshots/latest.md",
275
+ ".token-pilot/hook-events.jsonl",
276
+ ];
267
277
  const output = {
268
278
  hookSpecificOutput: {
269
279
  hookEventName: "SessionStart",
270
280
  additionalContext: message,
281
+ watchPaths,
271
282
  },
272
283
  };
273
284
  return JSON.stringify(output);
package/dist/index.js CHANGED
@@ -251,6 +251,57 @@ export async function main(cliArgs = process.argv.slice(2)) {
251
251
  });
252
252
  return;
253
253
  }
254
+ case "hook-bootstrap": {
255
+ // v0.35.0 — fires ONCE per project via Claude Code's undocumented
256
+ // `once: true` SessionStart flag. Self-removes after the first
257
+ // run, so steps must be idempotent (re-running cannot hurt).
258
+ // Stays silent on success; only emits hints when something is
259
+ // missing. Always exits 0 — the very first session must never
260
+ // be blocked by a bootstrap hint.
261
+ await runHookEntryPoint({ hook: "hook-bootstrap" }, async () => {
262
+ const cwd = process.cwd();
263
+ const hints = [];
264
+ // Detect installed tp-* agents (project-level OR user-level).
265
+ try {
266
+ const { readdirSync, existsSync } = await import("node:fs");
267
+ const projAgents = resolve(cwd, ".claude", "agents");
268
+ const userAgents = resolve(homedir(), ".claude", "agents");
269
+ let total = 0;
270
+ for (const dir of [projAgents, userAgents]) {
271
+ if (existsSync(dir)) {
272
+ total += readdirSync(dir).filter((f) => f.startsWith("tp-") && f.endsWith(".md")).length;
273
+ }
274
+ }
275
+ if (total === 0) {
276
+ hints.push("no tp-* agents installed — run `npx token-pilot install-agents --scope=project` to enable the 25-agent toolkit");
277
+ }
278
+ }
279
+ catch {
280
+ /* skip silently */
281
+ }
282
+ // Detect ast-index binary availability.
283
+ try {
284
+ const { findBinary } = await import("./ast-index/binary-manager.js");
285
+ const status = await findBinary();
286
+ if (!status.available) {
287
+ hints.push("ast-index binary missing — run `npx token-pilot install-ast-index` to unlock find_usages / outline / read_symbol");
288
+ }
289
+ }
290
+ catch {
291
+ /* skip silently */
292
+ }
293
+ if (hints.length > 0) {
294
+ const message = `[token-pilot] bootstrap notes:\n - ${hints.join("\n - ")}`;
295
+ process.stdout.write(JSON.stringify({
296
+ hookSpecificOutput: {
297
+ hookEventName: "SessionStart",
298
+ additionalContext: message,
299
+ },
300
+ }));
301
+ }
302
+ });
303
+ return;
304
+ }
254
305
  case "hook-session-start": {
255
306
  await runHookEntryPoint({ hook: "hook-session-start" }, async () => {
256
307
  const cfg = await loadConfig(process.cwd());
@@ -757,6 +808,32 @@ async function runHookReadDispatchImpl(filePathArg, mode, denyThreshold, project
757
808
  tier: pipelineResult.tier,
758
809
  });
759
810
  await writeEvent("denied", Math.ceil(message.length / 4));
811
+ // v0.35.0 — `updatedInput` rewrite. Claude Code's undocumented
812
+ // PreToolUse return key (surfaced from @anthropic-ai/claude-code@2.1.87
813
+ // source) lets a hook silently transform the tool_input instead of
814
+ // blocking. When TOKEN_PILOT_HOOK_REWRITE=1 is set we bound the Read
815
+ // to its first ~200 lines so the model sees a truncated file rather
816
+ // than a deny + suggestion. The structural summary still rides in
817
+ // `additionalContext`, so the model gets both views in one round.
818
+ //
819
+ // Default OFF — the field is undocumented and changes user-visible
820
+ // behaviour. Opt-in only.
821
+ if (process.env.TOKEN_PILOT_HOOK_REWRITE === "1") {
822
+ return JSON.stringify({
823
+ hookSpecificOutput: {
824
+ hookEventName: "PreToolUse",
825
+ permissionDecision: "allow",
826
+ updatedInput: {
827
+ file_path: filePath,
828
+ offset: 1,
829
+ limit: 200,
830
+ },
831
+ additionalContext: `[token-pilot] Read on ${filePath} was rewritten to lines 1-200 ` +
832
+ `(file has ${lineCount} lines). For full structure use mcp__token-pilot__smart_read(${filePath}).\n\n` +
833
+ message,
834
+ },
835
+ });
836
+ }
760
837
  return JSON.stringify({
761
838
  hookSpecificOutput: {
762
839
  hookEventName: "PreToolUse",
package/hooks/hooks.json CHANGED
@@ -57,6 +57,16 @@
57
57
  }
58
58
  ],
59
59
  "SessionStart": [
60
+ {
61
+ "hooks": [
62
+ {
63
+ "type": "command",
64
+ "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-bootstrap",
65
+ "once": true,
66
+ "statusMessage": "Bootstrapping token-pilot..."
67
+ }
68
+ ]
69
+ },
60
70
  {
61
71
  "hooks": [
62
72
  {
@@ -72,7 +82,8 @@
72
82
  "hooks": [
73
83
  {
74
84
  "type": "command",
75
- "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-post-bash"
85
+ "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-post-bash",
86
+ "async": true
76
87
  }
77
88
  ]
78
89
  },
@@ -81,7 +92,8 @@
81
92
  "hooks": [
82
93
  {
83
94
  "type": "command",
84
- "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-post-task"
95
+ "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-post-task",
96
+ "async": true
85
97
  }
86
98
  ]
87
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "token-pilot",
3
- "version": "0.34.3",
3
+ "version": "0.35.0",
4
4
  "description": "Save up to 80% tokens when AI reads code — MCP server for token-efficient code navigation, AST-aware structural reading instead of dumping full files into context window",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",