token-pilot 0.1.1
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/.claude-plugin/hooks/hooks.json +15 -0
- package/.claude-plugin/marketplace.json +15 -0
- package/.claude-plugin/plugin.json +9 -0
- package/.mcp.json +8 -0
- package/CHANGELOG.md +48 -0
- package/README.md +282 -0
- package/dist/ast-index/binary-manager.d.ts +15 -0
- package/dist/ast-index/binary-manager.d.ts.map +1 -0
- package/dist/ast-index/binary-manager.js +222 -0
- package/dist/ast-index/binary-manager.js.map +1 -0
- package/dist/ast-index/client.d.ts +48 -0
- package/dist/ast-index/client.d.ts.map +1 -0
- package/dist/ast-index/client.js +371 -0
- package/dist/ast-index/client.js.map +1 -0
- package/dist/ast-index/tar-extract.d.ts +6 -0
- package/dist/ast-index/tar-extract.d.ts.map +1 -0
- package/dist/ast-index/tar-extract.js +39 -0
- package/dist/ast-index/tar-extract.js.map +1 -0
- package/dist/ast-index/types.d.ts +78 -0
- package/dist/ast-index/types.d.ts.map +1 -0
- package/dist/ast-index/types.js +6 -0
- package/dist/ast-index/types.js.map +1 -0
- package/dist/config/defaults.d.ts +3 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +51 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/loader.d.ts +3 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +31 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/core/context-registry.d.ts +31 -0
- package/dist/core/context-registry.d.ts.map +1 -0
- package/dist/core/context-registry.js +133 -0
- package/dist/core/context-registry.js.map +1 -0
- package/dist/core/file-cache.d.ts +34 -0
- package/dist/core/file-cache.d.ts.map +1 -0
- package/dist/core/file-cache.js +120 -0
- package/dist/core/file-cache.js.map +1 -0
- package/dist/core/format-duration.d.ts +5 -0
- package/dist/core/format-duration.d.ts.map +1 -0
- package/dist/core/format-duration.js +13 -0
- package/dist/core/format-duration.js.map +1 -0
- package/dist/core/session-analytics.d.ts +26 -0
- package/dist/core/session-analytics.d.ts.map +1 -0
- package/dist/core/session-analytics.js +91 -0
- package/dist/core/session-analytics.js.map +1 -0
- package/dist/core/symbol-resolver.d.ts +21 -0
- package/dist/core/symbol-resolver.d.ts.map +1 -0
- package/dist/core/symbol-resolver.js +102 -0
- package/dist/core/symbol-resolver.js.map +1 -0
- package/dist/core/token-estimator.d.ts +10 -0
- package/dist/core/token-estimator.d.ts.map +1 -0
- package/dist/core/token-estimator.js +22 -0
- package/dist/core/token-estimator.js.map +1 -0
- package/dist/core/validation.d.ts +77 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +208 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/formatters/structure.d.ts +13 -0
- package/dist/formatters/structure.d.ts.map +1 -0
- package/dist/formatters/structure.js +90 -0
- package/dist/formatters/structure.js.map +1 -0
- package/dist/git/file-watcher.d.ts +17 -0
- package/dist/git/file-watcher.d.ts.map +1 -0
- package/dist/git/file-watcher.js +54 -0
- package/dist/git/file-watcher.js.map +1 -0
- package/dist/git/watcher.d.ts +25 -0
- package/dist/git/watcher.d.ts.map +1 -0
- package/dist/git/watcher.js +95 -0
- package/dist/git/watcher.js.map +1 -0
- package/dist/handlers/class-hierarchy.d.ts +11 -0
- package/dist/handlers/class-hierarchy.d.ts.map +1 -0
- package/dist/handlers/class-hierarchy.js +28 -0
- package/dist/handlers/class-hierarchy.js.map +1 -0
- package/dist/handlers/export-ast-index.d.ts +19 -0
- package/dist/handlers/export-ast-index.d.ts.map +1 -0
- package/dist/handlers/export-ast-index.js +107 -0
- package/dist/handlers/export-ast-index.js.map +1 -0
- package/dist/handlers/find-implementations.d.ts +11 -0
- package/dist/handlers/find-implementations.d.ts.map +1 -0
- package/dist/handlers/find-implementations.js +25 -0
- package/dist/handlers/find-implementations.js.map +1 -0
- package/dist/handlers/find-usages.d.ts +11 -0
- package/dist/handlers/find-usages.d.ts.map +1 -0
- package/dist/handlers/find-usages.js +23 -0
- package/dist/handlers/find-usages.js.map +1 -0
- package/dist/handlers/non-code.d.ts +25 -0
- package/dist/handlers/non-code.d.ts.map +1 -0
- package/dist/handlers/non-code.js +152 -0
- package/dist/handlers/non-code.js.map +1 -0
- package/dist/handlers/project-overview.d.ts +8 -0
- package/dist/handlers/project-overview.d.ts.map +1 -0
- package/dist/handlers/project-overview.js +84 -0
- package/dist/handlers/project-overview.js.map +1 -0
- package/dist/handlers/read-diff.d.ts +13 -0
- package/dist/handlers/read-diff.d.ts.map +1 -0
- package/dist/handlers/read-diff.js +174 -0
- package/dist/handlers/read-diff.js.map +1 -0
- package/dist/handlers/read-range.d.ts +14 -0
- package/dist/handlers/read-range.d.ts.map +1 -0
- package/dist/handlers/read-range.js +44 -0
- package/dist/handlers/read-range.js.map +1 -0
- package/dist/handlers/read-symbol.d.ts +16 -0
- package/dist/handlers/read-symbol.d.ts.map +1 -0
- package/dist/handlers/read-symbol.js +59 -0
- package/dist/handlers/read-symbol.js.map +1 -0
- package/dist/handlers/search-code.d.ts +14 -0
- package/dist/handlers/search-code.d.ts.map +1 -0
- package/dist/handlers/search-code.js +27 -0
- package/dist/handlers/search-code.js.map +1 -0
- package/dist/handlers/smart-read-many.d.ts +14 -0
- package/dist/handlers/smart-read-many.d.ts.map +1 -0
- package/dist/handlers/smart-read-many.js +32 -0
- package/dist/handlers/smart-read-many.js.map +1 -0
- package/dist/handlers/smart-read.d.ts +18 -0
- package/dist/handlers/smart-read.d.ts.map +1 -0
- package/dist/handlers/smart-read.js +86 -0
- package/dist/handlers/smart-read.js.map +1 -0
- package/dist/hooks/installer.d.ts +16 -0
- package/dist/hooks/installer.d.ts.map +1 -0
- package/dist/hooks/installer.js +89 -0
- package/dist/hooks/installer.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +120 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/context-mode-detector.d.ts +16 -0
- package/dist/integration/context-mode-detector.d.ts.map +1 -0
- package/dist/integration/context-mode-detector.js +53 -0
- package/dist/integration/context-mode-detector.js.map +1 -0
- package/dist/server.d.ts +36 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +375 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +122 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +67 -0
- package/skills/install/SKILL.md +14 -0
- package/skills/stats/SKILL.md +8 -0
- package/start.sh +27 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "token-pilot",
|
|
3
|
+
"displayName": "Token Pilot",
|
|
4
|
+
"description": "Reduces token consumption by 80-95% via AST-aware lazy file reading. 14 MCP tools for structural code reading, symbol navigation, and cross-file search.",
|
|
5
|
+
"version": "0.1.1",
|
|
6
|
+
"author": "Digital-Threads",
|
|
7
|
+
"repository": "https://github.com/Digital-Threads/token-pilot",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"keywords": ["mcp", "token", "ast", "code-reading", "optimization"],
|
|
10
|
+
"categories": ["developer-tools", "code-analysis"],
|
|
11
|
+
"installMethod": "plugin",
|
|
12
|
+
"requirements": {
|
|
13
|
+
"node": ">=18.0.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "token-pilot",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Reduces token consumption by 80-95% via AST-aware lazy file reading. Returns structural overviews instead of full files.",
|
|
5
|
+
"author": "token-pilot",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"skills": "../skills",
|
|
8
|
+
"hooks": "./hooks"
|
|
9
|
+
}
|
package/.mcp.json
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Token Pilot will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.1] - 2026-03-01
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `npx -y token-pilot` — zero-install for any MCP client (Cursor, Cline, Continue, etc.)
|
|
12
|
+
- Claude Code plugin marketplace support (`.claude-plugin/marketplace.json`)
|
|
13
|
+
- `start.sh` bootstrap script — auto `npm install` + `npm run build` on first run
|
|
14
|
+
- `npm publish` ready (`files` field, `prepublishOnly` script)
|
|
15
|
+
- Universal install instructions in README for Claude Code, Cursor, Cline
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- `.mcp.json` now uses `start.sh` for reliable bootstrap
|
|
19
|
+
- README reorganized: npx as primary install, from-source as fallback
|
|
20
|
+
|
|
21
|
+
## [0.1.0] - 2026-03-01
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **Core Reading Tools**: `smart_read`, `read_symbol`, `read_range`, `read_diff`, `smart_read_many`
|
|
26
|
+
- AST-based structural overviews saving 80-95% tokens
|
|
27
|
+
- Small file pass-through (< 80 lines returned in full)
|
|
28
|
+
- O(n) diff algorithm for re-reads
|
|
29
|
+
- Advisory context registry with compact reminders
|
|
30
|
+
- **Search & Navigation**: `search_code`, `find_usages`, `find_implementations`, `class_hierarchy`, `project_overview`
|
|
31
|
+
- Powered by ast-index (tree-sitter + SQLite FTS5)
|
|
32
|
+
- Cross-file symbol resolution
|
|
33
|
+
- **Context Management**: `session_analytics`, `context_status`, `forget`
|
|
34
|
+
- Token savings tracking per tool and per file
|
|
35
|
+
- Advisory (non-blocking) context tracking
|
|
36
|
+
- **Integration**: `export_ast_index`
|
|
37
|
+
- context-mode detection and complementary architecture
|
|
38
|
+
- AST data export for BM25 cross-indexing
|
|
39
|
+
- **Infrastructure**
|
|
40
|
+
- Git HEAD watcher with selective cache invalidation on branch switch
|
|
41
|
+
- File watcher (chokidar) for automatic cache invalidation
|
|
42
|
+
- LRU file cache with configurable size limit
|
|
43
|
+
- Input validation for all tools (path traversal protection)
|
|
44
|
+
- Auto-download of ast-index binary from GitHub releases
|
|
45
|
+
- PreToolUse hook installer for Claude Code
|
|
46
|
+
- Claude Code plugin format (.claude-plugin/)
|
|
47
|
+
- Non-code structural summaries (JSON, YAML, Markdown, TOML)
|
|
48
|
+
- Configurable via `.token-pilot.json`
|
package/README.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# Token Pilot
|
|
2
|
+
|
|
3
|
+
MCP server that reduces token consumption in AI coding assistants by **80-95%** via AST-aware lazy file reading.
|
|
4
|
+
|
|
5
|
+
Instead of dumping entire files into the LLM context, Token Pilot returns structural overviews (classes, functions, signatures, line ranges) and lets the AI load only the specific symbols it needs.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Traditional: Read("user-service.ts") → 500 lines → ~3000 tokens
|
|
11
|
+
Token Pilot: smart_read("user-service.ts") → 15-line outline → ~200 tokens
|
|
12
|
+
read_symbol("UserService.updateUser") → 45 lines → ~350 tokens
|
|
13
|
+
After edit: read_diff("user-service.ts") → ~20 tokens
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**93% reduction** in this example. Files under 80 lines are returned in full automatically (no overhead for small files).
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
### npx — Any AI Assistant (Cursor, Cline, Continue, etc.)
|
|
21
|
+
|
|
22
|
+
Zero install. Add to your `.mcp.json` (project-level or `~/.mcp.json` for global):
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"mcpServers": {
|
|
27
|
+
"token-pilot": {
|
|
28
|
+
"command": "npx",
|
|
29
|
+
"args": ["-y", "token-pilot"]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**That's it.** npx downloads the package, ast-index binary is fetched automatically on first run. No Rust, no Cargo, no manual setup.
|
|
36
|
+
|
|
37
|
+
#### Cursor
|
|
38
|
+
|
|
39
|
+
Settings → MCP Servers → Add:
|
|
40
|
+
- Command: `npx`
|
|
41
|
+
- Args: `-y token-pilot`
|
|
42
|
+
|
|
43
|
+
### Claude Code
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Global (all projects)
|
|
47
|
+
claude mcp add token-pilot -- npx -y token-pilot
|
|
48
|
+
|
|
49
|
+
# Project-only (adds to .mcp.json in current directory)
|
|
50
|
+
claude mcp add --scope project token-pilot -- npx -y token-pilot
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This registers the MCP server. The PreToolUse hook auto-suggests `smart_read` for large files.
|
|
54
|
+
|
|
55
|
+
### From Source
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
git clone https://github.com/Digital-Threads/token-pilot.git
|
|
59
|
+
cd token-pilot
|
|
60
|
+
npm install && npm run build
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"mcpServers": {
|
|
66
|
+
"token-pilot": {
|
|
67
|
+
"command": "node",
|
|
68
|
+
"args": ["/path/to/token-pilot/dist/index.js"]
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### ast-index (auto-installed)
|
|
75
|
+
|
|
76
|
+
ast-index is downloaded automatically on first run. If you prefer manual install:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Homebrew (macOS / Linux)
|
|
80
|
+
brew tap defendend/ast-index && brew install ast-index
|
|
81
|
+
|
|
82
|
+
# Or via Token Pilot CLI
|
|
83
|
+
npx token-pilot install-ast-index
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### PreToolUse Hook (optional)
|
|
87
|
+
|
|
88
|
+
Intercepts `Read` calls for large code files and suggests `smart_read`:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npx token-pilot install-hook # Current project
|
|
92
|
+
npx token-pilot uninstall-hook # Remove
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## MCP Tools (14)
|
|
96
|
+
|
|
97
|
+
### Core Reading
|
|
98
|
+
|
|
99
|
+
| Tool | Description |
|
|
100
|
+
|------|-------------|
|
|
101
|
+
| `smart_read` | AST-based structural overview of a file. Returns classes, functions, methods with signatures and line ranges. |
|
|
102
|
+
| `read_symbol` | Load source code of a specific symbol (e.g., `UserService.updateUser`). |
|
|
103
|
+
| `read_range` | Read a specific line range from a file. |
|
|
104
|
+
| `read_diff` | Show only what changed since Token Pilot last served the file. |
|
|
105
|
+
| `smart_read_many` | Batch `smart_read` for up to 20 files in one call. |
|
|
106
|
+
|
|
107
|
+
### Search & Navigation
|
|
108
|
+
|
|
109
|
+
| Tool | Description |
|
|
110
|
+
|------|-------------|
|
|
111
|
+
| `search_code` | Indexed structural code search via ast-index. Faster than grep for symbols. |
|
|
112
|
+
| `find_usages` | Find all usages of a symbol across the project (definitions, calls, imports, references). |
|
|
113
|
+
| `find_implementations` | Find all implementations of an interface/abstract class/trait. |
|
|
114
|
+
| `class_hierarchy` | Show class/interface inheritance hierarchy tree. |
|
|
115
|
+
| `project_overview` | Compact project overview: type, dependencies, structure map. |
|
|
116
|
+
|
|
117
|
+
### Integration & Analytics
|
|
118
|
+
|
|
119
|
+
| Tool | Description |
|
|
120
|
+
|------|-------------|
|
|
121
|
+
| `export_ast_index` | Export AST data as markdown/JSON for cross-tool indexing (e.g., context-mode BM25). |
|
|
122
|
+
| `session_analytics` | Token savings report: total saved, per-tool breakdown, top files. |
|
|
123
|
+
| `context_status` | Show what files/symbols are currently tracked in context. |
|
|
124
|
+
| `forget` | Remove a file or symbol from context tracking. |
|
|
125
|
+
|
|
126
|
+
## CLI Commands
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
token-pilot # Start MCP server (uses cwd as project root)
|
|
130
|
+
token-pilot /path/to/project # Start with specific project root
|
|
131
|
+
token-pilot install-ast-index # Download ast-index binary (auto on first run)
|
|
132
|
+
token-pilot install-hook [root] # Install PreToolUse hook
|
|
133
|
+
token-pilot uninstall-hook # Remove hook
|
|
134
|
+
token-pilot hook-read <file> # Hook handler (called by Claude Code)
|
|
135
|
+
token-pilot --help # Show help
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Configuration
|
|
139
|
+
|
|
140
|
+
Create `.token-pilot.json` in your project root to customize behavior:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"smartRead": {
|
|
145
|
+
"smallFileThreshold": 80,
|
|
146
|
+
"advisoryReminders": true
|
|
147
|
+
},
|
|
148
|
+
"cache": {
|
|
149
|
+
"maxSizeMB": 100,
|
|
150
|
+
"watchFiles": true
|
|
151
|
+
},
|
|
152
|
+
"git": {
|
|
153
|
+
"watchHead": true,
|
|
154
|
+
"selectiveInvalidation": true
|
|
155
|
+
},
|
|
156
|
+
"contextMode": {
|
|
157
|
+
"enabled": "auto",
|
|
158
|
+
"adviseDelegation": true,
|
|
159
|
+
"largeNonCodeThreshold": 200
|
|
160
|
+
},
|
|
161
|
+
"display": {
|
|
162
|
+
"showImports": true,
|
|
163
|
+
"showDocs": true,
|
|
164
|
+
"maxDepth": 2,
|
|
165
|
+
"showTokenSavings": true
|
|
166
|
+
},
|
|
167
|
+
"ignore": [
|
|
168
|
+
"node_modules/**",
|
|
169
|
+
"dist/**",
|
|
170
|
+
".git/**"
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
All fields are optional — sensible defaults are used for anything not specified.
|
|
176
|
+
|
|
177
|
+
### Key Config Options
|
|
178
|
+
|
|
179
|
+
| Option | Default | Description |
|
|
180
|
+
|--------|---------|-------------|
|
|
181
|
+
| `smartRead.smallFileThreshold` | `80` | Files with fewer lines are returned in full (no AST overhead). |
|
|
182
|
+
| `cache.maxSizeMB` | `100` | Max memory for file cache. LRU eviction when exceeded. |
|
|
183
|
+
| `cache.watchFiles` | `true` | Auto-invalidate cache on file changes (chokidar). |
|
|
184
|
+
| `git.watchHead` | `true` | Watch `.git/HEAD` for branch switches, invalidate changed files. |
|
|
185
|
+
| `contextMode.enabled` | `"auto"` | Detect context-mode plugin. `true`/`false` to force. |
|
|
186
|
+
| `contextMode.adviseDelegation` | `true` | Suggest context-mode for large non-code files. |
|
|
187
|
+
|
|
188
|
+
## Integration with context-mode
|
|
189
|
+
|
|
190
|
+
Token Pilot is **complementary** to [claude-context-mode](https://github.com/mksglu/claude-context-mode):
|
|
191
|
+
|
|
192
|
+
| Responsibility | Token Pilot | context-mode |
|
|
193
|
+
|----------------|-------------|--------------|
|
|
194
|
+
| Code files (.ts, .py, .rs, ...) | AST-level structural reading | - |
|
|
195
|
+
| Shell output (npm test, git log) | - | Sandbox + BM25 |
|
|
196
|
+
| Large data files (JSON, CSV, logs) | Structural summary | Deep BM25-indexed analysis |
|
|
197
|
+
| Re-reads of unchanged files | Compact reminders (~20 tokens) | - |
|
|
198
|
+
|
|
199
|
+
When both are configured, Token Pilot automatically:
|
|
200
|
+
- Detects context-mode via `.mcp.json`
|
|
201
|
+
- Suggests context-mode for large non-code files
|
|
202
|
+
- Shows combined architecture info in `session_analytics`
|
|
203
|
+
- Provides `export_ast_index` to feed AST data into context-mode's BM25 index
|
|
204
|
+
|
|
205
|
+
**Combined savings: ~80%** in a typical coding session.
|
|
206
|
+
|
|
207
|
+
## Supported Languages
|
|
208
|
+
|
|
209
|
+
Token Pilot supports all 23 languages that [ast-index](https://github.com/defendend/Claude-ast-index-search) supports:
|
|
210
|
+
|
|
211
|
+
TypeScript, JavaScript, Python, Rust, Go, Java, Kotlin, Swift, C#, C++, C, PHP, Ruby, Scala, Dart, Lua, Shell/Bash, SQL, R, Vue, Svelte, Perl, Groovy
|
|
212
|
+
|
|
213
|
+
Plus structural summaries for non-code files: JSON, YAML, Markdown, TOML, XML, CSV.
|
|
214
|
+
|
|
215
|
+
## Development
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
npm install # Install dependencies
|
|
219
|
+
npm run build # Compile TypeScript
|
|
220
|
+
npm test # Run tests (111 tests)
|
|
221
|
+
npm run test:watch # Run tests in watch mode
|
|
222
|
+
npm run dev # TypeScript watch mode
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Architecture
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
src/
|
|
229
|
+
index.ts — CLI entry point (6 commands)
|
|
230
|
+
server.ts — MCP server (14 tools)
|
|
231
|
+
types.ts — Core domain types
|
|
232
|
+
ast-index/
|
|
233
|
+
client.ts — ast-index CLI wrapper
|
|
234
|
+
binary-manager.ts — Auto-download & manage ast-index binary
|
|
235
|
+
tar-extract.ts — Minimal tar extractor (zero deps)
|
|
236
|
+
types.ts — ast-index response types
|
|
237
|
+
core/
|
|
238
|
+
file-cache.ts — LRU file cache with staleness detection
|
|
239
|
+
context-registry.ts — Advisory context tracking + compact reminders
|
|
240
|
+
symbol-resolver.ts — Qualified symbol resolution
|
|
241
|
+
token-estimator.ts — Token count estimation
|
|
242
|
+
session-analytics.ts — Token savings tracking
|
|
243
|
+
validation.ts — Input validators for all tools
|
|
244
|
+
format-duration.ts — Shared duration formatter
|
|
245
|
+
config/
|
|
246
|
+
loader.ts — Config loading + deep merge
|
|
247
|
+
defaults.ts — Default config values
|
|
248
|
+
formatters/
|
|
249
|
+
structure.ts — AST outline → text formatter
|
|
250
|
+
handlers/
|
|
251
|
+
smart-read.ts — smart_read handler
|
|
252
|
+
read-symbol.ts — read_symbol handler
|
|
253
|
+
read-range.ts — read_range handler
|
|
254
|
+
read-diff.ts — read_diff handler (O(n) diff)
|
|
255
|
+
smart-read-many.ts — Batch smart_read
|
|
256
|
+
search-code.ts — search_code handler
|
|
257
|
+
find-usages.ts — find_usages handler
|
|
258
|
+
find-implementations.ts
|
|
259
|
+
class-hierarchy.ts
|
|
260
|
+
project-overview.ts
|
|
261
|
+
non-code.ts — JSON/YAML/MD/TOML structural summaries
|
|
262
|
+
export-ast-index.ts — AST export for context-mode BM25
|
|
263
|
+
git/
|
|
264
|
+
watcher.ts — Git HEAD watcher (branch switch detection)
|
|
265
|
+
file-watcher.ts — File system watcher (cache invalidation)
|
|
266
|
+
hooks/
|
|
267
|
+
installer.ts — Hook install/uninstall for Claude Code
|
|
268
|
+
integration/
|
|
269
|
+
context-mode-detector.ts — context-mode presence detection
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Credits
|
|
273
|
+
|
|
274
|
+
Token Pilot is built on top of these excellent open-source projects:
|
|
275
|
+
|
|
276
|
+
- **[ast-index](https://github.com/defendend/Claude-ast-index-search)** by [@defendend](https://github.com/defendend) — Rust-based AST indexing engine with tree-sitter, SQLite FTS5, and support for 23 programming languages. Token Pilot uses it as the backend for all code analysis.
|
|
277
|
+
- **[claude-context-mode](https://github.com/mksglu/claude-context-mode)** by [@mksglu](https://github.com/mksglu) — Complementary MCP plugin for shell output and data file processing via sandbox + BM25. Token Pilot integrates with it for maximum combined savings.
|
|
278
|
+
- **[Model Context Protocol](https://modelcontextprotocol.io/)** by Anthropic — The protocol that makes all of this possible.
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface BinaryStatus {
|
|
2
|
+
available: boolean;
|
|
3
|
+
path: string;
|
|
4
|
+
version: string | null;
|
|
5
|
+
source: 'system' | 'managed' | 'none';
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Find ast-index binary: check system PATH first, then managed install.
|
|
9
|
+
*/
|
|
10
|
+
export declare function findBinary(configPath?: string | null): Promise<BinaryStatus>;
|
|
11
|
+
/**
|
|
12
|
+
* Download and install ast-index binary from GitHub releases.
|
|
13
|
+
*/
|
|
14
|
+
export declare function installBinary(onProgress?: (msg: string) => void): Promise<BinaryStatus>;
|
|
15
|
+
//# sourceMappingURL=binary-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-manager.d.ts","sourceRoot":"","sources":["../../src/ast-index/binary-manager.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;CACvC;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAwBlF;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACjC,OAAO,CAAC,YAAY,CAAC,CAiDvB"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { createWriteStream } from 'node:fs';
|
|
3
|
+
import { chmod, mkdir, access, rm } from 'node:fs/promises';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import { pipeline } from 'node:stream/promises';
|
|
6
|
+
import { createGunzip } from 'node:zlib';
|
|
7
|
+
import { homedir, platform, arch } from 'node:os';
|
|
8
|
+
import { get as httpsGet } from 'node:https';
|
|
9
|
+
import { get as httpGet } from 'node:http';
|
|
10
|
+
import { tarExtract } from './tar-extract.js';
|
|
11
|
+
const REPO = 'defendend/Claude-ast-index-search';
|
|
12
|
+
const BINARY_NAME = platform() === 'win32' ? 'ast-index.exe' : 'ast-index';
|
|
13
|
+
const INSTALL_DIR = resolve(homedir(), '.token-pilot', 'bin');
|
|
14
|
+
/**
|
|
15
|
+
* Find ast-index binary: check system PATH first, then managed install.
|
|
16
|
+
*/
|
|
17
|
+
export async function findBinary(configPath) {
|
|
18
|
+
// 1. Config override
|
|
19
|
+
if (configPath) {
|
|
20
|
+
const version = await getBinaryVersion(configPath);
|
|
21
|
+
if (version) {
|
|
22
|
+
return { available: true, path: configPath, version, source: 'system' };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// 2. System PATH
|
|
26
|
+
const systemPath = await findInPath();
|
|
27
|
+
if (systemPath) {
|
|
28
|
+
const version = await getBinaryVersion(systemPath);
|
|
29
|
+
return { available: true, path: systemPath, version, source: 'system' };
|
|
30
|
+
}
|
|
31
|
+
// 3. Managed install
|
|
32
|
+
const managedPath = resolve(INSTALL_DIR, BINARY_NAME);
|
|
33
|
+
const version = await getBinaryVersion(managedPath);
|
|
34
|
+
if (version) {
|
|
35
|
+
return { available: true, path: managedPath, version, source: 'managed' };
|
|
36
|
+
}
|
|
37
|
+
return { available: false, path: '', version: null, source: 'none' };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Download and install ast-index binary from GitHub releases.
|
|
41
|
+
*/
|
|
42
|
+
export async function installBinary(onProgress) {
|
|
43
|
+
const log = onProgress ?? (() => { });
|
|
44
|
+
// Determine platform/arch
|
|
45
|
+
const plat = getPlatform();
|
|
46
|
+
const ar = getArch();
|
|
47
|
+
if (!plat || !ar) {
|
|
48
|
+
throw new Error(`Unsupported platform: ${platform()} ${arch()}`);
|
|
49
|
+
}
|
|
50
|
+
log('Fetching latest release info...');
|
|
51
|
+
const release = await fetchLatestRelease();
|
|
52
|
+
const assetName = buildAssetName(release.tag, plat, ar);
|
|
53
|
+
const asset = release.assets.find(a => a.name === assetName);
|
|
54
|
+
if (!asset) {
|
|
55
|
+
throw new Error(`No binary found for ${plat}-${ar}. Available: ${release.assets.map(a => a.name).join(', ')}`);
|
|
56
|
+
}
|
|
57
|
+
log(`Downloading ${asset.name} (${(asset.size / 1024 / 1024).toFixed(1)}MB)...`);
|
|
58
|
+
await mkdir(INSTALL_DIR, { recursive: true });
|
|
59
|
+
const tmpPath = resolve(INSTALL_DIR, `${BINARY_NAME}.tmp`);
|
|
60
|
+
const finalPath = resolve(INSTALL_DIR, BINARY_NAME);
|
|
61
|
+
try {
|
|
62
|
+
if (assetName.endsWith('.tar.gz')) {
|
|
63
|
+
await downloadAndExtractTarGz(asset.url, INSTALL_DIR, BINARY_NAME);
|
|
64
|
+
}
|
|
65
|
+
else if (assetName.endsWith('.zip')) {
|
|
66
|
+
// For Windows, download zip and extract
|
|
67
|
+
await downloadFile(asset.url, tmpPath);
|
|
68
|
+
// Simple approach: use system unzip if available
|
|
69
|
+
throw new Error('ZIP extraction not yet supported. Please install ast-index manually on Windows.');
|
|
70
|
+
}
|
|
71
|
+
await chmod(finalPath, 0o755);
|
|
72
|
+
const version = await getBinaryVersion(finalPath);
|
|
73
|
+
log(`Installed ast-index ${version} to ${finalPath}`);
|
|
74
|
+
return { available: true, path: finalPath, version, source: 'managed' };
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
// Cleanup on failure
|
|
78
|
+
try {
|
|
79
|
+
await rm(tmpPath, { force: true });
|
|
80
|
+
}
|
|
81
|
+
catch { }
|
|
82
|
+
try {
|
|
83
|
+
await rm(finalPath, { force: true });
|
|
84
|
+
}
|
|
85
|
+
catch { }
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// --- Internal helpers ---
|
|
90
|
+
function getPlatform() {
|
|
91
|
+
switch (platform()) {
|
|
92
|
+
case 'darwin': return 'darwin';
|
|
93
|
+
case 'linux': return 'linux';
|
|
94
|
+
case 'win32': return 'windows';
|
|
95
|
+
default: return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function getArch() {
|
|
99
|
+
switch (arch()) {
|
|
100
|
+
case 'arm64': return 'arm64';
|
|
101
|
+
case 'x64': return 'x86_64';
|
|
102
|
+
default: return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function buildAssetName(tag, plat, ar) {
|
|
106
|
+
const ext = plat === 'windows' ? '.zip' : '.tar.gz';
|
|
107
|
+
return `ast-index-${tag}-${plat}-${ar}${ext}`;
|
|
108
|
+
}
|
|
109
|
+
async function findInPath() {
|
|
110
|
+
return new Promise(resolve => {
|
|
111
|
+
const cmd = platform() === 'win32' ? 'where' : 'which';
|
|
112
|
+
execFile(cmd, ['ast-index'], (err, stdout) => {
|
|
113
|
+
if (err)
|
|
114
|
+
return resolve(null);
|
|
115
|
+
const path = stdout.trim().split('\n')[0];
|
|
116
|
+
resolve(path || null);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async function getBinaryVersion(binaryPath) {
|
|
121
|
+
try {
|
|
122
|
+
await access(binaryPath);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return new Promise(resolve => {
|
|
128
|
+
execFile(binaryPath, ['--version'], { timeout: 5000 }, (err, stdout) => {
|
|
129
|
+
if (err)
|
|
130
|
+
return resolve(null);
|
|
131
|
+
// Parse "ast-index v3.24.0" or "ast-index 3.24.0"
|
|
132
|
+
const match = stdout.trim().match(/v?(\d+\.\d+\.\d+)/);
|
|
133
|
+
resolve(match ? match[1] : null);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async function fetchLatestRelease() {
|
|
138
|
+
const data = await fetchJson(`https://api.github.com/repos/${REPO}/releases/latest`);
|
|
139
|
+
return {
|
|
140
|
+
tag: data.tag_name,
|
|
141
|
+
assets: (data.assets ?? []).map((a) => ({
|
|
142
|
+
name: a.name,
|
|
143
|
+
url: a.browser_download_url,
|
|
144
|
+
size: a.size,
|
|
145
|
+
})),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function fetchJson(url) {
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
const options = {
|
|
151
|
+
headers: { 'User-Agent': 'token-pilot' },
|
|
152
|
+
};
|
|
153
|
+
httpsGet(url, options, (res) => {
|
|
154
|
+
// Handle redirects
|
|
155
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
156
|
+
const location = res.headers.location;
|
|
157
|
+
if (!location)
|
|
158
|
+
return reject(new Error('Redirect without location'));
|
|
159
|
+
fetchJson(location).then(resolve).catch(reject);
|
|
160
|
+
res.resume();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (res.statusCode !== 200) {
|
|
164
|
+
res.resume();
|
|
165
|
+
return reject(new Error(`HTTP ${res.statusCode} from ${url}`));
|
|
166
|
+
}
|
|
167
|
+
let body = '';
|
|
168
|
+
res.setEncoding('utf-8');
|
|
169
|
+
res.on('data', chunk => body += chunk);
|
|
170
|
+
res.on('end', () => {
|
|
171
|
+
try {
|
|
172
|
+
resolve(JSON.parse(body));
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
reject(new Error(`Invalid JSON from ${url}`));
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
res.on('error', reject);
|
|
179
|
+
}).on('error', reject);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
function followRedirects(url) {
|
|
183
|
+
return new Promise((resolve, reject) => {
|
|
184
|
+
const getter = url.startsWith('https') ? httpsGet : httpGet;
|
|
185
|
+
getter(url, { headers: { 'User-Agent': 'token-pilot' } }, (res) => {
|
|
186
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
187
|
+
const location = res.headers.location;
|
|
188
|
+
if (!location)
|
|
189
|
+
return reject(new Error('Redirect without location'));
|
|
190
|
+
res.resume();
|
|
191
|
+
followRedirects(location).then(resolve).catch(reject);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (res.statusCode !== 200) {
|
|
195
|
+
res.resume();
|
|
196
|
+
return reject(new Error(`HTTP ${res.statusCode} downloading from ${url}`));
|
|
197
|
+
}
|
|
198
|
+
resolve(res);
|
|
199
|
+
}).on('error', reject);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
async function downloadAndExtractTarGz(url, destDir, binaryName) {
|
|
203
|
+
const res = await followRedirects(url);
|
|
204
|
+
const gunzip = createGunzip();
|
|
205
|
+
// Pipe through gunzip, then our custom tar extractor
|
|
206
|
+
const chunks = [];
|
|
207
|
+
res.pipe(gunzip);
|
|
208
|
+
await new Promise((resolve, reject) => {
|
|
209
|
+
gunzip.on('data', (chunk) => chunks.push(chunk));
|
|
210
|
+
gunzip.on('end', resolve);
|
|
211
|
+
gunzip.on('error', reject);
|
|
212
|
+
res.on('error', reject);
|
|
213
|
+
});
|
|
214
|
+
const tarData = Buffer.concat(chunks);
|
|
215
|
+
await tarExtract(tarData, destDir, binaryName);
|
|
216
|
+
}
|
|
217
|
+
async function downloadFile(url, destPath) {
|
|
218
|
+
const res = await followRedirects(url);
|
|
219
|
+
const fileStream = createWriteStream(destPath);
|
|
220
|
+
await pipeline(res, fileStream);
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=binary-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-manager.js","sourceRoot":"","sources":["../../src/ast-index/binary-manager.ts"],"names":[],"mappings":"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"}
|