@reactgraph/cli 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +319 -0
  2. package/bun.lock +527 -0
  3. package/dist/cli/components/IndexProgress.d.ts +18 -0
  4. package/dist/cli/components/IndexProgress.d.ts.map +1 -0
  5. package/dist/cli/components/IndexProgress.js +26 -0
  6. package/dist/cli/components/IndexProgress.js.map +1 -0
  7. package/dist/cli/components/InitResult.d.ts +7 -0
  8. package/dist/cli/components/InitResult.d.ts.map +1 -0
  9. package/dist/cli/components/InitResult.js +6 -0
  10. package/dist/cli/components/InitResult.js.map +1 -0
  11. package/dist/cli/index-cmd.d.ts +7 -0
  12. package/dist/cli/index-cmd.d.ts.map +1 -0
  13. package/dist/cli/index-cmd.js +28 -0
  14. package/dist/cli/index-cmd.js.map +1 -0
  15. package/dist/cli/index.d.ts +3 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +81 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/init.d.ts +8 -0
  20. package/dist/cli/init.d.ts.map +1 -0
  21. package/dist/cli/init.js +77 -0
  22. package/dist/cli/init.js.map +1 -0
  23. package/dist/cli/serve.d.ts +2 -0
  24. package/dist/cli/serve.d.ts.map +1 -0
  25. package/dist/cli/serve.js +28 -0
  26. package/dist/cli/serve.js.map +1 -0
  27. package/dist/cli/unused.d.ts +2 -0
  28. package/dist/cli/unused.d.ts.map +1 -0
  29. package/dist/cli/unused.js +56 -0
  30. package/dist/cli/unused.js.map +1 -0
  31. package/dist/graph/graph.d.ts +30 -0
  32. package/dist/graph/graph.d.ts.map +1 -0
  33. package/dist/graph/graph.js +166 -0
  34. package/dist/graph/graph.js.map +1 -0
  35. package/dist/graph/index.d.ts +5 -0
  36. package/dist/graph/index.d.ts.map +1 -0
  37. package/dist/graph/index.js +5 -0
  38. package/dist/graph/index.js.map +1 -0
  39. package/dist/graph/schema.d.ts +33 -0
  40. package/dist/graph/schema.d.ts.map +1 -0
  41. package/dist/graph/schema.js +3 -0
  42. package/dist/graph/schema.js.map +1 -0
  43. package/dist/graph/serialize.d.ts +7 -0
  44. package/dist/graph/serialize.d.ts.map +1 -0
  45. package/dist/graph/serialize.js +39 -0
  46. package/dist/graph/serialize.js.map +1 -0
  47. package/dist/graph/traverse.d.ts +14 -0
  48. package/dist/graph/traverse.d.ts.map +1 -0
  49. package/dist/graph/traverse.js +50 -0
  50. package/dist/graph/traverse.js.map +1 -0
  51. package/dist/mcp/formatter.d.ts +26 -0
  52. package/dist/mcp/formatter.d.ts.map +1 -0
  53. package/dist/mcp/formatter.js +691 -0
  54. package/dist/mcp/formatter.js.map +1 -0
  55. package/dist/mcp/server.d.ts +2 -0
  56. package/dist/mcp/server.d.ts.map +1 -0
  57. package/dist/mcp/server.js +45 -0
  58. package/dist/mcp/server.js.map +1 -0
  59. package/dist/mcp/tools.d.ts +9 -0
  60. package/dist/mcp/tools.d.ts.map +1 -0
  61. package/dist/mcp/tools.js +136 -0
  62. package/dist/mcp/tools.js.map +1 -0
  63. package/dist/output/ai-context.d.ts +7 -0
  64. package/dist/output/ai-context.d.ts.map +1 -0
  65. package/dist/output/ai-context.js +26 -0
  66. package/dist/output/ai-context.js.map +1 -0
  67. package/dist/parser/extractors/api-calls.d.ts +15 -0
  68. package/dist/parser/extractors/api-calls.d.ts.map +1 -0
  69. package/dist/parser/extractors/api-calls.js +168 -0
  70. package/dist/parser/extractors/api-calls.js.map +1 -0
  71. package/dist/parser/extractors/components.d.ts +5 -0
  72. package/dist/parser/extractors/components.d.ts.map +1 -0
  73. package/dist/parser/extractors/components.js +236 -0
  74. package/dist/parser/extractors/components.js.map +1 -0
  75. package/dist/parser/extractors/context.d.ts +14 -0
  76. package/dist/parser/extractors/context.d.ts.map +1 -0
  77. package/dist/parser/extractors/context.js +196 -0
  78. package/dist/parser/extractors/context.js.map +1 -0
  79. package/dist/parser/extractors/effects.d.ts +14 -0
  80. package/dist/parser/extractors/effects.d.ts.map +1 -0
  81. package/dist/parser/extractors/effects.js +175 -0
  82. package/dist/parser/extractors/effects.js.map +1 -0
  83. package/dist/parser/extractors/hooks.d.ts +5 -0
  84. package/dist/parser/extractors/hooks.d.ts.map +1 -0
  85. package/dist/parser/extractors/hooks.js +242 -0
  86. package/dist/parser/extractors/hooks.js.map +1 -0
  87. package/dist/parser/extractors/imports.d.ts +6 -0
  88. package/dist/parser/extractors/imports.d.ts.map +1 -0
  89. package/dist/parser/extractors/imports.js +148 -0
  90. package/dist/parser/extractors/imports.js.map +1 -0
  91. package/dist/parser/extractors/index.d.ts +12 -0
  92. package/dist/parser/extractors/index.d.ts.map +1 -0
  93. package/dist/parser/extractors/index.js +11 -0
  94. package/dist/parser/extractors/index.js.map +1 -0
  95. package/dist/parser/extractors/jsx-tree.d.ts +5 -0
  96. package/dist/parser/extractors/jsx-tree.d.ts.map +1 -0
  97. package/dist/parser/extractors/jsx-tree.js +226 -0
  98. package/dist/parser/extractors/jsx-tree.js.map +1 -0
  99. package/dist/parser/extractors/routes.d.ts +13 -0
  100. package/dist/parser/extractors/routes.d.ts.map +1 -0
  101. package/dist/parser/extractors/routes.js +275 -0
  102. package/dist/parser/extractors/routes.js.map +1 -0
  103. package/dist/parser/extractors/state.d.ts +14 -0
  104. package/dist/parser/extractors/state.d.ts.map +1 -0
  105. package/dist/parser/extractors/state.js +368 -0
  106. package/dist/parser/extractors/state.js.map +1 -0
  107. package/dist/parser/extractors/types.d.ts +22 -0
  108. package/dist/parser/extractors/types.d.ts.map +1 -0
  109. package/dist/parser/extractors/types.js +51 -0
  110. package/dist/parser/extractors/types.js.map +1 -0
  111. package/dist/parser/indexer.d.ts +14 -0
  112. package/dist/parser/indexer.d.ts.map +1 -0
  113. package/dist/parser/indexer.js +167 -0
  114. package/dist/parser/indexer.js.map +1 -0
  115. package/dist/parser/pipeline.d.ts +16 -0
  116. package/dist/parser/pipeline.d.ts.map +1 -0
  117. package/dist/parser/pipeline.js +63 -0
  118. package/dist/parser/pipeline.js.map +1 -0
  119. package/dist/parser/setup.d.ts +4 -0
  120. package/dist/parser/setup.d.ts.map +1 -0
  121. package/dist/parser/setup.js +29 -0
  122. package/dist/parser/setup.js.map +1 -0
  123. package/dist/parser/walker.d.ts +6 -0
  124. package/dist/parser/walker.d.ts.map +1 -0
  125. package/dist/parser/walker.js +45 -0
  126. package/dist/parser/walker.js.map +1 -0
  127. package/dist/watcher.d.ts +12 -0
  128. package/dist/watcher.d.ts.map +1 -0
  129. package/dist/watcher.js +72 -0
  130. package/dist/watcher.js.map +1 -0
  131. package/package.json +51 -0
  132. package/src/cli/components/IndexProgress.tsx +79 -0
  133. package/src/cli/components/InitResult.tsx +28 -0
  134. package/src/cli/index-cmd.ts +41 -0
  135. package/src/cli/index.ts +92 -0
  136. package/src/cli/init.ts +97 -0
  137. package/src/cli/serve.ts +29 -0
  138. package/src/cli/unused.ts +88 -0
  139. package/src/graph/graph.ts +179 -0
  140. package/src/graph/index.ts +4 -0
  141. package/src/graph/schema.ts +68 -0
  142. package/src/graph/serialize.ts +40 -0
  143. package/src/graph/traverse.ts +66 -0
  144. package/src/mcp/formatter.ts +757 -0
  145. package/src/mcp/server.ts +59 -0
  146. package/src/mcp/tools.ts +154 -0
  147. package/src/output/ai-context.ts +29 -0
  148. package/src/parser/extractors/api-calls.ts +192 -0
  149. package/src/parser/extractors/components.ts +273 -0
  150. package/src/parser/extractors/context.ts +216 -0
  151. package/src/parser/extractors/effects.ts +205 -0
  152. package/src/parser/extractors/hooks.ts +268 -0
  153. package/src/parser/extractors/imports.ts +192 -0
  154. package/src/parser/extractors/index.ts +11 -0
  155. package/src/parser/extractors/jsx-tree.ts +271 -0
  156. package/src/parser/extractors/routes.ts +331 -0
  157. package/src/parser/extractors/state.ts +392 -0
  158. package/src/parser/extractors/types.ts +71 -0
  159. package/src/parser/indexer.ts +197 -0
  160. package/src/parser/pipeline.ts +89 -0
  161. package/src/parser/setup.ts +33 -0
  162. package/src/parser/walker.ts +61 -0
  163. package/src/watcher.ts +91 -0
  164. package/templates/CLAUDE.md +7 -0
  165. package/tests/extractors.test.ts +164 -0
  166. package/tests/fixtures/basic/src/App.tsx +12 -0
  167. package/tests/fixtures/basic/src/components/Dashboard.tsx +24 -0
  168. package/tests/fixtures/basic/src/components/MetricsCard.tsx +15 -0
  169. package/tests/fixtures/basic/src/components/Sidebar.tsx +20 -0
  170. package/tests/fixtures/basic/src/contexts/ThemeContext.tsx +16 -0
  171. package/tests/fixtures/basic/src/hooks/useAuth.ts +25 -0
  172. package/tests/fixtures/basic/src/stores/authStore.ts +15 -0
  173. package/tests/fixtures/basic/src/utils.ts +7 -0
  174. package/tests/graph.test.ts +91 -0
  175. package/tests/phase2.test.ts +309 -0
  176. package/tests/smoke.test.ts +77 -0
  177. package/tsconfig.json +20 -0
  178. package/vitest.config.ts +8 -0
