@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
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Remote secrets — read and use `agents secrets` bundles that live on another
3
- * host, over the same hardened SSH path that `agents secrets export --host`
3
+ * host, over the same hardened SSH path that `agents secrets export --device`
4
4
  * (the write inverse) already uses.
5
5
  *
6
6
  * This is the READ / USE direction:
@@ -10,7 +10,7 @@
10
10
  * inject it ephemerally — never written to this machine's keychain.
11
11
  *
12
12
  * Trust model: relies on the operator's existing SSH access to the host (same
13
- * boundary as `export --host` / `run --host`). Bundle names are shell-quoted
13
+ * boundary as `export --device` / `run --device`). Bundle names are shell-quoted
14
14
  * into the remote command; resolved VALUES return over ssh stdout; a forwarded
15
15
  * file-backend passphrase travels over ssh stdin (first line) so it never lands
16
16
  * in argv / `ps` / remote shell history. Nothing is persisted locally.
@@ -39,9 +39,8 @@ function hostKeyLookupName(target) {
39
39
  * - **Managed pinned host keys.** Verify against the CLI-owned known_hosts
40
40
  * store (`known-hosts.ts`), not `~/.ssh/known_hosts`. A CHANGED key on a
41
41
  * known host is refused (`StrictHostKeyChecking` `yes` once pinned,
42
- * `accept-new` which still refuses a changed key, only learns a genuinely
43
- * new one before that). So a machine-in-the-middle swapping a pinned host's
44
- * key can never receive or return a secret.
42
+ * `accept-new` before that). Callers that copy durable provider credentials
43
+ * must separately require an existing pin before invoking this transport.
45
44
  * - **No multiplex reuse.** `multiplex: false` — a credential channel never
46
45
  * leaves a persistent `ControlMaster` socket lingering (60s `ControlPersist`)
47
46
  * that any other `agents` invocation to that host would silently reuse.
