token-pilot 0.19.0 → 0.19.2
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.
- package/CHANGELOG.md +607 -575
- package/README.md +1 -1
- package/dist/ast-index/binary-manager.d.ts +3 -3
- package/dist/ast-index/binary-manager.js +74 -11
- package/dist/ast-index/client.d.ts +5 -1
- package/dist/ast-index/client.js +9 -2
- package/dist/handlers/session-snapshot.d.ts +1 -0
- package/dist/handlers/session-snapshot.js +6 -0
- package/dist/hooks/installer.d.ts +7 -1
- package/dist/hooks/installer.js +63 -33
- package/dist/index.js +38 -21
- package/dist/server/tool-definitions.d.ts +27 -0
- package/dist/server/tool-definitions.js +2 -1
- package/package.json +87 -87
package/README.md
CHANGED
|
@@ -215,7 +215,7 @@ For more control, you can add rules to your project:
|
|
|
215
215
|
|
|
216
216
|
| Tool | Description |
|
|
217
217
|
|------|-------------|
|
|
218
|
-
| `session_snapshot` | Capture session state as a compact markdown block (<200 tokens): goal, confirmed facts, relevant files, blockers, next step.
|
|
218
|
+
| `session_snapshot` | Capture session state as a compact markdown block (<200 tokens): goal, decisions (with reasoning), confirmed facts, relevant files, blockers, next step. Decisions field prevents revisiting rejected approaches after compaction. |
|
|
219
219
|
| `session_analytics` | Token savings report: total saved, per-tool breakdown, top files, per-intent breakdown, decision insights, policy advisories. |
|
|
220
220
|
|
|
221
221
|
## CLI Commands
|
|
@@ -2,14 +2,14 @@ export interface BinaryStatus {
|
|
|
2
2
|
available: boolean;
|
|
3
3
|
path: string;
|
|
4
4
|
version: string | null;
|
|
5
|
-
source: 'system' | 'managed' | 'none';
|
|
5
|
+
source: 'system' | 'npm' | 'managed' | 'none';
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Find ast-index binary:
|
|
8
|
+
* Find ast-index binary: config → system PATH → npm global → managed install.
|
|
9
9
|
*/
|
|
10
10
|
export declare function findBinary(configPath?: string | null): Promise<BinaryStatus>;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Install ast-index: tries npm global first (all platforms), falls back to GitHub download.
|
|
13
13
|
*/
|
|
14
14
|
export declare function installBinary(onProgress?: (msg: string) => void): Promise<BinaryStatus>;
|
|
15
15
|
/**
|
|
@@ -12,7 +12,7 @@ const REPO = 'defendend/Claude-ast-index-search';
|
|
|
12
12
|
const BINARY_NAME = platform() === 'win32' ? 'ast-index.exe' : 'ast-index';
|
|
13
13
|
const INSTALL_DIR = resolve(homedir(), '.token-pilot', 'bin');
|
|
14
14
|
/**
|
|
15
|
-
* Find ast-index binary:
|
|
15
|
+
* Find ast-index binary: config → system PATH → npm global → managed install.
|
|
16
16
|
*/
|
|
17
17
|
export async function findBinary(configPath) {
|
|
18
18
|
// 1. Config override
|
|
@@ -28,7 +28,15 @@ export async function findBinary(configPath) {
|
|
|
28
28
|
const version = await getBinaryVersion(systemPath);
|
|
29
29
|
return { available: true, path: systemPath, version, source: 'system' };
|
|
30
30
|
}
|
|
31
|
-
// 3.
|
|
31
|
+
// 3. npm global install (@ast-index/cli)
|
|
32
|
+
const npmPath = await findViaNpmBin();
|
|
33
|
+
if (npmPath) {
|
|
34
|
+
const version = await getBinaryVersion(npmPath);
|
|
35
|
+
if (version) {
|
|
36
|
+
return { available: true, path: npmPath, version, source: 'npm' };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// 4. Managed install (GitHub download)
|
|
32
40
|
const managedPath = resolve(INSTALL_DIR, BINARY_NAME);
|
|
33
41
|
const version = await getBinaryVersion(managedPath);
|
|
34
42
|
if (version) {
|
|
@@ -37,24 +45,53 @@ export async function findBinary(configPath) {
|
|
|
37
45
|
return { available: false, path: '', version: null, source: 'none' };
|
|
38
46
|
}
|
|
39
47
|
/**
|
|
40
|
-
*
|
|
48
|
+
* Install ast-index: tries npm global first (all platforms), falls back to GitHub download.
|
|
41
49
|
*/
|
|
42
50
|
export async function installBinary(onProgress) {
|
|
43
51
|
const log = onProgress ?? (() => { });
|
|
52
|
+
// Try npm first — simpler, handles all platforms including Windows
|
|
53
|
+
try {
|
|
54
|
+
return await installViaNpm(log);
|
|
55
|
+
}
|
|
56
|
+
catch (npmErr) {
|
|
57
|
+
log(`npm install failed (${npmErr instanceof Error ? npmErr.message : npmErr}), trying GitHub download...`);
|
|
58
|
+
}
|
|
59
|
+
// GitHub download fallback
|
|
60
|
+
return installViaNpmFallback(log);
|
|
61
|
+
}
|
|
62
|
+
async function installViaNpm(onProgress) {
|
|
63
|
+
onProgress('Installing @ast-index/cli via npm...');
|
|
64
|
+
await new Promise((resolve, reject) => {
|
|
65
|
+
execFile('npm', ['install', '-g', '@ast-index/cli'], { timeout: 120_000 }, (err, _stdout, stderr) => {
|
|
66
|
+
if (err)
|
|
67
|
+
reject(new Error(stderr.trim() || err.message));
|
|
68
|
+
else
|
|
69
|
+
resolve();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
const binPath = await findViaNpmBin();
|
|
73
|
+
if (!binPath) {
|
|
74
|
+
throw new Error('@ast-index/cli installed but binary not found in npm prefix');
|
|
75
|
+
}
|
|
76
|
+
const version = await getBinaryVersion(binPath);
|
|
77
|
+
onProgress(`Installed ast-index ${version} via npm at ${binPath}`);
|
|
78
|
+
return { available: true, path: binPath, version, source: 'npm' };
|
|
79
|
+
}
|
|
80
|
+
async function installViaNpmFallback(onProgress) {
|
|
44
81
|
// Determine platform/arch
|
|
45
82
|
const plat = getPlatform();
|
|
46
83
|
const ar = getArch();
|
|
47
84
|
if (!plat || !ar) {
|
|
48
85
|
throw new Error(`Unsupported platform: ${platform()} ${arch()}`);
|
|
49
86
|
}
|
|
50
|
-
|
|
87
|
+
onProgress('Fetching latest release info...');
|
|
51
88
|
const release = await fetchLatestRelease();
|
|
52
89
|
const assetName = buildAssetName(release.tag, plat, ar);
|
|
53
90
|
const asset = release.assets.find(a => a.name === assetName);
|
|
54
91
|
if (!asset) {
|
|
55
92
|
throw new Error(`No binary found for ${plat}-${ar}. Available: ${release.assets.map(a => a.name).join(', ')}`);
|
|
56
93
|
}
|
|
57
|
-
|
|
94
|
+
onProgress(`Downloading ${asset.name} (${(asset.size / 1024 / 1024).toFixed(1)}MB)...`);
|
|
58
95
|
await mkdir(INSTALL_DIR, { recursive: true });
|
|
59
96
|
const tmpPath = resolve(INSTALL_DIR, `${BINARY_NAME}.tmp`);
|
|
60
97
|
const finalPath = resolve(INSTALL_DIR, BINARY_NAME);
|
|
@@ -62,19 +99,16 @@ export async function installBinary(onProgress) {
|
|
|
62
99
|
if (assetName.endsWith('.tar.gz')) {
|
|
63
100
|
await downloadAndExtractTarGz(asset.url, INSTALL_DIR, BINARY_NAME);
|
|
64
101
|
}
|
|
65
|
-
else
|
|
66
|
-
// For Windows, download zip and extract
|
|
102
|
+
else {
|
|
67
103
|
await downloadFile(asset.url, tmpPath);
|
|
68
|
-
|
|
69
|
-
throw new Error('ZIP extraction not yet supported. Please install ast-index manually on Windows.');
|
|
104
|
+
throw new Error('ZIP extraction not yet supported. Please use: npm install -g @ast-index/cli');
|
|
70
105
|
}
|
|
71
106
|
await chmod(finalPath, 0o755);
|
|
72
107
|
const version = await getBinaryVersion(finalPath);
|
|
73
|
-
|
|
108
|
+
onProgress(`Installed ast-index ${version} to ${finalPath}`);
|
|
74
109
|
return { available: true, path: finalPath, version, source: 'managed' };
|
|
75
110
|
}
|
|
76
111
|
catch (err) {
|
|
77
|
-
// Cleanup on failure
|
|
78
112
|
try {
|
|
79
113
|
await rm(tmpPath, { force: true });
|
|
80
114
|
}
|
|
@@ -130,6 +164,35 @@ export function isNewerVersion(current, latest) {
|
|
|
130
164
|
return false;
|
|
131
165
|
}
|
|
132
166
|
// --- Internal helpers ---
|
|
167
|
+
/**
|
|
168
|
+
* Find ast-index binary installed via `npm install -g @ast-index/cli`.
|
|
169
|
+
* Checks the npm global prefix bin directory.
|
|
170
|
+
*/
|
|
171
|
+
async function findViaNpmBin() {
|
|
172
|
+
try {
|
|
173
|
+
const prefix = await new Promise((resolve, reject) => {
|
|
174
|
+
execFile('npm', ['config', 'get', 'prefix'], { timeout: 3000 }, (err, stdout) => {
|
|
175
|
+
if (err)
|
|
176
|
+
reject(err);
|
|
177
|
+
else
|
|
178
|
+
resolve(stdout.trim());
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
// Unix: <prefix>/bin/ast-index | Windows: <prefix>\ast-index.exe or <prefix>\bin\ast-index.exe
|
|
182
|
+
const candidates = platform() === 'win32'
|
|
183
|
+
? [resolve(prefix, BINARY_NAME), resolve(prefix, 'bin', BINARY_NAME)]
|
|
184
|
+
: [resolve(prefix, 'bin', BINARY_NAME)];
|
|
185
|
+
for (const candidate of candidates) {
|
|
186
|
+
try {
|
|
187
|
+
await access(candidate);
|
|
188
|
+
return candidate;
|
|
189
|
+
}
|
|
190
|
+
catch { }
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch { }
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
133
196
|
function getPlatform() {
|
|
134
197
|
switch (platform()) {
|
|
135
198
|
case 'darwin': return 'darwin';
|
|
@@ -27,12 +27,16 @@ export declare class AstIndexClient {
|
|
|
27
27
|
symbol(name: string): Promise<AstIndexSymbolDetail | null>;
|
|
28
28
|
search(query: string, options?: {
|
|
29
29
|
inFile?: string;
|
|
30
|
+
type?: string;
|
|
30
31
|
maxResults?: number;
|
|
31
32
|
fuzzy?: boolean;
|
|
32
33
|
}): Promise<AstIndexSearchResult[]>;
|
|
33
34
|
usages(symbolName: string): Promise<AstIndexUsageResult[]>;
|
|
34
35
|
implementations(name: string): Promise<AstIndexImplementation[]>;
|
|
35
|
-
hierarchy(name: string
|
|
36
|
+
hierarchy(name: string, options?: {
|
|
37
|
+
inFile?: string;
|
|
38
|
+
module?: string;
|
|
39
|
+
}): Promise<AstIndexHierarchyNode | null>;
|
|
36
40
|
stats(): Promise<string | null>;
|
|
37
41
|
listFiles(): Promise<string[]>;
|
|
38
42
|
refs(symbolName: string, limit?: number): Promise<AstIndexRefsResponse>;
|
package/dist/ast-index/client.js
CHANGED
|
@@ -223,6 +223,8 @@ export class AstIndexClient {
|
|
|
223
223
|
const args = ['search', query, '--format', 'json'];
|
|
224
224
|
if (options?.inFile)
|
|
225
225
|
args.push('--in-file', options.inFile);
|
|
226
|
+
if (options?.type)
|
|
227
|
+
args.push('--type', options.type);
|
|
226
228
|
if (options?.maxResults)
|
|
227
229
|
args.push('--limit', String(options.maxResults));
|
|
228
230
|
if (options?.fuzzy)
|
|
@@ -295,10 +297,15 @@ export class AstIndexClient {
|
|
|
295
297
|
return [];
|
|
296
298
|
}
|
|
297
299
|
}
|
|
298
|
-
async hierarchy(name) {
|
|
300
|
+
async hierarchy(name, options) {
|
|
299
301
|
await this.ensureIndex();
|
|
300
302
|
try {
|
|
301
|
-
const
|
|
303
|
+
const args = ['hierarchy', name, '--format', 'json'];
|
|
304
|
+
if (options?.inFile)
|
|
305
|
+
args.push('--in-file', options.inFile);
|
|
306
|
+
if (options?.module)
|
|
307
|
+
args.push('--module', options.module);
|
|
308
|
+
const result = await this.exec(args);
|
|
302
309
|
try {
|
|
303
310
|
return JSON.parse(result);
|
|
304
311
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export function handleSessionSnapshot(args) {
|
|
2
2
|
const lines = ['## Session State'];
|
|
3
3
|
lines.push(`**Goal:** ${args.goal}`);
|
|
4
|
+
if (args.decisions?.length) {
|
|
5
|
+
lines.push('**Decisions:**');
|
|
6
|
+
for (const item of args.decisions) {
|
|
7
|
+
lines.push(`- ${item}`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
4
10
|
if (args.confirmed?.length) {
|
|
5
11
|
lines.push('**Confirmed:**');
|
|
6
12
|
for (const item of args.confirmed) {
|
|
@@ -8,11 +8,17 @@ export interface HookUninstallResult {
|
|
|
8
8
|
fatal: boolean;
|
|
9
9
|
message: string;
|
|
10
10
|
}
|
|
11
|
+
export interface HookInstallOptions {
|
|
12
|
+
/** Absolute path to the entry script (dist/index.js). When provided, hooks use absolute paths instead of bare "token-pilot". */
|
|
13
|
+
scriptPath?: string;
|
|
14
|
+
/** Absolute path to the node binary. Defaults to process.execPath. */
|
|
15
|
+
nodeExecPath?: string;
|
|
16
|
+
}
|
|
11
17
|
/**
|
|
12
18
|
* Install Token Pilot hook into Claude Code settings.
|
|
13
19
|
* Creates or updates .claude/settings.json with PreToolUse hook.
|
|
14
20
|
*/
|
|
15
|
-
export declare function installHook(projectRoot: string): Promise<HookInstallResult>;
|
|
21
|
+
export declare function installHook(projectRoot: string, options?: HookInstallOptions): Promise<HookInstallResult>;
|
|
16
22
|
/**
|
|
17
23
|
* Remove Token Pilot hook from Claude Code settings.
|
|
18
24
|
*/
|
package/dist/hooks/installer.js
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
1
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
2
|
import { resolve, dirname } from 'node:path';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Build hook command that works in any shell (/bin/sh, bash, etc.)
|
|
5
|
+
* Uses absolute paths to node + script to avoid PATH/nvm issues.
|
|
6
|
+
* Falls back to bare "token-pilot" only for manual CLI installs.
|
|
7
|
+
*/
|
|
8
|
+
function buildHookCommand(action, options) {
|
|
9
|
+
if (options?.scriptPath) {
|
|
10
|
+
const node = options.nodeExecPath || process.execPath;
|
|
11
|
+
return `${node} ${options.scriptPath} ${action}`;
|
|
12
|
+
}
|
|
13
|
+
return `token-pilot ${action}`;
|
|
14
|
+
}
|
|
15
|
+
function createHookConfig(options) {
|
|
16
|
+
return {
|
|
17
|
+
hooks: {
|
|
18
|
+
PreToolUse: [
|
|
19
|
+
{
|
|
20
|
+
matcher: "Read",
|
|
21
|
+
hooks: [
|
|
22
|
+
{
|
|
23
|
+
type: "command",
|
|
24
|
+
command: buildHookCommand('hook-read', options),
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
matcher: "Edit",
|
|
30
|
+
hooks: [
|
|
31
|
+
{
|
|
32
|
+
type: "command",
|
|
33
|
+
command: buildHookCommand('hook-edit', options),
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
27
41
|
/**
|
|
28
42
|
* Install Token Pilot hook into Claude Code settings.
|
|
29
43
|
* Creates or updates .claude/settings.json with PreToolUse hook.
|
|
30
44
|
*/
|
|
31
|
-
export async function installHook(projectRoot) {
|
|
45
|
+
export async function installHook(projectRoot, options) {
|
|
46
|
+
// Skip auto-install when running as a Claude Code plugin —
|
|
47
|
+
// the plugin system already registers hooks via .claude-plugin/hooks/hooks.json
|
|
48
|
+
if (process.env.CLAUDE_PLUGIN_ROOT) {
|
|
49
|
+
return { installed: false, fatal: false, message: 'Running as plugin — hooks registered via plugin system.' };
|
|
50
|
+
}
|
|
32
51
|
const settingsPath = resolve(projectRoot, '.claude', 'settings.json');
|
|
52
|
+
const hookConfig = createHookConfig(options);
|
|
33
53
|
try {
|
|
34
54
|
// Ensure .claude dir exists
|
|
35
55
|
await mkdir(dirname(settingsPath), { recursive: true });
|
|
@@ -63,16 +83,26 @@ export async function installHook(projectRoot) {
|
|
|
63
83
|
const existingHooks = settings.hooks?.PreToolUse;
|
|
64
84
|
const isTokenPilotHook = (h) => h.hooks?.some((hook) => hook.command?.includes('token-pilot'));
|
|
65
85
|
if (Array.isArray(existingHooks)) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
// Remove old broken hooks (bare "token-pilot" without absolute path)
|
|
87
|
+
// and replace with working ones using absolute paths
|
|
88
|
+
const oldBrokenHooks = existingHooks.filter((h) => isTokenPilotHook(h) && h.hooks?.some((hook) => hook.command?.match(/^token-pilot\s/) // bare command without path
|
|
89
|
+
));
|
|
90
|
+
if (oldBrokenHooks.length > 0 && options?.scriptPath) {
|
|
91
|
+
// Remove old broken hooks, will re-add with absolute paths below
|
|
92
|
+
settings.hooks.PreToolUse = existingHooks.filter((h) => !isTokenPilotHook(h));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const hasRead = existingHooks.some((h) => h.matcher === 'Read' && isTokenPilotHook(h));
|
|
96
|
+
const hasEdit = existingHooks.some((h) => h.matcher === 'Edit' && isTokenPilotHook(h));
|
|
97
|
+
if (hasRead && hasEdit) {
|
|
98
|
+
return { installed: false, fatal: false, message: 'Token Pilot hooks already installed.' };
|
|
99
|
+
}
|
|
70
100
|
}
|
|
71
101
|
// Add missing hooks
|
|
72
|
-
for (const hookDef of
|
|
73
|
-
const exists =
|
|
102
|
+
for (const hookDef of hookConfig.hooks.PreToolUse) {
|
|
103
|
+
const exists = settings.hooks.PreToolUse.some((h) => h.matcher === hookDef.matcher && isTokenPilotHook(h));
|
|
74
104
|
if (!exists) {
|
|
75
|
-
|
|
105
|
+
settings.hooks.PreToolUse.push(hookDef);
|
|
76
106
|
}
|
|
77
107
|
}
|
|
78
108
|
}
|
|
@@ -80,7 +110,7 @@ export async function installHook(projectRoot) {
|
|
|
80
110
|
// Create hooks section
|
|
81
111
|
if (!settings.hooks)
|
|
82
112
|
settings.hooks = {};
|
|
83
|
-
settings.hooks.PreToolUse =
|
|
113
|
+
settings.hooks.PreToolUse = hookConfig.hooks.PreToolUse;
|
|
84
114
|
}
|
|
85
115
|
await writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
86
116
|
return {
|
package/dist/index.js
CHANGED
|
@@ -122,7 +122,16 @@ export async function startServer(cliArgs = process.argv.slice(2)) {
|
|
|
122
122
|
const binaryStatus = await findBinary(config.astIndex.binaryPath);
|
|
123
123
|
checkAllUpdates(config, binaryStatus).catch(() => { });
|
|
124
124
|
// Auto-install PreToolUse hook (non-blocking, Claude Code only)
|
|
125
|
-
|
|
125
|
+
// Uses absolute paths to node + script so hooks work in /bin/sh (nvm, npx, etc.)
|
|
126
|
+
let hookOptions;
|
|
127
|
+
try {
|
|
128
|
+
const rawPath = fileURLToPath(new URL('./index.js', import.meta.url));
|
|
129
|
+
hookOptions = { scriptPath: realpathSync(rawPath), nodeExecPath: process.execPath };
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// Can't resolve script path (e.g. running from src/ in tests) — fall back to bare command
|
|
133
|
+
}
|
|
134
|
+
installHook(projectRoot, hookOptions).then(result => {
|
|
126
135
|
if (result.installed) {
|
|
127
136
|
console.error(`[token-pilot] hook auto-installed: ${result.message}`);
|
|
128
137
|
}
|
|
@@ -239,7 +248,15 @@ export function handleHookEdit() {
|
|
|
239
248
|
process.exit(0);
|
|
240
249
|
}
|
|
241
250
|
export async function handleInstallHook(projectRoot) {
|
|
242
|
-
|
|
251
|
+
let hookOptions;
|
|
252
|
+
try {
|
|
253
|
+
const rawPath = fileURLToPath(new URL('./index.js', import.meta.url));
|
|
254
|
+
hookOptions = { scriptPath: realpathSync(rawPath), nodeExecPath: process.execPath };
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
// Fall back to bare command
|
|
258
|
+
}
|
|
259
|
+
const result = await installHook(projectRoot, hookOptions);
|
|
243
260
|
console.log(result.message);
|
|
244
261
|
process.exit(result.fatal ? 1 : 0);
|
|
245
262
|
}
|
|
@@ -443,25 +460,25 @@ export async function checkAllUpdates(config, binaryStatus) {
|
|
|
443
460
|
}
|
|
444
461
|
}
|
|
445
462
|
export function printHelp() {
|
|
446
|
-
console.log(`token-pilot v${getVersion()} — MCP server for token-efficient code reading
|
|
447
|
-
|
|
448
|
-
Usage:
|
|
449
|
-
token-pilot [project-root] Start MCP server (default: cwd)
|
|
450
|
-
token-pilot init [dir] Create .mcp.json with token-pilot + context-mode
|
|
451
|
-
token-pilot install-hook [root] Install PreToolUse hook (Claude Code only)
|
|
452
|
-
token-pilot uninstall-hook [root] Remove PreToolUse hook
|
|
453
|
-
token-pilot install-ast-index Download ast-index binary (auto on first run)
|
|
454
|
-
token-pilot doctor Run diagnostics (check ast-index, config, updates)
|
|
455
|
-
token-pilot --version Show version
|
|
456
|
-
token-pilot --help Show this help
|
|
457
|
-
|
|
458
|
-
Quick start:
|
|
459
|
-
npx token-pilot init Setup .mcp.json (token-pilot + context-mode)
|
|
460
|
-
|
|
461
|
-
MCP Tools (18):
|
|
462
|
-
smart_read, read_symbol, read_range, read_diff, read_for_edit, smart_read_many,
|
|
463
|
-
find_usages, find_unused, related_files, outline, project_overview, session_analytics,
|
|
464
|
-
code_audit, module_info, smart_diff, explore_area, smart_log, test_summary
|
|
463
|
+
console.log(`token-pilot v${getVersion()} — MCP server for token-efficient code reading
|
|
464
|
+
|
|
465
|
+
Usage:
|
|
466
|
+
token-pilot [project-root] Start MCP server (default: cwd)
|
|
467
|
+
token-pilot init [dir] Create .mcp.json with token-pilot + context-mode
|
|
468
|
+
token-pilot install-hook [root] Install PreToolUse hook (Claude Code only)
|
|
469
|
+
token-pilot uninstall-hook [root] Remove PreToolUse hook
|
|
470
|
+
token-pilot install-ast-index Download ast-index binary (auto on first run)
|
|
471
|
+
token-pilot doctor Run diagnostics (check ast-index, config, updates)
|
|
472
|
+
token-pilot --version Show version
|
|
473
|
+
token-pilot --help Show this help
|
|
474
|
+
|
|
475
|
+
Quick start:
|
|
476
|
+
npx token-pilot init Setup .mcp.json (token-pilot + context-mode)
|
|
477
|
+
|
|
478
|
+
MCP Tools (18):
|
|
479
|
+
smart_read, read_symbol, read_range, read_diff, read_for_edit, smart_read_many,
|
|
480
|
+
find_usages, find_unused, related_files, outline, project_overview, session_analytics,
|
|
481
|
+
code_audit, module_info, smart_diff, explore_area, smart_log, test_summary
|
|
465
482
|
`);
|
|
466
483
|
process.exit(0);
|
|
467
484
|
}
|
|
@@ -70,6 +70,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
70
70
|
runner?: undefined;
|
|
71
71
|
timeout?: undefined;
|
|
72
72
|
goal?: undefined;
|
|
73
|
+
decisions?: undefined;
|
|
73
74
|
confirmed?: undefined;
|
|
74
75
|
files?: undefined;
|
|
75
76
|
blocked?: undefined;
|
|
@@ -144,6 +145,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
144
145
|
runner?: undefined;
|
|
145
146
|
timeout?: undefined;
|
|
146
147
|
goal?: undefined;
|
|
148
|
+
decisions?: undefined;
|
|
147
149
|
confirmed?: undefined;
|
|
148
150
|
files?: undefined;
|
|
149
151
|
blocked?: undefined;
|
|
@@ -218,6 +220,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
218
220
|
runner?: undefined;
|
|
219
221
|
timeout?: undefined;
|
|
220
222
|
goal?: undefined;
|
|
223
|
+
decisions?: undefined;
|
|
221
224
|
confirmed?: undefined;
|
|
222
225
|
files?: undefined;
|
|
223
226
|
blocked?: undefined;
|
|
@@ -282,6 +285,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
282
285
|
runner?: undefined;
|
|
283
286
|
timeout?: undefined;
|
|
284
287
|
goal?: undefined;
|
|
288
|
+
decisions?: undefined;
|
|
285
289
|
confirmed?: undefined;
|
|
286
290
|
files?: undefined;
|
|
287
291
|
blocked?: undefined;
|
|
@@ -343,6 +347,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
343
347
|
runner?: undefined;
|
|
344
348
|
timeout?: undefined;
|
|
345
349
|
goal?: undefined;
|
|
350
|
+
decisions?: undefined;
|
|
346
351
|
confirmed?: undefined;
|
|
347
352
|
files?: undefined;
|
|
348
353
|
blocked?: undefined;
|
|
@@ -404,6 +409,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
404
409
|
runner?: undefined;
|
|
405
410
|
timeout?: undefined;
|
|
406
411
|
goal?: undefined;
|
|
412
|
+
decisions?: undefined;
|
|
407
413
|
confirmed?: undefined;
|
|
408
414
|
files?: undefined;
|
|
409
415
|
blocked?: undefined;
|
|
@@ -489,6 +495,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
489
495
|
runner?: undefined;
|
|
490
496
|
timeout?: undefined;
|
|
491
497
|
goal?: undefined;
|
|
498
|
+
decisions?: undefined;
|
|
492
499
|
confirmed?: undefined;
|
|
493
500
|
files?: undefined;
|
|
494
501
|
blocked?: undefined;
|
|
@@ -553,6 +560,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
553
560
|
runner?: undefined;
|
|
554
561
|
timeout?: undefined;
|
|
555
562
|
goal?: undefined;
|
|
563
|
+
decisions?: undefined;
|
|
556
564
|
confirmed?: undefined;
|
|
557
565
|
files?: undefined;
|
|
558
566
|
blocked?: undefined;
|
|
@@ -632,6 +640,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
632
640
|
runner?: undefined;
|
|
633
641
|
timeout?: undefined;
|
|
634
642
|
goal?: undefined;
|
|
643
|
+
decisions?: undefined;
|
|
635
644
|
confirmed?: undefined;
|
|
636
645
|
files?: undefined;
|
|
637
646
|
blocked?: undefined;
|
|
@@ -694,6 +703,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
694
703
|
runner?: undefined;
|
|
695
704
|
timeout?: undefined;
|
|
696
705
|
goal?: undefined;
|
|
706
|
+
decisions?: undefined;
|
|
697
707
|
confirmed?: undefined;
|
|
698
708
|
files?: undefined;
|
|
699
709
|
blocked?: undefined;
|
|
@@ -752,6 +762,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
752
762
|
runner?: undefined;
|
|
753
763
|
timeout?: undefined;
|
|
754
764
|
goal?: undefined;
|
|
765
|
+
decisions?: undefined;
|
|
755
766
|
confirmed?: undefined;
|
|
756
767
|
files?: undefined;
|
|
757
768
|
blocked?: undefined;
|
|
@@ -816,6 +827,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
816
827
|
runner?: undefined;
|
|
817
828
|
timeout?: undefined;
|
|
818
829
|
goal?: undefined;
|
|
830
|
+
decisions?: undefined;
|
|
819
831
|
confirmed?: undefined;
|
|
820
832
|
files?: undefined;
|
|
821
833
|
blocked?: undefined;
|
|
@@ -874,6 +886,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
874
886
|
runner?: undefined;
|
|
875
887
|
timeout?: undefined;
|
|
876
888
|
goal?: undefined;
|
|
889
|
+
decisions?: undefined;
|
|
877
890
|
confirmed?: undefined;
|
|
878
891
|
files?: undefined;
|
|
879
892
|
blocked?: undefined;
|
|
@@ -938,6 +951,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
938
951
|
runner?: undefined;
|
|
939
952
|
timeout?: undefined;
|
|
940
953
|
goal?: undefined;
|
|
954
|
+
decisions?: undefined;
|
|
941
955
|
confirmed?: undefined;
|
|
942
956
|
files?: undefined;
|
|
943
957
|
blocked?: undefined;
|
|
@@ -1009,6 +1023,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1009
1023
|
runner?: undefined;
|
|
1010
1024
|
timeout?: undefined;
|
|
1011
1025
|
goal?: undefined;
|
|
1026
|
+
decisions?: undefined;
|
|
1012
1027
|
confirmed?: undefined;
|
|
1013
1028
|
files?: undefined;
|
|
1014
1029
|
blocked?: undefined;
|
|
@@ -1071,6 +1086,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1071
1086
|
runner?: undefined;
|
|
1072
1087
|
timeout?: undefined;
|
|
1073
1088
|
goal?: undefined;
|
|
1089
|
+
decisions?: undefined;
|
|
1074
1090
|
confirmed?: undefined;
|
|
1075
1091
|
files?: undefined;
|
|
1076
1092
|
blocked?: undefined;
|
|
@@ -1136,6 +1152,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1136
1152
|
runner?: undefined;
|
|
1137
1153
|
timeout?: undefined;
|
|
1138
1154
|
goal?: undefined;
|
|
1155
|
+
decisions?: undefined;
|
|
1139
1156
|
confirmed?: undefined;
|
|
1140
1157
|
files?: undefined;
|
|
1141
1158
|
blocked?: undefined;
|
|
@@ -1201,6 +1218,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1201
1218
|
runner?: undefined;
|
|
1202
1219
|
timeout?: undefined;
|
|
1203
1220
|
goal?: undefined;
|
|
1221
|
+
decisions?: undefined;
|
|
1204
1222
|
confirmed?: undefined;
|
|
1205
1223
|
files?: undefined;
|
|
1206
1224
|
blocked?: undefined;
|
|
@@ -1265,6 +1283,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1265
1283
|
runner?: undefined;
|
|
1266
1284
|
timeout?: undefined;
|
|
1267
1285
|
goal?: undefined;
|
|
1286
|
+
decisions?: undefined;
|
|
1268
1287
|
confirmed?: undefined;
|
|
1269
1288
|
files?: undefined;
|
|
1270
1289
|
blocked?: undefined;
|
|
@@ -1330,6 +1349,7 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1330
1349
|
ref?: undefined;
|
|
1331
1350
|
count?: undefined;
|
|
1332
1351
|
goal?: undefined;
|
|
1352
|
+
decisions?: undefined;
|
|
1333
1353
|
confirmed?: undefined;
|
|
1334
1354
|
files?: undefined;
|
|
1335
1355
|
blocked?: undefined;
|
|
@@ -1347,6 +1367,13 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
1347
1367
|
type: string;
|
|
1348
1368
|
description: string;
|
|
1349
1369
|
};
|
|
1370
|
+
decisions: {
|
|
1371
|
+
type: string;
|
|
1372
|
+
items: {
|
|
1373
|
+
type: string;
|
|
1374
|
+
};
|
|
1375
|
+
description: string;
|
|
1376
|
+
};
|
|
1350
1377
|
confirmed: {
|
|
1351
1378
|
type: string;
|
|
1352
1379
|
items: {
|
|
@@ -29,7 +29,7 @@ export const MCP_INSTRUCTIONS = [
|
|
|
29
29
|
'17. Module architecture → module_info (deps, dependents, public API)',
|
|
30
30
|
'18. Read markdown/yaml/json/csv section → read_section (loads one heading/key/row-range, NOT the whole file)',
|
|
31
31
|
' - For editing sections: read_for_edit(path, section="Section Name")',
|
|
32
|
-
'19. Long session / before compaction → session_snapshot (capture goal, confirmed facts, files, next step as <200 token block)',
|
|
32
|
+
'19. Long session / before compaction → session_snapshot (capture goal, decisions, confirmed facts, files, next step as <200 token block)',
|
|
33
33
|
' - Budget-constrained? Use smart_read(max_tokens=N) to auto-downgrade output size',
|
|
34
34
|
'',
|
|
35
35
|
'USE DEFAULT TOOLS ONLY FOR: regex text search → Grep | exact raw content → Read | non-code configs → Read',
|
|
@@ -362,6 +362,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
362
362
|
type: 'object',
|
|
363
363
|
properties: {
|
|
364
364
|
goal: { type: 'string', description: 'Session goal — what and why' },
|
|
365
|
+
decisions: { type: 'array', items: { type: 'string' }, description: 'Key decisions made and why (e.g., "removed sysfee step — caused double counting"). Prevents revisiting rejected approaches.' },
|
|
365
366
|
confirmed: { type: 'array', items: { type: 'string' }, description: 'Established facts (what has been verified)' },
|
|
366
367
|
files: { type: 'array', items: { type: 'string' }, description: 'Relevant file paths' },
|
|
367
368
|
blocked: { type: 'string', description: 'Current blocker or obstacle' },
|