@phnx-labs/agents-cli 1.22.35 → 1.22.37

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 (487) hide show
  1. package/CHANGELOG.md +666 -2
  2. package/README.md +75 -35
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.d.ts +15 -0
  5. package/dist/bootstrap.js +1211 -0
  6. package/dist/commands/accounts.d.ts +4 -11
  7. package/dist/commands/accounts.js +159 -27
  8. package/dist/commands/attach.js +17 -4
  9. package/dist/commands/audit.d.ts +8 -8
  10. package/dist/commands/audit.js +57 -47
  11. package/dist/commands/browser.js +15 -11
  12. package/dist/commands/cloud.js +1 -1
  13. package/dist/commands/commands.js +0 -11
  14. package/dist/commands/computer-actions.js +33 -0
  15. package/dist/commands/computer-sessions-picker.d.ts +21 -0
  16. package/dist/commands/computer-sessions-picker.js +141 -0
  17. package/dist/commands/computer.d.ts +16 -0
  18. package/dist/commands/computer.js +37 -0
  19. package/dist/commands/config.d.ts +17 -0
  20. package/dist/commands/config.js +401 -0
  21. package/dist/commands/cp.d.ts +84 -0
  22. package/dist/commands/cp.js +231 -0
  23. package/dist/commands/daemon.js +243 -14
  24. package/dist/commands/detach-core.d.ts +1 -1
  25. package/dist/commands/detach-core.js +12 -2
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +64 -5
  28. package/dist/commands/events.d.ts +24 -12
  29. package/dist/commands/events.js +144 -28
  30. package/dist/commands/exec.js +85 -41
  31. package/dist/commands/feed.d.ts +1 -1
  32. package/dist/commands/feed.js +16 -8
  33. package/dist/commands/focus.d.ts +33 -1
  34. package/dist/commands/focus.js +177 -17
  35. package/dist/commands/funnel.d.ts +1 -1
  36. package/dist/commands/go.js +9 -8
  37. package/dist/commands/harness-wizard.d.ts +1 -0
  38. package/dist/commands/harness-wizard.js +18 -20
  39. package/dist/commands/harness.d.ts +2 -0
  40. package/dist/commands/harness.js +59 -26
  41. package/dist/commands/hooks.js +0 -11
  42. package/dist/commands/inspect.d.ts +94 -1
  43. package/dist/commands/inspect.js +866 -40
  44. package/dist/commands/lease.d.ts +4 -4
  45. package/dist/commands/lease.js +6 -6
  46. package/dist/commands/login.js +0 -13
  47. package/dist/commands/logs.d.ts +2 -2
  48. package/dist/commands/logs.js +2 -2
  49. package/dist/commands/mcp.js +7 -2
  50. package/dist/commands/memory.js +7 -2
  51. package/dist/commands/message.d.ts +1 -1
  52. package/dist/commands/message.js +37 -6
  53. package/dist/commands/models.js +4 -0
  54. package/dist/commands/monitors.d.ts +0 -1
  55. package/dist/commands/monitors.js +199 -16
  56. package/dist/commands/open.d.ts +18 -0
  57. package/dist/commands/open.js +57 -0
  58. package/dist/commands/packages.js +2 -107
  59. package/dist/commands/plugins.js +6 -3
  60. package/dist/commands/profiles.d.ts +1 -0
  61. package/dist/commands/profiles.js +16 -160
  62. package/dist/commands/projects.d.ts +28 -0
  63. package/dist/commands/projects.js +125 -5
  64. package/dist/commands/reconnect.js +9 -3
  65. package/dist/commands/repo.js +42 -1
  66. package/dist/commands/resource-view.d.ts +17 -0
  67. package/dist/commands/resource-view.js +36 -14
  68. package/dist/commands/resume.js +9 -2
  69. package/dist/commands/routines.d.ts +0 -2
  70. package/dist/commands/routines.js +473 -289
  71. package/dist/commands/secrets.js +52 -9
  72. package/dist/commands/sessions-export.d.ts +47 -0
  73. package/dist/commands/sessions-export.js +116 -6
  74. package/dist/commands/sessions-import.d.ts +17 -0
  75. package/dist/commands/sessions-import.js +114 -6
  76. package/dist/commands/sessions-migrate.d.ts +27 -0
  77. package/dist/commands/sessions-migrate.js +50 -9
  78. package/dist/commands/sessions-picker.js +23 -4
  79. package/dist/commands/sessions-resume.d.ts +5 -3
  80. package/dist/commands/sessions-resume.js +30 -8
  81. package/dist/commands/sessions-watch.d.ts +2 -0
  82. package/dist/commands/sessions-watch.js +53 -0
  83. package/dist/commands/sessions.d.ts +66 -3
  84. package/dist/commands/sessions.js +298 -47
  85. package/dist/commands/set.d.ts +1 -1
  86. package/dist/commands/set.js +2 -2
  87. package/dist/commands/setup-browser.js +2 -2
  88. package/dist/commands/setup-mine.js +0 -1
  89. package/dist/commands/setup-preferences.js +1 -1
  90. package/dist/commands/setup-share.js +34 -4
  91. package/dist/commands/setup.d.ts +5 -0
  92. package/dist/commands/setup.js +26 -0
  93. package/dist/commands/share.d.ts +67 -0
  94. package/dist/commands/share.js +275 -12
  95. package/dist/commands/skills.js +0 -11
  96. package/dist/commands/snapshot.js +1 -1
  97. package/dist/commands/ssh.d.ts +18 -0
  98. package/dist/commands/ssh.js +549 -210
  99. package/dist/commands/sync.d.ts +5 -0
  100. package/dist/commands/sync.js +212 -32
  101. package/dist/commands/teams.d.ts +13 -0
  102. package/dist/commands/teams.js +187 -30
  103. package/dist/commands/tickets.d.ts +2 -0
  104. package/dist/commands/tickets.js +43 -0
  105. package/dist/commands/update.js +2 -4
  106. package/dist/commands/usage.js +5 -3
  107. package/dist/commands/versions.js +11 -5
  108. package/dist/commands/view.js +15 -7
  109. package/dist/commands/webhook.d.ts +2 -2
  110. package/dist/commands/webhook.js +7 -7
  111. package/dist/index.d.ts +18 -2
  112. package/dist/index.js +53 -1264
  113. package/dist/lib/account-catalog.d.ts +18 -0
  114. package/dist/lib/account-catalog.js +38 -0
  115. package/dist/lib/account-provider-registry.d.ts +18 -0
  116. package/dist/lib/account-provider-registry.js +59 -0
  117. package/dist/lib/account-registry.d.ts +40 -0
  118. package/dist/lib/account-registry.js +239 -0
  119. package/dist/lib/account-schema.d.ts +44 -0
  120. package/dist/lib/account-schema.js +91 -0
  121. package/dist/lib/account-state-service.d.ts +21 -0
  122. package/dist/lib/account-state-service.js +60 -0
  123. package/dist/lib/activity.d.ts +1 -1
  124. package/dist/lib/activity.js +8 -1
  125. package/dist/lib/add-dir.d.ts +80 -0
  126. package/dist/lib/add-dir.js +241 -0
  127. package/dist/lib/agent-cli-commands.d.ts +11 -0
  128. package/dist/lib/agent-cli-commands.js +30 -0
  129. package/dist/lib/agents.js +44 -36
  130. package/dist/lib/answer-router.js +1 -1
  131. package/dist/lib/audit/log.d.ts +10 -27
  132. package/dist/lib/audit/log.js +20 -33
  133. package/dist/lib/auth-health.d.ts +9 -2
  134. package/dist/lib/auth-health.js +42 -9
  135. package/dist/lib/auto-pull-worker.js +7 -3
  136. package/dist/lib/auto-pull.d.ts +44 -3
  137. package/dist/lib/auto-pull.js +88 -5
  138. package/dist/lib/binary-shadow.d.ts +28 -0
  139. package/dist/lib/binary-shadow.js +121 -0
  140. package/dist/lib/brand.js +9 -3
  141. package/dist/lib/browser/ipc.d.ts +30 -0
  142. package/dist/lib/browser/ipc.js +81 -4
  143. package/dist/lib/browser/profiles.d.ts +3 -2
  144. package/dist/lib/browser/profiles.js +65 -22
  145. package/dist/lib/browser/service.d.ts +4 -0
  146. package/dist/lib/browser/service.js +30 -3
  147. package/dist/lib/browser/sessions-list.d.ts +22 -2
  148. package/dist/lib/browser/sessions-list.js +54 -6
  149. package/dist/lib/browser/stream.d.ts +2 -0
  150. package/dist/lib/browser/stream.js +1 -0
  151. package/dist/lib/browser/types.d.ts +19 -0
  152. package/dist/lib/byok-usage.d.ts +9 -2
  153. package/dist/lib/byok-usage.js +133 -31
  154. package/dist/lib/cli-entry.d.ts +11 -0
  155. package/dist/lib/cli-entry.js +46 -0
  156. package/dist/lib/cloud/host.d.ts +1 -1
  157. package/dist/lib/cloud/host.js +2 -2
  158. package/dist/lib/cloud/registry.js +1 -1
  159. package/dist/lib/cloud/types.d.ts +1 -1
  160. package/dist/lib/commands.d.ts +2 -0
  161. package/dist/lib/commands.js +2 -0
  162. package/dist/lib/computer/sessions-list.d.ts +150 -0
  163. package/dist/lib/computer/sessions-list.js +363 -0
  164. package/dist/lib/config-keys.d.ts +86 -0
  165. package/dist/lib/config-keys.js +193 -0
  166. package/dist/lib/config-machine-keys.d.ts +12 -0
  167. package/dist/lib/config-machine-keys.js +17 -0
  168. package/dist/lib/config-transfer.js +3 -4
  169. package/dist/lib/crabbox/cli.d.ts +2 -2
  170. package/dist/lib/crabbox/cli.js +3 -3
  171. package/dist/lib/daemon-health.d.ts +22 -0
  172. package/dist/lib/daemon-health.js +33 -3
  173. package/dist/lib/daemon-services.d.ts +50 -0
  174. package/dist/lib/daemon-services.js +147 -0
  175. package/dist/lib/daemon-ticks.d.ts +35 -66
  176. package/dist/lib/daemon-ticks.js +77 -159
  177. package/dist/lib/daemon.d.ts +72 -4
  178. package/dist/lib/daemon.js +792 -202
  179. package/dist/lib/deeplink/register.d.ts +49 -0
  180. package/dist/lib/deeplink/register.js +253 -0
  181. package/dist/lib/deeplink/url.d.ts +34 -0
  182. package/dist/lib/deeplink/url.js +78 -0
  183. package/dist/lib/device-config.d.ts +124 -29
  184. package/dist/lib/device-config.js +346 -141
  185. package/dist/lib/devices/config-migration.d.ts +42 -0
  186. package/dist/lib/devices/config-migration.js +203 -0
  187. package/dist/lib/devices/connect.js +14 -7
  188. package/dist/lib/devices/doctor-findings.d.ts +4 -1
  189. package/dist/lib/devices/doctor-findings.js +20 -1
  190. package/dist/lib/devices/harness-inventory.d.ts +11 -2
  191. package/dist/lib/devices/harness-inventory.js +0 -0
  192. package/dist/lib/devices/health.d.ts +1 -1
  193. package/dist/lib/devices/health.js +1 -1
  194. package/dist/lib/devices/pending.d.ts +22 -1
  195. package/dist/lib/devices/pending.js +67 -2
  196. package/dist/lib/devices/registry.d.ts +0 -25
  197. package/dist/lib/devices/registry.js +2 -83
  198. package/dist/lib/devices/resolve-profile.d.ts +20 -0
  199. package/dist/lib/devices/resolve-profile.js +44 -0
  200. package/dist/lib/devices/rollout-verify.d.ts +101 -0
  201. package/dist/lib/devices/rollout-verify.js +193 -0
  202. package/dist/lib/devices/ssh-config.js +10 -6
  203. package/dist/lib/event-families.d.ts +28 -0
  204. package/dist/lib/event-families.js +159 -0
  205. package/dist/lib/event-stream.d.ts +9 -1
  206. package/dist/lib/event-stream.js +26 -9
  207. package/dist/lib/events.d.ts +9 -1
  208. package/dist/lib/events.js +21 -6
  209. package/dist/lib/exec.d.ts +30 -0
  210. package/dist/lib/exec.js +219 -121
  211. package/dist/lib/feed-broadcast.d.ts +25 -0
  212. package/dist/lib/feed-broadcast.js +33 -0
  213. package/dist/lib/feed.d.ts +1 -1
  214. package/dist/lib/feed.js +12 -2
  215. package/dist/lib/fleet/capture.js +15 -0
  216. package/dist/lib/fleet/manifest.js +9 -0
  217. package/dist/lib/fleet/types.d.ts +9 -0
  218. package/dist/lib/fleet-status.js +10 -8
  219. package/dist/lib/git.d.ts +20 -6
  220. package/dist/lib/git.js +121 -17
  221. package/dist/lib/hosts/dispatch.d.ts +8 -3
  222. package/dist/lib/hosts/dispatch.js +29 -3
  223. package/dist/lib/hosts/logs.d.ts +2 -2
  224. package/dist/lib/hosts/logs.js +2 -2
  225. package/dist/lib/hosts/option.js +1 -1
  226. package/dist/lib/hosts/passthrough.d.ts +2 -3
  227. package/dist/lib/hosts/passthrough.js +10 -24
  228. package/dist/lib/hosts/progress.js +2 -2
  229. package/dist/lib/hosts/providers/devices.d.ts +3 -3
  230. package/dist/lib/hosts/providers/devices.js +18 -12
  231. package/dist/lib/hosts/ready.d.ts +5 -1
  232. package/dist/lib/hosts/ready.js +9 -3
  233. package/dist/lib/hosts/reconcile.d.ts +2 -2
  234. package/dist/lib/hosts/reconcile.js +2 -2
  235. package/dist/lib/hosts/registry.js +14 -9
  236. package/dist/lib/hosts/remote-cmd.js +1 -1
  237. package/dist/lib/hosts/remote-os.d.ts +9 -6
  238. package/dist/lib/hosts/remote-os.js +13 -6
  239. package/dist/lib/hosts/routing-flag.d.ts +23 -0
  240. package/dist/lib/hosts/routing-flag.js +41 -0
  241. package/dist/lib/hosts/run-target.js +1 -1
  242. package/dist/lib/hosts/session-index.js +1 -1
  243. package/dist/lib/hosts/tasks.d.ts +6 -6
  244. package/dist/lib/hosts/tasks.js +4 -4
  245. package/dist/lib/hosts/types.js +1 -2
  246. package/dist/lib/installations/resolve.js +2 -8
  247. package/dist/lib/isolation-boundary-report.js +0 -1
  248. package/dist/lib/linear-cache.d.ts +7 -0
  249. package/dist/lib/linear-cache.js +31 -4
  250. package/dist/lib/linear-project-counts.d.ts +1 -1
  251. package/dist/lib/linear-project-counts.js +2 -3
  252. package/dist/lib/linear-projects.js +1 -1
  253. package/dist/lib/loop.d.ts +2 -2
  254. package/dist/lib/loop.js +1 -1
  255. package/dist/lib/mailbox-target.d.ts +1 -1
  256. package/dist/lib/mailbox-target.js +1 -1
  257. package/dist/lib/manifest.js +7 -4
  258. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  259. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  260. package/dist/lib/menubar/snapshot.d.ts +3 -2
  261. package/dist/lib/menubar/snapshot.js +6 -2
  262. package/dist/lib/migrate-fold.d.ts +33 -0
  263. package/dist/lib/migrate-fold.js +130 -0
  264. package/dist/lib/migrate.d.ts +34 -34
  265. package/dist/lib/migrate.js +106 -128
  266. package/dist/lib/model-tier-overrides.d.ts +1 -1
  267. package/dist/lib/model-tier-overrides.js +15 -2
  268. package/dist/lib/monitors/config.d.ts +17 -3
  269. package/dist/lib/monitors/config.js +52 -18
  270. package/dist/lib/monitors/engine.d.ts +32 -1
  271. package/dist/lib/monitors/engine.js +94 -11
  272. package/dist/lib/monitors/fingerprint.d.ts +46 -0
  273. package/dist/lib/monitors/fingerprint.js +100 -0
  274. package/dist/lib/monitors/remote.d.ts +47 -0
  275. package/dist/lib/monitors/remote.js +81 -0
  276. package/dist/lib/monitors/state.d.ts +39 -0
  277. package/dist/lib/monitors/state.js +56 -0
  278. package/dist/lib/onepassword.d.ts +17 -0
  279. package/dist/lib/onepassword.js +52 -22
  280. package/dist/lib/open-url.js +1 -1
  281. package/dist/lib/picker.d.ts +14 -2
  282. package/dist/lib/picker.js +35 -13
  283. package/dist/lib/placement.d.ts +1 -1
  284. package/dist/lib/placement.js +1 -1
  285. package/dist/lib/pr-land-detach.d.ts +32 -0
  286. package/dist/lib/pr-land-detach.js +79 -0
  287. package/dist/lib/profiles-presets.js +13 -0
  288. package/dist/lib/profiles.d.ts +2 -0
  289. package/dist/lib/profiles.js +44 -1
  290. package/dist/lib/project-focus.d.ts +1 -1
  291. package/dist/lib/project-focus.js +1 -1
  292. package/dist/lib/project-probe.d.ts +4 -1
  293. package/dist/lib/project-probe.js +5 -4
  294. package/dist/lib/project-resources.js +2 -18
  295. package/dist/lib/project-root.d.ts +16 -0
  296. package/dist/lib/project-root.js +20 -2
  297. package/dist/lib/projects.d.ts +20 -1
  298. package/dist/lib/projects.js +78 -1
  299. package/dist/lib/refresh-coordinator.d.ts +24 -0
  300. package/dist/lib/refresh-coordinator.js +52 -0
  301. package/dist/lib/registry.d.ts +2 -2
  302. package/dist/lib/registry.js +1 -1
  303. package/dist/lib/resource-aliases.d.ts +13 -0
  304. package/dist/lib/resource-aliases.js +26 -0
  305. package/dist/lib/resources/types.d.ts +1 -1
  306. package/dist/lib/resources.d.ts +16 -0
  307. package/dist/lib/resources.js +66 -10
  308. package/dist/lib/rotate.d.ts +3 -4
  309. package/dist/lib/rotate.js +4 -5
  310. package/dist/lib/routine-activation.d.ts +22 -2
  311. package/dist/lib/routine-activation.js +63 -16
  312. package/dist/lib/routine-context.d.ts +9 -2
  313. package/dist/lib/routine-context.js +21 -6
  314. package/dist/lib/routines-project.d.ts +58 -48
  315. package/dist/lib/routines-project.js +190 -159
  316. package/dist/lib/routines.d.ts +41 -6
  317. package/dist/lib/routines.js +92 -34
  318. package/dist/lib/run-defaults.d.ts +5 -0
  319. package/dist/lib/run-defaults.js +11 -1
  320. package/dist/lib/runner.d.ts +10 -8
  321. package/dist/lib/runner.js +122 -39
  322. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  323. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  324. package/dist/lib/secrets/agent.d.ts +10 -3
  325. package/dist/lib/secrets/agent.js +43 -8
  326. package/dist/lib/secrets/bundles.d.ts +1 -0
  327. package/dist/lib/secrets/bundles.js +92 -80
  328. package/dist/lib/secrets/index.js +32 -9
  329. package/dist/lib/secrets/install-helper.d.ts +4 -4
  330. package/dist/lib/secrets/install-helper.js +4 -4
  331. package/dist/lib/secrets/push.d.ts +40 -6
  332. package/dist/lib/secrets/push.js +58 -11
  333. package/dist/lib/secrets/read-backoff.d.ts +1 -1
  334. package/dist/lib/secrets/read-backoff.js +1 -1
  335. package/dist/lib/secrets/remote.d.ts +24 -0
  336. package/dist/lib/secrets/remote.js +54 -4
  337. package/dist/lib/self-update.d.ts +108 -0
  338. package/dist/lib/self-update.js +276 -1
  339. package/dist/lib/session/active.d.ts +89 -5
  340. package/dist/lib/session/active.js +165 -10
  341. package/dist/lib/session/actor-sidecar.d.ts +1 -1
  342. package/dist/lib/session/actor-sidecar.js +2 -1
  343. package/dist/lib/session/db.d.ts +176 -2
  344. package/dist/lib/session/db.js +484 -17
  345. package/dist/lib/session/discover.js +27 -4
  346. package/dist/lib/session/hook-sessions.js +2 -2
  347. package/dist/lib/session/host-link.d.ts +2 -2
  348. package/dist/lib/session/host-link.js +2 -2
  349. package/dist/lib/session/pid-registry.d.ts +21 -0
  350. package/dist/lib/session/pid-registry.js +57 -0
  351. package/dist/lib/session/remote-active.js +15 -1
  352. package/dist/lib/session/remote.js +2 -2
  353. package/dist/lib/session/session-cache.d.ts +14 -7
  354. package/dist/lib/session/session-cache.js +51 -9
  355. package/dist/lib/session/state.d.ts +2 -2
  356. package/dist/lib/session/state.js +1 -1
  357. package/dist/lib/session/sync/config.d.ts +10 -10
  358. package/dist/lib/session/sync/config.js +10 -10
  359. package/dist/lib/session/sync/r2.d.ts +34 -0
  360. package/dist/lib/session/sync/r2.js +123 -0
  361. package/dist/lib/session/throughput.d.ts +1 -1
  362. package/dist/lib/session/throughput.js +1 -1
  363. package/dist/lib/session/types.d.ts +23 -1
  364. package/dist/lib/session/types.js +15 -0
  365. package/dist/lib/session/viewing-in.d.ts +1 -1
  366. package/dist/lib/session/viewing-in.js +1 -1
  367. package/dist/lib/session/watch.d.ts +101 -0
  368. package/dist/lib/session/watch.js +242 -0
  369. package/dist/lib/share/config.d.ts +4 -0
  370. package/dist/lib/share/config.js +1 -0
  371. package/dist/lib/share/provision.d.ts +38 -0
  372. package/dist/lib/share/provision.js +50 -0
  373. package/dist/lib/share/publish.d.ts +40 -1
  374. package/dist/lib/share/publish.js +116 -3
  375. package/dist/lib/share/worker-template.js +71 -6
  376. package/dist/lib/shims.d.ts +17 -3
  377. package/dist/lib/shims.js +98 -26
  378. package/dist/lib/signin-badge.js +3 -2
  379. package/dist/lib/skills.js +2 -0
  380. package/dist/lib/smart-launch.d.ts +8 -8
  381. package/dist/lib/smart-launch.js +80 -59
  382. package/dist/lib/ssh-exec.d.ts +1 -1
  383. package/dist/lib/ssh-exec.js +1 -1
  384. package/dist/lib/staleness/prune.d.ts +88 -0
  385. package/dist/lib/staleness/prune.js +69 -0
  386. package/dist/lib/staleness/registry.d.ts +1 -1
  387. package/dist/lib/staleness/writers/commands.js +34 -2
  388. package/dist/lib/staleness/writers/hooks.js +16 -0
  389. package/dist/lib/staleness/writers/kinds.d.ts +6 -0
  390. package/dist/lib/staleness/writers/skills.js +19 -0
  391. package/dist/lib/staleness/writers/subagents.d.ts +2 -3
  392. package/dist/lib/staleness/writers/subagents.js +0 -4
  393. package/dist/lib/staleness/writers/types.d.ts +32 -0
  394. package/dist/lib/startup/command-registry.d.ts +6 -12
  395. package/dist/lib/startup/command-registry.js +11 -31
  396. package/dist/lib/startup/dev-build.d.ts +10 -0
  397. package/dist/lib/startup/dev-build.js +13 -1
  398. package/dist/lib/startup/spellcheck.d.ts +18 -0
  399. package/dist/lib/startup/spellcheck.js +45 -0
  400. package/dist/lib/state.d.ts +36 -9
  401. package/dist/lib/state.js +96 -46
  402. package/dist/lib/subagents-registry.d.ts +0 -7
  403. package/dist/lib/subagents-registry.js +38 -65
  404. package/dist/lib/subagents.d.ts +0 -33
  405. package/dist/lib/subagents.js +0 -75
  406. package/dist/lib/sync-umbrella.js +1 -1
  407. package/dist/lib/teams/agents.d.ts +41 -1
  408. package/dist/lib/teams/agents.js +187 -9
  409. package/dist/lib/teams/api.d.ts +11 -1
  410. package/dist/lib/teams/api.js +11 -2
  411. package/dist/lib/teams/delivery.d.ts +41 -0
  412. package/dist/lib/teams/delivery.js +60 -0
  413. package/dist/lib/teams/registry.d.ts +14 -0
  414. package/dist/lib/teams/registry.js +51 -1
  415. package/dist/lib/teams/remoteWorktree.d.ts +19 -0
  416. package/dist/lib/teams/remoteWorktree.js +29 -0
  417. package/dist/lib/teams/scheduler.d.ts +1 -1
  418. package/dist/lib/teams/scheduler.js +1 -1
  419. package/dist/lib/teams/worktree.d.ts +24 -0
  420. package/dist/lib/teams/worktree.js +42 -0
  421. package/dist/lib/terminal/backends/vscodium-agent.d.ts +10 -1
  422. package/dist/lib/terminal/backends/vscodium-agent.js +16 -5
  423. package/dist/lib/terminal/engine.d.ts +4 -0
  424. package/dist/lib/terminal/engine.js +8 -2
  425. package/dist/lib/terminal/types.d.ts +21 -2
  426. package/dist/lib/testdata/refresh-coordinator-worker.d.ts +1 -0
  427. package/dist/lib/testdata/refresh-coordinator-worker.js +23 -0
  428. package/dist/lib/tickets/list.d.ts +53 -0
  429. package/dist/lib/tickets/list.js +153 -0
  430. package/dist/lib/tmux/orphan-reap.d.ts +320 -0
  431. package/dist/lib/tmux/orphan-reap.js +644 -0
  432. package/dist/lib/tmux/session.d.ts +68 -3
  433. package/dist/lib/tmux/session.js +95 -5
  434. package/dist/lib/triggers/handlers.d.ts +20 -0
  435. package/dist/lib/triggers/handlers.js +6 -1
  436. package/dist/lib/types.d.ts +46 -34
  437. package/dist/lib/usage-fleet.d.ts +32 -0
  438. package/dist/lib/usage-fleet.js +125 -0
  439. package/dist/lib/usage-refresh.d.ts +3 -3
  440. package/dist/lib/usage-refresh.js +19 -16
  441. package/dist/lib/usage.d.ts +51 -47
  442. package/dist/lib/usage.js +145 -153
  443. package/dist/lib/version-duplicates.js +2 -2
  444. package/dist/lib/versions.d.ts +56 -13
  445. package/dist/lib/versions.js +195 -45
  446. package/dist/lib/watchdog/log.d.ts +1 -1
  447. package/dist/lib/watchdog/log.js +3 -3
  448. package/dist/lib/watchdog/rotate.d.ts +6 -6
  449. package/dist/lib/watchdog/rotate.js +6 -6
  450. package/dist/lib/workflows.d.ts +1 -1
  451. package/dist/lib/yaml-io.d.ts +47 -0
  452. package/dist/lib/yaml-io.js +55 -0
  453. package/package.json +2 -1
  454. package/scripts/install-helper.js +2 -2
  455. package/scripts/postinstall.js +23 -20
  456. package/dist/commands/defaults.d.ts +0 -7
  457. package/dist/commands/defaults.js +0 -107
  458. package/dist/commands/export.d.ts +0 -11
  459. package/dist/commands/export.js +0 -215
  460. package/dist/commands/helper.d.ts +0 -12
  461. package/dist/commands/helper.js +0 -87
  462. package/dist/commands/hosts.d.ts +0 -11
  463. package/dist/commands/hosts.js +0 -330
  464. package/dist/commands/lock.d.ts +0 -12
  465. package/dist/commands/lock.js +0 -70
  466. package/dist/commands/pull.d.ts +0 -17
  467. package/dist/commands/pull.js +0 -39
  468. package/dist/commands/push.d.ts +0 -14
  469. package/dist/commands/push.js +0 -30
  470. package/dist/commands/wallet.d.ts +0 -20
  471. package/dist/commands/wallet.js +0 -216
  472. package/dist/commands/worktree.d.ts +0 -19
  473. package/dist/commands/worktree.js +0 -272
  474. package/dist/lib/account-labels.d.ts +0 -24
  475. package/dist/lib/account-labels.js +0 -72
  476. package/dist/lib/auto-dispatch-linear.d.ts +0 -18
  477. package/dist/lib/auto-dispatch-linear.js +0 -107
  478. package/dist/lib/auto-dispatch-provider.d.ts +0 -10
  479. package/dist/lib/auto-dispatch-provider.js +0 -30
  480. package/dist/lib/auto-dispatch.d.ts +0 -93
  481. package/dist/lib/auto-dispatch.js +0 -128
  482. package/dist/lib/export.d.ts +0 -72
  483. package/dist/lib/export.js +0 -269
  484. package/dist/lib/lock.d.ts +0 -93
  485. package/dist/lib/lock.js +0 -207
  486. package/dist/lib/wallet/index.d.ts +0 -78
  487. package/dist/lib/wallet/index.js +0 -253
