@nanonets/graft 0.4.0 → 0.4.2

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 (70) hide show
  1. package/README.md +48 -22
  2. package/dist/claude/hooks.d.ts.map +1 -1
  3. package/dist/claude/hooks.js +35 -22
  4. package/dist/claude/hooks.js.map +1 -1
  5. package/dist/claude/init.d.ts +1 -0
  6. package/dist/claude/init.d.ts.map +1 -1
  7. package/dist/claude/init.js +12 -3
  8. package/dist/claude/init.js.map +1 -1
  9. package/dist/claude/paths.d.ts +4 -0
  10. package/dist/claude/paths.d.ts.map +1 -1
  11. package/dist/claude/paths.js +6 -0
  12. package/dist/claude/paths.js.map +1 -1
  13. package/dist/claude/shim-template.d.ts +2 -2
  14. package/dist/claude/shim-template.d.ts.map +1 -1
  15. package/dist/claude/shim-template.js +54 -11
  16. package/dist/claude/shim-template.js.map +1 -1
  17. package/dist/claude/skill-template.d.ts +2 -0
  18. package/dist/claude/skill-template.d.ts.map +1 -0
  19. package/dist/claude/skill-template.js +49 -0
  20. package/dist/claude/skill-template.js.map +1 -0
  21. package/dist/cli.d.ts +1 -0
  22. package/dist/cli.d.ts.map +1 -1
  23. package/dist/cli.js +65 -10
  24. package/dist/cli.js.map +1 -1
  25. package/dist/graph/build.d.ts.map +1 -1
  26. package/dist/graph/build.js +24 -2
  27. package/dist/graph/build.js.map +1 -1
  28. package/dist/graph/extract.d.ts +1 -1
  29. package/dist/graph/extract.d.ts.map +1 -1
  30. package/dist/graph/extract.js +107 -9
  31. package/dist/graph/extract.js.map +1 -1
  32. package/dist/graph/resolve.d.ts +14 -1
  33. package/dist/graph/resolve.d.ts.map +1 -1
  34. package/dist/graph/resolve.js +0 -0
  35. package/dist/graph/resolve.js.map +1 -1
  36. package/dist/graph/types.d.ts +2 -2
  37. package/dist/graph/types.d.ts.map +1 -1
  38. package/dist/hosts/codex-hooks.d.ts +7 -0
  39. package/dist/hosts/codex-hooks.d.ts.map +1 -0
  40. package/dist/hosts/codex-hooks.js +75 -0
  41. package/dist/hosts/codex-hooks.js.map +1 -0
  42. package/dist/hosts/init.d.ts +21 -0
  43. package/dist/hosts/init.d.ts.map +1 -0
  44. package/dist/hosts/init.js +63 -0
  45. package/dist/hosts/init.js.map +1 -0
  46. package/dist/hosts/instructions.d.ts +9 -0
  47. package/dist/hosts/instructions.d.ts.map +1 -0
  48. package/dist/hosts/instructions.js +44 -0
  49. package/dist/hosts/instructions.js.map +1 -0
  50. package/dist/hosts/mcp-config.d.ts +9 -0
  51. package/dist/hosts/mcp-config.d.ts.map +1 -0
  52. package/dist/hosts/mcp-config.js +81 -0
  53. package/dist/hosts/mcp-config.js.map +1 -0
  54. package/dist/hosts/registry.d.ts +18 -0
  55. package/dist/hosts/registry.d.ts.map +1 -0
  56. package/dist/hosts/registry.js +69 -0
  57. package/dist/hosts/registry.js.map +1 -0
  58. package/dist/hosts/sections.d.ts +10 -0
  59. package/dist/hosts/sections.d.ts.map +1 -0
  60. package/dist/hosts/sections.js +61 -0
  61. package/dist/hosts/sections.js.map +1 -0
  62. package/dist/mcp/server.d.ts +2 -0
  63. package/dist/mcp/server.d.ts.map +1 -0
  64. package/dist/mcp/server.js +68 -0
  65. package/dist/mcp/server.js.map +1 -0
  66. package/dist/mcp/tools.d.ts +11 -0
  67. package/dist/mcp/tools.d.ts.map +1 -0
  68. package/dist/mcp/tools.js +79 -0
  69. package/dist/mcp/tools.js.map +1 -0
  70. package/package.json +2 -1
package/README.md CHANGED
@@ -22,52 +22,75 @@
22
22
 
23
23
  </div>
24
24
 
