@nanonets/graft 0.24.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/dist/ask/ask.d.ts +8 -0
  2. package/dist/ask/ask.d.ts.map +1 -1
  3. package/dist/ask/ask.js +33 -12
  4. package/dist/ask/ask.js.map +1 -1
  5. package/dist/claude/hook-io.d.ts +44 -0
  6. package/dist/claude/hook-io.d.ts.map +1 -0
  7. package/dist/claude/hook-io.js +144 -0
  8. package/dist/claude/hook-io.js.map +1 -0
  9. package/dist/claude/skills-hook-util.d.ts +25 -0
  10. package/dist/claude/skills-hook-util.d.ts.map +1 -0
  11. package/dist/claude/skills-hook-util.js +71 -0
  12. package/dist/claude/skills-hook-util.js.map +1 -0
  13. package/dist/cli-picker.d.ts +24 -0
  14. package/dist/cli-picker.d.ts.map +1 -1
  15. package/dist/cli-picker.js +36 -5
  16. package/dist/cli-picker.js.map +1 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +278 -29
  19. package/dist/cli.js.map +1 -1
  20. package/dist/cloud/lookup-activity.d.ts +16 -0
  21. package/dist/cloud/lookup-activity.d.ts.map +1 -0
  22. package/dist/cloud/lookup-activity.js +56 -0
  23. package/dist/cloud/lookup-activity.js.map +1 -0
  24. package/dist/cloud/nudge.d.ts.map +1 -1
  25. package/dist/cloud/nudge.js +3 -0
  26. package/dist/cloud/nudge.js.map +1 -1
  27. package/dist/cloud/onboarding.d.ts +237 -0
  28. package/dist/cloud/onboarding.d.ts.map +1 -0
  29. package/dist/cloud/onboarding.js +536 -0
  30. package/dist/cloud/onboarding.js.map +1 -0
  31. package/dist/cloud/pair.d.ts +76 -0
  32. package/dist/cloud/pair.d.ts.map +1 -0
  33. package/dist/cloud/pair.js +249 -0
  34. package/dist/cloud/pair.js.map +1 -0
  35. package/dist/cloud/workspace-sync.d.ts +10 -2
  36. package/dist/cloud/workspace-sync.d.ts.map +1 -1
  37. package/dist/cloud/workspace-sync.js +119 -7
  38. package/dist/cloud/workspace-sync.js.map +1 -1
  39. package/dist/cloud/workspace.d.ts +22 -1
  40. package/dist/cloud/workspace.d.ts.map +1 -1
  41. package/dist/cloud/workspace.js +16 -1
  42. package/dist/cloud/workspace.js.map +1 -1
  43. package/dist/graph/native.d.ts +2 -0
  44. package/dist/graph/native.d.ts.map +1 -1
  45. package/dist/graph/native.js +29 -4
  46. package/dist/graph/native.js.map +1 -1
  47. package/dist/hosts/claude-global.d.ts +14 -0
  48. package/dist/hosts/claude-global.d.ts.map +1 -1
  49. package/dist/hosts/claude-global.js +38 -3
  50. package/dist/hosts/claude-global.js.map +1 -1
  51. package/dist/init/install-record.d.ts +21 -0
  52. package/dist/init/install-record.d.ts.map +1 -0
  53. package/dist/init/install-record.js +144 -0
  54. package/dist/init/install-record.js.map +1 -0
  55. package/dist/init/plain-file.d.ts +11 -0
  56. package/dist/init/plain-file.d.ts.map +1 -0
  57. package/dist/init/plain-file.js +80 -0
  58. package/dist/init/plain-file.js.map +1 -0
  59. package/dist/mcp/brains.d.ts +72 -0
  60. package/dist/mcp/brains.d.ts.map +1 -0
  61. package/dist/mcp/brains.js +220 -0
  62. package/dist/mcp/brains.js.map +1 -0
  63. package/dist/mcp/server.d.ts +3 -1
  64. package/dist/mcp/server.d.ts.map +1 -1
  65. package/dist/mcp/server.js +40 -5
  66. package/dist/mcp/server.js.map +1 -1
  67. package/dist/mcp/tools.d.ts.map +1 -1
  68. package/dist/mcp/tools.js +7 -2
  69. package/dist/mcp/tools.js.map +1 -1
  70. package/dist/notes/cold-start.d.ts +30 -1
  71. package/dist/notes/cold-start.d.ts.map +1 -1
  72. package/dist/notes/cold-start.js +98 -19
  73. package/dist/notes/cold-start.js.map +1 -1
  74. package/dist/notes/every-repo.d.ts +18 -0
  75. package/dist/notes/every-repo.d.ts.map +1 -0
  76. package/dist/notes/every-repo.js +86 -0
  77. package/dist/notes/every-repo.js.map +1 -0
  78. package/dist/notes/guardrails.d.ts +8 -0
  79. package/dist/notes/guardrails.d.ts.map +1 -0
  80. package/dist/notes/guardrails.js +38 -0
  81. package/dist/notes/guardrails.js.map +1 -0
  82. package/dist/notes/lesson-index.d.ts +13 -0
  83. package/dist/notes/lesson-index.d.ts.map +1 -0
  84. package/dist/notes/lesson-index.js +135 -0
  85. package/dist/notes/lesson-index.js.map +1 -0
  86. package/dist/notes/linked-learnings.d.ts +8 -0
  87. package/dist/notes/linked-learnings.d.ts.map +1 -0
  88. package/dist/notes/linked-learnings.js +113 -0
  89. package/dist/notes/linked-learnings.js.map +1 -0
  90. package/dist/notes/replace.d.ts +14 -0
  91. package/dist/notes/replace.d.ts.map +1 -0
  92. package/dist/notes/replace.js +38 -0
  93. package/dist/notes/replace.js.map +1 -0
  94. package/dist/notes/repo-notes-dir.d.ts +2 -0
  95. package/dist/notes/repo-notes-dir.d.ts.map +1 -0
  96. package/dist/notes/repo-notes-dir.js +16 -0
  97. package/dist/notes/repo-notes-dir.js.map +1 -0
  98. package/dist/skills/anchors-cli.d.ts +33 -0
  99. package/dist/skills/anchors-cli.d.ts.map +1 -0
  100. package/dist/skills/anchors-cli.js +274 -0
  101. package/dist/skills/anchors-cli.js.map +1 -0
  102. package/dist/skills/anchors-git.d.ts +29 -0
  103. package/dist/skills/anchors-git.d.ts.map +1 -0
  104. package/dist/skills/anchors-git.js +241 -0
  105. package/dist/skills/anchors-git.js.map +1 -0
  106. package/dist/skills/anchors-wide.d.ts +25 -0
  107. package/dist/skills/anchors-wide.d.ts.map +1 -0
  108. package/dist/skills/anchors-wide.js +481 -0
  109. package/dist/skills/anchors-wide.js.map +1 -0
  110. package/dist/skills/anchors.d.ts +32 -0
  111. package/dist/skills/anchors.d.ts.map +1 -0
  112. package/dist/skills/anchors.js +485 -0
  113. package/dist/skills/anchors.js.map +1 -0
  114. package/dist/skills/check-result.d.ts +26 -0
  115. package/dist/skills/check-result.d.ts.map +1 -0
  116. package/dist/skills/check-result.js +46 -0
  117. package/dist/skills/check-result.js.map +1 -0
  118. package/dist/skills/codex-sandbox.d.ts +6 -0
  119. package/dist/skills/codex-sandbox.d.ts.map +1 -0
  120. package/dist/skills/codex-sandbox.js +55 -0
  121. package/dist/skills/codex-sandbox.js.map +1 -0
  122. package/dist/skills/compile-split.d.ts +57 -0
  123. package/dist/skills/compile-split.d.ts.map +1 -0
  124. package/dist/skills/compile-split.js +532 -0
  125. package/dist/skills/compile-split.js.map +1 -0
  126. package/dist/skills/compile-version.d.ts +37 -0
  127. package/dist/skills/compile-version.d.ts.map +1 -0
  128. package/dist/skills/compile-version.js +56 -0
  129. package/dist/skills/compile-version.js.map +1 -0
  130. package/dist/skills/compile-waits.d.ts +12 -0
  131. package/dist/skills/compile-waits.d.ts.map +1 -0
  132. package/dist/skills/compile-waits.js +52 -0
  133. package/dist/skills/compile-waits.js.map +1 -0
  134. package/dist/skills/compile-words.d.ts +82 -0
  135. package/dist/skills/compile-words.d.ts.map +1 -0
  136. package/dist/skills/compile-words.js +385 -0
  137. package/dist/skills/compile-words.js.map +1 -0
  138. package/dist/skills/compile.d.ts +35 -0
  139. package/dist/skills/compile.d.ts.map +1 -0
  140. package/dist/skills/compile.js +488 -0
  141. package/dist/skills/compile.js.map +1 -0
  142. package/dist/skills/credit-facts.d.ts +8 -0
  143. package/dist/skills/credit-facts.d.ts.map +1 -0
  144. package/dist/skills/credit-facts.js +32 -0
  145. package/dist/skills/credit-facts.js.map +1 -0
  146. package/dist/skills/directive-words.d.ts +11 -0
  147. package/dist/skills/directive-words.d.ts.map +1 -0
  148. package/dist/skills/directive-words.js +33 -0
  149. package/dist/skills/directive-words.js.map +1 -0
  150. package/dist/skills/fidelity.d.ts +42 -0
  151. package/dist/skills/fidelity.d.ts.map +1 -0
  152. package/dist/skills/fidelity.js +138 -0
  153. package/dist/skills/fidelity.js.map +1 -0
  154. package/dist/skills/forget-notice.d.ts +44 -0
  155. package/dist/skills/forget-notice.d.ts.map +1 -0
  156. package/dist/skills/forget-notice.js +131 -0
  157. package/dist/skills/forget-notice.js.map +1 -0
  158. package/dist/skills/found-skill.d.ts +35 -0
  159. package/dist/skills/found-skill.d.ts.map +1 -0
  160. package/dist/skills/found-skill.js +66 -0
  161. package/dist/skills/found-skill.js.map +1 -0
  162. package/dist/skills/front-version.d.ts +12 -0
  163. package/dist/skills/front-version.d.ts.map +1 -0
  164. package/dist/skills/front-version.js +87 -0
  165. package/dist/skills/front-version.js.map +1 -0
  166. package/dist/skills/host-facts.d.ts +51 -0
  167. package/dist/skills/host-facts.d.ts.map +1 -0
  168. package/dist/skills/host-facts.js +134 -0
  169. package/dist/skills/host-facts.js.map +1 -0
  170. package/dist/skills/ledger.d.ts +43 -0
  171. package/dist/skills/ledger.d.ts.map +1 -0
  172. package/dist/skills/ledger.js +336 -0
  173. package/dist/skills/ledger.js.map +1 -0
  174. package/dist/skills/lessons.d.ts +60 -0
  175. package/dist/skills/lessons.d.ts.map +1 -0
  176. package/dist/skills/lessons.js +396 -0
  177. package/dist/skills/lessons.js.map +1 -0
  178. package/dist/skills/offer-answers.d.ts +20 -0
  179. package/dist/skills/offer-answers.d.ts.map +1 -0
  180. package/dist/skills/offer-answers.js +51 -0
  181. package/dist/skills/offer-answers.js.map +1 -0
  182. package/dist/skills/own-folder.d.ts +9 -0
  183. package/dist/skills/own-folder.d.ts.map +1 -0
  184. package/dist/skills/own-folder.js +36 -0
  185. package/dist/skills/own-folder.js.map +1 -0
  186. package/dist/skills/person.d.ts +34 -0
  187. package/dist/skills/person.d.ts.map +1 -0
  188. package/dist/skills/person.js +102 -0
  189. package/dist/skills/person.js.map +1 -0
  190. package/dist/skills/probe-clean.d.ts +9 -0
  191. package/dist/skills/probe-clean.d.ts.map +1 -0
  192. package/dist/skills/probe-clean.js +48 -0
  193. package/dist/skills/probe-clean.js.map +1 -0
  194. package/dist/skills/probes.d.ts +26 -0
  195. package/dist/skills/probes.d.ts.map +1 -0
  196. package/dist/skills/probes.js +225 -0
  197. package/dist/skills/probes.js.map +1 -0
  198. package/dist/skills/recall.d.ts +119 -0
  199. package/dist/skills/recall.d.ts.map +1 -0
  200. package/dist/skills/recall.js +370 -0
  201. package/dist/skills/recall.js.map +1 -0
  202. package/dist/skills/receipts.d.ts +44 -0
  203. package/dist/skills/receipts.d.ts.map +1 -0
  204. package/dist/skills/receipts.js +223 -0
  205. package/dist/skills/receipts.js.map +1 -0
  206. package/dist/skills/run-checkout.d.ts +4 -0
  207. package/dist/skills/run-checkout.d.ts.map +1 -0
  208. package/dist/skills/run-checkout.js +37 -0
  209. package/dist/skills/run-checkout.js.map +1 -0
  210. package/dist/skills/runblock.d.ts +45 -0
  211. package/dist/skills/runblock.d.ts.map +1 -0
  212. package/dist/skills/runblock.js +222 -0
  213. package/dist/skills/runblock.js.map +1 -0
  214. package/dist/skills/save-parse.d.ts +42 -0
  215. package/dist/skills/save-parse.d.ts.map +1 -0
  216. package/dist/skills/save-parse.js +172 -0
  217. package/dist/skills/save-parse.js.map +1 -0
  218. package/dist/skills/save-store.d.ts +12 -0
  219. package/dist/skills/save-store.d.ts.map +1 -0
  220. package/dist/skills/save-store.js +22 -0
  221. package/dist/skills/save-store.js.map +1 -0
  222. package/dist/skills/settings.d.ts +38 -0
  223. package/dist/skills/settings.d.ts.map +1 -0
  224. package/dist/skills/settings.js +133 -0
  225. package/dist/skills/settings.js.map +1 -0
  226. package/dist/skills/skill-diff.d.ts +40 -0
  227. package/dist/skills/skill-diff.d.ts.map +1 -0
  228. package/dist/skills/skill-diff.js +191 -0
  229. package/dist/skills/skill-diff.js.map +1 -0
  230. package/dist/skills/skill-file.d.ts +24 -0
  231. package/dist/skills/skill-file.d.ts.map +1 -0
  232. package/dist/skills/skill-file.js +97 -0
  233. package/dist/skills/skill-file.js.map +1 -0
  234. package/dist/skills/skill-rebuild.d.ts +27 -0
  235. package/dist/skills/skill-rebuild.d.ts.map +1 -0
  236. package/dist/skills/skill-rebuild.js +85 -0
  237. package/dist/skills/skill-rebuild.js.map +1 -0
  238. package/dist/skills/skillmd.d.ts +17 -0
  239. package/dist/skills/skillmd.d.ts.map +1 -0
  240. package/dist/skills/skillmd.js +219 -0
  241. package/dist/skills/skillmd.js.map +1 -0
  242. package/dist/skills/skills.d.ts +2 -0
  243. package/dist/skills/skills.d.ts.map +1 -1
  244. package/dist/skills/skills.js +1 -1
  245. package/dist/skills/skills.js.map +1 -1
  246. package/dist/skills/staleness.d.ts +27 -0
  247. package/dist/skills/staleness.d.ts.map +1 -0
  248. package/dist/skills/staleness.js +178 -0
  249. package/dist/skills/staleness.js.map +1 -0
  250. package/dist/skills/state.d.ts +36 -0
  251. package/dist/skills/state.d.ts.map +1 -0
  252. package/dist/skills/state.js +259 -0
  253. package/dist/skills/state.js.map +1 -0
  254. package/dist/skills/store-fs.d.ts +77 -0
  255. package/dist/skills/store-fs.d.ts.map +1 -0
  256. package/dist/skills/store-fs.js +194 -0
  257. package/dist/skills/store-fs.js.map +1 -0
  258. package/dist/skills/store-held.d.ts +44 -0
  259. package/dist/skills/store-held.d.ts.map +1 -0
  260. package/dist/skills/store-held.js +147 -0
  261. package/dist/skills/store-held.js.map +1 -0
  262. package/dist/skills/store.d.ts +73 -0
  263. package/dist/skills/store.d.ts.map +1 -0
  264. package/dist/skills/store.js +279 -0
  265. package/dist/skills/store.js.map +1 -0
  266. package/dist/skills/validate.d.ts +11 -0
  267. package/dist/skills/validate.d.ts.map +1 -0
  268. package/dist/skills/validate.js +112 -0
  269. package/dist/skills/validate.js.map +1 -0
  270. package/dist/skills/versions-fs.d.ts +45 -0
  271. package/dist/skills/versions-fs.d.ts.map +1 -0
  272. package/dist/skills/versions-fs.js +234 -0
  273. package/dist/skills/versions-fs.js.map +1 -0
  274. package/dist/skills/versions.d.ts +56 -0
  275. package/dist/skills/versions.d.ts.map +1 -0
  276. package/dist/skills/versions.js +351 -0
  277. package/dist/skills/versions.js.map +1 -0
  278. package/dist/trace/checks.d.ts +63 -0
  279. package/dist/trace/checks.d.ts.map +1 -0
  280. package/dist/trace/checks.js +487 -0
  281. package/dist/trace/checks.js.map +1 -0
  282. package/dist/trace/claude.d.ts +124 -0
  283. package/dist/trace/claude.d.ts.map +1 -0
  284. package/dist/trace/claude.js +303 -0
  285. package/dist/trace/claude.js.map +1 -0
  286. package/dist/trace/codex-exec.d.ts +22 -0
  287. package/dist/trace/codex-exec.d.ts.map +1 -0
  288. package/dist/trace/codex-exec.js +129 -0
  289. package/dist/trace/codex-exec.js.map +1 -0
  290. package/dist/trace/codex-meta.d.ts +23 -0
  291. package/dist/trace/codex-meta.d.ts.map +1 -0
  292. package/dist/trace/codex-meta.js +112 -0
  293. package/dist/trace/codex-meta.js.map +1 -0
  294. package/dist/trace/codex.d.ts +33 -0
  295. package/dist/trace/codex.d.ts.map +1 -0
  296. package/dist/trace/codex.js +485 -0
  297. package/dist/trace/codex.js.map +1 -0
  298. package/dist/trace/cursor.d.ts +16 -0
  299. package/dist/trace/cursor.d.ts.map +1 -0
  300. package/dist/trace/cursor.js +133 -0
  301. package/dist/trace/cursor.js.map +1 -0
  302. package/dist/trace/dialect.d.ts +43 -0
  303. package/dist/trace/dialect.d.ts.map +1 -0
  304. package/dist/trace/dialect.js +95 -0
  305. package/dist/trace/dialect.js.map +1 -0
  306. package/dist/trace/epochs.d.ts +10 -0
  307. package/dist/trace/epochs.d.ts.map +1 -0
  308. package/dist/trace/epochs.js +16 -0
  309. package/dist/trace/epochs.js.map +1 -0
  310. package/dist/trace/failure.d.ts +15 -0
  311. package/dist/trace/failure.d.ts.map +1 -0
  312. package/dist/trace/failure.js +69 -0
  313. package/dist/trace/failure.js.map +1 -0
  314. package/dist/trace/gate-file.d.ts +71 -0
  315. package/dist/trace/gate-file.d.ts.map +1 -0
  316. package/dist/trace/gate-file.js +329 -0
  317. package/dist/trace/gate-file.js.map +1 -0
  318. package/dist/trace/guard-fast.d.ts +22 -0
  319. package/dist/trace/guard-fast.d.ts.map +1 -0
  320. package/dist/trace/guard-fast.js +213 -0
  321. package/dist/trace/guard-fast.js.map +1 -0
  322. package/dist/trace/housekeeping.d.ts +5 -0
  323. package/dist/trace/housekeeping.d.ts.map +1 -0
  324. package/dist/trace/housekeeping.js +93 -0
  325. package/dist/trace/housekeeping.js.map +1 -0
  326. package/dist/trace/jobs.d.ts +52 -0
  327. package/dist/trace/jobs.d.ts.map +1 -0
  328. package/dist/trace/jobs.js +182 -0
  329. package/dist/trace/jobs.js.map +1 -0
  330. package/dist/trace/known-repo.d.ts +3 -0
  331. package/dist/trace/known-repo.d.ts.map +1 -0
  332. package/dist/trace/known-repo.js +55 -0
  333. package/dist/trace/known-repo.js.map +1 -0
  334. package/dist/trace/pool.d.ts +40 -0
  335. package/dist/trace/pool.d.ts.map +1 -0
  336. package/dist/trace/pool.js +154 -0
  337. package/dist/trace/pool.js.map +1 -0
  338. package/dist/trace/repairs.d.ts +27 -0
  339. package/dist/trace/repairs.d.ts.map +1 -0
  340. package/dist/trace/repairs.js +303 -0
  341. package/dist/trace/repairs.js.map +1 -0
  342. package/dist/trace/run-calls.d.ts +82 -0
  343. package/dist/trace/run-calls.d.ts.map +1 -0
  344. package/dist/trace/run-calls.js +331 -0
  345. package/dist/trace/run-calls.js.map +1 -0
  346. package/dist/trace/run-join.d.ts +20 -0
  347. package/dist/trace/run-join.d.ts.map +1 -0
  348. package/dist/trace/run-join.js +99 -0
  349. package/dist/trace/run-join.js.map +1 -0
  350. package/dist/trace/run-sheets.d.ts +26 -0
  351. package/dist/trace/run-sheets.d.ts.map +1 -0
  352. package/dist/trace/run-sheets.js +145 -0
  353. package/dist/trace/run-sheets.js.map +1 -0
  354. package/dist/trace/run-turns.d.ts +24 -0
  355. package/dist/trace/run-turns.d.ts.map +1 -0
  356. package/dist/trace/run-turns.js +67 -0
  357. package/dist/trace/run-turns.js.map +1 -0
  358. package/dist/trace/run-verdict.d.ts +24 -0
  359. package/dist/trace/run-verdict.d.ts.map +1 -0
  360. package/dist/trace/run-verdict.js +176 -0
  361. package/dist/trace/run-verdict.js.map +1 -0
  362. package/dist/trace/runs.d.ts +54 -0
  363. package/dist/trace/runs.d.ts.map +1 -0
  364. package/dist/trace/runs.js +501 -0
  365. package/dist/trace/runs.js.map +1 -0
  366. package/dist/trace/skill-session.d.ts +64 -0
  367. package/dist/trace/skill-session.d.ts.map +1 -0
  368. package/dist/trace/skill-session.js +232 -0
  369. package/dist/trace/skill-session.js.map +1 -0
  370. package/dist/trace/tamper.d.ts +12 -0
  371. package/dist/trace/tamper.d.ts.map +1 -0
  372. package/dist/trace/tamper.js +405 -0
  373. package/dist/trace/tamper.js.map +1 -0
  374. package/dist/trace/typed.d.ts +30 -0
  375. package/dist/trace/typed.d.ts.map +1 -0
  376. package/dist/trace/typed.js +132 -0
  377. package/dist/trace/typed.js.map +1 -0
  378. package/dist/trace/wall-state.d.ts +86 -0
  379. package/dist/trace/wall-state.d.ts.map +1 -0
  380. package/dist/trace/wall-state.js +279 -0
  381. package/dist/trace/wall-state.js.map +1 -0
  382. package/dist/trace/walls.d.ts +40 -0
  383. package/dist/trace/walls.d.ts.map +1 -0
  384. package/dist/trace/walls.js +318 -0
  385. package/dist/trace/walls.js.map +1 -0
  386. package/dist/vendor/tree-sitter-swift/LICENSE +21 -0
  387. package/dist/vendor/tree-sitter-swift/node-types.json +30694 -0
  388. package/dist/vendor/tree-sitter-swift/prebuilds/darwin-arm64/tree-sitter-swift.node +0 -0
  389. package/dist/vendor/tree-sitter-swift/prebuilds/darwin-x64/tree-sitter-swift.node +0 -0
  390. package/dist/vendor/tree-sitter-swift/prebuilds/linux-arm64/tree-sitter-swift.node +0 -0
  391. package/dist/vendor/tree-sitter-swift/prebuilds/linux-x64/tree-sitter-swift.node +0 -0
  392. package/dist/vendor/tree-sitter-swift/prebuilds/win32-arm64/tree-sitter-swift.node +0 -0
  393. package/dist/vendor/tree-sitter-swift/prebuilds/win32-x64/tree-sitter-swift.node +0 -0
  394. package/package.json +6 -3
  395. package/scripts/stamp-telemetry-key.mjs +8 -5
  396. package/scripts/vendor-grammars.mjs +35 -0
