@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
@@ -13,7 +13,7 @@ import * as path from 'path';
13
13
  import { spawn } from 'child_process';
14
14
  import { Option } from 'commander';
15
15
  import chalk from 'chalk';
16
- import { truncate, padRight, humanDuration } from '../lib/format.js';
16
+ import { truncate, padRight, humanDuration, formatBytes } from '../lib/format.js';
17
17
  import { sanitizeForTerminal, redactSecrets } from '../lib/redact.js';
18
18
  import { resolveProjectKey } from '../lib/project-key.js';
19
19
  import { listProjectDefs, resolveProjectNameForCwd } from '../lib/projects.js';
@@ -21,7 +21,8 @@ import ora from 'ora';
21
21
  import { SESSION_AGENTS } from '../lib/session/types.js';
22
22
  import { discoverArtifacts, readArtifact, resolveArtifact } from '../lib/session/artifacts.js';
23
23
  import { looksLikePath, toComparablePath, homeDir, needsWindowsShell, composeWin32CommandLine } from '../lib/platform/index.js';
24
- import { getActiveSessions, sessionProcessIsLocal } from '../lib/session/active.js';
24
+ import { getActiveSessions, describeActiveDiscoveryHealth, sessionProcessIsLocal, backfillActiveRowsFromIndex, isRunningLiveSession, serializeActiveSessionsForJson, serializeSessionsJson } from '../lib/session/active.js';
25
+ export { activeSessionProjectKey, backfillActiveRowsFromIndex, backfillActiveRowsFromMeta, isRunningLiveSession, serializeActiveSessionsForJson, serializeSessionsJson } from '../lib/session/active.js';
25
26
  import { enumerateGhosttyTabs, assignGhosttyTabs } from '../lib/session/ghostty-tabs.js';
26
27
  import { mapPanesToTargets, listClients } from '../lib/tmux/session.js';
27
28
  import { resolveViewingIn, viewingInLabel } from '../lib/session/viewing-in.js';
@@ -33,7 +34,8 @@ import { gatherRemoteAgentsJson } from '../lib/remote-agents-json.js';
33
34
  import { stringWidth, truncateToWidth, padToWidth, terminalWidth } from '../lib/session/width.js';
34
35
  import { inferSessionState } from '../lib/session/state.js';
35
36
  import { discoverSessions, queryIndexedSessions, countSessionsInScope, resolveSessionById, isCompleteSessionId, looksLikeSessionId, searchContentIndex, getSessionRoots, scopeToManaged } from '../lib/session/discover.js';
36
- import { findSessionsById, querySessions, getSessionById, readSessionContent, readArchivedSessionPreview } from '../lib/session/db.js';
37
+ import { findSessionsById, querySessions, readSessionContent, readArchivedSessionPreview } from '../lib/session/db.js';
38
+ import { liveSessionMetas } from '../lib/session/live-metadata.js';
37
39
  import { filterTeamSessions, shouldShowTeamSessions, safeTeamText, groupSessionsByTeam, NO_TEAM_GROUP_KEY, } from '../lib/session/team-filter.js';
38
40
  import { parseSession } from '../lib/session/parse.js';
39
41
  import { runRemoteSessions, buildForwardedArgs, ensureWholeIndex } from '../lib/session/remote.js';
@@ -44,13 +46,13 @@ import { sessionOwnerDevice, RESUME_PINNED_ENV } from '../lib/session/resume-own
44
46
  import { renderMarkdown } from '../lib/markdown.js';
45
47
  import { AGENTS, colorAgent, resolveAgentName } from '../lib/agents.js';
46
48
  import { getShimsDir } from '../lib/state.js';
47
- import { listJobs, listJobsWithRuns, listRuns, getRunDir } from '../lib/routines.js';
49
+ import { listJobs, listJobsWithRuns, listRuns, getRunDir } from '../lib/scheduling/routines.js';
48
50
  import { formatUsd } from '../lib/pricing/cost.js';
49
51
  import { fuzzyMatch, FUZZY_PRESETS } from '../lib/fuzzy.js';
50
52
  import { itemPicker } from '../lib/picker.js';
51
53
  import { resolveSessionAlias } from '../lib/session/actor-sidecar.js';
52
- import { listInstalledVersions, resolveVersionAliasLoose } from '../lib/versions.js';
53
- import { getAgentsInvocation } from '../lib/daemon.js';
54
+ import { listInstalledVersions, resolveVersionAliasLoose } from '../lib/installations/versions.js';
55
+ import { getAgentsInvocation } from '../lib/daemon/daemon.js';
54
56
  import { sessionRecoveryRunArgs } from '../lib/session/recovery.js';
55
57
  import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
56
58
  import { sessionPicker, buildPreview, loadSessionPreviewDigest, formatTodoCompact, githubRepoUrlFromCwd, } from './sessions-picker.js';
@@ -203,13 +205,6 @@ function resolvePathFilter(query) {
203
205
  : query;
204
206
  return path.resolve(expanded);
205
207
  }
