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.
Files changed (142) hide show
  1. package/.claude-plugin/hooks/hooks.json +15 -0
  2. package/.claude-plugin/marketplace.json +15 -0
  3. package/.claude-plugin/plugin.json +9 -0
  4. package/.mcp.json +8 -0
  5. package/CHANGELOG.md +48 -0
  6. package/README.md +282 -0
  7. package/dist/ast-index/binary-manager.d.ts +15 -0
  8. package/dist/ast-index/binary-manager.d.ts.map +1 -0
  9. package/dist/ast-index/binary-manager.js +222 -0
  10. package/dist/ast-index/binary-manager.js.map +1 -0
  11. package/dist/ast-index/client.d.ts +48 -0
  12. package/dist/ast-index/client.d.ts.map +1 -0
  13. package/dist/ast-index/client.js +371 -0
  14. package/dist/ast-index/client.js.map +1 -0
  15. package/dist/ast-index/tar-extract.d.ts +6 -0
  16. package/dist/ast-index/tar-extract.d.ts.map +1 -0
  17. package/dist/ast-index/tar-extract.js +39 -0
  18. package/dist/ast-index/tar-extract.js.map +1 -0
  19. package/dist/ast-index/types.d.ts +78 -0
  20. package/dist/ast-index/types.d.ts.map +1 -0
  21. package/dist/ast-index/types.js +6 -0
  22. package/dist/ast-index/types.js.map +1 -0
  23. package/dist/config/defaults.d.ts +3 -0
  24. package/dist/config/defaults.d.ts.map +1 -0
  25. package/dist/config/defaults.js +51 -0
  26. package/dist/config/defaults.js.map +1 -0
  27. package/dist/config/loader.d.ts +3 -0
  28. package/dist/config/loader.d.ts.map +1 -0
  29. package/dist/config/loader.js +31 -0
  30. package/dist/config/loader.js.map +1 -0
  31. package/dist/core/context-registry.d.ts +31 -0
  32. package/dist/core/context-registry.d.ts.map +1 -0
  33. package/dist/core/context-registry.js +133 -0
  34. package/dist/core/context-registry.js.map +1 -0
  35. package/dist/core/file-cache.d.ts +34 -0
  36. package/dist/core/file-cache.d.ts.map +1 -0
  37. package/dist/core/file-cache.js +120 -0
  38. package/dist/core/file-cache.js.map +1 -0
  39. package/dist/core/format-duration.d.ts +5 -0
  40. package/dist/core/format-duration.d.ts.map +1 -0
  41. package/dist/core/format-duration.js +13 -0
  42. package/dist/core/format-duration.js.map +1 -0
  43. package/dist/core/session-analytics.d.ts +26 -0
  44. package/dist/core/session-analytics.d.ts.map +1 -0
  45. package/dist/core/session-analytics.js +91 -0
  46. package/dist/core/session-analytics.js.map +1 -0
  47. package/dist/core/symbol-resolver.d.ts +21 -0
  48. package/dist/core/symbol-resolver.d.ts.map +1 -0
  49. package/dist/core/symbol-resolver.js +102 -0
  50. package/dist/core/symbol-resolver.js.map +1 -0
  51. package/dist/core/token-estimator.d.ts +10 -0
  52. package/dist/core/token-estimator.d.ts.map +1 -0
  53. package/dist/core/token-estimator.js +22 -0
  54. package/dist/core/token-estimator.js.map +1 -0
  55. package/dist/core/validation.d.ts +77 -0
  56. package/dist/core/validation.d.ts.map +1 -0
  57. package/dist/core/validation.js +208 -0
  58. package/dist/core/validation.js.map +1 -0
  59. package/dist/formatters/structure.d.ts +13 -0
  60. package/dist/formatters/structure.d.ts.map +1 -0
  61. package/dist/formatters/structure.js +90 -0
  62. package/dist/formatters/structure.js.map +1 -0
  63. package/dist/git/file-watcher.d.ts +17 -0
  64. package/dist/git/file-watcher.d.ts.map +1 -0
  65. package/dist/git/file-watcher.js +54 -0
  66. package/dist/git/file-watcher.js.map +1 -0
  67. package/dist/git/watcher.d.ts +25 -0
  68. package/dist/git/watcher.d.ts.map +1 -0
  69. package/dist/git/watcher.js +95 -0
  70. package/dist/git/watcher.js.map +1 -0
  71. package/dist/handlers/class-hierarchy.d.ts +11 -0
  72. package/dist/handlers/class-hierarchy.d.ts.map +1 -0
  73. package/dist/handlers/class-hierarchy.js +28 -0
  74. package/dist/handlers/class-hierarchy.js.map +1 -0
  75. package/dist/handlers/export-ast-index.d.ts +19 -0
  76. package/dist/handlers/export-ast-index.d.ts.map +1 -0
  77. package/dist/handlers/export-ast-index.js +107 -0
  78. package/dist/handlers/export-ast-index.js.map +1 -0
  79. package/dist/handlers/find-implementations.d.ts +11 -0
  80. package/dist/handlers/find-implementations.d.ts.map +1 -0
  81. package/dist/handlers/find-implementations.js +25 -0
  82. package/dist/handlers/find-implementations.js.map +1 -0
  83. package/dist/handlers/find-usages.d.ts +11 -0
  84. package/dist/handlers/find-usages.d.ts.map +1 -0
  85. package/dist/handlers/find-usages.js +23 -0
  86. package/dist/handlers/find-usages.js.map +1 -0
  87. package/dist/handlers/non-code.d.ts +25 -0
  88. package/dist/handlers/non-code.d.ts.map +1 -0
  89. package/dist/handlers/non-code.js +152 -0
  90. package/dist/handlers/non-code.js.map +1 -0
  91. package/dist/handlers/project-overview.d.ts +8 -0
  92. package/dist/handlers/project-overview.d.ts.map +1 -0
  93. package/dist/handlers/project-overview.js +84 -0
  94. package/dist/handlers/project-overview.js.map +1 -0
  95. package/dist/handlers/read-diff.d.ts +13 -0
  96. package/dist/handlers/read-diff.d.ts.map +1 -0
  97. package/dist/handlers/read-diff.js +174 -0
  98. package/dist/handlers/read-diff.js.map +1 -0
  99. package/dist/handlers/read-range.d.ts +14 -0
  100. package/dist/handlers/read-range.d.ts.map +1 -0
  101. package/dist/handlers/read-range.js +44 -0
  102. package/dist/handlers/read-range.js.map +1 -0
  103. package/dist/handlers/read-symbol.d.ts +16 -0
  104. package/dist/handlers/read-symbol.d.ts.map +1 -0
  105. package/dist/handlers/read-symbol.js +59 -0
  106. package/dist/handlers/read-symbol.js.map +1 -0
  107. package/dist/handlers/search-code.d.ts +14 -0
  108. package/dist/handlers/search-code.d.ts.map +1 -0
  109. package/dist/handlers/search-code.js +27 -0
  110. package/dist/handlers/search-code.js.map +1 -0
  111. package/dist/handlers/smart-read-many.d.ts +14 -0
  112. package/dist/handlers/smart-read-many.d.ts.map +1 -0
  113. package/dist/handlers/smart-read-many.js +32 -0
  114. package/dist/handlers/smart-read-many.js.map +1 -0
  115. package/dist/handlers/smart-read.d.ts +18 -0
  116. package/dist/handlers/smart-read.d.ts.map +1 -0
  117. package/dist/handlers/smart-read.js +86 -0
  118. package/dist/handlers/smart-read.js.map +1 -0
  119. package/dist/hooks/installer.d.ts +16 -0
  120. package/dist/hooks/installer.d.ts.map +1 -0
  121. package/dist/hooks/installer.js +89 -0
  122. package/dist/hooks/installer.js.map +1 -0
  123. package/dist/index.d.ts +3 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +120 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/integration/context-mode-detector.d.ts +16 -0
  128. package/dist/integration/context-mode-detector.d.ts.map +1 -0
  129. package/dist/integration/context-mode-detector.js +53 -0
  130. package/dist/integration/context-mode-detector.js.map +1 -0
  131. package/dist/server.d.ts +36 -0
  132. package/dist/server.d.ts.map +1 -0
  133. package/dist/server.js +375 -0
  134. package/dist/server.js.map +1 -0
  135. package/dist/types.d.ts +122 -0
  136. package/dist/types.d.ts.map +1 -0
  137. package/dist/types.js +5 -0
  138. package/dist/types.js.map +1 -0
  139. package/package.json +67 -0
  140. package/skills/install/SKILL.md +14 -0
  141. package/skills/stats/SKILL.md +8 -0
  142. package/start.sh +27 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "hooks": {
3
+ "PreToolUse": [
4
+ {
5
+ "matcher": "Read",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "node ${CLAUDE_PLUGIN_ROOT}/dist/index.js hook-read $FILE_PATH"
10
+ }
11
+ ]
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -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
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "token-pilot": {
4
+ "command": "sh",
5
+ "args": ["${CLAUDE_PLUGIN_ROOT}/start.sh"]
6
+ }
7
+ }
8
+ }
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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"}