25
- <!-- placeholder: swap this diagram for a produced hero gif/screenshot (assets/hero.gif) when ready -->
26
-
27
- ```mermaid
28
- flowchart LR
29
- A["Your code"] -->|"graft build --deep"| B["graft/<br/>a graph of linked<br/>markdown nodes"]
30
- B -->|"git commit"| C[("your repo")]
31
- C -->|"git clone"| D["teammate + their agent"]
32
- D -->|"reads the graph first"| E["starts already knowing<br/>how the repo fits together"]
33
- ```
25
+ <p align="center">
26
+ <img src="assets/graft-terminal.png" alt="Two commands — npm install and graft init — then Graft rides along in a Claude Code session, statusline synced" width="820"/>
27
+ </p>
34
28
 
35
29
  ---
36
30
 
37
31
  ## Quick start
38
32
 
39
33
  ```bash
40
- export OPENROUTER_API_KEY=sk-or-...
41
- # the summaries are LLM-written — get a key at https://openrouter.ai/keys
34
+ npm install -g @nanonets/graft # install the CLI, once
35
+ graft init # build the graph + wire it into Claude Code
36
+ ```
42
37
 
43
- npx @nanonets/graft build --deep
44
- # builds graft/ from your code, one node per system, API, or concept
38
+ That is the whole setup. `graft init` builds `graft/` from your code and drops a statusline and hooks into `.claude/`, so from the next session on Graft rides along in Claude Code: it pulls the matching nodes into each prompt and rebuilds the graph in the background after every turn. No daemon, no re-indexing to remember, nothing to run or maintain by default — the graph is just files.
45
39
 
40
+ Commit `graft/` so everyone who clones the repo (and their agents) gets the map:
41
+
42
+ ```bash
46
43
  git add graft && git commit -m "add context graph"
47
- # commit it so everyone who clones the repo (and their agents) gets the graph
48
44
  ```
49
45
 
50
- Or install it once and get the `graft` command everywhere:
46
+ Want richer, LLM-written summaries on top of the structural graph? Point Graft at an OpenRouter key and run the deep pass whenever you like:
51
47
 
52
48
  ```bash
53
- npm install -g @nanonets/graft
49
+ export OPENROUTER_API_KEY=sk-or-... # https://openrouter.ai/keys
54
50
  graft build --deep
55
51
  ```
56
52
 
57
- That is it. Point your agent at `graft/` and it reads the graph before it starts working.
53
+ Prefer not to install globally? `npx @nanonets/graft init` works the same way.
58
54
 
59
55
  ---
60
56
 
61
- ## Claude Code integration
57
+ ## Agent integration
62
58
 