206
- function formatBytes(n) {
207
- if (n < 1024)
208
- return `${n} B`;
209
- if (n < 1024 * 1024)
210
- return `${(n / 1024).toFixed(1)} KB`;
211
- return `${(n / (1024 * 1024)).toFixed(1)} MB`;
212
- }
213
208
  async function renderArtifactsForSession(session, listAll, name) {
214
209
  const artifacts = discoverArtifacts(session);
215
210
  if (name !== undefined) {
@@ -430,66 +425,6 @@ export function indexActiveBySessionId(active) {
430
425
  }
431
426
  return byId;
432
427
  }
433
- /**
434
- * Backfill display-only fields onto live rows from the indexed SessionMeta, by
435
- * full session id (RUSH-2205). A running process reports no agent version, and a
436
- * live orphan row usually carries no ticket/PR/label/start-time; the historical
437
- * index does. Only a field the live row LACKS is filled — the live signal always
438
- * wins when present. Pure (no I/O) so the join is unit-tested against fixtures;
439
- * the DB read that builds `metaById` is the caller's concern.
440
- */
441
- export function backfillActiveRowsFromMeta(sessions, metaById) {
442
- for (const s of sessions) {
443
- if (!s.sessionId)
444
- continue;
445
- const m = metaById.get(s.sessionId);
446
- if (!m)
447
- continue;
448
- if (!s.version && m.version)
449
- s.version = m.version;
450
- if (!s.label && m.label)
451
- s.label = m.label;
452
- if (!s.ticket && m.ticketId)
453
- s.ticket = { id: m.ticketId, url: linearIssueUrl(m.ticketId) };
454
- if (!s.pr && m.prUrl)
455
- s.pr = { url: m.prUrl, number: m.prNumber };
456
- if (!s.startedAtMs && m.timestamp) {
457
- const ts = new Date(m.timestamp).getTime();
458
- if (!Number.isNaN(ts))
459
- s.startedAtMs = ts;
460
- }
461
- if (!s.origin && m.origin)
462
- s.origin = m.origin;
463
- if (!s.routineName && m.routineName)
464
- s.routineName = m.routineName;
465
- }
466
- }
467
- /**
468
- * Build the id→meta index the live-row backfill needs, reading the historical
469
- * session DB by full id. Best-effort: a missing or locked DB yields an empty map
470
- * so the live view still renders (mirrors {@link maybeLiveIndex}). Deduplicates
471
- * ids so N rows in one session cost one query.
472
- */
473
- function loadBackfillMetaFor(sessions) {
474
- const byId = new Map();
475
- try {
476
- for (const s of sessions) {
477
- if (!s.sessionId || byId.has(s.sessionId))
478
- continue;
479
- const m = getSessionById(s.sessionId);
480
- if (m)
481
- byId.set(s.sessionId, m);
482
- }
483
- }
484
- catch {
485
- /* enrichment is best-effort — an unavailable DB leaves rows un-backfilled */
486
- }
487
- return byId;
488
- }
489
- /** Add indexed display metadata to active rows for non-renderer consumers. */
490
- export function backfillActiveRowsFromIndex(sessions) {
491
- backfillActiveRowsFromMeta(sessions, loadBackfillMetaFor(sessions));
492
- }
493
428
  /**
494
429
  * The live decoration for a listing row: a status glyph and the latest-turn
495
430
  * preview, when the session is still running. `●` running / `◐` waiting on the
@@ -611,13 +546,6 @@ export function isAwaitingUser(s) {
611
546
  * both carry a genuinely alive pid; unknown liveness (an older peer's
612
547
  * row, or a pid that could never be resolved) does not.
613
548
  */
614
- export function isRunningLiveSession(s) {
615
- if (s.status === 'queued' || s.status === 'closed' || s.status === 'crashed')
616
- return false;
617
- if (s.context === 'cloud')
618
- return Boolean(s.cloudProvider) && Boolean(s.cloudTaskId);
619
- return Boolean(s.machine) && typeof s.pid === 'number' && s.pid > 0 && s.pidAlive === true;
620
- }
621
549
  /** Width of the live status column — `crashed` is the longest word it renders. */
622
550
  const LIVE_STATUS_W = 8;
623
551
  /** The colored, space-padded status cell for a listing row (empty when not live). */
@@ -650,29 +578,6 @@ export function linkCwdCell(s, label) {
650
578
  function modelLabel(model) {
651
579
  return model ? shortenModel(model) : '-';
652
580
  }
653
- /**
654
- * The row shape `agents sessions --active --json` emits. RUSH-1981: a watcher
655
- * joins active sessions on ticketId + project, but the raw ActiveSession nests
656
- * the ticket (`ticket.id`) and carries no `project` at all — so a naive join
657
- * silently drops every row. Emit both as flat, always-present top-level keys
658
- * (null when unknown) alongside the raw fields, so every active row is joinable.
659
- * `project` uses the same derivation SessionMeta does — basename(cwd) (see
660
- * discover.ts) — so the active view and the history view join identically.
661
- *
662
- * `viewingIn` flattens to the same display string the row renderer prints —
663
- * `'codium tab 3'` / `'detached'` / null — so a consumer can tell a watched
664
- * session from an orphaned one (its terminal died, the agent is still running)
665
- * without re-implementing the tmux client lookup.
666
- */
667
- export function serializeActiveSessionsForJson(sessions) {
668
- return sessions.map((s) => ({
669
- ...s,
670
- ticketId: s.ticket?.id ?? null,
671
- project: s.cwd ? path.basename(s.cwd) : null,
672
- prLink: s.pr?.url ?? null,
673
- viewingIn: viewingInLabel(s) ?? null,
674
- }));
675
- }
676
581
  /** Canonical JSON row consumed by resume pickers and other session UIs. */
677
582
  export function serializeSessionPickerRows(sessions, liveSessions, self = machineId()) {
678
583
  const liveById = new Map(liveSessions.filter((row) => row.sessionId).map((row) => [row.sessionId, row]));
@@ -1038,7 +943,7 @@ export function dedupeByMachineSession(sessions) {
1038
943
  return out;
1039
944
  }
1040
945
  /**
1041
- * Narrow a gathered live set to the machines an explicit `--host`/`--device`
946
+ * Narrow a gathered live set to the machines an explicit `--device`
1042
947
  * scope named. The gather picks which boxes to ASK; this asserts what the answer
1043
948
  * may contain, and the two are not the same question: a host-dispatched run is
1044
949
  * reported by the box that dispatched it while executing somewhere else, so
@@ -1094,13 +999,6 @@ export function mergeLocalFirst(sessions, localMachine) {
1094
999
  * newline. The single seam shared by the local `--json` path and the
1095
1000
  * `--json --host` remote fan-out so both emit byte-identical row shapes.
1096
1001
  */
1097
- export function serializeSessionsJson(sessions) {
1098
- const serializable = sessions.map((s) => {
1099
- const { _matchedTerms, _bm25Score, _remote, ...rest } = s;
1100
- return rest;
1101
- });
1102
- return JSON.stringify(serializable, null, 2) + '\n';
1103
- }
1104
1002
  /** The intentionally small metadata contract emitted by `sessions --resolve`.
1105
1003
  * It includes only launch identity needed to route/resume. Transcript paths,
1106
1004
  * extracted plans, costs, and content stay on the machine that owns them. */
@@ -1329,14 +1227,14 @@ async function enrichTmuxLocators(local, surfaces = []) {
1329
1227
  }
1330
1228
  catch { /* non-fatal */ }
1331
1229
  }
1332
- /** Normalize a `--host`/`--device` token (`alias`, `user@host`, `host.domain`)
1230
+ /** Normalize a `--device` token (`alias`, `user@host`, `host.domain`)
1333
1231
  * to the machine id the fan-out and registry key off. */
1334
1232
  function hostToken(h) {
1335
1233
  return normalizeHost(h.split('@').pop() || h);
1336
1234
  }
1337
1235
  /**
1338
1236
  * Whether the local machine's sessions belong in an `--active` view. Local is
1339
- * included by default; an explicit `--host`/`--device` list scopes the view to
1237
+ * included by default; an explicit `--device` list scopes the view to
1340
1238
  * exactly those machines, so local is dropped unless it is itself named (by
1341
1239
  * alias or `user@host`, matched on the normalized machine id). Exported for
1342
1240
  * unit testing without touching SSH or the live process table.
@@ -1347,7 +1245,7 @@ export function shouldIncludeLocal(hosts, self) {
1347
1245
  return hosts.some(h => hostToken(h) === self);
1348
1246
  }
1349
1247
  /**
1350
- * The peers to dial for an `--active` view. No `--host` → `undefined`, which
1248
+ * The peers to dial for an `--active` view. No `--device` → `undefined`, which
1351
1249
  * tells `gatherRemoteActive` to sweep the registered online devices. An
1352
1250
  * explicit list → exactly those, minus this machine (its sessions come from the
1353
1251
  * local seed, so dialing self would be a wasted SSH and a spurious "unreachable"
@@ -1363,9 +1261,9 @@ export function remoteHostsToDial(hosts, self) {
1363
1261
  /**
1364
1262
  * The fleet-wide live-session set behind every `--active` surface. Local sessions
1365
1263
  * come from `getActiveSessions()` and (unless `--local`) the registered online
1366
- * devices from `ag devices` are folded in over SSH. An explicit `--host`/`--device`
1264
+ * devices from `ag devices` are folded in over SSH. An explicit `--device`
1367
1265
  * list SCOPES the sweep to exactly those machines — the local machine is included
1368
- * only when it is itself named — so `--host` is a filter, not an addition.
1266
+ * only when it is itself named — so `--device` is a filter, not an addition.
1369
1267
  *
1370
1268
  * This is the single gather: the static renderer AND the interactive browser both
1371
1269
  * call it, so the browser can never disagree with `--active --json` about which
@@ -1375,7 +1273,7 @@ export function remoteHostsToDial(hosts, self) {
1375
1273
  * RUSH-2062: default path is cache-first against the daemon-warmed shared
1376
1274
  * snapshot (`session-cache.ts`). Menubar / Factory / watchdog / CLI share one
1377
1275
  * warm result instead of each re-running the full SSH fan-out. `forceRefresh`
1378
- * (or `AGENTS_SESSIONS_FORCE_REFRESH=1`) re-gathers live; scoped `--host` lists
1276
+ * (or `AGENTS_SESSIONS_FORCE_REFRESH=1`) re-gathers live; scoped `--device` lists
1379
1277
  * always gather live so a filter never returns a wrong unscoped snapshot.
1380
1278
  */
1381
1279
  export async function gatherActiveSessions(opts = {}) {
@@ -1403,7 +1301,12 @@ export async function gatherActiveSessions(opts = {}) {
1403
1301
  forceRefresh,
1404
1302
  gather: () => gatherActiveSessionsLive({ local: false }),
1405
1303
  });
1406
- return { sessions: loaded.sessions, remoteDeviceCount: loaded.remoteDeviceCount };
1304
+ return {
1305
+ sessions: loaded.sessions,
1306
+ remoteDeviceCount: loaded.remoteDeviceCount,
1307
+ remoteSkipped: loaded.remoteSkipped,
1308
+ remoteDiscoveryFailed: loaded.remoteDiscoveryFailed,
1309
+ };
1407
1310
  }
1408
1311
  return gatherActiveSessionsLive(opts);
1409
1312
  }