@@ -13,16 +13,17 @@ import { runSupervisor } from '../lib/teams/supervisor.js';
13
13
  import { debug } from '../lib/teams/debug.js';
14
14
  import { runPrWatch, DEFAULT_MAX_WAVES, } from '../lib/teams/pr-watch.js';
15
15
  import { handleSpawn, handleStatus, handleStop, toTaskStatusSummary, } from '../lib/teams/api.js';
16
+ import { resolveTeammateDelivery, deliveryDisplayLabel, deliveryColorKey, } from '../lib/teams/delivery.js';
16
17
  import { createTeam, ensureTeam, getTeam, loadTeams, removeTeam, teamExists, } from '../lib/teams/registry.js';
17
18
  import { setHelpSections } from '../lib/help.js';
18
- import { createWorktree, isGitRepo, hasUncommittedChanges, removeWorktree, worktreeCheckoutExists, worktreeExists, } from '../lib/teams/worktree.js';
19
+ import { createWorktree, commitsBehindDefault, isGitRepo, hasUncommittedChanges, removeWorktree, worktreeCheckoutExists, worktreeExists, } from '../lib/teams/worktree.js';
19
20
  import { resolveHost } from '../lib/hosts/registry.js';
20
21
  import { isDeviceAuto, resolveDeviceAuto } from '../lib/smart-launch.js';