package/dist/cli.js CHANGED
@@ -41,6 +41,7 @@ import { planInit, selectedWrites } from "./hosts/plan.js";
41
41
  import { planRetract, runRetract, changed } from "./hosts/retract.js";
42
42
  import { compactWrites, formatNonInteractiveHelp, formatPlan, pickLearnings, runPicker } from "./cli-picker.js";
43
43
  import { buildGraphWithProgress } from "./claude/build-progress.js";
44
+ import { installBrainsServer, removeBrainsServer } from "./hosts/claude-global.js";
44
45
  import { homedir } from "node:os";
45
46
  import { formatUpgradeReport, formatVersionReport, getNpmViewVersion, readCurrentVersion, readPackageName, runUpgrade } from "./cli-meta.js";
46
47
  import { nativeFallbackNotice } from "./graph/native.js";
@@ -52,13 +53,17 @@ import { costLabel, listNotes, noteName, notePlace, noteTargets, readingTokens,
52
53
  import { findLearning, liveLearnings } from "./notes/learning-fields.js";
53
54
  import { aboutTerms, currentSessionCost } from "./notes/session-cost.js";
54
55
  import { beginPastRead, finishPastRead } from "./notes/cold-start.js";
56
+ import { skippedSkillLines } from "./skills/found-skill.js";
55
57
  import { anchoredReviews, beginReviewRead, finishReviewRead } from "./notes/pr-reviews.js";
56
58
  import { finishMemoryRead, memoryCandidates, offeredBefore } from "./notes/memory-notes.js";
59
+ import { finishPair, PairRun, validPairCode } from "./cloud/pair.js";
57
60
  import { currentBranch, noteAuthor, teammatesOn } from "./notes/git-facts.js";
58
61
  import { gateNote, namesRepoSymbol, symbolCandidates, trackedFiles } from "./notes/note-gate.js";
59
62
  import { confirm, fold, getSkill, learn, listSkills, publish, skillForAgent, skillName, skillStatus } from "./skills/skills.js";
63
+ import { recordLookup } from "./cloud/lookup-activity.js";
60
64
  import { clearPending, cloudLines, loginLink, sessionKey, waitForConnect } from "./cloud/nudge.js";
61
- import { addRepo, clearCloud, cloudEnabled, fetchMe, fetchTeam, isError, readCloud, writeCloud } from "./cloud/workspace.js";
65
+ import { addRepo, clearCloud, cloudEnabled, fetchMe, fetchTeam, isError, readCloud, trailUrl, writeCloud } from "./cloud/workspace.js";
66
+ import { claimConnectCode, connectAgain, offlineLine, learningsSummary, machineName, normalizeCode, OnboardingReporter, repoRef, teammatesChecked, teammatesFromGit, tokensOnOneLookup, } from "./cloud/onboarding.js";
62
67
  import { inWorkspace, maybeSyncInBackground, recordActivity, runSyncChild, syncRepo } from "./cloud/workspace-sync.js";
63
68
  import { checkLocally } from "./check/local-check.js";
64
69
  import { formatOverlap, maybeRefreshBranches, overlapsWith, pushedWhen, readBranchCache, refreshBranches } from "./notes/branches.js";
@@ -307,6 +312,14 @@ program
307
312
  .action(async () => {
308
313
  await waitForConnect();
309
314
  });
315
+ program
316
+ .command("_trail-pair", { hidden: true })
317
+ .description("internal: after `init --pair`, wait for the connect and the review in the browser, then upload the repo's learnings")
318
+ .argument("<state>")
319
+ .argument("<dir>")
320
+ .action(async (state, dir) => {
321
+ await finishPair(state, resolve(dir));
322
+ });
310
323
  program
311
324
  .command("_update-check", { hidden: true })
312
325
  .description("internal: refresh the cached latest-version answer")
@@ -622,39 +635,27 @@ grouped(program.command("build"), GROUP.setup)
622
635
  }
