token-pilot 0.19.1 → 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 -580
- 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/hooks/installer.d.ts +7 -1
- package/dist/hooks/installer.js +63 -33
- package/dist/index.js +38 -21
- package/package.json +87 -87
|
@@ -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
|
}
|
|
@@ -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
|
}
|
package/package.json
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "token-pilot",
|
|
3
|
-
"version": "0.19.
|
|
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
|
-
"type": "module",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"token-pilot": "dist/index.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"dist/**/*.js",
|
|
12
|
-
"dist/**/*.d.ts",
|
|
13
|
-
"start.sh",
|
|
14
|
-
".claude-plugin/",
|
|
15
|
-
".mcp.json",
|
|
16
|
-
"skills/",
|
|
17
|
-
"README.md",
|
|
18
|
-
"CHANGELOG.md"
|
|
19
|
-
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"prebuild": "node --input-type=module -e \"import { rm } from 'node:fs/promises'; await rm('dist', { recursive: true, force: true });\"",
|
|
22
|
-
"build": "tsc",
|
|
23
|
-
"dev": "tsc --watch",
|
|
24
|
-
"start": "node dist/index.js",
|
|
25
|
-
"test": "vitest run",
|
|
26
|
-
"test:coverage": "vitest run --coverage",
|
|
27
|
-
"test:watch": "vitest",
|
|
28
|
-
"lint": "tsc --noEmit",
|
|
29
|
-
"prepublishOnly": "npm run build && node --input-type=module -e \"import { chmod } from 'node:fs/promises'; await chmod('dist/index.js', 0o755);\""
|
|
30
|
-
},
|
|
31
|
-
"keywords": [
|
|
32
|
-
"mcp",
|
|
33
|
-
"mcp-server",
|
|
34
|
-
"model-context-protocol",
|
|
35
|
-
"claude",
|
|
36
|
-
"claude-code",
|
|
37
|
-
"cursor",
|
|
38
|
-
"codex",
|
|
39
|
-
"cline",
|
|
40
|
-
"ai-coding",
|
|
41
|
-
"llm-tools",
|
|
42
|
-
"token-savings",
|
|
43
|
-
"token-reduction",
|
|
44
|
-
"context-window",
|
|
45
|
-
"context-optimization",
|
|
46
|
-
"ast",
|
|
47
|
-
"code-reading",
|
|
48
|
-
"code-navigation",
|
|
49
|
-
"smart-read",
|
|
50
|
-
"developer-tools",
|
|
51
|
-
"tree-sitter"
|
|
52
|
-
],
|
|
53
|
-
"repository": {
|
|
54
|
-
"type": "git",
|
|
55
|
-
"url": "git+https://github.com/Digital-Threads/token-pilot.git"
|
|
56
|
-
},
|
|
57
|
-
"homepage": "https://github.com/Digital-Threads/token-pilot#readme",
|
|
58
|
-
"bugs": {
|
|
59
|
-
"url": "https://github.com/Digital-Threads/token-pilot/issues"
|
|
60
|
-
},
|
|
61
|
-
"mcpName": "io.github.Digital-Threads/token-pilot",
|
|
62
|
-
"license": "MIT",
|
|
63
|
-
"dependencies": {
|
|
64
|
-
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
65
|
-
"chokidar": "^4.0.3"
|
|
66
|
-
},
|
|
67
|
-
"devDependencies": {
|
|
68
|
-
"@vitest/coverage-v8": "^3.2.4",
|
|
69
|
-
"@types/node": "^22.0.0",
|
|
70
|
-
"typescript": "^5.7.0",
|
|
71
|
-
"vitest": "^3.0.0"
|
|
72
|
-
},
|
|
73
|
-
"engines": {
|
|
74
|
-
"node": ">=18.0.0"
|
|
75
|
-
},
|
|
76
|
-
"peerDependencies": {
|
|
77
|
-
"ast-index": ">=0.1.0"
|
|
78
|
-
},
|
|
79
|
-
"peerDependenciesMeta": {
|
|
80
|
-
"ast-index": {
|
|
81
|
-
"optional": true
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
"optionalDependencies": {
|
|
85
|
-
"@ast-grep/cli": "^0.41.0"
|
|
86
|
-
}
|
|
87
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "token-pilot",
|
|
3
|
+
"version": "0.19.2",
|
|
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
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"token-pilot": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/**/*.js",
|
|
12
|
+
"dist/**/*.d.ts",
|
|
13
|
+
"start.sh",
|
|
14
|
+
".claude-plugin/",
|
|
15
|
+
".mcp.json",
|
|
16
|
+
"skills/",
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"prebuild": "node --input-type=module -e \"import { rm } from 'node:fs/promises'; await rm('dist', { recursive: true, force: true });\"",
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev": "tsc --watch",
|
|
24
|
+
"start": "node dist/index.js",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:coverage": "vitest run --coverage",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"lint": "tsc --noEmit",
|
|
29
|
+
"prepublishOnly": "npm run build && node --input-type=module -e \"import { chmod } from 'node:fs/promises'; await chmod('dist/index.js', 0o755);\""
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"mcp",
|
|
33
|
+
"mcp-server",
|
|
34
|
+
"model-context-protocol",
|
|
35
|
+
"claude",
|
|
36
|
+
"claude-code",
|
|
37
|
+
"cursor",
|
|
38
|
+
"codex",
|
|
39
|
+
"cline",
|
|
40
|
+
"ai-coding",
|
|
41
|
+
"llm-tools",
|
|
42
|
+
"token-savings",
|
|
43
|
+
"token-reduction",
|
|
44
|
+
"context-window",
|
|
45
|
+
"context-optimization",
|
|
46
|
+
"ast",
|
|
47
|
+
"code-reading",
|
|
48
|
+
"code-navigation",
|
|
49
|
+
"smart-read",
|
|
50
|
+
"developer-tools",
|
|
51
|
+
"tree-sitter"
|
|
52
|
+
],
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/Digital-Threads/token-pilot.git"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/Digital-Threads/token-pilot#readme",
|
|
58
|
+
"bugs": {
|
|
59
|
+
"url": "https://github.com/Digital-Threads/token-pilot/issues"
|
|
60
|
+
},
|
|
61
|
+
"mcpName": "io.github.Digital-Threads/token-pilot",
|
|
62
|
+
"license": "MIT",
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
65
|
+
"chokidar": "^4.0.3"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
69
|
+
"@types/node": "^22.0.0",
|
|
70
|
+
"typescript": "^5.7.0",
|
|
71
|
+
"vitest": "^3.0.0"
|
|
72
|
+
},
|
|
73
|
+
"engines": {
|
|
74
|
+
"node": ">=18.0.0"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"ast-index": ">=0.1.0"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"ast-index": {
|
|
81
|
+
"optional": true
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"optionalDependencies": {
|
|
85
|
+
"@ast-grep/cli": "^0.41.0"
|
|
86
|
+
}
|
|
87
|
+
}
|