21
22
  import { sshTargetFor } from '../lib/hosts/types.js';
22
23
  import { ensureHostReady } from '../lib/hosts/ready.js';
23
24
  import { remoteShellFor } from '../lib/hosts/remote-cmd.js';
24
25
  import { resolveRemoteOsSync } from '../lib/hosts/remote-os.js';
25
- import { remoteWorktreeDirty, removeRemoteWorktree, ensureRemoteRepo } from '../lib/teams/remoteWorktree.js';
26
+ import { remoteWorktreeDirty, removeRemoteWorktree, ensureRemoteRepo, remoteCommitsBehindDefault } from '../lib/teams/remoteWorktree.js';
26
27
  import { getRemoteUrl } from '../lib/git.js';
27
28
  import { machineId } from '../lib/session/sync/config.js';
28
29
  import { isVersionInstalled, resolveVersionAlias, resolveVersionAliasLoose } from '../lib/versions.js';
@@ -59,6 +60,7 @@ function statusColor(status) {
59
60
  case 'pending': return chalk.blue;
60
61
  case 'running': return chalk.yellow;
61
62
  case 'completed': return chalk.green;
63
+ case 'pr_open': return chalk.magenta; // RUSH-2380: process done, PR not merged
62
64
  case 'failed': return chalk.red;
63
65
  case 'stopped': return chalk.gray;
64
66
  default: return chalk.white;
@@ -299,6 +301,57 @@ function warnOrphanWorktree(baseCwd, name, reason) {
299
301
  ` Remove it manually: git -C ${baseCwd} worktree remove --force .agents/worktrees/${name} ` +
300
302
  `&& git -C ${baseCwd} branch -D agents/${name}\n`));
