@nanonets/graft 0.21.1 → 0.22.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 (348) hide show
  1. package/README.md +549 -315
  2. package/dist/app/review-process.d.ts.map +1 -1
  3. package/dist/app/review-process.js +6 -5
  4. package/dist/app/review-process.js.map +1 -1
  5. package/dist/app/sources.js +2 -2
  6. package/dist/app/sources.js.map +1 -1
  7. package/dist/ask/ask.d.ts +12 -6
  8. package/dist/ask/ask.d.ts.map +1 -1
  9. package/dist/ask/ask.js +28 -38
  10. package/dist/ask/ask.js.map +1 -1
  11. package/dist/bin/graft.d.ts +3 -0
  12. package/dist/bin/graft.d.ts.map +1 -0
  13. package/dist/bin/graft.js +8 -0
  14. package/dist/bin/graft.js.map +1 -0
  15. package/dist/bin/trail.d.ts +3 -0
  16. package/dist/bin/trail.d.ts.map +1 -0
  17. package/dist/bin/trail.js +6 -0
  18. package/dist/bin/trail.js.map +1 -0
  19. package/dist/blast/blast-cli.d.ts.map +1 -1
  20. package/dist/blast/blast-cli.js +2 -1
  21. package/dist/blast/blast-cli.js.map +1 -1
  22. package/dist/blast/render.d.ts.map +1 -1
  23. package/dist/blast/render.js +3 -2
  24. package/dist/blast/render.js.map +1 -1
  25. package/dist/brand.d.ts +97 -0
  26. package/dist/brand.d.ts.map +1 -0
  27. package/dist/brand.js +254 -0
  28. package/dist/brand.js.map +1 -0
  29. package/dist/check/local-check.d.ts +104 -0
  30. package/dist/check/local-check.d.ts.map +1 -0
  31. package/dist/check/local-check.js +830 -0
  32. package/dist/check/local-check.js.map +1 -0
  33. package/dist/check/types.d.ts +31 -0
  34. package/dist/check/types.d.ts.map +1 -0
  35. package/dist/check/types.js +2 -0
  36. package/dist/check/types.js.map +1 -0
  37. package/dist/claude/format.d.ts +44 -1
  38. package/dist/claude/format.d.ts.map +1 -1
  39. package/dist/claude/format.js +113 -19
  40. package/dist/claude/format.js.map +1 -1
  41. package/dist/claude/hook-layers.d.ts +8 -0
  42. package/dist/claude/hook-layers.d.ts.map +1 -0
  43. package/dist/claude/hook-layers.js +72 -0
  44. package/dist/claude/hook-layers.js.map +1 -0
  45. package/dist/claude/hooks.d.ts +34 -0
  46. package/dist/claude/hooks.d.ts.map +1 -1
  47. package/dist/claude/hooks.js +220 -12
  48. package/dist/claude/hooks.js.map +1 -1
  49. package/dist/claude/init.d.ts +12 -1
  50. package/dist/claude/init.d.ts.map +1 -1
  51. package/dist/claude/init.js +48 -19
  52. package/dist/claude/init.js.map +1 -1
  53. package/dist/claude/session-metrics.d.ts +1 -1
  54. package/dist/claude/session-metrics.d.ts.map +1 -1
  55. package/dist/claude/session-metrics.js +11 -8
  56. package/dist/claude/session-metrics.js.map +1 -1
  57. package/dist/claude/settings-merge.d.ts +1 -0
  58. package/dist/claude/settings-merge.d.ts.map +1 -1
  59. package/dist/claude/settings-merge.js +21 -18
  60. package/dist/claude/settings-merge.js.map +1 -1
  61. package/dist/claude/shim-template.d.ts +17 -2
  62. package/dist/claude/shim-template.d.ts.map +1 -1
  63. package/dist/claude/shim-template.js +116 -22
  64. package/dist/claude/shim-template.js.map +1 -1
  65. package/dist/claude/skill-template.d.ts +10 -1
  66. package/dist/claude/skill-template.d.ts.map +1 -1
  67. package/dist/claude/skill-template.js +132 -1
  68. package/dist/claude/skill-template.js.map +1 -1
  69. package/dist/claude/state.d.ts +8 -0
  70. package/dist/claude/state.d.ts.map +1 -1
  71. package/dist/claude/state.js.map +1 -1
  72. package/dist/claude/statusline.d.ts.map +1 -1
  73. package/dist/claude/statusline.js +4 -1
  74. package/dist/claude/statusline.js.map +1 -1
  75. package/dist/claude/tally.js +1 -1
  76. package/dist/claude/tally.js.map +1 -1
  77. package/dist/cli-epilogue.d.ts +0 -6
  78. package/dist/cli-epilogue.d.ts.map +1 -1
  79. package/dist/cli-epilogue.js +5 -4
  80. package/dist/cli-epilogue.js.map +1 -1
  81. package/dist/cli-meta.d.ts +8 -0
  82. package/dist/cli-meta.d.ts.map +1 -1
  83. package/dist/cli-meta.js +28 -8
  84. package/dist/cli-meta.js.map +1 -1
  85. package/dist/cli-picker.d.ts.map +1 -1
  86. package/dist/cli-picker.js +11 -7
  87. package/dist/cli-picker.js.map +1 -1
  88. package/dist/cli.d.ts +0 -5
  89. package/dist/cli.d.ts.map +1 -1
  90. package/dist/cli.js +1039 -559
  91. package/dist/cli.js.map +1 -1
  92. package/dist/cloud/diff.d.ts +18 -0
  93. package/dist/cloud/diff.d.ts.map +1 -0
  94. package/dist/cloud/diff.js +58 -0
  95. package/dist/cloud/diff.js.map +1 -0
  96. package/dist/cloud/nudge.d.ts +66 -0
  97. package/dist/cloud/nudge.d.ts.map +1 -0
  98. package/dist/cloud/nudge.js +269 -0
  99. package/dist/cloud/nudge.js.map +1 -0
  100. package/dist/cloud/workspace-sync.d.ts +58 -0
  101. package/dist/cloud/workspace-sync.d.ts.map +1 -0
  102. package/dist/cloud/workspace-sync.js +268 -0
  103. package/dist/cloud/workspace-sync.js.map +1 -0
  104. package/dist/cloud/workspace.d.ts +159 -0
  105. package/dist/cloud/workspace.d.ts.map +1 -0
  106. package/dist/cloud/workspace.js +134 -0
  107. package/dist/cloud/workspace.js.map +1 -0
  108. package/dist/context/check.d.ts +1 -1
  109. package/dist/context/check.d.ts.map +1 -1
  110. package/dist/context/check.js +9 -8
  111. package/dist/context/check.js.map +1 -1
  112. package/dist/context/node-file.js +1 -1
  113. package/dist/context/node-file.js.map +1 -1
  114. package/dist/context/savings.d.ts.map +1 -1
  115. package/dist/context/savings.js +10 -7
  116. package/dist/context/savings.js.map +1 -1
  117. package/dist/engine.d.ts.map +1 -1
  118. package/dist/engine.js +3 -1
  119. package/dist/engine.js.map +1 -1
  120. package/dist/graph/build.d.ts +30 -0
  121. package/dist/graph/build.d.ts.map +1 -1
  122. package/dist/graph/build.js +65 -19
  123. package/dist/graph/build.js.map +1 -1
  124. package/dist/graph/cards.d.ts.map +1 -1
  125. package/dist/graph/cards.js +4 -2
  126. package/dist/graph/cards.js.map +1 -1
  127. package/dist/graph/check.d.ts.map +1 -1
  128. package/dist/graph/check.js +17 -18
  129. package/dist/graph/check.js.map +1 -1
  130. package/dist/graph/container.d.ts.map +1 -1
  131. package/dist/graph/container.js +7 -2
  132. package/dist/graph/container.js.map +1 -1
  133. package/dist/graph/extract-cache.d.ts +4 -0
  134. package/dist/graph/extract-cache.d.ts.map +1 -1
  135. package/dist/graph/extract-cache.js.map +1 -1
  136. package/dist/graph/extract.d.ts +2 -0
  137. package/dist/graph/extract.d.ts.map +1 -1
  138. package/dist/graph/extract.js +5 -32
  139. package/dist/graph/extract.js.map +1 -1
  140. package/dist/graph/generic.d.ts +7 -1
  141. package/dist/graph/generic.d.ts.map +1 -1
  142. package/dist/graph/generic.js +48 -8
  143. package/dist/graph/generic.js.map +1 -1
  144. package/dist/graph/native.d.ts +38 -0
  145. package/dist/graph/native.d.ts.map +1 -0
  146. package/dist/graph/native.js +169 -0
  147. package/dist/graph/native.js.map +1 -0
  148. package/dist/graph/refresh.d.ts.map +1 -1
  149. package/dist/graph/refresh.js +3 -2
  150. package/dist/graph/refresh.js.map +1 -1
  151. package/dist/graph/traverse-cli.d.ts.map +1 -1
  152. package/dist/graph/traverse-cli.js +4 -3
  153. package/dist/graph/traverse-cli.js.map +1 -1
  154. package/dist/graph/workspace-cli.d.ts +2 -0
  155. package/dist/graph/workspace-cli.d.ts.map +1 -1
  156. package/dist/graph/workspace-cli.js +13 -1
  157. package/dist/graph/workspace-cli.js.map +1 -1
  158. package/dist/graph/workspace.d.ts.map +1 -1
  159. package/dist/graph/workspace.js +6 -5
  160. package/dist/graph/workspace.js.map +1 -1
  161. package/dist/hosts/antigravity.d.ts +10 -3
  162. package/dist/hosts/antigravity.d.ts.map +1 -1
  163. package/dist/hosts/antigravity.js +27 -10
  164. package/dist/hosts/antigravity.js.map +1 -1
  165. package/dist/hosts/claude-global.d.ts +27 -4
  166. package/dist/hosts/claude-global.d.ts.map +1 -1
  167. package/dist/hosts/claude-global.js +90 -9
  168. package/dist/hosts/claude-global.js.map +1 -1
  169. package/dist/hosts/codex-hooks.d.ts.map +1 -1
  170. package/dist/hosts/codex-hooks.js +1 -2
  171. package/dist/hosts/codex-hooks.js.map +1 -1
  172. package/dist/hosts/config-write.d.ts.map +1 -1
  173. package/dist/hosts/config-write.js +2 -1
  174. package/dist/hosts/config-write.js.map +1 -1
  175. package/dist/hosts/cursor-hooks.d.ts +5 -2
  176. package/dist/hosts/cursor-hooks.d.ts.map +1 -1
  177. package/dist/hosts/cursor-hooks.js +14 -9
  178. package/dist/hosts/cursor-hooks.js.map +1 -1
  179. package/dist/hosts/init.d.ts +3 -0
  180. package/dist/hosts/init.d.ts.map +1 -1
  181. package/dist/hosts/init.js +32 -10
  182. package/dist/hosts/init.js.map +1 -1
  183. package/dist/hosts/instructions.d.ts +9 -4
  184. package/dist/hosts/instructions.d.ts.map +1 -1
  185. package/dist/hosts/instructions.js +19 -16
  186. package/dist/hosts/instructions.js.map +1 -1
  187. package/dist/hosts/mcp-config.d.ts +19 -4
  188. package/dist/hosts/mcp-config.d.ts.map +1 -1
  189. package/dist/hosts/mcp-config.js +81 -30
  190. package/dist/hosts/mcp-config.js.map +1 -1
  191. package/dist/hosts/plan.d.ts.map +1 -1
  192. package/dist/hosts/plan.js +11 -9
  193. package/dist/hosts/plan.js.map +1 -1
  194. package/dist/hosts/registry.d.ts +25 -2
  195. package/dist/hosts/registry.d.ts.map +1 -1
  196. package/dist/hosts/registry.js +53 -0
  197. package/dist/hosts/registry.js.map +1 -1
  198. package/dist/hosts/retract.d.ts.map +1 -1
  199. package/dist/hosts/retract.js +73 -33
  200. package/dist/hosts/retract.js.map +1 -1
  201. package/dist/hosts/sections.d.ts +17 -1
  202. package/dist/hosts/sections.d.ts.map +1 -1
  203. package/dist/hosts/sections.js +52 -2
  204. package/dist/hosts/sections.js.map +1 -1
  205. package/dist/mcp/instructions.d.ts +1 -25
  206. package/dist/mcp/instructions.d.ts.map +1 -1
  207. package/dist/mcp/instructions.js +6 -4
  208. package/dist/mcp/instructions.js.map +1 -1
  209. package/dist/mcp/server.d.ts.map +1 -1
  210. package/dist/mcp/server.js +7 -3
  211. package/dist/mcp/server.js.map +1 -1
  212. package/dist/mcp/tool-names.d.ts +10 -3
  213. package/dist/mcp/tool-names.d.ts.map +1 -1
  214. package/dist/mcp/tool-names.js +13 -5
  215. package/dist/mcp/tool-names.js.map +1 -1
  216. package/dist/mcp/tools.d.ts.map +1 -1
  217. package/dist/mcp/tools.js +6 -5
  218. package/dist/mcp/tools.js.map +1 -1
  219. package/dist/notes/ask-notes.d.ts +8 -0
  220. package/dist/notes/ask-notes.d.ts.map +1 -0
  221. package/dist/notes/ask-notes.js +18 -0
  222. package/dist/notes/ask-notes.js.map +1 -0
  223. package/dist/notes/branches.d.ts +85 -0
  224. package/dist/notes/branches.d.ts.map +1 -0
  225. package/dist/notes/branches.js +238 -0
  226. package/dist/notes/branches.js.map +1 -0
  227. package/dist/notes/cold-start.d.ts +127 -0
  228. package/dist/notes/cold-start.d.ts.map +1 -0
  229. package/dist/notes/cold-start.js +476 -0
  230. package/dist/notes/cold-start.js.map +1 -0
  231. package/dist/notes/git-facts.d.ts +17 -0
  232. package/dist/notes/git-facts.d.ts.map +1 -0
  233. package/dist/notes/git-facts.js +117 -0
  234. package/dist/notes/git-facts.js.map +1 -0
  235. package/dist/notes/home.d.ts +87 -0
  236. package/dist/notes/home.d.ts.map +1 -0
  237. package/dist/notes/home.js +423 -0
  238. package/dist/notes/home.js.map +1 -0
  239. package/dist/notes/notes.d.ts +178 -0
  240. package/dist/notes/notes.d.ts.map +1 -0
  241. package/dist/notes/notes.js +498 -0
  242. package/dist/notes/notes.js.map +1 -0
  243. package/dist/notes/repo-trail.d.ts +16 -0
  244. package/dist/notes/repo-trail.d.ts.map +1 -0
  245. package/dist/notes/repo-trail.js +74 -0
  246. package/dist/notes/repo-trail.js.map +1 -0
  247. package/dist/notes/session-cost.d.ts +21 -0
  248. package/dist/notes/session-cost.d.ts.map +1 -0
  249. package/dist/notes/session-cost.js +162 -0
  250. package/dist/notes/session-cost.js.map +1 -0
  251. package/dist/search/grep-cli.d.ts.map +1 -1
  252. package/dist/search/grep-cli.js +4 -3
  253. package/dist/search/grep-cli.js.map +1 -1
  254. package/dist/skills/skills.d.ts +118 -0
  255. package/dist/skills/skills.d.ts.map +1 -0
  256. package/dist/skills/skills.js +370 -0
  257. package/dist/skills/skills.js.map +1 -0
  258. package/dist/telemetry/contract.d.ts +2 -14
  259. package/dist/telemetry/contract.d.ts.map +1 -1
  260. package/dist/telemetry/contract.js +39 -24
  261. package/dist/telemetry/contract.js.map +1 -1
  262. package/dist/telemetry/gate.d.ts.map +1 -1
  263. package/dist/telemetry/gate.js +2 -1
  264. package/dist/telemetry/gate.js.map +1 -1
  265. package/dist/telemetry/notice.d.ts +1 -1
  266. package/dist/telemetry/notice.d.ts.map +1 -1
  267. package/dist/telemetry/notice.js +6 -5
  268. package/dist/telemetry/notice.js.map +1 -1
  269. package/dist/telemetry/track.d.ts.map +1 -1
  270. package/dist/telemetry/track.js +5 -0
  271. package/dist/telemetry/track.js.map +1 -1
  272. package/dist/upkeep-run.d.ts +7 -0
  273. package/dist/upkeep-run.d.ts.map +1 -1
  274. package/dist/upkeep-run.js +52 -12
  275. package/dist/upkeep-run.js.map +1 -1
  276. package/dist/upkeep.d.ts +9 -19
  277. package/dist/upkeep.d.ts.map +1 -1
  278. package/dist/upkeep.js +38 -59
  279. package/dist/upkeep.js.map +1 -1
  280. package/dist/util/browser.d.ts +3 -0
  281. package/dist/util/browser.d.ts.map +1 -0
  282. package/dist/util/browser.js +14 -0
  283. package/dist/util/browser.js.map +1 -0
  284. package/dist/util/front-matter.d.ts +19 -0
  285. package/dist/util/front-matter.d.ts.map +1 -0
  286. package/dist/util/front-matter.js +21 -0
  287. package/dist/util/front-matter.js.map +1 -0
  288. package/dist/util/state.d.ts +1 -18
  289. package/dist/util/state.d.ts.map +1 -1
  290. package/dist/util/state.js +4 -2
  291. package/dist/util/state.js.map +1 -1
  292. package/dist/viz/assemble.js +1 -1
  293. package/dist/viz/assemble.js.map +1 -1
  294. package/dist/viz/serve.d.ts.map +1 -1
  295. package/dist/viz/serve.js +4 -3
  296. package/dist/viz/serve.js.map +1 -1
  297. package/package.json +7 -7
  298. package/scripts/pack-trail.mjs +53 -0
  299. package/scripts/postinstall.mjs +17 -2
  300. package/scripts/run-tests.mjs +4 -1
  301. package/dist/brain/attach.d.ts +0 -44
  302. package/dist/brain/attach.d.ts.map +0 -1
  303. package/dist/brain/attach.js +0 -63
  304. package/dist/brain/attach.js.map +0 -1
  305. package/dist/brain/claude-md.d.ts +0 -61
  306. package/dist/brain/claude-md.d.ts.map +0 -1
  307. package/dist/brain/claude-md.js +0 -171
  308. package/dist/brain/claude-md.js.map +0 -1
  309. package/dist/brain/connect.d.ts +0 -59
  310. package/dist/brain/connect.d.ts.map +0 -1
  311. package/dist/brain/connect.js +0 -80
  312. package/dist/brain/connect.js.map +0 -1
  313. package/dist/brain/context-files.d.ts +0 -79
  314. package/dist/brain/context-files.d.ts.map +0 -1
  315. package/dist/brain/context-files.js +0 -245
  316. package/dist/brain/context-files.js.map +0 -1
  317. package/dist/brain/link.d.ts +0 -106
  318. package/dist/brain/link.d.ts.map +0 -1
  319. package/dist/brain/link.js +0 -167
  320. package/dist/brain/link.js.map +0 -1
  321. package/dist/brain/pull.d.ts +0 -48
  322. package/dist/brain/pull.d.ts.map +0 -1
  323. package/dist/brain/pull.js +0 -257
  324. package/dist/brain/pull.js.map +0 -1
  325. package/dist/brain/push.d.ts +0 -155
  326. package/dist/brain/push.d.ts.map +0 -1
  327. package/dist/brain/push.js +0 -304
  328. package/dist/brain/push.js.map +0 -1
  329. package/dist/brain/signup.d.ts +0 -117
  330. package/dist/brain/signup.d.ts.map +0 -1
  331. package/dist/brain/signup.js +0 -276
  332. package/dist/brain/signup.js.map +0 -1
  333. package/dist/brain/upload.d.ts +0 -61
  334. package/dist/brain/upload.d.ts.map +0 -1
  335. package/dist/brain/upload.js +0 -210
  336. package/dist/brain/upload.js.map +0 -1
  337. package/dist/brain/watch.d.ts +0 -209
  338. package/dist/brain/watch.d.ts.map +0 -1
  339. package/dist/brain/watch.js +0 -397
  340. package/dist/brain/watch.js.map +0 -1
  341. package/dist/brain/wire.d.ts +0 -38
  342. package/dist/brain/wire.d.ts.map +0 -1
  343. package/dist/brain/wire.js +0 -133
  344. package/dist/brain/wire.js.map +0 -1
  345. package/dist/legacy-args.d.ts +0 -12
  346. package/dist/legacy-args.d.ts.map +0 -1
  347. package/dist/legacy-args.js +0 -31
  348. package/dist/legacy-args.js.map +0 -1