623
636
  }
624
637
  });
625
- /** The file part of a hit's `file:Lx-Ly` pointer. */
626
- function pointerFile(pointer) {
627
- return pointer.replace(/:L\d+(-L?\d+)?$/, "");
628
- }
629
638
  /**
630
639
  * After `ask`, under trail: which shown learnings are a teammate's, and the
631
- * shown learnings recorded as a use, which is what the team page counts as
632
- * reuse. Then the background upkeep that keeps branches and the workspace
633
- * current. Spawns no git itself. Teammates' branches come up after an edit
640
+ * lookup recorded (the learnings shown are a use, which is what the team page
641
+ * counts as reuse; the tokens saved ride along). Then the background upkeep
642
+ * that keeps branches and the workspace current. Spawns no git itself. Teammates' branches come up after an edit
634
643
  * instead, once there's a function to compare (notes/edit-overlap.ts).
635
644
  */
636
645
  function afterAsk(r, repo) {
646
+ // Every lookup is reported, not only ones that showed a learning: the tokens
647
+ // the map saved are what the team page's running total counts. A no-op unless
648
+ // this machine is connected and the repo is the workspace's.
649
+ recordLookup(r, repo);
637
650
  if (!r.notesChecked)
638
651
  return;
639
652
  rememberRepo(repo);
640
653
  maybeRefreshBranches(repo);
641
654
  const me = noteAuthor(repo);
642
- const files = [...new Set(r.hits.map((h) => pointerFile(h.pointer)))];
643
655
  const shown = r.notes ?? [];
644
656
  if (shown.length) {
645
657
  for (const h of shown)
646
658
  h.note.teammate = !!h.note.author && !!me && h.note.author !== me;
647
- recordActivity({
648
- repo: repoPlace(repo).key,
649
- kind: "search",
650
- asker: me,
651
- session: sessionKey(repo) ?? `${me}-${new Date().toISOString().slice(0, 10)}`,
652
- query: r.query,
653
- files,
654
- shown_paths: shown.map((h) => noteName(h.note)),
655
- shown_authors: shown.map((h) => h.note.author),
656
- at: new Date().toISOString(),
657
- });
658
659
  const saved = shown.reduce((sum, h) => sum + savedByNote(h.note), 0);
659
660
  track("learning_reused", { teammate: String(shown.some((h) => h.note.teammate)), saved_tokens_bucket: savedTokensBucket(saved) }, { repo });
660
661
  }
@@ -853,9 +854,14 @@ program
853
854
  .command("mcp", { hidden: TRAIL })
854
855
  .description("Serve the graph over MCP (stdio) — exposes graft_find_code, graft_trace_calls, graft_find_all, graft_file_api, graft_repo_map and graft_check_freshness as tools")
855
856
  .argument(...DIR_ARG)
856
- .action(async (dirArg) => {
857
- const dir = noteQuery(queryRoot(dirArg));
857
+ .option("--brains", "serve only the connected Trail workspace's brain tools (what Claude Code gets after init --connect)")
858
+ .action(async (dirArg, opts) => {
858
859
  const { startMcpServer } = await import("./mcp/server.js");
860
+ if (opts.brains) {
861
+ startMcpServer(process.cwd(), undefined, currentVersion, { brainsOnly: true });
862
+ return;
863
+ }
864
+ const dir = noteQuery(queryRoot(dirArg));
859
865
  const globalOpts = program.opts();
860
866
  startMcpServer(dir, globalOpts.dir, currentVersion);
861
867
  });
@@ -1172,8 +1178,19 @@ grouped(program.command("init"), GROUP.setup)
1172
1178
  .option("-y, --yes", "skip the picker and wire every detected agent (the pre-0.8 default)")
1173
1179
  .option("--no-global", "skip writes outside this repo (the ~/.codex/ config + hooks)")
1174
1180
  .option("--verbose", "print every file written, the graph build's own output and the closing banner")
1181
+ .option("--connect <code>", "connect this machine to your Trail workspace with the one-time code from team.trailhq.com, and send it a summary of this repo (titles, counts and names; never code)")
1182
+ .option("--pair <code>", "the pair code from Trail's onboarding page: that page shows this run live, then you review what it found")
1183
+ .option("--server <url>", "the Trail that gave the code (default: Trail cloud, https://team.trailhq.com)")
1175
1184
  .action(async (dir, opts) => {
1176
- await runInitCommand(dir, opts);
1185
+ if (opts.connect !== undefined && opts.pair !== undefined) {
1186
+ console.error("✗ --connect and --pair are two ways in: use the one your Trail page gave you");
1187
+ process.exitCode = 1;
1188
+ return;
1189
+ }
1190
+ if (opts.connect !== undefined)
1191
+ await runConnectInit(dir, opts);
1192
+ else
1193
+ await runInitCommand(dir, opts);
1177
1194
  });
1178
1195
  /** Everything on stdin, or "" when nothing is piped in. */
1179
1196
  async function readStdin() {
@@ -1334,19 +1351,58 @@ function printLines(lines) {
1334
1351
  if (lines.length)
1335
1352
  console.log(`\n${lines.join("\n")}`);
1336
1353
  }
1354
+ /**
1355
+ * `--server <url>` on `init --connect` and `--pair`: the Trail that gave the
1356
+ * code, kept for the rest of this run as TRAIL_URL. False, after saying why,
1357
+ * when it isn't a URL.
1358
+ */
1359
+ function useServerOption(raw) {
1360
+ const server = raw?.trim().replace(/\/+$/, "");
1361
+ if (!server)
1362
+ return true;
1363
+ if (!/^https?:\/\//.test(server)) {
1364
+ console.error("✗ --server takes a URL, like https://dev.trailhq.com");
1365
+ process.exitCode = 1;
1366
+ return false;
1367
+ }
1368
+ process.env.TRAIL_URL = server;
1369
+ return true;
1370
+ }
1371
+ /**
1372
+ * What `init --pair` hears from init, as the onboarding page's steps: the map
1373
+ * is done when `mapped` fires, the past sessions when `learned` does. Nothing
1374
+ * to say for a run that read no sessions (that step is already marked).
1375
+ */
1376
+ function pairProgress(pair) {
1377
+ return {
1378
+ mapped: (m) => pair.phase("files", "done", m.files ? `${m.files.toLocaleString("en-US")} files` : "", m.files ? `Mapped ${m.files.toLocaleString("en-US")} files` : "Mapped the code"),
1379
+ learned: (l) => {
1380
+ if (l.sessions <= 0)
1381
+ return;
1382
+ // The PR reviews' learnings come with `sessions: 0`; the rest were said in past sessions.
1383
+ const fromSessions = l.notes.filter((n) => n.sessions !== 0).length;
1384
+ pair.phase("decisions", "done", `${l.sessions} sessions`, `Read ${l.sessions} past sessions: ${fromSessions} thing${fromSessions === 1 ? "" : "s"} you told Claude more than once`);
1385
+ },
1386
+ };
1387
+ }
1337
1388
  /** Repo-relative with forward slashes, for printing. */
1338
1389
  function shown(repo, path) {
1339
1390
  return relative(repo, path).split("\\").join("/");
1340
1391
  }
1392
+ /** Agents init knows by another id: both read AGENTS.md. */
1393
+ const AGENT_ALIASES = { codex: "agents", opencode: "agents" };
1341
1394
  /** `graft init`. */
1342
- async function runInitCommand(dir, opts) {
1395
+ async function runInitCommand(dir, opts, progress) {
1343
1396
  if (opts.listAgents) {
1344
1397
  for (const id of [...hostIds(), "claude"])
1345
1398
  console.log(id);
1346
1399
  return null;
1347
1400
  }
1348
1401
  const repo = resolve(dir);
1349
- const explicit = Array.isArray(opts.agents) ? opts.agents : undefined;
1402
+ // Codex and OpenCode read AGENTS.md: `--agents codex` means that wiring.
1403
+ // The name as given is kept for Trail's onboarding page.
1404
+ const asked = Array.isArray(opts.agents) ? opts.agents : undefined;
1405
+ const explicit = asked ? [...new Set(asked.map((id) => AGENT_ALIASES[id] ?? id))] : undefined;
1350
1406
  // Checked before anything is written: run from the home folder, init wired
1351
1407
  // it, mapped every code file under it, then said to commit.
1352
1408
  const refusal = homeFolderRefusal(repo);
@@ -1426,6 +1482,26 @@ async function runInitCommand(dir, opts) {
1426
1482
  console.error("· no agents selected — nothing written");
1427
1483
  return null;
1428
1484
  }
1485
+ // With --pair, Trail's onboarding page is waiting on this run: tell it
1486
+ // first, so the person can sign up while the rest of init runs.
1487
+ let pair = null;
1488
+ if (opts.pair !== undefined) {
1489
+ if (!useServerOption(opts.server))
1490
+ return null;
1491
+ if (!validPairCode(opts.pair)) {
1492
+ console.error(`✗ --pair takes the code from Trail's onboarding page, got "${opts.pair}"`);
1493
+ process.exitCode = 1;
1494
+ return null;
1495
+ }
1496
+ const started = await PairRun.start(repo, opts.pair, { agent: asked?.[0] ?? ids[0], version: currentVersion });
1497
+ if ("error" in started) {
1498
+ console.error(`⚠ couldn't tell Trail about this run (${started.error}); setting up here anyway`);
1499
+ }
1500
+ else {
1501
+ pair = started;
1502
+ console.error(`· Trail's page is following along · ${started.url}`);
1503
+ }
1504
+ }
1429
1505
  const wantClaude = ids.includes("claude");
1430
1506
  const cliPath = fileURLToPath(import.meta.url);
1431
1507
  // Under trail, each repo gets its `.trail/learnings/`, committed with the
@@ -1452,6 +1528,16 @@ async function runInitCommand(dir, opts) {
1452
1528
  const reviewRead = TRAIL && wantClaude ? beginReviewRead(repo) : null;
1453
1529
  if (reviewRead)
1454
1530
  console.error("· reading review comments on this repo's merged PRs for what reviewers keep flagging");
1531
+ if (pair) {
1532
+ if (pastRead)
1533
+ pair.phase("decisions", "running", "", `Reading ${pastRead.sessions} past Claude sessions`);
1534
+ else
1535
+ pair.phase("decisions", "done", "none here");
1536
+ if (reviewRead)
1537
+ pair.phase("prs", "running", "", "Reading review comments on merged PRs");
1538
+ else
1539
+ pair.phase("prs", "done", "none here");
1540
+ }
1455
1541
  if (children.length)
1456
1542
  console.error(`· workspace: wiring ${repo} and ${children.length} child repo(s) — ${children.join(", ")}`);
1457
1543
  // Today's output, file by file, behind --verbose. Everything else gets one
@@ -1467,6 +1553,7 @@ async function runInitCommand(dir, opts) {
1467
1553
  // the workspace build, so it covers every child.
1468
1554
  let graphLine = null;
1469
1555
  if (!verbose) {
1556
+ pair?.phase("files", "running", "", "Mapping the code");
1470
1557
  const res = await buildGraphWithProgress(repo, { build: opts.build, cliPath });
1471
1558
  for (const m of res.messages)
1472
1559
  console.error(m);
@@ -1491,6 +1578,25 @@ async function runInitCommand(dir, opts) {
1491
1578
  graphLine = `· skipped the graph build — run ${cmd("graft build")}`;
1492
1579
  }
1493
1580
  }
1581
+ // --pair hears the same stages --connect does; only the ones InitProgress
1582
+ // has no slot for (a read starting, the PR read, nothing to read) stay inline.
1583
+ const report = pair ? pairProgress(pair) : progress;
1584
+ if (report?.mapped) {
1585
+ const g = loadGraphCached(contextDirFor(repo, children.length ? undefined : program.opts().dir));
1586
+ report.mapped({
1587
+ nodes: g?.meta.nodeCount ?? 0,
1588
+ edges: g?.meta.edgeCount ?? 0,
1589
+ files: g ? g.nodes.filter((n) => n.kind === "file").length : 0,
1590
+ });
1591
+ }
1592
+ // With --pair, one lookup measured against reading the files whole: the
1593
+ // page's token step. It needs the map, so it follows the build.
1594
+ let tokens = null;
1595
+ if (pair) {
1596
+ pair.phase("tokens", "running", "", "Measuring one lookup against reading the files");
1597
+ tokens = tokensOnOneLookup(repo, { contextDir: program.opts().dir });
1598
+ pair.tokensDone(tokens);
1599
+ }
1494
1600
  if (!verbose) {
1495
1601
  // Warnings and removals in full, whatever else is folded.
1496
1602
  const removed = [...new Set(reports.flatMap((r) => r.retracted))];
@@ -1512,6 +1618,7 @@ async function runInitCommand(dir, opts) {
1512
1618
  // what reviewers kept flagging on merged PRs, and Claude Code's notes about
1513
1619
  // the repo on this machine. What the person kept telling Claude is theirs.
1514
1620
  let learnedNow = false;
1621
+ let skillsWritten = [];
1515
1622
  let teamSaved = 0;
1516
1623
  const memory = TRAIL && wantClaude ? memoryCandidates(repo, { offered: offeredBefore(repo) }) : [];
1517
1624
  if (TRAIL && (pastRead || reviewRead || memory.length)) {
@@ -1525,7 +1632,7 @@ async function runInitCommand(dir, opts) {
1525
1632
  // first and ticked, their own unticked. A scripted run, or one with
1526
1633
  // --yes, keeps the team's and what they told Claude. Cancelling saves
1527
1634
  // none, and the next init asks again.
1528
- const picked = process.stdin.isTTY && process.stderr.isTTY && !opts.yes && fromReviews.length + memory.length + fromSessions.length
1635
+ const picked = process.stdin.isTTY && process.stderr.isTTY && !opts.yes && !pair && fromReviews.length + memory.length + fromSessions.length
1529
1636
  ? await pickLearnings([
1530
1637
  ...fromReviews.map((f) => ({ title: f.title, forTeam: true, prs: f.prs })),
1531
1638
  ...memory.map((c) => ({ title: c.title, forTeam: c.forTeam, memory: true })),
@@ -1537,10 +1644,13 @@ async function runInitCommand(dir, opts) {
1537
1644
  ? undefined
1538
1645
  : async (found) => picked && picked.filter((i) => i >= from && i < from + found.length).map((i) => found[i - from]);
1539
1646
  const learned = [];
1647
+ const learnedFrom = [];
1648
+ let sessionsRead = 0;
1540
1649
  // Reviews first: which of them are offered depends on the learnings already saved.
1541
1650
  if (reviewRead) {
1542
1651
  const { result, saved, kept, cancelled } = await finishReviewRead(repo, reviewRead, keepFrom(0));
1543
1652
  const offered = fromReviews.length;
1653
+ pair?.phase("prs", "done", `${result.prs} PRs`, `Read ${result.prs} merged PRs: ${saved.length} thing${saved.length === 1 ? "" : "s"} reviewers made authors change`);
1544
1654
  if (saved.length) {
1545
1655
  const n = saved.length;
1546
1656
  const what = n < offered ? `kept ${n} of the ${offered} things` : `learned ${n} thing${n === 1 ? "" : "s"}`;
@@ -1558,6 +1668,9 @@ async function runInitCommand(dir, opts) {
1558
1668
  console.error(`· couldn't read PR reviews this time; ${cmd("graft init")} again tries again`);
1559
1669
  }
1560
1670
  learned.push(...saved);
1671
+ // Not said in past sessions: `sessions: 0` keeps them out of the page's session count.
1672
+ for (const note of saved)
1673
+ learnedFrom.push({ note, sessions: 0 });
1561
1674
  }
1562
1675
  if (memory.length) {
1563
1676
  const { saved, cancelled } = await finishMemoryRead(repo, memory, keepFrom(fromReviews.length));
@@ -1570,9 +1683,21 @@ async function runInitCommand(dir, opts) {
1570
1683
  console.error(`· saved none of the ${memory.length} notes your Claude keeps about this repo; ${cmd("graft init")} again asks again`);
1571
1684
  }
1572
1685
  learned.push(...saved);
1686
+ for (const note of saved)
1687
+ learnedFrom.push({ note, sessions: 0 });
1573
1688
  }
1574
1689
  if (pastRead) {
1575
- const { result, saved, kept, cancelled } = await finishPastRead(repo, pastRead, keepFrom(fromReviews.length + memory.length));
1690
+ const { result, saved, kept, skills, cancelled } = await finishPastRead(repo, pastRead, keepFrom(fromReviews.length + memory.length));
1691
+ sessionsRead = result.read ?? 0;
1692
+ skillsWritten = skills;
1693
+ for (const { skill, path } of skills) {
1694
+ console.error(`✓ wrote a skill from a procedure you walked Claude through more than once: ${skill.title}`);
1695
+ console.error(` ${skill.for === "team" ? "for your team" : "just for you "} · ${path}`);
1696
+ }
1697
+ if (!cancelled)
1698
+ for (const line of skippedSkillLines(repo, result.skills, skills))
1699
+ console.error(line);
1700
+ saved.forEach((note, i) => learnedFrom.push({ note, sessions: kept[i]?.sessions.length }));
1576
1701
  const offered = result.findings.length;
1577
1702
  if (saved.length) {
1578
1703
  const n = saved.length;
@@ -1598,12 +1723,16 @@ async function runInitCommand(dir, opts) {
1598
1723
  }
1599
1724
  learnedNow = learned.length > 0;
1600
1725
  teamSaved = learned.filter((s) => s.scope === "repo").length;
1726
+ report?.learned?.({ notes: learnedFrom, sessions: sessionsRead });
1601
1727
  if (learnedNow) {
1602
1728
  console.error("· Claude follows them from your next session");
1603
1729
  if (teamSaved)
1604
1730
  console.error(commitLines({}, teammatesOn(repo), "repo").uncommitted);
1605
1731
  }
1606
1732
  }
1733
+ // Nothing read this run (already read once, or not Claude Code): the page still gets its stage.
1734
+ if (!(TRAIL && (pastRead || reviewRead || memory.length)))
1735
+ report?.learned?.({ notes: [], sessions: 0 });
1607
1736
  if (TRAIL && !learnedNow) {
1608
1737
  const home = notesHome.get(repo);
1609
1738
  if (home) {
@@ -1660,14 +1789,130 @@ async function runInitCommand(dir, opts) {
1660
1789
  nodes: graphs.reduce((n, g) => n + g.meta.nodeCount, 0),
1661
1790
  edges: graphs.reduce((n, g) => n + g.meta.edgeCount, 0),
1662
1791
  }));
1792
+ // Hand what was found to the review page, and leave a child waiting for
1793
+ // the person to connect and review there.
1794
+ if (pair) {
1795
+ // Teammates' branches on this person's files, checked against the
1796
+ // learnings just saved and the repo's own: synchronous, so the finding
1797
+ // exists before the page is told the read is done.
1798
+ pair.phase("team", "running", "", "Checking your team's branches");
1799
+ const teamNotes = listNotes(repo, { branches: false }).filter((n) => n.scope === "repo" && !n.ref);
1800
+ // No remote (or no default branch) means nothing was checked: `teammates`
1801
+ // is left out, since an empty list would say "checked, none".
1802
+ const teammates = teammatesChecked(repo, { learnings: teamNotes });
1803
+ pair.teamDone(teammates);
1804
+ pair.findings({ tokens, sessions: pastRead?.sessions, teammates });
1805
+ await pair.finish(repo, skillsWritten);
1806
+ pair.handOff(repo);
1807
+ console.error(`✓ Trail has what it found · review it in the browser: ${pair.url}`);
1808
+ if (!process.stdout.isTTY)
1809
+ console.error(`[trail] Tell the user, in one line: their Trail page has moved on; review what Trail found there. If it isn't open, the link is ${pair.url}`);
1810
+ }
1663
1811
  // Run by an agent, not a person: the last line tells it to ask about the
1664
1812
  // commit, since the person never saw the picker and Claude Code folds the rest.
1665
- if (teamSaved && !process.stderr.isTTY)
1813
+ // With --pair the person reviews them on the Trail page first, so no ask here.
1814
+ if (teamSaved && !pair && !process.stderr.isTTY)
1666
1815
  console.error(`→ ${teamSaved} team learning${teamSaved === 1 ? "" : "s"} in ${LEARNINGS_DIR}/ ${teamSaved === 1 ? "isn't" : "aren't"} committed yet. Ask the user: "Commit ${teamSaved === 1 ? "it" : `the ${teamSaved}`} so your teammates' Claude starts from ${teamSaved === 1 ? "it" : "them"}? (yes / no)"`);
1667
1816
  // Sorted so `claude,cursor` and `cursor,claude` aggregate as one value.
1668
1817
  track("init_completed", { agents: [...ids].sort().join(","), consent: consent === undefined ? "unasked" : String(consent) }, { repo });
1669
1818
  return { ids };
1670
1819
  }
1820
+ /**
1821
+ * `trail init --connect <CODE>`: the onboarding on team.trailhq.com. Claims the
1822
+ * one-time code (a wrong or spent one stops here, before anything is written),
1823
+ * saves the workspace token where `trail login` keeps it, then runs init as
1824
+ * usual while the page ticks off connected, mapped and learned. At the end,
1825
+ * one summary of the repo goes up (a lookup's tokens saved, the learnings'
1826
+ * titles, teammates' branches from git: never code, diffs or session text),
1827
+ * then `done`. Offline, init still sets the repo up and says how to connect.
1828
+ */
1829
+ async function runConnectInit(dir, opts) {
1830
+ if (opts.listAgents || opts.dryRun) {
1831
+ if (opts.dryRun)
1832
+ console.error("· --dry-run: not connecting");
1833
+ await runInitCommand(dir, opts);
1834
+ return;
1835
+ }
1836
+ const repo = resolve(dir);
1837
+ if (!useServerOption(opts.server))
1838
+ return;
1839
+ const base = trailUrl();
1840
+ const code = normalizeCode(opts.connect ?? "");
1841
+ if (!code) {
1842
+ console.error(`✗ "${opts.connect ?? ""}" isn't a Trail code · it looks like TRL-7F2A-K9QD, from ${base}/welcome/code`);
1843
+ process.exitCode = 1;
1844
+ return;
1845
+ }
1846
+ const ref = repoRef(repo);
1847
+ const machine = machineName();
1848
+ const got = await claimConnectCode(base, code, { machine, repo: ref });
1849
+ const cloud = "cloud" in got ? got.cloud : null;
1850
+ if ("cloud" in got) {
1851
+ const cloud = got.cloud;
1852
+ writeCloud(cloud);
1853
+ // A sign-in link out from before is moot now.
1854
+ clearPending();
1855
+ console.error(`✓ connected to workspace ${cloud.workspace.name}`);
1856
+ track("brain_signup_settled", { outcome: "linked", mode: "connect", duration_bucket: durationBucket(0) }, { repo });
1857
+ }
1858
+ else if (got.reason === "invalid") {
1859
+ console.error(`✗ ${got.error} · get a new code at ${base}/welcome/code`);
1860
+ process.exitCode = 1;
1861
+ return;
1862
+ }
1863
+ else {
1864
+ console.error(offlineLine(got.error, base, code, cmd("graft init")));
1865
+ }
1866
+ const reporter = cloud ? new OnboardingReporter(cloud, ref, { machine }) : null;
1867
+ void reporter?.stage("connected");
1868
+ // What init learned this run, kept for the summary.
1869
+ const heard = { notes: [], sessions: 0 };
1870
+ const progress = reporter
1871
+ ? {
1872
+ mapped: (m) => void reporter.stage("mapped", m),
1873
+ learned: (l) => {
1874
+ Object.assign(heard, l);
1875
+ const team = learningsSummary(repo, l.notes);
1876
+ void reporter.stage("learned", { learnings: team.length, sessions: l.sessions || Math.max(0, ...team.map((t) => t.sessions)) });
1877
+ },
1878
+ }
1879
+ : undefined;
1880
+ // The page's command is pasted into a terminal, but an agent may run it for
1881
+ // them: with no terminal to pick in, wire the agents this machine has.
1882
+ const interactive = process.stdin.isTTY && process.stderr.isTTY;
1883
+ const res = await runInitCommand(dir, interactive ? opts : { ...opts, yes: true }, progress);
1884
+ if (!reporter || !cloud)
1885
+ return;
1886
+ if (!res) {
1887
+ await reporter.flush();
1888
+ return;
1889
+ }
1890
+ // What Trail found, for the page: route B, summaries only.
1891
+ const learnings = learningsSummary(repo, heard.notes);
1892
+ const sessions = heard.sessions || Math.max(0, ...learnings.map((l) => l.sessions));
1893
+ const tokens = tokensOnOneLookup(repo, { contextDir: program.opts().dir });
1894
+ const teamNotes = listNotes(repo, { branches: false }).filter((n) => n.scope === "repo" && !n.ref);
1895
+ const teammates = teammatesFromGit(repo, { learnings: teamNotes });
1896
+ const sent = await reporter.summary({ tokens, ...(sessions ? { sessions } : {}), learnings, teammates });
1897
+ await reporter.stage("done");
1898
+ await reporter.flush();
1899
+ // Claude Code gets the workspace's brains through one user-level `trail` entry.
1900
+ const brainsEntry = res.ids.includes("claude") && opts.global !== false ? installBrainsServer(homedir()) : null;
1901
+ if (sent) {
1902
+ const parts = [
1903
+ tokens ? `one lookup saved ${tokens.pct}% of the tokens` : null,
1904
+ `${learnings.length} learning${learnings.length === 1 ? "" : "s"}`,
1905
+ `${teammates.length} teammate branch${teammates.length === 1 ? "" : "es"} on your files`,
1906
+ ].filter(Boolean);
1907
+ console.error(`✓ sent ${cloud.workspace.name} a summary: ${parts.join(", ")} · titles, counts and names only, no code`);
1908
+ console.error(`· see what Trail found: ${base}/welcome/code/found`);
1909
+ }
1910
+ else {
1911
+ console.error(`· couldn't send the summary to Trail this time · with a new code from ${base}/welcome/code, ${connectAgain(cmd("graft init"), "<code>", base)} sends it again`);
1912
+ }
1913
+ if (brainsEntry?.action === "created" || brainsEntry?.action === "updated")
1914
+ console.error(`✓ Claude Code gets your workspace's brains in every project · restart it to pick them up`);
1915
+ }
1671
1916
  /** One repo's worth of `init` writes — the parent, then each workspace child. */
1672
1917
  function wireTarget(repo, ids, ctx) {
1673
1918
  const { home, cliPath, plan, wantClaude } = ctx;
@@ -1829,7 +2074,7 @@ function loginCommand(name = "login") {
1829
2074
  return new Command(name)
1830
2075
  .description("Connect this machine to a Trail workspace: sign in, pick the repos it gets, invite your team")
1831
2076
  .argument("[dir]", "the repo you're in, ticked first in the picker", ".")
1832
- .option("--server <url>", "a self-hosted Trail, e.g. https://trail.acme.internal (default: Trail cloud)")
2077
+ .option("--server <url>", "a self-hosted Trail, e.g. https://trail.acme.internal (default: Trail cloud, https://team.trailhq.com)")
1833
2078
  .action(async (dir, opts) => {
1834
2079
  const repo = resolve(dir);
1835
2080
  const server = opts.server?.trim().replace(/\/+$/, "");
@@ -1869,6 +2114,7 @@ function logoutCommand(name = "logout") {
1869
2114
  .action(() => {
1870
2115
  const cloud = readCloud();
1871
2116
  clearPending();
2117
+ removeBrainsServer(homedir());
1872
2118
  if (!clearCloud()) {
1873
2119
  console.error("· not connected to a workspace");
1874
2120
  return;
@@ -2250,6 +2496,9 @@ function statusCommand(name = "status") {
2250
2496
  if (cloudEnabled())
2251
2497
  row("workspace", "not connected · Claude offers a link once there are learnings to share");
2252
2498
  }
2499
+ else if (cloud.via === "connect") {
2500
+ row("workspace", `${cloud.workspace.name} · gets a summary of the repos you run ${cmd("graft init")} --connect in · ${cloud.workspace.url}`);
2501
+ }
2253
2502
  else
2254
2503
  row("workspace", `${cloud.workspace.name} · ${cloud.repos.length} repo${cloud.repos.length === 1 ? "" : "s"}${shared ? ", this one included" : `, not this one (${cmd("graft workspace add")})`} · ${cloud.workspace.url}`);
2255
2504
  row("this week", saved > 0 ? `~${shortCount(saved)} tokens saved` : "nothing saved yet");