301
303
  }
304
+ /** Pluralize a commit count: "1 commit" / "3 commits". */
305
+ function commitsWord(behind) {
306
+ return `${behind} commit${behind === 1 ? '' : 's'}`;
307
+ }
308
+ /**
309
+ * The blocking message when `teams add` is pointed at a stale checkout. Pure so
310
+ * the guidance is pinned by tests (mirrors `remoteCwdOnAddError`): it MUST name
311
+ * how far behind, tell the caller to sync with remote main, and mention `--confirm`
312
+ * as the override.
313
+ */
314
+ export function staleRepoError(params) {
315
+ return (`${params.where} is ${commitsWord(params.behind)} behind origin/${params.base}. ` +
316
+ `A team started here would build on stale code — bring it up to date with remote main first:\n` +
317
+ ` ${params.sync}\n` +
318
+ `Then re-run \`agents teams add ${params.team} …\`, or pass --confirm to start on the stale repo anyway.`);
319
+ }
320
+ /**
321
+ * Guard against pointing a team at a stale checkout. Before a teammate is bound
322
+ * to a repo, this fetches origin and counts how far behind `origin/<default>` the
323
+ * base checkout is (the local cwd, or the repo provisioned on a `--device` host).
324
+ * If it is behind and the caller did NOT pass `--confirm`, the add is refused with
325
+ * {@link staleRepoError} — because a team started on stale code reasons and builds
326
+ * against a tree that has already moved on (the 71-commit-stale s1 checkout
327
+ * incident). With `--confirm` it prints a one-line advisory and proceeds.
328
+ *
329
+ * A `null` behind-count (offline, non-repo, unreachable host) is "can't tell" and
330
+ * never blocks — this is a freshness nudge, not a hard prerequisite.
331
+ */
332
+ async function assertRepoFreshOrConfirm(params) {
333
+ const { team, confirm, json } = params;
334
+ const res = params.remote
335
+ ? remoteCommitsBehindDefault(params.remote.target, params.remote.repoPath, {
336
+ extraSshArgs: params.remote.extraSshArgs,
337
+ })
338
+ : params.local
339
+ ? await commitsBehindDefault(params.local)
340
+ : null;
341
+ if (!res || res.behind <= 0)
342
+ return;
343
+ const where = params.remote
344
+ ? `The repo on ${params.remote.host} (${params.remote.repoPath})`
345
+ : `This checkout (${params.local})`;
346
+ const sync = params.remote
347
+ ? `agents ssh ${params.remote.host} 'git -C ${params.remote.repoPath} merge --ff-only origin/${res.base}'`
348
+ : `git -C ${params.local} merge --ff-only origin/${res.base}`;
349
+ if (confirm) {
350
+ process.stderr.write(chalk.yellow(`⚠ ${where} is ${commitsWord(res.behind)} behind origin/${res.base}; starting anyway (--confirm).\n`));
351
+ return;
352
+ }
353
+ dieFriction('teams', 'repo-stale', staleRepoError({ team, where, behind: res.behind, base: res.base, sync }), 1, { json });
354
+ }
302
355
  /**
303
356
  * Register the generic cloud dispatcher — staged cloud teammates get
304
357
  * dispatched when their --after deps resolve, using repo/branch stored on
@@ -526,7 +579,14 @@ async function reactWithTeammate(mgr, team, action, prompt) {
526
579
  }
527
580
  let result;
528
581
  try {
529
- result = await handleSpawn(mgr, team, 'claude', prompt, cwd, 'edit', 'medium', null, cwd, null, name, after, null, null, taskType, null, null, null, null, worktreeName, worktreePath);
582
+ result = await handleSpawn(mgr, team, 'claude', prompt, cwd, 'edit', 'medium', null, cwd, null, name, after, null, null, taskType, null, null, null, null, worktreeName, worktreePath, null, // profileName
583
+ null, // hostName
584
+ null, // hostTarget
585
+ null, // repoPath
586
+ // A pr-watch fixer belongs to the same team, so it gets the same project
587
+ // grants as any other teammate. Wiring `--project` into only the
588
+ // `teams add` caller would have left this one silently without them.
589
+ (await getTeam(team))?.project ?? null);
530
590
  }
531
591
  catch (err) {
532
592
  // The spawn failed after we created this fixer's worktree — tear it down so
@@ -617,7 +677,11 @@ async function resolveTeammateAcrossTeams(base, ref, teamHint) {
617
677
  // ! reported an error (if flagged)
618
678
  // PR: <url> (if set)
619
679
  function printAgentDetail(a, session) {
620
- const label = statusColor(a.status)(a.status.toUpperCase());
680
+ // RUSH-2380: process COMPLETED + open PR → show PR OPEN, not COMPLETED.
681
+ const delivery = a.delivery ??
682
+ resolveTeammateDelivery({ status: a.status, prUrl: a.pr_url });
683
+ const colorKey = deliveryColorKey(delivery, a.status);
684
+ const label = statusColor(colorKey)(deliveryDisplayLabel(delivery, a.status));
621
685
  const who = fullName(a.agent_type, a.version);
622
686
  const h = displayHandle(a);
623
687
  const secondary = a.name ? chalk.gray(`(${shortId(a.agent_id)})`) : '';
@@ -722,7 +786,10 @@ async function resolveTeammateSessions(agents) {
722
786
  // last." Caller passes the projected AgentStatusSummary; for the full
723
787
  // verbose layout use printAgentDetail above.
724
788
  function printAgentSummary(s) {
725
- const label = statusColor(s.status)(s.status.toUpperCase());
789
+ const delivery = s.delivery ??
790
+ resolveTeammateDelivery({ status: s.status, prUrl: s.pr_url });
791
+ const colorKey = deliveryColorKey(delivery, s.status);
792
+ const label = statusColor(colorKey)(deliveryDisplayLabel(delivery, s.status));
726
793
  const handle = s.name ?? shortId(s.agent_id);
727
794
  const ident = s.name ? chalk.gray(`(${shortId(s.agent_id)})`) : '';
728
795
  const duration = s.duration ? `${chalk.gray(' · ')}${chalk.white(s.duration)}` : '';
@@ -1282,9 +1349,22 @@ export function registerTeamsCommands(program) {
1282
1349
  .option('--devices <list>', 'Pool of machines this team may run teammates on (comma-separated). Enables distributed auto-scheduling.')
1283
1350
  .option('--hosts <list>', 'Alias for --devices.')
1284
1351
  .option('--repo <urlOrPath>', 'How each remote (--device) teammate gets the code — ONE git URL/path for the whole team (existing checkout reused, else cloned). A team is single-repo; for work across repos, make one team per repo. Defaults to this checkout origin.')
1352
+ .option('--project <slug>', "Work this team on a defined project: its primary directory is each local teammate's base cwd, its other directories become --add-dir grants")
1285
1353
  .option('--json', 'Output machine-readable JSON')
1286
1354
  .action(async (team, opts) => {
1287
1355
  try {
1356
+ // Fail here, not at the first `teams add`: a team created against a
1357
+ // project that does not resolve would silently fall back to the
1358
+ // orchestrator's cwd for every teammate.
1359
+ if (opts.project) {
1360
+ const { resolveProjectRef } = await import('../lib/project-root.js');
1361
+ try {
1362
+ await resolveProjectRef(opts.project, { forRemote: false });
1363
+ }
1364
+ catch (err) {
1365
+ dieFriction('teams', 'project-unresolved', err.message);
1366
+ }
1367
+ }
1288
1368
  // --devices / --hosts are aliases; commander can't express a two-name
1289
1369
  // option that isn't a short flag, so merge them here. Split on comma,
1290
1370
  // trim, drop blanks, dedupe (preserving first-seen order).
@@ -1302,8 +1382,8 @@ export function registerTeamsCommands(program) {
1302
1382
  continue;
1303
1383
  const host = await resolveHost(name);
1304
1384
  if (!host) {
1305
- dieFriction('teams', 'pool-device-not-resolvable', `Couldn't resolve pool device "${name}". Register it with \`agents devices\`, ` +
1306
- `enroll it with \`agents hosts add ${name}\`, or pass user@host.`);
1385
+ dieFriction('teams', 'pool-device-not-resolvable', `Couldn't resolve pool device "${name}". Register it with \`agents devices add ${name} <target>\`, ` +
1386
+ `or pass user@host.`);
1307
1387
  }
1308
1388
  if (remoteShellFor(host.os ?? resolveRemoteOsSync(host.name)) === 'powershell') {
1309
1389
  dieFriction('teams', 'pool-device-windows-unsupported', `Distributed teams on Windows device "${host.name}" are not supported yet — ` +
@@ -1328,6 +1408,7 @@ export function registerTeamsCommands(program) {
1328
1408
  useWorktree: opts.useWorktree,
1329
1409
  devices,
1330
1410
  repo,
1411
+ project: opts.project,
1331
1412
  });
1332
1413
  if (isJsonMode(opts)) {
1333
1414
  console.log(JSON.stringify({ team, ...meta }, null, 2));
@@ -1344,6 +1425,8 @@ export function registerTeamsCommands(program) {
1344
1425
  console.log(chalk.gray(` devices: ${meta.devices.join(', ')}`));
1345
1426
  if (meta.repo)
1346
1427
  console.log(chalk.gray(` repo: ${meta.repo}`));
1428
+ if (meta.project)
1429
+ console.log(chalk.gray(` project: ${meta.project}`));
1347
1430
  console.log();
1348
1431
  console.log(chalk.gray('Add your first teammate:'));
1349
1432
  if (meta.enable_worktrees) {
@@ -1374,6 +1457,7 @@ export function registerTeamsCommands(program) {
1374
1457
  .option('--repo <owner/repo>', 'GitHub repository (required for --cloud rush)')
1375
1458
  .option('--branch <name>', 'Target git branch for cloud dispatch')
1376
1459
  .option('--force', "Skip the advisory 'may not be signed in' / 'account throttled' warnings")
1460
+ .option('--confirm', 'Proceed even when the base checkout/repo is behind origin/main (a stale repo otherwise blocks the add)')
1377
1461
  .option('--json', 'Output machine-readable JSON')
1378
1462
  .action(async (team, teammate, task, opts) => {
1379
1463
  // `--remote-cwd` rides the shared --host option family but is never read by
@@ -1440,14 +1524,15 @@ export function registerTeamsCommands(program) {
1440
1524
  let hostName = null;
1441
1525
  let hostTarget = null;
1442
1526
  let hostRepoPath = null;
1527
+ let hostExtraSshArgs = [];
1443
1528
  if (explicitDevice && explicitDevice.toLowerCase() !== machineId()) {
1444
1529
  if (cloudProviderId) {
1445
1530
  dieFriction('teams', 'device-cloud-mutually-exclusive', `--device and --cloud are mutually exclusive (two different remote backends). Pick one.`);
1446
1531
  }
1447
1532
  const host = await resolveHost(explicitDevice);
1448
1533
  if (!host) {
1449
- dieFriction('teams', 'device-not-resolvable', `Couldn't resolve --device "${explicitDevice}". Register it with \`agents devices\`, ` +
1450
- `enroll it with \`agents hosts add ${explicitDevice}\`, or pass user@host.`);
1534
+ dieFriction('teams', 'device-not-resolvable', `Couldn't resolve --device "${explicitDevice}". Register it with \`agents devices add ${explicitDevice} <target>\`, ` +
1535
+ `or pass user@host.`);
1451
1536
  }
1452
1537
  // POSIX-only in v1: the remote follow/monitor layer offset-tails the log
1453
1538
  // with tail/cat/kill, which don't exist under PowerShell. Refuse Windows
@@ -1491,9 +1576,12 @@ export function registerTeamsCommands(program) {
1491
1576
  if (!effectiveRepo && (await isGitRepo(process.cwd()))) {
1492
1577
  effectiveRepo = (await getRemoteUrl(process.cwd())) ?? '';
1493
1578
  }
1579
+ // Capture the ssh args ensureRemoteRepo uses so the staleness probe below
1580
+ // reaches the host with the same identity.
1581
+ hostExtraSshArgs = host.identityFile ? ['-i', host.identityFile, '-o', 'IdentitiesOnly=yes'] : [];
1494
1582
  try {
1495
1583
  hostRepoPath = ensureRemoteRepo(hostTarget, effectiveRepo, team, {
1496
- extraSshArgs: host.identityFile ? ['-i', host.identityFile, '-o', 'IdentitiesOnly=yes'] : [],
1584
+ extraSshArgs: hostExtraSshArgs,
1497
1585
  });
1498
1586
  }
1499
1587
  catch (err) {
@@ -1570,6 +1658,25 @@ export function registerTeamsCommands(program) {
1570
1658
  catch (err) {
1571
1659
  dieFriction('teams', 'add-precondition-failed', err.message);
1572
1660
  }
1661
+ // Stale-repo guard: refuse to point a team at a checkout behind origin/main
1662
+ // unless --confirm. A cloud teammate clones fresh in the provider, so it has
1663
+ // no local/remote checkout to assess — skip it there.
1664
+ if (!cloudProviderId) {
1665
+ if (hostName) {
1666
+ await assertRepoFreshOrConfirm({
1667
+ team,
1668
+ confirm: Boolean(opts.confirm),
1669
+ json: isJsonMode(opts),
1670
+ remote: { target: hostTarget, repoPath: hostRepoPath, host: hostName, extraSshArgs: hostExtraSshArgs },
1671
+ });
1672
+ }
1673
+ else {
1674
+ const base = sharedWorktree ?? opts.cwd ?? process.cwd();
1675
+ if (await isGitRepo(base)) {
1676
+ await assertRepoFreshOrConfirm({ team, confirm: Boolean(opts.confirm), json: isJsonMode(opts), local: base });
1677
+ }
1678
+ }
1679
+ }
1573
1680
  // Track a worktree WE create in this add so a later failure (dep race,
1574
1681
  // launch error, cloud dispatch) can tear it down instead of stranding the
1575
1682
  // branch. Only a worktree THIS add created is ever torn down, so a
@@ -1674,10 +1781,32 @@ export function registerTeamsCommands(program) {
1674
1781
  else if (opts.worktree) {
1675
1782
  dieFriction('teams', 'worktree-requires-enable-worktrees', `--worktree requires --enable-worktrees on the team. Recreate the team with: agents teams create ${team} --enable-worktrees`);
1676
1783
  }
1784
+ // The team's project (`teams create --project`) contributes a base cwd and
1785
+ // the access grants for its other directories. It sits BELOW --cwd in the
1786
+ // precedence chain: an explicit --cwd on this teammate still wins.
1787
+ //
1788
+ // Grants are attached even when a worktree or --cwd owns the cwd — the
1789
+ // sibling repos are what the project binds, not where the teammate sits.
1790
+ // Only the base cwd is resolved here — a LOCAL teammate needs a concrete
1791
+ // directory to start in. The GRANTS are deliberately not resolved now:
1792
+ // an unpinned teammate on a --devices pool is placed at launch, so its
1793
+ // shape (absolute vs ~/…) is not yet knowable. The project name rides on
1794
+ // the record and resolveTeammateGrants resolves it per launch.
1795
+ let projectCwd;
1796
+ if (teamMeta?.project && !hostName) {
1797
+ const { resolveProjectRef } = await import('../lib/project-root.js');
1798
+ try {
1799
+ projectCwd = await resolveProjectRef(teamMeta.project, { forRemote: false });
1800
+ }
1801
+ catch (err) {
1802
+ dieFriction('teams', 'project-unresolved', err.message);
1803
+ }
1804
+ }
1677
1805
  // Distributed teammates have no LOCAL cwd — their working dir lives on the
1678
1806
  // host (repoPath / the remote worktree). Local teammates default to the
1679
- // worktree path, then --cwd, then the current directory.
1680
- const cwd = hostName ? null : (worktreePath ?? opts.cwd ?? process.cwd());
1807
+ // worktree path, then --cwd, then the project's primary directory, then
1808
+ // the current directory.
1809
+ const cwd = hostName ? null : (worktreePath ?? opts.cwd ?? projectCwd ?? process.cwd());
1681
1810
  // Factory teammates: prepend the worker-skill preamble to every task
1682
1811
  // prompt so implementers/testers/reviewers know about the Ledger, the
1683
1812
  // dynamic DAG, and the pattern for filing new tasks mid-flight. No
@@ -1735,7 +1864,7 @@ export function registerTeamsCommands(program) {
1735
1864
  }
1736
1865
  }
1737
1866
  try {
1738
- const result = await handleSpawn(mgr, team, agent, effectiveTask, cwd, opts.mode, opts.effort, null, cwd, version, opts.name ?? null, after, opts.model ?? null, envOverrides ?? null, taskType, cloudProviderId, cloudSessionId, opts.repo ?? null, opts.branch ?? null, worktreeName, worktreePath, profileName, hostName, hostTarget, hostRepoPath);
1867
+ const result = await handleSpawn(mgr, team, agent, effectiveTask, cwd, opts.mode, opts.effort, null, cwd, version, opts.name ?? null, after, opts.model ?? null, envOverrides ?? null, taskType, cloudProviderId, cloudSessionId, opts.repo ?? null, opts.branch ?? null, worktreeName, worktreePath, profileName, hostName, hostTarget, hostRepoPath, teamMeta?.project ?? null);
1739
1868
  emit('teams.add', { module: 'teams', team, agent, name: result.name, agent_id: result.agent_id, status: result.status });
1740
1869
  if (isJsonMode(opts)) {
1741
1870
  console.log(JSON.stringify(result, null, 2));
@@ -1920,6 +2049,24 @@ export function registerTeamsCommands(program) {
1920
2049
  return;
1921
2050
  team = picked;
1922
2051
  }
2052
+ // RUSH-2450: a disbanded team must not be re-startable. Orphan PENDING
2053
+ // records can no longer resurrect after purge + saveMeta guard, but if a
2054
+ // caller still points start at a gone team name, fail loud with a reason
2055
+ // instead of launching nothing and looking successful.
2056
+ if (!(await teamExists(team))) {
2057
+ const orphanCount = (await mgr.listByTask(team)).length;
2058
+ const msg = orphanCount > 0
2059
+ ? `Team '${team}' is not registered (disbanded?). ${orphanCount} orphan teammate record(s) remain on disk — re-create the team or purge them before starting.`
2060
+ : `Team '${team}' is not registered (disbanded or never created). Nothing to start.`;
2061
+ if (isJsonMode(opts)) {
2062
+ console.log(JSON.stringify({ team, error: 'team-not-found', message: msg, orphan_teammates: orphanCount }));
2063
+ }
2064
+ else {
2065
+ dieFriction('teams', 'team-not-found', msg, 2);
2066
+ }
2067
+ process.exitCode = 1;
2068
+ return;
2069
+ }
1923
2070
  if (!opts.force && !isJsonMode(opts)) {
1924
2071
  await warnUnsignedTeammates(mgr, team);
1925
2072
  await warnThrottledTeammates(mgr, team);
@@ -2366,11 +2513,14 @@ export function registerTeamsCommands(program) {
2366
2513
  const stopRes = await handleStop(mgr, team);
2367
2514
  if ('error' in stopRes)
2368
2515
  dieFriction('teams', 'stop-failed', stopRes.error);
2516
+ // Snapshot the roster once for worktree cleanup + messaging. Purge below
2517
+ // is the terminal removal of teammate records (RUSH-2450).
2369
2518
  const status = await handleStatus(mgr, team, 'all');
2519
+ const rosterBefore = status.agents;
2370
2520
  // Clean up worktrees for all teammates
2371
2521
  const baseCwd = process.cwd();
2372
2522
  const keptWorktrees = [];
2373
- for (const a of status.agents) {
2523
+ for (const a of rosterBefore) {
2374
2524
  const agent = await mgr.get(a.agent_id);
2375
2525
  if (agent?.worktreeName && agent?.worktreePath) {
2376
2526
  try {
@@ -2397,30 +2547,37 @@ export function registerTeamsCommands(program) {
2397
2547
  catch { /* best-effort */ }