package/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # ReactGraph
2
+
3
+ Pre-computed React project graph for AI-assisted development. Stop Claude Code from searching — start it navigating.
4
+
5
+ ## The Problem
6
+
7
+ When Claude Code works on a React project, more than half its time and tokens go to file discovery — grep/cat cycles burning 30,000–60,000 tokens per task just to understand the codebase.
8
+
9
+ ## The Solution
10
+
11
+ ReactGraph parses your React project with tree-sitter, builds a graph of components, hooks, state stores, context providers, routes, and API calls, then exposes it via an MCP server or a flat file. Claude reads one compact project map and starts coding immediately.
12
+
13
+ **Before ReactGraph:** 40+ tool calls to understand the codebase → 60K tokens wasted
14
+ **After ReactGraph:** 1 MCP call → ~2–4K token project map → start coding immediately
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ # Install
20
+ bun install -g reactgraph
21
+
22
+ # In your React project
23
+ cd my-react-app
24
+ reactgraph init # detects framework, creates .reactgraph/
25
+ reactgraph index # builds the graph (~2-5 seconds)
26
+ ```
27
+
28
+ After indexing, `.reactgraph/ai-context.md` is generated automatically — a flat file Claude can read with zero setup.
29
+
30
+ ## Connect to Claude Code
31
+
32
+ ### Option 1: MCP Server (recommended)
33
+
34
+ ```bash
35
+ claude mcp add reactgraph -- reactgraph serve
36
+ ```
37
+
38
+ Or add to `.mcp.json`:
39
+
40
+ ```json
41
+ {
42
+ "mcpServers": {
43
+ "reactgraph": {
44
+ "command": "reactgraph",
45
+ "args": ["serve"]
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ Use `--watch` to automatically update the graph when files change:
52
+
53
+ ```json
54
+ {
55
+ "mcpServers": {
56
+ "reactgraph": {
57
+ "command": "reactgraph",
58
+ "args": ["serve", "--watch"]
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
64
+ ### Option 2: Flat File (zero setup)
65
+
66
+ Add to your `CLAUDE.md`:
67
+
68
+ ```markdown
69
+ Read .reactgraph/ai-context.md at session start instead of exploring files.
70
+ ```
71
+
72
+ ## CLAUDE.md Integration
73
+
74
+ Add these navigation rules to your project's `CLAUDE.md`:
75
+
76
+ ```markdown
77
+ ## Navigation Rules (ReactGraph)
78
+
79
+ - ALWAYS call reactgraph.get_map() at session start instead of exploring files
80
+ - Use reactgraph.get_subgraph(name) before modifying any component or hook
81
+ - Use reactgraph.get_file_context(path) for detailed file info before editing
82
+ - Use reactgraph.find_nodes({ query: "name" }) to find a node and its connections
83
+ - Use reactgraph.impact(target) before refactoring to know what breaks
84
+ - Do NOT use grep/find/glob to discover project structure — the graph has it
85
+ - If ReactGraph MCP is not available, read .reactgraph/ai-context.md instead
86
+ ```
87
+
88
+ ## MCP Tools
89
+
90
+ ### `get_map()`
91
+
92
+ Returns a compact overview of the entire project — routes, components sorted by connectivity, hooks, state stores, context providers, and shared modules.
93
+
94
+ ```
95
+ # REACTGRAPH MAP | 127 components, 43 hooks, 8 stores, 12 routes
96
+ # Indexed: 2026-03-22T14:30:00Z | 342 files
97
+
98
+ ## ROUTES
99
+ / → DashboardPage [src/app/page.tsx]
100
+ /settings → SettingsPage [src/app/settings/page.tsx]
101
+ POST /api/auth [src/app/api/auth/route.ts]
102
+
103
+ ## COMPONENTS (top 30 by connectivity)
104
+ Dashboard [src/components/Dashboard.tsx:5]
105
+ renders: MetricsCard, FilterBar
106
+ hooks: useAuth, useDashboardData
107
+ context: ThemeCtx(read)
108
+ state: dashboardStore(read)
109
+ props: none (page component)
110
+
111
+ ## HOOKS
112
+ useAuth [src/hooks/useAuth.ts:3]
113
+ returns: { user, login, logout, isLoading }
114
+ state: authStore(read/write)
115
+ fetches: GET /api/auth/me
116
+ used-by: Dashboard, Sidebar, Header (23 total)
117
+
118
+ ## STATE STORES
119
+ authStore [zustand] [src/stores/auth.ts]
120
+ shape: { user, token, isAuthenticated }
121
+ writers: useAuth
122
+ readers: Dashboard, Sidebar, Header
123
+
124
+ ## CONTEXT PROVIDERS
125
+ ThemeCtx [src/contexts/Theme.tsx] provided-at: App
126
+ consumers: Dashboard, Sidebar, Header (12 total)
127
+ ```
128
+
129
+ ### `get_subgraph(target, depth?)`
130
+
131
+ Zoom into a specific component, hook, or store. Shows all connections up to the given depth.
132
+
133
+ ```
134
+ > get_subgraph("useAuth", depth=2)
135
+
136
+ useAuth [src/hooks/useAuth.ts:12]
137
+ ├─ reads_store → authStore [src/stores/auth.ts]
138
+ │ └─ reads_store → Dashboard, Sidebar, Header
139
+ ├─ fetches → GET /api/auth/me
140
+ ├─ uses_hook → useState, useEffect
141
+ used-by (23):
142
+ │ ← uses_hook ← Dashboard [src/pages/Dashboard.tsx]
143
+ │ ← uses_hook ← Sidebar [src/components/Sidebar.tsx]
144
+ │ ← uses_hook ← Header [src/components/Header.tsx]
145
+ ```
146
+
147
+ ### `get_file_context(path)`
148
+
149
+ Everything about a specific file — exports, imports, components, hooks, stores, effects, and all relationships.
150
+
151
+ ```
152
+ > get_file_context("src/components/Dashboard.tsx")
153
+
154
+ FILE: src/components/Dashboard.tsx
155
+ EXPORTS: Dashboard (default)
156
+ IMPORTS:
157
+ useAuth ← src/hooks/useAuth.ts
158
+ MetricsCard ← src/components/MetricsCard.tsx
159
+
160
+ COMPONENT: Dashboard (line 5)
161
+ RENDERS: MetricsCard
162
+ HOOKS: useAuth → { user, isLoading }
163
+ STATE: authStore(read)
164
+ CONTEXT: ThemeCtx(read)
165
+ RENDERED BY: App
166
+ ```
167
+
168
+ ### `trace_flow(from, to)`
169
+
170
+ Trace the data flow path between two nodes. Shows how data gets from A to B.
171
+
172
+ ```
173
+ > trace_flow("LoginForm", "/api/auth/login")
174
+
175
+ LoginForm → POST /api/auth/login
176
+
177
+ LoginForm [src/components/LoginForm.tsx]
178
+ └─ uses_hook → useAuth [src/hooks/useAuth.ts]
179
+ └─ fetches → endpoint:POST:/api/auth/login
180
+ ```
181
+
182
+ ### `impact(target)`
183
+
184
+ Analyze what would break if a component, hook, or store is changed.
185
+
186
+ ```
187
+ > impact("useAuth")
188
+
189
+ IMPACT ANALYSIS: useAuth [src/hooks/useAuth.ts]
190
+
191
+ DIRECT (23 dependents):
192
+ uses_hook ← Dashboard [src/pages/Dashboard.tsx]
193
+ uses_hook ← Sidebar [src/components/Sidebar.tsx]
194
+ uses_hook ← Header [src/components/Header.tsx]
195
+
196
+ INDIRECT (via components using useAuth):
197
+ App [src/App.tsx]
198
+
199
+ SAFE TO CHANGE:
200
+ Internal implementation (same return type + same store writes = no breakage)
201
+ RISKY:
202
+ Return type shape — 23 consumers destructure { user, login, logout, isLoading }
203
+ ```
204
+
205
+ ### `find_nodes(filters)`
206
+
207
+ Query the graph. Use `query` to find a node and see all its connections. Use other filters for bulk searches.
208
+
209
+ ```
210
+ > find_nodes({ query: "useUIStore" })
211
+
212
+ useUIStore [Store] [src/lib/ui-store.ts:69]
213
+
214
+ reads_store ← Sidebar [src/components/Sidebar.tsx], Header [src/components/Header.tsx]
215
+ writes_store ← useUIActions [src/hooks/useUIActions.ts]
216
+
217
+ > find_nodes({ kind: "Hook", fetches: true })
218
+
219
+ Found 4 nodes:
220
+ useAuth [Hook] [src/hooks/useAuth.ts:3]
221
+ useDashboardData [Hook] [src/hooks/useDashboardData.ts:5]
222
+
223
+ > find_nodes({ kind: "Component", orphan: true })
224
+
225
+ Found 2 nodes:
226
+ DeprecatedBanner [Component] [src/components/DeprecatedBanner.tsx:1]
227
+ OldUserCard [Component] [src/components/OldUserCard.tsx:1]
228
+ ```
229
+
230
+ **Available filters:** `query`, `name`, `kind`, `using_hook`, `using_store`, `fetches`, `orphan`
231
+
232
+ ## CLI Commands
233
+
234
+ | Command | Description |
235
+ |---------|-------------|
236
+ | `reactgraph init` | Detect framework, create `.reactgraph/` config |
237
+ | `reactgraph index` | Build the project graph with progress display |
238
+ | `reactgraph serve` | Start the MCP server (stdio transport) |
239
+ | `reactgraph serve --watch` | Start MCP server + auto-update on file changes |
240
+ | `reactgraph unused` | Find orphan components, unused hooks, dead exports |
241
+
242
+ ## How It Works
243
+
244
+ 1. **Walk** — finds all `.ts`, `.tsx`, `.js`, `.jsx` files, respecting `.gitignore`
245
+ 2. **Parse** — tree-sitter builds ASTs (fast, handles broken code)
246
+ 3. **Extract** — nine extractors run per file in order:
247
+ - **imports** — import/export graph, path resolution
248
+ - **components** — function, arrow, memo-wrapped, class components
249
+ - **hooks** — custom hook definitions + all hook call sites
250
+ - **jsx-tree** — which components render which, prop passing
251
+ - **context** — createContext, Provider, useContext tracking
252
+ - **state** — Zustand, Redux Toolkit, Jotai, Recoil store detection
253
+ - **api-calls** — fetch, axios, API wrapper call extraction
254
+ - **routes** — React Router, Next.js App/Pages Router
255
+ - **effects** — useEffect dependency arrays, cleanup detection
256
+ 4. **Resolve** — two-pass indexing ensures cross-file references (stores, contexts, components) are fully linked regardless of file processing order
257
+ 5. **Persist** — graph saved to `.reactgraph/graph.json` with SHA256 file hashes for incremental re-indexing
258
+ 6. **Format** — token-optimized structured text output for AI consumption
259
+
260
+ ## What It Detects
261
+
262
+ | Category | What's Tracked |
263
+ |----------|---------------|
264
+ | Components | Function, arrow, class, memo/forwardRef wrapped |
265
+ | Hooks | Custom definitions, all call sites, destructured returns |
266
+ | Render tree | Which components render which, prop passing |
267
+ | Context | createContext, Provider wrapping, useContext consumers |
268
+ | State | Zustand `create()`, Redux `createSlice()`, Jotai `atom()`, Recoil `atom()` |
269
+ | Store usage | Readers (`useStore`, `useSelector`, `useAtomValue`) and writers (`setState`, `dispatch`, `useSetAtom`) |
270
+ | API calls | `fetch()`, `axios.*()`, custom API wrappers |
271
+ | Routes | React Router `<Route>`, Next.js file-based routing (App + Pages) |
272
+ | Effects | `useEffect`/`useLayoutEffect` deps, cleanup, triggers |
273
+ | Imports | Full import/export graph with path resolution |
274
+
275
+ ## Graph Schema
276
+
277
+ **Node kinds:** Component, Hook, BuiltinHook, Context, Route, Module, Store, ApiEndpoint, Type, Util, Constant
278
+
279
+ **Edge kinds:** imports, renders, passes_prop, uses_hook, provides, consumes, calls, fetches, reads_store, writes_store, routes_to, type_of
280
+
281
+ ## Configuration
282
+
283
+ After `reactgraph init`, settings are stored in `.reactgraph/config.json`:
284
+
285
+ ```json
286
+ {
287
+ "srcDirs": ["src"],
288
+ "framework": "next",
289
+ "exclude": ["**/*.test.*", "**/*.spec.*", "**/*.stories.*"]
290
+ }
291
+ ```
292
+
293
+ `.reactgraph/` is automatically added to `.gitignore` — it's a local cache, not a shared artifact.
294
+
295
+ ## Tech Stack
296
+
297
+ | Layer | Choice |
298
+ |-------|--------|
299
+ | Parser | tree-sitter (TS/TSX/JS/JSX) |
300
+ | Graph | Custom in-memory with secondary indexes |
301
+ | CLI | Commander + Ink |
302
+ | MCP | @modelcontextprotocol/sdk (stdio) |
303
+ | File watching | chokidar (incremental re-parse) |
304
+ | Persistence | JSON with file hash caching |
305
+
306
+ Five runtime dependencies. No databases, no API keys, no Docker.
307
+
308
+ ## Development
309
+
310
+ ```bash
311
+ bun install
312
+ bun test # run tests (37 tests)
313
+ bun run build # compile TypeScript
314
+ bun run dev # run CLI directly
315
+ ```
316
+
317
+ ## License
318
+
319
+ MIT