clast-ai 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +14 -0
- package/.claude-plugin/plugin.json +11 -9
- package/README.md +449 -390
- package/bench/ab/onair-concept.json +22 -0
- package/bench/ab/onair-deadcode.json +7 -0
- package/bench/ab/onair-hard.json +32 -0
- package/bench/ab/onair-impact.json +17 -0
- package/bench/ab/onair-refactors.json +18 -0
- package/bench/ab/onair-survey.json +17 -0
- package/bench/ab/onair-tasks.json +20 -0
- package/bench/ab/onair.json +52 -0
- package/bench/ab/vscode-concept.json +22 -0
- package/bench/ab/vscode-hard.json +32 -0
- package/bench/ab/vscode-impact.json +17 -0
- package/bench/ab/vscode-refactors.json +18 -0
- package/bench/ab/vscode-tasks.json +20 -0
- package/bench/ab/vscode.json +52 -0
- package/bench/ab.mjs +213 -0
- package/bench/bench.mjs +98 -0
- package/bench/resolution.mjs +75 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +257 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/defaults.d.ts +12 -2
- package/dist/config/defaults.js +38 -31
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +26 -14
- package/dist/config/index.js.map +1 -1
- package/dist/db/index.d.ts +73 -13
- package/dist/db/index.js +481 -39
- package/dist/db/index.js.map +1 -1
- package/dist/engine.d.ts +15 -0
- package/dist/engine.js +28 -0
- package/dist/engine.js.map +1 -0
- package/dist/indexer/imports.d.ts +6 -0
- package/dist/indexer/imports.js +254 -0
- package/dist/indexer/imports.js.map +1 -0
- package/dist/indexer/index.d.ts +63 -0
- package/dist/indexer/index.js +360 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/process.d.ts +22 -0
- package/dist/indexer/process.js +42 -0
- package/dist/indexer/process.js.map +1 -0
- package/dist/indexer/scan.d.ts +43 -0
- package/dist/indexer/scan.js +223 -0
- package/dist/indexer/scan.js.map +1 -0
- package/dist/indexer/worker.d.ts +1 -0
- package/dist/indexer/worker.js +23 -0
- package/dist/indexer/worker.js.map +1 -0
- package/dist/llm/comment-generator.d.ts +17 -19
- package/dist/llm/comment-generator.js +46 -80
- package/dist/llm/comment-generator.js.map +1 -1
- package/dist/llm/index.d.ts +0 -1
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/prompts.d.ts +0 -1
- package/dist/llm/prompts.js +16 -16
- package/dist/parser/extractor.d.ts +21 -16
- package/dist/parser/extractor.js +700 -228
- package/dist/parser/extractor.js.map +1 -1
- package/dist/parser/index.d.ts +17 -21
- package/dist/parser/index.js +115 -171
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/langs/c.d.ts +3 -0
- package/dist/parser/langs/c.js +879 -0
- package/dist/parser/langs/c.js.map +1 -0
- package/dist/parser/langs/csharp.d.ts +2 -0
- package/dist/parser/langs/csharp.js +548 -0
- package/dist/parser/langs/csharp.js.map +1 -0
- package/dist/parser/langs/dart.d.ts +2 -0
- package/dist/parser/langs/dart.js +893 -0
- package/dist/parser/langs/dart.js.map +1 -0
- package/dist/parser/langs/go.d.ts +2 -0
- package/dist/parser/langs/go.js +455 -0
- package/dist/parser/langs/go.js.map +1 -0
- package/dist/parser/langs/java.d.ts +2 -0
- package/dist/parser/langs/java.js +390 -0
- package/dist/parser/langs/java.js.map +1 -0
- package/dist/parser/langs/php.d.ts +2 -0
- package/dist/parser/langs/php.js +486 -0
- package/dist/parser/langs/php.js.map +1 -0
- package/dist/parser/langs/python.d.ts +2 -0
- package/dist/parser/langs/python.js +216 -0
- package/dist/parser/langs/python.js.map +1 -0
- package/dist/parser/langs/ruby.d.ts +2 -0
- package/dist/parser/langs/ruby.js +602 -0
- package/dist/parser/langs/ruby.js.map +1 -0
- package/dist/parser/langs/rust.d.ts +2 -0
- package/dist/parser/langs/rust.js +931 -0
- package/dist/parser/langs/rust.js.map +1 -0
- package/dist/parser/langs/swift.d.ts +2 -0
- package/dist/parser/langs/swift.js +616 -0
- package/dist/parser/langs/swift.js.map +1 -0
- package/dist/parser/langs/typescript.d.ts +4 -0
- package/dist/parser/langs/typescript.js +535 -0
- package/dist/parser/langs/typescript.js.map +1 -0
- package/dist/parser/registry.d.ts +16 -0
- package/dist/parser/registry.js +87 -0
- package/dist/parser/registry.js.map +1 -0
- package/dist/parser/returns.d.ts +9 -0
- package/dist/parser/returns.js +152 -0
- package/dist/parser/returns.js.map +1 -0
- package/dist/parser/spec.d.ts +165 -0
- package/dist/parser/spec.js +188 -0
- package/dist/parser/spec.js.map +1 -0
- package/dist/query/arity.d.ts +27 -0
- package/dist/query/arity.js +187 -0
- package/dist/query/arity.js.map +1 -0
- package/dist/query/callgraph.d.ts +113 -0
- package/dist/query/callgraph.js +332 -0
- package/dist/query/callgraph.js.map +1 -0
- package/dist/query/format.d.ts +36 -0
- package/dist/query/format.js +136 -0
- package/dist/query/format.js.map +1 -0
- package/dist/query/hierarchy.d.ts +44 -0
- package/dist/query/hierarchy.js +441 -0
- package/dist/query/hierarchy.js.map +1 -0
- package/dist/query/resolve.d.ts +265 -0
- package/dist/query/resolve.js +1957 -0
- package/dist/query/resolve.js.map +1 -0
- package/dist/query/search.d.ts +35 -0
- package/dist/query/search.js +379 -0
- package/dist/query/search.js.map +1 -0
- package/dist/query/words.d.ts +30 -0
- package/dist/query/words.js +201 -0
- package/dist/query/words.js.map +1 -0
- package/dist/server/index.d.ts +1 -3
- package/dist/server/index.js +313 -73
- package/dist/server/index.js.map +1 -1
- package/dist/tools/context.d.ts +35 -0
- package/dist/tools/context.js +79 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/explore.d.ts +51 -0
- package/dist/tools/explore.js +779 -0
- package/dist/tools/explore.js.map +1 -0
- package/dist/tools/impact.d.ts +21 -0
- package/dist/tools/impact.js +743 -0
- package/dist/tools/impact.js.map +1 -0
- package/dist/tools/search.d.ts +59 -0
- package/dist/tools/search.js +843 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/stats.d.ts +26 -0
- package/dist/tools/stats.js +604 -0
- package/dist/tools/stats.js.map +1 -0
- package/dist/types.d.ts +95 -40
- package/dist/types.js +9 -1
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/dist/watcher/index.d.ts +18 -16
- package/dist/watcher/index.js +94 -77
- package/dist/watcher/index.js.map +1 -1
- package/package.json +21 -24
- package/plugin/server.mjs +50 -0
- package/skills/audit/SKILL.md +37 -0
- package/skills/deadcode/SKILL.md +33 -0
- package/skills/explore/SKILL.md +54 -0
- package/skills/impact/SKILL.md +24 -0
- package/skills/status/SKILL.md +11 -0
- package/src/cli.ts +256 -0
- package/src/config/defaults.ts +50 -32
- package/src/config/index.ts +23 -14
- package/src/db/index.ts +540 -43
- package/src/engine.ts +30 -0
- package/src/indexer/imports.ts +241 -0
- package/src/indexer/index.ts +369 -0
- package/src/indexer/process.ts +63 -0
- package/src/indexer/scan.ts +226 -0
- package/src/indexer/worker.ts +24 -0
- package/src/llm/comment-generator.ts +52 -103
- package/src/llm/index.ts +80 -80
- package/src/llm/prompts.ts +95 -95
- package/src/parser/extractor.ts +643 -256
- package/src/parser/index.ts +105 -205
- package/src/parser/langs/c.ts +860 -0
- package/src/parser/langs/csharp.ts +519 -0
- package/src/parser/langs/dart.ts +820 -0
- package/src/parser/langs/go.ts +437 -0
- package/src/parser/langs/java.ts +361 -0
- package/src/parser/langs/php.ts +450 -0
- package/src/parser/langs/python.ts +206 -0
- package/src/parser/langs/ruby.ts +554 -0
- package/src/parser/langs/rust.ts +904 -0
- package/src/parser/langs/swift.ts +590 -0
- package/src/parser/langs/typescript.ts +499 -0
- package/src/parser/registry.ts +88 -0
- package/src/parser/returns.ts +137 -0
- package/src/parser/spec.ts +309 -0
- package/src/query/arity.ts +173 -0
- package/src/query/callgraph.ts +473 -0
- package/src/query/format.ts +136 -0
- package/src/query/hierarchy.ts +447 -0
- package/src/query/resolve.ts +1972 -0
- package/src/query/search.ts +430 -0
- package/src/query/words.ts +183 -0
- package/src/server/index.ts +390 -79
- package/src/tools/context.ts +82 -0
- package/src/tools/explore.ts +860 -0
- package/src/tools/impact.ts +748 -0
- package/src/tools/search.ts +886 -0
- package/src/tools/stats.ts +633 -0
- package/src/types.ts +113 -45
- package/src/version.ts +2 -0
- package/src/watcher/index.ts +82 -88
- package/tsconfig.json +7 -4
- package/.mcp.json +0 -8
- package/commands/clast-status.md +0 -9
- package/dist/config/defaults.d.ts.map +0 -1
- package/dist/config/index.d.ts.map +0 -1
- package/dist/db/index.d.ts.map +0 -1
- package/dist/db/queries.d.ts +0 -44
- package/dist/db/queries.d.ts.map +0 -1
- package/dist/db/queries.js +0 -251
- package/dist/db/queries.js.map +0 -1
- package/dist/db/schema.d.ts +0 -3
- package/dist/db/schema.d.ts.map +0 -1
- package/dist/db/schema.js +0 -94
- package/dist/db/schema.js.map +0 -1
- package/dist/db/types.d.ts +0 -44
- package/dist/db/types.d.ts.map +0 -1
- package/dist/db/types.js +0 -2
- package/dist/db/types.js.map +0 -1
- package/dist/llm/comment-generator.d.ts.map +0 -1
- package/dist/llm/index.d.ts.map +0 -1
- package/dist/llm/prompts.d.ts.map +0 -1
- package/dist/parser/call-resolver.d.ts +0 -15
- package/dist/parser/call-resolver.d.ts.map +0 -1
- package/dist/parser/call-resolver.js +0 -16
- package/dist/parser/call-resolver.js.map +0 -1
- package/dist/parser/extractor.d.ts.map +0 -1
- package/dist/parser/index.d.ts.map +0 -1
- package/dist/parser/languages.d.ts +0 -11
- package/dist/parser/languages.d.ts.map +0 -1
- package/dist/parser/languages.js +0 -74
- package/dist/parser/languages.js.map +0 -1
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/register-tools.d.ts +0 -7
- package/dist/server/register-tools.d.ts.map +0 -1
- package/dist/server/register-tools.js +0 -17
- package/dist/server/register-tools.js.map +0 -1
- package/dist/server/tools/clast-call-graph.d.ts +0 -4
- package/dist/server/tools/clast-call-graph.d.ts.map +0 -1
- package/dist/server/tools/clast-call-graph.js +0 -70
- package/dist/server/tools/clast-call-graph.js.map +0 -1
- package/dist/server/tools/clast-comment.d.ts +0 -5
- package/dist/server/tools/clast-comment.d.ts.map +0 -1
- package/dist/server/tools/clast-comment.js +0 -64
- package/dist/server/tools/clast-comment.js.map +0 -1
- package/dist/server/tools/clast-file-summary.d.ts +0 -4
- package/dist/server/tools/clast-file-summary.d.ts.map +0 -1
- package/dist/server/tools/clast-file-summary.js +0 -42
- package/dist/server/tools/clast-file-summary.js.map +0 -1
- package/dist/server/tools/clast-get-context.d.ts +0 -4
- package/dist/server/tools/clast-get-context.d.ts.map +0 -1
- package/dist/server/tools/clast-get-context.js +0 -80
- package/dist/server/tools/clast-get-context.js.map +0 -1
- package/dist/server/tools/clast-reindex.d.ts +0 -5
- package/dist/server/tools/clast-reindex.d.ts.map +0 -1
- package/dist/server/tools/clast-reindex.js +0 -36
- package/dist/server/tools/clast-reindex.js.map +0 -1
- package/dist/server/tools/clast-search.d.ts +0 -4
- package/dist/server/tools/clast-search.d.ts.map +0 -1
- package/dist/server/tools/clast-search.js +0 -29
- package/dist/server/tools/clast-search.js.map +0 -1
- package/dist/server/tools/clast-status.d.ts +0 -5
- package/dist/server/tools/clast-status.d.ts.map +0 -1
- package/dist/server/tools/clast-status.js +0 -23
- package/dist/server/tools/clast-status.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/watcher/gitignore.d.ts +0 -9
- package/dist/watcher/gitignore.d.ts.map +0 -1
- package/dist/watcher/gitignore.js +0 -38
- package/dist/watcher/gitignore.js.map +0 -1
- package/dist/watcher/index.d.ts.map +0 -1
- package/skills/clast-explore/SKILL.md +0 -41
- package/src/db/queries.ts +0 -332
- package/src/db/schema.ts +0 -106
- package/src/db/types.ts +0 -47
- package/src/parser/call-resolver.ts +0 -17
- package/src/parser/languages.ts +0 -86
- package/src/server/register-tools.ts +0 -30
- package/src/server/tools/clast-call-graph.ts +0 -82
- package/src/server/tools/clast-comment.ts +0 -76
- package/src/server/tools/clast-file-summary.ts +0 -59
- package/src/server/tools/clast-get-context.ts +0 -97
- package/src/server/tools/clast-reindex.ts +0 -52
- package/src/server/tools/clast-search.ts +0 -38
- package/src/server/tools/clast-status.ts +0 -37
- package/src/watcher/gitignore.ts +0 -42
package/README.md
CHANGED
|
@@ -1,474 +1,533 @@
|
|
|
1
|
-
# Clast
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- **
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- **
|
|
1
|
+
# Clast v0.2
|
|
2
|
+
|
|
3
|
+
A code index for LLM coding agents, served over MCP. Clast parses your repository with
|
|
4
|
+
[tree-sitter](https://tree-sitter.github.io/), keeps a live index of symbols, calls, references, imports and
|
|
5
|
+
type relationships in SQLite, and exposes tools that answer navigation questions in one call instead of a
|
|
6
|
+
chain of greps and file reads.
|
|
7
|
+
|
|
8
|
+
What an agent gets:
|
|
9
|
+
|
|
10
|
+
- **Ranked symbol search** - exact names, partial names, abbreviations (`KProd`, `gcn`), typos, qualified
|
|
11
|
+
names (`Parser.parse`) and plain words (`resolve import path`) matched against names, signatures, docs
|
|
12
|
+
and what function bodies mention.
|
|
13
|
+
- **Exact symbol source** - the body of one function or class, read fresh from disk with line numbers,
|
|
14
|
+
together with its callers, callees, overrides and subtypes. No need to read the whole file.
|
|
15
|
+
- **Type-aware call graph** - calls are resolved with declared receiver types, imports, inheritance,
|
|
16
|
+
`this`/`self`/`super` and argument counts, so `record.topic()` goes to the right class, an overload
|
|
17
|
+
gets its own callers and `list.push()` is not mistaken for your `Stack.push`. Edges that are name-only
|
|
18
|
+
guesses are marked `?`.
|
|
19
|
+
- **References, type hierarchy, repo map, text search, git change impact** - see the tool list below.
|
|
20
|
+
- **Always fresh** - a file watcher re-indexes on save, and every query re-checks the files it is about to
|
|
21
|
+
quote, so line numbers and source are never stale, even right after the agent edits a file.
|
|
22
|
+
- **Fast** - parallel indexing in worker threads; warm start only stats files; queries take milliseconds.
|
|
23
|
+
- **No native compilation** - grammars are WASM, storage is Node's built-in `node:sqlite`.
|
|
24
|
+
|
|
25
|
+
Languages: TypeScript, TSX, JavaScript, Python, Java, C#, Go, Rust, C, C++, Ruby, PHP, Swift, Dart.
|
|
14
26
|
|
|
15
27
|
---
|
|
16
28
|
|
|
17
|
-
## Quick
|
|
29
|
+
## Quick start
|
|
18
30
|
|
|
19
|
-
|
|
31
|
+
Requires **Node.js 22.22 or newer** (Clast uses the built-in SQLite module).
|
|
20
32
|
|
|
21
|
-
|
|
22
|
-
npm install -g clast-ai
|
|
23
|
-
```
|
|
33
|
+
### As a Claude Code plugin (recommended)
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
In Claude Code:
|
|
26
36
|
|
|
27
|
-
```bash
|
|
28
|
-
npm install -g github:xls/clast
|
|
29
37
|
```
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
### Option 3: Clone and Build
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
git clone https://github.com/xls/clast.git
|
|
37
|
-
cd clast
|
|
38
|
-
npm install
|
|
39
|
-
npm run build
|
|
38
|
+
/plugin marketplace add xls/clast
|
|
39
|
+
/plugin install clast@clast
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
or from a shell: `claude plugin marketplace add xls/clast && claude plugin install clast@clast`.
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
cd clast
|
|
47
|
-
npm install && npm run build
|
|
48
|
-
claude plugin add /path/to/clast
|
|
49
|
-
```
|
|
44
|
+
The plugin brings the MCP server, a short skill that teaches Claude which tool answers which question,
|
|
45
|
+
and four slash commands:
|
|
50
46
|
|
|
51
|
-
|
|
47
|
+
| Command | What it does |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| `/clast:deadcode [path]` | Finds unused functions, methods and types, verifies the candidates, and removes the ones you confirm |
|
|
50
|
+
| `/clast:impact <symbol>` | What must change with a symbol, every caller, and the tests to run |
|
|
51
|
+
| `/clast:audit [path]` | Inventory for due diligence or onboarding: size, structure, endpoints, database access, dependencies, dead code |
|
|
52
|
+
| `/clast:status` | State of the index |
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
The plugin starts the server from a global `clast-ai` 0.2.x when there is one, otherwise through
|
|
55
|
+
`npx clast-ai@0.2` (downloaded on first use). Update with `/plugin update clast@clast`.
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
### As a plain MCP server
|
|
56
58
|
|
|
57
59
|
```bash
|
|
58
|
-
npm
|
|
59
|
-
|
|
60
|
+
npm install -g clast-ai
|
|
61
|
+
claude mcp add -s user clast clast-ai
|
|
60
62
|
```
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
---
|
|
64
|
+
`-s user` registers the server for all projects. This gives the tools without the skill and the slash
|
|
65
|
+
commands. Use one of the two ways, not both: with both, every tool is listed twice.
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
Either way, restart Claude Code (or "Developer: Reload Window" in VS Code) and run `/mcp`: `clast`
|
|
68
|
+
should be listed with 15 tools. The first start indexes the project in the background (seconds, about
|
|
69
|
+
half a minute for 15k files); until that first index is ready the tools answer with the build progress
|
|
70
|
+
and ask to be called again. Later starts are ready immediately.
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```json
|
|
71
|
-
{
|
|
72
|
-
"mcpServers": {
|
|
73
|
-
"clast": {
|
|
74
|
-
"command": "clast-ai"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Or using the CLI:
|
|
72
|
+
### Other ways
|
|
81
73
|
|
|
82
74
|
```bash
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
# alias command (npm package)
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
> `clast` is the local alias (shows up in `/mcp` and settings). `clast-ai` is the actual npm binary that gets executed. The alias can be anything you want.
|
|
89
|
-
|
|
90
|
-
Restart Claude Code (`Ctrl+Shift+P` → "Claude Code: Restart" in VS Code, or just relaunch the CLI). Clast will automatically index whichever project directory you open.
|
|
91
|
-
|
|
92
|
-
## Setup for VS Code (Claude Code Extension)
|
|
93
|
-
|
|
94
|
-
The Claude Code extension for VS Code uses the **same MCP configuration files** as the CLI. There is no separate VS Code-specific config.
|
|
95
|
-
|
|
96
|
-
**Step 1:** Open VS Code's integrated terminal and run:
|
|
75
|
+
# from GitHub, without npm
|
|
76
|
+
npm install -g github:xls/clast
|
|
97
77
|
|
|
98
|
-
|
|
99
|
-
|
|
78
|
+
# from a clone (also how to work on clast itself)
|
|
79
|
+
git clone https://github.com/xls/clast.git && cd clast
|
|
80
|
+
npm install && npm run build
|
|
81
|
+
claude mcp add -s user clast node /path/to/clast/dist/cli.js
|
|
82
|
+
claude --plugin-dir /path/to/clast # or: try the plugin from the clone for one session
|
|
100
83
|
```
|
|
101
84
|
|
|
102
|
-
|
|
85
|
+
Per-project registration for a team: put this in `.mcp.json` in the project root.
|
|
103
86
|
|
|
104
87
|
```json
|
|
105
|
-
{
|
|
106
|
-
"mcpServers": {
|
|
107
|
-
"clast": {
|
|
108
|
-
"command": "clast-ai"
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
88
|
+
{ "mcpServers": { "clast": { "command": "clast-ai" } } }
|
|
112
89
|
```
|
|
113
90
|
|
|
114
|
-
|
|
91
|
+
The project root is `CLAST_PROJECT_DIR`, else `CLAUDE_PROJECT_DIR`, else the working directory.
|
|
115
92
|
|
|
116
|
-
|
|
117
|
-
- Type "Claude Code: Restart" and hit Enter
|
|
118
|
-
|
|
119
|
-
**Step 3:** Verify by typing `/mcp` in the Claude Code chat panel — you should see `clast` listed with 7 tools.
|
|
120
|
-
|
|
121
|
-
> **Note:** When VS Code spawns the MCP server, the working directory is your open workspace folder. Clast automatically indexes that directory — no path configuration needed.
|
|
93
|
+
---
|
|
122
94
|
|
|
123
|
-
|
|
95
|
+
## Tools
|
|
96
|
+
|
|
97
|
+
| Tool | Answers | Typical use |
|
|
98
|
+
|------|---------|-------------|
|
|
99
|
+
| `clast_overview` | What is in this repo / directory? | First call in an unfamiliar codebase: languages, layout with sizes, most referenced symbols, hub files, entry points |
|
|
100
|
+
| `clast_file_summary` | What is in this file / directory? | Outline of a file (signatures, line ranges, doc summaries, imports, importers) or a directory listing with main symbols |
|
|
101
|
+
| `clast_search` | Where is X? What is it called? | Ranked symbol search by name, partial name, abbreviation, typo, qualified name or descriptive words (matched against names, signatures, docs and what function bodies mention) |
|
|
102
|
+
| `clast_get_context` | Show me X. | Source of one symbol plus callers, callees, overloads, overrides, subtypes. Batch several names in one call |
|
|
103
|
+
| `clast_call_graph` | Who calls X? What does X call? | Caller / callee tree to depth N, test callers separated, `within` path filter. Works for external names too |
|
|
104
|
+
| `clast_references` | Where is X used? | Every usage of an identifier (calls, types, imports, assignments) with the enclosing symbol of each line |
|
|
105
|
+
| `clast_hierarchy` | What implements / extends / overrides X? | Supertypes and transitive subtypes; Ruby mixins; Go interface satisfaction by method set (names plus parameter / result counts); the same method across related types; `within` path filter |
|
|
106
|
+
| `clast_grep` | Where does this text appear? | Literal or regex search over all text files; each hit is labelled with its enclosing function |
|
|
107
|
+
| `clast_changes` | What did this diff touch? | Symbols changed vs HEAD or a base ref, their callers outside the change, and the tests that exercise them |
|
|
108
|
+
| `clast_impact` | What breaks if I change X? Which tests do I run? | Declarations, overrides and implementations that must change together; every direct caller by file and line; how far it reaches through indirect callers; the test files that call it directly or through its callers |
|
|
109
|
+
| `clast_unused` | What is dead code? | Functions, methods and types nothing references (or only other unused code does), by file with line ranges; code used only by tests; names that only appear in strings or non-code files |
|
|
110
|
+
| `clast_stats` | How many X are there? What does this code base consist of? | Exact totals grouped by directory, file, kind or name; inventory, endpoints, database access, dependencies |
|
|
111
|
+
| `clast_status` | Is the index healthy? | Counts, languages, indexing progress, watcher state |
|
|
112
|
+
| `clast_reindex` | Rebuild | Rarely needed; incremental rescan or forced rebuild |
|
|
113
|
+
| `clast_comment` | Docs for X | Existing doc comment, or one generated by a local LLM (optional) |
|
|
114
|
+
|
|
115
|
+
All tools return compact plain text (not JSON): one line per fact, `path:line` locations that can be
|
|
116
|
+
passed straight to an editor, and a hint about the next useful call when something is not found.
|
|
117
|
+
|
|
118
|
+
### Addressing symbols
|
|
119
|
+
|
|
120
|
+
Anywhere a tool takes a symbol name you can write:
|
|
121
|
+
|
|
122
|
+
| Form | Example |
|
|
123
|
+
|------|---------|
|
|
124
|
+
| bare name | `parseConfig` |
|
|
125
|
+
| member | `Parser.parse`, `Parser::parse`, `Parser#parse` |
|
|
126
|
+
| inherited member | `Engine.GET` (defined on an embedded / base type) |
|
|
127
|
+
| package or module path | `django.shortcuts.render`, `page.Clear`, `Illuminate\Pipeline\Pipeline` |
|
|
128
|
+
| file and name | `src/db/index.ts:open` |
|
|
129
|
+
| file and line | `src/db/index.ts:120` (the symbol containing that line) |
|
|
130
|
+
|
|
131
|
+
When a bare name has many unrelated definitions the tools list them instead of guessing.
|
|
132
|
+
|
|
133
|
+
### Example
|
|
124
134
|
|
|
125
|
-
```json
|
|
126
|
-
{
|
|
127
|
-
"mcpServers": {
|
|
128
|
-
"clast": {
|
|
129
|
-
"command": "node",
|
|
130
|
-
"args": ["/path/to/clast/dist/server/index.js"]
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
135
|
```
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
}
|
|
136
|
+
> clast_get_context { "name": "cylinderVolume" }
|
|
137
|
+
|
|
138
|
+
function cylinderVolume src/math/volume.ts:4-6 [exported]
|
|
139
|
+
3| /** Volume of a cylinder. */
|
|
140
|
+
4| export function cylinderVolume(radius: number, height: number): number {
|
|
141
|
+
5| return circleArea(radius) * height;
|
|
142
|
+
6| }
|
|
143
|
+
callers (1 resolved):
|
|
144
|
+
main src/app.ts:10
|
|
145
|
+
calls (1):
|
|
146
|
+
circleArea src/math/area.ts:2-4
|
|
148
147
|
```
|
|
149
148
|
|
|
150
|
-
|
|
149
|
+
```
|
|
150
|
+
> clast_call_graph { "name": "MemTable.Add", "direction": "callers" }
|
|
151
|
+
|
|
152
|
+
method leveldb.MemTable.Add db/memtable.cc:76-100
|
|
153
|
+
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, const Slice& value)
|
|
154
|
+
callers (3; caller call-site):
|
|
155
|
+
leveldb.MemTableInserter.Put db/write_batch.cc:122
|
|
156
|
+
leveldb.MemTableInserter.Delete db/write_batch.cc:126
|
|
157
|
+
leveldb.MemTableConstructor.FinishImpl table/table_test.cc:315
|
|
158
|
+
```
|
|
151
159
|
|
|
152
160
|
---
|
|
153
161
|
|
|
154
|
-
##
|
|
155
|
-
|
|
156
|
-
### What happens when you start Claude Code?
|
|
157
|
-
|
|
158
|
-
1. Claude Code spawns the Clast MCP server as a background process
|
|
159
|
-
2. Clast automatically scans and indexes your entire project (typically under a second)
|
|
160
|
-
3. The file watcher starts monitoring for changes
|
|
161
|
-
4. All 7 `clast_*` tools become available to Claude
|
|
162
|
-
|
|
163
|
-
**You don't need to do anything** — the AST database is created automatically. There's no manual "index" step.
|
|
164
|
-
|
|
165
|
-
### How does Claude know to use Clast?
|
|
162
|
+
## How Claude knows to use it
|
|
166
163
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
- *"Use clast to find the Database class"*
|
|
172
|
-
- *"What calls parseAndStore? Check the call graph"*
|
|
173
|
-
- *"Show me the structure of queries.ts using clast"*
|
|
174
|
-
|
|
175
|
-
Or you can tell Claude once at the start of a session:
|
|
176
|
-
|
|
177
|
-
> *"Use the clast tools to navigate code instead of reading files directly"*
|
|
178
|
-
|
|
179
|
-
### What can you ask Claude?
|
|
180
|
-
|
|
181
|
-
| What you want | What to ask | Tool Claude uses |
|
|
182
|
-
|---------------|-------------|------------------|
|
|
183
|
-
| Find a function | *"Find the extractFromTree function"* | `clast_search` |
|
|
184
|
-
| Understand a function before editing | *"What does parseAndStore do? Show me its context"* | `clast_get_context` |
|
|
185
|
-
| Check what calls a function | *"What calls resolveCallEdges?"* | `clast_call_graph` |
|
|
186
|
-
| Understand a file's structure | *"What's in src/db/queries.ts?"* | `clast_file_summary` |
|
|
187
|
-
| Check if the index is working | *"Show clast status"* | `clast_status` |
|
|
188
|
-
| Force re-index after big changes | *"Reindex the project"* | `clast_reindex` |
|
|
189
|
-
| Generate a missing docstring | *"Generate a comment for the insertNodes function"* | `clast_comment` |
|
|
190
|
-
|
|
191
|
-
### Does the index stay up to date?
|
|
192
|
-
|
|
193
|
-
Yes. The file watcher detects changes in real-time:
|
|
194
|
-
|
|
195
|
-
- **File saved** → re-parsed, AST database updated, call edges re-resolved
|
|
196
|
-
- **File deleted** → removed from database
|
|
197
|
-
- **New file created** → parsed and added
|
|
198
|
-
|
|
199
|
-
Only changed files are re-parsed (SHA-256 hash comparison), so incremental updates are near-instant.
|
|
164
|
+
The server sends usage instructions to the client when it connects, and every tool description says when
|
|
165
|
+
to prefer it over grep or reading files. Installed as a plugin, the bundled `explore` skill adds a
|
|
166
|
+
short workflow guide. You can also say it once: "use the clast tools to navigate the code".
|
|
200
167
|
|
|
201
168
|
---
|
|
202
169
|
|
|
203
|
-
##
|
|
170
|
+
## Command line
|
|
204
171
|
|
|
205
|
-
|
|
172
|
+
The same queries are available from a shell, which is handy for scripts, hooks and debugging:
|
|
206
173
|
|
|
207
174
|
```bash
|
|
208
|
-
|
|
175
|
+
clast-ai overview # repository map
|
|
176
|
+
clast-ai outline src/db # directory or file outline
|
|
177
|
+
clast-ai search "resolve import path" # ranked symbol search
|
|
178
|
+
clast-ai symbol Indexer.indexAll # source + callers + callees
|
|
179
|
+
clast-ai callers resolveImports --depth 2 --no-tests
|
|
180
|
+
clast-ai hierarchy Shape
|
|
181
|
+
clast-ai refs DEFAULT_CONFIG
|
|
182
|
+
clast-ai grep "TODO" --path src
|
|
183
|
+
clast-ai changes main # symbols changed vs main and their impact
|
|
184
|
+
clast-ai impact Shape.area # what must change with it, callers, tests to run
|
|
185
|
+
clast-ai unused src/billing # dead code under a directory (or the whole project)
|
|
186
|
+
clast-ai index --force # rebuild the index
|
|
187
|
+
clast-ai parse file.go # debug: what the extractor sees
|
|
209
188
|
```
|
|
210
189
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## How It Detects Your Project
|
|
216
|
-
|
|
217
|
-
Clast resolves the project root in this order:
|
|
218
|
-
|
|
219
|
-
1. `CLAST_PROJECT_DIR` environment variable (explicit override)
|
|
220
|
-
2. `CLAUDE_PROJECT_DIR` (set automatically by Claude Code for plugins)
|
|
221
|
-
3. `process.cwd()` — the current working directory
|
|
222
|
-
|
|
223
|
-
**In most cases you don't need to set anything.** Claude Code (both CLI and VS Code) sets the working directory to your project folder when spawning MCP servers.
|
|
224
|
-
|
|
225
|
-
Override example (for indexing a different directory):
|
|
226
|
-
|
|
227
|
-
```json
|
|
228
|
-
{
|
|
229
|
-
"mcpServers": {
|
|
230
|
-
"clast": {
|
|
231
|
-
"command": "clast-ai",
|
|
232
|
-
"env": {
|
|
233
|
-
"CLAST_PROJECT_DIR": "/path/to/other/project"
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
---
|
|
241
|
-
|
|
242
|
-
## MCP Tools
|
|
243
|
-
|
|
244
|
-
| Tool | Description | Read-only |
|
|
245
|
-
|------|-------------|-----------|
|
|
246
|
-
| `clast_search` | Search symbols by name, type, or pattern | Yes |
|
|
247
|
-
| `clast_call_graph` | Trace callers/callees with configurable depth (1-5 levels) | Yes |
|
|
248
|
-
| `clast_file_summary` | All symbols in a file, grouped by type (imports, classes, functions, etc.) | Yes |
|
|
249
|
-
| `clast_get_context` | Full symbol context: definition, comments, callers, callees, parent class | Yes |
|
|
250
|
-
| `clast_status` | Index statistics: files, nodes, edges, watcher state | Yes |
|
|
251
|
-
| `clast_reindex` | Force re-index a specific file or the entire repo | No |
|
|
252
|
-
| `clast_comment` | Get existing or generate new documentation comments via LLM | No |
|
|
253
|
-
|
|
254
|
-
### Example Usage in Claude Code
|
|
255
|
-
|
|
256
|
-
- *"Search for the ParserManager class"* → Claude uses `clast_search`
|
|
257
|
-
- *"What calls the `parseAndStore` function?"* → Claude uses `clast_call_graph`
|
|
258
|
-
- *"Show me the structure of `src/db/queries.ts`"* → Claude uses `clast_file_summary`
|
|
259
|
-
- *"I need to refactor `extractFromTree` — what's the blast radius?"* → Claude uses `clast_get_context` + `clast_call_graph`
|
|
190
|
+
Add `--root <dir>` to point at another project. `clast-ai` with no arguments runs the MCP server.
|
|
260
191
|
|
|
261
192
|
---
|
|
262
193
|
|
|
263
194
|
## Configuration
|
|
264
195
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
To customize, create `clast.config.json` in your project root (or `.claude/clast.config.json`):
|
|
196
|
+
Optional. Create `clast.config.json` (or `.claude/clast.config.json`) in the project root:
|
|
268
197
|
|
|
269
198
|
```json
|
|
270
199
|
{
|
|
271
|
-
"languages": ["typescript", "
|
|
272
|
-
"ignoredPaths": ["node_modules", "
|
|
273
|
-
"
|
|
274
|
-
"
|
|
275
|
-
"
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
"apiKey": "",
|
|
279
|
-
"alwaysGenerate": false,
|
|
280
|
-
"maxConcurrent": 3
|
|
281
|
-
},
|
|
282
|
-
"watch": {
|
|
283
|
-
"debounceMs": 300,
|
|
284
|
-
"enabled": true
|
|
285
|
-
}
|
|
200
|
+
"languages": ["typescript", "python"],
|
|
201
|
+
"ignoredPaths": ["node_modules", "dist", "*.min.js"],
|
|
202
|
+
"respectGitignore": true,
|
|
203
|
+
"maxFileSize": 1000000,
|
|
204
|
+
"workers": 0,
|
|
205
|
+
"watch": { "enabled": true, "debounceMs": 200 },
|
|
206
|
+
"llm": { "endpoint": "http://localhost:11434/v1", "model": "" }
|
|
286
207
|
}
|
|
287
208
|
```
|
|
288
209
|
|
|
289
|
-
| Setting | Default |
|
|
290
|
-
|
|
291
|
-
| `languages` |
|
|
292
|
-
| `ignoredPaths` |
|
|
293
|
-
| `
|
|
294
|
-
| `
|
|
295
|
-
| `
|
|
296
|
-
| `
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
299
|
-
| `llm
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
| TypeScript | `typescript` | `.ts` |
|
|
308
|
-
| TSX | `tsx` | `.tsx` |
|
|
210
|
+
| Setting | Default | Meaning |
|
|
211
|
+
|---------|---------|---------|
|
|
212
|
+
| `languages` | all | Language ids to index (see below) |
|
|
213
|
+
| `ignoredPaths` | common build / dependency dirs | gitignore-style patterns to skip, in addition to `.gitignore` |
|
|
214
|
+
| `respectGitignore` | `true` | Honour `.gitignore` files, including nested ones |
|
|
215
|
+
| `dbPath` | `.clast/index.db` | Index location (the directory gets its own `.gitignore`) |
|
|
216
|
+
| `maxFileSize` | `1000000` | Skip files larger than this many bytes |
|
|
217
|
+
| `workers` | `0` (auto) | Parser threads for bulk indexing; `1` disables workers |
|
|
218
|
+
| `watch.enabled` | `true` | Re-index files as they change |
|
|
219
|
+
| `watch.debounceMs` | `200` | Debounce for file change events |
|
|
220
|
+
| `llm.*` | disabled | OpenAI-compatible endpoint for `clast_comment` generation |
|
|
221
|
+
|
|
222
|
+
Environment: `CLAST_PROJECT_DIR` (project root), `CLAST_DB_PATH` (index location override),
|
|
223
|
+
`CLAST_GRAMMARS_DIR` (alternative grammar directory), `CLAST_DEBUG=1` (timings and spec warnings).
|
|
224
|
+
|
|
225
|
+
| Language | id | Extensions |
|
|
226
|
+
|----------|----|------------|
|
|
227
|
+
| TypeScript | `typescript` (also enables `tsx`) | `.ts`, `.mts`, `.cts`, `.tsx` |
|
|
309
228
|
| JavaScript | `javascript` | `.js`, `.jsx`, `.mjs`, `.cjs` |
|
|
310
|
-
| Python | `python` | `.py`, `.pyw` |
|
|
229
|
+
| Python | `python` | `.py`, `.pyi`, `.pyw` |
|
|
311
230
|
| Java | `java` | `.java` |
|
|
312
231
|
| C# | `csharp` | `.cs` |
|
|
313
232
|
| Go | `go` | `.go` |
|
|
314
233
|
| Rust | `rust` | `.rs` |
|
|
315
|
-
| C | `c` | `.c`, `.h` |
|
|
316
|
-
| C++ | `cpp` | `.cpp`, `.hpp`, `.cc`, `.hh`, `.cxx`, `.hxx` |
|
|
317
|
-
| Ruby | `ruby` | `.rb` |
|
|
234
|
+
| C | `c` | `.c`, `.h` (headers that look like C++ are parsed as C++) |
|
|
235
|
+
| C++ | `cpp` | `.cpp`, `.hpp`, `.cc`, `.hh`, `.cxx`, `.hxx`, `.inl`, `.ipp` |
|
|
236
|
+
| Ruby | `ruby` | `.rb`, `.rake`, `.gemspec` |
|
|
318
237
|
| PHP | `php` | `.php` |
|
|
238
|
+
| Swift | `swift` | `.swift` |
|
|
239
|
+
| Dart | `dart` | `.dart` |
|
|
319
240
|
|
|
320
|
-
|
|
241
|
+
### Optional: generated doc comments
|
|
321
242
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
```
|
|
243
|
+
`clast_comment` can ask a local or hosted OpenAI-compatible model (Ollama, LM Studio, vLLM, OpenAI,
|
|
244
|
+
OpenRouter) to write a doc comment for an undocumented symbol. Set `llm.model` to enable it, for example
|
|
245
|
+
`{"llm": {"endpoint": "http://localhost:11434/v1", "model": "qwen2.5-coder:7b"}}` for Ollama. Generated
|
|
246
|
+
text is stored by file path and qualified name, so it survives re-indexing.
|
|
327
247
|
|
|
328
248
|
---
|
|
329
249
|
|
|
330
|
-
##
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
3.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
|
366
|
-
|
|
367
|
-
|
|
|
368
|
-
|
|
|
369
|
-
|
|
|
370
|
-
|
|
|
371
|
-
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
1.
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
"model": "qwen2.5-coder-7b-instruct"
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
> **Note:** The model name in `clast.config.json` must match exactly what LM Studio shows in its server panel.
|
|
392
|
-
|
|
393
|
-
### Setup with OpenAI / OpenRouter / Any Cloud API
|
|
394
|
-
|
|
395
|
-
Any service that exposes an OpenAI-compatible `/v1/chat/completions` endpoint works:
|
|
396
|
-
|
|
397
|
-
```json
|
|
398
|
-
{
|
|
399
|
-
"llm": {
|
|
400
|
-
"endpoint": "https://api.openai.com/v1",
|
|
401
|
-
"model": "gpt-4o-mini",
|
|
402
|
-
"apiKey": "sk-..."
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
**OpenRouter** (access many models via one API):
|
|
408
|
-
|
|
409
|
-
```json
|
|
410
|
-
{
|
|
411
|
-
"llm": {
|
|
412
|
-
"endpoint": "https://openrouter.ai/api/v1",
|
|
413
|
-
"model": "qwen/qwen-2.5-coder-32b-instruct",
|
|
414
|
-
"apiKey": "sk-or-..."
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### Setup with vLLM (Self-Hosted)
|
|
420
|
-
|
|
421
|
-
If you run [vLLM](https://docs.vllm.ai/) on a server or cloud GPU:
|
|
422
|
-
|
|
423
|
-
```json
|
|
424
|
-
{
|
|
425
|
-
"llm": {
|
|
426
|
-
"endpoint": "http://your-server:8000/v1",
|
|
427
|
-
"model": "Qwen/Qwen2.5-Coder-7B-Instruct"
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
```
|
|
250
|
+
## How it works
|
|
251
|
+
|
|
252
|
+
1. **Scan** - walk the tree honouring `.gitignore` (root and nested) and `ignoredPaths`; compare size and
|
|
253
|
+
mtime with the index so an unchanged file costs one `stat`.
|
|
254
|
+
2. **Parse** - changed files are read, hashed and parsed by a pool of worker threads (tree-sitter WASM).
|
|
255
|
+
A per-language spec turns the syntax tree into symbols (with qualified names, signatures, doc comments,
|
|
256
|
+
line ranges), calls (with receiver text and declared receiver type), imports, inheritance and
|
|
257
|
+
identifier occurrences.
|
|
258
|
+
3. **Store** - the main thread writes to SQLite (`node:sqlite`, WAL). A cold index uses a bulk-load mode
|
|
259
|
+
that builds secondary indexes at the end. Symbol names, signatures and docs also go into an FTS5 index.
|
|
260
|
+
4. **Link at query time** - call edges are stored as "symbol A calls name N on receiver R of type T" and
|
|
261
|
+
resolved when queried, so nothing goes stale when another file changes. Resolution order: declared
|
|
262
|
+
receiver type, then imports and same-file definitions, then `this`/`self` and inheritance, then
|
|
263
|
+
evidence scoring for untyped receivers. Argument counts separate overloads and rule out same-named
|
|
264
|
+
methods of another shape. A call through an interface or base type counts as a caller of the
|
|
265
|
+
implementations it can reach (Go's structural interfaces as "possible"); a call bound to a subclass
|
|
266
|
+
override does not count for the base method, and `super.m()` binds to the inherited method. Types
|
|
267
|
+
are told apart by more than their name where the language allows it: Go packages (`pkg.Type`
|
|
268
|
+
against the file's imports), imports and packages in TS / Python / Java / PHP, C# generic arity and
|
|
269
|
+
partial classes, Ruby lexical constant lookup, Rust module paths.
|
|
270
|
+
5. **Stay fresh** - a watcher re-indexes saved files; in addition every tool re-checks the files it is
|
|
271
|
+
about to quote and re-parses them on the spot if they changed.
|
|
272
|
+
|
|
273
|
+
The index lives in `.clast/index.db` and is a pure cache: delete it at any time.
|
|
274
|
+
|
|
275
|
+
### Performance
|
|
276
|
+
|
|
277
|
+
Measured with `npm run bench` (Node 24, Windows 11, Ryzen 9950X3D, up to 12 parser workers). Cold index is a first run on an
|
|
278
|
+
empty index; warm rescan is a restart with nothing changed.
|
|
279
|
+
|
|
280
|
+
<!-- BENCH:START -->
|
|
281
|
+
| repo | files | symbols | cold index | warm rescan | db size | search (name) | search (words) | symbol + callers/callees | callers depth 2 | references |
|
|
282
|
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
283
|
+
| vscode | 15726 | 461365 | 26.1 s | 1895 ms | 357 MB | 168 ms | 42 ms | 28 ms | 38 ms | 11 ms |
|
|
284
|
+
| aspnetcore | 11470 | 145271 | 10.2 s | 1382 ms | 135 MB | 9.3 ms | 86 ms | 33 ms | 38 ms | 6.6 ms |
|
|
285
|
+
| kafka | 6481 | 126393 | 9.5 s | 863 ms | 144 MB | 26 ms | 33 ms | 25 ms | 962 ms | 5.6 ms |
|
|
286
|
+
| rails | 3580 | 61549 | 3.8 s | 352 ms | 52 MB | 8.7 ms | 15 ms | 22 ms | 35 ms | 3.0 ms |
|
|
287
|
+
| framework | 3180 | 44124 | 3.0 s | 337 ms | 38 MB | 1.4 ms | 46 ms | 23 ms | 23 ms | 2.2 ms |
|
|
288
|
+
| django | 2987 | 60131 | 3.1 s | 522 ms | 42 MB | 29 ms | 41 ms | 21 ms | 48 ms | 2.5 ms |
|
|
289
|
+
| fastapi | 1224 | 10049 | 0.8 s | 161 ms | 7 MB | 5.0 ms | 17 ms | 5.7 ms | 48 ms | 2.4 ms |
|
|
290
|
+
| hugo | 939 | 16896 | 1.1 s | 127 ms | 11 MB | 7.2 ms | 38 ms | 18 ms | 18 ms | 2.4 ms |
|
|
291
|
+
| redis | 919 | 35752 | 1.9 s | 103 ms | 23 MB | 5.7 ms | 16 ms | 7.0 ms | 26 ms | 2.2 ms |
|
|
292
|
+
| tokio | 816 | 12341 | 1.1 s | 85 ms | 11 MB | 3.9 ms | 17 ms | 2.0 ms | 4.2 ms | 1.4 ms |
|
|
293
|
+
| http | 362 | 3947 | 0.7 s | 75 ms | 3 MB | 1.3 ms | 9.6 ms | 3.5 ms | 1.6 ms | 5.3 ms |
|
|
294
|
+
| express | 142 | 439 | 0.4 s | 20 ms | 1 MB | 0.4 ms | 1.0 ms | 0.8 ms | 0.5 ms | 1.6 ms |
|
|
295
|
+
| leveldb | 133 | 3456 | 0.6 s | 14 ms | 2 MB | 2.2 ms | 15 ms | 3.3 ms | 1.8 ms | 2.5 ms |
|
|
296
|
+
| Alamofire | 107 | 4085 | 1.5 s | 23 ms | 4 MB | 2.4 ms | 7.1 ms | 1.5 ms | 530 ms | 1.3 ms |
|
|
297
|
+
| ripgrep | 103 | 4496 | 0.6 s | 13 ms | 3 MB | 1.3 ms | 13 ms | 1.3 ms | 1.4 ms | 0.5 ms |
|
|
298
|
+
| gin | 99 | 2157 | 0.4 s | 12 ms | 2 MB | 1.5 ms | 7.7 ms | 2.2 ms | 4.3 ms | 0.7 ms |
|
|
299
|
+
| spring-petclinic | 50 | 323 | 0.2 s | 11 ms | 1 MB | 0.8 ms | 0.7 ms | 0.6 ms | 0.6 ms | 1.3 ms |
|
|
300
|
+
|
|
301
|
+
Node v24.7.0, win32 x64. Query times are medians of 5 in-process runs on the most-called function of each repo.
|
|
302
|
+
<!-- BENCH:END -->
|
|
303
|
+
|
|
304
|
+
Worst case measured: `callers IDisposable.dispose` on vscode (10.7k call sites, 4.7k definitions of
|
|
305
|
+
`dispose`) takes 5-6 s. Scoped with `within` it is fast.
|
|
431
306
|
|
|
432
307
|
---
|
|
433
308
|
|
|
434
|
-
##
|
|
309
|
+
## Clast vs grep + read
|
|
310
|
+
|
|
311
|
+
Measured with real headless Claude Code sessions (`bench/ab.mjs`): every question runs in its own
|
|
312
|
+
fresh session, once with clast connected and once with only Read / Grep / Glob. Two large repositories:
|
|
313
|
+
vscode (TypeScript, 15.7k files) and OnAir (C++, 7.5k files, 1.6M lines). The index was fully built
|
|
314
|
+
before the first session. Answers are scored against facts verified in the source beforehand; an
|
|
315
|
+
implementation task is scored on its diff.
|
|
316
|
+
|
|
317
|
+
"Cost" is the API-price equivalent that Claude Code reports for the session. It weights fresh input and
|
|
318
|
+
output above cached prompt tokens, so it is the closest single number to "tokens that matter".
|
|
319
|
+
|
|
320
|
+
| Kind of work | Repo | Sessions per arm | Tool calls (clast / grep) | Wall time | Cost per question | Correct |
|
|
321
|
+
| --- | --- | ---: | ---: | ---: | ---: | ---: |
|
|
322
|
+
| Multi-hop questions (call chains, transitive subclasses, impact) | vscode | 18 | 1.3 / 3.1 | 16.0 s / 19.8 s | $0.063 / $0.126 | 18 / 18 |
|
|
323
|
+
| Multi-hop questions | OnAir | 18 | 1.2 / 5.9 | 12.5 s / 25.8 s | $0.056 / $0.212 | 18 / 18 |
|
|
324
|
+
| Simple lookups (where is X, who calls X, what implements X) | vscode | 30 | 1.4 / 1.4 | 13.9 s / 13.9 s | $0.053 / $0.059 | 30 / 29 |
|
|
325
|
+
| Simple lookups | OnAir | 30 | 1.7 / 1.7 | 12.7 s / 14.3 s | $0.063 / $0.096 | 30 / 30 |
|
|
326
|
+
| Counting ("how many receiver classes under core/") | OnAir | 3 | 1.0 / 3.3 | 11 s / 34 s | about $0.02 / $0.29 | 3 / 2 |
|
|
327
|
+
| Small implementation tasks (new provider, new enum value, new subclass) | vscode | 6 | 7.5 / 8.5 | 30 s / 31 s | $0.29 / $0.24 | 6 / 6 |
|
|
328
|
+
| Small implementation tasks | OnAir | 6 | 11.5 / 12.8 | 39 s / 40 s | $0.58 / $0.56 | 6 / 6 |
|
|
329
|
+
| Cross-cutting refactors (rename a method in 28 files, add a parameter and update all callers) | vscode | 4 | 21.8 / 22.0 | 47 s / 48 s | $0.45 / $0.37 | 4 / 4 |
|
|
330
|
+
| Cross-cutting refactors | OnAir | 4 | 9.8 / 7.8 | 26 s / 25 s | $0.25 / $0.24 | 4 / 4 |
|
|
331
|
+
| Before a change (tests that reach a function, files to edit for a signature change, dead functions in a file) | vscode | 9 | 2.3 / 2.2 | 19.3 s / 19.8 s | $0.098 / $0.154 | 9 / 9 |
|
|
332
|
+
| Before a change | OnAir | 9 | 1.7 / 3.6 | 14.3 s / 17.4 s | $0.126 / $0.173 | 9 / 9 |
|
|
333
|
+
| Find dead code in a directory ("five unused functions under app/", answers checked by hand) | OnAir | 2 | 2.0 / 16.0 | 20 s / 124 s | $0.15 / $1.89 | 2 / 2 |
|
|
334
|
+
| Questions that describe behaviour without naming anything ("what takes out the spike in the middle of the spectrum") | OnAir | 12 | 1.8 / 4.2 | 12.0 s / 20.5 s | $0.068 / $0.197 | 12 / 12 |
|
|
335
|
+
| Questions that describe behaviour | vscode | 12 | 1.0 / 1.0 | 11.7 s / 11.8 s | $0.048 / $0.044 | 12 / 12 |
|
|
336
|
+
|
|
337
|
+
What this says:
|
|
338
|
+
|
|
339
|
+
- **Multi-hop questions are where clast pays off**: half the cost and 20% less time on vscode, a
|
|
340
|
+
quarter of the cost and half the time on OnAir. One call returns a call chain or a full inheritance
|
|
341
|
+
tree that grep needs three to twelve rounds for, and the agent reads 70-85% less tool output.
|
|
342
|
+
- **Simple lookups are a tie.** A current model with ripgrep answers them in one or two calls; clast
|
|
343
|
+
does not make that faster, it only returns a little less text.
|
|
344
|
+
- **Counting is faster and exact** with `clast_stats`. With grep the agent tallied matches by hand and
|
|
345
|
+
was off by one in one of three runs.
|
|
346
|
+
- **Finding dead code is the largest gap measured**: one `clast_unused` call and a confirming grep
|
|
347
|
+
against 11-21 greps, a sixth of the time and a thirteenth of the cost. Every function either arm
|
|
348
|
+
named was verified unused, and all ten the grep sessions found are in clast's list.
|
|
349
|
+
- **Describing behaviour instead of naming it** works on a repository the model has never seen
|
|
350
|
+
(OnAir): search over names, comments and what function bodies mention finds the place in one or two
|
|
351
|
+
calls where grep needs four rounds of guessing words. On vscode it is a tie at one call, because the
|
|
352
|
+
model already knows where things are in vscode; that row measures the model's memory, not the tools.
|
|
353
|
+
- **Questions before a change are cheaper, not always faster.** With `clast_impact` and `clast_unused`
|
|
354
|
+
the sessions cost 27-36% less because the agent reads less tool output. The clear win is "which
|
|
355
|
+
tests reach this function when none names it": 1 call and 11 s against 5.7 calls and 22 s on OnAir.
|
|
356
|
+
"Which files do I edit for a signature change" is one grep and stays a tie.
|
|
357
|
+
- **Implementation work showed no benefit**, neither small features nor cross-cutting refactors. Both
|
|
358
|
+
arms made the same edits in the same files in the same time (refactors were also checked for
|
|
359
|
+
completeness: nothing of the old name or call shape left). Finding every occurrence of one name is
|
|
360
|
+
a single grep, and before editing the agent reads the neighbouring code either way. Clast costs a
|
|
361
|
+
little more here because its tool definitions are in the prompt.
|
|
362
|
+
- **Small samples.** Two repositories, three runs per question, questions written by the tool's
|
|
363
|
+
author. The figures show the direction, not a precise ratio.
|
|
364
|
+
|
|
365
|
+
One result changed the server itself. Claude Code defers MCP tools behind its tool search by default,
|
|
366
|
+
and in that state the agent never called clast: 0 of 60 sessions, every question answered with Grep.
|
|
367
|
+
The navigation tools now ask the client to keep them loaded, after which the agent used clast in every
|
|
368
|
+
question session where it helped. The cost is about 5k tokens of tool definitions and instructions in
|
|
369
|
+
the cached prompt (measured with 13 tools: 23.7k against 19.3k prompt tokens for a session that calls
|
|
370
|
+
no tool; `clast_impact` and `clast_unused` add about 0.6k).
|
|
371
|
+
|
|
372
|
+
Reproduce with `node bench/ab.mjs <repo> bench/ab/<set>.json --runs 3`. The question sets are in
|
|
373
|
+
`bench/ab/`.
|
|
374
|
+
|
|
375
|
+
### Answer quality
|
|
376
|
+
|
|
377
|
+
Reviewer agents asked deliberately hard questions on 17 real repositories and checked every answer
|
|
378
|
+
against the source. Over the last five rounds the share of first answers judged correct rose from
|
|
379
|
+
roughly 45-60% to 65-78%, with new questions each round.
|
|
380
|
+
|
|
381
|
+
Two further audits read the cited source lines for call edges that clast shows as certain (no `?`):
|
|
382
|
+
|
|
383
|
+
| Repo | Language | Wrong | Checked |
|
|
384
|
+
| --- | --- | ---: | ---: |
|
|
385
|
+
| kafka | Java | 0 | 57 |
|
|
386
|
+
| tokio | Rust | 0 | 17 |
|
|
387
|
+
| laravel | PHP | 0 | 19 |
|
|
388
|
+
| vscode | TypeScript | 1 | 45 |
|
|
389
|
+
| django | Python | 1 | 39 |
|
|
390
|
+
| aspnetcore | C# | 1 | 58 |
|
|
391
|
+
| hugo | Go | 1 | 19 |
|
|
392
|
+
| rails | Ruby | 4 | 18 |
|
|
393
|
+
|
|
394
|
+
The vscode and aspnetcore errors were fixed afterwards; the django, hugo and rails ones are open (see
|
|
395
|
+
Known limitations).
|
|
435
396
|
|
|
436
|
-
|
|
437
|
-
2. **Storage** — Extracted symbols (functions, classes, methods, imports, etc.) are stored in a SQLite database at `.clast/clast.db`, along with SHA-256 file hashes
|
|
438
|
-
3. **Call graph** — Call relationships are extracted from function bodies and resolved across files using name matching
|
|
439
|
-
4. **Watching** — A file watcher detects changes and incrementally re-indexes only modified files (hash comparison skips unchanged files)
|
|
440
|
-
5. **Querying** — Claude Code queries the AST database through MCP tools instead of reading raw files, getting structured context with file paths and line numbers
|
|
441
|
-
|
|
442
|
-
### What Gets Indexed
|
|
443
|
-
|
|
444
|
-
For each supported file, Clast extracts:
|
|
445
|
-
- **Functions and methods** — name, signature, body, line numbers
|
|
446
|
-
- **Classes, interfaces, structs, traits** — with their methods as children
|
|
447
|
-
- **Imports and exports** — module relationships
|
|
448
|
-
- **Enums and type aliases**
|
|
449
|
-
- **Call edges** — which function calls which (resolved across files)
|
|
450
|
-
- **Comments and docstrings** — linked to their parent symbol
|
|
451
|
-
|
|
452
|
-
### Database Location
|
|
397
|
+
---
|
|
453
398
|
|
|
454
|
-
|
|
399
|
+
## Changelog
|
|
400
|
+
|
|
401
|
+
### 0.2.0
|
|
402
|
+
|
|
403
|
+
New tools (7 to 13):
|
|
404
|
+
|
|
405
|
+
- `clast_references`: every use of a symbol, not just calls.
|
|
406
|
+
- `clast_hierarchy`: supertypes, subtypes, implementers and overrides, including Go structural
|
|
407
|
+
interfaces and Ruby mixins.
|
|
408
|
+
- `clast_overview`: map of a repository or directory.
|
|
409
|
+
- `clast_grep`: text search over all text files with the enclosing symbol on every hit.
|
|
410
|
+
- `clast_changes`: symbols touched by a git diff, plus their callers.
|
|
411
|
+
- `clast_impact`: for one symbol, what has to change with it (declarations, overrides, implementations,
|
|
412
|
+
overloads), every direct caller by file and line, the reach through indirect callers, and the test
|
|
413
|
+
files to run, including tests that only reach it through its callers.
|
|
414
|
+
- `clast_unused`: dead code. A name counts as unused when it is never referenced outside its own
|
|
415
|
+
definitions, or only from other unused code (so a deleted feature's helpers are found with it).
|
|
416
|
+
Reported separately: code used only by tests, names that still appear in a string, config or
|
|
417
|
+
template, and (Java, C#, C, C++, Rust) methods whose every call binds to another definition. Left
|
|
418
|
+
out, with counts: entry points, decorated or attribute-marked symbols, subclasses of library types
|
|
419
|
+
and their methods, object-literal members, exported Go methods, C# extension classes.
|
|
420
|
+
- `clast_stats`: exact counts grouped by directory, file, kind or name: inventory, symbols by name
|
|
421
|
+
pattern, direct and indirect subtypes, call sites by name and receiver, text matches, external
|
|
422
|
+
dependencies, and pattern-based inventories of HTTP / RPC endpoints and database access.
|
|
423
|
+
|
|
424
|
+
Call graph:
|
|
425
|
+
|
|
426
|
+
- Calls are resolved at query time using declared receiver types, imports and aliases, field types
|
|
427
|
+
across files, return types of call chains, inheritance and `super`.
|
|
428
|
+
- Edges are shown as certain, uncertain, or `?` (matched by name only).
|
|
429
|
+
- Argument counts separate overloads. A bare name means all overloads; `path:line` selects one.
|
|
430
|
+
- A call bound to a subclass override no longer counts as a caller of the base method.
|
|
431
|
+
- Language rules: Go packages and structural interfaces, Rust `impl Trait for Arc<T>` and std types,
|
|
432
|
+
C# generic arity / partial / static classes, Ruby mixins and bare calls, Java static imports, Python
|
|
433
|
+
submodule calls and imported instances, TypeScript renamed re-exports, C macro bodies, C++ namespace
|
|
434
|
+
functions.
|
|
435
|
+
|
|
436
|
+
Search:
|
|
437
|
+
|
|
438
|
+
- Ranked by exact name, prefix, abbreviation, typo and plain words.
|
|
439
|
+
- Descriptive queries also match what function bodies mention (marked `[body]`).
|
|
440
|
+
- Overloads fold into one hit.
|
|
441
|
+
|
|
442
|
+
Performance and storage:
|
|
443
|
+
|
|
444
|
+
- `node:sqlite` on disk (WAL, FTS5) replaces in-memory sql.js.
|
|
445
|
+
- Parsing runs in worker threads, with an inline fallback if a worker fails.
|
|
446
|
+
- The server connects first and indexes afterwards; on a first build, tools wait for the index.
|
|
447
|
+
- A watcher re-indexes changed files, and every tool re-checks the files it quotes.
|
|
448
|
+
|
|
449
|
+
Other:
|
|
450
|
+
|
|
451
|
+
- Swift and Dart added (14 languages).
|
|
452
|
+
- All dependencies updated (MCP SDK 1.32, web-tree-sitter 0.27).
|
|
453
|
+
- 283 tests, plus `bench/bench.mjs`, `bench/resolution.mjs` and the A/B harness `bench/ab.mjs`.
|
|
454
|
+
- Installable as a Claude Code plugin from this repository (`/plugin marketplace add xls/clast`,
|
|
455
|
+
`/plugin install clast@clast`): the MCP server, a usage skill, and the slash commands
|
|
456
|
+
`/clast:deadcode`, `/clast:impact`, `/clast:audit` and `/clast:status`. The old VS Code extension
|
|
457
|
+
scaffold that wrote the server into `.claude/settings.local.json` is removed.
|
|
458
|
+
- The navigation tools ask Claude Code to keep them loaded instead of deferring them behind tool
|
|
459
|
+
search; deferred, the agent never called them.
|
|
460
|
+
- Ruby classes and their ancestors are compared by qualified name (`Rails::Generators::Base` is not
|
|
461
|
+
`ActiveRecord::Base`; `Thor::Group` is not a project class called `Group`).
|
|
462
|
+
- C++ functions declared through a head-building macro (`FN(jstring, nativeStart)(args)`) are indexed
|
|
463
|
+
under their real name.
|
|
464
|
+
- C / C++ function pointers whose calling convention is a macro (`err_t (MY_CALL* find)(args)`) are
|
|
465
|
+
indexed as a field called `find`, not as a method called `err_t`.
|
|
466
|
+
|
|
467
|
+
### Upgrading from 0.1
|
|
468
|
+
|
|
469
|
+
- Node.js 22.22+ is required (was 18).
|
|
470
|
+
- The index moved from `.clast/clast.db` (sql.js) to `.clast/index.db` (`node:sqlite`). Nothing is
|
|
471
|
+
migrated: the index is a cache and is rebuilt on first start. The old file is ignored and can be
|
|
472
|
+
deleted.
|
|
473
|
+
- A later schema change deletes and rebuilds the index automatically (the schema is at version 26).
|
|
474
|
+
- Tool output is compact text instead of JSON.
|
|
475
|
+
- `clast_call_graph` defaults to depth 1 and gained `within` and `includeTests`.
|
|
476
|
+
- The binary entry point is `dist/cli.js`; `dist/server/index.js` still starts the server for old configs.
|
|
455
477
|
|
|
456
478
|
---
|
|
457
479
|
|
|
458
|
-
##
|
|
480
|
+
## Known limitations
|
|
481
|
+
|
|
482
|
+
- **Untyped receivers**: `obj.save()` in dynamic code cannot be attributed. Such calls are listed as
|
|
483
|
+
"receiver type unknown", not guessed.
|
|
484
|
+
- **Same-named types**: classes with the same short name in different PHP namespaces or Java packages
|
|
485
|
+
can be confused when the calling file gives no hint.
|
|
486
|
+
- **Ruby**: the least exercised language. The rails audit found 4 wrong edges of 18 with one cause
|
|
487
|
+
(classes called `Base` in different namespaces treated as one family); classes are now compared by
|
|
488
|
+
qualified name, which fixes that case, but Ruby has not been re-audited since. Methods defined by
|
|
489
|
+
metaprogramming are invisible.
|
|
490
|
+
- **Overloads**: those that differ only in parameter types, not count, are one target.
|
|
491
|
+
- **Generics and inference**: no generic substitution; TypeScript return types are known only when
|
|
492
|
+
annotated.
|
|
493
|
+
- **Framework conventions**: Django managers, Laravel facades and container lookups, and services
|
|
494
|
+
injected by string are not modelled.
|
|
495
|
+
- **Python**: a local variable that holds a class is not followed.
|
|
496
|
+
- **Go**: a call through a chain of fields can be attributed to the wrong type; the module path is
|
|
497
|
+
inferred from imports, not from go.mod.
|
|
498
|
+
- **Swift**: the grammar fails on some files depending on parse order, which can drop a class while
|
|
499
|
+
keeping its members. Swift and Dart are new and less exercised.
|
|
500
|
+
- **Dead code is judged by name**: a member whose name is also used by other symbols (`get`, `run`,
|
|
501
|
+
`close`) is never listed, so the list is incomplete for common method names; calls built from
|
|
502
|
+
strings at run time are only caught when the prefix is a literal (`getattr(x, "as_" + vendor)`).
|
|
503
|
+
In a spot check of 8-12 random findings per repository (kafka, aspnetcore, vscode, django, tokio,
|
|
504
|
+
hugo, OnAir) against a word grep, the remaining wrong ones were convention-based discovery (Django
|
|
505
|
+
`AppConfig` classes inside Django itself). Treat the list as candidates and let the compiler or the
|
|
506
|
+
tests confirm a deletion.
|
|
507
|
+
- **Search is lexical**: a description that shares no word with the code finds the neighbourhood, not
|
|
508
|
+
always the function.
|
|
509
|
+
- **Not indexed**: Kotlin, Scala and other languages without a bundled grammar. `clast_grep` still
|
|
510
|
+
searches those files as text.
|
|
511
|
+
- **Size and cold start**: the index takes about 12-25 MB per 1,000 source files; a cold index of
|
|
512
|
+
vscode takes about 26 s.
|
|
513
|
+
|
|
514
|
+
The full list with examples is in [docs/v0.2-summary.md](docs/v0.2-summary.md).
|
|
459
515
|
|
|
460
|
-
|
|
461
|
-
- Auto-detects workspace folders
|
|
462
|
-
- Configures Claude Code's MCP settings automatically
|
|
463
|
-
- Provides commands: `Clast: Reindex`, `Clast: Status`, `Clast: Configure`
|
|
516
|
+
---
|
|
464
517
|
|
|
465
|
-
|
|
518
|
+
## Development
|
|
466
519
|
|
|
467
|
-
|
|
520
|
+
```bash
|
|
521
|
+
npm install
|
|
522
|
+
npm run build # tsc
|
|
523
|
+
npm test # node:test, 260+ tests incl. an end-to-end MCP session
|
|
524
|
+
npm run bench -- /path/to/dir-with-repos
|
|
525
|
+
```
|
|
468
526
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
-
|
|
527
|
+
Adding a language: create `src/parser/langs/<name>.ts` exporting a `LangSpec` (see `typescript.ts` and
|
|
528
|
+
`python.ts` for the two reference implementations), register it in `src/parser/registry.ts`, and add a
|
|
529
|
+
test under `test/langs/`. `clast-ai ast <file>` dumps the syntax tree and `clast-ai parse <file>` shows what
|
|
530
|
+
your spec extracts. The grammar must be available in `@repomix/tree-sitter-wasms`.
|
|
472
531
|
|
|
473
532
|
## License
|
|
474
533
|
|