2398
2548
  }
2399
2549
  }
2400
- const removedIds = [];
2401
- if (!opts.keepLogs) {
2402
- const base = await getAgentsDir();
2403
- for (const a of status.agents) {
2404
- try {
2405
- await fs.rm(path.join(base, a.agent_id), { recursive: true, force: true });
2406
- removedIds.push(a.agent_id);
2407
- }
2408
- catch { /* best-effort */ }
2409
- }
2410
- }
2550
+ // Drop the registry entry FIRST so any concurrent supervisor's saveMeta
2551
+ // (RUSH-2450) refuses to re-persist teammates for this team, then purge
2552
+ // the durable teammate records + in-memory cache. Order matters: purge
2553
+ // after removeTeam closes the race where a supervisor re-writes meta
2554
+ // between the two steps.
2411
2555
  const existed = await removeTeam(team);
2556
+ const removedIds = await mgr.purgeByTask(team, { keepLogs: Boolean(opts.keepLogs) });
2412
2557
  if (isJsonMode(opts)) {
2413
- console.log(JSON.stringify({ team, existed, stopped: stopRes.stopped, removed_members: removedIds }, null, 2));
2558
+ console.log(JSON.stringify({
2559
+ team,
2560
+ existed,
2561
+ stopped: stopRes.stopped,
2562
+ removed_members: removedIds,
2563
+ already_gone: !existed && rosterBefore.length === 0 && removedIds.length === 0,
2564
+ }, null, 2));
2414
2565
  return;
2415
2566
  }
