@phnx-labs/agents-cli 1.22.39 → 1.22.40

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 (554) hide show
  1. package/CHANGELOG.md +294 -0
  2. package/README.md +111 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +45 -26
  5. package/dist/browser.js +2 -2
  6. package/dist/cli/command-registry.d.ts +135 -0
  7. package/dist/cli/command-registry.js +260 -0
  8. package/dist/commands/accounts.d.ts +20 -0
  9. package/dist/commands/accounts.js +186 -25
  10. package/dist/commands/apply.d.ts +3 -3
  11. package/dist/commands/apply.js +20 -63
  12. package/dist/commands/browser.js +206 -94
  13. package/dist/commands/budget.d.ts +7 -6
  14. package/dist/commands/budget.js +8 -7
  15. package/dist/commands/cloud.js +17 -20
  16. package/dist/commands/commands.js +1 -1
  17. package/dist/commands/computer-actions.d.ts +1 -35
  18. package/dist/commands/computer-actions.js +13 -181
  19. package/dist/commands/computer.d.ts +28 -3
  20. package/dist/commands/computer.js +93 -65
  21. package/dist/commands/config.js +16 -3
  22. package/dist/commands/cost.d.ts +2 -1
  23. package/dist/commands/cost.js +7 -6
  24. package/dist/commands/daemon.js +151 -4
  25. package/dist/commands/detach.js +1 -1
  26. package/dist/commands/doctor.js +19 -11
  27. package/dist/commands/events.js +1 -1
  28. package/dist/commands/exec.d.ts +2 -50
  29. package/dist/commands/exec.js +160 -215
  30. package/dist/commands/factory.js +1 -1
  31. package/dist/commands/feed.d.ts +2 -2
  32. package/dist/commands/feed.js +9 -12
  33. package/dist/commands/fleet-capture.js +25 -27
  34. package/dist/commands/focus.d.ts +2 -3
  35. package/dist/commands/focus.js +34 -9
  36. package/dist/commands/go.js +15 -5
  37. package/dist/commands/harness.d.ts +3 -3
  38. package/dist/commands/harness.js +53 -5
  39. package/dist/commands/hooks.js +1 -1
  40. package/dist/commands/import.js +2 -2
  41. package/dist/commands/insights.d.ts +5 -5
  42. package/dist/commands/insights.js +15 -9
  43. package/dist/commands/inspect.d.ts +2 -3
  44. package/dist/commands/inspect.js +4 -16
  45. package/dist/commands/logs.d.ts +2 -2
  46. package/dist/commands/logs.js +9 -9
  47. package/dist/commands/mcp.js +2 -2
  48. package/dist/commands/memory.js +1 -1
  49. package/dist/commands/message.d.ts +1 -1
  50. package/dist/commands/message.js +7 -7
  51. package/dist/commands/mine.d.ts +11 -8
  52. package/dist/commands/mine.js +11 -10
  53. package/dist/commands/models.js +1 -1
  54. package/dist/commands/modes.js +1 -1
  55. package/dist/commands/monitors.js +23 -6
  56. package/dist/commands/output.d.ts +7 -6
  57. package/dist/commands/output.js +11 -10
  58. package/dist/commands/packages.js +4 -4
  59. package/dist/commands/perf.js +1 -1
  60. package/dist/commands/permissions.js +49 -32
  61. package/dist/commands/plugins.d.ts +1 -1
  62. package/dist/commands/plugins.js +3 -3
  63. package/dist/commands/profiles.d.ts +6 -9
  64. package/dist/commands/profiles.js +8 -321
  65. package/dist/commands/projects.d.ts +9 -0
  66. package/dist/commands/projects.js +140 -8
  67. package/dist/commands/prune.js +5 -13
  68. package/dist/commands/refresh-rules.js +1 -1
  69. package/dist/commands/repo.d.ts +5 -7
  70. package/dist/commands/repo.js +34 -18
  71. package/dist/commands/resource-view.js +4 -0
  72. package/dist/commands/resume.d.ts +11 -7
  73. package/dist/commands/resume.js +82 -98
  74. package/dist/commands/route.d.ts +12 -0
  75. package/dist/commands/route.js +261 -0
  76. package/dist/commands/routines.d.ts +2 -3
  77. package/dist/commands/routines.js +120 -145
  78. package/dist/commands/rules.js +1 -1
  79. package/dist/commands/run-account-picker.d.ts +1 -1
  80. package/dist/commands/run-account-picker.js +2 -2
  81. package/dist/commands/run-broadcast.d.ts +21 -0
  82. package/dist/commands/run-broadcast.js +89 -0
  83. package/dist/commands/run-cloud.js +1 -1
  84. package/dist/commands/secrets-vault.d.ts +10 -0
  85. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  86. package/dist/commands/secrets.d.ts +4 -4
  87. package/dist/commands/secrets.js +72 -63
  88. package/dist/commands/sessions-backfill.js +1 -1
  89. package/dist/commands/sessions-browser.d.ts +1 -1
  90. package/dist/commands/sessions-browser.js +9 -5
  91. package/dist/commands/sessions-export.js +2 -2
  92. package/dist/commands/sessions-inject.js +4 -5
  93. package/dist/commands/sessions-migrate.js +16 -27
  94. package/dist/commands/sessions-picker.d.ts +13 -0
  95. package/dist/commands/sessions-picker.js +182 -8
  96. package/dist/commands/sessions-resume.d.ts +7 -3
  97. package/dist/commands/sessions-resume.js +81 -33
  98. package/dist/commands/sessions-stats.js +2 -2
  99. package/dist/commands/sessions.d.ts +75 -68
  100. package/dist/commands/sessions.js +142 -180
  101. package/dist/commands/setup-computer.js +1 -1
  102. package/dist/commands/setup-fleet.js +3 -0
  103. package/dist/commands/setup-mine.d.ts +7 -3
  104. package/dist/commands/setup-mine.js +13 -8
  105. package/dist/commands/setup-secrets.js +2 -2
  106. package/dist/commands/setup-watchdog.js +2 -2
  107. package/dist/commands/setup.js +7 -2
  108. package/dist/commands/share.d.ts +65 -0
  109. package/dist/commands/share.js +253 -20
  110. package/dist/commands/skills.js +3 -3
  111. package/dist/commands/snapshot.d.ts +2 -2
  112. package/dist/commands/snapshot.js +9 -9
  113. package/dist/commands/ssh.d.ts +1 -1
  114. package/dist/commands/ssh.js +186 -64
  115. package/dist/commands/subagents.js +1 -1
  116. package/dist/commands/sync.js +24 -9
  117. package/dist/commands/teams.d.ts +2 -2
  118. package/dist/commands/teams.js +9 -18
  119. package/dist/commands/tmux.js +5 -1
  120. package/dist/commands/trash.js +1 -1
  121. package/dist/commands/usage.d.ts +1 -1
  122. package/dist/commands/usage.js +2 -2
  123. package/dist/commands/utils.d.ts +4 -14
  124. package/dist/commands/utils.js +6 -27
  125. package/dist/commands/versions.js +2 -2
  126. package/dist/commands/view.d.ts +9 -77
  127. package/dist/commands/view.js +23 -8
  128. package/dist/commands/watchdog.js +1 -1
  129. package/dist/commands/webhook.js +11 -25
  130. package/dist/commands/workflows.js +1 -1
  131. package/dist/index.js +1 -1
  132. package/dist/lib/account-capabilities.d.ts +39 -0
  133. package/dist/lib/account-capabilities.js +59 -0
  134. package/dist/lib/account-catalog.js +1 -1
  135. package/dist/lib/account-registry.d.ts +66 -0
  136. package/dist/lib/account-registry.js +151 -5
  137. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  138. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  139. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  140. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  141. package/dist/lib/agent-spec/provider.js +1 -1
  142. package/dist/lib/agents.d.ts +72 -4
  143. package/dist/lib/agents.js +231 -199
  144. package/dist/lib/answer-router.d.ts +2 -2
  145. package/dist/lib/ask-classifier.d.ts +1 -1
  146. package/dist/lib/ask-classifier.js +1 -1
  147. package/dist/lib/audit/log.js +1 -1
  148. package/dist/lib/auth-health.d.ts +1 -1
  149. package/dist/lib/auth-health.js +2 -2
  150. package/dist/lib/brand.js +1 -1
  151. package/dist/lib/browser/caller-identity.d.ts +28 -0
  152. package/dist/lib/browser/caller-identity.js +156 -0
  153. package/dist/lib/browser/cdp.js +1 -1
  154. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  155. package/dist/lib/browser/drivers/ssh.js +2 -2
  156. package/dist/lib/browser/hygiene.d.ts +10 -2
  157. package/dist/lib/browser/hygiene.js +7 -4
  158. package/dist/lib/browser/ipc.d.ts +22 -2
  159. package/dist/lib/browser/ipc.js +185 -21
  160. package/dist/lib/browser/profiles.d.ts +67 -3
  161. package/dist/lib/browser/profiles.js +129 -7
  162. package/dist/lib/browser/remote-control.d.ts +2 -2
  163. package/dist/lib/browser/remote-control.js +3 -3
  164. package/dist/lib/browser/runtime-state.d.ts +79 -0
  165. package/dist/lib/browser/runtime-state.js +119 -1
  166. package/dist/lib/browser/service.d.ts +113 -1
  167. package/dist/lib/browser/service.js +454 -40
  168. package/dist/lib/browser/sessions-list.d.ts +2 -1
  169. package/dist/lib/browser/sessions-list.js +4 -13
  170. package/dist/lib/browser/types.d.ts +18 -0
  171. package/dist/lib/budget/config.js +1 -1
  172. package/dist/lib/budget/ledger.js +1 -1
  173. package/dist/lib/byok-usage.js +1 -1
  174. package/dist/lib/capabilities.js +3 -15
  175. package/dist/lib/catchup.d.ts +1 -1
  176. package/dist/lib/catchup.js +1 -1
  177. package/dist/lib/cloud/dispatch.js +1 -1
  178. package/dist/lib/cloud/host.d.ts +3 -3
  179. package/dist/lib/cloud/host.js +5 -5
  180. package/dist/lib/cloud/rush.d.ts +9 -21
  181. package/dist/lib/cloud/rush.js +33 -120
  182. package/dist/lib/cloud/types.d.ts +2 -2
  183. package/dist/lib/commands.js +3 -13
  184. package/dist/lib/computer/actions.d.ts +36 -0
  185. package/dist/lib/computer/actions.js +162 -0
  186. package/dist/lib/computer/dispatch.d.ts +2 -2
  187. package/dist/lib/computer/dispatch.js +2 -2
  188. package/dist/lib/computer/sessions-list.d.ts +3 -3
  189. package/dist/lib/computer/sessions-list.js +2 -2
  190. package/dist/lib/config-keys.d.ts +2 -1
  191. package/dist/lib/config-keys.js +8 -4
  192. package/dist/lib/config-machine-keys.d.ts +4 -2
  193. package/dist/lib/config-machine-keys.js +5 -2
  194. package/dist/lib/crabbox/lease.js +9 -1
  195. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  196. package/dist/lib/crabbox/runtimes.js +72 -30
  197. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  198. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  199. package/dist/lib/daemon-services.d.ts +1 -1
  200. package/dist/lib/daemon-services.js +5 -0
  201. package/dist/lib/daemon-ticks.d.ts +25 -0
  202. package/dist/lib/daemon-ticks.js +31 -1
  203. package/dist/lib/daemon-webhooks.d.ts +102 -0
  204. package/dist/lib/daemon-webhooks.js +210 -0
  205. package/dist/lib/device-config.d.ts +85 -75
  206. package/dist/lib/device-config.js +279 -141
  207. package/dist/lib/devices/config-migration.d.ts +29 -34
  208. package/dist/lib/devices/config-migration.js +209 -130
  209. package/dist/lib/devices/connect.d.ts +2 -2
  210. package/dist/lib/devices/connect.js +2 -2
  211. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  212. package/dist/lib/devices/discovery-policy.js +101 -0
  213. package/dist/lib/devices/fleet-inventory.js +8 -3
  214. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  215. package/dist/lib/devices/harness-inventory.js +12 -3
  216. package/dist/lib/devices/known-hosts.js +1 -1
  217. package/dist/lib/devices/pool.d.ts +10 -5
  218. package/dist/lib/devices/pool.js +5 -7
  219. package/dist/lib/devices/registry.d.ts +1 -1
  220. package/dist/lib/devices/registry.js +1 -1
  221. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  222. package/dist/lib/devices/resolve-profile.js +2 -2
  223. package/dist/lib/devices/resolve-target.d.ts +1 -1
  224. package/dist/lib/devices/resolve-target.js +4 -4
  225. package/dist/lib/devices/self-host.d.ts +1 -1
  226. package/dist/lib/devices/self-host.js +3 -3
  227. package/dist/lib/devices/ssh-config.d.ts +1 -1
  228. package/dist/lib/devices/stats-cache.js +1 -1
  229. package/dist/lib/devices/sync.d.ts +3 -1
  230. package/dist/lib/devices/sync.js +3 -3
  231. package/dist/lib/doctor-diff.js +4 -4
  232. package/dist/lib/drift-sync.js +2 -2
  233. package/dist/lib/drift.js +2 -2
  234. package/dist/lib/event-families.d.ts +1 -1
  235. package/dist/lib/event-stream.d.ts +1 -1
  236. package/dist/lib/event-stream.js +2 -2
  237. package/dist/lib/events-ingest.js +2 -2
  238. package/dist/lib/exec.d.ts +4 -4
  239. package/dist/lib/exec.js +11 -11
  240. package/dist/lib/factory/snapshot.d.ts +1 -1
  241. package/dist/lib/factory/snapshot.js +1 -1
  242. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  243. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  244. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  245. package/dist/lib/{events.js → feed/events.js} +5 -5
  246. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  247. package/dist/lib/feed-outcome.d.ts +1 -1
  248. package/dist/lib/feed-policy.d.ts +1 -1
  249. package/dist/lib/feed-policy.js +1 -1
  250. package/dist/lib/feed-post.d.ts +1 -1
  251. package/dist/lib/feed-post.js +1 -1
  252. package/dist/lib/feed-ranking.d.ts +1 -1
  253. package/dist/lib/fleet/apply.d.ts +0 -6
  254. package/dist/lib/fleet/apply.js +18 -45
  255. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  256. package/dist/lib/fleet/auth-sync.js +16 -75
  257. package/dist/lib/fleet/capture.js +8 -6
  258. package/dist/lib/fleet/manifest.js +23 -11
  259. package/dist/lib/fleet/types.d.ts +19 -7
  260. package/dist/lib/fleet-cache.d.ts +1 -1
  261. package/dist/lib/fleet-cache.js +1 -1
  262. package/dist/lib/format.d.ts +19 -0
  263. package/dist/lib/format.js +44 -1
  264. package/dist/lib/friction-heuristics.d.ts +1 -1
  265. package/dist/lib/git.d.ts +24 -1
  266. package/dist/lib/git.js +82 -38
  267. package/dist/lib/heal.js +3 -3
  268. package/dist/lib/hooks.d.ts +18 -0
  269. package/dist/lib/hooks.js +113 -1
  270. package/dist/lib/hosts/credentials.d.ts +30 -10
  271. package/dist/lib/hosts/credentials.js +38 -26
  272. package/dist/lib/hosts/dispatch.d.ts +3 -3
  273. package/dist/lib/hosts/dispatch.js +3 -3
  274. package/dist/lib/hosts/option.d.ts +3 -3
  275. package/dist/lib/hosts/option.js +7 -8
  276. package/dist/lib/hosts/passthrough.d.ts +17 -17
  277. package/dist/lib/hosts/passthrough.js +67 -50
  278. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  279. package/dist/lib/hosts/providers/devices.js +1 -1
  280. package/dist/lib/hosts/reconcile.d.ts +1 -1
  281. package/dist/lib/hosts/reconcile.js +1 -1
  282. package/dist/lib/hosts/reconnect.d.ts +1 -1
  283. package/dist/lib/hosts/reconnect.js +2 -2
  284. package/dist/lib/hosts/registry.d.ts +5 -5
  285. package/dist/lib/hosts/registry.js +5 -5
  286. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  287. package/dist/lib/hosts/remote-cmd.js +25 -18
  288. package/dist/lib/hosts/remote-os.d.ts +4 -4
  289. package/dist/lib/hosts/remote-os.js +4 -4
  290. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  291. package/dist/lib/hosts/remote-session-id.js +2 -2
  292. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  293. package/dist/lib/hosts/routing-flag.js +4 -5
  294. package/dist/lib/hosts/run-target.d.ts +4 -4
  295. package/dist/lib/hosts/run-target.js +4 -4
  296. package/dist/lib/hosts/session-index.d.ts +2 -2
  297. package/dist/lib/hosts/session-index.js +1 -1
  298. package/dist/lib/hosts/session-marker.d.ts +1 -1
  299. package/dist/lib/hosts/session-marker.js +1 -1
  300. package/dist/lib/hosts/types.d.ts +2 -2
  301. package/dist/lib/hosts/types.js +2 -2
  302. package/dist/lib/import.js +1 -1
  303. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +13 -1
  304. package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
  305. package/dist/lib/installations/resolve.js +1 -1
  306. package/dist/lib/installations/strategies.js +1 -1
  307. package/dist/lib/installations/update.js +2 -2
  308. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  309. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  310. package/dist/lib/isolation-boundary-report.js +1 -1
  311. package/dist/lib/linear-projects.d.ts +28 -0
  312. package/dist/lib/linear-projects.js +30 -0
  313. package/dist/lib/loop.js +1 -1
  314. package/dist/lib/mailbox-gc.js +1 -1
  315. package/dist/lib/mailbox.js +1 -1
  316. package/dist/lib/mcp-registry.d.ts +62 -0
  317. package/dist/lib/mcp-registry.js +177 -0
  318. package/dist/lib/mcp.d.ts +5 -0
  319. package/dist/lib/mcp.js +124 -307
  320. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  321. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  322. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  323. package/dist/lib/menubar/install-menubar.js +24 -6
  324. package/dist/lib/menubar/snapshot.d.ts +7 -0
  325. package/dist/lib/menubar/snapshot.js +8 -6
  326. package/dist/lib/models.js +1 -1
  327. package/dist/lib/monitors/config.d.ts +12 -0
  328. package/dist/lib/monitors/config.js +3 -0
  329. package/dist/lib/monitors/dispatch.js +26 -5
  330. package/dist/lib/monitors/engine.js +10 -0
  331. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  332. package/dist/lib/monitors/state.d.ts +42 -0
  333. package/dist/lib/monitors/state.js +30 -0
  334. package/dist/lib/notify.d.ts +1 -1
  335. package/dist/lib/observe-aliases.d.ts +2 -2
  336. package/dist/lib/observe-aliases.js +2 -11
  337. package/dist/lib/output/git-output.js +2 -2
  338. package/dist/lib/overdue.d.ts +1 -1
  339. package/dist/lib/overdue.js +1 -1
  340. package/dist/lib/permissions-registry.d.ts +65 -0
  341. package/dist/lib/permissions-registry.js +599 -0
  342. package/dist/lib/permissions.d.ts +24 -13
  343. package/dist/lib/permissions.js +52 -271
  344. package/dist/lib/picker.d.ts +16 -0
  345. package/dist/lib/picker.js +33 -3
  346. package/dist/lib/placement.d.ts +1 -1
  347. package/dist/lib/placement.js +4 -4
  348. package/dist/lib/platform/paths.d.ts +8 -0
  349. package/dist/lib/platform/paths.js +11 -0
  350. package/dist/lib/platform/posixpath.js +3 -3
  351. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  352. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  353. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  354. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  355. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  356. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  357. package/dist/lib/pricing/cost.d.ts +1 -1
  358. package/dist/lib/pricing/cost.js +1 -1
  359. package/dist/lib/profiles-presets.d.ts +1 -1
  360. package/dist/lib/profiles-presets.js +1 -1
  361. package/dist/lib/profiles.js +2 -2
  362. package/dist/lib/project-import.js +4 -1
  363. package/dist/lib/project-launch.d.ts +1 -1
  364. package/dist/lib/project-launch.js +3 -3
  365. package/dist/lib/project-pull.d.ts +128 -0
  366. package/dist/lib/project-pull.js +384 -0
  367. package/dist/lib/project-root.d.ts +2 -2
  368. package/dist/lib/project-root.js +2 -2
  369. package/dist/lib/project-status.js +1 -1
  370. package/dist/lib/projects.d.ts +23 -0
  371. package/dist/lib/projects.js +29 -6
  372. package/dist/lib/refresh.d.ts +12 -1
  373. package/dist/lib/refresh.js +16 -9
  374. package/dist/lib/registry.d.ts +9 -2
  375. package/dist/lib/registry.js +11 -4
  376. package/dist/lib/resources.d.ts +2 -2
  377. package/dist/lib/resources.js +2 -2
  378. package/dist/lib/routers.d.ts +81 -0
  379. package/dist/lib/routers.js +153 -0
  380. package/dist/lib/routine-context.d.ts +1 -0
  381. package/dist/lib/routine-context.js +7 -2
  382. package/dist/lib/routine-notify-owner.d.ts +1 -1
  383. package/dist/lib/routine-notify.d.ts +1 -1
  384. package/dist/lib/routine-notify.js +1 -1
  385. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  386. package/dist/lib/routine-readiness.d.ts +1 -1
  387. package/dist/lib/routine-readiness.js +11 -4
  388. package/dist/lib/routines-placement.d.ts +12 -2
  389. package/dist/lib/routines-placement.js +20 -3
  390. package/dist/lib/routines-project.d.ts +1 -1
  391. package/dist/lib/routines-project.js +1 -1
  392. package/dist/lib/rules/compile.d.ts +1 -0
  393. package/dist/lib/rules/compile.js +10 -2
  394. package/dist/lib/rules/rules.js +1 -1
  395. package/dist/lib/run-notify.js +1 -1
  396. package/dist/lib/runner.d.ts +80 -2
  397. package/dist/lib/runner.js +241 -62
  398. package/dist/lib/sandbox.d.ts +1 -1
  399. package/dist/lib/scheduler.d.ts +1 -1
  400. package/dist/lib/scheduler.js +1 -1
  401. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  402. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  403. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  404. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  405. package/dist/lib/secrets/agent.js +2 -2
  406. package/dist/lib/secrets/audit.js +1 -1
  407. package/dist/lib/secrets/bundles.d.ts +3 -3
  408. package/dist/lib/secrets/bundles.js +7 -7
  409. package/dist/lib/secrets/index.js +1 -1
  410. package/dist/lib/secrets/list-filter.d.ts +1 -1
  411. package/dist/lib/secrets/list-filter.js +2 -2
  412. package/dist/lib/secrets/push.d.ts +1 -1
  413. package/dist/lib/secrets/push.js +10 -12
  414. package/dist/lib/secrets/remote.d.ts +12 -10
  415. package/dist/lib/secrets/remote.js +21 -14
  416. package/dist/lib/secrets/vault.js +2 -2
  417. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  418. package/dist/lib/self-heal/checks/shims.js +1 -1
  419. package/dist/lib/self-update.d.ts +39 -4
  420. package/dist/lib/self-update.js +78 -25
  421. package/dist/lib/serve/control.d.ts +1 -1
  422. package/dist/lib/serve/control.js +4 -4
  423. package/dist/lib/serve/data.d.ts +1 -1
  424. package/dist/lib/serve/data.js +1 -1
  425. package/dist/lib/serve/stream.js +1 -1
  426. package/dist/lib/service-manifest.d.ts +29 -0
  427. package/dist/lib/service-manifest.js +80 -0
  428. package/dist/lib/session/active.d.ts +59 -7
  429. package/dist/lib/session/active.js +158 -17
  430. package/dist/lib/session/bash-command.js +1 -1
  431. package/dist/lib/session/claude-accounts.d.ts +1 -1
  432. package/dist/lib/session/claude-accounts.js +1 -1
  433. package/dist/lib/session/db.d.ts +10 -2
  434. package/dist/lib/session/db.js +25 -6
  435. package/dist/lib/session/discover.d.ts +77 -0
  436. package/dist/lib/session/discover.js +130 -25
  437. package/dist/lib/session/fork.js +1 -1
  438. package/dist/lib/session/inject.d.ts +1 -1
  439. package/dist/lib/session/insights.d.ts +1 -1
  440. package/dist/lib/session/insights.js +1 -1
  441. package/dist/lib/session/live-metadata.d.ts +15 -0
  442. package/dist/lib/session/live-metadata.js +76 -0
  443. package/dist/lib/session/migrate-targets.d.ts +1 -1
  444. package/dist/lib/session/recovery.d.ts +1 -1
  445. package/dist/lib/session/recovery.js +2 -2
  446. package/dist/lib/session/remote-active.d.ts +10 -1
  447. package/dist/lib/session/remote-active.js +8 -3
  448. package/dist/lib/session/remote-bundle.d.ts +1 -1
  449. package/dist/lib/session/remote-bundle.js +2 -2
  450. package/dist/lib/session/remote-list.d.ts +15 -4
  451. package/dist/lib/session/remote-list.js +40 -3
  452. package/dist/lib/session/remote.d.ts +5 -5
  453. package/dist/lib/session/remote.js +13 -17
  454. package/dist/lib/session/resume-command.d.ts +3 -2
  455. package/dist/lib/session/resume-command.js +4 -3
  456. package/dist/lib/session/resume-owner.d.ts +3 -3
  457. package/dist/lib/session/resume-owner.js +3 -3
  458. package/dist/lib/session/session-cache.d.ts +12 -0
  459. package/dist/lib/session/session-cache.js +2 -0
  460. package/dist/lib/session/shell-programs.js +1 -1
  461. package/dist/lib/session/state.js +5 -5
  462. package/dist/lib/session/team-filter.d.ts +1 -1
  463. package/dist/lib/session/team-filter.js +1 -1
  464. package/dist/lib/session/types.d.ts +3 -3
  465. package/dist/lib/session/width.d.ts +2 -2
  466. package/dist/lib/session/width.js +2 -2
  467. package/dist/lib/share/delete.d.ts +21 -0
  468. package/dist/lib/share/delete.js +42 -0
  469. package/dist/lib/share/publish.d.ts +82 -0
  470. package/dist/lib/share/publish.js +170 -18
  471. package/dist/lib/share/worker-template.js +172 -9
  472. package/dist/lib/shims.js +35 -7
  473. package/dist/lib/smart-launch.d.ts +4 -4
  474. package/dist/lib/smart-launch.js +6 -4
  475. package/dist/lib/snapshot.d.ts +4 -4
  476. package/dist/lib/snapshot.js +2 -2
  477. package/dist/lib/ssh-exec.d.ts +1 -1
  478. package/dist/lib/ssh-exec.js +2 -2
  479. package/dist/lib/ssh-tunnel.d.ts +10 -10
  480. package/dist/lib/ssh-tunnel.js +12 -12
  481. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  482. package/dist/lib/staleness/checkers/hooks.js +1 -1
  483. package/dist/lib/staleness/detectors/permissions.js +0 -23
  484. package/dist/lib/staleness/detectors/plugins.js +1 -1
  485. package/dist/lib/staleness/fingerprint.js +1 -1
  486. package/dist/lib/staleness/layers.d.ts +1 -1
  487. package/dist/lib/staleness/layers.js +1 -1
  488. package/dist/lib/staleness/writers/mcp.js +3 -1
  489. package/dist/lib/staleness/writers/plugins.js +1 -1
  490. package/dist/lib/staleness/writers/types.d.ts +8 -0
  491. package/dist/lib/startup/command-registry.d.ts +5 -147
  492. package/dist/lib/startup/command-registry.js +38 -303
  493. package/dist/lib/startup/dev-build.d.ts +0 -21
  494. package/dist/lib/startup/dev-build.js +29 -8
  495. package/dist/lib/state.d.ts +19 -1
  496. package/dist/lib/state.js +120 -51
  497. package/dist/lib/subagents.js +1 -1
  498. package/dist/lib/sync-status.js +1 -1
  499. package/dist/lib/sync-umbrella.d.ts +6 -1
  500. package/dist/lib/sync-umbrella.js +9 -4
  501. package/dist/lib/teams/agents.js +2 -2
  502. package/dist/lib/teams/registry.js +1 -1
  503. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  504. package/dist/lib/terminal/engine.js +1 -1
  505. package/dist/lib/terminal/index.d.ts +4 -0
  506. package/dist/lib/terminal/index.js +3 -0
  507. package/dist/lib/terminal/inject.d.ts +2 -2
  508. package/dist/lib/terminal/inject.js +2 -2
  509. package/dist/lib/terminal/transport.js +1 -1
  510. package/dist/lib/tmux/index.d.ts +1 -1
  511. package/dist/lib/tmux/index.js +1 -1
  512. package/dist/lib/tmux/session.d.ts +21 -5
  513. package/dist/lib/tmux/session.js +76 -22
  514. package/dist/lib/triggers/handlers.d.ts +1 -1
  515. package/dist/lib/triggers/handlers.js +2 -2
  516. package/dist/lib/triggers/webhook.d.ts +36 -2
  517. package/dist/lib/triggers/webhook.js +97 -42
  518. package/dist/lib/types.d.ts +18 -6
  519. package/dist/lib/usage-fleet.d.ts +1 -1
  520. package/dist/lib/usage-fleet.js +1 -1
  521. package/dist/lib/usage-refresh.d.ts +1 -1
  522. package/dist/lib/usage-refresh.js +3 -3
  523. package/dist/lib/version-duplicates.js +2 -2
  524. package/dist/lib/view-types.d.ts +56 -0
  525. package/dist/lib/view-types.js +1 -0
  526. package/dist/lib/watchdog/rotate.d.ts +2 -2
  527. package/dist/lib/watchdog/rotate.js +3 -3
  528. package/dist/lib/watchdog/runner.d.ts +2 -3
  529. package/dist/lib/watchdog/runner.js +3 -4
  530. package/dist/lib/workflows.js +1 -1
  531. package/package.json +2 -1
  532. package/scripts/postinstall.js +2 -2
  533. package/dist/commands/bench.d.ts +0 -2
  534. package/dist/commands/bench.js +0 -101
  535. package/dist/commands/cp.d.ts +0 -84
  536. package/dist/commands/cp.js +0 -231
  537. package/dist/commands/login.d.ts +0 -2
  538. package/dist/lib/resources/commands.d.ts +0 -46
  539. package/dist/lib/resources/commands.js +0 -211
  540. package/dist/lib/resources/hooks.d.ts +0 -16
  541. package/dist/lib/resources/hooks.js +0 -153
  542. package/dist/lib/resources/mcp.d.ts +0 -34
  543. package/dist/lib/resources/mcp.js +0 -250
  544. package/dist/lib/resources/memory.d.ts +0 -15
  545. package/dist/lib/resources/memory.js +0 -46
  546. package/dist/lib/resources/permissions.d.ts +0 -13
  547. package/dist/lib/resources/permissions.js +0 -202
  548. package/dist/lib/resources/rules.d.ts +0 -46
  549. package/dist/lib/resources/rules.js +0 -179
  550. package/dist/lib/resources/skills.d.ts +0 -37
  551. package/dist/lib/resources/skills.js +0 -247
  552. package/dist/lib/resources/subagents.d.ts +0 -46
  553. package/dist/lib/resources/subagents.js +0 -202
  554. /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