package/README.md CHANGED
@@ -1,238 +1,511 @@
1
1
  <div align="center">
2
2
 
3
- <img src="assets/graft-hero.png" alt="Graft — open-source context layer for large codebases" width="100%"/>
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="assets/trail-code-banner-dark.png">
5
+ <img src="assets/trail-code-banner.png" alt="Trail-code (previously graft), by Trail. A map of a codebase, with one team decision pinned to it: keep retries at 4." width="100%"/>
6
+ </picture>
4
7
 
5
- ### Turbocharge Claude Code, Cursor, Codex, Gemini & every coding agent: faster, cheaper, with contextual understanding specific to your codebase.
8
+ ### The self-learning context layer for coding agents.
6
9
 
7
- <a href="https://trendshift.io/repositories/92209?utm_source=trendshift-badge&utm_medium=badge&utm_campaign=badge-trendshift-92209" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/92209/daily?language=TypeScript" alt="trailhq/Graft | Trendshift" width="250" height="55"/></a>
10
+ Trail-code gives Claude Code, Cursor, Codex and other coding agents a map of your code, and what your team has learned about it.
11
+
12
+ | | Code map (previously graft) | Learnings |
13
+ |---|---|---|
14
+ | **What is it?** | An index of your code: every function and who calls it, so your agent sees what a change can break | What you, your agents and your team have learned and decided |
15
+ | **What does it do for your agent?** | Takes it straight to the right files | Lets it pick up where you and your team left off |
16
+ | **Where does it come from?** | Your code, read on your machine | Your conversations, as you work |
17
+
18
+ <a href="https://trendshift.io/repositories/92209?utm_source=trendshift-badge&utm_medium=badge&utm_campaign=badge-trendshift-92209" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/92209/daily?language=TypeScript" alt="trailhq/Trail-Code | Trendshift" width="250" height="55"/></a>
8
19
 
9
20
  <p>
10
- <a href="https://github.com/NanoNets/Graft"><img src="https://img.shields.io/github/stars/NanoNets/Graft?style=for-the-badge&logo=github&logoColor=white&label=Star%20on%20GitHub&color=FFC83D" /></a>
21
+ <a href="https://github.com/trailhq/Trail-Code"><img src="https://img.shields.io/github/stars/trailhq/Trail-Code?style=for-the-badge&logo=github&logoColor=white&label=Star%20on%20GitHub&color=FFC83D" /></a>
11
22
  <a href="https://trailhq.com/graft"><img src="https://img.shields.io/badge/website-trailhq.com/graft-E5484D?style=for-the-badge" /></a>
12
23
  <a href="https://discord.gg/zxmKweAA29"><img src="https://img.shields.io/badge/Discord-join-5865F2?style=for-the-badge&logo=discord&logoColor=white" /></a>
13
- <a href="https://www.npmjs.com/package/@nanonets/graft"><img src="https://img.shields.io/npm/v/%40nanonets%2Fgraft?style=for-the-badge&logo=npm&logoColor=white&label=npm" /></a>
14
- <a href="https://www.npmjs.com/package/@nanonets/graft"><img src="https://img.shields.io/npm/dm/%40nanonets%2Fgraft?style=for-the-badge&logo=npm&logoColor=white&label=downloads" /></a>
15
- <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/%40nanonets%2Fgraft?style=for-the-badge&logo=nodedotjs&logoColor=white" /></a>
24
+ <a href="https://www.npmjs.com/package/@trailhq/trail-code"><img src="https://img.shields.io/npm/v/%40trailhq%2Ftrail-code?style=for-the-badge&logo=npm&logoColor=white&label=npm" /></a>
25
+ <a href="https://www.npmjs.com/package/@trailhq/trail-code"><img src="https://img.shields.io/npm/dm/%40trailhq%2Ftrail-code?style=for-the-badge&logo=npm&logoColor=white&label=downloads" /></a>
26
+ <a href="https://nodejs.org"><img src="https://img.shields.io/node/v/%40trailhq%2Ftrail-code?style=for-the-badge&logo=nodedotjs&logoColor=white" /></a>
16
27
  <img src="https://img.shields.io/badge/TypeScript-strict-3178C6?style=for-the-badge&logo=typescript&logoColor=white" />
17
28
  <img src="https://img.shields.io/badge/License-MIT-20C997?style=for-the-badge" />
18
29
  <a href="TELEMETRY.md"><img src="https://img.shields.io/badge/telemetry-anonymous%2C%20opt--out-546FFF?style=for-the-badge" /></a>
19
- <a href="https://scorecard.dev/viewer/?uri=github.com/NanoNets/Graft"><img src="https://img.shields.io/ossf-scorecard/github.com/NanoNets/Graft?style=for-the-badge&label=openssf%20scorecard" /></a>
20
- <a href="https://app.trailhq.com/get-started?step=repo"><img src="https://img.shields.io/badge/Trail-try%20it-E5484D?style=for-the-badge&logoColor=white" /></a>
30
+ <a href="https://scorecard.dev/viewer/?uri=github.com/trailhq/Trail-Code"><img src="https://img.shields.io/ossf-scorecard/github.com/trailhq/Trail-Code?style=for-the-badge&label=openssf%20scorecard" /></a>
21
31
  </p>
22
32
 
23
- ### Up to **4× cheaper** and **3× faster**, with better or no loss of correctness.
33
+ ### **46% fewer tool calls**, **60% less time**, and more real issues solved.
24
34
 
25
- | Metric | Cold Claude Code | Claude Code with graft |
35
+ | | Cold agent | Agent with the graft map |
26
36
  |---|---|---|
27
- | Tool-call reduction | Baseline | **+46%** |
28
- | Token savings | Baseline | **+42%** |
29
- | Time savings | Baseline | **+60%** |
30
- | Correctness | 54% | **66% (+12 pts)** |
37
+ | Tool calls, 162 runs | baseline | **46% fewer** |
38
+ | Uncached input tokens, 162 runs | baseline | **42% fewer** |
39
+ | Time, 162 runs | baseline | **60% less** |
40
+ | SWE-bench Verified, 50 real issues | 27 solved (54%) | **33 solved (66%)** |
41
+
42
+ ```bash
43
+ npm install -g @trailhq/trail-code && trail init
44
+ ```
31
45
 
32
46
  </div>
33
47
 
34
- <p align="center">
35
- <b>Stop repeating yourself to your coding agent.</b><br/>
36
- You correct it, and by the next session it has forgotten. Trail manages your CLAUDE.md and AGENTS.md so it doesn't.
37
- </p>
48
+ > [!NOTE]
49
+ > **Graft is now Trail-code.** Graft lives on as the graft map, and every `graft` command still works. What's new is learnings. [What changed](#coming-from-graft)
38
50
 
39
51
  <p align="center">
40
- &bull;&nbsp; Every correction you make becomes a rule your agent keeps.<br/>
41
- &bull;&nbsp; The ones that can't break get a hook that blocks it, not a note it ignores.
52
+ <picture>
53
+ <source media="(prefers-color-scheme: dark)" srcset="assets/trail-code-how-it-works-dark.webp">
54
+ <img src="assets/trail-code-how-it-works.webp" alt="Without Trail: each task starts a new session with an agent that has no memory. It searches blind, opens the wrong files, guesses how the code is wired, ships the task, and the context is lost. This repeats for every task and every teammate's agent. With Trail, your agent already knows your code: trail init builds the graft map, a hook points the agent to it before each session, the agent reads the graph with its impact radius, gets precise context, ships the task, then saves learnings. One graph, every agent, up to 4x tokens saved." width="880"/>
55
+ </picture>
42
56
  </p>
43
57
 
44
- <p align="center">
45
- <a href="https://app.trailhq.com/get-started?step=repo"><img src="https://img.shields.io/badge/Try%20it%20on%20your%20repo%20%E2%86%92-E5484D?style=for-the-badge" alt="Try it on your repo" height="34"/></a>
46
- </p>
58
+ ---
47
59
 