63
- If you use [Claude Code](https://claude.com/claude-code), one command wires Graft into every session in the repo:
59
+ One command wires Graft into the coding agents you use:
64
60
 
65
61
  ```bash
66
62
  npx @nanonets/graft init
67
- # writes .claude/ (statusline + hooks) and builds the graph if it's missing
63
+ # detects your agents and writes each one's native instruction file;
64
+ # Claude Code additionally gets the live statusline + hooks below
68
65
  ```
69
66
 
70
- From then on, any Claude Code session opened in the repo gets:
67
+ `init` auto-detects which agents are present (via their config directories) and writes a marker-fenced Graft section into each one's shared instruction file — `AGENTS.md`, `GEMINI.md`, `.github/copilot-instructions.md` — or a wholly-owned rule file for the agents that use one — `.cursor/rules/graft.mdc`, `.kiro/steering/graft.md`, `.windsurf/rules/graft.md`. Re-running only updates Graft's own section (or replaces the owned file) and never touches the rest of your content.
68
+
69
+ | Flag | Effect |
70
+ |---|---|
71
+ | `--agents <ids...>` | wire only these — ids: `agents`, `cursor`, `gemini`, `copilot`, `kiro`, `windsurf`, `claude` |
72
+ | `--all-agents` | write instruction files for every known agent, detected or not |
73
+ | `--no-agents` | Claude Code wiring only; skip other agents |
74
+ | `--list-agents` | print the known agent ids and exit |
75
+ | `--no-mcp` | skip MCP server registration |
76
+ | `--no-hooks` | skip hook installation |
77
+
78
+ ### MCP server
79
+
80
+ `graft init` also registers Graft's MCP server with agents that support it, so
81
+ `graft_ask`, `graft_check`, and `graft_blast_radius` appear as native tools —
82
+ no shell required. Skip with `--no-mcp`. Run it manually with `graft mcp [dir]`,
83
+ or register it by hand:
84
+
85
+ ```json
86
+ { "mcpServers": { "graft": { "command": "npx", "args": ["-y", "@nanonets/graft", "mcp"] } } }
87
+ ```
88
+
89
+ Where a CLI agent supports user-level `hooks.json`, `init` also installs Graft's post-edit hook — blast-radius warnings and automatic `$0` graph re-sync after edits (skip with `--no-hooks`).
90
+
91
+ ### Claude Code (deep integration)
92
+
93
+ `graft init` always wires up Claude Code, and Claude Code gets more than an instruction file. From then on, any Claude Code session opened in the repo gets:
71
94
 
72
95
  - **a live statusline** — graph size, % enriched, and a `⚠ N stale` warning when the code has moved ahead of the graph
73
96
  - **auto-sync** — after you edit code, Graft rebuilds the graph in the background at the end of the turn (structural, `$0` — it never calls the LLM on its own)
@@ -178,8 +201,11 @@ graft check --json # print the drift report as JSON
178
201
  graft viz [dir] # see the graph: serves an interactive viewer on localhost
179
202
  graft viz --port 5000 --no-open # pick a port; don't auto-open the browser
180
203
 
181
- graft init [dir] # set up the Claude Code integration (.claude/ statusline + hooks) in this repo
204
+ graft init [dir] # wire Graft into the coding agents detected in this repo (Claude Code always gets full hooks + statusline)
182
205
  graft init --no-build # wire the files only; don't build the graph
206
+ graft init --agents cursor kiro # wire only these agents (ids: agents, cursor, gemini, copilot, kiro, windsurf, claude)
207
+ graft init --all-agents # wire every known agent, detected or not
208
+ graft init --list-agents # list known agent ids and exit
183
209
 
184
210
  # global
185
211
  graft --dir <path> # use a context dir other than <repo>/graft
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/claude/hooks.ts"],"names":[],"mappings":"AAkBA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAG7D;AAwBD,wBAAsB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DvD"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/claude/hooks.ts"],"names":[],"mappings":"AAkBA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAG7D;AAgDD,wBAAsB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCvD"}
@@ -53,6 +53,34 @@ function checkStaleCount(dir) {
53
53
  function emit(eventName, additionalContext) {
54
54
  process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: eventName, additionalContext } }));
55
55
  }