@@ -49,6 +48,13 @@ function hostKeyLookupName(target) {
49
48
  export function credentialTransportSshOpts(target) {
50
49
  return { hostKeyOpts: hostKeyCheckingOpts(isHostPinned(hostKeyLookupName(target))), multiplex: false };
51
50
  }
51
+ /** Refuse durable credential transfer until the destination SSH key is pinned. */
52
+ export function assertCredentialTransportHostPinned(target, pinned = isHostPinned(hostKeyLookupName(target))) {
53
+ if (pinned)
54
+ return;
55
+ throw new Error(`Refusing to transfer provider credentials to '${target}' before its SSH host key is pinned. ` +
56
+ `Connect once with 'agents ssh ${target}' and verify the host, then retry.`);
57
+ }
52
58
  /**
53
59
  * Trust boundary for a remote-resolved env map. A peer's `secrets export` output
54
60
  * is untrusted input: a compromised or misconfigured host could return keys that
@@ -85,9 +91,9 @@ function osForTarget(target, lookupName) {
85
91
  return byName ?? resolveRemoteOsSync(target.split('@').pop() ?? target);
86
92
  }
87
93
  /**
88
- * Resolve a `--host` value to an ssh target STRING for the remote-secrets path.
94
+ * Resolve a `--device` value to an ssh target STRING for the remote-secrets path.
89
95
  * Delegates to the single host/device resolver (`resolveHost`, RUSH-1967) so a
90
- * name here dials the exact same box `run --host` does; on a miss, treats the
96
+ * name here dials the exact same box `run --device` does; on a miss, treats the
91
97
  * value as a raw ssh target and validates it against injection. Named distinctly
92
98
  * from `../devices/resolve-target.ts` (which returns richer shapes) so importing
93
99
  * the wrong one can't silently change which machine you dial.
@@ -102,7 +108,7 @@ export async function resolveHostSshTarget(nameOrAlias) {
102
108
  /**
103
109
  * Merge `--host <single>` / `--hosts <a,b,c>` (and their `--device` / `--devices`
104
110
  * aliases) into an ordered, de-duplicated list. All four flags compose; any alone
105
- * works. `--device`/`--devices` resolve identically to `--host`/`--hosts` so the
111
+ * works. `--device`/`--devices` resolve identically to `--device`/`--hosts` so the
106
112
  * fleet-wide `--device` vocabulary (see `agents run --device`, `agents feed --host`)
107
113
  * works on the secrets remote commands too. Empty when none is set.
108
114
  */
@@ -158,7 +164,7 @@ export function remoteSecretsRaw(target, args, opts = {}) {
158
164
  // to multiplex — see `credentialTransportSshOpts` (RUSH-2527). A `-tt` session
159
165
  // (a remote reveal/passphrase prompt) additionally allocates a PTY and never
160
166
  // multiplexes, and it COMPOSES with the secret posture: a `view --reveal` over
161
- // `--host` both prompts AND streams the plaintext value back over ssh stdout,
167
+ // `--device` both prompts AND streams the plaintext value back over ssh stdout,
162
168
  // so it needs the managed host-key pin too — `tty` must not short-circuit past
163
169
  // `secret`. A plain browse `list` passes neither and keeps the shared baseline.
164
170
  const posture = opts.secret ? credentialTransportSshOpts(target) : {};
@@ -180,13 +186,13 @@ export function remoteSecretsRaw(target, args, opts = {}) {
180
186
  * appear (the macOS file-store guard then hard-errors "needs
181
187
  * AGENTS_SECRETS_PASSPHRASE") — this inherits the caller's real terminal, so the
182
188
  * remote sees a genuine TTY and its hidden passphrase prompt surfaces and reads
183
- * the keystrokes. This is the transport for `unlock --host`: you type the remote
189
+ * the keystrokes. This is the transport for `unlock --device`: you type the remote
184
190
  * bundle's passphrase at your own terminal. Output is NOT captured (it streams
185
191
  * to the terminal); only the exit code is returned.
186
192
  */
187
193
  export function remoteSecretsStream(target, args, opts = {}) {
188
194
  const remoteCmd = buildRemoteAgentsInvocation(['secrets', ...args], undefined, osForTarget(target, opts.osLookupName));
189
- // `unlock --host` carries the remote bundle's passphrase to the destination over
195
+ // `unlock --device` carries the remote bundle's passphrase to the destination over
190
196
  // this interactive channel, so it is secret-bearing: pin the managed host key
191
197
  // (a changed key is refused) and never multiplex (RUSH-2527).
192
198
  return sshStream(target, remoteCmd, { tty: true, ...credentialTransportSshOpts(target) });
@@ -346,7 +352,7 @@ export function keychainWriteFailureMessage(host, bundle, reason) {
346
352
  `A macOS login keychain is LOCKED under headless SSH, so a keychain-backed write ` +
347
353
  `lands the bundle metadata but no readable secret items, and later reads fail with ` +
348
354
  `"stored item '…' not found". Re-run with a headless-readable backend:\n` +
349
- ` agents secrets export ${bundle} --host ${host} --remote-backend file\n` +
355
+ ` agents secrets export ${bundle} --device ${host} --remote-backend file\n` +
350
356
  `(needs AGENTS_SECRETS_PASSPHRASE set locally), or unlock the remote keychain first ` +
351
357
  `(e.g. an interactive login / \`agents secrets unlock\` on ${host}) and retry.`);
352
358
  }
@@ -400,7 +406,7 @@ export function verifyRemoteKeychainPush(target, bundle, pushedKeys, opts = {})
400
406
  }
401
407
  /**
402
408
  * The `bash -lc` command + stdin payload that drives a **file-backed** remote
403
- * import for `secrets export --host … --remote-backend file`.
409
+ * import for `secrets export --device … --remote-backend file`.
404
410
  *
405
411
  * The file store is passphrase-free by default: with `AGENTS_SECRETS_PASSPHRASE`
406
412
  * unset the remote `agents secrets import --backend file` auto-provisions the
@@ -422,7 +428,8 @@ export function verifyRemoteKeychainPush(target, bundle, pushedKeys, opts = {})
422
428
  */
423
429
  export function buildRemoteFileImportCommand(bundle, dotenv, opts = {}) {
424
430
  const force = opts.force ? ' --force' : '';
425
- const importCmd = `agents secrets import ${shellQuote(bundle)} --from - --backend file${force}`;
431
+ const policy = opts.policyNever ? ' --policy never --i-understand' : '';
432
+ const importCmd = `agents secrets import ${shellQuote(bundle)} --from - --backend file${force}${policy}`;
426
433
  const passphrase = opts.passphrase ?? '';
427
434
  if (passphrase) {
428
435
  // Opt-in shared passphrase: read it off the FIRST stdin line, export it, then
@@ -237,7 +237,7 @@ export function getVaultSession() {
237
237
  function requireVaultKey() {
238
238
  const session = getVaultSession();
239
239
  if (!session.loggedIn) {
240
- throw new Error('Not logged in. Run: agents login');
240
+ throw new Error('Synced secrets locked. Run: agents secrets vault unlock');
241
241
  }
242
242
  return session.key;
243
243
  }
@@ -259,7 +259,7 @@ function parseVaultItem(item) {
259
259
  function vaultMissingError(file) {
260
260
  return new Error(`Vault file is missing: ${file}. A vault was created but the file is gone` +
261
261
  ' (a sync conflict, an undownloaded placeholder, or an accidental move/delete).' +
262
- ' Restore it before writing, or run: agents login --create --force to start over.');
262
+ ' Restore it before writing, or run: agents secrets vault unlock --create --force to start over.');
263
263
  }
264
264
  function readVaultData() {
265
265
  const file = vaultPath();
@@ -6,7 +6,7 @@
6
6
  import { resultOf } from '../types.js';
7
7
  import { AGENTS } from '../../agents.js';
8
8
  import { getPathShadowingExecutable, adoptShadowingLauncher, listAgentsWithNonIsolatedInstalledVersions, } from '../../shims.js';
9
- import { getGlobalDefault } from '../../versions.js';
9
+ import { getGlobalDefault } from '../../installations/versions.js';
10
10
  export const shadowingCheck = {
11
11
  id: 'shadowing',
12
12
  title: 'Launcher shadowing the version-managed shim',
@@ -5,7 +5,7 @@
5
5
  import { resultOf } from '../types.js';
6
6
  import { AGENTS } from '../../agents.js';
7
7
  import { createShim, ensureShimCurrent, ensureVersionedAliasCurrent, isShimCurrent, isVersionedAliasCurrent, removeShim, shimExists, shimPointsAtLiveInstall, removeLegacyUserShim, listAgentsWithInstalledVersions, listAgentsWithNonIsolatedInstalledVersions, listShimFileNames, pruneOrphanedCommandShim, } from '../../shims.js';
8
- import { listInstalledVersions } from '../../versions.js';
8
+ import { listInstalledVersions } from '../../installations/versions.js';
9
9
  export const shimsCheck = {
10
10
  id: 'shims',
11
11
  title: 'Dispatch shims + versioned aliases',
@@ -200,7 +200,24 @@ export interface MultiInstallInventoryEntry {
200
200
  packageRoot: string;
201
201
  version: string;
202
202
  note: string;
203
+ /** True for the copy that is currently executing. */
204
+ running: boolean;
205
+ /**
206
+ * True when a bare `agents doctor --fix` deletes this copy (RUSH-2415:
207
+ * npx-cache / unsafe-legacy / pre-1.22.30 with a fixed peer). False for the
208
+ * running copy and for any duplicate --fix will not touch — a healthy
209
+ * >=1.22.30 peer, or a pre-1.22.30 copy with no fixed peer to fall back to;
210
+ * both need the manual command from manualUninstallCommand() (RUSH-2705/2713).
211
+ */
212
+ autoPurgeable: boolean;
203
213
  }
214
+ /**
215
+ * The exact shell command that removes the install at `packageRoot` by hand —
216
+ * the remedy for duplicates `doctor --fix` deliberately will not purge
217
+ * (RUSH-2705). `--prefix` pins the target tree no matter which npm binary
218
+ * PATH resolves, mirroring installPackageIntoPrefix.
219
+ */
220
+ export declare function manualUninstallCommand(packageRoot: string): string;
204
221
  export declare function buildMultiInstallInventory(runningRoot: string, runningVersion: string, installs: AgentsCliInstall[]): MultiInstallInventoryEntry[];
205
222
  /** Why a discovered install is safe to delete without an interactive confirm. */
206
223
  export type RemovableInstallReason = 'npx-cache' | 'unsafe-legacy-helper' | 'pre-fixed-version';
@@ -250,6 +267,27 @@ export declare function purgeRemovableAgentsCliInstalls(candidates: RemovableAge
250
267
  dryRun?: boolean;
251
268
  runningRoot?: string;
252
269
  }): PurgeRemovableInstallsResult;
270
+ /** A detected duplicate that `doctor --fix` will not purge (RUSH-2705). */
271
+ export interface UnresolvedDuplicateInstall {
272
+ packageRoot: string;
273
+ version: string;
274
+ /** Exact shell command that removes this copy by hand. */
275
+ manualRemoveCommand: string;
276
+ }
277
+ export interface RemediateStaleInstallsResult extends PurgeRemovableInstallsResult {
278
+ inventory: MultiInstallInventoryEntry[];
279
+ candidates: RemovableAgentsCliInstall[];
280
+ /**
281
+ * Duplicates detected but NOT auto-purged, for either reason:
282
+ * 1. a healthy >=1.22.30 global (safe, just redundant), or
283
+ * 2. a pre-1.22.30 copy left alone only because no fixed peer exists to fall
284
+ * back to (the anti-stranding guard) — this one is genuinely vulnerable,
285
+ * not healthy.
286
+ * Either way the caller must surface manualRemoveCommand — otherwise the
287
+ * multi-install warning keeps firing with no working remedy (RUSH-2705/2713).
288
+ */
289
+ unresolved: UnresolvedDuplicateInstall[];
290
+ }
253
291
  /**
254
292
  * Scan + classify + purge in one call. Used by `agents doctor --fix` and
255
293
  * `agents upgrade` so both paths remediate the same set of latent copies.
@@ -260,10 +298,7 @@ export declare function remediateStaleAgentsCliInstalls(opts: {
260
298
  pathEnv?: string;
261
299
  findOpts?: FindAgentsCliInstallsOptions;
262
300
  dryRun?: boolean;
263
- }): PurgeRemovableInstallsResult & {
264
- inventory: MultiInstallInventoryEntry[];
265
- candidates: RemovableAgentsCliInstall[];
266
- };
301
+ }): RemediateStaleInstallsResult;
267
302
  /**
268
303
  * Resolve every `agents` entrypoint on PATH, then inspect the bounded global
269
304
  * install layouts used by NVM, fnm, Volta, Bun, npm, and npx. More than one
@@ -145,6 +145,13 @@ export function readMultiInstallScanCache(file) {
145
145
  !Array.isArray(raw.inventory)) {
146
146
  return null;
147
147
  }
148
+ // A cache written before the entries carried running/autoPurgeable
149
+ // (RUSH-2705) cannot drive the banner's remedy choice — treat it as
150
+ // corrupt so the caller re-scans rather than mis-advertising --fix.
151
+ const entries = raw.inventory;
152
+ if (entries.some((entry) => typeof entry?.running !== 'boolean' || typeof entry?.autoPurgeable !== 'boolean')) {
153
+ return null;
154
+ }
148
155
  return raw;
149
156
  }
150
157
  catch {
@@ -415,11 +422,67 @@ function packageRootForEntry(real) {
415
422
  }
416
423
  return null;
417
424
  }
425
+ /** Best-effort canonical path; keeps the input when realpath fails. */
426
+ function canonicalPath(p) {
427
+ try {
428
+ return fs.realpathSync(p);
429
+ }
430
+ catch {
431
+ return p;
432
+ }
433
+ }
434
+ /**
435
+ * Ensure the running copy participates in classification (the "has a fixed
436
+ * peer" check) even when the PATH scan missed it — a source tree or unusual
437
+ * layout. The running root is never deleted regardless.
438
+ */
439
+ function withRunningInstall(installs, runningRoot, runningVersion) {
440
+ const runningCanonical = canonicalPath(runningRoot);
441
+ const already = installs.some((install) => canonicalPath(install.packageRoot) === runningCanonical);
442
+ if (already)
443
+ return installs;
444
+ return [...installs, {
445
+ packageRoot: runningRoot,
446
+ version: runningVersion,
447
+ // Unknown for a synthetic entry — classify only uses version for the
448
+ // fixed-peer check; the running root is never deleted regardless.
449
+ atomicHelperInstall: true,
450
+ }];
451
+ }
452
+ /**
453
+ * The exact shell command that removes the install at `packageRoot` by hand —
454
+ * the remedy for duplicates `doctor --fix` deliberately will not purge
455
+ * (RUSH-2705). `--prefix` pins the target tree no matter which npm binary
456
+ * PATH resolves, mirroring installPackageIntoPrefix.
457
+ */
458
+ export function manualUninstallCommand(packageRoot) {
459
+ const resolved = path.resolve(packageRoot);
460
+ if (detectPackageManager(resolved) === 'bun') {
461
+ return `bun remove -g ${NPM_PACKAGE_NAME}`;
462
+ }
463
+ try {
464
+ return `npm uninstall -g --prefix '${deriveGlobalPrefix(resolved)}' ${NPM_PACKAGE_NAME}`;
465
+ }
466
+ catch {
467
+ // Not inside a node_modules tree — no npm prefix owns it; deleting the
468
+ // directory is the only removal there is.
469
+ return `rm -rf '${resolved}'`;
470
+ }
471
+ }
418
472
  export function buildMultiInstallInventory(runningRoot, runningVersion, installs) {
473
+ const runningCanonical = canonicalPath(runningRoot);
474
+ const removableRoots = new Set(classifyRemovableAgentsCliInstalls(runningRoot, withRunningInstall(installs, runningRoot, runningVersion)).map((candidate) => candidate.packageRoot));
419
475
  const byRoot = new Map();
420
- byRoot.set(runningRoot, { packageRoot: runningRoot, version: runningVersion, note: 'running' });
476
+ byRoot.set(runningRoot, {
477
+ packageRoot: runningRoot,
478
+ version: runningVersion,
479
+ note: 'running',
480
+ running: true,
481
+ autoPurgeable: false,
482
+ });
421
483
  for (const install of installs) {
422
- const notes = [install.packageRoot === runningRoot
484
+ const running = canonicalPath(install.packageRoot) === runningCanonical;
485
+ const notes = [running
423
486
  ? 'running'
424
487
  : install.binPath
425
488
  ? `agents on PATH: ${install.binPath}`
@@ -430,6 +493,8 @@ export function buildMultiInstallInventory(runningRoot, runningVersion, installs
430
493
  packageRoot: install.packageRoot,
431
494
  version: install.version,
432
495
  note: notes.join('; '),
496
+ running,
497
+ autoPurgeable: !running && removableRoots.has(canonicalPath(install.packageRoot)),
433
498
  });
434
499
  }
435
500
  return [...byRoot.values()];
@@ -588,38 +653,26 @@ export function purgeRemovableAgentsCliInstalls(candidates, opts = {}) {
588
653
  */
589
654
  export function remediateStaleAgentsCliInstalls(opts) {
590
655
  const pathEnv = opts.pathEnv ?? (process.env.PATH || '');
591
- const installs = findAgentsCliInstalls(pathEnv, opts.findOpts);
656
+ let installs = findAgentsCliInstalls(pathEnv, opts.findOpts);
592
657
  // Ensure the running root participates in "has a fixed peer" even when the
593
658
  // PATH scan missed it (source tree, unusual layout).
594
659
  if (opts.runningVersion) {
595
- const already = installs.some((i) => {
596
- try {
597
- return fs.realpathSync(i.packageRoot) === fs.realpathSync(opts.runningRoot);
598
- }
599
- catch {
600
- return i.packageRoot === opts.runningRoot;
601
- }
602
- });
603
- if (!already) {
604
- installs.push({
605
- packageRoot: opts.runningRoot,
606
- version: opts.runningVersion,
607
- // Unknown for a synthetic entry — classify only uses version for the
608
- // fixed-peer check; the running root is never deleted regardless.
609
- atomicHelperInstall: true,
610
- });
611
- }
660
+ installs = withRunningInstall(installs, opts.runningRoot, opts.runningVersion);
612
661
  }
613
662
  const candidates = classifyRemovableAgentsCliInstalls(opts.runningRoot, installs);
614
663
  const purge = purgeRemovableAgentsCliInstalls(candidates, {
615
664
  dryRun: opts.dryRun,
616
665
  runningRoot: opts.runningRoot,
617
666
  });
618
- return {
619
- ...purge,
620
- candidates,
621
- inventory: buildMultiInstallInventory(opts.runningRoot, opts.runningVersion ?? 'unknown', installs),
622
- };
667
+ const inventory = buildMultiInstallInventory(opts.runningRoot, opts.runningVersion ?? 'unknown', installs);
668
+ const unresolved = inventory
669
+ .filter((entry) => !entry.running && !entry.autoPurgeable)
670
+ .map((entry) => ({
671
+ packageRoot: entry.packageRoot,
672
+ version: entry.version,
673
+ manualRemoveCommand: manualUninstallCommand(entry.packageRoot),
674
+ }));
675
+ return { ...purge, candidates, inventory, unresolved };
623
676
  }
624
677
  function childDirectories(parent) {
625
678
  try {
@@ -77,7 +77,7 @@ export declare function spawnDetached(command: string, args: string[], stdio?: S
77
77
  /**
78
78
  * Default run dispatcher: re-invoke `agents run` with a server-minted id so the
79
79
  * run is addressable, detached so it outlives this request (and the anchor
80
- * process). Local runs detach here; `--host` runs detach on the executor via
80
+ * process). Local runs detach here; `--device` runs detach on the executor via
81
81
  * the existing dispatch path.
82
82
  */
83
83
  export declare const defaultRunner: RunDispatcher;
@@ -2,7 +2,7 @@ import { createServer } from 'http';
2
2
  import fs from 'fs';
3
3
  import { spawn } from 'child_process';
4
4
  import { randomUUID, randomBytes } from 'crypto';
5
- import { getAgentsInvocation } from '../daemon.js';
5
+ import { getAgentsInvocation } from '../daemon/daemon.js';
6
6
  import { handleServeGet, resolveServeContext } from './server.js';
7
7
  import { verifyControlToken } from './token.js';
8
8
  import { readNewEvents, streamDir, streamLogPath } from './stream.js';
@@ -127,7 +127,7 @@ export function spawnDetached(command, args, stdio = 'ignore') {
127
127
  /**
128
128
  * Default run dispatcher: re-invoke `agents run` with a server-minted id so the
129
129
  * run is addressable, detached so it outlives this request (and the anchor
130
- * process). Local runs detach here; `--host` runs detach on the executor via
130
+ * process). Local runs detach here; `--device` runs detach on the executor via
131
131
  * the existing dispatch path.
132
132
  */
133
133
  export const defaultRunner = async (req) => {
@@ -144,7 +144,7 @@ export const defaultRunner = async (req) => {
144
144
  if (req.mode)
145
145
  argv.push('--mode', req.mode);
146
146
  if (req.host)
147
- argv.push('--host', req.host);
147
+ argv.push('--device', req.host);
148
148
  if (req.cwd)
149
149
  argv.push('--cwd', req.cwd);
150
150
  const inv = getAgentsInvocation(argv);
@@ -152,7 +152,7 @@ export const defaultRunner = async (req) => {
152
152
  // unhandled 'error' that crashes the anchor for every other session.
153
153
  //
154
154
  // For an anchor-local run, capture the `--json` NDJSON to a per-session file
155
- // so `GET /api/session/:id/stream` can offset-tail it. A `--host` run emits
155
+ // so `GET /api/session/:id/stream` can offset-tail it. A `--device` run emits
156
156
  // its NDJSON on the remote box (streaming that reuses pullRemoteLogDelta — a
157
157
  // follow-up), so we don't capture the local dispatcher's output.
158
158
  if (req.host) {
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { AgentManager } from '../teams/agents.js';
17
17
  import type { AgentStatusSummary } from '../teams/api.js';
18
- import type { JobConfig } from '../routines.js';
18
+ import type { JobConfig } from '../scheduling/routines.js';
19
19
  import type { CloudTask } from '../cloud/types.js';
20
20
  /** One teammate's worktree and its current uncommitted diff. */
21
21
  export interface WorktreeDiff {
@@ -16,7 +16,7 @@
16
16
  import { AgentManager } from '../teams/agents.js';
17
17
  import { handleTasks, handleStatus, toTaskStatusSummary } from '../teams/api.js';
18
18
  import { gitDiff } from '../teams/worktree.js';
19
- import { listJobs } from '../routines.js';
19
+ import { listJobs } from '../scheduling/routines.js';
20
20
  import { listTasks as listCloudTasks } from '../cloud/store.js';
21
21
  /**
22
22
  * Build the per-worktree diffs for a set of teammates. Only teammates with a
@@ -9,7 +9,7 @@
9
9
  * phone that drops mid-run reconnects with `?offset=<bytes>` (or the standard
10
10
  * `Last-Event-ID` header) and never loses or double-counts an event.
11
11
  *
12
- * Scope: this streams runs whose executor is the anchor itself (no `--host`).
12
+ * Scope: this streams runs whose executor is the anchor itself (no `--device`).
13
13
  * Streaming a run offloaded to another box reuses `pullRemoteLogDelta` and is a
14
14
  * follow-up; see the changelog fragment.
15
15
  */
@@ -0,0 +1,29 @@
1
+ /**
2
+ * A short, stable hash of this process's HOME when — and only when — HOME has
3
+ * been redirected away from the account's real home.
4
+ *
5
+ * `os.userInfo().homedir` reads the OS/passwd record directly and ignores
6
+ * `$HOME` (unlike `os.homedir()`, which honors it), so comparing the two
7
+ * detects exactly that redirection: true for every hermetic test process, false
8
+ * for every real interactive or production invocation. A real user's services
9
+ * therefore keep registering under their unchanged production identifiers.
10
+ */
11
+ export declare function isolatedHomeSuffix(): string | null;
12
+ /**
13
+ * Namespace a service identifier under a redirected HOME. Returns `base`
14
+ * unchanged for a real production invocation.
15
+ */
16
+ export declare function namespacedServiceLabel(base: string): string;
17
+ /**
18
+ * The home-resolution environment every generated service manifest must carry,
19
+ * so the service-manager-started child resolves the SAME home the caller did.
20
+ *
21
+ * `AGENTS_REAL_HOME` is the canonical seam that distinguishes an agent's
22
+ * isolated version home from the active installation home; pinning it alongside
23
+ * HOME keeps a child that a login shell or service manager re-homes pointed at
24
+ * the installation the caller meant.
25
+ */
26
+ export declare function serviceManifestHomeEnv(): {
27
+ HOME: string;
28
+ AGENTS_REAL_HOME: string;
29
+ };
@@ -0,0 +1,80 @@
1
+ /**
2
+ * One rule for every service manifest this CLI writes — the launchd plists and
3
+ * the systemd unit that a service manager, not this process, will later start.
4
+ *
5
+ * RUSH-2639. A service manager does NOT inherit the environment of whoever
6
+ * called `launchctl bootstrap` / `systemctl --user start`. The started child
7
+ * sees the login session's own environment plus whatever the manifest declares,
8
+ * so a manifest that omits HOME hands its child the ACCOUNT home no matter what
9
+ * HOME the process that generated and loaded it was running under. In
10
+ * production that is a no-op — the login session's HOME already is the account
11
+ * home — but under the hermetic test harness (`tests/setup.ts` redirects HOME to
12
+ * a fork-private sandbox) it means a service-manager-started process silently
13
+ * escapes the sandbox and bootstraps the developer's or the CI runner's REAL
14
+ * `~/.agents` (`ensureAgentsDir`, `state.ts`, creates `.system`, `.history`,
15
+ * `.cache`, `routines`).
16
+ *
17
+ * The same asymmetry applies to the service IDENTIFIER. `launchctl` and
18
+ * `systemctl` route `bootout`/`bootstrap`/`unload`/`load`/`list` by identifier
19
+ * alone, never by the manifest file's path, so a sandboxed instance's own
20
+ * teardown of its own never-loaded manifest tears down whatever job the OS
21
+ * already has registered under that same label — on a developer's machine, the
22
+ * real always-on service; in CI, another concurrent test fork's.
23
+ *
24
+ * Both were fixed once for the daemon and left unfixed for the menu-bar helper
25
+ * (`lib/menubar/install-menubar.ts`) and the computer helper
26
+ * (`commands/computer.ts`), which is why the leak survived the daemon fix. This
27
+ * module is the single place both rules live, so a new manifest has one obvious
28
+ * thing to call.
29
+ *
30
+ * It is not yet the only consumer of the identifier rule: `lib/secrets/agent.ts`
31
+ * keeps a literal `SERVICE_LABEL` for its `bootout`. That path is retire-only —
32
+ * it detects and removes a plist an older version installed and generates none
33
+ * of its own — so it has no HOME to bake and was deliberately left alone.
34
+ */
35
+ import * as crypto from 'crypto';
36
+ import * as os from 'os';
37
+ import * as path from 'path';
38
+ /**
39
+ * A short, stable hash of this process's HOME when — and only when — HOME has
40
+ * been redirected away from the account's real home.
41
+ *
42
+ * `os.userInfo().homedir` reads the OS/passwd record directly and ignores
43
+ * `$HOME` (unlike `os.homedir()`, which honors it), so comparing the two
44
+ * detects exactly that redirection: true for every hermetic test process, false
45
+ * for every real interactive or production invocation. A real user's services
46
+ * therefore keep registering under their unchanged production identifiers.
47
+ */
48
+ export function isolatedHomeSuffix() {
49
+ try {
50
+ const effective = path.resolve(process.env.HOME || os.homedir());
51
+ const real = path.resolve(os.userInfo().homedir);
52
+ if (effective === real)
53
+ return null;
54
+ return crypto.createHash('sha256').update(effective).digest('hex').slice(0, 12);
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ /**
61
+ * Namespace a service identifier under a redirected HOME. Returns `base`
62
+ * unchanged for a real production invocation.
63
+ */
64
+ export function namespacedServiceLabel(base) {
65
+ const suffix = isolatedHomeSuffix();
66
+ return suffix ? `${base}.sandbox-${suffix}` : base;
67
+ }
68
+ /**
69
+ * The home-resolution environment every generated service manifest must carry,
70
+ * so the service-manager-started child resolves the SAME home the caller did.
71
+ *
72
+ * `AGENTS_REAL_HOME` is the canonical seam that distinguishes an agent's
73
+ * isolated version home from the active installation home; pinning it alongside
74
+ * HOME keeps a child that a login shell or service manager re-homes pointed at
75
+ * the installation the caller meant.
76
+ */
77
+ export function serviceManifestHomeEnv() {
78
+ const home = process.env.HOME || os.homedir();
79
+ return { HOME: home, AGENTS_REAL_HOME: process.env.AGENTS_REAL_HOME || home };
80
+ }