@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,7 +1,7 @@
1
1
  import * as path from 'path';
2
2
  import chalk from 'chalk';
3
3
  import { readAndResolveBundleEnv } from '../lib/secrets/bundles.js';
4
- import { createFileDeliveryStore, startWebhookServer } from '../lib/triggers/webhook.js';
4
+ import { createFileDeliveryStore, startWebhookServer, waitForListening } from '../lib/triggers/webhook.js';
5
5
  import { getRuntimeStateDir } from '../lib/state.js';
6
6
  const DEFAULT_HOST = '127.0.0.1';
7
7
  const DEFAULT_PORT = 8787;
@@ -30,26 +30,6 @@ function readWebhookSecrets(bundleName) {
30
30
  }
31
31
  return secrets;
32
32
  }
33
- function waitForListening(server) {
34
- if (server.listening)
35
- return Promise.resolve();
36
- return new Promise((resolve, reject) => {
37
- const cleanup = () => {
38
- server.off('listening', onListening);
39
- server.off('error', onError);
40
- };
41
- const onListening = () => {
42
- cleanup();
43
- resolve();
44
- };
45
- const onError = (err) => {
46
- cleanup();
47
- reject(err);
48
- };
49
- server.once('listening', onListening);
50
- server.once('error', onError);
51
- });
52
- }
53
33
  export function registerWebhooksCommand(program) {
54
34
  const webhooks = program
55
35
  .command('webhooks')
@@ -58,7 +38,7 @@ export function registerWebhooksCommand(program) {
58
38
  .command('serve')
59
39
  .description('Receive signed GitHub/Linear webhooks on /hooks/<source> and fire matching routines.')
60
40
  .requiredOption('--secrets-bundle <name>', 'agents secrets bundle containing GITHUB_WEBHOOK_SECRET and/or LINEAR_WEBHOOK_SECRET')
61
- .option('--host <addr>', `Bind address (default ${DEFAULT_HOST})`, DEFAULT_HOST)
41
+ .option('--bind <addr>', `Bind address (default ${DEFAULT_HOST})`, DEFAULT_HOST)
62
42
  .option('-p, --port <n>', `Local port (default ${DEFAULT_PORT})`, String(DEFAULT_PORT))
63
43
  .option('--rate-limit <n>', 'Accepted deliveries per source per minute', '60')
64
44
  .action(async (opts) => {
@@ -74,7 +54,7 @@ export function registerWebhooksCommand(program) {
74
54
  const rateLimit = positiveInt(opts.rateLimit, 60);
75
55
  try {
76
56
  const server = startWebhookServer({
77
- host: opts.host ?? DEFAULT_HOST,
57
+ host: opts.bind ?? DEFAULT_HOST,
78
58
  port,
79
59
  secrets,
80
60
  rateLimitPerMinute: rateLimit,
@@ -90,12 +70,18 @@ export function registerWebhooksCommand(program) {
90
70
  console.log(`${new Date().toISOString()} ${webhook.source}:${webhook.event} ` +
91
71
  (parts.length ? `fired ${parts.join('; ')}` : 'no match'));
92
72
  },
73
+ // The delivery is acked 202 before dispatch (RUSH-2548), so a dispatch
74
+ // failure has no HTTP status left to ride — print it instead.
75
+ onDeliveryError: (webhook, err) => {
76
+ console.error(chalk.red(`${new Date().toISOString()} ${webhook.source}:${webhook.event} dispatch failed after ack: ${err.message}`));
77
+ },
93
78
  });
94
79
  await waitForListening(server);
95
80
  const address = server.address();
96
81
  const bound = typeof address === 'object' && address ? address.port : port;
97
- console.log(`${chalk.green('agents webhooks')} ${chalk.dim('→')} ${chalk.cyan(`http://${opts.host ?? DEFAULT_HOST}:${bound}`)}`);
98
- console.log(chalk.dim('signed · localhost by default · endpoints: /hooks/github, /hooks/linear · Ctrl-C to stop'));
82
+ console.log(`${chalk.green('agents webhooks')} ${chalk.dim('→')} ${chalk.cyan(`http://${opts.bind ?? DEFAULT_HOST}:${bound}`)}`);
83
+ console.log(chalk.dim('signed · localhost by default · endpoints: /hooks/github, /hooks/linear · acks 202 then dispatches · Ctrl-C to stop'));
84
+ console.log(chalk.dim('for a supervised receiver that survives reboot: agents daemon webhooks add --secrets-bundle <name>'));
99
85
  const shutdown = () => {
100
86
  server.close(() => process.exit(0));
101
87
  };
@@ -8,7 +8,7 @@ import { resolveAgentName, agentLabel } from '../lib/agents.js';
8
8
  import { capableAgents } from '../lib/capabilities.js';
9
9
  import { cloneRepo } from '../lib/git.js';
10
10
  import { discoverWorkflowsFromRepo, installWorkflowCentrally, removeWorkflow, listInstalledWorkflows, listWorkflowsForAgent, removeWorkflowFromVersion, iterWorkflowsCapableVersions, } from '../lib/workflows.js';
11
- import { getVersionHomePath, getGlobalDefault, syncResourcesToVersion, promptAgentVersionSelection, } from '../lib/versions.js';
11
+ import { getVersionHomePath, getGlobalDefault, syncResourcesToVersion, promptAgentVersionSelection, } from '../lib/installations/versions.js';
12
12
  import { recordVersionResources, getUserWorkflowsDir } from '../lib/state.js';
13
13
  import { isPromptCancelled, isInteractiveTerminal, requireInteractiveSelection, printWithPager, promptRemovalTargets, parseCommaSeparatedList, resolveAgentTargetsAutoInstalling, resolveListFilterOrExit, } from './utils.js';
14
14
  import { showResourceList, buildTargetsSection, } from './resource-view.js';
package/dist/index.js CHANGED
@@ -71,7 +71,7 @@ if (process.argv[2] === '__shim') {
71
71
  process.exit(code);
72
72
  }
73
73
  if (process.argv[2] === '__daemon-run') {
74
- const { runDaemon, log: daemonLog } = await import('./lib/daemon.js');
74
+ const { runDaemon, log: daemonLog } = await import('./lib/daemon/daemon.js');
75
75
  // RUSH-2418: the daemon is the one always-on process here, and it ran with no
76
76
  // top-level handler of any kind — an uncaught throw or a rejected promise from
77
77
  // any of its background ticks died on Node's default handler, printing a raw
@@ -0,0 +1,39 @@
1
+ import type { AgentId } from './types.js';
2
+ /**
3
+ * How safely agents-cli can read a harness's native login identity, and at what
4
+ * granularity that identity is scoped.
5
+ *
6
+ * - `inspection`: `strong` = a stable account key (Claude/Codex/Grok);
7
+ * `email` = only an email claim, so the name binds to an address not a token
8
+ * (Muse); `opaque` = a stable but non-human identifier from an OAuth/JWT blob
9
+ * with no email (the device-scoped harnesses); `none` = no inspectable identity.
10
+ * - `scope`: `version` = auth lives per installed version home; `device` = one
11
+ * login per device shared by every install; `unsupported` = agents-cli must not
12
+ * name/attach this harness's native login.
13
+ * - `status`: `supported` = name + attach safely; `conditional` = supported only
14
+ * when the weaker (email) identity is present; `discovery-only` = shown in the
15
+ * list but not nameable; `unsupported` = neither.
16
+ */
17
+ export interface NativeAccountCapability {
18
+ inspection: 'strong' | 'email' | 'opaque' | 'none';
19
+ scope: 'version' | 'device' | 'unsupported';
20
+ status: 'supported' | 'conditional' | 'discovery-only' | 'unsupported';
21
+ }
22
+ /** Canonical truth for native-account naming and attachment semantics. */
23
+ export declare const NATIVE_ACCOUNT_CAPABILITIES: Record<AgentId, NativeAccountCapability>;
24
+ export declare function nativeAccountCapability(agent: AgentId): NativeAccountCapability;
25
+ /** Whether a harness's native login can be named/attached (supported or conditional). */
26
+ export declare function nativeAccountNameable(agent: AgentId): boolean;
27
+ /**
28
+ * The single identity key used at `accounts name`, attach, exec validation,
29
+ * view, and inventory. Prefer the harness's stable `accountKey`. For an
30
+ * email-only (`conditional`) harness, email is a presence gate — the stored
31
+ * key is still `accountKey` (e.g. `muse:email=user@x.com`), never the bare
32
+ * address, so `run`/`view` compare against the same value `getAccountInfo`
33
+ * returns.
34
+ */
35
+ export declare function nativeIdentityKey(info: {
36
+ signedIn?: boolean;
37
+ email?: string | null;
38
+ accountKey?: string | null;
39
+ }, capability: NativeAccountCapability): string | null;
@@ -0,0 +1,59 @@
1
+ /** Canonical truth for native-account naming and attachment semantics. */
2
+ export const NATIVE_ACCOUNT_CAPABILITIES = {
3
+ // Version-scoped with a strong account key — the only harnesses whose native
4
+ // identity is safe to pin per installed version.
5
+ claude: { inspection: 'strong', scope: 'version', status: 'supported' },
6
+ codex: { inspection: 'strong', scope: 'version', status: 'supported' },
7
+ grok: { inspection: 'strong', scope: 'version', status: 'supported' },
8
+ // Version-scoped but only an email identity — nameable only when that email is
9
+ // present (the resolver rejects an emailless Muse login).
10
+ muse: { inspection: 'email', scope: 'version', status: 'conditional' },
11
+ // Device-scoped, opaque identity (an OAuth/JWT blob). These are recorded as
12
+ // device-scoped opaque, but marked UNSUPPORTED for naming: a NativeAccount has
13
+ // no device-id discriminator, so an opaque/singleton identity cannot be proven
14
+ // to distinguish accounts across synced metadata — Droid exposes no account key
15
+ // at all, and Antigravity (singleton) / OpenCode (provider-set) can read two
16
+ // different credentials as the same identity on another device. A truthful
17
+ // "unsupported" is correct until a device-scoped identity key (with a stable
18
+ // device id) exists to validate against.
19
+ antigravity: { inspection: 'opaque', scope: 'device', status: 'unsupported' },
20
+ kimi: { inspection: 'opaque', scope: 'device', status: 'unsupported' },
21
+ droid: { inspection: 'opaque', scope: 'device', status: 'unsupported' },
22
+ opencode: { inspection: 'opaque', scope: 'device', status: 'unsupported' },
23
+ // Cursor multi-account isolation is unresolved (RUSH-2400) — blocked from
24
+ // native naming/attachment; its API-key path is a provider account instead.
25
+ cursor: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
26
+ // Discoverable in the list, but not nameable.
27
+ gemini: { inspection: 'email', scope: 'unsupported', status: 'discovery-only' },
28
+ copilot: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
29
+ openclaw: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
30
+ amp: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
31
+ kiro: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
32
+ goose: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
33
+ hermes: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
34
+ pi: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
35
+ warp: { inspection: 'none', scope: 'unsupported', status: 'unsupported' },
36
+ };
37
+ export function nativeAccountCapability(agent) {
38
+ return NATIVE_ACCOUNT_CAPABILITIES[agent];
39
+ }
40
+ /** Whether a harness's native login can be named/attached (supported or conditional). */
41
+ export function nativeAccountNameable(agent) {
42
+ const cap = NATIVE_ACCOUNT_CAPABILITIES[agent];
43
+ return (cap.status === 'supported' || cap.status === 'conditional') && cap.scope !== 'unsupported';
44
+ }
45
+ /**
46
+ * The single identity key used at `accounts name`, attach, exec validation,
47
+ * view, and inventory. Prefer the harness's stable `accountKey`. For an
48
+ * email-only (`conditional`) harness, email is a presence gate — the stored
49
+ * key is still `accountKey` (e.g. `muse:email=user@x.com`), never the bare
50
+ * address, so `run`/`view` compare against the same value `getAccountInfo`
51
+ * returns.
52
+ */
53
+ export function nativeIdentityKey(info, capability) {
54
+ if (!info.signedIn)
55
+ return null;
56
+ if (capability.inspection === 'email' && !info.email)
57
+ return null;
58
+ return info.accountKey ?? info.email?.toLowerCase() ?? null;
59
+ }
@@ -1,5 +1,5 @@
1
1
  import { ALL_AGENT_IDS, getAccountInfo, supportsAccountInspection } from './agents.js';
2
- import { getVersionHomePath, listInstalledVersions } from './versions.js';
2
+ import { getVersionHomePath, listInstalledVersions } from './installations/versions.js';
3
3
  export function groupNativeAccountRows(rows) {
4
4
  const grouped = new Map();
5
5
  for (const row of rows) {
@@ -19,12 +19,42 @@ export interface ResolvedCredentialAccount {
19
19
  auth: AccountAuthKind;
20
20
  env: Record<string, string>;
21
21
  }
22
+ export interface NativeAccount {
23
+ id: string;
24
+ name: string;
25
+ kind: 'native';
26
+ agent: AgentId;
27
+ identityKey: string;
28
+ identityLabel?: string;
29
+ scope: 'version' | 'device';
30
+ }
31
+ export type UnifiedAccount = (CredentialAccount & {
32
+ kind: 'provider';
33
+ }) | NativeAccount;
22
34
  export declare function accountRegistryPath(base?: string): string;
23
35
  export declare function readAccountRegistry(base?: string): AccountRegistryDocument;
24
36
  export declare function findAccount(name: string, doc?: AccountRegistryDocument): CredentialAccount | null;
37
+ export declare function listNativeAccounts(meta: Pick<Meta, 'accounts'>): NativeAccount[];
38
+ /**
39
+ * Resolve one account by name or id across both stores, native first.
40
+ *
41
+ * `doc` is optional and read LAZILY: a native match returns without ever reading
42
+ * the provider bundle registry — so a native view/attach/run never triggers a
43
+ * bundle read, legacy-`accounts.yaml` migration, or a keychain decrypt (which
44
+ * would surface a Touch ID prompt or crash on an undecryptable legacy item). A
45
+ * default-evaluated `doc = readAccountRegistry()` argument would defeat this by
46
+ * running before the body, so callers that only need a native lookup must be
47
+ * able to omit it.
48
+ */
49
+ export declare function findUnifiedAccount(nameOrId: string, meta: Pick<Meta, 'accounts'>, doc?: AccountRegistryDocument): UnifiedAccount | null;
50
+ export declare function addNativeAccount(name: string, agent: AgentId, identityKey: string, identityLabel: string | undefined, scope: 'version' | 'device'): NativeAccount;
51
+ export declare function bindAccount(nameOrId: string, target: string): UnifiedAccount;
52
+ export declare function unbindAccount(nameOrId: string, target: string): void;
53
+ export declare function accountBindings(accountId: string, meta: Pick<Meta, 'accounts'>): string[];
25
54
  /** Explicit selection wins over a configured per-harness default. */
26
55
  export declare function resolveAccountSelection(explicit: string | undefined, agent: AgentId, meta: Pick<Meta, 'accounts'>, opts?: {
27
56
  useDefault?: boolean;
57
+ target?: string;
28
58
  }): string | undefined;
29
59
  export interface AddAccountOptions {
30
60
  baseUrl?: string;
@@ -38,3 +68,39 @@ export declare function inspectAccount(name: string, base?: string): CredentialA
38
68
  policy: 'never';
39
69
  };
40
70
  export declare function resolveCredentialAccount(name: string, host: AgentId, expectedProvider?: string, base?: string): ResolvedCredentialAccount;
71
+ /** The account a spawn should launch under, classified for the exec path. */
72
+ export type SpawnAccount = {
73
+ kind: 'provider';
74
+ id: string;
75
+ name: string;
76
+ agent: AgentId;
77
+ env: Record<string, string>;
78
+ } | {
79
+ kind: 'native';
80
+ id: string;
81
+ name: string;
82
+ agent: AgentId;
83
+ identityKey: string;
84
+ scope: 'version' | 'device';
85
+ };
86
+ /**
87
+ * Resolve the account a run should launch under, following the binding order
88
+ * (explicit → exact `agent@version` → device-scoped `agent` → per-harness
89
+ * default) and classifying the result:
90
+ *
91
+ * - **provider** → the injected env is resolved here (fails closed when the
92
+ * credential is absent or the provider cannot authenticate the host).
93
+ * - **native** → returns the identity the caller must confirm is live on the
94
+ * execution device; **no secret or env is produced**, because a native login
95
+ * is owned by the harness and read from its own home. The caller validates the
96
+ * live fingerprint against the installed version before spawn.
97
+ *
98
+ * A native account bound to a different harness than the one being launched
99
+ * fails loudly (EXEC-ACCOUNT-4). Returns null when nothing is selected.
100
+ */
101
+ export declare function resolveSpawnAccount(explicit: string | undefined, agent: AgentId, version: string | undefined, meta: Pick<Meta, 'accounts'>, opts?: {
102
+ useDefault?: boolean;
103
+ provider?: string;
104
+ base?: string;
105
+ target?: string;
106
+ }): SpawnAccount | null;
@@ -19,7 +19,7 @@ import * as path from 'node:path';
19
19
  import * as crypto from 'node:crypto';
20
20
  import * as yaml from 'yaml';
21
21
  import { atomicWriteFileSync } from './fs-atomic.js';
22
- import { getUserAgentsDir } from './state.js';
22
+ import { getUserAgentsDir, readMeta, updateMeta } from './state.js';
23
23
  import { deleteKeychainToken, getKeychainToken, hasKeychainToken } from './secrets/index.js';
24
24
  import { bundleExists, deleteBundle, listBundles, readBundle, renameBundle, writeBundleWithItems } from './secrets/bundles.js';
25
25
  import { getAccountProvider } from './account-provider-registry.js';
@@ -128,10 +128,85 @@ export function readAccountRegistry(base = getUserAgentsDir()) {
128
128
  export function findAccount(name, doc = readAccountRegistry()) {
129
129
  return doc.accounts[name] ?? Object.values(doc.accounts).find(account => account.name === name) ?? null;
130
130
  }
131
+ export function listNativeAccounts(meta) {
132
+ return Object.values(meta.accounts?.native ?? {}).map(account => ({ ...account, kind: 'native' }));
133
+ }
134
+ /**
135
+ * Resolve one account by name or id across both stores, native first.
136
+ *
137
+ * `doc` is optional and read LAZILY: a native match returns without ever reading
138
+ * the provider bundle registry — so a native view/attach/run never triggers a
139
+ * bundle read, legacy-`accounts.yaml` migration, or a keychain decrypt (which
140
+ * would surface a Touch ID prompt or crash on an undecryptable legacy item). A
141
+ * default-evaluated `doc = readAccountRegistry()` argument would defeat this by
142
+ * running before the body, so callers that only need a native lookup must be
143
+ * able to omit it.
144
+ */
145
+ export function findUnifiedAccount(nameOrId, meta, doc) {
146
+ const native = listNativeAccounts(meta).find(account => account.id === nameOrId || account.name === nameOrId);
147
+ if (native)
148
+ return native;
149
+ const provider = findAccount(nameOrId, doc ?? readAccountRegistry());
150
+ return provider ? { ...provider, kind: 'provider' } : null;
151
+ }
152
+ function assertUniqueUnifiedName(name, meta, doc) {
153
+ if (findUnifiedAccount(name, meta, doc))
154
+ throw new Error(`Account '${name}' already exists.`);
155
+ }
156
+ export function addNativeAccount(name, agent, identityKey, identityLabel, scope) {
157
+ assertName(name);
158
+ const meta = readMeta();
159
+ assertUniqueUnifiedName(name, meta);
160
+ const duplicate = listNativeAccounts(meta).find(account => account.agent === agent && account.identityKey === identityKey);
161
+ if (duplicate)
162
+ throw new Error(`This ${agent} login is already named '${duplicate.name}'.`);
163
+ const account = { id: crypto.randomUUID(), name, kind: 'native', agent, identityKey, identityLabel, scope };
164
+ updateMeta(current => ({
165
+ ...current,
166
+ accounts: {
167
+ ...current.accounts,
168
+ native: { ...current.accounts?.native, [account.id]: { id: account.id, name, agent, identityKey, identityLabel, scope } },
169
+ },
170
+ }));
171
+ return account;
172
+ }
173
+ export function bindAccount(nameOrId, target) {
174
+ const meta = readMeta();
175
+ const account = findUnifiedAccount(nameOrId, meta);
176
+ if (!account)
177
+ throw new Error(`Unknown account '${nameOrId}'.`);
178
+ updateMeta(current => ({
179
+ ...current,
180
+ accounts: { ...current.accounts, bindings: { ...current.accounts?.bindings, [target]: account.id } },
181
+ }));
182
+ return account;
183
+ }
184
+ export function unbindAccount(nameOrId, target) {
185
+ const meta = readMeta();
186
+ const account = findUnifiedAccount(nameOrId, meta);
187
+ if (!account)
188
+ throw new Error(`Unknown account '${nameOrId}'.`);
189
+ if (meta.accounts?.bindings?.[target] !== account.id)
190
+ throw new Error(`Account '${account.name}' is not attached to '${target}'.`);
191
+ updateMeta(current => {
192
+ const bindings = { ...current.accounts?.bindings };
193
+ delete bindings[target];
194
+ return { ...current, accounts: { ...current.accounts, bindings } };
195
+ });
196
+ }
197
+ export function accountBindings(accountId, meta) {
198
+ return Object.entries(meta.accounts?.bindings ?? {}).filter(([, id]) => id === accountId).map(([target]) => target).sort();
199
+ }
131
200
  /** Explicit selection wins over a configured per-harness default. */
132
201
  export function resolveAccountSelection(explicit, agent, meta, opts = {}) {
133
202
  if (explicit)
134
203
  return explicit;
204
+ const bound = opts.target ? meta.accounts?.bindings?.[opts.target] : undefined;
205
+ if (bound)
206
+ return bound;
207
+ const deviceScoped = meta.accounts?.bindings?.[agent];
208
+ if (deviceScoped)
209
+ return deviceScoped;
135
210
  return opts.useDefault === false ? undefined : meta.accounts?.defaults?.[agent];
136
211
  }
137
212
  function profileConsumers(name, base) {
@@ -158,12 +233,11 @@ function renameProfileConsumers(oldName, newName, base) {
158
233
  }
159
234
  export function addAccount(name, provider, auth, secret, base = getUserAgentsDir(), opts = {}) {
160
235
  assertName(name);
236
+ assertUniqueUnifiedName(name, readMeta(), readAccountRegistry(base));
161
237
  const adapter = getAccountProvider(provider);
162
238
  adapter.validate(auth, secret);
163
239
  if (bundleExists(name))
164
240
  throw new Error(`Secrets bundle '${name}' already exists. Choose a different account name.`);
165
- if (findAccount(name, readAccountRegistry(base)))
166
- throw new Error(`Account '${name}' already exists.`);
167
241
  const record = { id: crypto.randomUUID(), name, provider: adapter.provider, auth, baseUrl: opts.baseUrl };
168
242
  const { bundle, items } = buildAccountBundle(record, secret);
169
243
  writeBundleWithItems(bundle, items);
@@ -182,18 +256,49 @@ export function setAccountSecret(name, secret, base = getUserAgentsDir()) {
182
256
  export function renameAccount(oldName, newName, base = getUserAgentsDir()) {
183
257
  assertName(newName);
184
258
  const doc = readAccountRegistry(base);
259
+ const meta = readMeta();
260
+ const native = listNativeAccounts(meta).find(account => account.id === oldName || account.name === oldName);
261
+ if (native) {
262
+ assertUniqueUnifiedName(newName, meta, doc);
263
+ updateMeta(current => ({
264
+ ...current,
265
+ accounts: {
266
+ ...current.accounts,
267
+ native: { ...current.accounts?.native, [native.id]: { ...current.accounts?.native?.[native.id], name: newName } },
268
+ },
269
+ }));
270
+ return;
271
+ }
185
272
  const account = findAccount(oldName, doc);
186
273
  if (!account)
187
274
  throw new Error(`Unknown account '${oldName}'.`);
188
- if (findAccount(newName, doc))
189
- throw new Error(`Account '${newName}' already exists.`);
275
+ assertUniqueUnifiedName(newName, meta, doc);
190
276
  renameBundle(account.name, newName); // moves metadata + secret, preserves ACCOUNT_ID
191
277
  renameProfileConsumers(account.name, newName, base);
192
278
  }
193
279
  export function removeAccount(name, base = getUserAgentsDir()) {
280
+ const meta = readMeta();
281
+ const native = listNativeAccounts(meta).find(account => account.id === name || account.name === name);
282
+ if (native) {
283
+ const bindings = accountBindings(native.id, meta);
284
+ if (bindings.length)
285
+ throw new Error(`Account '${native.name}' is attached to: ${bindings.join(', ')}. Detach it before removing it.`);
286
+ updateMeta(current => {
287
+ const accounts = { ...current.accounts?.native };
288
+ delete accounts[native.id];
289
+ return { ...current, accounts: { ...current.accounts, native: accounts } };
290
+ });
291
+ return;
292
+ }
194
293
  const account = findAccount(name, readAccountRegistry(base));
195
294
  if (!account)
196
295
  throw new Error(`Unknown account '${name}'.`);
296
+ const bindings = accountBindings(account.id, meta);
297
+ const defaults = Object.entries(meta.accounts?.defaults ?? {}).filter(([, id]) => id === account.id).map(([agent]) => agent);
298
+ if (bindings.length || defaults.length) {
299
+ const refs = [...bindings.map(target => `binding ${target}`), ...defaults.map(agent => `default ${agent}`)];
300
+ throw new Error(`Account '${account.name}' is still referenced by: ${refs.join(', ')}. Detach or clear those references before removing it.`);
301
+ }
197
302
  const consumers = [...new Set([...profileConsumers(account.name, base), ...profileConsumers(account.id, base)])].sort();
198
303
  if (consumers.length)
199
304
  throw new Error(`Account '${account.name}' is used by harness${consumers.length === 1 ? '' : 'es'}: ${consumers.join(', ')}. Reassign them before removing it.`);
@@ -237,3 +342,44 @@ export function resolveCredentialAccount(name, host, expectedProvider, base = ge
237
342
  env: { ...connectionEnv, [envVar]: getKeychainToken(account.secretRef) },
238
343
  };
239
344
  }
345
+ /**
346
+ * Resolve the account a run should launch under, following the binding order
347
+ * (explicit → exact `agent@version` → device-scoped `agent` → per-harness
348
+ * default) and classifying the result:
349
+ *
350
+ * - **provider** → the injected env is resolved here (fails closed when the
351
+ * credential is absent or the provider cannot authenticate the host).
352
+ * - **native** → returns the identity the caller must confirm is live on the
353
+ * execution device; **no secret or env is produced**, because a native login
354
+ * is owned by the harness and read from its own home. The caller validates the
355
+ * live fingerprint against the installed version before spawn.
356
+ *
357
+ * A native account bound to a different harness than the one being launched
358
+ * fails loudly (EXEC-ACCOUNT-4). Returns null when nothing is selected.
359
+ */
360
+ export function resolveSpawnAccount(explicit, agent, version, meta, opts = {}) {
361
+ // The binding lookup key. A custom harness passes its own profile/harness name
362
+ // (a run of `deepseek` must find a binding on `deepseek`, not `claude@x`); a
363
+ // native/global run keys on the exact `agent@version` installation.
364
+ const target = opts.target ?? (version ? `${agent}@${version}` : agent);
365
+ const selection = resolveAccountSelection(explicit, agent, meta, { useDefault: opts.useDefault, target });
366
+ if (!selection)
367
+ return null;
368
+ const unified = findUnifiedAccount(selection, meta);
369
+ if (!unified)
370
+ throw new Error(`Unknown account '${selection}'.`);
371
+ if (unified.kind === 'native') {
372
+ if (unified.agent !== agent) {
373
+ throw new Error(`Account '${unified.name}' is a ${unified.agent} login and cannot authenticate the ${agent} harness.`);
374
+ }
375
+ // A provider-backed custom harness still injects its provider auth env, so a
376
+ // native identity claim over it is incoherent — reject before spawn even when
377
+ // the account is chosen explicitly with --account (which bypasses `attach`).
378
+ if (opts.provider) {
379
+ throw new Error(`Account '${unified.name}' is a native ${unified.agent} login and cannot run under a provider-backed harness (${opts.provider}); the harness's ${opts.provider} credentials would still be injected. Use a matching provider account.`);
380
+ }
381
+ return { kind: 'native', id: unified.id, name: unified.name, agent, identityKey: unified.identityKey, scope: unified.scope };
382
+ }
383
+ const resolved = resolveCredentialAccount(unified.name, agent, opts.provider, opts.base ?? getUserAgentsDir());
384
+ return { kind: 'provider', id: resolved.id, name: resolved.name, agent, env: resolved.env };
385
+ }
@@ -4,11 +4,11 @@
4
4
  * Detects which installed versions have expired credentials and rotates
5
5
  * authentication tokens so users maintain active sessions across version switches.
6
6
  */
7
- import type { AgentId, RunStrategy } from './types.js';
8
- import type { FallbackEntry } from './exec.js';
9
- import { type AccountInfo, type CredentialPresence } from './agents.js';
7
+ import type { AgentId, RunStrategy } from '../types.js';
8
+ import type { FallbackEntry } from '../exec.js';
9
+ import { type AccountInfo, type CredentialPresence } from '../agents.js';
10
10
  import { type UsageSnapshot } from './usage.js';
11
- import { type AuthVerdict } from './auth-health.js';
11
+ import { type AuthVerdict } from '../auth-health.js';
12
12
  export interface RotateCandidate {
13
13
  agent: AgentId;
14
14
  version: string;
@@ -6,15 +6,15 @@
6
6
  */
7
7
  import * as fs from 'fs';
8
8
  import * as path from 'path';
9
- import { accountDisplayLabel, getAccountInfo, credentialPresence, ALL_AGENT_IDS, } from './agents.js';
10
- import { readMeta, writeMeta, getHelpersDir } from './state.js';
11
- import { listInstalledVersions, getVersionHomePath, resolveVersion } from './versions.js';
12
- import { getProjectRunConfigs } from './run-config.js';
13
- import { emit } from './events.js';
9
+ import { accountDisplayLabel, getAccountInfo, credentialPresence, ALL_AGENT_IDS, } from '../agents.js';
10
+ import { readMeta, writeMeta, getHelpersDir } from '../state.js';
11
+ import { listInstalledVersions, getVersionHomePath, resolveVersion } from '../installations/versions.js';
12
+ import { getProjectRunConfigs } from '../run-config.js';
13
+ import { emit } from '../feed/events.js';
14
14
  import { getUsageInfoByIdentity, getUsageLookupKey, deriveUsageStatusFromSnapshot, } from './usage.js';
15
- import { readAccountHeadroom } from './fleet-cache.js';
16
- import { machineId } from './machine-id.js';
17
- import { readAuthHealthCache, authCacheKey, isDeadVerdict } from './auth-health.js';
15
+ import { readAccountHeadroom } from '../fleet-cache.js';
16
+ import { machineId } from '../machine-id.js';
17
+ import { readAuthHealthCache, authCacheKey, isDeadVerdict } from '../auth-health.js';
18
18
  function getRotateDir() {
19
19
  const dir = path.join(getHelpersDir(), 'rotate');
20
20
  fs.mkdirSync(dir, { recursive: true });
@@ -1,5 +1,5 @@
1
- import { type AccountInfo } from './agents.js';
2
- import type { AgentId } from './types.js';
1
+ import { type AccountInfo } from '../agents.js';
2
+ import type { AgentId } from '../types.js';
3
3
  /**
4
4
  * Why a usage read produced no snapshot, when the cause is the credential or the
5
5
  * server rather than the payload. Every provider used to return `error: null`
@@ -460,14 +460,14 @@ export declare function normalizeDroidWindows(data: DroidBillingLimitsResponse):
460
460
  * 1. The OS keychain (`getKeychainToken`). Canonical on macOS — Claude Code
461
461
  * writes the token to the login keychain and we read it via `/usr/bin/security`.
462
462
  * 2. `<home>/.claude/.credentials.json`. On a headless Linux box (the
463
- * `agents view --host <linux>` case) there is no reachable Secret Service, so
463
+ * `agents view --device <linux>` case) there is no reachable Secret Service, so
464
464
  * the Claude CLI stores its OAuth token in this plaintext file instead. The
465
465
  * keychain read above finds nothing on that platform, so we fall back to the
466
466
  * file. Same wrapped `{ claudeAiOauth }` shape, so one parser handles both.
467
467
  * Mirrors `readClaudeCredentialsBlob` (cloud/rush.ts), the proven pattern.
468
468
  *
469
469
  * Without step 2 the live usage fetch got no token on Linux, so `agents view`
470
- * (run remotely over SSH by `--host`) rendered no usage bars even though the
470
+ * (run remotely over SSH by `--device`) rendered no usage bars even though the
471
471
  * account + plan — read from the plaintext `.claude.json` — showed fine.
472
472
  *
473
473
  * `opts.accessTokenCache` marks a read-only, access-token-only consumer (the
@@ -17,15 +17,15 @@ import * as path from 'path';
17
17
  import * as readline from 'readline';
18
18
  import { promisify } from 'util';
19
19
  import chalk from 'chalk';
20
- import { decodeJwtPayload, decryptDroidAuthPayload } from './agents.js';
21
- import { walkForFiles } from './fs-walk.js';
22
- import { getKeychainToken, setKeychainToken, deleteKeychainToken, isKeychainBackendOverridden, } from './secrets/index.js';
23
- import { resolveClaudeSetupToken } from './claude-account-token.js';
24
- import { formatBackoffRemaining, noteUsageRateLimited, usageRateLimitedUntil, } from './usage-backoff.js';
25
- import { getCacheDir } from './state.js';
26
- import { mapBounded } from './concurrency.js';
27
- import { atomicWriteFileSync, ensureLockTarget, withFileLock } from './fs-atomic.js';
28
- import { withRefreshLease } from './refresh-coordinator.js';
20
+ import { decodeJwtPayload, decryptDroidAuthPayload } from '../agents.js';
21
+ import { walkForFiles } from '../fs-walk.js';
22
+ import { getKeychainToken, setKeychainToken, deleteKeychainToken, isKeychainBackendOverridden, } from '../secrets/index.js';
23
+ import { resolveClaudeSetupToken } from '../claude-account-token.js';
24
+ import { formatBackoffRemaining, noteUsageRateLimited, usageRateLimitedUntil, } from '../usage-backoff.js';
25
+ import { getCacheDir } from '../state.js';
26
+ import { mapBounded } from '../concurrency.js';
27
+ import { atomicWriteFileSync, ensureLockTarget, withFileLock } from '../fs-atomic.js';
28
+ import { withRefreshLease } from '../refresh-coordinator.js';
29
29
  const execFileAsync = promisify(execFile);
30
30
  const CLAUDE_USAGE_URL = 'https://api.anthropic.com/api/oauth/usage';
31
31
  const CLAUDE_TOKEN_URL = 'https://platform.claude.com/v1/oauth/token';
@@ -1282,14 +1282,14 @@ function deleteCachedClaudeOauth(service) {
1282
1282
  * 1. The OS keychain (`getKeychainToken`). Canonical on macOS — Claude Code
1283
1283
  * writes the token to the login keychain and we read it via `/usr/bin/security`.
1284
1284
  * 2. `<home>/.claude/.credentials.json`. On a headless Linux box (the
1285
- * `agents view --host <linux>` case) there is no reachable Secret Service, so
1285
+ * `agents view --device <linux>` case) there is no reachable Secret Service, so
1286
1286
  * the Claude CLI stores its OAuth token in this plaintext file instead. The
1287
1287
  * keychain read above finds nothing on that platform, so we fall back to the
1288
1288
  * file. Same wrapped `{ claudeAiOauth }` shape, so one parser handles both.
1289
1289
  * Mirrors `readClaudeCredentialsBlob` (cloud/rush.ts), the proven pattern.
1290
1290
  *
1291
1291
  * Without step 2 the live usage fetch got no token on Linux, so `agents view`
1292
- * (run remotely over SSH by `--host`) rendered no usage bars even though the
1292
+ * (run remotely over SSH by `--device`) rendered no usage bars even though the
1293
1293
  * account + plan — read from the plaintext `.claude.json` — showed fine.
1294
1294
  *
1295
1295
  * `opts.accessTokenCache` marks a read-only, access-token-only consumer (the
@@ -1,6 +1,6 @@
1
1
  // The production VersionProvider: the only fs/meta-coupled file in the engine.
2
2
  // Everything else in this module is pure and testable without it.
3
- import { listInstalledVersions, getGlobalDefault, getIsolatedDefault, getProjectVersion, isVersionInstalled, } from '../versions.js';
3
+ import { listInstalledVersions, getGlobalDefault, getIsolatedDefault, getProjectVersion, isVersionInstalled, } from '../installations/versions.js';
4
4
  export const defaultVersionProvider = {
5
5
  listInstalled: (agent) => listInstalledVersions(agent),
6
6
  getProjectVersion: (agent, cwd) => getProjectVersion(agent, cwd),