56
+ async function handlePostEdit(input, dir) {
57
+ const file = input?.tool_input?.file_path;
58
+ if (!file || underGraft(dir, file))
59
+ return;
60
+ patchStats(dir, { dirty: true, staleCount: checkStaleCount(dir), lastFile: basename(file) });
61
+ const w = readWiring(dir);
62
+ if (w) {
63
+ const br = formatBlastRadius(w, file);
64
+ if (br)
65
+ emit('PostToolUse', br);
66
+ }
67
+ }
68
+ function handleStop(dir) {
69
+ // sync-run.js ships next to this module inside the package, so it resolves in
70
+ // any repo that installs graft (not just graft's own). Defensive existsSync:
71
+ // if the package is somehow incomplete, skip rather than wedge on syncing:true.
72
+ // GRAFT_TEST_SYNC_RUN is a test seam (mirrors GRAFT_TEST_STDIN) so tests can point
73
+ // this at a stub file inside their own sandbox instead of writing into src/claude/.
74
+ const syncRun = process.env.GRAFT_TEST_SYNC_RUN ?? claudeScriptPath('sync-run.js');
75
+ if (!existsSync(syncRun))
76
+ return;
77
+ const stats = readStats(dir);
78
+ if (stats?.dirty && acquireLock(dir)) {
79
+ patchStats(dir, { syncing: true });
80
+ const child = spawn(process.execPath, [syncRun, dir], { detached: true, stdio: 'ignore' });
81
+ child.unref();
82
+ }
83
+ }
56
84
  export async function main(event) {
57
85
  const input = readStdin();
58
86
  const dir = projectDir(input);
@@ -65,31 +93,16 @@ export async function main(event) {
65
93
  return;
66
94
  }
67
95
  if (event === 'post-edit') {
68
- const file = input?.tool_input?.file_path;
69
- if (!file || underGraft(dir, file))
70
- return;
71
- patchStats(dir, { dirty: true, staleCount: checkStaleCount(dir), lastFile: basename(file) });
72
- const w = readWiring(dir);
73
- if (w) {
74
- const br = formatBlastRadius(w, file);
75
- if (br)
76
- emit('PostToolUse', br);
77
- }
96
+ await handlePostEdit(input, dir);
78
97
  return;
79
98
  }
80
99
  if (event === 'stop') {
81
- // sync-run.js ships next to this module inside the package, so it resolves in
82
- // any repo that installs graft (not just graft's own). Defensive existsSync:
83
- // if the package is somehow incomplete, skip rather than wedge on syncing:true.
84
- const syncRun = claudeScriptPath('sync-run.js');
85
- if (!existsSync(syncRun))
86
- return;
87
- const stats = readStats(dir);
88
- if (stats?.dirty && acquireLock(dir)) {
89
- patchStats(dir, { syncing: true });
90
- const child = spawn(process.execPath, [syncRun, dir], { detached: true, stdio: 'ignore' });
91
- child.unref();
92
- }
100
+ handleStop(dir);
101
+ return;
102
+ }
103
+ if (event === 'post-edit-sync') {
104
+ await handlePostEdit(input, dir);
105
+ handleStop(dir);
93
106
  return;
94
107
  }
95
108
  if (event === 'prompt') {
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/claude/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/claude/hooks.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export interface InitResult {
2
2
  settingsPath: string;
3
3
  shims: string[];
4
+ skill: string;
4
5
  warnings: string[];
5
6
  built: boolean;
6
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/claude/init.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,UAAU,CAwBjG"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/claude/init.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,UAAU,CAgCjG"}
@@ -3,6 +3,8 @@ import { join } from 'node:path';
3
3
  import { execFileSync } from 'node:child_process';
4
4
  import { mergeGraftSettings } from './settings-merge.js';
5
5
  import { statuslineShim, hooksShim } from './shim-template.js';
6
+ import { skillTemplate } from './skill-template.js';
7
+ import { claudeDistDir } from './paths.js';
6
8
  export function runInit(dir, opts = {}) {
7
9
  const helpersDir = join(dir, '.claude', 'helpers');
8
10
  mkdirSync(helpersDir, { recursive: true });
@@ -16,10 +18,17 @@ export function runInit(dir, opts = {}) {
16
18
  writeFileSync(settingsPath, `${JSON.stringify(merged, null, 2)}\n`);
17
19
  const sl = join(helpersDir, 'graft-statusline.cjs');
18
20
  const hk = join(helpersDir, 'graft-hooks.cjs');
19
- writeFileSync(sl, statuslineShim());
21
+ const bakedDir = claudeDistDir(); // absolute <pkg>/dist/claude — the shims' primary resolution path
22
+ writeFileSync(sl, statuslineShim(bakedDir));
20
23
  chmodSync(sl, 0o755);
21
- writeFileSync(hk, hooksShim());
24
+ writeFileSync(hk, hooksShim(bakedDir));
22
25
  chmodSync(hk, 0o755);
26
+ // Install the graft skill — the piece that redirects the agent to graft/ before it
27
+ // greps source. Overwritten each run (graft owns this file), like the shims above.
28
+ const skillDir = join(dir, '.claude', 'skills', 'graft');
29
+ mkdirSync(skillDir, { recursive: true });
30
+ const skillPath = join(skillDir, 'SKILL.md');
31
+ writeFileSync(skillPath, skillTemplate());
23
32
  let built = false;
24
33
  const wiring = join(dir, 'graft', '.graph', 'wiring.json');
25
34
  if (opts.build !== false && opts.cliPath && !existsSync(wiring)) {
@@ -29,6 +38,6 @@ export function runInit(dir, opts = {}) {
29
38
  }
30
39
  catch { /* build best-effort; user can run `graft build` manually */ }
31
40
  }
32
- return { settingsPath, shims: [sl, hk], warnings, built };
41
+ return { settingsPath, shims: [sl, hk], skill: skillPath, warnings, built };
33
42
  }
34
43
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/claude/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAS/D,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,OAA8C,EAAE;IACnF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACnD,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAC3D,IAAI,QAAQ,GAAwB,EAAE,CAAC;IACvC,IAAI,CAAC;QAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,gCAAgC,CAAC,CAAC;IAC7G,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC1D,aAAa,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAEpE,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;IACpD,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,EAAE,cAAc,EAAE,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1D,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAErD,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC3D,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAChE,IAAI,CAAC;YACH,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAC9G,KAAK,GAAG,IAAI,CAAC;QACf,CAAC;QAAC,MAAM,CAAC,CAAC,4DAA4D,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC5D,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/claude/init.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,9 @@
1
1
  /** Absolute path to the graft CLI (`<pkgRoot>/dist/cli.js`), resolved from this module. */
2
2
  export declare function graftCliPath(): string;
3
+ /** Absolute path to this package's `dist/claude` dir. Baked into the generated shims at
4
+ * init time as their primary resolution candidate, so the statusline/hooks find graft
5
+ * without runtime guesswork — correct regardless of how Node was installed. */
6
+ export declare function claudeDistDir(): string;
3
7
  /** Absolute path to a sibling script in the claude dir (e.g. `sync-run.js`). */
4
8
  export declare function claudeScriptPath(name: string): string;
5
9
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/claude/paths.ts"],"names":[],"mappings":"AASA,2FAA2F;AAC3F,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/claude/paths.ts"],"names":[],"mappings":"AASA,2FAA2F;AAC3F,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;+EAE+E;AAC/E,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -9,6 +9,12 @@ const CLAUDE_DIR = dirname(fileURLToPath(import.meta.url));
9
9
  export function graftCliPath() {
10
10
  return join(CLAUDE_DIR, '..', 'cli.js');
11
11
  }
12
+ /** Absolute path to this package's `dist/claude` dir. Baked into the generated shims at
13
+ * init time as their primary resolution candidate, so the statusline/hooks find graft
14
+ * without runtime guesswork — correct regardless of how Node was installed. */
15
+ export function claudeDistDir() {
16
+ return CLAUDE_DIR;
17
+ }
12
18
  /** Absolute path to a sibling script in the claude dir (e.g. `sync-run.js`). */
13
19
  export function claudeScriptPath(name) {
14
20
  return join(CLAUDE_DIR, name);
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/claude/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,4FAA4F;AAC5F,8FAA8F;AAC9F,mFAAmF;AACnF,8FAA8F;AAC9F,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE3D,2FAA2F;AAC3F,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/claude/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,4FAA4F;AAC5F,8FAA8F;AAC9F,mFAAmF;AACnF,8FAA8F;AAC9F,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE3D,2FAA2F;AAC3F,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED;;+EAE+E;AAC/E,MAAM,UAAU,aAAa;IAC3B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC"}
@@ -1,3 +1,3 @@
1
- export declare function statuslineShim(): string;
2
- export declare function hooksShim(): string;
1
+ export declare function statuslineShim(bakedDir: string): string;
2
+ export declare function hooksShim(bakedDir: string): string;
3
3
  //# sourceMappingURL=shim-template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shim-template.d.ts","sourceRoot":"","sources":["../../src/claude/shim-template.ts"],"names":[],"mappings":"AAkBA,wBAAgB,cAAc,IAAI,MAAM,CAA8C;AACtF,wBAAgB,SAAS,IAAI,MAAM,CAAwD"}
1
+ {"version":3,"file":"shim-template.d.ts","sourceRoot":"","sources":["../../src/claude/shim-template.ts"],"names":[],"mappings":"AA6DA,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAwD;AAChH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAkE"}
@@ -1,20 +1,63 @@
1
- function shim(entryFile, call) {
1
+ // Generates the tiny `.cjs` shims committed into a repo's `.claude/helpers/`. Their only
2
+ // job is to locate the installed `@nanonets/graft` package's `dist/claude/<entry>.js` and
3
+ // call into it — so the real logic lives in the package and upgrades with it.
4
+ //
5
+ // Resolution order (first hit wins), designed so a global install works regardless of how
6
+ // Node was installed (Homebrew/Windows/volta all shipped broken before this):
7
+ // 1. `bakedDir` — the absolute `dist/claude` graft was running from at init time.
8
+ // Correct with zero guesswork for whoever ran `graft init`.
9
+ // 2. repo node_modules — a local dev-dep install.
10
+ // 3. `execDir/../lib` — the cheap legacy guess (covers nvm / classic prefix layout).
11
+ // 4. `npm root -g` — authoritative global dir, layout-agnostic. Only shelled out to
12
+ // when 1–3 miss (the baked path hits first for the installer), so it's
13
+ // rarely reached; queried on demand — no on-disk cache, which on a
14
+ // shared machine would be a world-writable path an attacker could point
15
+ // at their own code for us to import.
16
+ function shim(entryFile, call, bakedDir) {
2
17
  return `#!/usr/bin/env node
3
18
  const path = require('path');
19
+ const fs = require('fs');
20
+ const { pathToFileURL } = require('url');
21
+ const { execFileSync } = require('child_process');
4
22
  const dir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
23
+ const BAKED = ${JSON.stringify(bakedDir)};
24
+
25
+ // The dist/claude dir of @nanonets/graft resolved from a base whose node_modules is searched.
26
+ function fromPkg(base) {
27
+ try {
28
+ const pkg = require.resolve('@nanonets/graft/package.json', { paths: [base] });
29
+ return path.join(path.dirname(pkg), 'dist', 'claude');
30
+ } catch { return null; }
31
+ }
32
+
33
+ // The global node_modules dir per npm (handles Homebrew/Windows/volta). Queried on demand.
34
+ function globalRoot() {
35
+ try {
36
+ const root = execFileSync('npm', ['root', '-g'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], shell: true }).trim();
37
+ return root || null;
38
+ } catch { return null; /* npm unavailable */ }
39
+ }
40
+
41
+ function candidates() {
42
+ const out = [];
43
+ if (BAKED) out.push(BAKED);
44
+ const local = fromPkg(dir); if (local) out.push(local);
45
+ const legacy = fromPkg(path.join(path.dirname(process.execPath), '..', 'lib')); if (legacy) out.push(legacy);
46
+ const gr = globalRoot(); if (gr) out.push(path.join(gr, '@nanonets', 'graft', 'dist', 'claude'));
47
+ return out;
48
+ }
49
+
5
50
  function entry(name) {
6
- const globalBase = path.join(path.dirname(process.execPath), '..', 'lib');
7
- for (const base of [dir, globalBase]) {
8
- try {
9
- const pkg = require.resolve('@nanonets/graft/package.json', { paths: [base] });
10
- return path.join(path.dirname(pkg), 'dist', 'claude', name);
11
- } catch { /* try next base */ }
51
+ for (const d of candidates()) {
52
+ const f = path.join(d, name);
53
+ if (fs.existsSync(f)) return f;
12
54
  }
13
- return path.join(dir, 'dist', 'claude', name);
55
+ return path.join(dir, 'dist', 'claude', name); // last-ditch; import will no-op if absent
14
56
  }
15
- import(entry(${JSON.stringify(entryFile)})).then((m) => ${call}).catch(() => { /* graft unavailable — no-op */ });
57
+
58
+ import(pathToFileURL(entry(${JSON.stringify(entryFile)})).href).then((m) => ${call}).catch(() => { /* graft unavailable — no-op */ });
16
59
  `;
17
60
  }
18
- export function statuslineShim() { return shim('statusline.js', 'm.main()'); }
19
- export function hooksShim() { return shim('hooks.js', 'm.main(process.argv[2])'); }
61
+ export function statuslineShim(bakedDir) { return shim('statusline.js', 'm.main()', bakedDir); }
62
+ export function hooksShim(bakedDir) { return shim('hooks.js', 'm.main(process.argv[2])', bakedDir); }
20
63
  //# sourceMappingURL=shim-template.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shim-template.js","sourceRoot":"","sources":["../../src/claude/shim-template.ts"],"names":[],"mappings":"AAAA,SAAS,IAAI,CAAC,SAAiB,EAAE,IAAY;IAC3C,OAAO;;;;;;;;;;;;;eAaM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,kBAAkB,IAAI;CAC7D,CAAC;AACF,CAAC;AAED,MAAM,UAAU,cAAc,KAAa,OAAO,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;AACtF,MAAM,UAAU,SAAS,KAAa,OAAO,IAAI,CAAC,UAAU,EAAE,yBAAyB,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"shim-template.js","sourceRoot":"","sources":["../../src/claude/shim-template.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,0FAA0F;AAC1F,8EAA8E;AAC9E,EAAE;AACF,0FAA0F;AAC1F,8EAA8E;AAC9E,sFAAsF;AACtF,gFAAgF;AAChF,oDAAoD;AACpD,wFAAwF;AACxF,0FAA0F;AAC1F,2FAA2F;AAC3F,uFAAuF;AACvF,4FAA4F;AAC5F,0DAA0D;AAC1D,SAAS,IAAI,CAAC,SAAiB,EAAE,IAAY,EAAE,QAAgB;IAC7D,OAAO;;;;;;gBAMO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAmCX,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,wBAAwB,IAAI;CACjF,CAAC;AACF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgB,IAAY,OAAO,IAAI,CAAC,eAAe,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChH,MAAM,UAAU,SAAS,CAAC,QAAgB,IAAY,OAAO,IAAI,CAAC,UAAU,EAAE,yBAAyB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function skillTemplate(): string;
2
+ //# sourceMappingURL=skill-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-template.d.ts","sourceRoot":"","sources":["../../src/claude/skill-template.ts"],"names":[],"mappings":"AAKA,wBAAgB,aAAa,IAAI,MAAM,CA0CtC"}
@@ -0,0 +1,49 @@
1
+ // The graft Claude Code skill, bundled as a string so `graft init` can write it into a
2
+ // consumer repo's .claude/skills/graft/SKILL.md — no network fetch, version-locked to the
3
+ // installed graft. This is the single source of truth for the skill text; graft's own
4
+ // repo copy is regenerated from here when `init` runs in this repo. Mirrors the `.cjs`
5
+ // shim pattern in shim-template.ts.
6
+ export function skillTemplate() {
7
+ return `---
8
+ name: graft
9
+ description: This repo is indexed by graft/. For ANY task here — understanding
10
+ how something works, finding where code lives, or scoping a change — get your
11
+ context from graft before grepping or reading source files.
12
+ ---
13
+
14
+ # graft
15
+
16
+ This repo's code is summarised in \`graft/\` — small markdown nodes, each
17
+ explaining one part in plain prose and naming the exact files and line-spans it
18
+ covers. Reading a node costs a few hundred tokens; reading source to rebuild the
19
+ same understanding costs thousands.
20
+
21
+ **Get context from graft first — two ways, both land here:**
22
+
23
+ - Ask: \`graft ask "<your task, in plain words>"\` — returns the relevant nodes,
24
+ ranked, with file:line pointers. Add \`--source\` to inline the actual code at
25
+ each span, so the result IS the code you need — no separate file read.
26
+ - Or explore as usual: grep / ls / cat inside \`graft/\`. A grep for any concept,
27
+ symbol, or filename hits the node that covers it; \`graft/INDEX.md\` lists them
28
+ all.
29
+
30
+ **Then STOP at the node. It is the answer, not a lookup toward the answer.**
31
+
32
+ - **Explaining / tracing / understanding** (no code change): the node's prose
33
+ IS your deliverable. Cite files and functions straight from its \`covers:\`
34
+ list — \`covers:\` gives you the exact \`file:line\` for every symbol, so you can
35
+ cite precisely **without opening the source at all.** Do NOT open source to
36
+ "verify," "confirm," or "see the real code" — the node was generated from that
37
+ source and the spans are authoritative. Opening it costs thousands of tokens
38
+ and changes nothing in your answer.
39
+ - **Editing:** run \`graft ask "<symbol>" --source\` to pull the exact span's
40
+ code inline, and edit straight from that. Only touch the file to apply the
41
+ change at the named \`file:line\` — never read the whole file, never open
42
+ neighbouring files to "get oriented"; the pack already oriented you.
43
+
44
+ If a node genuinely lacks a detail you need, \`graft ask\` for a more specific
45
+ node before falling back to source. Reading whole source files to build
46
+ understanding is the thing graft exists to replace — it already did that work.
47
+ `;
48
+ }
49
+ //# sourceMappingURL=skill-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-template.js","sourceRoot":"","sources":["../../src/claude/skill-template.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,0FAA0F;AAC1F,sFAAsF;AACtF,uFAAuF;AACvF,oCAAoC;AACpC,MAAM,UAAU,aAAa;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwCR,CAAC;AACF,CAAC"}
package/dist/cli.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  * ask query the graph ($0, no LLM).
7
7
  * check fail if graft/ has drifted from the code — for CI.
8
8
  * viz serve the interactive graph viewer.
9
+ * mcp serve the graph over MCP (stdio) for coding agents.
9
10
  * init set up the Claude Code integration (.claude/ statusline + hooks) in this repo.
10
11
  *
11
12
  * Git is the sync: commit graft/ and anyone who clones the repo has the
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AACH,OAAO,eAAe,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AACH,OAAO,eAAe,CAAC"}
package/dist/cli.js CHANGED
@@ -6,6 +6,7 @@
6
6
  * ask query the graph ($0, no LLM).
7
7
  * check fail if graft/ has drifted from the code — for CI.
8
8
  * viz serve the interactive graph viewer.
9
+ * mcp serve the graph over MCP (stdio) for coding agents.
9
10
  * init set up the Claude Code integration (.claude/ statusline + hooks) in this repo.
10
11
  *
11
12
  * Git is the sync: commit graft/ and anyone who clones the repo has the
@@ -20,6 +21,8 @@ import { resolveConfig } from "./ai/providers.js";
20
21
  import { formatCheckReport } from "./context/check.js";
21
22
  import { formatGraphCheckReport } from "./graph/check.js";
22
23
  import { runInit } from "./claude/init.js";
24
+ import { runHostsInit } from "./hosts/init.js";
25
+ import { hostIds } from "./hosts/registry.js";
23
26
  const program = new Command();
24
27
  program
25
28
  .name("graft")
@@ -162,21 +165,73 @@ program
162
165
  spawn(opener, [srv.url], { stdio: "ignore", detached: true, shell: process.platform === "win32" }).unref();
163
166
  }
164
167
  });
168
+ program
169
+ .command("mcp")
170
+ .description("Serve the graph over MCP (stdio) — exposes graft_ask / graft_check / graft_blast_radius as tools")
171
+ .argument("[dir]", "repository root", ".")
172
+ .action(async (dir) => {
173
+ const { resolve } = await import("node:path");
174
+ const { startMcpServer } = await import("./mcp/server.js");
175
+ startMcpServer(resolve(dir));
176
+ });
165
177
  program
166
178
  .command("init")
167
- .description("Set up the Claude Code integration (.claude/ statusline + hooks) in this repo")
179
+ .description("Wire Graft into the AI coding agents used with this repo (instruction files; full hooks + statusline for Claude Code)")
168
180
  .argument("[dir]", "target repo directory", ".")
169
181
  .option("--no-build", "skip building the graph (wire files only)")
182
+ .option("--agents <ids...>", `only these agents (${hostIds().join(", ")}, claude)`)
183
+ .option("--all-agents", "write instruction files for every known agent, detected or not")
184
+ .option("--no-agents", "Claude Code wiring only; skip other agents")
185
+ .option("--list-agents", "list known agent ids and exit")
186
+ .option("--no-mcp", "skip MCP server registration for other agents")
187
+ .option("--no-hooks", "skip hook installation for other agents")
170
188
  .action((dir, opts) => {
171
- const cliPath = fileURLToPath(import.meta.url);
172
- const res = runInit(resolve(dir), { build: opts.build, cliPath });
173
- console.error(`✓ wrote ${res.settingsPath}`);
174
- for (const s of res.shims)
175
- console.error(`✓ wrote ${s}`);
176
- console.error(res.built ? "✓ built the graph (graft build)" : "· skipped graph build");
177
- for (const w of res.warnings)
178
- console.error(`⚠ ${w}`);
179
- console.error("\nDone. The statusline + hooks activate in Claude Code sessions in this repo.");
189
+ if (opts.listAgents) {
190
+ for (const id of [...hostIds(), "claude"])
191
+ console.log(id);
192
+ return;
193
+ }
194
+ const repo = resolve(dir);
195
+ const explicit = Array.isArray(opts.agents) ? opts.agents : undefined;
196
+ if (explicit) {
197
+ const validIds = [...hostIds(), "claude"];
198
+ const unknown = explicit.filter((id) => !validIds.includes(id));
199
+ if (unknown.length) {
200
+ console.error(`✗ unknown agent id(s): ${unknown.join(", ")} — valid: ${validIds.join(", ")}`);
201
+ process.exit(1);
202
+ }
203
+ }
204
+ const wantClaude = !explicit || explicit.includes("claude");
205
+ if (wantClaude) {
206
+ const cliPath = fileURLToPath(import.meta.url);
207
+ const res = runInit(repo, { build: opts.build, cliPath });
208
+ console.error(`✓ wrote ${res.settingsPath}`);
209
+ for (const s of res.shims)
210
+ console.error(`✓ wrote ${s}`);
211
+ console.error(`✓ wrote ${res.skill}`);
212
+ console.error(res.built ? "✓ built the graph (graft build)" : "· skipped graph build");
213
+ for (const w of res.warnings)
214
+ console.error(`⚠ ${w}`);
215
+ }
216
+ const skipOthers = opts.agents === false;
217
+ if (!skipOthers) {
218
+ const r = runHostsInit(repo, {
219
+ agents: explicit?.filter((id) => id !== "claude"),
220
+ all: opts.allAgents,
221
+ mcp: opts.mcp,
222
+ hooks: opts.hooks,
223
+ });
224
+ for (const w of r.written)
225
+ console.error(`✓ ${w.id}: ${w.path} (${w.action})`);
226
+ if (!explicit && !opts.allAgents && r.written.length === 0)
227
+ console.error("· no other agents detected (see --list-agents / --all-agents)");
228
+ // r.unknown is always empty here — ids are validated above, before any writes.
229
+ for (const m of r.mcp)
230
+ console.error(`✓ mcp ${m.id}: ${m.path} (${m.action})`);
231
+ for (const h of r.hooks)
232
+ console.error(`✓ hook ${h.id}: ${h.path} (${h.action})`);
233
+ }
234
+ console.error("\nDone. Claude Code gets live hooks + statusline; other agents read their instruction files.");
180
235
  console.error("For LLM summaries: set OPENROUTER_API_KEY and run `graft build --deep`.");
181
236
  });
182
237
  program.parseAsync().catch((err) => {