@szabadkai/graphite 0.1.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/README.md +427 -0
- package/dist/cli/formatters.d.ts +3 -0
- package/dist/cli/formatters.js +61 -0
- package/dist/cli/formatters.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +186 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/call-resolver.d.ts +8 -0
- package/dist/indexer/call-resolver.js +161 -0
- package/dist/indexer/call-resolver.js.map +1 -0
- package/dist/indexer/extractors/calls.d.ts +17 -0
- package/dist/indexer/extractors/calls.js +206 -0
- package/dist/indexer/extractors/calls.js.map +1 -0
- package/dist/indexer/extractors/classes.d.ts +35 -0
- package/dist/indexer/extractors/classes.js +209 -0
- package/dist/indexer/extractors/classes.js.map +1 -0
- package/dist/indexer/extractors/exports.d.ts +12 -0
- package/dist/indexer/extractors/exports.js +267 -0
- package/dist/indexer/extractors/exports.js.map +1 -0
- package/dist/indexer/extractors/functions.d.ts +12 -0
- package/dist/indexer/extractors/functions.js +169 -0
- package/dist/indexer/extractors/functions.js.map +1 -0
- package/dist/indexer/extractors/imports.d.ts +12 -0
- package/dist/indexer/extractors/imports.js +195 -0
- package/dist/indexer/extractors/imports.js.map +1 -0
- package/dist/indexer/extractors/index.d.ts +7 -0
- package/dist/indexer/extractors/index.js +24 -0
- package/dist/indexer/extractors/index.js.map +1 -0
- package/dist/indexer/extractors/types.d.ts +12 -0
- package/dist/indexer/extractors/types.js +138 -0
- package/dist/indexer/extractors/types.js.map +1 -0
- package/dist/indexer/extractors/variables.d.ts +10 -0
- package/dist/indexer/extractors/variables.js +134 -0
- package/dist/indexer/extractors/variables.js.map +1 -0
- package/dist/indexer/file-discovery.d.ts +7 -0
- package/dist/indexer/file-discovery.js +92 -0
- package/dist/indexer/file-discovery.js.map +1 -0
- package/dist/indexer/file-indexer.d.ts +2 -0
- package/dist/indexer/file-indexer.js +267 -0
- package/dist/indexer/file-indexer.js.map +1 -0
- package/dist/indexer/graph-contract.d.ts +25 -0
- package/dist/indexer/graph-contract.js +7 -0
- package/dist/indexer/graph-contract.js.map +1 -0
- package/dist/indexer/hasher.d.ts +1 -0
- package/dist/indexer/hasher.js +11 -0
- package/dist/indexer/hasher.js.map +1 -0
- package/dist/indexer/import-resolver.d.ts +11 -0
- package/dist/indexer/import-resolver.js +131 -0
- package/dist/indexer/import-resolver.js.map +1 -0
- package/dist/indexer/index.d.ts +11 -0
- package/dist/indexer/index.js +28 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/inheritance-resolver.d.ts +7 -0
- package/dist/indexer/inheritance-resolver.js +119 -0
- package/dist/indexer/inheritance-resolver.js.map +1 -0
- package/dist/indexer/parser.d.ts +5 -0
- package/dist/indexer/parser.js +48 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/path-utils.d.ts +3 -0
- package/dist/indexer/path-utils.js +20 -0
- package/dist/indexer/path-utils.js.map +1 -0
- package/dist/indexer/project-indexer.d.ts +14 -0
- package/dist/indexer/project-indexer.js +167 -0
- package/dist/indexer/project-indexer.js.map +1 -0
- package/dist/indexer/property-parsers.d.ts +20 -0
- package/dist/indexer/property-parsers.js +81 -0
- package/dist/indexer/property-parsers.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.js +20 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/response-formatter.d.ts +10 -0
- package/dist/mcp/response-formatter.js +47 -0
- package/dist/mcp/response-formatter.js.map +1 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.js +118 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools-list.d.ts +9 -0
- package/dist/mcp/tools-list.js +12 -0
- package/dist/mcp/tools-list.js.map +1 -0
- package/dist/mcp/tools.d.ts +13 -0
- package/dist/mcp/tools.js +163 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/query/analyze-impact.d.ts +18 -0
- package/dist/query/analyze-impact.js +58 -0
- package/dist/query/analyze-impact.js.map +1 -0
- package/dist/query/find-callees.d.ts +12 -0
- package/dist/query/find-callees.js +46 -0
- package/dist/query/find-callees.js.map +1 -0
- package/dist/query/find-callers.d.ts +12 -0
- package/dist/query/find-callers.js +46 -0
- package/dist/query/find-callers.js.map +1 -0
- package/dist/query/find-definition.d.ts +3 -0
- package/dist/query/find-definition.js +41 -0
- package/dist/query/find-definition.js.map +1 -0
- package/dist/query/find-dependency-path.d.ts +2 -0
- package/dist/query/find-dependency-path.js +39 -0
- package/dist/query/find-dependency-path.js.map +1 -0
- package/dist/query/find-implementations.d.ts +10 -0
- package/dist/query/find-implementations.js +34 -0
- package/dist/query/find-implementations.js.map +1 -0
- package/dist/query/get-exports.d.ts +3 -0
- package/dist/query/get-exports.js +82 -0
- package/dist/query/get-exports.js.map +1 -0
- package/dist/query/get-file-structure.d.ts +3 -0
- package/dist/query/get-file-structure.js +58 -0
- package/dist/query/get-file-structure.js.map +1 -0
- package/dist/query/get-graph-stats.d.ts +21 -0
- package/dist/query/get-graph-stats.js +42 -0
- package/dist/query/get-graph-stats.js.map +1 -0
- package/dist/query/index.d.ts +11 -0
- package/dist/query/index.js +28 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/search-symbols.d.ts +6 -0
- package/dist/query/search-symbols.js +75 -0
- package/dist/query/search-symbols.js.map +1 -0
- package/dist/query/types.d.ts +41 -0
- package/dist/query/types.js +36 -0
- package/dist/query/types.js.map +1 -0
- package/dist/storage/database.d.ts +13 -0
- package/dist/storage/database.js +49 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/index.d.ts +7 -0
- package/dist/storage/index.js +24 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/migrations/001_initial.sql +59 -0
- package/dist/storage/migrations/002_add_name_index.sql +9 -0
- package/dist/storage/migrator.d.ts +9 -0
- package/dist/storage/migrator.js +86 -0
- package/dist/storage/migrator.js.map +1 -0
- package/dist/storage/paths.d.ts +5 -0
- package/dist/storage/paths.js +25 -0
- package/dist/storage/paths.js.map +1 -0
- package/dist/storage/reader.d.ts +10 -0
- package/dist/storage/reader.js +103 -0
- package/dist/storage/reader.js.map +1 -0
- package/dist/storage/schema.d.ts +14 -0
- package/dist/storage/schema.js +18 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/storage/types.d.ts +42 -0
- package/dist/storage/types.js +3 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/writer.d.ts +13 -0
- package/dist/storage/writer.js +160 -0
- package/dist/storage/writer.js.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
# Graphite
|
|
2
|
+
|
|
3
|
+
A local-first semantic code graph for TypeScript and JavaScript. Index your project once, then query its structure — who calls what, where things are defined, how files depend on each other — from the CLI, an MCP-enabled AI assistant, or the VS Code sidebar.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Quick Start](#quick-start)
|
|
11
|
+
- [Usage: CLI](#usage-cli)
|
|
12
|
+
- [Usage: MCP Server (AI Assistants)](#usage-mcp-server-ai-assistants)
|
|
13
|
+
- [Usage: VS Code Extension](#usage-vs-code-extension)
|
|
14
|
+
- [Query Reference](#query-reference)
|
|
15
|
+
- [Configuration](#configuration)
|
|
16
|
+
- [Architecture](#architecture)
|
|
17
|
+
- [Supported Languages](#supported-languages)
|
|
18
|
+
- [Limitations](#limitations)
|
|
19
|
+
- [Contributing](#contributing)
|
|
20
|
+
- [License](#license)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Install locally in your project
|
|
28
|
+
npm install graphite
|
|
29
|
+
|
|
30
|
+
# Or run without installing
|
|
31
|
+
npx graphite index
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
For the VS Code extension, install from the `vscode-extension/` directory:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cd vscode-extension
|
|
38
|
+
npm install && npm run compile
|
|
39
|
+
# Then press F5 in VS Code to launch the Extension Development Host
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# 1. Index your project (creates .graphite/index.db)
|
|
48
|
+
npx graphite index
|
|
49
|
+
|
|
50
|
+
# 2. Find where a function is defined
|
|
51
|
+
npx graphite query find_definition processPayment
|
|
52
|
+
|
|
53
|
+
# 3. Find who calls it
|
|
54
|
+
npx graphite query find_callers processPayment
|
|
55
|
+
|
|
56
|
+
# 4. Start the MCP server for AI assistants
|
|
57
|
+
npx graphite serve
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Usage: CLI
|
|
63
|
+
|
|
64
|
+
The CLI has four commands: `index`, `query`, `status`, and `serve`.
|
|
65
|
+
|
|
66
|
+
### Global Options
|
|
67
|
+
|
|
68
|
+
| Flag | Description |
|
|
69
|
+
|------|-------------|
|
|
70
|
+
| `--project-root <path>` | Project root (default: current directory) |
|
|
71
|
+
| `--json` | Output raw JSON instead of human-readable tables |
|
|
72
|
+
| `--verbose` | Show timing information |
|
|
73
|
+
|
|
74
|
+
### `graphite index`
|
|
75
|
+
|
|
76
|
+
Index (or re-index) the current project. Uses content hashing for incremental updates — unchanged files are skipped.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Index the current directory
|
|
80
|
+
graphite index
|
|
81
|
+
|
|
82
|
+
# Index a specific project
|
|
83
|
+
graphite index --project-root /path/to/project
|
|
84
|
+
|
|
85
|
+
# Get JSON output for scripting
|
|
86
|
+
graphite index --json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Output example:
|
|
90
|
+
```
|
|
91
|
+
Indexed 142/142 files (38 new, 12 updated, 2 deleted, 90 skipped, 0 failed)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `graphite status`
|
|
95
|
+
|
|
96
|
+
Show the current state of the index.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
graphite status
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Output example:
|
|
103
|
+
```
|
|
104
|
+
Graphite Status
|
|
105
|
+
Files 142
|
|
106
|
+
Nodes Function:89, Class:23, Method:67, Interface:12, TypeAlias:8, Variable:34
|
|
107
|
+
Edges CONTAINS:156, IMPORTS:78, EXPORTS:102, CALLS:213, EXTENDS:5, IMPLEMENTS:8
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### `graphite query <tool> [args...]`
|
|
111
|
+
|
|
112
|
+
Run any of the 10 query tools. The first positional argument after the tool name is the primary argument (usually a symbol name or file path). The second is an optional secondary argument.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Find a symbol's definition
|
|
116
|
+
graphite query find_definition UserService
|
|
117
|
+
|
|
118
|
+
# Search symbols by prefix
|
|
119
|
+
graphite query search_symbols handle
|
|
120
|
+
|
|
121
|
+
# Get the structure of a file
|
|
122
|
+
graphite query get_file_structure src/services/auth.ts
|
|
123
|
+
|
|
124
|
+
# Get a file's exports
|
|
125
|
+
graphite query get_exports src/utils/index.ts
|
|
126
|
+
|
|
127
|
+
# Find callers of a function (with depth)
|
|
128
|
+
graphite query find_callers processPayment --depth 3
|
|
129
|
+
|
|
130
|
+
# Find callees of a function
|
|
131
|
+
graphite query find_callees handleRequest --depth 2
|
|
132
|
+
|
|
133
|
+
# Find implementations of an interface
|
|
134
|
+
graphite query find_implementations EventHandler
|
|
135
|
+
|
|
136
|
+
# Analyze blast radius of changing a symbol
|
|
137
|
+
graphite query analyze_impact createUser --max-depth 5
|
|
138
|
+
|
|
139
|
+
# Find the import path between two files
|
|
140
|
+
graphite query find_dependency_path src/app.ts src/db/client.ts
|
|
141
|
+
|
|
142
|
+
# Get overall graph statistics
|
|
143
|
+
graphite query get_graph_stats
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### Query Options
|
|
147
|
+
|
|
148
|
+
| Flag | Applies to | Description |
|
|
149
|
+
|------|-----------|-------------|
|
|
150
|
+
| `--depth <n>` | `find_callers`, `find_callees` | Traversal depth (default: 1) |
|
|
151
|
+
| `--max-results <n>` | `find_callers`, `find_callees`, `search_symbols` | Max results (default: 50) |
|
|
152
|
+
| `--max-depth <n>` | `analyze_impact` | Max reverse-traversal depth (default: 5) |
|
|
153
|
+
|
|
154
|
+
### `graphite serve`
|
|
155
|
+
|
|
156
|
+
Start the MCP server on stdio. This is what AI assistants connect to.
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
graphite serve
|
|
160
|
+
graphite serve --project-root /path/to/project
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The server auto-indexes the project on the first tool call if no index exists.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Usage: MCP Server (AI Assistants)
|
|
168
|
+
|
|
169
|
+
Graphite exposes all 10 query tools as an MCP server. Any MCP-compatible client can use it.
|
|
170
|
+
|
|
171
|
+
### GitHub Copilot (VS Code)
|
|
172
|
+
|
|
173
|
+
**Option A: Install the VS Code extension** (recommended)
|
|
174
|
+
|
|
175
|
+
The Graphite VS Code extension automatically registers the MCP server with Copilot. Install the extension and it works out of the box — Copilot can immediately use all 10 tools.
|
|
176
|
+
|
|
177
|
+
**Option B: Manual configuration**
|
|
178
|
+
|
|
179
|
+
Add to your VS Code `settings.json`:
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"mcp": {
|
|
184
|
+
"servers": {
|
|
185
|
+
"graphite": {
|
|
186
|
+
"type": "stdio",
|
|
187
|
+
"command": "npx",
|
|
188
|
+
"args": ["graphite", "serve", "--project-root", "${workspaceFolder}"]
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Or add a `.vscode/mcp.json` to your project:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"servers": {
|
|
200
|
+
"graphite": {
|
|
201
|
+
"type": "stdio",
|
|
202
|
+
"command": "npx",
|
|
203
|
+
"args": ["graphite", "serve"]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Claude Desktop
|
|
210
|
+
|
|
211
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or the equivalent on your OS:
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"mcpServers": {
|
|
216
|
+
"graphite": {
|
|
217
|
+
"command": "npx",
|
|
218
|
+
"args": ["graphite", "serve", "--project-root", "/absolute/path/to/your/project"]
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Claude Code (CLI)
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
claude mcp add graphite -- npx graphite serve --project-root /path/to/project
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Cursor
|
|
231
|
+
|
|
232
|
+
Add to Cursor's MCP config (Settings → MCP):
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"mcpServers": {
|
|
237
|
+
"graphite": {
|
|
238
|
+
"command": "npx",
|
|
239
|
+
"args": ["graphite", "serve", "--project-root", "/path/to/project"]
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Any MCP Client
|
|
246
|
+
|
|
247
|
+
Graphite uses stdio transport. Spawn the process and communicate via stdin/stdout:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
npx graphite serve --project-root /path/to/project
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Usage: VS Code Extension
|
|
256
|
+
|
|
257
|
+
The extension lives in `vscode-extension/` and provides a graphical interface to the code graph.
|
|
258
|
+
|
|
259
|
+
### Sidebar Panels
|
|
260
|
+
|
|
261
|
+
Open the **Graphite** sidebar (type-hierarchy icon in the activity bar):
|
|
262
|
+
|
|
263
|
+
- **File Structure** — Shows all symbols in the current file (functions, classes with methods, interfaces, types, enums, variables). Click any symbol to jump to it. Updates automatically when you switch files.
|
|
264
|
+
- **Callers** — Shows functions that call the selected symbol. Use right-click → "Find Callers" to populate.
|
|
265
|
+
- **Callees** — Shows functions called by the selected symbol. Use right-click → "Find Callees" to populate.
|
|
266
|
+
|
|
267
|
+
### Commands
|
|
268
|
+
|
|
269
|
+
Open the Command Palette (`Cmd+Shift+P`) and type "Graphite":
|
|
270
|
+
|
|
271
|
+
| Command | What it does |
|
|
272
|
+
|---------|--------------|
|
|
273
|
+
| **Graphite: Index Project** | Manually trigger a full re-index |
|
|
274
|
+
| **Graphite: Show Index Status** | Opens a document showing file/node/edge counts |
|
|
275
|
+
| **Graphite: Find Callers** | Finds callers of the word under cursor, shows in sidebar |
|
|
276
|
+
| **Graphite: Find Callees** | Finds callees of the word under cursor, shows in sidebar |
|
|
277
|
+
| **Graphite: Find Definition** | Jumps to definition (or shows a picker if multiple) |
|
|
278
|
+
| **Graphite: Find Implementations** | Shows implementations of an interface/class |
|
|
279
|
+
| **Graphite: Analyze Impact** | Opens blast radius analysis for the word under cursor |
|
|
280
|
+
| **Graphite: Refresh Explorer** | Refreshes all sidebar panels |
|
|
281
|
+
|
|
282
|
+
### Context Menu
|
|
283
|
+
|
|
284
|
+
Right-click in any TypeScript/JavaScript file to access:
|
|
285
|
+
|
|
286
|
+
- Find Callers
|
|
287
|
+
- Find Callees
|
|
288
|
+
- Find Implementations
|
|
289
|
+
- Analyze Impact
|
|
290
|
+
|
|
291
|
+
### Auto-Indexing
|
|
292
|
+
|
|
293
|
+
By default, the extension indexes the project on activation and re-indexes when you save a `.ts`/`.js` file. Disable with:
|
|
294
|
+
|
|
295
|
+
```json
|
|
296
|
+
{
|
|
297
|
+
"graphite.autoIndex": false
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Copilot Integration
|
|
302
|
+
|
|
303
|
+
When the extension is active in VS Code 1.99+, it automatically registers the Graphite MCP server with GitHub Copilot. Copilot can then use all 10 tools in chat without any manual MCP configuration.
|
|
304
|
+
|
|
305
|
+
### Extension Settings
|
|
306
|
+
|
|
307
|
+
| Setting | Default | Description |
|
|
308
|
+
|---------|---------|-------------|
|
|
309
|
+
| `graphite.autoIndex` | `true` | Auto-index on activation and file changes |
|
|
310
|
+
| `graphite.maxDepth` | `3` | Default depth for caller/callee traversal |
|
|
311
|
+
| `graphite.maxResults` | `50` | Maximum results for queries |
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Query Reference
|
|
316
|
+
|
|
317
|
+
| Tool | Description | Required Args | Optional Args |
|
|
318
|
+
|------|-------------|--------------|---------------|
|
|
319
|
+
| `find_definition` | Locate where a symbol is defined | `symbol` | `type` |
|
|
320
|
+
| `search_symbols` | Prefix search across all symbols | `query` | `type`, `max_results` |
|
|
321
|
+
| `get_file_structure` | All symbols in a file, grouped by type | `file_path` | — |
|
|
322
|
+
| `get_exports` | Public exports of a file or module | `file_or_module` | — |
|
|
323
|
+
| `find_callers` | Who calls this function (multi-hop) | `symbol` | `depth`, `max_results` |
|
|
324
|
+
| `find_callees` | What does this function call (multi-hop) | `symbol` | `depth`, `max_results` |
|
|
325
|
+
| `get_graph_stats` | Summary stats for the entire graph | — | — |
|
|
326
|
+
| `find_implementations` | Classes implementing an interface/extending a class | `symbol` | — |
|
|
327
|
+
| `analyze_impact` | Blast radius: all affected files/symbols | `symbol` | `max_depth` |
|
|
328
|
+
| `find_dependency_path` | Shortest import chain between two files | `source_file`, `target_file` | — |
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## Configuration
|
|
333
|
+
|
|
334
|
+
### `.graphiteignore`
|
|
335
|
+
|
|
336
|
+
Place a `.graphiteignore` file in your project root (same syntax as `.gitignore`) to exclude additional paths from indexing:
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
# Skip generated code
|
|
340
|
+
src/generated/**
|
|
341
|
+
*.d.ts
|
|
342
|
+
|
|
343
|
+
# Skip test fixtures
|
|
344
|
+
test/fixtures/**
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
The indexer always skips: `node_modules`, `.git`, `.graphite`, `dist`, `build`, `coverage`.
|
|
348
|
+
|
|
349
|
+
### `tsconfig.json` Path Aliases
|
|
350
|
+
|
|
351
|
+
Graphite reads your `tsconfig.json` and respects `compilerOptions.paths` and `baseUrl` for import resolution:
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"compilerOptions": {
|
|
356
|
+
"baseUrl": "src",
|
|
357
|
+
"paths": {
|
|
358
|
+
"@utils/*": ["utils/*"],
|
|
359
|
+
"@services/*": ["services/*"]
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Imports like `import { foo } from '@utils/helpers'` will resolve correctly.
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Architecture
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
src/
|
|
373
|
+
indexer/ Tree-sitter parsing, AST extraction, cross-file stitching
|
|
374
|
+
storage/ SQLite schema, migrations, read/write layers
|
|
375
|
+
query/ 10 query functions (callers, callees, impact, etc.)
|
|
376
|
+
cli/ Commander.js CLI with 4 commands
|
|
377
|
+
mcp/ MCP server, tool registry, LLM response formatting
|
|
378
|
+
|
|
379
|
+
vscode-extension/
|
|
380
|
+
src/ VS Code extension: sidebar, commands, MCP registration
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
- **Indexer**: tree-sitter parses TS/JS → extracts functions, classes, imports, exports → resolves cross-file calls and inheritance → stores as nodes + edges in SQLite
|
|
384
|
+
- **Storage**: SQLite with WAL mode, FTS5 for symbol search, prepared statements for performance
|
|
385
|
+
- **Query**: SQL queries using recursive CTEs for multi-hop traversal
|
|
386
|
+
- **MCP**: Stdio transport, auto-index on first call, response truncation for LLMs
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Supported Languages
|
|
391
|
+
|
|
392
|
+
| Language | Extensions |
|
|
393
|
+
|----------|-----------|
|
|
394
|
+
| TypeScript | `.ts`, `.tsx` |
|
|
395
|
+
| JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` |
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Limitations
|
|
400
|
+
|
|
401
|
+
- TypeScript and JavaScript only (no Python/Go/Rust yet)
|
|
402
|
+
- No real-time file watcher (re-index on save via VS Code extension, or run `graphite index` manually)
|
|
403
|
+
- Local projects only (no remote/SSH indexing)
|
|
404
|
+
- Dynamic `import()` expressions are not resolved
|
|
405
|
+
- CommonJS `module.exports =` patterns have limited support
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## Contributing
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
git clone <repo>
|
|
413
|
+
cd graphite
|
|
414
|
+
npm install
|
|
415
|
+
npm run build
|
|
416
|
+
npm test
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
- See [docs/PRD.md](docs/PRD.md) for the product requirements
|
|
420
|
+
- See [docs/TASKS.md](docs/TASKS.md) for the task list and architecture notes
|
|
421
|
+
- Run benchmarks: `npm run benchmark:indexer`
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## License
|
|
426
|
+
|
|
427
|
+
MIT
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatKeyValueBlock = formatKeyValueBlock;
|
|
4
|
+
exports.formatList = formatList;
|
|
5
|
+
exports.formatTable = formatTable;
|
|
6
|
+
function formatKeyValueBlock(title, entries) {
|
|
7
|
+
const lines = [title];
|
|
8
|
+
for (const [key, value] of entries) {
|
|
9
|
+
lines.push(` ${key}: ${value}`);
|
|
10
|
+
}
|
|
11
|
+
return lines.join("\n");
|
|
12
|
+
}
|
|
13
|
+
function formatList(title, lines) {
|
|
14
|
+
return [title, ...lines.map((line) => ` - ${line}`)].join("\n");
|
|
15
|
+
}
|
|
16
|
+
// M7: Human-readable table output for query results
|
|
17
|
+
function formatTable(title, rows) {
|
|
18
|
+
if (rows.length === 0) {
|
|
19
|
+
return `${title}\n (no results)`;
|
|
20
|
+
}
|
|
21
|
+
// Pick display columns from the first row
|
|
22
|
+
const sample = rows[0];
|
|
23
|
+
const displayKeys = Object.keys(sample).filter((key) => {
|
|
24
|
+
const value = sample[key];
|
|
25
|
+
return typeof value !== "object" || value === null;
|
|
26
|
+
});
|
|
27
|
+
if (displayKeys.length === 0) {
|
|
28
|
+
// Fallback to JSON
|
|
29
|
+
return formatList(title, rows.map((row) => JSON.stringify(row)));
|
|
30
|
+
}
|
|
31
|
+
// Compute column widths
|
|
32
|
+
const widths = new Map();
|
|
33
|
+
for (const key of displayKeys) {
|
|
34
|
+
widths.set(key, key.length);
|
|
35
|
+
}
|
|
36
|
+
for (const row of rows) {
|
|
37
|
+
const record = row;
|
|
38
|
+
for (const key of displayKeys) {
|
|
39
|
+
const value = String(record[key] ?? "");
|
|
40
|
+
const current = widths.get(key) ?? 0;
|
|
41
|
+
widths.set(key, Math.max(current, Math.min(value.length, 60)));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const header = displayKeys.map((key) => key.padEnd(widths.get(key) ?? 0)).join(" ");
|
|
45
|
+
const separator = displayKeys.map((key) => "-".repeat(widths.get(key) ?? 0)).join(" ");
|
|
46
|
+
const dataLines = rows.slice(0, 50).map((row) => {
|
|
47
|
+
const record = row;
|
|
48
|
+
return displayKeys
|
|
49
|
+
.map((key) => {
|
|
50
|
+
const value = String(record[key] ?? "");
|
|
51
|
+
return value.slice(0, 60).padEnd(widths.get(key) ?? 0);
|
|
52
|
+
})
|
|
53
|
+
.join(" ");
|
|
54
|
+
});
|
|
55
|
+
const lines = [title, ` ${header}`, ` ${separator}`, ...dataLines.map((line) => ` ${line}`)];
|
|
56
|
+
if (rows.length > 50) {
|
|
57
|
+
lines.push(` ... and ${rows.length - 50} more`);
|
|
58
|
+
}
|
|
59
|
+
return lines.join("\n");
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=formatters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/cli/formatters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.runCli = runCli;
|
|
5
|
+
const commander_1 = require("commander");
|
|
6
|
+
const index_1 = require("../index");
|
|
7
|
+
const formatters_1 = require("./formatters");
|
|
8
|
+
function printJson(value) {
|
|
9
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
10
|
+
}
|
|
11
|
+
function createProgram() {
|
|
12
|
+
const program = new commander_1.Command();
|
|
13
|
+
program
|
|
14
|
+
.name("graphite")
|
|
15
|
+
.description("Local-first semantic code index and query CLI")
|
|
16
|
+
.version("0.1.0")
|
|
17
|
+
.option("--json", "output JSON", false)
|
|
18
|
+
.option("--project-root <path>", "project root path", process.cwd())
|
|
19
|
+
.option("--verbose", "verbose output", false);
|
|
20
|
+
program
|
|
21
|
+
.command("index")
|
|
22
|
+
.description("Index a project")
|
|
23
|
+
.action(() => {
|
|
24
|
+
const options = program.opts();
|
|
25
|
+
const manager = (0, index_1.connectDatabase)({ projectRoot: options.projectRoot });
|
|
26
|
+
try {
|
|
27
|
+
// M9: Use verbose flag for timing info
|
|
28
|
+
const start = Date.now();
|
|
29
|
+
const summary = (0, index_1.indexProject)({ projectRoot: options.projectRoot, db: manager.db });
|
|
30
|
+
const elapsed = Date.now() - start;
|
|
31
|
+
if (options.json) {
|
|
32
|
+
printJson(summary);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
process.stdout.write(`${(0, index_1.printIndexSummary)(summary)}\n`);
|
|
36
|
+
if (options.verbose) {
|
|
37
|
+
process.stdout.write(`Completed in ${elapsed}ms\n`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
manager.close();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
program
|
|
46
|
+
.command("status")
|
|
47
|
+
.description("Show graph status")
|
|
48
|
+
.action(() => {
|
|
49
|
+
const options = program.opts();
|
|
50
|
+
const manager = (0, index_1.connectDatabase)({ projectRoot: options.projectRoot });
|
|
51
|
+
try {
|
|
52
|
+
const stats = (0, index_1.getGraphStats)(manager.db);
|
|
53
|
+
if (options.json) {
|
|
54
|
+
printJson(stats);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
process.stdout.write(`${(0, formatters_1.formatKeyValueBlock)("Graphite Status", [
|
|
58
|
+
["Files", stats.totalFiles],
|
|
59
|
+
["Nodes", stats.nodeCountByType.map((item) => `${item.type}:${item.count}`).join(", ")],
|
|
60
|
+
["Edges", stats.edgeCountByType.map((item) => `${item.type}:${item.count}`).join(", ")]
|
|
61
|
+
])}\n`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
manager.close();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// M10: Add --depth and --max-results options to query command
|
|
69
|
+
program
|
|
70
|
+
.command("query")
|
|
71
|
+
.description("Run a query tool")
|
|
72
|
+
.argument("<tool>", "tool name")
|
|
73
|
+
.argument("[arg1]", "first argument")
|
|
74
|
+
.argument("[arg2]", "second argument")
|
|
75
|
+
.option("--depth <n>", "traversal depth for caller/callee queries", parseInt)
|
|
76
|
+
.option("--max-results <n>", "maximum results to return", parseInt)
|
|
77
|
+
.option("--max-depth <n>", "max depth for impact analysis", parseInt)
|
|
78
|
+
.action((tool, arg1, arg2, cmdOpts) => {
|
|
79
|
+
const options = program.opts();
|
|
80
|
+
const manager = (0, index_1.connectDatabase)({ projectRoot: options.projectRoot });
|
|
81
|
+
let result;
|
|
82
|
+
try {
|
|
83
|
+
const requireArg = (name, value) => {
|
|
84
|
+
if (!value || value.trim().length === 0) {
|
|
85
|
+
throw new Error(`Missing required query argument: ${name}`);
|
|
86
|
+
}
|
|
87
|
+
return value;
|
|
88
|
+
};
|
|
89
|
+
// M9: Verbose timing
|
|
90
|
+
const start = Date.now();
|
|
91
|
+
switch (tool) {
|
|
92
|
+
case "find_definition":
|
|
93
|
+
result = (0, index_1.findDefinition)(manager.db, requireArg("symbol", arg1), arg2);
|
|
94
|
+
break;
|
|
95
|
+
case "search_symbols":
|
|
96
|
+
result = (0, index_1.searchSymbols)(manager.db, requireArg("query", arg1), {
|
|
97
|
+
type: arg2,
|
|
98
|
+
maxResults: cmdOpts.maxResults
|
|
99
|
+
});
|
|
100
|
+
break;
|
|
101
|
+
case "get_file_structure":
|
|
102
|
+
result = (0, index_1.getFileStructure)(manager.db, requireArg("file_path", arg1));
|
|
103
|
+
break;
|
|
104
|
+
case "get_exports":
|
|
105
|
+
result = (0, index_1.getExports)(manager.db, requireArg("file_or_module", arg1));
|
|
106
|
+
break;
|
|
107
|
+
case "find_callers":
|
|
108
|
+
result = (0, index_1.findCallers)(manager.db, requireArg("symbol", arg1), {
|
|
109
|
+
depth: cmdOpts.depth,
|
|
110
|
+
maxResults: cmdOpts.maxResults
|
|
111
|
+
});
|
|
112
|
+
break;
|
|
113
|
+
case "find_callees":
|
|
114
|
+
result = (0, index_1.findCallees)(manager.db, requireArg("symbol", arg1), {
|
|
115
|
+
depth: cmdOpts.depth,
|
|
116
|
+
maxResults: cmdOpts.maxResults
|
|
117
|
+
});
|
|
118
|
+
break;
|
|
119
|
+
case "get_graph_stats":
|
|
120
|
+
result = (0, index_1.getGraphStats)(manager.db);
|
|
121
|
+
break;
|
|
122
|
+
case "find_implementations":
|
|
123
|
+
result = (0, index_1.findImplementations)(manager.db, requireArg("symbol", arg1));
|
|
124
|
+
break;
|
|
125
|
+
case "analyze_impact":
|
|
126
|
+
result = (0, index_1.analyzeImpact)(manager.db, requireArg("symbol", arg1), {
|
|
127
|
+
maxDepth: cmdOpts.maxDepth
|
|
128
|
+
});
|
|
129
|
+
break;
|
|
130
|
+
case "find_dependency_path":
|
|
131
|
+
result = (0, index_1.findDependencyPath)(manager.db, requireArg("source_file", arg1), requireArg("target_file", arg2));
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
throw new Error(`Unknown query tool: ${tool}`);
|
|
135
|
+
}
|
|
136
|
+
const elapsed = Date.now() - start;
|
|
137
|
+
if (options.json) {
|
|
138
|
+
printJson(result);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// M7: Human-readable table output instead of raw JSON
|
|
142
|
+
if (Array.isArray(result)) {
|
|
143
|
+
process.stdout.write(`${(0, formatters_1.formatTable)(`Query: ${tool}`, result)}\n`);
|
|
144
|
+
}
|
|
145
|
+
else if (typeof result === "object" && result !== null) {
|
|
146
|
+
const entries = Object.entries(result).map(([key, value]) => [key, typeof value === "object" ? JSON.stringify(value) : String(value)]);
|
|
147
|
+
process.stdout.write(`${(0, formatters_1.formatKeyValueBlock)(`Query: ${tool}`, entries)}\n`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
process.stdout.write(`${(0, formatters_1.formatList)(`Query: ${tool}`, [String(result)])}\n`);
|
|
151
|
+
}
|
|
152
|
+
if (options.verbose) {
|
|
153
|
+
process.stdout.write(`Completed in ${elapsed}ms\n`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
manager.close();
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
program
|
|
162
|
+
.command("serve")
|
|
163
|
+
.description("Start MCP server")
|
|
164
|
+
.action(async () => {
|
|
165
|
+
const options = program.opts();
|
|
166
|
+
const mcpServer = (0, index_1.createGraphiteMcpServer)({
|
|
167
|
+
projectRoot: options.projectRoot
|
|
168
|
+
});
|
|
169
|
+
await mcpServer.start();
|
|
170
|
+
await new Promise(() => {
|
|
171
|
+
// Keep process alive while stdio transport is active.
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
return program;
|
|
175
|
+
}
|
|
176
|
+
async function runCli(argv) {
|
|
177
|
+
await createProgram().parseAsync(argv);
|
|
178
|
+
}
|
|
179
|
+
if (require.main === module) {
|
|
180
|
+
runCli(process.argv).catch((error) => {
|
|
181
|
+
const message = error instanceof Error ? error.message : "Unknown CLI error";
|
|
182
|
+
process.stderr.write(`${message}\n`);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=index.js.map
|