48
- <p align="center">
49
- <img src="assets/graft-comparison-demo.gif" alt="Side-by-side comparison of a coding agent working with and without graft" width="820"/>
50
- </p>
60
+ ## What changes in your agent
61
+
62
+ | Without Trail-code | With Trail-code |
63
+ |---|---|
64
+ | Greps and opens file after file to find the code it needs | Gets the right files and functions with your prompt |
65
+ | Re-explores code a teammate already figured out last week | Starts from their learning: what they decided, what they ruled out, what to watch out for |
66
+ | Undoes a teammate's decision, because it never knew about it | `trail check` flags it before the PR, quoting who decided it and why |
67
+ | Finds out at merge time that a teammate changed the same file | Opens its reply with the overlap: `● overlap · Kumar's branch kumar/retry also changes client.go` |
68
+ | Has to be told the same things every session | Starts from what you've told it before: `trail init` finds what you said more than once in your past sessions |
69
+ | You write and update CLAUDE.md by hand | Learnings are saved from your conversations, in files you can read |
70
+
71
+ **Same model, more tasks solved.** On SWE-bench Verified (real GitHub issues, graded by the maintainers' own tests), Claude Sonnet 5 solved **33 of 50** issues with the graft map and **27 of 50** without it, using 23% fewer tokens. [Details](#swe-bench-verified)
72
+
73
+ **Cheaper and faster.** Across 162 runs of the same agent on the same tasks: **32% lower cost**, **42% fewer tokens**, **60% less time**, and the same share of correct answers. On popular open-source repos, up to **4× cheaper** and **3× faster**. [Details](#benchmark)
51
74
 
52
75
  ---
53
76
 
54
77
  ## Contents
55
78
 
79
+ - [How it works](#how-it-works)
56
80
  - [Quick start](#quick-start)
57
- - [The problem](#the-problem)
58
- - [What Graft does](#what-graft-does)
59
- - [Benchmark](#benchmark)
60
- - [SWE-bench Verified](#swe-bench-verified)
61
- - [How the graph gets built](#how-the-graph-gets-built)
62
- - [Supported languages](#supported-languages)
63
- - [What's in a node](#whats-in-a-node)
64
- - [What runs where](#what-runs-where)
65
- - [Agent integration](#agent-integration) — [MCP server](#mcp-server) · [Claude Code (deep integration)](#claude-code-deep-integration)
66
- - [CLI](#cli)
67
- - [Search & orient](#search--orient-graft-grep--graft-map) (`graft grep` / `graft map`)
68
- - [Monorepos & multi-repo folders](#monorepos--multi-repo-folders)
69
- - [Visualize it](#visualize-it-graft-viz) (`graft viz`)
70
- - [Tested on your popular repos](#tested-on-your-popular-repos)
71
- - [Development](#development)
72
- - [License](#license)
81
+ - [Part 1: The graft map](#part-1-the-graft-map), your code
82
+ - [Part 2: Learnings](#part-2-learnings), what you, your agents and your team know
83
+ - [Four kinds, three places](#four-kinds-three-places) · [One decision, two teammates](#one-decision-two-teammates) · [A learning is a file](#a-learning-is-a-file) · [Your agent does the saving](#your-agent-does-the-saving)
84
+ - [Your team](#your-team)
85
+ - [What stays on your machine](#what-stays-on-your-machine)
86
+ - [Benchmark](#benchmark) · [SWE-bench Verified](#swe-bench-verified) · [Tested on popular repos](#tested-on-popular-repos)
87
+ - [FAQ](#faq)
88
+ - Reference: [How the graph gets built](#how-the-graph-gets-built) · [Supported languages](#supported-languages) · [What's in a node](#whats-in-a-node) · [What runs where](#what-runs-where) · [Agent integration](#agent-integration) · [CLI](#cli) · [Search & orient](#search--orient-trail-grep--trail-map) · [Monorepos](#monorepos-submodules--multi-repo-folders) · [Visualize it](#visualize-it-trail-viz) · [Development](#development)
89
+
90
+ ---
91
+
92
+ ## How it works
93
+
94
+ Trail-code has two parts. Both run on your machine.
95
+
96
+ 1. **The graft map: your code.** `trail init` parses your repo with tree-sitter into a map of every file, function and who calls what. No model, no API key. It refreshes itself when the code changes, uncommitted edits included. Your agent gets pointers to the matching files and functions with each prompt, and sees what depends on a file right after it edits it.
97
+ 2. **Learnings: what you, your agents and your team know.** When a session works something out, or you correct how something is done, your agent saves it as a learning. The next session on that code, yours or a teammate's, starts from it instead of digging again. Learnings about the code are committed with the code; learnings about you stay on your machine. On day one, `trail init` starts you off with what you told Claude more than once in your past sessions.
98
+
99
+ The graft map tells your agent *where* things are. Learnings tell it *why* they are that way, and *how* the work gets done here.
73
100
 
74
101
  ---
75
102
 
76
103
  ## Quick start
77
104
 
78
105
  ```bash
79
- npm install -g @nanonets/graft # install the CLI, once
80
- graft init # build the graph + wire it into Claude Code
106
+ npm install -g @trailhq/trail-code # install the CLI, once
107
+ trail init # in your repo: build the graft map, set up .trail/, wire your agents
81
108
  ```
82
109
 
83
- That is the whole setup. `graft init` asks which of your coding agents to wire up, 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.
84
-
85
- Nothing is written until you pick. Run `graft init --dry-run` to see every file it would touch first, or `graft init --agents claude` to skip the prompt and wire Claude Code alone.
110
+ That is the whole setup. `trail init` asks which of your coding agents to wire up, builds the graft map from your code, creates `.trail/` for the repo's learnings, and adds a statusline and hooks to Claude Code. It also reads your past Claude Code sessions in the repo, once, for what you told Claude more than once, and saves those as learnings. Your own Claude Code does that reading, in about a minute. Then work the way you always do. No daemon, no server, nothing to babysit: it is all files.
86
111
 
87
- `graft build` adds `graft/` to your `.gitignore` automatically — the graph is a local, regenerable cache (like `node_modules`), not something you commit. What you share is the wiring `init` dropped into `.claude/`; each teammate runs `graft build` to generate their own graph:
112
+ Commit the setup so your teammates get it too. The graft map itself, in `graft/`, is a local cache like `node_modules` and is added to `.gitignore`, so it stays out of the commit:
88
113
 
89
114
  ```bash
90
- git add .claude && git commit -m "wire in graft"
115
+ git add .claude .mcp.json .trail .gitignore .ignore && git commit -m "set up Trail-code"
91
116
  ```
92
117
 
93
- Prefer not to install globally? `npx @nanonets/graft init` works the same way.
118
+ Teammates' Claude Code reads the learnings in `.trail/` even before they install anything, and tells them once how to get the rest.
119
+
120
+ `trail init --dry-run` shows the agent wiring it would write; `trail init --agents claude` wires Claude Code alone.
121
+
122
+ ### Coming from graft?
123
+
124
+ Nothing breaks. The code map you know is now called the graft map, and it is one of Trail-code's two parts.
125
+
126
+ | | Before | Now |
127
+ |---|---|---|
128
+ | Name | graft | Trail-code |
129
+ | The code map | graft | the graft map (same thing) |
130
+ | Command | `graft` | `trail` (`graft` still works) |
131
+ | Package | `@nanonets/graft` | `@trailhq/trail-code` (the old one still works) |
132
+ | Learnings | None | New, see [Part 2](#part-2-learnings) |
133
+
134
+ `graft` and `@nanonets/graft` run the same code as `trail`, and print what they always printed.
135
+
136
+ Already have graft? `graft upgrade` adds the `trail` command next to it.
137
+
138
+ Repos that graft set up move to trail on their own: once the `trail` command is installed, each one moves the first time you open Claude Code in it. To move one right away, run `trail init` in it. Commit what changes so your teammates move too.
94
139
 
95
- <p align="center">
96
- <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"/>
97
- </p>
98
140
 
99
141
  ---
100
142
 
101
- ## The problem
143
+ ## Part 1: The graft map
102
144
 
103
- Every task, your coding agent starts blind. Before it changes anything, it re-explores the repo: grep a term, open a file, follow an import, back out, try again. It is rebuilding a picture of a codebase it mapped an hour ago and threw away. That rediscovery burns most of a run's tool calls, tokens, and latency, and it is pure overhead:
145
+ Without a map, your coding agent starts every task blind. It greps a term, opens a file, follows an import, backs out and tries again, rebuilding a picture of a codebase it mapped an hour ago and threw away. That rediscovery burns most of a run's tool calls, tokens and time. People onboard to a codebase once. Agents onboard every single time.
104
146
 
105
- - **Repeated.** Every task pays the exploration cost again, from zero.
106
- - **Discarded.** Whatever the agent figured out dies with the session.
107
- - **Unshared.** The next teammate, and their agent, start from scratch too.
147
+ The graft map builds that understanding once, and keeps it current:
108
148
 
109
- Humans onboard to a codebase once. Agents onboard every single time.
149
+ - **Every file, function and caller.** Parsed with tree-sitter into a graph of symbols and who calls what. Deterministic, no model, no network, 23 languages.
150
+ - **The right code with every prompt.** In Claude Code, hooks add the matching files and functions to each prompt, and show what depends on a file right after your agent edits it (the "blast radius"). Cursor, Codex and other agents get the same map through MCP tools and their instruction files.
151
+ - **Always fresh.** Every query checks the working tree first (a few tens of milliseconds when nothing moved) and rebuilds only what changed, so answers describe the code as it is right now, uncommitted edits included.
152
+ - **Plain files you can read.** Linked markdown nodes your agent opens and greps like any other file. No embeddings, no index to keep warm.
153
+ - **Summaries if you want them.** `trail build --deep` adds plain-English summaries of each part of the system, written by the model provider you choose, under your own key.
110
154
 
111
- <p align="center">
112
- <img src="assets/graft-site-act-demo.gif" alt="A no-map agent's exploration trail wandering file to file before it finds what it needs" width="820"/>
113
- </p>
155
+ | | Cold Claude Code | Claude Code with the graft map |
156
+ |---|---|---|
157
+ | SWE-bench Verified, 50 real issues | 27 solved | **33 solved (+12 pts)** |
158
+ | Our benchmark, 162 runs | baseline | **32% lower cost, 42% fewer tokens, 60% less time** |
159
+ | Popular open-source repos | baseline | **up to 4× cheaper, 3× faster** |
160
+
161
+ How it is measured: [Benchmark](#benchmark), [SWE-bench Verified](#swe-bench-verified) and [Tested on popular repos](#tested-on-popular-repos). How it is built: [the reference](#how-the-graph-gets-built).
114
162
 
115
163
  ---
116
164
 
117
- ## What Graft does
165
+ ## Part 2: Learnings
118
166
 
119
- Graft builds that understanding **once** and writes it into your repo as a folder of linked markdown files, one node per system, API, or concept.
167
+ Your agent forgets everything when a session ends. Next week, it digs through the same code again, or worse, undoes a decision it never knew was made. Your teammates' agents do the same.
120
168
 
121
- - **Real explanations, not a list of symbols.** Each node says, in plain English, what a part of the system does and how it connects to the rest, the way a senior engineer would explain it. That is the part an agent actually needs so it can skip the exploration. It is not a dump of function names.
122
- - **A real graph you can read.** No embeddings, no similarity search, no index to keep warm. The graph is a set of linked files your agent opens, greps, and follows, exactly the way it reads any other file in the repo.
123
- - **A local cache, not a committed artifact.** `graft build` writes `graft/` and adds it to `.gitignore` — it's a regenerable local cache, like `node_modules`. What you commit is the small wiring `graft init` drops in (`.claude/`, `AGENTS.md`, the MCP config); each teammate runs `graft build` to generate their own graph. No database, no server, no setup.
124
- - **Always fresh, automatically.** Every query rebuilds the graph against the working tree first — structural, `$0`, ~3ms when nothing moved — so `ask`/`grep`/`callers`/`skeleton`/`map` describe the code as it is right now, including uncommitted edits. `graft check` is a local freshness signal; there's no stale index to babysit.
125
- - **Your provider, your key, your model.** Summaries are written by any provider you choose — OpenAI, Anthropic (native), OpenRouter, Fireworks, Groq, OrcaRouter, a LiteLLM proxy, or a local model — under your own key. The structural code graph (`graft build`, `graft check`) is deterministic tree-sitter and never calls a model at all.
169
+ Trail-code keeps what your agent works out as **learnings**, saved from your conversations as you work. The next session starts from what you, your agents and your team already know. You don't have to write any of it by hand.
126
170
 
127
- <p align="center">
128
- <picture>
129
- <source media="(prefers-color-scheme: dark)" srcset="assets/graft-cold-vs-graft-dark.png">
130
- <img src="assets/graft-cold-vs-graft.png" alt="The same task, 'fix the auth bug', run two ways. A cold Claude Code session re-reads the repo and wanders file to file; Claude Code + graft loads its map once and rides the hooks to one clean pass. With Graft: 46% fewer tool calls, 42% fewer tokens, 60% less time, +22% more SWE-bench instances resolved." width="880"/>
131
- </picture>
132
- </p>
171
+ ### Four kinds, three places
172
+
173
+ Every learning has a kind (what it is) and a place (who it is for).
174
+
175
+ **Three places:**
176
+
177
+ | Place | What goes there | Where it lives | Who sees it |
178
+ |---|---|---|---|
179
+ | **Personal** | About you and your machine: your setup, your habits | `~/.trail/` | Only you. Never committed, never uploaded |
180
+ | **Repo** | About the code: why it is the way it is, how work gets done in it | the repo's `.trail/`, committed with the change | Everyone who clones the repo, even before they install Trail-code |
181
+ | **Team** | What your whole team has learned, across repos | a Trail workspace (soon) | Your team, on the team page |
182
+
183
+ Your agent picks between personal and repo: something about your own setup stays personal ("saved just for you"); something about the code goes in the repo ("saved for your team"). The team place will gather the repo learnings of every repo in your workspace, so your team sees them together.
184
+
185
+ **Four kinds:**
186
+
187
+ | Kind | Example | Personal | Repo | Team |
188
+ |---|---|:---:|:---:|:---:|
189
+ | **Decisions**: why the code is the way it is | *"Keep retries at 4. Ruled out 10: one call could block for over an hour."* | ✅ | ✅ | soon |
190
+ | **Preferences**: how you like things done | *"Use pnpm, not npm."* Saved when you correct your agent, and found in your past sessions by `trail init`. | ✅ | ✅ | soon |
191
+ | **Skills**: how a job is done here | *"Read rotation with page.Rotation(), never pdfcpu: it drops /Rotate."* | soon | soon | soon |
192
+ | **Guardrails**: what must never happen | *"Never push to main."* Checked before the command runs. | soon | soon | soon |
193
+
194
+ Decision or preference? Ask whether it points at specific code and goes stale when that code changes. If it does, it is a decision. If not, it is a preference.
195
+
196
+ ### One decision, two teammates
197
+
198
+ A real test: two people, two clones of [hashicorp/go-retryablehttp](https://github.com/hashicorp/go-retryablehttp), headless Claude Code sessions.
199
+
200
+ **1. Anirudh works out why the retry count is 4.** Before committing, the agent saves what it found as a learning, and commits it with the change:
201
+
202
+ ```text
203
+ ✓ saved for your team · .trail/learnings/2026-10-09-keep-the-default-retry-count-at-anirudh.md
204
+ ```
205
+
206
+ The reply ends with `📝 Committed · Kumar works in this part of the codebase, and their agents now get a 27k-token head start`.
207
+
208
+ **2. Kumar pulls and asks about the same code.** Kumar's Claude reads Anirudh's learning before exploring, answers from it in 11 seconds for $0.10, and ends with a line saying where the answer came from, like:
209
+
210
+ ```text
211
+ 📝 Started from Anirudh's learning · saved ~27k tokens
212
+ ```
213
+
214
+ **3. Kumar raises the retry count to 10 anyway.** Before the PR, `trail check` compares the change with everything the team has learned:
215
+
216
+ ```text
217
+ checking 1 changed file against 1 learning and 0 skills
218
+
219
+ ✗ client.go:51
220
+ changes defaultRetryMax from 4 to 10
221
+ Anirudh · Oct 9: Keep defaultRetryMax = 4: ten retries with the
222
+ default backoff can hold one Do() call for over an hour.
223
+
224
+ · 1 conflict · fix it, or say why in the commit message or PR description
225
+ ```
226
+
227
+ Kumar's Claude explains the override in the commit.
228
+
229
+ **4. Anirudh asks about the same code again.** Kumar's branch isn't merged yet, but Anirudh's Claude opens its reply with:
230
+
231
+ ```text
232
+ ● overlap · Kumar's branch kumar/retry also changes client.go (pushed today 15:32)
233
+ ```
234
+
235
+ None of this needs a server. Learnings travel through git, like the code they are about.
236
+
237
+ ### A learning is a file
238
+
239
+ A decision is a short markdown file in `.trail/learnings/`, reviewed in the pull request like any other change:
240
+
241
+ ```markdown
242
+ ---
243
+ title: Keep the default retry count at 4
244
+ author: Anirudh
245
+ date: 2026-10-09
246
+ cost: { tokens: 27400 }
247
+ touches:
248
+ - client.go
249
+ ---
250
+
251
+ ## Decided
252
+ - Keep defaultRetryMax = 4: ten retries with the default backoff can hold one Do() call for over an hour.
253
+
254
+ ## Tried and ruled out
255
+ - Raising the default to 10 for one customer: worst case, a single Do() call blocks for over an hour.
256
+
257
+ ## Watch out
258
+ - RetryWaitMax caps each wait at 30s, not the total: the waits add up with every retry.
259
+ ```
260
+
261
+ `touches` is how the next session on `client.go` finds it. A learning also records what the session spent working it out, in minutes and tokens. That is where "saved ~27k tokens" comes from: what the learning took to work out, less what it costs to read.
262
+
263
+ Where everything lives:
264
+
265
+ ```text
266
+ your-repo/
267
+ ├── .trail/learnings/ learnings about this repo's code (commit them)
268
+ └── graft/ the graft map, a local cache (gitignored)
269
+
270
+ ~/.trail/ your personal learnings, on this machine only
271
+ ```
272
+
273
+ ### Your agent does the saving
274
+
275
+ Your agent saves and uses learnings on its own, at these moments:
276
+
277
+ - **On day one, what you told Claude before.** `trail init` reads your own messages in the repo's past Claude Code sessions, leaving out tool output, pasted text and headless runs. It keeps only what you said in two or more sessions, and scrubs secrets.
278
+ - **After real digging, a decision.** When a turn took real work and nothing was saved yet, Claude Code is asked once a session to save a learning: what was decided, what was ruled out, what to watch out for. A summary, never a transcript, and nothing secret.
279
+ - **After a correction, a learning.** When you correct how something is done here, or state a rule for it, your agent saves that too, so nobody has to say it again.
280
+ - **Before each task, the learnings on it.** Each session starts with the learnings that apply to all work in the repo. Each prompt brings in the ones earlier sessions left on that code, above the code itself. A teammate's learning says whose it is.
281
+ - **Before a PR, the check.** Your agent is told to run `trail check` before it commits, pushes or opens a pull request.
282
+ - **Never rewrites history.** Your agent never edits an existing learning. When it goes against one, it says why in the commit and saves a new one.
283
+
284
+ The commands, if you want them:
285
+
286
+ ```bash
287
+ trail note --title "<what it was about>" # save a learning (the text on stdin); --personal keeps it in ~/.trail
288
+ trail check # check your branch against everything the team has learned
289
+ trail team # what the team learned this week, and where work overlaps
290
+ trail status # the graft map, learnings and tokens saved, on one screen
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Your team
296
+
297
+ Learnings reach your teammates through git, with no server: commit `.trail/`, and every clone has them. Learnings on a teammate's pushed branch show up before it merges, marked "pushed and not merged yet", with only their first lines.
298
+
299
+ `trail team` shows the last 7 days in your terminal: what the team learned and where work overlaps.
300
+
301
+ ```bash
302
+ trail team # this week's learnings and overlaps
303
+ ```
304
+
305
+ Coming soon: a Trail workspace, for your team's view across repos. A team page will show who is learning what, how often learnings were reused, and where work overlaps.
306
+
307
+ ---
308
+
309
+ ## What stays on your machine
310
+
311
+ - **Your code.** The graft map is built on your machine with tree-sitter. No model, no network. The optional `trail build --deep` summaries go to the model provider you choose, under your own key.
312
+ - **Personal learnings.** Kept in `~/.trail`. Never committed, never uploaded.
313
+ - **Repo learnings.** Files in your repo, shared through git like any other file.
314
+ - **Your past sessions.** `trail init` reads your own messages from Claude Code's transcripts for the repo, on your machine. Your own Claude Code does the reading, with Claude Sonnet under your login, so your messages go only to Anthropic, and it counts toward your Claude usage. None of it goes to Trail.
315
+ - **If you connect a Trail workspace.** No learning goes to Trail until you do. Once connected, the learnings in the repos you picked go to Trail, including those on teammates' pushed branches. So does a record of each search and check that used them: the search text, the files, and whose learnings were shown. That is how the team page counts reuse.
316
+ - **Anonymous usage stats.** Buckets and fixed labels only, never the title, text or paths of a learning. [`TELEMETRY.md`](TELEMETRY.md) lists every field. Turn it off with `trail telemetry disable` or `DO_NOT_TRACK=1`.
133
317
 
134
318
  ---
135
319
 
136
320
  ## Benchmark
137
321
 
138
- An agent that reads the graph should be cheaper and faster without getting more answers wrong. That's the whole claim, so we measured it instead of asserting it.
322
+ An agent that reads the graft map should be cheaper and faster without getting more answers wrong. That's the whole claim, so we measured it instead of asserting it.
139
323
 
140
- The harness ran three variants of the same Claude Sonnet 5 agent with the same file tools: **cold** (explores from zero), **Graft** (a `graft ask --source` bundle pushed up front), and **pull** (graft_find_code/graft_file_api tools, nothing injected — context paid for only when asked). An Opus 4.8 judge scored correctness with a required-keyword floor, so a fast-but-wrong answer couldn't win by being fast. Cost is cache-aware: reads ≈0.1×, writes 1.25×, the billing model agents actually run under.
324
+ The harness ran three variants of the same agent loop on Claude Sonnet 5, with the same file tools: **cold** (explores from zero), **push** (a `trail ask --source` bundle up front), and **pull** (the `trail_find_code` and `trail_file_api` tools, nothing injected, context paid for only when asked). An Opus 4.8 judge scored correctness with a required-keyword floor, so a fast but wrong answer couldn't win by being fast. Cost is cache-aware: reads ≈0.1×, writes 1.25×, the billing model agents actually run under.
141
325
 
142
- 162 runs, two repos (graft itself and a real Node/Express auth service), 3 trials each, tasks split between single-file and multi-file questions.
326
+ 162 runs, two repos (this one and a real Node/Express auth service), 3 trials each, tasks split between single-file and multi-file questions.
143
327
 
144
- | Metric (mean/task) | Cold Claude Code | Claude Code with graft |
328
+ | Metric (mean/task) | Cold agent | Agent with the graft map (push) |
145
329
  |---|---|---|
146
- | Cost savings ($) | 0.0429 | **0.0292 (+32%)** |
147
- | Token savings | 8,070 | **4,650 (+42%)** |
148
- | Tool-call savings | 4.2 | **2.3 (+46%)** |
149
- | Latency savings (s) | 39.8 | **15.8 (+60%)** |
330
+ | Cost ($) | 0.0429 | **0.0292 (32% lower)** |
331
+ | Uncached input tokens | 8,070 | **4,650 (42% fewer)** |
332
+ | Tool calls | 4.2 | **2.3 (46% fewer)** |
333
+ | Latency (s) | 39.8 | **15.8 (60% less)** |
150
334
  | Correctness | 93% | 93% (equal) |
151
335
 
152
- Graft never answered worse than cold, on any corpus. The pull variant gave up most of that speed for something bigger: correctness jumped to 98%, +5 points over cold, the strongest single result in the sweep. Push when speed is what you need; pull when being right matters more.
336
+ Push, the column above, gave up 3 correctness points on one corpus for its savings. The pull variant never answered worse than cold on any corpus, and gave up most of that speed for something bigger: correctness jumped to 98%, 5 points over cold, the strongest single result in the sweep. Push when speed is what you need; pull when being right matters more.
153
337
 
154
338
  ---
155
339
 
156
340
  ## SWE-bench Verified
157
341
 
158
- The sweep above is our harness measuring our mechanism. So we ran the industry-standard one too — **SWE-bench Verified**, real GitHub issues from real repos, graded by the official `swebench` harness. No judge model, no similarity score: your patch is applied, the maintainers' own tests are run, and you either flip the failing test without breaking the passing ones or you don't.
342
+ The sweep above is our harness measuring our mechanism. So we ran the industry-standard one too: **SWE-bench Verified**, real GitHub issues from real repos, graded by the official `swebench` harness. No judge model, no similarity score: your patch is applied, the maintainers' own tests are run, and you either flip the failing test without breaking the passing ones or you don't.
159
343
 
160
- **50 instances**, same model on both arms — **Claude Sonnet 5** — same Docker images, same turn limits. The only difference is whether graft is wired in.
344
+ **50 instances**, the same model on both arms (**Claude Sonnet 5**), the same Docker images, the same turn limits. The only difference is whether the graft map is wired in.
161
345
 
162
- | Correctness & efficiency | Cold Claude Code | Claude Code with graft | Improvement |
346
+ | Correctness & efficiency | Cold Claude Code | Claude Code with the graft map | Improvement |
163
347
  |---|---|---|---|
164
348
  | Correctness | 27 / 50 (54%) | **33 / 50 (66%)** | **+12 pts** |
165
- | Token savings | 142.0M | **109.4M** | **+23%** |
166
- | Cost savings | $52.34 | **$42.43** | **+19%** |
167
- | Tool-call savings | 1,370 | **1,031** | **+25%** |
168
- | API-request savings | 2,455 | **1,875** | **+24%** |
169
- | Wall-clock savings | 13,094s | **8,922s** | **+32%** |
349
+ | Tokens | 142.0M | **109.4M** | **23% fewer** |
350
+ | Cost | $52.34 | **$42.43** | **19% lower** |
351
+ | Tool calls | 1,370 | **1,031** | **25% fewer** |
352
+ | API requests | 2,455 | **1,875** | **24% fewer** |
353
+ | Wall-clock | 13,094s | **8,922s** | **32% less** |
170
354
 
171
- graft resolved **33 of 50 instances** against Cold Claude Code's 27 — and got there with 25% fewer tool calls, 23% fewer tokens, and 32% less wall-clock time. Every correctness win has the same shape: the baseline patches one file and misses its siblings. On `django-11532` it patched 1 of the 5 files the fix requires and broke 18 previously-passing tests, twice over. On `django-16263` it patched 1 of 4 and scored 102 / 103. graft found the rest — and on `django-16263` did it in half the tokens and half the time.
355
+ The graft map resolved **33 of 50 instances** against cold Claude Code's 27, with 25% fewer tool calls, 23% fewer tokens and 32% less wall-clock time. Every correctness win has the same shape: the baseline patches one file and misses its siblings. On `django-11532` it patched 1 of the 5 files the fix requires and broke 18 previously passing tests, twice over. On `django-16263` it patched 1 of 4 and scored 102 / 103. The graft map found the rest, and on `django-16263` did it in half the tokens and half the time.
172
356
 
173
- Two harnesses, two claims: the controlled sweep says graft is cheaper and faster, SWE-bench says it's also more correct.
357
+ Two harnesses, two claims: the controlled sweep says the graft map is cheaper and faster, SWE-bench says it's also more correct.
174
358
 
175
359
  <sub>Correctness over all instances; tokens, cost and calls over the instances both arms resolved, for a like-for-like comparison. Official SWE-bench Verified images and official `swebench` 4.1.0 grader, native x86_64.</sub>
176
360
 
177
361
  ---
178
362
 
363
+ ## Tested on popular repos
364
+
365
+ The [benchmarks](#benchmark) measure the mechanism. The real test is whether the graft map helps an agent **ship real changes** on code people actually run, not just answer questions. So we benchmark it on popular open-source repos: **15 tasks each**, 10 real developer questions plus **5 actual implementation tasks** (real merged pull requests, each re-implemented from its base commit and scored against the files the maintainers actually changed). Same agent (Claude Opus), same file tools; the only difference is whether the graft map is wired in.
366
+
367
+ On PocketBase the graft map ran **21% cheaper and 14% faster** across the 15 tasks, and **2.6× cheaper** on the hardest cross-file question, with no loss of correctness: it reproduced the real merged PRs by touching the same files the maintainers did.
368
+
369
+ ### PocketBase (Go, ~350 files)
370
+
371
+ | Aggregate over 15 tasks | Standard Claude Code | With the graft map |
372
+ |---|---|---|
373
+ | Cost | $13.91 | **$11.02 (−21%)** |
374
+ | Wall-clock | 2,044s | **1,762s (−14%)** |
375
+ | PRs reproduced | 5 / 5 | **5 / 5 (same files as the maintainers)** |
376
+
377
+ Cheaper and faster with no loss of correctness: the graft map reproduced all five merged PRs, touching the same files the maintainers did. The gap is widest on cross-file understanding: "how does auth work across OAuth2 providers" dropped from $2.19 to $0.84.
378
+
379
+ <details>
380
+ <summary><b>The 10 questions we asked</b></summary>
381
+
382
+ 1. **Orientation**: Give me a map of PocketBase's architecture: the main subsystems and how an HTTP request flows through to the database.
383
+ 2. **Entry-point trace**: Trace end-to-end what happens when a client creates a record via the REST API, from route handler to database write.
384
+ 3. **Feature location**: I want to add a brand-new collection field type. Where do I hook it in, and which pieces must change?
385
+ 4. **Bug localization**: Realtime subscriptions silently stop delivering events after a while. Where would you start looking, and why?
386
+ 5. **Blast radius**: If I change the signature of the record-validation logic, what depends on it and what could break?
387
+ 6. **Cross-file synthesis**: How does auth work across OAuth2 providers: where are tokens issued, validated, stored, and refreshed?
388
+ 7. **Extensibility**: How do I use PocketBase as a Go framework to register a custom route plus an on-record-create hook?
389
+ 8. **Security discovery**: Where is user input validated, and where are collection API access rules enforced before a query runs?
390
+ 9. **Public API**: As an external app, how do I authenticate and then list and filter records over the REST API?
391
+ 10. **Test verification**: Where are the tests for the record CRUD API, and what do they assert about access rules?
392
+
393
+ </details>
394
+
395
+ <details>
396
+ <summary><b>The 5 merged PRs we re-implemented</b></summary>
397
+
398
+ Each PR was reset to its base commit; the agent's diff was scored against the files the merged PR changed.
399
+
400
+ | PR | Type | What it does | Files the maintainers touched |
401
+ |---|---|---|---|
402
+ | [#6744](https://github.com/pocketbase/pocketbase/pull/6744) | feat | Generate & serve WebP thumbnails | `apis/file.go`, `tools/filesystem/filesystem.go` |
403
+ | [#6947](https://github.com/pocketbase/pocketbase/pull/6947) | fix | Uniform char distribution in regex random strings | `tools/security/random_by_regex.go` |
404
+ | [#6690](https://github.com/pocketbase/pocketbase/pull/6690) | refactor | Patreon OAuth2 to use `x/oauth2/endpoints` | `tools/auth/patreon.go` |
405
+ | [#2726](https://github.com/pocketbase/pocketbase/pull/2726) | perf | Drop a redundant admin-count query on a hot middleware path | `apis/middlewares.go` |
406
+ | [#3192](https://github.com/pocketbase/pocketbase/pull/3192) | fix | Restore prior API rules on automigration rollback | `plugins/migratecmd/templates.go` |
407
+
408
+ </details>
409
+
410
+ <details>
411
+ <summary><b>Method</b></summary>
412
+
413
+ Two clones of PocketBase at the same commit: one wired with `graft init`, one untouched and verified to have no graft map in it. Each task run headless (`claude -p`, Claude Opus) with an empty MCP config. Understanding questions were graded by whether the answer pointed to the right files and functions; PR tasks were scored on whether the agent's diff touched the same files as the merged PR. Every transcript was audited to confirm the graft map was actually used in one arm and absent from the other.
414
+
415
+ </details>
416
+
417
+ ---
418
+
419
+ ## FAQ
420
+
421
+ **Is this graft?**
422
+ Yes. Trail-code is graft's new name, and graft lives on inside it as the graft map. The command is `trail` and the package is `@trailhq/trail-code`; `graft` and `@nanonets/graft` run the same code, print what they always printed, and keep working.
423
+
424
+ **How is this different from CLAUDE.md or AGENTS.md?**
425
+ You write those by hand, keep them current by hand, and your agent can skip them. Trail-code saves learnings from your conversations, brings in only the ones about the code you're working on, checks your changes against them before a PR, and adds a map of your code. It works next to your instruction files: `trail init` never touches your `CLAUDE.md`.
426
+
427
+ **Will it fill up my context window?**
428
+ No. Each prompt gets only pointers to the matching code, and the learnings that match it, and a teammate's unmerged learnings show only their first lines. In our benchmark, uncached input tokens went down 42%.
429
+
430
+ **Do I need an API key?**
431
+ No. The graft map, the hooks, learnings and `trail check` all work without one. A key only adds the written summaries from `trail build --deep`.
432
+
433
+ **Do I need to sign in?**
434
+ No. Everything above works on your machine, and learnings reach your team through git. A Trail workspace, coming soon, is only for the team page across repos.
435
+
436
+ **Which agents does it work with?**
437
+ Claude Code gets the deepest setup: hooks, statusline, learnings with every prompt, and the ask to save one after real digging. Trail-code also wires Cursor, Codex and other `AGENTS.md` readers, Gemini CLI, GitHub Copilot, Windsurf, Kiro, Antigravity, Grok, Hermes and AdaL, and serves any agent that speaks MCP.
438
+
439
+ **What if it learns something wrong?**
440
+ A repo learning is a file in your pull request, so it gets reviewed like the code it is about. Delete or edit the file to drop it. Personal learnings are files in `~/.trail`, just as easy to change.
441
+
442
+ **Does it work in monorepos?**
443
+ Yes: one repo with many packages, submodules, and folders of separate repos. See [Monorepos](#monorepos-submodules--multi-repo-folders).
444
+
445
+ **What does it cost?**
446
+ The CLI is free and open source under the MIT license.
447
+
448
+ ---
449
+
179
450
  ## How the graph gets built
180
451
 
181
- Graft builds the graph in two passes, both powered by a language model:
452
+ The graft map is built in layers. Tier 1 is tree-sitter: every symbol and call edge, no model, no key. `trail build --deep` adds two language-model passes on top:
182
453
 
183
454
  1. **Read each file.** Every source file is summarized once into a short description of what it does.
184
- 2. **Group into nodes.** Those summaries are grouped into a curated set of nodes (subsystems, key files, and concepts) with typed links between them. Graft chooses the right level of detail for you instead of making one node per file, so a big repo becomes a few dozen readable nodes.
455
+ 2. **Group into nodes.** Those summaries are grouped into a curated set of nodes (subsystems, key files, and concepts) with typed links between them. The graft map chooses the right level of detail for you instead of making one node per file, so a big repo becomes a few dozen readable nodes.
185
456
 
186
457
  ```mermaid
187
458
  flowchart LR
188
- S[Source files] --> T["Tier 1 — tree-sitter<br/>no model, no key"]
189
- S --> P1["Pass 1 — LLM summarizes<br/>each file (--deep)"]
459
+ S[Source files] --> T["Tier 1: tree-sitter<br/>no model, no key"]
460
+ S --> P1["Pass 1: LLM summarizes<br/>each file (--deep)"]
190
461
  T --> W["graft/.graph/wiring.json<br/>per-symbol code graph"]
191
- P1 --> P2["Pass 2 — group into nodes<br/>+ typed links"]
462
+ P1 --> P2["Pass 2: group into nodes<br/>+ typed links"]
192
463
  P2 --> N["graft/*.md<br/>markdown node graph"]
193
464
  ```
194
465
 
195
- Every pass is cached by content hash — the LLM ones and the tree-sitter parse alike. Re-running only touches the files that changed, so the second build is fast and cheap (on this repo, 124 files: 0.74s cold, 0.18s after one edited file, 0.18s with nothing changed). `graft build --no-reuse` forces a cold re-parse.
466
+ Every pass is cached by content hash, the LLM ones and the tree-sitter parse alike. Re-running only touches the files that changed, so the second build is fast and cheap (on this repo, 312 files: about 5s cold, about 0.6s after one edited file or with nothing changed). `trail build --no-reuse` forces a cold re-parse.
196
467
 
197
- That cheapness is what lets **every query refresh the graph before it answers**. A retrieval call stats the tree against the last build's fingerprint (~3ms), and rebuilds only if something moved — so `ask`/`grep`/`callers`/`skeleton`/`map` describe the code as it is right now, including edits that are unsaved to git: uncommitted, unstaged, or staged all look the same to graft. Git determines the visible file set; freshness compares the working-tree bytes rather than commit or index state. The refresh is structural and `$0`; it never calls the LLM. Turn it off per-command with `--no-refresh`, or everywhere with `GRAFT_NO_REFRESH=1`.
468
+ That cheapness is what lets **every query refresh the graph before it answers**. A retrieval call stats the tree against the last build's fingerprint (about 50ms on this repo), and rebuilds only if something moved, so `ask`/`grep`/`callers`/`skeleton`/`map` describe the code as it is right now, including edits that are unsaved to git: uncommitted, unstaged, or staged all look the same to the graft map. Git determines the visible file set; freshness compares the working-tree bytes rather than commit or index state. The refresh is structural and `$0`; it never calls the LLM. Turn it off per-command with `--no-refresh`, or everywhere with `GRAFT_NO_REFRESH=1`.
198
469
 
199
- Alongside the markdown graph, `graft build` builds `graft/.graph/wiring.json` — a per-symbol code graph — plus a per-file wiring card mirroring your source tree. Tier 1 is pure tree-sitter (every function, class, and call edge; deterministic, no model, no network), which is why plain `graft build` needs no key. The `--deep` pass adds a one-line summary and a crux excerpt per symbol, cached by body hash.
470
+ Alongside the markdown graph, `trail build` builds `graft/.graph/wiring.json` (a per-symbol code graph) plus a per-file wiring card mirroring your source tree. Tier 1 is pure tree-sitter (every function, class, and call edge; deterministic, no model, no network), which is why plain `trail build` needs no key. The `--deep` pass adds a one-line summary and a crux excerpt per symbol, cached by body hash.
200
471
 
201
472
  ---
202
473
 
203
474
  ## Supported languages
204
475
 
205
- Graft parses with tree-sitter at two levels of fidelity, plus an optional
206
- compiler-grade layer — all `$0` and deterministic (no model, no key):
476
+ The graft map parses with tree-sitter at two levels of fidelity, plus an optional
477
+ compiler-grade layer, all `$0` and deterministic (no model, no key):
207
478
 
208
- - **Full-fidelity** — hand-written extractors with scope-aware, cross-file call
479
+ - **Full-fidelity**: hand-written extractors with scope-aware, cross-file call
209
480
  and import resolution:
210
481
  **TypeScript / JavaScript** (incl. JSX & TSX), **Python**, **Go**, **Java**,
211
482
  **Kotlin**, **PHP**, **Swift** (classes, structs, enums, actors, protocols;
212
- extension members attach to the extended type), **R** (`.R`/`.r` — plain
483
+ extension members attach to the extended type), **R** (`.R`/`.r`: plain
213
484
  functions, S3/S4/R6 classes and methods, roxygen `@export`,
214
- `library()`/`source()` imports).
485
+ `library()`/`source()` imports), and **Vue** single-file components (their
486
+ `<script>` blocks go through the TypeScript extractor).
215
487
 
216
- - **Broad** — symbols (functions, classes, methods, types, …) plus name-resolved
488
+ - **Broad**: symbols (functions, classes, methods, types, …) plus name-resolved
217
489
  call edges via a generic tree-sitter extractor, one grammar per language:
218
490
  **Rust, C, C++, C#, Ruby, Scala, Elixir, Solidity,
219
- OCaml, Zig, Dart, Clojure, Nix, Lua**.
491
+ Dart, Clojure, Nix, Lua**, and **OCaml, Zig** (symbols only for now, no call edges).
220
492
 
221
- - **Compiler-grade edges (opt-in)** — `graft build --lsp` adds precise
493
+ - **Compiler-grade edges (opt-in)**: `trail build --lsp` adds precise
222
494
  `lsp_resolved` call edges (member calls the static pass can't type) when a
223
- language server is on your `PATH`: **rust-analyzer** (Rust), **clangd** (C/C++),
495
+ language server is on your `PATH`. It uses the first one installed, in this
496
+ order, one server per build: **rust-analyzer** (Rust), **clangd** (C/C++),
224
497
  **gopls** (Go), **pyright** (Python), **typescript-language-server** (TS/JS).
225
- It's best-effort — with no server installed the graph is unchanged.
498
+ It's best-effort: with no server installed the graph is unchanged.
226
499
 
227
- Twenty-three languages in total. A file whose language isn't listed is skipped, not
228
- indexed. Adding a broad-tier language is a small contribution — see
500
+ Twenty-three languages, plus Vue single-file components. A file whose language isn't listed is skipped, not
501
+ indexed. Adding a broad-tier language is a small contribution; see
229
502
  [CREDITS.md](CREDITS.md) for the folks who added the current set.
230
503
 
231
504
  ---
232
505
 
233
506
  ## What's in a node
234
507
 
235
- A node is a single markdown file. Most code maps stop at an address: this thing lives in that file, on that line. That tells an agent where to look, not what it will find, so it still has to open the source and read. A Graft node holds the meaning inline, so the agent learns what it needs up front and opens the file only when it wants more.
508
+ A node is a single markdown file. Most code maps stop at an address: this thing lives in that file, on that line. That tells an agent where to look, not what it will find, so it still has to open the source and read. A graft map node holds the meaning inline, so the agent learns what it needs up front and opens the file only when it wants more.
236
509
 
237
510
  Each node holds:
238
511
 
@@ -240,194 +513,210 @@ Each node holds:
240
513
  |---|---|
241
514
  | **Summary** | A plain-English explanation of what the code does, written by the model and cached. It is there whether or not the code was ever documented, and it is regenerated when the source changes. |
242
515
  | **Crux** | The handful of lines that actually carry the logic: the guard, the skip condition, the state change. Lifted straight from the source and stored inline, so the agent sees *how* it works, not just what. |
243
- | **Sources** | The exact files the node is built from, each tracked by a content hash, so Graft can tell precisely when a node has gone stale. |
516
+ | **Sources** | The exact files the node is built from, each tracked by a content hash, so the graft map can tell precisely when a node has gone stale. |
244
517
  | **Links** | Typed connections to other nodes (`depends_on`, `part_of`, `uses`, `implements`, `produces`), written as `[[wikilinks]]` your agent can follow. |
245
- | **Notes** | Anything you write below the generated block. It is preserved across regenerations, so your own context is never overwritten. |
518
+ | **Your text** | Anything you write below the generated block. It is preserved across regenerations, so your own context is never overwritten. |
246
519
 
247
- That is three depths in one file: the summary says *what* the code does, the crux shows *how*, and the sources point to the rest if the agent needs it. A plain index makes it read a whole file to learn one thing. A Graft node hands it the answer inline, and the follow-up read often never happens.
520
+ That is three depths in one file: the summary says *what* the code does, the crux shows *how*, and the sources point to the rest if the agent needs it. A plain index makes it read a whole file to learn one thing. A graft map node hands it the answer inline, and the follow-up read often never happens.
248
521
 
249
522
  The crux is stored as the code itself, not as a line range, on purpose. Line numbers drift whenever unrelated code above them shifts, but the lines that matter do not. Keeping the text, not the numbers, means the crux stays correct even as the file around it moves.
250
523
 
251
- _Summary, sources, links, and notes ship today in markdown nodes. The crux ships per-symbol in the code graph (`graft build --deep`); inlining it into markdown nodes is next._
524
+ _Summary, sources, links, and your text ship today in markdown nodes. The crux ships per-symbol in the code graph (`trail build --deep`); inlining it into markdown nodes is next._
252
525
 
253
526
  ---
254
527
 
255
528
  ## What runs where
256
529
 
257
- - **On your machine, no key, no network:** the structural code graph. `graft build` (wiring graph + per-file cards), `graft check`, and `graft ask` are deterministic tree-sitter — they never call a model.
258
- - **Through your provider key:** the LLM-written parts — `graft build --deep` adds the concept nodes (file summaries + node synthesis) and the per-symbol summaries and cruxes. graft is vendor-neutral: set `GRAFT_PROVIDER` (`openai` for any OpenAI-compatible endpoint, `anthropic` for the native API, or `litellm` / `orcarouter` for a gateway that speaks the OpenAI-compatible format), your `GRAFT_API_KEY`, `GRAFT_MODEL`, and — for the `openai` wire format — `GRAFT_BASE_URL` to point at OpenRouter, Fireworks, Groq, a LiteLLM proxy, a local server, or OpenAI itself. Or pass `--provider/--model/--api-key/--base-url` on the command line. (`OPENROUTER_API_KEY` still works as a deprecated fallback, and `ORCAROUTER_API_KEY` as a second one.)
259
- - **Anonymous usage stats** — the only network calls are the LLM requests you configured, a daily npm version check, and one batched usage ping. The ping carries buckets and fixed labels only: never your code, file paths, repo name, symbols, queries, or error messages. [`TELEMETRY.md`](TELEMETRY.md) is the complete list and `graft telemetry debug` prints exactly what your machine would send. Turn it off with `graft telemetry disable`, `DO_NOT_TRACK=1`, or by unchecking the box in `graft init`; it is off in CI and in any build from source.
530
+ - **On your machine, no key, no network:** the structural code graph. `trail build` (wiring graph + per-file cards), `trail build --check`, `trail ask`, learnings and `trail check` are deterministic. They never call a model.
531
+ - **Through your provider key:** the LLM-written parts. `trail build --deep` adds the concept nodes (file summaries + node synthesis) and the per-symbol summaries and cruxes. The graft map is vendor-neutral: set `GRAFT_PROVIDER` (`openai` for any OpenAI-compatible endpoint, `anthropic` for the native API, or `litellm` / `orcarouter` for a gateway that speaks the OpenAI-compatible format), your `GRAFT_API_KEY`, `GRAFT_MODEL`, and, for the `openai` wire format, `GRAFT_BASE_URL` to point at OpenRouter, Fireworks, Groq, a LiteLLM proxy, a local server, or OpenAI itself. Or pass `--provider/--model/--api-key/--base-url` on the command line. (`OPENROUTER_API_KEY` still works as a deprecated fallback, and `ORCAROUTER_API_KEY` as a second one.)
532
+ - **Through Trail, only if you connect a workspace:** the learnings in the repos you picked, and the searches and checks that used them. See [What stays on your machine](#what-stays-on-your-machine).
533
+ - **Anonymous usage stats:** a daily npm version check and one batched usage ping. The ping carries buckets and fixed labels only: never your code, file paths, repo name, symbols, queries, learnings or error messages. [`TELEMETRY.md`](TELEMETRY.md) is the complete list and `trail telemetry debug` prints exactly what your machine would send. Turn it off with `trail telemetry disable`, `DO_NOT_TRACK=1`, or by unchecking the box in `trail init`; it is off in CI and in any build from source.
260
534
 
261
- See [`.env.example`](.env.example) for the full list of settings (model, base URL, graph directory).
535
+ Settings keep their `GRAFT_` names. See [`.env.example`](.env.example) for the full list (model, base URL, graph directory).
262
536
 
263
537
  ---
264
538
 
265
539
  ## Agent integration
266
540
 
267
- One command wires Graft into the coding agents you use:
541
+ One command wires Trail-code into the coding agents you use:
268
542
 
269
543
  ```bash
270
- npx @nanonets/graft init
544
+ npm install -g @trailhq/trail-code && trail init
271
545
  # detects your agents and writes each one's native instruction file;
272
546
  # Claude Code additionally gets the live statusline + hooks below
273
547
  ```
274
548
 
275
- On a terminal, `init` shows you every agent it knows about — flagging the ones it detected (via their config directories) and listing the exact files each would write — and wires only the ones you select. Claude Code is pre-selected; nothing else is. Selected agents get a marker-fenced Graft section in their shared instruction file — `AGENTS.md` (Codex, OpenCode and other CLIs that read it), `GEMINI.md`, `.github/copilot-instructions.md` — or a wholly-owned rule/skill file for the agents that use one: `.claude/skills/graft/SKILL.md`, `.cursor/rules/graft.mdc`, `.kiro/steering/graft.md`, `.windsurf/rules/graft.md`, `.grok/skills/graft/SKILL.md` for Grok (xAI), `.adal/skills/graft/SKILL.md` for [AdaL](https://adal.sylph.ai). Claude Code is in the second group: `init` writes its own skill file and never touches your `CLAUDE.md`. Re-running only updates Graft's own section (or replaces the owned file) and never touches the rest of your content.
549
+ On a terminal, `init` shows you every agent it knows about, flags the ones it detected (via their config directories), lists the exact files each would write, and wires only the ones you select. Claude Code is pre-selected; nothing else is. Selected agents get a marker-fenced Trail-code section in their shared instruction file (`AGENTS.md` for Codex, OpenCode and other CLIs that read it, `GEMINI.md`, `.github/copilot-instructions.md`), or a wholly-owned rule or skill file for the agents that use one, such as `.claude/skills/trail/SKILL.md` and `.cursor/rules/trail.mdc`. Claude Code is in the second group: `init` writes its own skill file and never touches your `CLAUDE.md`. Re-running only updates Trail-code's own section (or replaces the owned file) and never touches the rest of your content.
550
+
551
+ In Claude Code, the committed skill file is also how a teammate without Trail-code installed gets your learnings: it tells their agent where `.trail/learnings/` is, to read it before exploring, and to tell them once how to install the rest.
276
552
 
277
- With no TTY to prompt on — CI, a Dockerfile, a piped shell — `init` writes **nothing** and prints the command to run instead. Pass `--agents <ids>` or `--yes` to make a scripted run explicit.
553
+ With no TTY to prompt on (CI, a Dockerfile, a piped shell), `init` writes **nothing** and prints the command to run instead. Pass `--agents <ids>` or `--yes` to make a scripted run explicit.
278
554
 
279
555
  | Flag | Effect |
280
556
  |---|---|
281
- | `--agents <ids...>` | wire only these, no prompt — ids: `agents`, `cursor`, `gemini`, `grok`, `copilot`, `kiro`, `windsurf`, `adal`, `claude` |
557
+ | `--agents <ids...>` | wire only these, no prompt; ids: `agents`, `adal`, `cursor`, `gemini`, `grok`, `hermes`, `antigravity`, `copilot`, `kiro`, `windsurf`, `claude` |
282
558
  | `--yes`, `-y` | skip the prompt and wire every **detected** agent |
283
- | `--dry-run` | print every file `init` would touch, then exit without writing |
559
+ | `--dry-run` | print the agent wiring `init` would write, then exit without writing |
284
560
  | `--all-agents` | write instruction files for every known agent, detected or not |
285
561
  | `--no-agents` | Claude Code wiring only; skip other agents |
286
562
  | `--list-agents` | print the known agent ids and exit |
287
- | `--no-mcp` | skip MCP server registration |
288
- | `--no-hooks` | skip hook installation |
563
+ | `--no-mcp` | skip MCP registration for agents other than Claude Code |
564
+ | `--no-hooks` | skip hook installation for agents other than Claude Code |
289
565
  | `--no-statusline` | skip writing Claude Code `statusLine` (same as `GRAFT_NO_STATUSLINE=1`) |
290
566
  | `--no-global` | skip writes outside this repo (the `~/.codex/` entries below) |
291
567
 
292
568
  #### Writes outside the repo
293
569
 
294
- Selecting the `agents` host also touches your **user-level** Codex config, when `~/.codex/` exists:
570
+ Some agents also get **user-level** files, so the wiring follows you into worktrees and folders the repo's files don't reach:
295
571
 
296
- | Path | What changes |
297
- |---|---|
298
- | `~/.codex/config.toml` | registers the Graft MCP server (`[mcp_servers.graft]`) |
299
- | `~/.codex/hooks/graft/graft-hooks.cjs` | the post-edit hook shim |
300
- | `~/.codex/hooks.json` | a `PostToolUse` entry matching `Write\|Edit\|MultiEdit` |
572
+ | Agent | Path | What changes |
573
+ |---|---|---|
574
+ | Claude Code | `~/.claude/settings.json` | `SessionStart`, `UserPromptSubmit`, `PostToolUse` and `Stop` hooks |
575
+ | Claude Code | `~/.claude/helpers/graft-hooks.cjs` | the hooks shim they call |
576
+ | Claude Code | `~/.claude.json` | the `trail` MCP server |
577
+ | Codex (`agents`), when `~/.codex/` exists | `~/.codex/config.toml` | the `trail` MCP server |
578
+ | Codex | `~/.codex/hooks.json` | the same four hook events, matching `apply_patch\|Write\|Edit\|MultiEdit` after edits |
579
+ | Codex | `~/.codex/hooks/graft/graft-hooks.cjs` | the hooks shim |
580
+ | Antigravity | `~/.gemini/config/mcp_config.json` | the `trail` MCP server |
581
+ | Antigravity | `~/.gemini/skills/trail/SKILL.md` | its skill file |
301
582
 
302
- Both configs are user-level, so they apply to **every** repo you open with Codex, not just this one. The picker labels these `machine-wide`, `--dry-run` lists them in their own section, and `--no-global` skips them while still wiring `AGENTS.md`.
583
+ These apply to **every** repo you open with that agent, not just this one. The picker labels them `machine-wide`, `--dry-run` lists them in their own section, and `--no-global` skips them all while still wiring the repo's own files.
303
584
 
304
585
  ### MCP server
305
586
 
306
- `graft init` also registers Graft's MCP server with agents that support it, so these six tools appear natively, no shell required. Claude Code gets this too: `graft init` writes the server into the project's `.mcp.json` (restart Claude Code to load it). Skip with `--no-mcp`; run it manually with `graft mcp [dir]`.
587
+ `trail init` also registers the Trail-code MCP server with agents that support it, so these six tools appear natively, no shell required. Claude Code gets this too: `trail init` writes the server into the project's `.mcp.json` (restart Claude Code to load it). Run it by hand with `trail mcp [dir]`.
307
588
 
308
589
  | Tool | Takes | What it's for |
309
590
  |---|---|---|
310
- | `graft_find_code` | a question | Ranked nodes with file:line, source inlined — usually the full answer, no follow-up read needed. |
311
- | `graft_file_api` | a file path | Every signature in that file, no bodies — the API surface for a tenth of the tokens. |
312
- | `graft_trace_calls` | a symbol | Who depends on it, or what it depends on with `direction: out`, N levels deep for blast radius. |
313
- | `graft_find_all` | a regex | Every hit, grouped by enclosing symbol, ranked by how coupled that symbol is. |
314
- | `graft_repo_map` | nothing | A first look at an unfamiliar repo: directory clusters, hubs, hotspots. |
315
- | `graft_check_freshness` | nothing | Whether the local graph has drifted from the code. |
591
+ | `trail_find_code` | a question | Ranked nodes with file:line, source inlined; usually the full answer, no follow-up read needed. |
592
+ | `trail_file_api` | a file path | Every signature in that file, no bodies: the API surface for a tenth of the tokens. |
593
+ | `trail_trace_calls` | a symbol | Who depends on it, or what it depends on with `direction: out`, N levels deep for blast radius. |
594
+ | `trail_find_all` | a regex | Every hit, grouped by enclosing symbol, ranked by how coupled that symbol is. |
595
+ | `trail_repo_map` | nothing | A first look at an unfamiliar repo: directory clusters, hubs, hotspots. |
596
+ | `trail_check_freshness` | nothing | Whether the local graph has drifted from the code. |
316
597
 
317
- Register it by hand if your agent needs it explicit:
598
+ The same server still answers the old `graft_*` tool names. Register it by hand if your agent needs it explicit:
318
599
 
319
600
  ```json
320
- { "mcpServers": { "graft": { "command": "npx", "args": ["-y", "@nanonets/graft", "mcp"] } } }
601
+ { "mcpServers": { "trail": { "command": "npx", "args": ["-y", "@trailhq/trail-code", "mcp"] } } }
321
602
  ```
322
603
 
323
- 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`).
604
+ Where a CLI agent supports user-level `hooks.json`, as Codex does, `init` also installs Trail-code's hooks there: session start, context with each prompt, blast radius and a `$0` graph re-sync after edits, and the end-of-turn sync (skip with `--no-hooks`).
324
605
 
325
606
  ### Claude Code (deep integration)
326
607
 
327
- `graft init` always wires up Claude Code, and Claude Code gets more than the skill file above. From then on, any Claude Code session opened in the repo gets:
608
+ When Claude Code is selected (it is by default), it gets more than the skill file above. From then on, any Claude Code session opened in the repo gets:
328
609
 
329
- - **a live statusline** — graph size, % enriched, and a `⚠ N stale` warning when the code has moved ahead of the graph
330
- - **auto-sync** — every graft query brings the graph up to date first, so an answer always describes the code as it is right now, uncommitted edits included. A query refreshes only what it reads; the markdown under `graft/` is refreshed by the background rebuild at the end of a turn that touched code. Both are structural and `$0` — auto-sync never calls the LLM on its own
331
- - **context on tap** — each prompt pulls the matching nodes into the session; editing a file surfaces what depends on it ("blast radius"); new sessions start with the repo map
332
-
333
- <p align="center">
334
- <img src="assets/graft-hooks-demo.gif" alt="How Claude Code hooks wire graft in: install, graft init, then the hooks loop (session start, user prompt, post tool use, stop) keeps the graph built, read, and committed automatically" width="820"/>
335
- <br/><sub>install → init → hooks keep the graph fresh every session</sub>
336
- </p>
610
+ - **a live statusline**: the graft map's size, how many learnings the repo has, and a `⚠ N stale` warning when the code has moved ahead of the map
611
+ - **auto-sync**: every query brings the graph up to date first, so an answer always describes the code as it is right now, uncommitted edits included. A query refreshes only what it reads; the markdown under `graft/` is refreshed by the background rebuild at the end of a turn that touched code. Both are structural and `$0`; auto-sync never calls the LLM on its own
612
+ - **context on tap**: each prompt pulls in the matching nodes and the learnings left on that code; editing a file surfaces what depends on it ("blast radius"); new sessions start with the repo map and how many learnings there are
613
+ - **the ask to save a learning**: after a turn of real digging with nothing saved, Claude is asked once a session to save one
614
+ - **overlap with teammates**: at session start, and every few minutes, it reads which files teammates' recent pushed branches change; when one changes the code your prompt is about, Claude says so first
337
615
 
338
616
  <p align="center">
339
- <img src="assets/graft-hook-blast-radius-demo.gif" alt="graft's post-edit hook: editing node-file.ts prints its blast radius (who depends on it) inline, the statusline flips stale → syncing → synced on its own, and the same dependents light up in graft viz" width="820"/>
340
- <br/><sub>edit a file → blast radius appears inline → graph auto-resyncs → confirmed in <code>graft viz</code></sub>
617
+ <img src="assets/graft-hook-blast-radius-demo.gif" alt="The post-edit hook: editing node-file.ts prints its blast radius (who depends on it) inline, the statusline flips stale → syncing → synced on its own, and the same dependents light up in the viewer" width="820"/>
618
+ <br/><sub>edit a file → blast radius appears inline → graph auto-resyncs → confirmed in the viewer</sub>
341
619
  </p>
342
620
 
343
- `graft init` is idempotent and never clobbers your existing `.claude/settings.json` — it merges its blocks and leaves the rest alone. A `statusLine` that is not Graft's (anything whose command does not name `graft-statusline.cjs`) is left untouched; re-running `init` will refresh Graft's own helper command if it is already installed. Pass `--no-statusline` (or `GRAFT_NO_STATUSLINE=1`) to skip installing one at all — a project-level `statusLine` would otherwise hide a custom one in `~/.claude/settings.json`. Want the LLM summaries too? Run `graft build --deep` (with a key) whenever you like; auto-sync will never do it for you.
621
+ `trail init` is idempotent and never clobbers your existing `.claude/settings.json`: it merges its blocks and leaves the rest alone. A `statusLine` that is not Trail-code's is left untouched; re-running `init` refreshes Trail-code's own helper command if it is already installed. Pass `--no-statusline` (or `GRAFT_NO_STATUSLINE=1`) to skip installing one at all, since a project-level `statusLine` would otherwise hide a custom one in `~/.claude/settings.json`. Want the LLM summaries too? Run `trail build --deep` (with a key) whenever you like; auto-sync will never do it for you.
344
622
 
345
623
  ---
346
624
 
347
625
  ## CLI
348
626
 
627
+ `trail --help` lists the commands in four groups. Every `graft` command still works too.
628
+
349
629
  ```bash
350
- graft build [dir] # build graft/ from the code at [dir]: wiring graph + per-file cards (no LLM, no key)
351
- graft build --deep # add the LLM layer: concept nodes + per-symbol summary/crux (cached)
352
- graft build --extensions .ts .py # only include these code extensions
353
- graft build --no-reuse # re-parse every file instead of replaying unchanged ones from cache
354
- graft build --follow-submodules # include initialized submodules; persist the choice for builds + MCP refresh
355
- graft build --no-follow-submodules # exclude submodules again and persist that choice (the default)
356
- graft build --follow-nested-repos # include nested git clones the index doesn't track; persist the choice
357
- graft build --no-follow-nested-repos # exclude nested clones again and persist that choice (the default)
358
-
359
- graft ask "<task>" [dir] # query the graph — ranked nodes + exact file:line (no LLM, no key)
360
- graft ask "<task>" --json # machine-readable result
361
- graft ask "<task>" --in <scope> # narrow to one sub-project of a monorepo/multi-repo folder (see below)
362
-
363
- graft skeleton <file> [dir] # every signature in one file, no bodies — the API surface for ~1/10th the tokens (no LLM, no key)
364
-
365
- graft callers <symbol> [dir] # who calls/references/imports/implements/extends a symbol (no LLM, no key)
366
- graft callers <symbol> --direction out # the reverse: what the symbol itself calls/references (was `graft callees`)
367
- graft callers <symbol> -d N # walk transitively out to depth N — full blast radius (was `graft impact`)
368
-
369
- graft grep "<regex>" [dir] # exhaustive regex search over indexed files, grouped by enclosing symbol (no LLM, no key)
370
- graft grep "<regex>" --in <path> # narrow to files at or under this path prefix
371
- graft grep "<regex>" -i --fixed # case-insensitive; treat the pattern as a literal string, not a regex
372
-
373
- graft map [dir] # token-budgeted repo orientation — dir clusters, hubs, hotspots (no LLM, no key)
374
- graft map --max-dirs N # raise/lower the number of directories shown
375
-
376
- graft blast [dir] # blast radius of a diff: what depends on the lines this change touched (no LLM, no key)
377
- graft blast --base origin/main # diff against the merge base with HEAD — what a PR job runs
378
- graft blast --format markdown # a PR comment: the areas a change can reach, per-symbol detail collapsed under it
379
- graft blast --base origin/main --name # name those areas with one cached LLM call, instead of a full --deep build
380
- graft blast --export-viz site/ # also write the interactive page for this radius (what a PR comment links to)
381
- graft blast --no-owners # skip "who to tag" — by default git history names the people behind each area
382
- graft blast --depth all --format json # the full transitive closure, machine-readable
383
-
384
- graft check [dir] # fail (exit 1) if graft/ has drifted from the code (never auto-refreshes — it's the drift report)
385
- graft check --json # print the drift report as JSON
630
+ # find code · your agent runs these
631
+ trail ask "<task>" [dir] # the matching code and learnings: ranked nodes + exact file:line (no LLM, no key)
632
+ trail ask "<task>" --json # machine-readable result
633
+ trail ask "<task>" --in <scope> # narrow to one sub-project of a monorepo/multi-repo folder (see below)
634
+
635
+ trail grep "<regex>" [dir] # exhaustive regex search over indexed files, grouped by enclosing symbol (no LLM, no key)
636
+ trail grep "<regex>" --in <path> # narrow to files at or under this path prefix
637
+ trail grep "<regex>" -i --fixed # case-insensitive; treat the pattern as a literal string, not a regex
638
+
639
+ trail skeleton <file> [dir] # every signature in one file, no bodies: the API surface for ~1/10th the tokens (no LLM, no key)
640
+
641
+ trail callers <symbol> [dir] # who calls/references/imports/implements/extends a symbol (no LLM, no key)
642
+ trail callers <symbol> --direction out # the reverse: what the symbol itself calls/references
643
+ trail callers <symbol> -d N # walk transitively out to depth N: full blast radius
644
+
645
+ trail map [dir] # token-budgeted repo orientation: dir clusters, hubs, hotspots (no LLM, no key)
646
+ trail map --max-dirs N # raise/lower the number of directories shown
386
647
 
387
648
  # ask / skeleton / callers / grep / map / blast all refresh the graph first if the working tree moved:
388
649
  # --no-refresh # answer from the graph exactly as it is on disk
389
650
  # GRAFT_NO_REFRESH=1 # same, for every command
390
651
  # GRAFT_REFRESH=hash # hash every file instead of trusting size+mtime
391
652
 
392
- graft viz [dir] # see the graph: serves an interactive viewer on localhost
393
- graft viz --port 5000 --no-open # pick a port; don't auto-open the browser
394
- graft viz --export site/ --title "PR #12" # one self-contained index.html — for CI, GitHub Pages, or a build artifact
395
-
396
- graft init [dir] # pick which agents to wire (prompts on a terminal; writes nothing until you choose)
397
- graft init --dry-run # list every file it would touch, then exit
398
- graft init --agents cursor kiro # wire only these agents, no prompt (ids: agents, cursor, gemini, grok, copilot, kiro, windsurf, adal, claude)
399
- graft init --yes # no prompt; wire every detected agent
400
- graft init --no-global # skip writes outside this repo (~/.codex/ config + hooks)
401
- graft init --no-statusline # skip Claude Code statusLine (same as GRAFT_NO_STATUSLINE=1)
402
- graft init --no-build # wire the files only; don't build the graph
403
- graft init --all-agents # wire every known agent, detected or not
404
- graft init --list-agents # list known agent ids and exit
405
-
406
- graft uninstall [dir] # remove every file and config entry graft wrote here (the inverse of init)
407
- graft uninstall -y # actually remove (without -y it prints what it would remove and exits)
408
- graft uninstall --keep-cache # wiring only; leave graft/ and the .gitignore entry
409
- graft uninstall --no-global # leave out-of-repo files alone (~/.codex, ~/.gemini)
410
-
411
- graft version # print the installed + latest published npm version
412
- graft upgrade # npm install -g the latest published version
653
+ # team memory
654
+ trail note --title "<about>" [dir] # save a decision: what this session decided, tried and ruled out (the text on stdin)
655
+ trail note --personal # about your own setup, not the code: keep it in ~/.trail, out of the repo
656
+ trail check [dir] # check your branch's diff against the repo's learnings, yours and your skills (exit 1 on a conflict)
657
+ trail check --base origin/main # compare against this base instead of origin's default branch
658
+ trail team [dir] # what the team learned this week, who's working on what, and where work overlaps
659
+
660
+ # setup
661
+ trail init [dir] # pick which agents to wire (prompts on a terminal; writes nothing until you choose)
662
+ trail init --dry-run # list the agent wiring it would write, then exit
663
+ trail init --agents cursor kiro # wire only these agents, no prompt (ids: agents, adal, cursor, gemini, grok, hermes, antigravity, copilot, kiro, windsurf, claude)
664
+ trail init --yes # no prompt; wire every detected agent
665
+ trail init --no-global # skip writes outside this repo (~/.claude, ~/.claude.json, ~/.codex, ~/.gemini)
666
+ trail init --no-statusline # skip Claude Code statusLine (same as GRAFT_NO_STATUSLINE=1)
667
+ trail init --no-build # wire the files only; don't build the graph
668
+ trail init --all-agents # wire every known agent, detected or not
669
+ trail init --list-agents # list known agent ids and exit
670
+
671
+ trail build [dir] # build the graft map in graft/: wiring graph + per-file cards (no LLM, no key)
672
+ trail build --deep # add the LLM layer: concept nodes + per-symbol summary/crux (cached)
673
+ trail build --check # build nothing: fail (exit 1) if graft/ has drifted from the code, for CI
674
+ trail build --deep -e .ts .py # with --deep: only summarize these extensions
675
+ trail build --no-reuse # re-parse every file instead of replaying unchanged ones from cache
676
+ trail build --follow-submodules # include initialized submodules; persist the choice for builds + MCP refresh
677
+ trail build --no-follow-submodules # exclude submodules again and persist that choice (the default)
678
+ trail build --follow-nested-repos # include nested git clones the index doesn't track; persist the choice
679
+ trail build --no-follow-nested-repos # exclude nested clones again and persist that choice (the default)
680
+
681
+ trail status [dir] # the graft map, learnings and tokens saved, on one screen
682
+ trail upgrade # npm install -g the latest published version
413
683
  # a new version is announced automatically (checked once a day);
414
684
  # after upgrading, the next session refreshes this repo's wiring itself
685
+ trail uninstall [dir] # remove every file and config entry it wrote here (the inverse of init)
686
+ trail uninstall -y # actually remove (without -y it prints what it would remove and exits)
687
+ trail uninstall --keep-cache # wiring only; leave graft/ and the .gitignore entry
688
+ trail uninstall --no-global # leave out-of-repo files alone (~/.claude, ~/.claude.json, ~/.codex, ~/.gemini)
689
+ trail telemetry [status|enable|disable|debug] # anonymous usage stats; debug prints exactly what would be sent
690
+
691
+ # CI
692
+ trail blast [dir] # blast radius of a diff: what depends on the lines this change touched (no LLM, no key)
693
+ trail blast --base origin/main # diff against the merge base with HEAD (what a PR job runs)
694
+ trail blast --format markdown # a PR comment: the areas a change can reach, per-symbol detail collapsed under it
695
+ trail blast --base origin/main --name # name those areas with one cached LLM call, instead of a full --deep build
696
+ trail blast --export-viz site/ # also write the interactive page for this radius (what a PR comment links to)
697
+ trail blast --no-owners # skip "who to tag" (by default, git history names the people behind each area)
698
+ trail blast --depth all --format json # the full transitive closure, machine-readable
699
+
700
+ # not listed in --help, still there
701
+ trail viz [dir] # see the graph: serves an interactive viewer on localhost
702
+ trail viz --export site/ --title "PR #12" # one self-contained index.html for CI, GitHub Pages, or a build artifact
703
+ trail mcp [dir] # run the MCP server by hand
415
704
 
416
705
  # global
417
- graft --dir <path> # use a context dir other than <repo>/graft
418
- graft --version, -v # print the installed version and exit
706
+ trail --dir <path> # use a context dir other than <repo>/graft
707
+ trail --version, -v # print the installed version and exit
419
708
  ```
420
709
 
421
- Method calls resolve through the receiver's type — constructor assignments
710
+ Method calls resolve through the receiver's type, using constructor assignments
422
711
  (`self.router = APIRouter()`) and type annotations, not just the call-site
423
- name — so `callers`/`grep --in` return calls bound to the right
712
+ name, so `callers`/`grep --in` return calls bound to the right
424
713
  type on method-heavy code, not every method anywhere with that name.
425
714
 
426
- ## Search & orient (`graft grep` / `graft map`)
715
+ ## Search & orient (`trail grep` / `trail map`)
427
716
 
428
- `graft grep "<regex>"` is exhaustive over every indexed file and groups hits
429
- by enclosing symbol, ranked by the same in-edge coupling `graft map` uses —
430
- built for "every occurrence of this pattern" tasks where `graft ask`'s
717
+ `trail grep "<regex>"` is exhaustive over every indexed file and groups hits
718
+ by enclosing symbol, ranked by the same in-edge coupling `trail map` uses.
719
+ It's built for "every occurrence of this pattern" tasks where `trail ask`'s
431
720
  ranked top-N isn't enough:
432
721
 
433
722
  ```
@@ -440,73 +729,73 @@ rarelyCalled · function · src/a.ts:L4-L6 · 0 in-edges
440
729
  L5: console.log("NEEDLE hit in rarelyCalled");
441
730
  ```
442
731
 
443
- `graft map` is a token-budgeted first look at a repo — directory clusters
444
- with file/symbol counts, each dir's local hubs, and the global hotspots —
732
+ `trail map` is a token-budgeted first look at a repo: directory clusters
733
+ with file/symbol counts, each dir's local hubs, and the global hotspots,
445
734
  all ranked by in-degree, no LLM, no key:
446
735
 
447
736
  ```
448
- repo map — 113 files · 687 symbols · 2186 edges · typescript
737
+ repo map — 313 files · 2349 symbols · 8148 edges · javascript, typescript
449
738
 
450
- src/ 63 files · 527 symbols hubs: contextDirFor (node-file.ts, 21←), wiringPath (write.ts, 14←), buildGraph (build.ts, 11←)
451
- test/ 43 files · 102 symbols hubs: edge (graph-traverse.test.ts, 4←), graphOf (graph-traverse.test.ts, 4←), fileNode (graph-map.test.ts, 3←)
452
- viewer/ 5 files · 58 symbols hubs: $ (main.ts, 9←), activeGraph (main.ts, 5←), cvar (data.ts, 5←)
453
- scripts/ 2 files · 0 symbols
739
+ src/ 157 files · 1804 symbols hubs: wiringPath (write.ts, 48←), cmd (brand.ts, 45←), buildGraph (build.ts, 39←)
740
+ test/ 144 files · 467 symbols hubs: tmpRepo (helpers.ts, 46←), fetch (app-identity.test.ts, 7←), fakeProviders (helpers.ts, 5←)
741
+ viewer/ 5 files · 71 symbols hubs: $ (main.ts, 9←), cvar (data.ts, 6←), activeGraph (main.ts, 5←)
742
+ scripts/ 7 files · 7 symbols hubs: bump (graph-quality.mjs, 1←), defaultTranscriptDir (tally-audit.mjs, 1←), flush (tally-audit.mjs, 1←)
454
743
 
455
- hotspots: contextDirFor · function · src/context/node-file.ts:L100-L103 · 21← wiringPath · function · src/graph/write.ts:L20-L22 · 14← buildGraph · function · src/graph/build.ts:L104-L218 · 11← ...
744
+ hotspots: wiringPath · function · src/graph/write.ts:L20-L22 · 48← tmpRepo · function · test/helpers.ts:L30-L32 · 46← cmd · function · src/brand.ts:L63-L70 · 45← ...
456
745
  ```
457
746
 
458
747
  ## Monorepos, submodules & multi-repo folders
459
748
 
460
- Graft supports these layouts:
749
+ The graft map supports these layouts:
461
750
 
462
751
  - **A monorepo with one `.git`** (a `pnpm-workspace.yaml`/`package.json`
463
- `workspaces`, or per-package `go.mod`/`pyproject.toml`/`Cargo.toml`) —
464
- `graft build` discovers each sub-project as a ranking scope. `ask`/`map`
752
+ `workspaces`, or per-package `go.mod`/`pyproject.toml`/`Cargo.toml`):
753
+ `trail build` discovers each sub-project as a ranking scope. `ask`/`map`
465
754
  rank every scope on its own terms and fuse the results, so the biggest
466
755
  sub-project can't drown a small one; hits carry `[scope/]` labels, and
467
- `graft map` groups its directory clusters by scope first.
468
- - **A Git superproject with initialized submodules** — submodules stay excluded
469
- by default. Run `graft build --follow-submodules` to fold initialized gitlinks
756
+ `trail map` groups its directory clusters by scope first.
757
+ - **A Git superproject with initialized submodules**: submodules stay excluded
758
+ by default. Run `trail build --follow-submodules` to fold initialized gitlinks
470
759
  into one graph, prefixing child paths (for example,
471
760
  `deps/parser/src/index.ts`) while honoring each submodule's own Git ignore
472
761
  rules. Visible untracked files are included too; uninitialized submodules
473
762
  remain absent until `git submodule update --init` checks them out. The choice
474
763
  is saved in `.graft/config.json`, so later no-flag builds and MCP automatic
475
- refreshes behave the same way. Run `graft build --no-follow-submodules` to
764
+ refreshes behave the same way. Run `trail build --no-follow-submodules` to
476
765
  restore and persist the default boundary.
477
- - **A git repo with other repos cloned inside it** (no gitlink, no index entry) — the shape multi-repo manifest tools like `west`, `repo`, `gclient` and `tsrc` check dependencies out into, and the shape you get by cloning an upstream into the tree to patch it locally. `--follow-submodules` cannot reach these: they have no `160000` index entry to follow. Run `graft build --follow-nested-repos` to fold them into one graph, prefixing child paths (for example, `external/parser/src/index.ts`) while honoring each clone's own Git ignore rules. A clone at a git-ignored path stays absent, since Git never reports it. The choice is saved in `.graft/config.json` and is independent of `--follow-submodules` — neither flag implies the other. Run `graft build --no-follow-nested-repos` to restore and persist the default boundary. Prefer this over the multi-repo split below when the nested repos import from each other and you want those edges in one graph; prefer the split when you want each repo scored and refreshed on its own.
478
- - **A folder of separate git repos** (no `.git` at the top) — `graft build`
766
+ - **A git repo with other repos cloned inside it** (no gitlink, no index entry): the shape multi-repo manifest tools like `west`, `repo`, `gclient` and `tsrc` check dependencies out into, and the shape you get by cloning an upstream into the tree to patch it locally. `--follow-submodules` cannot reach these: they have no `160000` index entry to follow. Run `trail build --follow-nested-repos` to fold them into one graph, prefixing child paths (for example, `external/parser/src/index.ts`) while honoring each clone's own Git ignore rules. A clone at a git-ignored path stays absent, since Git never reports it. The choice is saved in `.graft/config.json` and is independent of `--follow-submodules`; neither flag implies the other. Run `trail build --no-follow-nested-repos` to restore and persist the default boundary. Prefer this over the multi-repo split below when the nested repos import from each other and you want those edges in one graph; prefer the split when you want each repo scored and refreshed on its own.
767
+ - **A folder of separate git repos** (no `.git` at the top): `trail build`
479
768
  auto-splits: each child gets its own (git-ignored) `graft/`, and the parent
480
769
  gets a `graft/workspace.json` index. Queries from the parent federate across
481
- every child, always labeled `<child>/`. Run `graft build` inside a child to
770
+ every child, always labeled `<child>/`. Run `trail build` inside a child to
482
771
  work on just that repo.
483
772
 
484
- In every layout, narrow to one sub-project with `graft ask "<task>" --in <scope>/`
773
+ In every layout, narrow to one sub-project with `trail ask "<task>" --in <scope>/`
485
774
  once you know where you're working.
486
775
 
487
- `graft init` at the parent of a multi-repo folder wires **every child repo too**,
488
- not just the parent — an agent session opens at a repo root and reads its
776
+ `trail init` at the parent of a multi-repo folder wires **every child repo too**,
777
+ not just the parent. An agent session opens at a repo root and reads its
489
778
  instruction files from there, so each child needs its own. A session started in
490
779
  the parent gets the federated view; one started in a child sees that repo alone.
491
780
 
492
781
  Commands also find the graph from a subdirectory: with no `[dir]` argument they
493
- walk up to the nearest `graft/`, so `graft ask` works from `src/deep/inside/`
782
+ walk up to the nearest `graft/`, so `trail ask` works from `src/deep/inside/`
494
783
  without a `cd` to the repo root.
495
784
 
496
- ## Visualize it (`graft viz`)
785
+ ## Visualize it (`trail viz`)
497
786
 
498
- `graft viz` opens a local, interactive view of both graphs — no install, no dev
787
+ `trail viz` opens a local, interactive view of both graphs. No install, no dev
499
788
  server; the viewer ships prebuilt inside the package.
500
789
 
501
790
  <p align="center">
502
- <img src="assets/graft-viz-demo.gif" alt="graft viz — searching a symbol and jumping to it lights up its dependency graph: amber edges are what it depends on, teal is what depends on it" width="820"/>
791
+ <img src="assets/graft-viz-demo.gif" alt="The graph viewer: searching a symbol and jumping to it lights up its dependency graph: amber edges are what it depends on, indigo is what depends on it" width="820"/>
503
792
  <br/><sub>search → jump to a node → dependency graph lights up</sub>
504
793
  </p>
505
794
 
506
- - **Context** tab — the architecture graph from `graft/*.md`. Nodes colored by
795
+ - **Context** tab: the architecture graph from `graft/*.md`. Nodes colored by
507
796
  type, sized by connectedness.
508
- - **Code** tab — the per-symbol graph from `graft/.graph/wiring.json` (run `graft build` first).
509
- - **Outline** tab — the file → class → method hierarchy as a collapsible tree.
797
+ - **Code** tab: the per-symbol graph from `graft/.graph/wiring.json` (run `trail build` first).
798
+ - **Outline** tab: the file → class → method hierarchy as a collapsible tree.
510
799
 
511
800
  Edges speak the code's language. Every link is one of a closed set of verbs, each
512
801
  answering a question someone building or reviewing code actually asks:
@@ -519,76 +808,21 @@ answering a question someone building or reviewing code actually asks:
519
808
  | `configures` | what changes its behavior without a code change? |
520
809
  | `validates` | what checks or judges this? (tests, drift checks, scoring) |
521
810
  | `extends` / `implements` | what contract must this honor? |
811
+ | `references` | what names this without calling it? (drawn as faint dots) |
522
812
 
523
813
  Select a node and its edges take on direction: **amber = what it depends on,
524
- teal = what depends on it**, with the verb written on each highlighted edge.
525
- Chips above the canvas filter by verb; tree-sitter-extracted edges draw solid
526
- while LLM-inferred ones draw dashed. The viewer live-reloads when `graft/`
814
+ indigo = what depends on it**, with the verb written on each highlighted edge.
815
+ Chips above the canvas filter by verb; edges the parser resolved exactly draw
816
+ solid, while edges matched by name alone, or inferred by the model, draw dashed. The viewer live-reloads when `graft/`
527
817
  changes on disk. Older graphs with vague verbs (`influences`, `supports`) are
528
- normalized on load — no regeneration needed.
529
-
530
- ---
531
-
532
- ## Tested on your popular repos
533
-
534
- The [benchmarks](#benchmark) measure the mechanism. The real test is whether graft helps an agent **ship real changes** on code people actually run, not just answer questions. So we benchmark it on popular open-source repos: **15 tasks each**, 10 real developer questions plus **5 actual implementation tasks** (real merged pull requests, each re-implemented from its base commit and scored against the files the maintainers actually changed). Same agent (Claude Opus), same file tools; the only difference is whether graft is wired in.
535
-
536
- Across these repos graft runs **up to 4× cheaper and 3× faster**, with better or no loss of correctness: it reproduces the real merged PRs by touching the same files the maintainers did. Per-repo detail below.
537
-
538
- ### PocketBase (Go, ~350 files)
539
-
540
- | Aggregate over 15 tasks | Standard Claude Code | With graft |
541
- |---|---|---|
542
- | Cost | $13.91 | **$11.02 (−21%)** |
543
- | Wall-clock | 2,044s | **1,762s (−14%)** |
544
- | PRs reproduced | 5 / 5 | **5 / 5 (same files as the maintainers)** |
545
-
546
- Cheaper and faster with no loss of correctness: graft reproduced all five merged PRs, touching the same files the maintainers did. The gap is widest on cross-file understanding — "how does auth work across OAuth2 providers" dropped from $2.19 to $0.84.
547
-
548
- <details>
549
- <summary><b>The 10 questions we asked</b></summary>
550
-
551
- 1. **Orientation** — Give me a map of PocketBase's architecture: the main subsystems and how an HTTP request flows through to the database.
552
- 2. **Entry-point trace** — Trace end-to-end what happens when a client creates a record via the REST API, from route handler to database write.
553
- 3. **Feature location** — I want to add a brand-new collection field type. Where do I hook it in, and which pieces must change?
554
- 4. **Bug localization** — Realtime subscriptions silently stop delivering events after a while. Where would you start looking, and why?
555
- 5. **Blast radius** — If I change the signature of the record-validation logic, what depends on it and what could break?
556
- 6. **Cross-file synthesis** — How does auth work across OAuth2 providers: where are tokens issued, validated, stored, and refreshed?
557
- 7. **Extensibility** — How do I use PocketBase as a Go framework to register a custom route plus an on-record-create hook?
558
- 8. **Security discovery** — Where is user input validated, and where are collection API access rules enforced before a query runs?
559
- 9. **Public API** — As an external app, how do I authenticate and then list and filter records over the REST API?
560
- 10. **Test verification** — Where are the tests for the record CRUD API, and what do they assert about access rules?
561
-
562
- </details>
563
-
564
- <details>
565
- <summary><b>The 5 merged PRs we re-implemented</b></summary>
566
-
567
- Each PR was reset to its base commit; graft's diff was scored against the files the merged PR changed.
568
-
569
- | PR | Type | What it does | Files the maintainers touched |
570
- |---|---|---|---|
571
- | [#6744](https://github.com/pocketbase/pocketbase/pull/6744) | feat | Generate & serve WebP thumbnails | `apis/file.go`, `tools/filesystem/filesystem.go` |
572
- | [#6947](https://github.com/pocketbase/pocketbase/pull/6947) | fix | Uniform char distribution in regex random strings | `tools/security/random_by_regex.go` |
573
- | [#6690](https://github.com/pocketbase/pocketbase/pull/6690) | refactor | Patreon OAuth2 to use `x/oauth2/endpoints` | `tools/auth/patreon.go` |
574
- | [#2726](https://github.com/pocketbase/pocketbase/pull/2726) | perf | Drop a redundant admin-count query on a hot middleware path | `apis/middlewares.go` |
575
- | [#3192](https://github.com/pocketbase/pocketbase/pull/3192) | fix | Restore prior API rules on automigration rollback | `plugins/migratecmd/templates.go` |
576
-
577
- </details>
578
-
579
- <details>
580
- <summary><b>Method</b></summary>
581
-
582
- Two clones of PocketBase at the same commit: one wired with `graft init`, one untouched and verified graft-free. Each task run headless (`claude -p`, Claude Opus) with an empty MCP config. Understanding questions were graded by whether the answer pointed to the right files and functions; PR tasks were scored on whether the agent's diff touched the same files as the merged PR. Every transcript was audited to confirm graft was actually used in the graft arm and absent from the standard arm.
583
-
584
- </details>
818
+ normalized on load, so no regeneration is needed.
585
819
 
586
820
  ---
587
821
 
588
822
  ## Development
589
823
 
590
824
  ```bash
591
- git clone https://github.com/NanoNets/context-graph-engine.git && cd context-graph-engine
825
+ git clone https://github.com/trailhq/Trail-Code.git && cd Trail-Code
592
826
  npm install
593
827
  npm run build
594
828
  npm test