@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.
Files changed (148) hide show
  1. package/README.md +427 -0
  2. package/dist/cli/formatters.d.ts +3 -0
  3. package/dist/cli/formatters.js +61 -0
  4. package/dist/cli/formatters.js.map +1 -0
  5. package/dist/cli/index.d.ts +2 -0
  6. package/dist/cli/index.js +186 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/index.d.ts +6 -0
  9. package/dist/index.js +23 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/indexer/call-resolver.d.ts +8 -0
  12. package/dist/indexer/call-resolver.js +161 -0
  13. package/dist/indexer/call-resolver.js.map +1 -0
  14. package/dist/indexer/extractors/calls.d.ts +17 -0
  15. package/dist/indexer/extractors/calls.js +206 -0
  16. package/dist/indexer/extractors/calls.js.map +1 -0
  17. package/dist/indexer/extractors/classes.d.ts +35 -0
  18. package/dist/indexer/extractors/classes.js +209 -0
  19. package/dist/indexer/extractors/classes.js.map +1 -0
  20. package/dist/indexer/extractors/exports.d.ts +12 -0
  21. package/dist/indexer/extractors/exports.js +267 -0
  22. package/dist/indexer/extractors/exports.js.map +1 -0
  23. package/dist/indexer/extractors/functions.d.ts +12 -0
  24. package/dist/indexer/extractors/functions.js +169 -0
  25. package/dist/indexer/extractors/functions.js.map +1 -0
  26. package/dist/indexer/extractors/imports.d.ts +12 -0
  27. package/dist/indexer/extractors/imports.js +195 -0
  28. package/dist/indexer/extractors/imports.js.map +1 -0
  29. package/dist/indexer/extractors/index.d.ts +7 -0
  30. package/dist/indexer/extractors/index.js +24 -0
  31. package/dist/indexer/extractors/index.js.map +1 -0
  32. package/dist/indexer/extractors/types.d.ts +12 -0
  33. package/dist/indexer/extractors/types.js +138 -0
  34. package/dist/indexer/extractors/types.js.map +1 -0
  35. package/dist/indexer/extractors/variables.d.ts +10 -0
  36. package/dist/indexer/extractors/variables.js +134 -0
  37. package/dist/indexer/extractors/variables.js.map +1 -0
  38. package/dist/indexer/file-discovery.d.ts +7 -0
  39. package/dist/indexer/file-discovery.js +92 -0
  40. package/dist/indexer/file-discovery.js.map +1 -0
  41. package/dist/indexer/file-indexer.d.ts +2 -0
  42. package/dist/indexer/file-indexer.js +267 -0
  43. package/dist/indexer/file-indexer.js.map +1 -0
  44. package/dist/indexer/graph-contract.d.ts +25 -0
  45. package/dist/indexer/graph-contract.js +7 -0
  46. package/dist/indexer/graph-contract.js.map +1 -0
  47. package/dist/indexer/hasher.d.ts +1 -0
  48. package/dist/indexer/hasher.js +11 -0
  49. package/dist/indexer/hasher.js.map +1 -0
  50. package/dist/indexer/import-resolver.d.ts +11 -0
  51. package/dist/indexer/import-resolver.js +131 -0
  52. package/dist/indexer/import-resolver.js.map +1 -0
  53. package/dist/indexer/index.d.ts +11 -0
  54. package/dist/indexer/index.js +28 -0
  55. package/dist/indexer/index.js.map +1 -0
  56. package/dist/indexer/inheritance-resolver.d.ts +7 -0
  57. package/dist/indexer/inheritance-resolver.js +119 -0
  58. package/dist/indexer/inheritance-resolver.js.map +1 -0
  59. package/dist/indexer/parser.d.ts +5 -0
  60. package/dist/indexer/parser.js +48 -0
  61. package/dist/indexer/parser.js.map +1 -0
  62. package/dist/indexer/path-utils.d.ts +3 -0
  63. package/dist/indexer/path-utils.js +20 -0
  64. package/dist/indexer/path-utils.js.map +1 -0
  65. package/dist/indexer/project-indexer.d.ts +14 -0
  66. package/dist/indexer/project-indexer.js +167 -0
  67. package/dist/indexer/project-indexer.js.map +1 -0
  68. package/dist/indexer/property-parsers.d.ts +20 -0
  69. package/dist/indexer/property-parsers.js +81 -0
  70. package/dist/indexer/property-parsers.js.map +1 -0
  71. package/dist/mcp/index.d.ts +3 -0
  72. package/dist/mcp/index.js +20 -0
  73. package/dist/mcp/index.js.map +1 -0
  74. package/dist/mcp/response-formatter.d.ts +10 -0
  75. package/dist/mcp/response-formatter.js +47 -0
  76. package/dist/mcp/response-formatter.js.map +1 -0
  77. package/dist/mcp/server.d.ts +10 -0
  78. package/dist/mcp/server.js +118 -0
  79. package/dist/mcp/server.js.map +1 -0
  80. package/dist/mcp/tools-list.d.ts +9 -0
  81. package/dist/mcp/tools-list.js +12 -0
  82. package/dist/mcp/tools-list.js.map +1 -0
  83. package/dist/mcp/tools.d.ts +13 -0
  84. package/dist/mcp/tools.js +163 -0
  85. package/dist/mcp/tools.js.map +1 -0
  86. package/dist/query/analyze-impact.d.ts +18 -0
  87. package/dist/query/analyze-impact.js +58 -0
  88. package/dist/query/analyze-impact.js.map +1 -0
  89. package/dist/query/find-callees.d.ts +12 -0
  90. package/dist/query/find-callees.js +46 -0
  91. package/dist/query/find-callees.js.map +1 -0
  92. package/dist/query/find-callers.d.ts +12 -0
  93. package/dist/query/find-callers.js +46 -0
  94. package/dist/query/find-callers.js.map +1 -0
  95. package/dist/query/find-definition.d.ts +3 -0
  96. package/dist/query/find-definition.js +41 -0
  97. package/dist/query/find-definition.js.map +1 -0
  98. package/dist/query/find-dependency-path.d.ts +2 -0
  99. package/dist/query/find-dependency-path.js +39 -0
  100. package/dist/query/find-dependency-path.js.map +1 -0
  101. package/dist/query/find-implementations.d.ts +10 -0
  102. package/dist/query/find-implementations.js +34 -0
  103. package/dist/query/find-implementations.js.map +1 -0
  104. package/dist/query/get-exports.d.ts +3 -0
  105. package/dist/query/get-exports.js +82 -0
  106. package/dist/query/get-exports.js.map +1 -0
  107. package/dist/query/get-file-structure.d.ts +3 -0
  108. package/dist/query/get-file-structure.js +58 -0
  109. package/dist/query/get-file-structure.js.map +1 -0
  110. package/dist/query/get-graph-stats.d.ts +21 -0
  111. package/dist/query/get-graph-stats.js +42 -0
  112. package/dist/query/get-graph-stats.js.map +1 -0
  113. package/dist/query/index.d.ts +11 -0
  114. package/dist/query/index.js +28 -0
  115. package/dist/query/index.js.map +1 -0
  116. package/dist/query/search-symbols.d.ts +6 -0
  117. package/dist/query/search-symbols.js +75 -0
  118. package/dist/query/search-symbols.js.map +1 -0
  119. package/dist/query/types.d.ts +41 -0
  120. package/dist/query/types.js +36 -0
  121. package/dist/query/types.js.map +1 -0
  122. package/dist/storage/database.d.ts +13 -0
  123. package/dist/storage/database.js +49 -0
  124. package/dist/storage/database.js.map +1 -0
  125. package/dist/storage/index.d.ts +7 -0
  126. package/dist/storage/index.js +24 -0
  127. package/dist/storage/index.js.map +1 -0
  128. package/dist/storage/migrations/001_initial.sql +59 -0
  129. package/dist/storage/migrations/002_add_name_index.sql +9 -0
  130. package/dist/storage/migrator.d.ts +9 -0
  131. package/dist/storage/migrator.js +86 -0
  132. package/dist/storage/migrator.js.map +1 -0
  133. package/dist/storage/paths.d.ts +5 -0
  134. package/dist/storage/paths.js +25 -0
  135. package/dist/storage/paths.js.map +1 -0
  136. package/dist/storage/reader.d.ts +10 -0
  137. package/dist/storage/reader.js +103 -0
  138. package/dist/storage/reader.js.map +1 -0
  139. package/dist/storage/schema.d.ts +14 -0
  140. package/dist/storage/schema.js +18 -0
  141. package/dist/storage/schema.js.map +1 -0
  142. package/dist/storage/types.d.ts +42 -0
  143. package/dist/storage/types.js +3 -0
  144. package/dist/storage/types.js.map +1 -0
  145. package/dist/storage/writer.d.ts +13 -0
  146. package/dist/storage/writer.js +160 -0
  147. package/dist/storage/writer.js.map +1 -0
  148. 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,3 @@
1
+ export declare function formatKeyValueBlock(title: string, entries: Array<[string, string | number]>): string;
2
+ export declare function formatList(title: string, lines: string[]): string;
3
+ export declare function formatTable(title: string, rows: unknown[]): string;
@@ -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,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function runCli(argv: string[]): Promise<void>;
@@ -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