@@ -6,7 +6,7 @@
6
6
  * yet. This is a starting point: one detector for the most actionable pattern,
7
7
  * an agent stuck retrying the SAME denied action instead of adapting.
8
8
  */
9
- import type { EventRecord } from './events.js';
9
+ import type { EventRecord } from './feed/events.js';
10
10
  export interface RepeatedGuardBlockFinding {
11
11
  /** Session id the repeated blocks happened in, or 'unknown' when the
12
12
  * friction event carried no session (e.g. a guard fired outside any
package/dist/lib/git.d.ts CHANGED
@@ -207,6 +207,10 @@ export declare function isGitRepo(dir: string): boolean;
207
207
  * Shells out to `git rev-parse --show-toplevel`, so it resolves correctly from
208
208
  * any subdirectory and for linked worktrees (unlike the root-only, synchronous
209
209
  * {@link isGitRepo} above). Throws if `dir` is not inside a git repository.
210
+ *
211
+ * Git prints POSIX separators even on Windows (`C:/Users/...`); we fold them to
212
+ * the native separator so the result is a real filesystem path that compares
213
+ * equal to one built with `path.*`. On POSIX this is a no-op.
210
214
  */
211
215
  export declare function getGitRoot(dir: string): Promise<string>;
212
216
  /**
@@ -216,6 +220,10 @@ export declare function getGitRoot(dir: string): Promise<string>;
216
220
  * worktree: `--show-toplevel` there returns the worktree's own path, but the
217
221
  * common git dir (`--git-common-dir`) always points at the primary repo's
218
222
  * `.git`, whose parent is the main checkout. Throws if `dir` is not in a repo.
223
+ *
224
+ * Git prints POSIX separators even on Windows (`C:/Users/...`); we fold them to
225
+ * the native separator so the result is a real filesystem path that compares
226
+ * equal to one built with `path.*`. On POSIX this is a no-op.
219
227
  */
220
228
  export declare function getMainRepoRoot(dir: string): Promise<string>;
221
229
  /**
@@ -281,7 +289,22 @@ export declare function displayHomePath(dir: string): string;
281
289
  * 3. Genuinely diverged (local commits not on tracking) → `rebase` onto the
282
290
  * tracking ref (same outcome as {@link syncRepoGit}, without a second pull).
283
291
  */
284
- export declare function pullRepo(dir: string): Promise<{
292
+ export interface PullRepoOptions {
293
+ /**
294
+ * `'default-branch-fast-forward'` — strict mode for `projects pull`:
295
+ * - Blocks immediately if the tree is dirty (no remote read needed).
296
+ * - Fetches origin, resolves the remote default branch, and refuses if the
297
+ * current branch is not the remote default.
298
+ * - Refuses if HEAD is ahead of the upstream (local commits not on remote).
299
+ * - Fast-forwards only (`merge --ff-only`). NEVER rebases.
300
+ * - NEVER installs git hook symlinks (read-only model path).
301
+ *
302
+ * `'preserve-local'` (default) — the existing behavior: tolerates dirty trees
303
+ * when the incoming diff does not collide, and rebases a diverged branch.
304
+ */
305
+ mode?: 'preserve-local' | 'default-branch-fast-forward';
306
+ }
307
+ export declare function pullRepo(dir: string, options?: PullRepoOptions): Promise<{
285
308
  success: boolean;
286
309
  commit: string;
287
310
  error?: string;
package/dist/lib/git.js CHANGED
@@ -10,7 +10,7 @@ import { execFileSync } from 'node:child_process';
10
10
  import * as fs from 'fs';
11
11
  import * as os from 'os';
12
12
  import * as path from 'path';
13
- import { IS_WINDOWS, isWindowsAbsolutePath } from './platform/index.js';
13
+ import { IS_WINDOWS, isWindowsAbsolutePath, toNativePath } from './platform/index.js';
14
14
  import { getPackageLocalPath } from './state.js';
15
15
  import { DEFAULT_SYSTEM_REPO, systemRepoSlug } from './types.js';
16
16
  /**
@@ -658,10 +658,14 @@ export function isGitRepo(dir) {
658
658
  * Shells out to `git rev-parse --show-toplevel`, so it resolves correctly from
659
659
  * any subdirectory and for linked worktrees (unlike the root-only, synchronous
660
660
  * {@link isGitRepo} above). Throws if `dir` is not inside a git repository.
661
+ *
662
+ * Git prints POSIX separators even on Windows (`C:/Users/...`); we fold them to
663
+ * the native separator so the result is a real filesystem path that compares
664
+ * equal to one built with `path.*`. On POSIX this is a no-op.
661
665
  */
662
666
  export async function getGitRoot(dir) {
663
667
  const root = await simpleGit(dir).revparse(['--show-toplevel']);
664
- return root.trim();
668
+ return toNativePath(root.trim());
665
669
  }
666
670
  /**
667
671
  * Return the absolute path to the **main** working-tree root for `dir`.
@@ -670,10 +674,14 @@ export async function getGitRoot(dir) {
670
674
  * worktree: `--show-toplevel` there returns the worktree's own path, but the
671
675
  * common git dir (`--git-common-dir`) always points at the primary repo's
672
676
  * `.git`, whose parent is the main checkout. Throws if `dir` is not in a repo.
677
+ *
678
+ * Git prints POSIX separators even on Windows (`C:/Users/...`); we fold them to
679
+ * the native separator so the result is a real filesystem path that compares
680
+ * equal to one built with `path.*`. On POSIX this is a no-op.
673
681
  */
674
682
  export async function getMainRepoRoot(dir) {
675
683
  const common = await simpleGit(dir).raw(['rev-parse', '--path-format=absolute', '--git-common-dir']);
676
- return path.dirname(common.trim());
684
+ return toNativePath(path.dirname(common.trim()));
677
685
  }
678
686
  /**
679
687
  * Initialize a git repo in an existing directory.
@@ -863,23 +871,8 @@ export function displayHomePath(dir) {
863
871
  const rel = dir.startsWith(home) ? '~' + dir.slice(home.length) : dir;
864
872
  return rel.replace(/\\/g, '/');
865
873
  }
866
- /**
867
- * Pull changes in an existing repo.
868
- * A dirty working tree no longer refuses outright: a fast-forward that touches
869
- * no uncommitted path still runs (see `dirtyTreeRefusal`). It refuses when the
870
- * branch has local commits to rebase, or when an incoming path is also dirty.
871
- *
872
- * Strategy (RUSH-2282):
873
- * 1. Fetch, then compare HEAD to the resolved tracking ref.
874
- * 2. Clean behind-only (HEAD is an ancestor of tracking) → `merge --ff-only`
875
- * against the tracking ref. Never re-enter `git pull` after a bare fetch —
876
- * multi-entry FETCH_HEAD (concurrent fetch, multi-branch remote) makes
877
- * `git pull --rebase` die with "Cannot rebase onto multiple branches" even
878
- * when the checkout is a pure fast-forward.
879
- * 3. Genuinely diverged (local commits not on tracking) → `rebase` onto the
880
- * tracking ref (same outcome as {@link syncRepoGit}, without a second pull).
881
- */
882
- export async function pullRepo(dir) {
874
+ export async function pullRepo(dir, options = {}) {
875
+ const strict = options.mode === 'default-branch-fast-forward';
883
876
  try {
884
877
  const git = simpleGit(dir);
885
878
  // A rebase left in progress by an earlier run must be reported as itself.
@@ -916,14 +909,24 @@ export async function pullRepo(dir) {
916
909
  };
917
910
  }
918
911
  const status = await git.status();
912
+ // Strict mode (projects pull): refuse a dirty tree immediately — no fetch
913
+ // needed to know the answer, and the caller must not risk touching staged
914
+ // or modified files with an incoming fast-forward.
915
+ const isDirty = !status.isClean();
916
+ if (strict && isDirty) {
917
+ return {
918
+ success: false,
919
+ commit: '',
920
+ error: `Blocked: dirty working tree. Commit or discard local changes before pulling.\n\n cd ${displayHomePath(dir)} && git status`,
921
+ };
922
+ }
919
923
  // A dirty tree is not decided here: whether a fast-forward is safe depends
920
924
  // on what is actually incoming, and that needs a fetched upstream ref. The
921
925
  // gate therefore sits just before the integrate step below. The exception is
922
926
  // a repo with no remote at all — there is nothing to fast-forward from, so
923
927
  // the dirt is the whole answer and the resolution below would only fail
924
928
  // with a less useful message.
925
- const isDirty = !status.isClean();
926
- if (isDirty && (await git.getRemotes()).length === 0) {
929
+ if (!strict && isDirty && (await git.getRemotes()).length === 0) {
927
930
  return {
928
931
  success: false,
929
932
  commit: '',
@@ -931,13 +934,13 @@ export async function pullRepo(dir) {
931
934
  };
932
935
  }
933
936
  const branch = status.current || 'main';
934
- // Resolve the upstream ref to fast-forward against. Prefer the local
935
- // branch's tracking config; otherwise ask origin for its default branch.
937
+ // Resolve the upstream ref to fast-forward against.
938
+ // Strict mode: always fetch origin and resolve its default branch — then
939
+ // verify the current branch IS the remote default (refuse otherwise).
940
+ // Preserve-local mode: prefer the local branch's tracking config; only
941
+ // fetch when no tracking is set.
936
942
  let tracking = status.tracking;
937
- if (!tracking) {
938
- // No tracking config: fetch origin so its HEAD is known, then ask which
939
- // branch it points at. This path only ever concerns origin — a branch with
940
- // no upstream has no other remote to consult.
943
+ if (strict || !tracking) {
941
944
  try {
942
945
  await git.fetch('origin');
943
946
  await git.raw(['remote', 'set-head', 'origin', '--auto']);
@@ -948,6 +951,19 @@ export async function pullRepo(dir) {
948
951
  tracking = `origin/${branch}`;
949
952
  }
950
953
  }
954
+ // Strict: the checkout must be on the remote default branch — never pull a
955
+ // feature branch across the fleet unattended.
956
+ if (strict) {
957
+ const sep = tracking.indexOf('/');
958
+ const expectedBranch = sep > 0 ? tracking.slice(sep + 1) : tracking;
959
+ if (branch !== expectedBranch) {
960
+ return {
961
+ success: false,
962
+ commit: '',
963
+ error: `Blocked: HEAD is on "${branch}" but origin defaults to "${expectedBranch}". Switch to "${expectedBranch}" before pulling.`,
964
+ };
965
+ }
966
+ }
951
967
  // Split the remote-tracking ref (<remote>/<branch>) so callers/logs can name
952
968
  // the remote. Branch names may contain slashes, so split on the FIRST
953
969
  // separator only. The integrate step below uses `tracking` directly (not a
@@ -983,15 +999,32 @@ export async function pullRepo(dir) {
983
999
  // around that call would always report "can ff" (RUSH-2282).
984
1000
  const aheadCount = parseInt((await git.raw(['rev-list', '--count', `${tracking}..HEAD`])).trim(), 10);
985
1001
  const behindCount = parseInt((await git.raw(['rev-list', '--count', `HEAD..${tracking}`])).trim(), 10);
986
- const canFastForward = Number.isFinite(aheadCount) &&
987
- Number.isFinite(behindCount) &&
988
- aheadCount === 0 &&
989
- behindCount > 0;
990
- // Dirty tree: same rule `syncRepoGit` applies, from the same function — a
991
- // fast-forward that touches nothing the author is holding may proceed; a
992
- // rebase or a colliding path may not. Refusing on any dirt at all is what
993
- // used to strand merged changes on every box that had an unrelated edit.
994
- if (isDirty) {
1002
+ // Both counts are the ONLY inputs to the fast-forward decision, so a count
1003
+ // we cannot read is a refusal, not a reason to guess. Fail here rather than
1004
+ // downstream: an unreadable count used to fall through to the rebase arm in
1005
+ // preserve-local mode, and to a "HEAD diverged" message in strict mode that
1006
+ // named the wrong cause.
1007
+ if (!Number.isFinite(aheadCount) || !Number.isFinite(behindCount)) {
1008
+ return {
1009
+ success: false,
1010
+ commit: '',
1011
+ error: `Could not read how far HEAD is from ${tracking} — 'git rev-list --count' returned no usable count. Check the checkout, then pull again:\n\n cd ${displayHomePath(dir)} && git status`,
1012
+ };
1013
+ }
1014
+ const canFastForward = aheadCount === 0 && behindCount > 0;
1015
+ // Strict: block if HEAD has local commits not on the remote — fast-forward
1016
+ // requires the local tip to be an ancestor of the remote tip.
1017
+ if (strict && aheadCount > 0) {
1018
+ return {
1019
+ success: false,
1020
+ commit: '',
1021
+ error: `Blocked: HEAD is ${aheadCount} commit${aheadCount === 1 ? '' : 's'} ahead of ${tracking}. Push or discard local commits before pulling.`,
1022
+ };
1023
+ }
1024
+ // Dirty tree (preserve-local only): same rule `syncRepoGit` applies —
1025
+ // a fast-forward that touches nothing the author is holding may proceed; a
1026
+ // rebase or a colliding path may not. Strict mode already refused above.
1027
+ if (!strict && isDirty) {
995
1028
  const refusal = await dirtyTreeRefusal(git, status, tracking);
996
1029
  if (refusal) {
997
1030
  return {
@@ -1010,6 +1043,14 @@ export async function pullRepo(dir) {
1010
1043
  // Diverged (or local-only commits). Rebase onto the tracking tip —
1011
1044
  // same outcome as `git pull --rebase <remote> <branch>` without
1012
1045
  // re-fetching or consulting FETCH_HEAD.
1046
+ //
1047
+ // PRESERVE-LOCAL ONLY — strict mode can never reach this arm, so the
1048
+ // fleet pull never rewrites history. Strict has already returned for
1049
+ // every case that leaves `canFastForward` false: an identical local and
1050
+ // remote ref, `aheadCount > 0` (which is also what "diverged" means),
1051
+ // and a count that would not parse. That leaves `aheadCount === 0` with
1052
+ // a differing ref, i.e. `behindCount > 0` — a fast-forward. Keep those
1053
+ // three returns above intact if you change this.
1013
1054
  await git.raw(['rebase', tracking]);
1014
1055
  }
1015
1056
  }
@@ -1028,7 +1069,10 @@ export async function pullRepo(dir) {
1028
1069
  error: `${verb} onto ${tracking} failed — the pull was rolled back, nothing changed.\n\nResolve the divergence, then pull again:\n\n cd ${displayHomePath(dir)} && git log --oneline HEAD...${tracking}\n\n${err.message}`,
1029
1070
  };
1030
1071
  }
1031
- installGithooksSymlinks(dir);
1072
+ // Strict mode never installs git hook symlinks — the command is a read-model
1073
+ // operation (update pointers only; never reconfigure the checkout).
1074
+ if (!strict)
1075
+ installGithooksSymlinks(dir);
1032
1076
  const log = await git.log({ maxCount: 1 });
1033
1077
  return {
1034
1078
  success: true,
package/dist/lib/heal.js CHANGED
@@ -23,10 +23,10 @@
23
23
  * `agents prune cleanup`, so a heal pass can never lose work.
24
24
  */
25
25
  import { ALL_AGENT_IDS } from './agents.js';
26
- import { syncResourcesToVersion, listInstalledVersions, isVersionIsolated, getVersionHomePath, getActuallySyncedResources, compareVersions, } from './versions.js';
26
+ import { syncResourcesToVersion, listInstalledVersions, isVersionIsolated, getVersionHomePath, getActuallySyncedResources, compareVersions, } from './installations/versions.js';
27
27
  import { diffVersionResources, } from './doctor-diff.js';
28
- import { discoverPlugins, updatePlugin, readPluginSourceInfo, getUpstreamManifestVersion, } from './plugins.js';
29
- import { repairPluginManifestFile } from './plugin-marketplace.js';
28
+ import { discoverPlugins, updatePlugin, readPluginSourceInfo, getUpstreamManifestVersion, } from './plugins/plugins.js';
29
+ import { repairPluginManifestFile } from './plugins/plugin-marketplace.js';
30
30
  import * as fs from 'fs';
31
31
  import * as path from 'path';
32
32
  import * as os from 'os';
@@ -386,3 +386,21 @@ export declare function registerHooksToSettings(agentId: AgentId, versionHome: s
386
386
  * entries removed.
387
387
  */
388
388
  export declare function pruneVersionHomeHookEntriesFromSettings(settingsPath: string, agent: AgentId, removedVersion: string): number;
389
+ export interface InstallSessionTrackerHookResult {
390
+ installed: boolean;
391
+ error?: string;
392
+ }
393
+ /**
394
+ * Install the shared SessionStart state-writer hook (`packages/session-tracker`)
395
+ * into the harness's native config. Gated by `supports(agent, 'hooks', version)`;
396
+ * unsupported agents return `installed: false` with a reason instead of throwing.
397
+ *
398
+ * This is the bridge that makes bare `claude` / `codex` / `kimi` launches write
399
+ * `~/.agents/.cache/terminals/sessions/<pid>.json`, not just `agents run` launches.
400
+ */
401
+ export declare function installSessionTrackerHook(agent: AgentId, version?: string, home?: string): Promise<InstallSessionTrackerHookResult>;
402
+ /**
403
+ * Synchronous variant for callers that cannot be made async (e.g.
404
+ * `syncResourcesToVersion`). Best-effort: failures are returned, not thrown.
405
+ */
406
+ export declare function installSessionTrackerHookSync(agent: AgentId, version?: string, home?: string): InstallSessionTrackerHookResult;
package/dist/lib/hooks.js CHANGED
@@ -13,6 +13,9 @@ import * as os from 'os';
13
13
  import * as path from 'path';
14
14
  import * as yaml from 'yaml';
15
15
  import * as TOML from 'smol-toml';
16
+ import { execFile, execFileSync } from 'child_process';
17
+ import { promisify } from 'util';
18
+ import { fileURLToPath } from 'url';
16
19
  import { AGENTS, agentConfigDirName, isAgentHardDeprecated } from './agents.js';
17
20
  import { supports, explainSkip, capableAgents } from './capabilities.js';
18
21
  import { getHooksDir as getSystemHooksDir, getUserHooksDir, getUserAgentsDir, getSystemAgentsDir, getProjectAgentsDir, getTrashHooksDir, getEnabledExtraRepos, getResolvedRulesDir, getUserRulesDir, getPerfDir } from './state.js';
@@ -264,7 +267,7 @@ function collapseVersionHookEntries(entries, activeVersionHome) {
264
267
  return true;
265
268
  });
266
269
  }
267
- import { getEffectiveHome, getGlobalDefault, getVersionHomePath, isVersionIsolated, listInstalledVersions, resolveVersion, } from './versions.js';
270
+ import { getEffectiveHome, getGlobalDefault, getVersionHomePath, isVersionIsolated, listInstalledVersions, resolveVersion, } from './installations/versions.js';
268
271
  import { generateHookShim, getHookShimPath, isValidHookShimName, parseCacheConfig, removeHookShim } from './hooks/cache.js';
269
272
  import { getHookShimsDir } from './state.js';
270
273
  function hookContentHash(scriptPath) {
@@ -3244,3 +3247,112 @@ function registerHooksForHermes(versionHome, manifest, resolveScript, managedPre
3244
3247
  }
3245
3248
  return { registered, errors };
3246
3249
  }
3250
+ const execFileAsync = promisify(execFile);
3251
+ function resolveSessionTrackerRoot() {
3252
+ const here = path.dirname(fileURLToPath(import.meta.url));
3253
+ // Built/installed layout: dist/lib/ -> dist/session-tracker
3254
+ const built = path.resolve(here, '..', 'session-tracker');
3255
+ if (fs.existsSync(path.join(built, 'dist', 'hook.sh'))) {
3256
+ return built;
3257
+ }
3258
+ // Source layout: apps/cli/src/lib/ -> repo root -> packages/session-tracker
3259
+ const source = path.resolve(here, '..', '..', '..', '..', 'packages', 'session-tracker');
3260
+ if (fs.existsSync(path.join(source, 'src', 'hook.sh'))) {
3261
+ return source;
3262
+ }
3263
+ return null;
3264
+ }
3265
+ function resolveTsxLoader(trackerRoot) {
3266
+ const loader = path.join(trackerRoot, 'node_modules', 'tsx', 'dist', 'cli.mjs');
3267
+ if (fs.existsSync(loader))
3268
+ return loader;
3269
+ return null;
3270
+ }
3271
+ function buildInstallHookInvocation(trackerRoot, agent) {
3272
+ const distScript = path.join(trackerRoot, 'dist', 'install-hook.js');
3273
+ if (fs.existsSync(distScript)) {
3274
+ return { command: process.execPath, args: [distScript, agent] };
3275
+ }
3276
+ const loader = resolveTsxLoader(trackerRoot);
3277
+ if (!loader)
3278
+ return null;
3279
+ return {
3280
+ command: process.execPath,
3281
+ args: [loader, path.join(trackerRoot, 'src', 'install-hook.ts'), agent],
3282
+ };
3283
+ }
3284
+ /**
3285
+ * Install the shared SessionStart state-writer hook (`packages/session-tracker`)
3286
+ * into the harness's native config. Gated by `supports(agent, 'hooks', version)`;
3287
+ * unsupported agents return `installed: false` with a reason instead of throwing.
3288
+ *
3289
+ * This is the bridge that makes bare `claude` / `codex` / `kimi` launches write
3290
+ * `~/.agents/.cache/terminals/sessions/<pid>.json`, not just `agents run` launches.
3291
+ */
3292
+ export async function installSessionTrackerHook(agent, version, home) {
3293
+ const gate = supports(agent, 'hooks', version);
3294
+ if (!gate.ok) {
3295
+ return { installed: false, error: explainSkip(agent, 'hooks', gate, version) };
3296
+ }
3297
+ const trackerRoot = resolveSessionTrackerRoot();
3298
+ if (!trackerRoot) {
3299
+ return { installed: false, error: 'session-tracker package not found' };
3300
+ }
3301
+ const invocation = buildInstallHookInvocation(trackerRoot, agent);
3302
+ if (!invocation) {
3303
+ return { installed: false, error: 'session-tracker not built and tsx is unavailable' };
3304
+ }
3305
+ try {
3306
+ await execFileAsync(invocation.command, invocation.args, {
3307
+ env: { ...process.env, HOME: home ?? process.env.HOME },
3308
+ encoding: 'utf8',
3309
+ });
3310
+ return { installed: true };
3311
+ }
3312
+ catch (err) {
3313
+ return { installed: false, error: installFailureMessage(err) };
3314
+ }
3315
+ }
3316
+ /**
3317
+ * The child reports its refusal reason on stdout (its HOOK_SUPPORT table), not
3318
+ * stderr — and a Buffer-typed empty stderr is truthy, so a bare `err.stderr ??
3319
+ * err.message` surfaced an empty string. Prefer the first NON-EMPTY stream.
3320
+ */
3321
+ function installFailureMessage(err) {
3322
+ const e = err;
3323
+ for (const stream of [e.stderr, e.stdout]) {
3324
+ const text = stream == null ? '' : String(stream).trim();
3325
+ if (text.length > 0)
3326
+ return text;
3327
+ }
3328
+ return e.message;
3329
+ }
3330
+ /**
3331
+ * Synchronous variant for callers that cannot be made async (e.g.
3332
+ * `syncResourcesToVersion`). Best-effort: failures are returned, not thrown.
3333
+ */
3334
+ export function installSessionTrackerHookSync(agent, version, home) {
3335
+ const gate = supports(agent, 'hooks', version);
3336
+ if (!gate.ok) {
3337
+ return { installed: false, error: explainSkip(agent, 'hooks', gate, version) };
3338
+ }
3339
+ const trackerRoot = resolveSessionTrackerRoot();
3340
+ if (!trackerRoot) {
3341
+ return { installed: false, error: 'session-tracker package not found' };
3342
+ }
3343
+ const invocation = buildInstallHookInvocation(trackerRoot, agent);
3344
+ if (!invocation) {
3345
+ return { installed: false, error: 'session-tracker not built and tsx is unavailable' };
3346
+ }
3347
+ try {
3348
+ execFileSync(invocation.command, invocation.args, {
3349
+ env: { ...process.env, HOME: home ?? process.env.HOME },
3350
+ stdio: ['ignore', 'pipe', 'pipe'],
3351
+ encoding: 'utf8',
3352
+ });
3353
+ return { installed: true };
3354
+ }
3355
+ catch (err) {
3356
+ return { installed: false, error: installFailureMessage(err) };
3357
+ }
3358
+ }
@@ -1,28 +1,48 @@
1
1
  /**
2
- * Credential provisioning for `agents run --host --copy-creds`.
2
+ * Credential provisioning for `agents run --device --copy-creds`.
3
3
  *
4
- * Reuses the lease flow's runtime detection + credential-script builder so a
5
- * persistent host can boot logged-in the same way an ephemeral leased box does.
6
- * Unlike `--lease`, a host is persistent, so copying tokens is strictly opt-in
7
- * per run and we shred the files after the run to bound the credential window.
4
+ * `--copy-creds` USED TO copy each signed-in runtime's native login to a
5
+ * persistent host the Claude OAuth token (`.claude/.credentials.json`) plus
6
+ * codex/grok/gemini `auth.json`-style files so the box booted logged-in. Every
7
+ * one of those is a **rotating, interactive OAuth / session credential**, and
8
+ * copying it between devices is forbidden by the fleet-auth contract
9
+ * (`docs/specifications.md` SING-1b, `docs/credential-management.md` invariant 2):
10
+ * a shared refresh token rotates server-side on the next refresh and invalidates
11
+ * every other copy — the "droid collapsed 10 boxes to 1 overnight" failure.
12
+ *
13
+ * So this module no longer serializes native logins at all. It REFUSES the
14
+ * transfer and steers to the portable path — a long-lived, non-rotating provider
15
+ * account (`agents accounts add` / `agents accounts sync`), whose bundle is
16
+ * policy-`never` and safe to reuse on many devices. That sync rides its own
17
+ * hardened SSH transport (RUSH-2527); it never touches this path.
8
18
  */
9
19
  import type { AgentId } from '../types.js';
10
- import { type DetectedRuntime } from '../crabbox/runtimes.js';
20
+ import type { DetectedRuntime } from '../crabbox/runtimes.js';
21
+ export { isNativeOAuthRuntime, nativeOAuthTransferRefusal } from '../crabbox/runtimes.js';
11
22
  export interface HostCredentials {
12
23
  runtimes: AgentId[];
13
24
  detected: DetectedRuntime[];
14
25
  claudeCredentialsJson?: string | null;
15
26
  }
16
27
  /**
17
- * Build the setup (write credential files) and teardown (shred them) scripts for
18
- * a host run. Returns shell snippets meant to be run on the remote host.
28
+ * Build the setup/teardown scripts for a `--copy-creds` host run.
29
+ *
30
+ * Every runtime `--copy-creds` handles is a native OAuth / session login, so this
31
+ * REFUSES rather than serialize one across the wire (SING-1b) — it throws with the
32
+ * concrete `agents accounts` steer. The refusal happens BEFORE anything is
33
+ * serialized, so a native credential can never reach a remote-write script. An
34
+ * empty runtime set is a no-op (nothing to provision, nothing forbidden).
19
35
  */
20
36
  export declare function buildHostCredentialScript(opts: HostCredentials): {
21
37
  setup: string;
22
38
  teardown: string;
23
39
  };
24
40
  /**
25
- * Wrap a remote command so credentials are written before it runs and shredded
26
- * after it exits, regardless of success or failure.
41
+ * Wrap a remote command with credential setup/teardown for a `--copy-creds` run.
42
+ *
43
+ * Delegates to {@link buildHostCredentialScript}, which now refuses to transfer a
44
+ * native OAuth login — so a `--copy-creds` run against a signed-in native runtime
45
+ * fails loudly here (before dispatch) with the `agents accounts sync` steer,
46
+ * rather than shipping a rotating token to another device.
27
47
  */
28
48
  export declare function wrapHostCommandWithCredentials(innerCommand: string, opts: HostCredentials): string;
@@ -1,37 +1,49 @@
1
1
  /**
2
- * Credential provisioning for `agents run --host --copy-creds`.
2
+ * Credential provisioning for `agents run --device --copy-creds`.
3
3
  *
4
- * Reuses the lease flow's runtime detection + credential-script builder so a
5
- * persistent host can boot logged-in the same way an ephemeral leased box does.
6
- * Unlike `--lease`, a host is persistent, so copying tokens is strictly opt-in
7
- * per run and we shred the files after the run to bound the credential window.
4
+ * `--copy-creds` USED TO copy each signed-in runtime's native login to a
5
+ * persistent host the Claude OAuth token (`.claude/.credentials.json`) plus
6
+ * codex/grok/gemini `auth.json`-style files so the box booted logged-in. Every
7
+ * one of those is a **rotating, interactive OAuth / session credential**, and
8
+ * copying it between devices is forbidden by the fleet-auth contract
9
+ * (`docs/specifications.md` SING-1b, `docs/credential-management.md` invariant 2):
10
+ * a shared refresh token rotates server-side on the next refresh and invalidates
11
+ * every other copy — the "droid collapsed 10 boxes to 1 overnight" failure.
12
+ *
13
+ * So this module no longer serializes native logins at all. It REFUSES the
14
+ * transfer and steers to the portable path — a long-lived, non-rotating provider
15
+ * account (`agents accounts add` / `agents accounts sync`), whose bundle is
16
+ * policy-`never` and safe to reuse on many devices. That sync rides its own
17
+ * hardened SSH transport (RUSH-2527); it never touches this path.
8
18
  */
9
- import { buildCredentialScript, CLAUDE_TOKEN_REMOTE } from '../crabbox/runtimes.js';
10
- function getShredPaths(runtimes) {
11
- const pathsById = {
12
- claude: ['.claude.json', CLAUDE_TOKEN_REMOTE],
13
- codex: ['.codex/auth.json'],
14
- gemini: ['.gemini/google_accounts.json'],
15
- grok: ['.grok/auth.json'],
16
- };
17
- return runtimes.flatMap((id) => pathsById[id] ?? []);
18
- }
19
+ import { isNativeOAuthRuntime, nativeOAuthTransferRefusal } from '../crabbox/runtimes.js';
20
+ // The native-OAuth predicate + refusal are canonical in `crabbox/runtimes.ts`
21
+ // (next to `LEASE_RUNTIMES`), so `--copy-creds` here and `--lease` there refuse
22
+ // against exactly the same set. Re-export for this module's existing consumers.
23
+ export { isNativeOAuthRuntime, nativeOAuthTransferRefusal } from '../crabbox/runtimes.js';
19
24
  /**
20
- * Build the setup (write credential files) and teardown (shred them) scripts for
21
- * a host run. Returns shell snippets meant to be run on the remote host.
25
+ * Build the setup/teardown scripts for a `--copy-creds` host run.
26
+ *
27
+ * Every runtime `--copy-creds` handles is a native OAuth / session login, so this
28
+ * REFUSES rather than serialize one across the wire (SING-1b) — it throws with the
29
+ * concrete `agents accounts` steer. The refusal happens BEFORE anything is
30
+ * serialized, so a native credential can never reach a remote-write script. An
31
+ * empty runtime set is a no-op (nothing to provision, nothing forbidden).
22
32
  */
23
33
  export function buildHostCredentialScript(opts) {
24
- const setup = buildCredentialScript(opts.runtimes, opts.detected, {
25
- claudeCredentialsJson: opts.claudeCredentialsJson,
26
- });
27
- const teardown = getShredPaths(opts.runtimes)
28
- .map((p) => `rm -f "$HOME/${p}" 2>/dev/null || true`)
29
- .join('\n');
30
- return { setup, teardown };
34
+ const native = opts.runtimes.filter(isNativeOAuthRuntime);
35
+ if (native.length > 0) {
36
+ throw new Error(nativeOAuthTransferRefusal(native));
37
+ }
38
+ return { setup: '', teardown: '' };
31
39
  }
32
40
  /**
33
- * Wrap a remote command so credentials are written before it runs and shredded
34
- * after it exits, regardless of success or failure.
41
+ * Wrap a remote command with credential setup/teardown for a `--copy-creds` run.
42
+ *
43
+ * Delegates to {@link buildHostCredentialScript}, which now refuses to transfer a
44
+ * native OAuth login — so a `--copy-creds` run against a signed-in native runtime
45
+ * fails loudly here (before dispatch) with the `agents accounts sync` steer,
46
+ * rather than shipping a rotating token to another device.
35
47
  */
36
48
  export function wrapHostCommandWithCredentials(innerCommand, opts) {
37
49
  const { setup, teardown } = buildHostCredentialScript(opts);
@@ -5,7 +5,7 @@
5
5
  * remote log and its exit code to a sibling `.exit` file, so progress survives a
6
6
  * dropped connection (followed via offset-tail in progress.ts). This is the
7
7
  * offload win: the process/thread/file fan-out happens on the host, not the
8
- * laptop. `agents run` uses it; `agents teams start --watch --host` reuses the
8
+ * laptop. `agents run` uses it; `agents teams start --watch --device` reuses the
9
9
  * same core so a remote team supervisor keeps running after you disconnect.
10
10
  */
11
11
  import type { Host } from './types.js';
@@ -221,7 +221,7 @@ export declare function buildInteractiveRunForwardedArgs(opts: InteractiveDispat
221
221
  * tmux wrapping; the local machine is just the transport.
222
222
  */
223
223
  export declare function runInteractiveOnHost(host: Host, opts: InteractiveDispatchOptions): Promise<number>;
224
- /** Dispatch an `agents run <agent> "<prompt>"` onto a host (the `run --host` path). */
224
+ /** Dispatch an `agents run <agent> "<prompt>"` onto a host (the `run --device` path). */
225
225
  export declare function dispatchToHost(host: Host, opts: DispatchOptions): Promise<DispatchResult>;
226
226
  export interface CommandDispatchOptions {
227
227
  /** `agents …` args (command name first), already stripped of routing flags. */
@@ -232,7 +232,7 @@ export interface CommandDispatchOptions {
232
232
  }
233
233
  /**
234
234
  * Dispatch an arbitrary long-running `agents <command>` onto a host detached —
235
- * used for `teams start --watch --host`, whose supervisor must outlive the SSH
235
+ * used for `teams start --watch --device`, whose supervisor must outlive the SSH
236
236
  * connection. Reachability is assumed (the caller has already resolved the host);
237
237
  * a launch failure surfaces the remote stderr.
238
238
  */
@@ -5,7 +5,7 @@
5
5
  * remote log and its exit code to a sibling `.exit` file, so progress survives a
6
6
  * dropped connection (followed via offset-tail in progress.ts). This is the
7
7
  * offload win: the process/thread/file fan-out happens on the host, not the
8
- * laptop. `agents run` uses it; `agents teams start --watch --host` reuses the
8
+ * laptop. `agents run` uses it; `agents teams start --watch --device` reuses the
9
9
  * same core so a remote team supervisor keeps running after you disconnect.
10
10
  */
11
11
  import { randomUUID } from 'crypto';
@@ -499,7 +499,7 @@ export async function runInteractiveOnHost(host, opts) {
499
499
  extraSshArgs: hostIdentityArgs(host),
500
500
  });
501
501
  }
502
- /** Dispatch an `agents run <agent> "<prompt>"` onto a host (the `run --host` path). */
502
+ /** Dispatch an `agents run <agent> "<prompt>"` onto a host (the `run --device` path). */
503
503
  export async function dispatchToHost(host, opts) {
504
504
  const target = sshTargetFor(host);
505
505
  // Concrete agent@version pins fail loud before we print "Dispatched" and
@@ -524,7 +524,7 @@ export async function dispatchToHost(host, opts) {
524
524
  }
525
525
  /**
526
526
  * Dispatch an arbitrary long-running `agents <command>` onto a host detached —
527
- * used for `teams start --watch --host`, whose supervisor must outlive the SSH
527
+ * used for `teams start --watch --device`, whose supervisor must outlive the SSH
528
528
  * connection. Reachability is assumed (the caller has already resolved the host);
529
529
  * a launch failure surfaces the remote stderr.
530
530
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Shared `--host` option registrar. Every command that can run on a remote host
2
+ * Shared `--device` option registrar. Every command that can run on a remote device
3
3
  * declares the flag through here, so its spelling, help text, and companions
4
4
  * (`--remote-cwd`, `--no-tty`, `--any`) stay identical everywhere and show up in
5
5
  * each command's `--help`.
@@ -7,8 +7,8 @@
7
7
  * The flags are consumed centrally by `maybeRunOnHost` (passthrough.ts) *before*
8
8
  * commander parses, so for a real remote run the local action never sees them.
9
9
  * Registering them here still matters: it documents the flag and keeps the local
10
- * fall-through (e.g. `--host <this-machine>`) from erroring on an unknown option.
10
+ * fall-through (e.g. `--device <this-machine>`) from erroring on an unknown option.
11
11
  */
12
12
  import type { Command } from 'commander';
13
- /** Attach the standard `--host` flag family to a command and return it (chainable). */
13
+ /** Attach the standard `--device` flag family to a command and return it (chainable). */
14
14
  export declare function addHostOption(cmd: Command): Command;