2416
- if (!existed && stopRes.stopped.length === 0 && status.agents.length === 0) {
2417
- dieFriction('teams', 'team-not-found', `No team called '${team}'`, 2);
2567
+ if (!existed && stopRes.stopped.length === 0 && rosterBefore.length === 0 && removedIds.length === 0) {
2568
+ // Second disband on a fully-gone team: clean no-op, not a false success
2569
+ // that claims N logs were cleared again.
2570
+ dieFriction('teams', 'team-not-found', `No team called '${team}' (already disbanded or never created)`, 2);
2418
2571
  }
2419
2572
  console.log(chalk.green(`Team ${chalk.cyan(team)} disbanded.`));
2420
2573
  if (stopRes.stopped.length)
2421
2574
  console.log(chalk.gray(` Stopped ${stopRes.stopped.length} working teammate(s).`));
2422
- if (removedIds.length)
2423
- console.log(chalk.gray(` Cleared ${removedIds.length} teammate log(s).`));
2575
+ if (removedIds.length && !opts.keepLogs) {
2576
+ console.log(chalk.gray(` Cleared ${removedIds.length} teammate record(s).`));
2577
+ }
2578
+ else if (removedIds.length && opts.keepLogs) {
2579
+ console.log(chalk.gray(` Removed ${removedIds.length} teammate record(s); logs kept.`));
2580
+ }
2424
2581
  if (keptWorktrees.length) {
2425
2582
  console.log(chalk.yellow(` Kept ${keptWorktrees.length} worktree(s) with uncommitted changes: ${keptWorktrees.join(', ')}`));
2426
2583
  }
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerTicketsCommand(program: Command): void;
@@ -0,0 +1,43 @@
1
+ import { setHelpSections } from '../lib/help.js';
2
+ import { listTickets } from '../lib/tickets/list.js';
3
+ export function registerTicketsCommand(program) {
4
+ const tickets = program
5
+ .command('tickets')
6
+ .description('Read work items from the trackers linked to this workspace.');
7
+ setHelpSections(tickets, {
8
+ examples: `
9
+ agents tickets list --json
10
+ agents tickets list --github-assigned-only --json
11
+ `,
12
+ notes: `
13
+ The response reports each source's availability explicitly. A failed tracker
14
+ never makes another tracker's rows disappear.
15
+ `,
16
+ });
17
+ tickets
18
+ .command('list')
19
+ .description('List workspace tickets from Linear and GitHub.')
20
+ .option('--cwd <path>', 'Workspace used to resolve tracker context')
21
+ .option('--no-linear', 'Exclude Linear tickets')
22
+ .option('--no-github', 'Exclude GitHub issues')
23
+ .option('--github-assigned-only', 'Only include GitHub issues assigned to the current user')
24
+ .option('--json', 'Output machine-readable tickets, cycle metadata, and source availability')
25
+ .action(async (options) => {
26
+ const result = await listTickets({
27
+ cwd: options.cwd ?? process.cwd(),
28
+ linear: options.linear,
29
+ github: options.github,
30
+ githubAssignedOnly: options.githubAssignedOnly === true,
31
+ });
32
+ if (options.json) {
33
+ console.log(JSON.stringify(result, null, 2));
34
+ return;
35
+ }
36
+ console.log(`${result.tickets.length} ticket${result.tickets.length === 1 ? '' : 's'}`);
37
+ for (const source of ['linear', 'github']) {
38
+ const status = result.sources[source];
39
+ if (!status.available && status.error)
40
+ console.error(`${source}: ${status.error}`);
41
+ }
42
+ });
43
+ }
@@ -83,7 +83,6 @@ export function registerUpdateCommand(program) {
83
83
  .command('update [target]')
84
84
  .description('Move a frozen agent installation to a new release, keeping its name and every reference to it')
85
85
  .option('--to <release>', 'Release to move to: latest (default), oldest, or an exact version')
86
- .option('--account <label>', 'Disambiguate by signed-in account when several installations match')
87
86
  .option('--json', 'Machine-readable result')
88
87
  .action(async (target, options) => {
89
88
  try {
@@ -96,7 +95,7 @@ export function registerUpdateCommand(program) {
96
95
  // and reporting it as the pin that was asked for.
97
96
  throw new Error(`${agent} is a single self-updating binary with no pinnable releases — drop --to, or pass --to latest.`);
98
97
  }
99
- const installation = await resolveInstallation(agent, selector, { account: options.account });
98
+ const installation = await resolveInstallation(agent, selector);
100
99
  const strategy = selectUpdateStrategy(agent);
101
100
  if (!options.json && !strategy.transactional) {
102
101
  console.log(chalk.yellow(`${agent} installs one vendor-managed binary, so this update cannot be staged or rolled back; `
@@ -137,12 +136,11 @@ export function registerUpdateCommand(program) {
137
136
  examples: `agents update list claude
138
137
  agents update claude@2.0.65
139
138
  agents update claude@2.0.65 --to 2.1.220
140
- agents update claude --account work
141
139
  agents update claude@2.0.65 --json`,
142
140
  notes: 'An installation keeps its name for life; only the release inside it moves. That is why a default, a project pin, '
143
141
  + 'a routine version, or a profile that names claude@2.0.65 keeps working after you update it. '
144
142
  + 'The selector matches either the installation name or the release it currently carries — when two installations '
145
- + 'share a release, name one or pass --account <label> (see: agents accounts). '
143
+ + 'share a release, select one by its installation name. '
146
144
  + 'The new release is fetched and launched before it replaces the working one, so a bad release leaves your agent running.',
147
145
  });
148
146
  }
@@ -7,11 +7,13 @@ export function registerUsageCommand(program) {
7
7
  addHostOption(program.command('usage [agent]'))
8
8
  .description('Show rate-limit / quota usage per agent')
9
9
  .option('--json', 'Emit machine-readable JSON (per-agent usage snapshot) instead of the table')
10
+ .option('-r, --refresh', 'Collect fresh usage through the shared device coordinator before rendering')
10
11
  .addHelpText('after', `
11
12
  Examples:
12
13
  agents usage Show usage for all installed agents
13
14
  agents usage claude Show usage for Claude only
14
15
  agents usage codex Show usage for Codex only
16
+ agents usage claude --refresh Explicitly refresh Claude once, device-wide
15
17
  agents usage --json Machine-readable snapshot for scripts
16
18
  `)
17
19
  .action(async (agentFilter, options) => {
@@ -35,7 +37,7 @@ Examples:
35
37
  console.log(chalk.gray('No agents installed. Run `agents add <agent>` first.'));
36
38
  return;
37
39
  }
38
- const records = await Promise.all(targets.map((agentId) => collectAgentUsage(agentId)));
40
+ const records = await Promise.all(targets.map((agentId) => collectAgentUsage(agentId, options.refresh === true)));
39
41
  if (options.json) {
40
42
  console.log(JSON.stringify(records, null, 2));
41
43
  return;
@@ -44,7 +46,7 @@ Examples:
44
46
  });
45
47
  }
46
48
  /** Gather one agent's usage snapshot as structured data (shared by both renderers). */
47
- async function collectAgentUsage(agentId) {
49
+ async function collectAgentUsage(agentId, forceRefresh = false) {
48
50
  // Plain name — color is applied only at text-render time (formatAgentUsage), so
49
51
  // `--json` never emits ANSI escapes in `label` (e.g. under FORCE_COLOR=1).
50
52
  const label = AGENTS[agentId].name;
@@ -61,7 +63,7 @@ async function collectAgentUsage(agentId) {
61
63
  if (!info.usageKey && !info.accountKey) {
62
64
  return { agent: agentId, label, status: 'not-signed-in' };
63
65
  }
64
- const usage = await getUsageInfoForIdentity({ agentId, home, info, cliVersion: null });
66
+ const usage = await getUsageInfoForIdentity({ agentId, home, info, cliVersion: null }, forceRefresh ? { forceRefresh: true } : undefined);
65
67
  return { agent: agentId, label, status: 'ok', email: info.email ?? undefined, usage };
66
68
  }
67
69
  /** Render one usage record as the human table section. */
@@ -5,7 +5,7 @@ import * as fs from 'fs';
5
5
  import * as path from 'path';
6
6
  import { select, confirm, checkbox } from '@inquirer/prompts';
7
7
  import { AGENTS, MANAGED_AGENT_IDS, accountOrgBadge, getAccountEmail, getAccountInfo, agentLabel, warnAgentDeprecated, isAgentHardDeprecated, hardDeprecationError, isSelfUpdatingAgent, } from '../lib/agents.js';
8
- import { formatUsageSummary, getUsageInfoForIdentity, getUsageInfoByIdentity, getUsageLookupKey, } from '../lib/usage.js';
8
+ import { formatUsageSummary, getUsageInfoForIdentity, getUsageInfoByIdentity, getUsageLookupKey, isUsageHeadlessScopeError, } from '../lib/usage.js';
9
9
  import { viewAction } from './view.js';
10
10
  import { resolveConfiguredModel, formatAgentIdentity } from '../lib/models.js';
11
11
  import { readManifest, writeManifest, createDefaultManifest } from '../lib/manifest.js';
@@ -31,7 +31,7 @@ function fixSessionFilePaths(agent, version, oldVersionDir) {
31
31
  const trashPath = path.join(trashAgentDir, stamps[0]);
32
32
  updateSessionFilePaths(oldVersionDir, trashPath);
33
33
  }
34
- function formatAccountHint(info, usage, unverified = false) {
34
+ function formatAccountHint(info, usage, unverified = false, headless = false) {
35
35
  const parts = [];
36
36
  if (info.email) {
37
37
  // Same-email accounts can live in different orgs (personal Max vs a Team
@@ -39,7 +39,10 @@ function formatAccountHint(info, usage, unverified = false) {
39
39
  const badge = accountOrgBadge(info);
40
40
  parts.push(badge ? `${info.email} (${badge})` : info.email);
41
41
  }
42
- const usageSummary = formatUsageSummary(info.plan, usage, 3, { unverified });
42
+ const usageSummary = formatUsageSummary(info.plan, usage, 3, {
43
+ unverified: unverified && !headless,
44
+ headless,
45
+ });
43
46
  if (usageSummary)
44
47
  parts.push(usageSummary);
45
48
  if (parts.length === 0)
@@ -540,7 +543,8 @@ export function registerVersionsCommands(program) {
540
543
  // This hint sits in a "switch your default to this version?"
541
544
  // confirm — the one place a stale reading directly steers a
542
545
  // choice, so it must not present an unconfirmed bar as fact.
543
- const accountHint = formatAccountHint(info, usage.snapshot, !!usage.snapshot && !!usage.error);
546
+ const headless = isUsageHeadlessScopeError(usage.error);
547
+ const accountHint = formatAccountHint(info, usage.snapshot, !headless && !!usage.snapshot && !!usage.error, headless);
544
548
  const message = `Switch default from ${agentLabel(agentConfig.id)}@${currentDefault} to ${agentLabel(agentConfig.id)}@${installedVersion}${accountHint}?`;
545
549
  const setAsDefault = await confirm({
546
550
  message,
@@ -708,9 +712,11 @@ export function registerVersionsCommands(program) {
708
712
  const email = accountInfo?.email || '';
709
713
  const usageKey = getUsageLookupKey(accountInfo);
710
714
  const versionUsage = usageKey ? usageByKey.get(usageKey) : undefined;
715
+ const headless = isUsageHeadlessScopeError(versionUsage?.error);
711
716
  const usageSummary = usageKey
712
717
  ? formatUsageSummary(null, versionUsage?.snapshot || null, 3, {
713
- unverified: !!versionUsage?.snapshot && !!versionUsage.error,
718
+ unverified: !headless && !!versionUsage?.snapshot && !!versionUsage.error,
719
+ headless,
714
720
  })
715
721
  : '';
716
722
  if (maxEmailLen > 0) {
@@ -8,7 +8,7 @@ import { AGENTS, ALL_AGENT_IDS, accountDisplayLabel, getAllCliStates, getUnmanag
8
8
  import { ambientClaudeToken, loginHint } from '../lib/signin-badge.js';
9
9
  import { machineId } from '../lib/machine-id.js';
10
10
  import { authCacheKey, formatCheckedAge, readAuthHealthCache } from '../lib/auth-health.js';
11
- import { agentReportsUsage, deriveUsageStatusFromSnapshot, formatUsageSection, formatUsageSummary, formatUsageStatusBadge, getUsageInfoForIdentity, getUsageInfoByIdentity, getUsageLookupKey, } from '../lib/usage.js';
11
+ import { agentReportsUsage, deriveUsageStatusFromSnapshot, formatUsageSection, formatUsageSummary, formatUsageStatusBadge, getUsageInfoForIdentity, getUsageInfoByIdentity, getUsageLookupKey, isUsageHeadlessScopeError, } from '../lib/usage.js';
12
12
  import { readManifest } from '../lib/manifest.js';
13
13
  import { listInstalledVersions, listInstalledVersionDirs, getGlobalDefault, getVersionHomePath, getVersionDir, removeVersion, printTrashFooter, reconcileStaleLatestForAgent, isGlobalBinaryAgent, getLiveVersion, isVersionIsolated, getIsolatedDefault, } from '../lib/versions.js';
14
14
  import { ensureVersionedAliasCurrent, removeShim, } from '../lib/shims.js';
@@ -520,11 +520,13 @@ async function showInstalledVersions(filterAgentId, viewOpts) {
520
520
  const info = rawInfo ? mergeCanonical(rawInfo) : undefined;
521
521
  const usageKey = getUsageLookupKey(info);
522
522
  const usageInfo = usageKey ? usageByKey.get(usageKey) : undefined;
523
- const usageUnavailable = agentReportsUsage(agentId) && !!info?.signedIn && !usageInfo?.snapshot;
524
- const usageUnverified = !!usageInfo?.snapshot && !!usageInfo.error;
523
+ const headless = isUsageHeadlessScopeError(usageInfo?.error);
524
+ const usageUnavailable = agentReportsUsage(agentId) && !!info?.signedIn && !usageInfo?.snapshot && !headless;
525
+ const usageUnverified = !headless && !!usageInfo?.snapshot && !!usageInfo.error;
525
526
  const usageStr = formatUsageSummary(info?.plan || null, usageInfo?.snapshot || null, maxPlanWidth, {
526
527
  unavailable: usageUnavailable,
527
528
  unverified: usageUnverified,
529
+ headless,
528
530
  maxWindows: usageWindowCap,
529
531
  });
530
532
  maxUsageWidth = Math.max(maxUsageWidth, stringWidth(usageStr));
@@ -586,11 +588,13 @@ async function showInstalledVersions(filterAgentId, viewOpts) {
586
588
  }
587
589
  const hasEmail = !!vInfo?.email;
588
590
  const signedIn = !!vInfo?.signedIn;
589
- const usageUnavailable = agentReportsUsage(agentId) && signedIn && !usageInfo?.snapshot;
590
- const usageUnverified = !!usageInfo?.snapshot && !!usageInfo.error;
591
+ const headless = isUsageHeadlessScopeError(usageInfo?.error);
592
+ const usageUnavailable = agentReportsUsage(agentId) && signedIn && !usageInfo?.snapshot && !headless;
593
+ const usageUnverified = !headless && !!usageInfo?.snapshot && !!usageInfo.error;
591
594
  const usageStr = formatUsageSummary(vInfo?.plan || null, usageInfo?.snapshot || null, maxPlanWidth, {
592
595
  unavailable: usageUnavailable,
593
596
  unverified: usageUnverified,
597
+ headless,
594
598
  maxWindows: usageWindowCap,
595
599
  });
596
600
  const hasUsage = usageStr.length > 0;
@@ -712,8 +716,10 @@ async function showInstalledVersions(filterAgentId, viewOpts) {
712
716
  gMaxStatusWidth = Math.max(gMaxStatusWidth, stringWidth(formatUsageStatusBadge(gInfo?.usageStatus)));
713
717
  const gUsageKey = getUsageLookupKey(gInfo);
714
718
  const gUsage = gUsageKey ? usageByKey.get(gUsageKey) : undefined;
719
+ const gHeadless = isUsageHeadlessScopeError(gUsage?.error);
715
720
  const gUsageStr = formatUsageSummary(gInfo?.plan || null, gUsage?.snapshot || null, 3, {
716
- unverified: !!gUsage?.snapshot && !!gUsage.error,
721
+ unverified: !gHeadless && !!gUsage?.snapshot && !!gUsage.error,
722
+ headless: gHeadless,
717
723
  maxWindows: usageWindowCap,
718
724
  });
719
725
  gMaxUsageWidth = Math.max(gMaxUsageWidth, stringWidth(gUsageStr));
@@ -733,8 +739,10 @@ async function showInstalledVersions(filterAgentId, viewOpts) {
733
739
  const parts = [` ${verLabel}${padding}`];
734
740
  const gUsageKey = getUsageLookupKey(gInfo);
735
741
  const gUsage = gUsageKey ? usageByKey.get(gUsageKey) : undefined;
742
+ const gHeadless = isUsageHeadlessScopeError(gUsage?.error);
736
743
  const gUsageStr = formatUsageSummary(gInfo?.plan || null, gUsage?.snapshot || null, 3, {
737
- unverified: !!gUsage?.snapshot && !!gUsage.error,
744
+ unverified: !gHeadless && !!gUsage?.snapshot && !!gUsage.error,
745
+ headless: gHeadless,
738
746
  maxWindows: usageWindowCap,
739
747
  });
740
748
  const gActiveStr = gInfo ? formatLastActive(gInfo.lastActive) : '';
@@ -1,9 +1,9 @@
1
1
  /**
2
- * `agents webhook` — localhost receiver for signed public webhook ingress.
2
+ * `agents webhooks` — localhost receiver for signed public webhook ingress.
3
3
  *
4
4
  * The receiver intentionally binds localhost by default. Public exposure is a
5
5
  * separate `agents funnel up <host>` step so the HTTP process can be tested and
6
6
  * rotated without changing the Tailscale Funnel config.
7
7
  */
8
8
  import type { Command } from 'commander';
9
- export declare function registerWebhookCommand(program: Command): void;
9
+ export declare function registerWebhooksCommand(program: Command): void;