@@ -1427,6 +1330,8 @@ async function gatherActiveSessionsLive(opts = {}) {
1427
1330
  if (!s.machine)
1428
1331
  s.machine = self;
1429
1332
  let remoteDeviceCount = 0;
1333
+ let remoteSkipped = [];
1334
+ let remoteDiscoveryFailed = false;
1430
1335
  let merged = local;
1431
1336
  if (!opts.local) {
1432
1337
  const remoteHosts = remoteHostsToDial(opts.hosts, self);
@@ -1435,6 +1340,8 @@ async function gatherActiveSessionsLive(opts = {}) {
1435
1340
  if (!opts.hosts?.length || (remoteHosts && remoteHosts.length > 0)) {
1436
1341
  const remote = await gatherRemoteActive(remoteHosts);
1437
1342
  remoteDeviceCount = remote.deviceCount;
1343
+ remoteSkipped = remote.skipped;
1344
+ remoteDiscoveryFailed = remote.discoveryFailed;
1438
1345
  merged = dedupeByMachineSession([...local, ...remote.sessions]);
1439
1346
  }
1440
1347
  }
@@ -1446,8 +1353,36 @@ async function gatherActiveSessionsLive(opts = {}) {
1446
1353
  return {
1447
1354
  sessions: filterActiveSessionsByHostScope(merged, opts.hosts, self),
1448
1355
  remoteDeviceCount,
1356
+ remoteSkipped,
1357
+ remoteDiscoveryFailed,
1449
1358
  };
1450
1359
  }
1360
+ /**
1361
+ * Explain an empty `--active` result instead of the old flat
1362
+ * "No active agent sessions." either way (RUSH-2507: a live fleet sweep found
1363
+ * ~41 running agents while this printed the same line as a genuinely idle
1364
+ * fleet). Re-probes local tmux health only now, on the empty path, and names
1365
+ * any remote peer that went unheard rather than silently folding it into
1366
+ * "nothing running".
1367
+ */
1368
+ async function describeEmptyActiveDiscovery(opts, remoteSkipped, remoteDiscoveryFailed) {
1369
+ const parts = [];
1370
+ if (!opts.hosts?.length || opts.local) {
1371
+ const health = await describeActiveDiscoveryHealth();
1372
+ if (health.degradedSources.length > 0) {
1373
+ parts.push(`local discovery is degraded (${health.degradedSources.join(', ')} unreachable) — sessions may be hidden, run \`agents doctor\` to diagnose`);
1374
+ }
1375
+ }
1376
+ if (remoteDiscoveryFailed) {
1377
+ parts.push('the device list could not be loaded — no peer was reachable to sweep');
1378
+ }
1379
+ else if (remoteSkipped && remoteSkipped.length > 0) {
1380
+ parts.push(`${remoteSkipped.length} peer(s) went unheard (${remoteSkipped.join(', ')}) — sessions there may be hidden`);
1381
+ }
1382
+ if (parts.length === 0)
1383
+ return 'No active agent sessions.';
1384
+ return `No active agent sessions found, but discovery was degraded: ${parts.join('; ')}.`;
1385
+ }
1451
1386
  /**
1452
1387
  * Render the unified active-session view, grouped by machine. Scoping and the
1453
1388
  * fleet sweep live in {@link gatherActiveSessions}; this owns the presentation
@@ -1457,7 +1392,7 @@ async function gatherActiveSessionsLive(opts = {}) {
1457
1392
  async function renderActiveSessions(asJson, waitingOnly = false, opts = {}) {
1458
1393
  const self = machineId();
1459
1394
  const gathered = await gatherActiveSessions(opts);
1460
- const { remoteDeviceCount } = gathered;
1395
+ const { remoteDeviceCount, remoteSkipped, remoteDiscoveryFailed } = gathered;
1461
1396
  // Backfill agent version, refs, created time, and routine provenance from the
1462
1397
  // historical index. Routine filtering needs that provenance before it narrows
1463
1398
  // the live pool; doing it here also enriches both JSON and human output.
@@ -1489,7 +1424,11 @@ async function renderActiveSessions(asJson, waitingOnly = false, opts = {}) {
1489
1424
  return;
1490
1425
  }
1491
1426
  if (sessions.length === 0) {
1492
- console.log(chalk.gray(waitingOnly ? 'No sessions waiting on input.' : 'No active agent sessions.'));
1427
+ if (waitingOnly) {
1428
+ console.log(chalk.gray('No sessions waiting on input.'));
1429
+ return;
1430
+ }
1431
+ console.log(chalk.gray(await describeEmptyActiveDiscovery(opts, remoteSkipped, remoteDiscoveryFailed)));
1493
1432
  if (!opts.local && !opts.hosts?.length && remoteDeviceCount === 0)
1494
1433
  printCrossMachineTip();
1495
1434
  return;
@@ -1582,8 +1521,8 @@ function useInteractiveBrowser(options) {
1582
1521
  /**
1583
1522
  * A bare interactive fleet listing — no query, no render/filter flag — that the
1584
1523
  * `runSessionBrowser` picker can represent. The single predicate shared by the
1585
- * bare-browser branch and the `--host` early-return guard so they can't drift:
1586
- * when this holds, an explicit `--host`/`--device` scope is folded into the
1524
+ * bare-browser branch and the `--device` early-return guard so they can't drift:
1525
+ * when this holds, an explicit `--device` scope is folded into the
1587
1526
  * browser (preview-rich, selectable) instead of the legacy per-host raw stream.
1588
1527
  */
1589
1528
  export function isBareBrowserListing(options, query) {
@@ -2022,12 +1961,16 @@ function canonicalSessionsCommand(query, options) {
2022
1961
  * Backs `--preview` — the fast path for the "peek before resume" hot loop. */
2023
1962
  export async function renderSessionPreview(query, scope) {
2024
1963
  let outcome = await resolveSessionMetadataValue(query, scope);
2025
- // A just-created transcript may not have reached the incremental index yet.
2026
- // Keep the indexed path hot, but repair a local cold miss once before saying
2027
- // it does not exist. This also preserves Claude history-alias discovery.
1964
+ // resolveSessionMetadataValue already consults the live registry for a running
1965
+ // session with no transcript row (RUSH-2682), so a live session resolves above.
1966
+ // This block still repairs the residual case a session whose transcript is on
1967
+ // disk but not yet indexed (e.g. one that just ended). `waitForScan` makes the
1968
+ // repair honest: when another process holds the scan claim it waits for that
1969
+ // scan instead of returning the stale read. Also preserves Claude history-alias
1970
+ // discovery.
2028
1971
  if (outcome.kind !== 'resolved'
2029
1972
  && (!scope.hosts?.length || shouldIncludeLocal(scope.hosts, machineId()))) {
2030
- const discovered = applyScopeFilters(await discoverSessions({ all: true, cwd: process.cwd(), limit: 5000 }), scope);
1973
+ const discovered = applyScopeFilters(await discoverSessions({ all: true, cwd: process.cwd(), limit: 5000, waitForScan: true }), scope);
2031
1974
  const localMatches = resolveSessionQuery(discovered, query, { indexFallback: false }).matches
2032
1975
  .map(session => ({ ...session, machine: session.machine || machineId() }));
2033
1976
  const exact = localMatches.find(session => selectorAllowsEarlyExit(query)
@@ -2353,7 +2296,7 @@ limitSource) {
2353
2296
  }
2354
2297
  }
2355
2298
  // Normalize convenience flags before any routing reads them: per-agent
2356
- // shorthands fold into --agent, and --device is an alias for --host (both
2299
+ // shorthands fold into --agent; --device and --devices (both
2357
2300
  // resolve against the same device registry).
2358
2301
  applyAgentShorthands(options);
2359
2302
  try {
@@ -2364,7 +2307,7 @@ limitSource) {
2364
2307
  process.exitCode = 1;
2365
2308
  return;
2366
2309
  }
2367
- // --device / --devices both alias --host. A bare `all` / `fleet` sentinel means
2310
+ // --device / --devices values are merged into options.host for internal routing. A bare `all` / `fleet` sentinel means
2368
2311
  // "search every peer" — which is already the default — so it resolves to no
2369
2312
  // explicit host set rather than erroring on a device literally named "all".
2370
2313
  const deviceTargets = [...(options.device ?? []), ...(options.devices ?? [])]
@@ -2445,7 +2388,7 @@ limitSource) {
2445
2388
  await runRemoteSessionsJson(options.host);
2446
2389
  return;
2447
2390
  }
2448
- // A bare interactive `--host`/`--device <box>` listing falls through to the
2391
+ // A bare interactive `--device`/`--device <box>` listing falls through to the
2449
2392
  // fleet browser below, which folds the named host(s) into the same merged,
2450
2393
  // preview-rich, selectable view as the local listing (via gatherRemoteList).
2451
2394
  // A query, a render/filter flag, or a non-interactive caller keeps the legacy
@@ -3797,7 +3740,7 @@ export function formatPickerLabel(s, query, cols = {}, ssh, host = '', bookmarke
3797
3740
  /** Hints rotated above the picker so the flags/features stay discoverable. */
3798
3741
  const PICKER_TIPS = [
3799
3742
  'Tip: narrow with -a/--agent (e.g. -a codex), or --project <name> for another folder.',
3800
- "Tip: --all searches every directory; -H/--host <machine> folds in another box's sessions.",
3743
+ "Tip: --all searches every directory; -D/--device <machine> folds in another box's sessions.",
3801
3744
  'Tip: just type to fuzzy-search prompts and responses; press space to preview a session.',
3802
3745
  'Tip: --since 2d / --until <date> bound the time window; pass a session id to open it directly.',
3803
3746
  ];
@@ -3865,7 +3808,7 @@ export async function handlePickedSession(picked) {
3865
3808
  if (isIdlessLiveRow(picked.session)) {
3866
3809
  const where = picked.session.machine ? ` on ${picked.session.machine}` : '';
3867
3810
  console.log(chalk.yellow(`This session hasn't reported a session id yet — nothing to open${where}.`));
3868
- console.log(chalk.gray(`Watch for it with: agents sessions --active${picked.session.machine ? ` --host ${picked.session.machine}` : ''}`));
3811
+ console.log(chalk.gray(`Watch for it with: agents sessions --active${picked.session.machine ? ` --device ${picked.session.machine}` : ''}`));
3869
3812
  return;
3870
3813
  }
3871
3814
  // Reading and resuming are on DIFFERENT machines' terms, and conflating them
@@ -3902,9 +3845,9 @@ export async function resumeOnOwnerIfRemote(session) {
3902
3845
  if (!owner)
3903
3846
  return false;
3904
3847
  console.log(chalk.gray(`Resuming ${session.shortId} on ${owner} over SSH...`));
3905
- // `agents resume <id>` is the strict single-session path — one pick, one
3906
- // resume. (`sessions resume <shortId>` would re-open a picker over there.)
3907
- const rc = await runOnPeer(['resume', session.id], owner, {
3848
+ // `agents sessions resume <id>` is the strict single-session path — one pick, one
3849
+ // resume.
3850
+ const rc = await runOnPeer(['sessions', 'resume', session.id], owner, {
3908
3851
  tty: true,
3909
3852
  env: { [RESUME_PINNED_ENV]: '1' },
3910
3853
  });
@@ -3922,7 +3865,7 @@ export async function resumeOnOwnerIfRemote(session) {
3922
3865
  export async function resumeSessionInPlace(session) {
3923
3866
  // This function is the LOCAL takeover, and every caller is responsible for
3924
3867
  // routing a peer-owned session before it gets here (the picker above,
3925
- // `agents resume`, `sessions attach`). Reaching it with one anyway means a
3868
+ // `agents sessions resume`, `sessions attach`). Reaching it with one anyway means a
3926
3869
  // caller skipped that step, so refuse rather than start the harness against
3927
3870
  // state this box does not have — the `fs.existsSync(session.cwd)` fallback
3928
3871
  // just below is exactly how that used to pass unnoticed, quietly swapping in
@@ -3930,7 +3873,7 @@ export async function resumeSessionInPlace(session) {
3930
3873
  const owner = sessionOwnerDevice(session);
3931
3874
  if (owner) {
3932
3875
  console.error(chalk.red(`Session ${session.shortId} belongs to ${owner} — it cannot resume on this machine.`));
3933
- console.error(chalk.gray(` Resume it there: agents resume ${session.id}`));
3876
+ console.error(chalk.gray(` Resume it there: agents sessions resume ${session.id}`));
3934
3877
  process.exitCode = 1;
3935
3878
  return;
3936
3879
  }
@@ -4792,14 +4735,60 @@ export function metadataResolveOutcome(localMatches, remote, selector) {
4792
4735
  return { kind: 'ambiguous', candidates };
4793
4736
  return { kind: 'resolved', session: candidates[0].hits[0].session };
4794
4737
  }
4795
- /** Reusable local-first resolver for `agents run --resume` and `agents resume`.
4796
- * Full UUIDs hit the local SQLite index without any SSH fan-out. */
4797
- export async function resolveSessionMetadataValue(selector, scope = {}, deps = { gatherRemoteList }) {
4738
+ /**
4739
+ * Local metadata candidates for a selector: the indexed SQLite rows, plus when
4740
+ * an id-shaped selector misses the index entirely the live-session registry
4741
+ * (RUSH-2682).
4742
+ *
4743
+ * Indexing is lazy (it only runs inside `discoverSessions`), so a session THIS
4744
+ * box just started is "running" in `agents sessions --active` minutes before its
4745
+ * transcript reaches the local index. Every id resolver (`preview`, `resume`,
4746
+ * `focus`, and the fan-out peer that answers `--resolve-safe-v1`) therefore
4747
+ * consults the SAME live registry `--active` reads before declaring a running
4748
+ * session non-existent. It reshapes process state the registry already computed;
4749
+ * it parses no transcript and renders nothing. The live path is entered ONLY on a
4750
+ * cold id miss, so an indexed hit keeps its richer row and keyword resolution is
4751
+ * unchanged.
4752
+ */
4753
+ export async function computeLocalMetadataMatches(selector, scope, deps = {}) {
4798
4754
  const localMachine = machineId();
4799
4755
  const includeLocal = !scope.hosts?.length || shouldIncludeLocal(scope.hosts, localMachine);
4800
- const indexed = includeLocal ? indexedRowsForSelector(selector, scope) : [];
4801
- const localMatches = resolveIndexedMetadataRows(indexed, selector)
4802
- .map(session => ({ ...session, machine: session.machine || localMachine }));
4756
+ if (!includeLocal)
4757
+ return [];
4758
+ const indexed = resolveIndexedMetadataRows(indexedRowsForSelector(selector, scope), selector);
4759
+ if (indexed.length > 0 || !looksLikeSessionId(selector)) {
4760
+ return indexed.map(session => ({ ...session, machine: session.machine || localMachine }));
4761
+ }
4762
+ const live = await liveMetadataMatches(selector, scope, localMachine, deps);
4763
+ return live.map(session => ({ ...session, machine: session.machine || localMachine }));
4764
+ }
4765
+ /**
4766
+ * Resolve an id-shaped selector against the local live-session registry
4767
+ * (RUSH-2682). Reads the daemon-warmed active snapshot first (cheap); if that
4768
+ * snapshot predates a just-started session and misses, it forces ONE fresh
4769
+ * gather before conceding, so a session started seconds ago resolves
4770
+ * synchronously. Never throws — a degraded registry read yields no candidates,
4771
+ * so the caller falls through to the ordinary not-found path.
4772
+ */
4773
+ export async function liveMetadataMatches(selector, scope, self, deps = {}) {
4774
+ const load = deps.loadActive ?? loadLocalActiveSessions;
4775
+ const match = (metas) => resolveIndexedMetadataRows(applyScopeFilters(metas, scope), selector);
4776
+ try {
4777
+ const cached = liveSessionMetas((await load()).sessions, self, Date.now());
4778
+ const hit = match(cached);
4779
+ if (hit.length > 0)
4780
+ return hit;
4781
+ const fresh = liveSessionMetas((await load({ forceRefresh: true })).sessions, self, Date.now());
4782
+ return match(fresh);
4783
+ }
4784
+ catch {
4785
+ return [];
4786
+ }
4787
+ }
4788
+ /** Reusable local-first resolver for `agents run --resume` and `agents sessions resume`.
4789
+ * Full UUIDs hit the local SQLite index without any SSH fan-out. */
4790
+ export async function resolveSessionMetadataValue(selector, scope = {}, deps = { gatherRemoteList }) {
4791
+ const localMatches = await computeLocalMetadataMatches(selector, scope, deps);
4803
4792
  // A full-UUID local hit resolves with ZERO SSH: a UUID is globally unique, so
4804
4793
  // finding it locally is the whole answer and no peer is dialed. (A label is
4805
4794
  // NOT resolved local-only here — it can collide with a same-label session on a
@@ -4835,11 +4824,11 @@ export async function resolveSessionMetadataValue(selector, scope = {}, deps = {
4835
4824
  * injectable) so tests can drive this real call site against a fake fan-out
4836
4825
  * instead of only the pure resolver it wraps. */
4837
4826
  export async function resolveSessionMetadata(selector, scope, deps = { gatherRemoteList }) {
4838
- const localMachine = machineId();
4839
- const includeLocal = !scope.hosts?.length || shouldIncludeLocal(scope.hosts, localMachine);
4840
- const indexed = includeLocal ? indexedRowsForSelector(selector, scope) : [];
4841
- const localMatches = resolveIndexedMetadataRows(indexed, selector)
4842
- .map(session => ({ ...session, machine: session.machine || localMachine }));
4827
+ // Same local candidate set as resolveSessionMetadataValue, so the peer
4828
+ // answering a fan-out (`--resolve-safe-v1`, NO_FANOUT) surfaces a running
4829
+ // session its own index has not caught yet — the cross-device half of the
4830
+ // RUSH-2682 fix, since the parent's fan-out reads this box's answer.
4831
+ const localMatches = await computeLocalMetadataMatches(selector, scope, deps);
4843
4832
  // A peer is already inside gatherRemoteList. Return all local candidates so
4844
4833
  // the parent can distinguish a fleet-wide unique match from an ambiguity.
4845
4834
  if (process.env[NO_FANOUT_ENV] === '1') {
@@ -4940,7 +4929,7 @@ export function registerSessionsCommands(program) {
4940
4929
  .option('--query <clause>', 'Search text; repeat with --include tools to require distinct matching calls', collectQueryClause, [])
4941
4930
  .option('--resolve <selector>', 'Resolve one full ID, unique prefix, or keyword query to safe session metadata (requires --json; searches the fleet unless --local)')
4942
4931
  .addOption(new Option('--resolve-safe-v1 <selector>').hideHelp())
4943
- .description('Find, browse, and read agent conversation transcripts. Live roster: `agents sessions --active` (alias: `agents roster`).')
4932
+ .description('Find, browse, and read agent conversation transcripts. Live roster: `agents sessions --active`.')
4944
4933
  .option('-a, --agent <agent>', 'Filter by agent type and version (e.g., claude, codex@0.116.0)')
4945
4934
  .addOption(new Option('--session-version <version>', 'Internal spelling for the public sessions --version filter')
4946
4935
  .hideHelp())
@@ -4989,8 +4978,7 @@ export function registerSessionsCommands(program) {
4989
4978
  .option('--flat', 'Plain flat table (one row per session) instead of the grouped project overview')
4990
4979
  .option('--no-live', 'Do not enrich the listing with live status/preview for running sessions')
4991
4980
  .option('--cloud', 'Source sessions from Rush Cloud (captured runs) instead of local disk')
4992
- .option('-H, --host <target...>', 'Run this query on remote machine(s) over SSH (host alias or user@host; repeatable)')
4993
- .option('--device <target...>', 'Alias for --host (device alias from `agents devices`; repeatable). `--device all` searches the whole fleet (the default).')
4981
+ .option('-D, --device <target...>', 'Run this query on remote machine(s) over SSH (device alias from `agents devices`, user@host, or `all` to search the whole fleet; repeatable)')
4994
4982
  .addOption(new Option('--devices <target...>', 'Plural alias for --device (accepts `all`/`fleet`).').hideHelp())
4995
4983
  .option('--fleet', 'With --include tools: query every registered online compute device and merge compact matches')
4996
4984
  .option('--count', 'With one program:<name> tool query: count static occurrences, containing calls, and sessions')
@@ -5075,10 +5063,10 @@ export function registerSessionsCommands(program) {
5075
5063
  agents sessions --resolve d3470b57 --json
5076
5064
 
5077
5065
  # Search another machine's sessions live over SSH (no sync needed)
5078
- agents sessions "auth bug" --last 3 --host yosemite-s1
5066
+ agents sessions "auth bug" --last 3 --device yosemite-s1
5079
5067
 
5080
5068
  # Fan the same query out across several machines
5081
- agents sessions --all "deploy script" --host box-a --host box-b
5069
+ agents sessions --all "deploy script" --device box-a --device box-b
5082
5070
  `,
5083
5071
  notes: `
5084
5072
  Session lifecycle — ONE verb gets you back in, it detects the state:
@@ -5090,7 +5078,7 @@ export function registerSessionsCommands(program) {
5090
5078
  - The interactive listing and every live-status flag fold in your other online machines automatically (live over SSH, no sync) — each row is labelled by host, this machine first. Use --local to skip the fan-out; single-id lookups stay local.
5091
5079
  - --all is not a device flag: it widens historical directory and time filters. Fleet collection is already the default. A status flag (--working/--idle/--waiting/--orphan/--crashed/--closed/--abandoned/--queued/--unknown) implies --active; combine status flags for a union.
5092
5080
  - --version <version> requires --agent and is equivalent to --agent <agent@version>.
5093
- - --host runs the query on the remote's own index over SSH (host alias or user@host); repeat or pass several to fan out. SSH access is the only auth.
5081
+ - --device runs the query on the remote's own index over SSH (host alias or user@host); repeat or pass several to fan out. SSH access is the only auth.
5094
5082
  - --in-team matches both ends of the lineage: the session that ran 'agents teams create/add', and (with --teams) that team's teammates. In the interactive list, 't' cycles the same filter over the teams in view.
5095
5083
  - --include and --exclude are mutually exclusive.
5096
5084
  - With --include tools, repeat --query for same-session AND across distinct calls. Fields: tool, program, input, output, status, exit, error.
@@ -5142,8 +5130,7 @@ export function registerSessionsCommands(program) {
5142
5130
  .option('-a, --agent <agent>', 'Narrow the ID to one agent type/version')
5143
5131
  .option('-p, --project <name>', 'Narrow the ID to one project')
5144
5132
  .option('--local', 'Only this machine; do not resolve the ID across the fleet')
5145
- .option('-H, --host <target...>', 'Resolve only on the named device(s)')
5146
- .option('--device <target...>', 'Alias for --host')
5133
+ .option('-D, --device <target...>', 'Resolve only on the named device(s)')
5147
5134
  .option('--json', 'Output the session preview as JSON');
5148
5135
  setHelpSections(previewCmd, {
5149
5136
  examples: `
@@ -5194,31 +5181,6 @@ export function registerSessionsCommands(program) {
5194
5181
  registerSessionsInsightsCommand(sessionsCmd);
5195
5182
  registerSessionsOptimizeCommand(sessionsCmd);
5196
5183
  registerSessionsWatchCommand(sessionsCmd);
5197
- // Observe-umbrella alias (Phase 3): roster → sessions --active.
5198
- registerSessionsObserveAliases(program);
5199
- }
5200
- /**
5201
- * `roster` → sessions --active. Registered with the sessions module so the
5202
- * lazy loader for `roster` also registers the real `sessions` command for re-parse.
5203
- */
5204
- function registerSessionsObserveAliases(program) {
5205
- program
5206
- .command('roster')
5207
- .description('Live agent roster (alias of `agents sessions --active`). Who is running right now.')
5208
- .allowUnknownOption()
5209
- .allowExcessArguments()
5210
- .action(async () => {
5211
- const { expandObserveAlias } = await import('../lib/observe-aliases.js');
5212
- const rest = process.argv.slice(3);
5213
- const expanded = expandObserveAlias('roster', rest);
5214
- if (!expanded) {
5215
- console.error(chalk.red('Unknown observe alias: roster'));
5216
- process.exit(1);
5217
- }
5218
- if (process.stderr.isTTY)
5219
- process.stderr.write(chalk.gray(`${expanded.note}\n`));
5220
- await program.parseAsync(['node', 'agents', ...expanded.argv]);
5221
- });
5222
5184
  }
5223
5185
  function formatNoSessionsMessage(showAll, project) {
5224
5186
  const projectQuery = project?.trim();
@@ -33,7 +33,7 @@ function openPane(pane) {
33
33
  export async function runComputerWizard() {
34
34
  if (os.platform() !== 'darwin') {
35
35
  console.log(chalk.yellow('`agents setup computer` configures the macOS helper (local control).'));
36
- console.log(chalk.dim('On Windows, provision a remote host from a Mac/Linux box instead: `agents computer setup --host <device>`.'));
36
+ console.log(chalk.dim('On Windows, provision a remote host from a Mac/Linux box instead: `agents computer setup --device <device>`.'));
37
37
  return false;
38
38
  }
39
39
  // 1. Download + verify + install the signed, notarized helper.
@@ -10,6 +10,7 @@ import { spawnSync } from 'node:child_process';
10
10
  import { getCliLaunch } from '../lib/cli-entry.js';
11
11
  import { loadDevices } from '../lib/devices/registry.js';
12
12
  import { runDeviceSync } from '../lib/devices/sync.js';
13
+ import { setDeviceDiscoveryStatus } from '../lib/devices/discovery-policy.js';
13
14
  import { tailscaleStatusJson } from '../lib/devices/tailscale.js';
14
15
  import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
15
16
  import { maybePickInteractiveHost } from './setup-preferences.js';
@@ -107,6 +108,8 @@ async function syncDevices(opts) {
107
108
  console.error(chalk.red(`Tailscale discovery failed: ${res.reason ?? 'unknown error'}`));
108
109
  return false;
109
110
  }
111
+ for (const name of res.syncedNames)
112
+ setDeviceDiscoveryStatus(name, 'approved');
110
113
  const extra = res.pending.length ? chalk.gray(` (${res.pending.length} new)`) : '';
111
114
  console.log(chalk.green(`Synced ${res.synced} device${res.synced === 1 ? '' : 's'} from Tailscale${extra}.`));
112
115
  return true;