@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,15 @@
1
+ /**
2
+ * `agents secrets vault` — unlock/lock the age-encrypted synced-secrets file
3
+ * at ~/.agents/vault.age (distinct from `agents secrets unlock|lock`, which
4
+ * holds keychain bundles in the secrets-agent).
5
+ *
6
+ * Formerly top-level `agents login` / `agents logout`.
7
+ */
1
8
  import chalk from 'chalk';
2
9
  import * as fs from 'fs';
3
10
  import { readStdinSync } from '../lib/format.js';
4
11
  import { clearVaultKey, createVault, getVaultSession, joinVault, unlock, vaultExists, vaultPath, } from '../lib/secrets/vault.js';
12
+ import { setHelpSections } from '../lib/help.js';
5
13
  import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
6
14
  async function promptPassword(message) {
7
15
  if (!isInteractiveTerminal()) {
@@ -19,7 +27,7 @@ async function readPassword(opts, message) {
19
27
  }
20
28
  return promptPassword(message);
21
29
  }
22
- async function chooseFreshLoginMode(opts) {
30
+ async function chooseFreshMode(opts) {
23
31
  if (opts.create && opts.join)
24
32
  throw new Error('--create and --join are mutually exclusive.');
25
33
  if (opts.create)
@@ -31,10 +39,10 @@ async function chooseFreshLoginMode(opts) {
31
39
  }
32
40
  const { select } = await import('@inquirer/prompts');
33
41
  return select({
34
- message: 'No synced secrets login found. What do you want to do?',
42
+ message: 'No synced secrets vault found. What do you want to do?',
35
43
  choices: [
36
- { name: 'Create a new login', value: 'create' },
37
- { name: 'Join with an existing synced secrets file', value: 'join' },
44
+ { name: 'Create a new vault', value: 'create' },
45
+ { name: 'Join with an existing vault.age file', value: 'join' },
38
46
  ],
39
47
  });
40
48
  }
@@ -51,9 +59,21 @@ function formatRemaining(expiresAt) {
51
59
  const days = Math.round(hours / 24);
52
60
  return `${days} day${days === 1 ? '' : 's'}`;
53
61
  }
54
- export function registerLoginCommands(program) {
55
- program
56
- .command('login')
62
+ /** Register `agents secrets vault unlock|lock` under the secrets parent. */
63
+ export function registerSecretsVaultCommands(secretsCmd) {
64
+ const vault = secretsCmd
65
+ .command('vault')
66
+ .description('Unlock or lock the age-encrypted synced-secrets file (~/.agents/vault.age)');
67
+ setHelpSections(vault, {
68
+ examples: `agents secrets vault unlock
69
+ agents secrets vault unlock --create
70
+ agents secrets vault unlock --join ~/Downloads/vault.age
71
+ agents secrets vault lock`,
72
+ notes: `This is the synced vault passphrase cache — not \`agents secrets unlock\`, which holds keychain bundles in the secrets-agent after Touch ID.
73
+ Harness OAuth sign-out is \`agents accounts logout\` (OAuth native logins only).`,
74
+ });
75
+ vault
76
+ .command('unlock')
57
77
  .description('Unlock synced secrets for this shell session')
58
78
  .option('--create', 'Create a new encrypted synced-secrets file at ~/.agents/vault.age')
59
79
  .option('--join <path>', 'Copy and unlock an existing vault.age file')
@@ -69,10 +89,10 @@ export function registerLoginCommands(program) {
69
89
  unlock(password);
70
90
  const session = getVaultSession();
71
91
  const ttl = session.loggedIn ? formatRemaining(session.expiresAt) : '8 hours';
72
- console.log(chalk.green(`Logged in. Synced secrets unlocked for ${ttl}.`));
92
+ console.log(chalk.green(`Unlocked. Synced secrets available for ${ttl}.`));
73
93
  return;
74
94
  }
75
- const mode = await chooseFreshLoginMode(opts);
95
+ const mode = await chooseFreshMode(opts);
76
96
  if (mode === 'join') {
77
97
  let source = opts.join;
78
98
  if (!source) {
@@ -86,12 +106,12 @@ export function registerLoginCommands(program) {
86
106
  }
87
107
  const password = await readPassword(opts, 'Master password');
88
108
  joinVault(password, source, { overwrite: opts.force });
89
- console.log(chalk.green(`Logged in. Copied synced secrets file to ${vaultPath()}.`));
109
+ console.log(chalk.green(`Unlocked. Copied synced secrets file to ${vaultPath()}.`));
90
110
  return;
91
111
  }
92
112
  const password = await readPassword(opts, 'Choose a master password');
93
113
  createVault(password, { overwrite: opts.force });
94
- console.log(chalk.green(`Logged in. Created synced secrets file at ${vaultPath()}.`));
114
+ console.log(chalk.green(`Unlocked. Created synced secrets file at ${vaultPath()}.`));
95
115
  }
96
116
  catch (err) {
97
117
  if (isPromptCancelled(err))
@@ -100,11 +120,11 @@ export function registerLoginCommands(program) {
100
120
  process.exit(1);
101
121
  }
102
122
  });
103
- program
104
- .command('logout')
123
+ vault
124
+ .command('lock')
105
125
  .description('Forget the cached synced-secrets key')
106
126
  .action(() => {
107
127
  clearVaultKey();
108
- console.log(chalk.green('Logged out. Synced secrets are locked.'));
128
+ console.log(chalk.green('Locked. Synced secrets require unlock again.'));
109
129
  });
110
130
  }
@@ -17,7 +17,7 @@ import { type BundleUsageSummary } from '../lib/secrets/usage-db.js';
17
17
  /** Read all available data from stdin synchronously, trimmed. */
18
18
  /**
19
19
  * Read the raw `.env` text for `import --from <path|->`. A `-` reads the .env
20
- * from stdin (the SSH push path: `export --host` pipes the resolved dotenv over
20
+ * from stdin (the SSH push path: `export --device` pipes the resolved dotenv over
21
21
  * ssh stdin, which has no `/dev/stdin` on a Windows remote); any other value is
22
22
  * a filesystem path.
23
23
  */
@@ -45,7 +45,7 @@ export declare function parseImportSource(opts: {
45
45
  vault?: string;
46
46
  }): ImportSource;
47
47
  /**
48
- * Build the remote `agents secrets unlock` argv for `unlock --host`. `--all`
48
+ * Build the remote `agents secrets unlock` argv for `unlock --device`. `--all`
49
49
  * forwards verbatim; otherwise the explicit bundle names. A `--ttl` is passed
50
50
  * through as-is so the REMOTE parses its own duration (its platform rules, its
51
51
  * defaults). Shared with the command action so the wiring is unit-testable
@@ -78,10 +78,10 @@ export declare function buildRemoteUnlockArgs(names: string[], opts: {
78
78
  durable?: boolean;
79
79
  }): string[];
80
80
  /**
81
- * Build the remote `agents secrets list` argv for `list --host`. Every filter
81
+ * Build the remote `agents secrets list` argv for `list --device`. Every filter
82
82
  * must be forwarded: `browseRemote` sends this argv verbatim, so a flag left out
83
83
  * here is not an error — the remote just lists everything, and
84
- * `secrets list --host zion --expired` reports every bundle on zion as expired.
84
+ * `secrets list --device zion --expired` reports every bundle on zion as expired.
85
85
  * Silent and wrong beats loud and wrong only for the person who wrote the bug.
86
86
  *
87
87
  * Values pass through unparsed so the REMOTE validates them under its own rules,
@@ -14,7 +14,7 @@ import * as os from 'os';
14
14
  import * as path from 'path';
15
15
  import { SSH_TARGET_RE, assertValidSshTarget } from '../lib/ssh-exec.js';
16
16
  import { quoteWin32ExecArg, composeWin32CommandLine } from '../lib/platform/index.js';
17
- import { ensureDaemonStarted, isDaemonRunning } from '../lib/daemon.js';
17
+ import { ensureDaemonStarted, isDaemonRunning } from '../lib/daemon/daemon.js';
18
18
  import { parseHostsOption, remoteResolveEnv, remoteSecretsRaw, remoteSecretsStream, resolveHostSshTarget, } from '../lib/secrets/remote.js';
19
19
  import { resolveBundleForPush, pushResolvedBundleToHost, bundleEnvToDotenv } from '../lib/secrets/push.js';
20
20
  export { bundleEnvToDotenv };
@@ -30,7 +30,7 @@ import { saveSession, deleteBundleSessions, deleteAllSessions } from '../lib/sec
30
30
  import { getCliVersionFresh } from '../lib/version.js';
31
31
  import { readMeta } from '../lib/state.js';
32
32
  import { parseDuration } from '../lib/hooks/cache.js';
33
- import { emit, query } from '../lib/events.js';
33
+ import { emit, query } from '../lib/feed/events.js';
34
34
  import { emitSecretAudit } from '../lib/secrets/audit.js';
35
35
  import { SYNC_PASSPHRASE_ENV, resolveSyncPassphraseFromEnv } from '../lib/secrets/sync-passphrase.js';
36
36
  import { getBundleUsage, getAllBundleUsage, getUsageHistory, SECRET_USAGE_EVENTS, } from '../lib/secrets/usage-db.js';
@@ -43,6 +43,7 @@ import { registerSecretsSyncCommands } from './secrets-sync.js';
43
43
  import { registerSecretsMigrateAclCommand } from './secrets-migrate.js';
44
44
  import { registerSecretsImportKeyringCommand } from './secrets-import.js';
45
45
  import { registerSecretsRotatePassphraseCommand } from './secrets-rotate-passphrase.js';
46
+ import { registerSecretsVaultCommands } from './secrets-vault.js';
46
47
  /** Prompt the user for a secret value with masked input. Requires an interactive TTY. */
47
48
  async function promptForSecret(message) {
48
49
  if (!isInteractiveTerminal()) {
@@ -144,7 +145,7 @@ async function resolveVault(vaultOpt) {
144
145
  /** Read all available data from stdin synchronously, trimmed. */
145
146
  /**
146
147
  * Read the raw `.env` text for `import --from <path|->`. A `-` reads the .env
147
- * from stdin (the SSH push path: `export --host` pipes the resolved dotenv over
148
+ * from stdin (the SSH push path: `export --device` pipes the resolved dotenv over
148
149
  * ssh stdin, which has no `/dev/stdin` on a Windows remote); any other value is
149
150
  * a filesystem path.
150
151
  */
@@ -262,7 +263,7 @@ function maybePrintSyncedHint(name, stillPresent) {
262
263
  }
263
264
  }
264
265
  /**
265
- * Build the remote `agents secrets unlock` argv for `unlock --host`. `--all`
266
+ * Build the remote `agents secrets unlock` argv for `unlock --device`. `--all`
266
267
  * forwards verbatim; otherwise the explicit bundle names. A `--ttl` is passed
267
268
  * through as-is so the REMOTE parses its own duration (its platform rules, its
268
269
  * defaults). Shared with the command action so the wiring is unit-testable
@@ -323,10 +324,10 @@ export function buildRemoteUnlockArgs(names, opts) {
323
324
  ];
324
325
  }
325
326
  /**
326
- * Build the remote `agents secrets list` argv for `list --host`. Every filter
327
+ * Build the remote `agents secrets list` argv for `list --device`. Every filter
327
328
  * must be forwarded: `browseRemote` sends this argv verbatim, so a flag left out
328
329
  * here is not an error — the remote just lists everything, and
329
- * `secrets list --host zion --expired` reports every bundle on zion as expired.
330
+ * `secrets list --device zion --expired` reports every bundle on zion as expired.
330
331
  * Silent and wrong beats loud and wrong only for the person who wrote the bug.
331
332
  *
332
333
  * Values pass through unparsed so the REMOTE validates them under its own rules,
@@ -927,7 +928,7 @@ export function registerSecretsCommands(program) {
927
928
  eval "$(agents secrets export prod --plaintext)"
928
929
 
929
930
  # Push the bundle to remote machine(s) over SSH (lands as a native bundle there)
930
- agents secrets export prod --host yosemite-s0 --host yosemite-s1 --force
931
+ agents secrets export prod --device yosemite-s0 --device yosemite-s1 --force
931
932
 
932
933
  # Run a one-off command with secrets injected
933
934
  agents secrets exec prod -- ./deploy.sh
@@ -983,15 +984,15 @@ export function registerSecretsCommands(program) {
983
984
  { title: 'Raw item commands', names: ['get', 'set'] },
984
985
  { title: 'Sync commands', names: ['push', 'pull', 'remote-list'] },
985
986
  { title: 'Utilities', names: ['exec', 'mcp', 'generate', 'migrate-acl'] },
987
+ { title: 'Synced vault', names: ['vault'] },
986
988
  ]);
989
+ registerSecretsVaultCommands(cmd);
987
990
  const listCmd = cmd
988
991
  .command('list [query]')
989
992
  .alias('ls')
990
- .description('List configured secrets bundles, optionally filtered (use --host/--hosts for other machines over SSH)')
991
- .option('--host <target>', 'List bundles on a remote host over SSH (enrolled `agents hosts` name, ssh-config alias, or user@host)')
992
- .option('--hosts <list>', 'Comma-separated hosts to list in one shot, e.g. yosemite-s0,yosemite-s1')
993
- .option('--device <target>', 'Alias for --host')
994
- .option('--devices <list>', 'Alias for --hosts')
993
+ .description('List configured secrets bundles, optionally filtered (use --device/--devices for other machines over SSH)')
994
+ .option('--device <target>', 'List bundles on a remote device over SSH (enrolled `agents hosts` name, ssh-config alias, or user@host)')
995
+ .option('--devices <list>', 'Comma-separated devices to list in one shot, e.g. yosemite-s0,yosemite-s1')
995
996
  .option('--json', 'Emit machine-readable JSON (bundle metadata only — never secret values) instead of the table')
996
997
  .option('--policy <list>', "Only these prompt policies (comma-separated): hold, always, never. '--policy never' is the audit for bundles that read with no Touch ID at all")
997
998
  .option('--backend <list>', 'Only these backends (comma-separated): keychain, file, vault')
@@ -1005,7 +1006,7 @@ export function registerSecretsCommands(program) {
1005
1006
  .addOption(new Option('--sort <field>', 'Sort by: name (default), used (most recently used), uses (most frequently accessed), created, updated, expiry').choices([...SORT_FIELDS]))
1006
1007
  .option('-n, --limit <n>', 'Show at most this many bundles (after filtering and sorting)')
1007
1008
  .action(async (query, opts) => {
1008
- const targets = parseHostsOption(opts);
1009
+ const targets = parseHostsOption({ device: opts.device, devices: opts.devices });
1009
1010
  if (targets.length > 0) {
1010
1011
  // Forward the filters — browseRemote sends this argv verbatim, so a
1011
1012
  // dropped flag would make the remote silently list everything.
@@ -1028,7 +1029,7 @@ export function registerSecretsCommands(program) {
1028
1029
  // hold-state filter would answer from no data — every bundle would look
1029
1030
  // not-held. Refuse rather than return a confidently wrong list.
1030
1031
  if (filter.held !== undefined && process.platform !== 'darwin') {
1031
- throw new Error('--held/--not-held need the secrets-agent, which is macOS-only. Run it on a Mac, or with --host <mac>.');
1032
+ throw new Error('--held/--not-held need the secrets-agent, which is macOS-only. Run it on a Mac, or with --device <mac>.');
1032
1033
  }
1033
1034
  }
1034
1035
  catch (err) {
@@ -1160,16 +1161,16 @@ export function registerSecretsCommands(program) {
1160
1161
  agents secrets list --policy hold --backend file --expiring
1161
1162
 
1162
1163
  # Same filters, on another machine, machine-readable
1163
- agents secrets list --expired --host mac-mini --json
1164
+ agents secrets list --expired --device mac-mini --json
1164
1165
  `,
1165
1166
  notes: `
1166
1167
  - Filters compose: every flag you add narrows the list further.
1167
1168
  - An unknown value is an error, not an empty list — '--policy hodl' names the valid set.
1168
- - --held/--not-held read live broker state, so they need macOS. Use --host <mac> from elsewhere.
1169
+ - --held/--not-held read live broker state, so they need macOS. Use --device <mac> from elsewhere.
1169
1170
  - --expired and --expiring are different questions: already lapsed vs coming due. The EXPIRING column counts both and turns red once anything has lapsed.
1170
1171
  - --unused matches bundles never read at all, not just old ones.
1171
1172
  - Filters apply before --json, so the JSON is the exact twin of the table.
1172
- - Filters are forwarded over --host, so a remote list narrows the same way.
1173
+ - Filters are forwarded over --device, so a remote list narrows the same way.
1173
1174
  - --sort used|uses read the value-free usage read-model (~/.agents/secrets/secrets.db); see 'agents secrets activity'.
1174
1175
  `,
1175
1176
  });
@@ -1224,13 +1225,11 @@ export function registerSecretsCommands(program) {
1224
1225
  .option('--reveal', 'Print keychain-backed values in the clear (TTY only unless --plaintext)')
1225
1226
  .option('--plaintext', 'Allow --reveal in non-interactive shells (use with care)')
1226
1227
  .option('--json', 'Emit machine-readable JSON (values masked unless --reveal) instead of the human view')
1227
- .option('--host <target>', 'Show a bundle on a remote host over SSH (enrolled `agents hosts` name, ssh-config alias, or user@host)')
1228
- .option('--hosts <list>', 'Comma-separated hosts to show in one shot, e.g. yosemite-s0,yosemite-s1')
1229
- .option('--device <target>', 'Alias for --host')
1230
- .option('--devices <list>', 'Alias for --hosts')
1228
+ .option('--device <target>', 'Show a bundle on a remote device over SSH (enrolled `agents hosts` name, ssh-config alias, or user@host)')
1229
+ .option('--devices <list>', 'Comma-separated devices to show in one shot, e.g. yosemite-s0,yosemite-s1')
1231
1230
  .action(async (name, opts) => {
1232
1231
  try {
1233
- const targets = parseHostsOption(opts);
1232
+ const targets = parseHostsOption({ device: opts.device, devices: opts.devices });
1234
1233
  if (targets.length > 0) {
1235
1234
  if (!name) {
1236
1235
  console.error(chalk.red('A bundle name is required when viewing a remote host (interactive pick needs a local terminal).'));
@@ -1382,7 +1381,7 @@ export function registerSecretsCommands(program) {
1382
1381
  if (bundle.backend === 'file')
1383
1382
  console.log(chalk.gray('backend: file (encrypted at rest; headless reads via a machine-local key, or AGENTS_SECRETS_PASSPHRASE if set — no Touch ID)'));
1384
1383
  if (bundle.backend === 'vault')
1385
- console.log(chalk.gray('storage: synced (age-encrypted ~/.agents/vault.age; needs agents login)'));
1384
+ console.log(chalk.gray('storage: synced (age-encrypted ~/.agents/vault.age; needs `agents secrets vault unlock`)'));
1386
1385
  if (bundlePolicy(bundle) === 'never') {
1387
1386
  console.log(chalk.red.bold('policy: never — NO biometry ACL; reads are silent (no Touch ID, no user-presence check). Automation-only.'));
1388
1387
  }
@@ -2019,12 +2018,28 @@ Examples:
2019
2018
  .option('--backend <backend>', 'When creating the bundle: keychain or file (defaults to agents.yaml secrets.backend)')
2020
2019
  .option('--synced', 'When creating the bundle, store it in the age-encrypted synced secrets file')
2021
2020
  .option('--force', 'Overwrite an existing key in the bundle')
2021
+ .option('--policy <policy>', 'Set the bundle prompt policy as part of this import (always, hold, or never)')
2022
+ .option('--i-understand', 'Confirm an import with policy never (no biometry ACL)')
2022
2023
  .option('--purge', 'With --from icloud: delete the iCloud copies after a successful import (iCloud propagates the deletion to your other devices)')
2023
2024
  .option('--from-file <path>', `Import from an AES-256-GCM encrypted offline bundle file (needs ${SYNC_PASSPHRASE_ENV}; symmetric counterpart of export --to-file)`)
2024
- .option('--from-ssh', 'Pull the bundle from a fleet peer over SSH and import it locally (requires --host)')
2025
- .option('--host <peer>', 'SSH peer to pull from when using --from-ssh (host alias or user@host)')
2025
+ .option('--from-ssh', 'Pull the bundle from a fleet peer over SSH and import it locally (requires --device)')
2026
+ .option('--device <peer>', 'SSH peer to pull from when using --from-ssh (device alias or user@host)')
2026
2027
  .action(async (bundleName, opts) => {
2027
2028
  try {
2029
+ const importPolicy = opts.policy ? parsePolicyOpt(opts.policy) : undefined;
2030
+ const policyAck = assertNeverPolicyAcknowledged(importPolicy, {
2031
+ iUnderstand: opts.iUnderstand,
2032
+ interactive: isInteractiveTerminal(),
2033
+ });
2034
+ if (policyAck === 'prompt' && !(await confirmNeverPolicyInteractive(bundleName ?? 'imported bundle'))) {
2035
+ console.error(chalk.yellow('Aborted.'));
2036
+ return;
2037
+ }
2038
+ const applyImportPolicy = (bundle) => {
2039
+ if (importPolicy)
2040
+ bundle.policy = importPolicy;
2041
+ return bundle;
2042
+ };
2028
2043
  // A single import can name only one source. --from-file / --from-ssh are
2029
2044
  // early-return paths, so guard them against each other and the --from /
2030
2045
  // --from-1password pair (which parseImportSource guards on its own).
@@ -2043,24 +2058,24 @@ Examples:
2043
2058
  }
2044
2059
  const env = importBundleFromFile(opts.fromFile, passphrase);
2045
2060
  const resolvedBundleName = bundleName ?? (await pickBundleName('import into'));
2046
- const bundle = resolveImportBundle(resolvedBundleName, opts.backend, opts.synced, opts.force);
2061
+ const bundle = applyImportPolicy(resolveImportBundle(resolvedBundleName, opts.backend, opts.synced, opts.force));
2047
2062
  const { added, skipped } = applyEnvToBundle(bundle, env, opts);
2048
2063
  emitSecretAudit({ event: 'secrets.import', bundle: bundle.name, operation: 'import --from-file', source: 'file', status: 'success', keyCount: added });
2049
2064
  console.log(chalk.green(`Imported ${added} key(s) from file${skipped ? `, skipped ${skipped} (already set, pass --force)` : ''}.`));
2050
2065
  return;
2051
2066
  }
2052
2067
  if (opts.fromSsh) {
2053
- if (!opts.host) {
2054
- throw new Error('--from-ssh requires --host <peer>.');
2068
+ if (!opts.device) {
2069
+ throw new Error('--from-ssh requires --device <peer>.');
2055
2070
  }
2056
- assertValidSshTarget(opts.host);
2071
+ assertValidSshTarget(opts.device);
2057
2072
  const resolvedBundleName = bundleName ?? (await pickBundleName('import into'));
2058
- const target = await resolveHostSshTarget(opts.host);
2059
- const env = await remoteResolveEnv(target, resolvedBundleName, { osLookupName: opts.host });
2060
- const bundle = resolveImportBundle(resolvedBundleName, opts.backend, opts.synced, opts.force);
2073
+ const target = await resolveHostSshTarget(opts.device);
2074
+ const env = await remoteResolveEnv(target, resolvedBundleName, { osLookupName: opts.device });
2075
+ const bundle = applyImportPolicy(resolveImportBundle(resolvedBundleName, opts.backend, opts.synced, opts.force));
2061
2076
  const { added, skipped } = applyEnvToBundle(bundle, env, opts);
2062
- emitSecretAudit({ event: 'secrets.import', bundle: bundle.name, operation: 'import --from-ssh', source: 'ssh', host: opts.host, status: 'success', keyCount: added });
2063
- console.log(chalk.green(`Imported ${added} key(s) from ${opts.host}${skipped ? `, skipped ${skipped} (already set, pass --force)` : ''}.`));
2077
+ emitSecretAudit({ event: 'secrets.import', bundle: bundle.name, operation: 'import --from-ssh', source: 'ssh', host: opts.device, status: 'success', keyCount: added });
2078
+ console.log(chalk.green(`Imported ${added} key(s) from ${opts.device}${skipped ? `, skipped ${skipped} (already set, pass --force)` : ''}.`));
2064
2079
  return;
2065
2080
  }
2066
2081
  const source = parseImportSource(opts);
@@ -2083,9 +2098,9 @@ Examples:
2083
2098
  const resolvedBundleName = bundleName ?? (await pickBundleName('import into'));
2084
2099
  // resolveImportBundle inherits an existing bundle's backend (and refuses
2085
2100
  // to downgrade keychain -> file) or creates it with the requested backend
2086
- // so a single `import --backend file` works (what `export --host ...
2101
+ // so a single `import --backend file` works (what `export --device ...
2087
2102
  // --remote-backend file` drives on the remote).
2088
- const bundle = resolveImportBundle(resolvedBundleName, opts.backend, opts.synced, opts.force);
2103
+ const bundle = applyImportPolicy(resolveImportBundle(resolvedBundleName, opts.backend, opts.synced, opts.force));
2089
2104
  if (source.kind === '1password') {
2090
2105
  assertOpAvailable();
2091
2106
  const vault = await resolveVault(source.vault);
@@ -2118,23 +2133,17 @@ Examples:
2118
2133
  });
2119
2134
  cmd
2120
2135
  .command('export [bundle]')
2121
- .description('Resolve a bundle and print KEY=VALUE lines, push it to a 1Password vault with --to-1password, or push it to remote machine(s) over SSH with --host.')
2136
+ .description('Resolve a bundle and print KEY=VALUE lines, push it to a 1Password vault with --to-1password, or push it to remote machine(s) over SSH with --device.')
2122
2137
  .option('--plaintext', 'Acknowledge that the resolved values will be printed in the clear (shell export mode)')
2123
2138
  .option('--to-1password', 'Push every key in the bundle as a PASSWORD item in a 1Password vault')
2124
2139
  .option('--vault <name>', '1Password vault name (used with --to-1password)')
2125
- .option('--host <target...>', 'Push the bundle over SSH to this target (host alias or user@host); repeatable for multiple machines')
2126
- .option('--device <target...>', 'Alias for --host; repeatable')
2127
- .option('--remote-backend <backend>', 'Backend for the bundle on the remote (with --host): keychain (default) or file. file is headless-readable via the remote\'s machine-local key; it forwards AGENTS_SECRETS_PASSPHRASE over stdin only if set (opt-in).', 'keychain')
2128
- .option('--force', 'Overwrite existing keys/items on the target (used with --to-1password and --host)')
2140
+ .option('--device <target...>', 'Push the bundle over SSH to this device (host alias or user@host); repeatable for multiple machines')
2141
+ .option('--remote-backend <backend>', 'Backend for the bundle on the remote device (with --device): keychain (default) or file. file is headless-readable via the remote\'s machine-local key; it forwards AGENTS_SECRETS_PASSPHRASE over stdin only if set (opt-in).', 'keychain')
2142
+ .option('--force', 'Overwrite existing keys/items on the target (used with --to-1password and --device)')
2129
2143
  .option('--format <shell|json>', 'Output for --plaintext export: shell (default) or json (lossless, machine-readable; used by remote resolve)', 'shell')
2130
2144
  .option('--to-file <path>', `Write the bundle as an AES-256-GCM encrypted offline file (needs ${SYNC_PASSPHRASE_ENV}; symmetric counterpart of import --from-file)`)
2131
2145
  .action(async (bundleName, opts) => {
2132
2146
  try {
2133
- // `--device` is an alias for `--host` (fleet vocabulary parity with
2134
- // `agents run --device`); fold it into the host list up front so
2135
- // every downstream branch sees one resolved target list.
2136
- if (opts.device?.length)
2137
- opts.host = [...(opts.host ?? []), ...opts.device];
2138
2147
  const { readAndResolveBundleEnv, bundleToEnvPrefix, isReservedEnvName } = await import('../lib/secrets/bundles.js');
2139
2148
  const resolvedBundleName = bundleName ?? (await pickBundleName('export'));
2140
2149
  if (opts.toFile) {
@@ -2150,10 +2159,10 @@ Examples:
2150
2159
  console.log(chalk.green(`Exported ${Object.keys(env).length} key(s) to ${opts.toFile}`));
2151
2160
  return;
2152
2161
  }
2153
- // The presence of --host selects SSH push: --host is the destination
2162
+ // The presence of --device selects SSH push: --device is the destination
2154
2163
  // and carries the mode (no separate --to-ssh needed — it would be
2155
- // strictly redundant since SSH always requires at least one host).
2156
- const hosts = opts.host ?? [];
2164
+ // strictly redundant since SSH always requires at least one device).
2165
+ const hosts = opts.device ?? [];
2157
2166
  if (hosts.length > 0) {
2158
2167
  for (const h of hosts)
2159
2168
  assertValidSshTarget(h);
@@ -2203,7 +2212,7 @@ Examples:
2203
2212
  }
2204
2213
  console.log(chalk.green(`${host} -> '${resolvedBundleName}': ${out.message}`));
2205
2214
  }
2206
- emitSecretAudit({ event: 'secrets.export', bundle: resolvedBundleName, operation: `export --host ${hosts.join(',')}`, source: 'ssh', host: hosts.join(','), status: failures > 0 ? 'error' : 'success', keyCount });
2215
+ emitSecretAudit({ event: 'secrets.export', bundle: resolvedBundleName, operation: `export --device ${hosts.join(',')}`, source: 'ssh', host: hosts.join(','), status: failures > 0 ? 'error' : 'success', keyCount });
2207
2216
  if (failures > 0)
2208
2217
  process.exit(1);
2209
2218
  return;
@@ -2287,8 +2296,8 @@ Examples:
2287
2296
  });
2288
2297
  cmd
2289
2298
  .command('exec <bundle> [command...]')
2290
- .description('Run a command with the bundle\'s secrets injected into the environment (use --host to resolve the bundle from a remote machine, ephemerally)')
2291
- .option('--host <target>', 'Resolve <bundle> on a remote host over SSH and inject it (ephemeral — never stored on this machine)')
2299
+ .description('Run a command with the bundle\'s secrets injected into the environment (use --device to resolve the bundle from a remote machine, ephemerally)')
2300
+ .option('--device <target>', 'Resolve <bundle> on a remote device over SSH and inject it (ephemeral — never stored on this machine)')
2292
2301
  .option('--keys <keys>', 'Inject only this comma-separated subset of keys (e.g. KEY1,KEY2). Missing keys are an error.')
2293
2302
  .option('--allow-expired', 'Inject keys even if their expiry date has passed (overrides the pre-run expiry abort).')
2294
2303
  .allowUnknownOption()
@@ -2303,14 +2312,14 @@ Examples:
2303
2312
  ? execOpts.keys.split(',').map((k) => k.trim()).filter(Boolean)
2304
2313
  : undefined;
2305
2314
  let secretEnv;
2306
- if (execOpts.host) {
2315
+ if (execOpts.device) {
2307
2316
  // Least-privilege flags do not yet cross the SSH resolver —
2308
2317
  // silently applying them would inject the full remote env or an
2309
2318
  // expired key. Fail loud so the user can drop the flag or run
2310
2319
  // locally instead.
2311
2320
  const { assertRemoteBundleFlagsUnsupported } = await import('../lib/secrets/bundles.js');
2312
- assertRemoteBundleFlagsUnsupported(bundleName, execOpts.host, { keys: keysSubset, allowExpired: execOpts.allowExpired }, { keysFlag: '--keys', allowExpiredFlag: '--allow-expired' });
2313
- secretEnv = await remoteResolveEnv(await resolveHostSshTarget(execOpts.host), bundleName, { osLookupName: execOpts.host });
2321
+ assertRemoteBundleFlagsUnsupported(bundleName, execOpts.device, { keys: keysSubset, allowExpired: execOpts.allowExpired }, { keysFlag: '--keys', allowExpiredFlag: '--allow-expired' });
2322
+ secretEnv = await remoteResolveEnv(await resolveHostSshTarget(execOpts.device), bundleName, { osLookupName: execOpts.device });
2314
2323
  }
2315
2324
  else {
2316
2325
  const { readAndResolveBundleEnv } = await import('../lib/secrets/bundles.js');
@@ -2497,14 +2506,14 @@ Examples:
2497
2506
  });
2498
2507
  cmd
2499
2508
  .command('unlock [names...]')
2500
- .description('Hold a bundle in the secrets-agent after one Touch ID, so concurrent runs read it without re-prompting (macOS). With --host, unlock FILE-backed bundle(s) on a remote (the passphrase prompt surfaces over the SSH TTY); keychain/biometry bundles are GUI-only and can\'t be remote-unlocked.')
2509
+ .description('Hold a bundle in the secrets-agent after one Touch ID, so concurrent runs read it without re-prompting (macOS). With --device, unlock FILE-backed bundle(s) on a remote (the passphrase prompt surfaces over the SSH TTY); keychain/biometry bundles are GUI-only and can\'t be remote-unlocked.')
2501
2510
  .option('--ttl <duration>', 'How long to hold it (e.g. 30m, 8h, 3d). Default 7d.')
2502
2511
  .option('--until <date>', 'Hold until this absolute date or timestamp (for example 2026-08-06T12:00:00Z). Mutually exclusive with --ttl.')
2503
2512
  .option('--durable', 'Keep the unlock across sleep + reboot too (default: survives upgrade/restart but re-locks on sleep). Set secrets.agent.durable in agents.yaml to make this the default.')
2504
2513
  .option('--agent <agent>', 'Narrow the unlock to ONE harness type (for example claude, codex, or kimi). Default: the grant is global — every harness and a plain shell can read it, so one Touch ID covers them all.')
2505
2514
  .option('--keys <keys>', 'Hold ONLY this comma-separated subset of the bundle\'s keys instead of the whole bundle. Scopes exactly one bundle; fails closed on an unknown key. `secrets status` shows which keys a scoped hold covers.')
2506
2515
  .option('--all', 'Unlock every configured bundle')
2507
- .option('--host <target>', 'Unlock the bundle(s) on this remote machine over SSH instead of locally (file-backed bundles only — the remote\'s passphrase prompt surfaces on your terminal over a -tt session). Single-valued (NOT variadic) so it never swallows the bundle name: `unlock <name> --host <machine>`.')
2516
+ .option('--device <target>', 'Unlock the bundle(s) on this remote device over SSH instead of locally (file-backed bundles only — the remote\'s passphrase prompt surfaces on your terminal over a -tt session). Single-valued (NOT variadic) so it never swallows the bundle name: `unlock <name> --device <machine>`.')
2508
2517
  .action(async (names, opts) => {
2509
2518
  if (opts.ttl && opts.until) {
2510
2519
  console.error(chalk.red('--ttl and --until are mutually exclusive.'));
@@ -2512,10 +2521,10 @@ Examples:
2512
2521
  }
2513
2522
  if (opts.keys !== undefined) {
2514
2523
  // --keys scopes ONE bundle to an explicit subset. It is local-only (a
2515
- // remote --host unlock holds the whole file-backed bundle) and cannot
2524
+ // remote --device unlock holds the whole file-backed bundle) and cannot
2516
2525
  // combine with --all, which would hold every bundle whole.
2517
- if (opts.host) {
2518
- console.error(chalk.red('--keys is local-only; a remote (--host) unlock holds the whole file-backed bundle.'));
2526
+ if (opts.device) {
2527
+ console.error(chalk.red('--keys is local-only; a remote (--device) unlock holds the whole file-backed bundle.'));
2519
2528
  process.exit(1);
2520
2529
  }
2521
2530
  if (opts.all || !names || names.length !== 1) {
@@ -2523,10 +2532,10 @@ Examples:
2523
2532
  process.exit(1);
2524
2533
  }
2525
2534
  }
2526
- // Single-valued (not variadic): a variadic --host greedily consumes the
2527
- // positional bundle name (`unlock --host mac wztest` -> host=[mac,wztest],
2535
+ // Single-valued (not variadic): a variadic --device greedily consumes the
2536
+ // positional bundle name (`unlock --device mac wztest` -> device=[mac,wztest],
2528
2537
  // names=[]). Unlock targets one remote at a time anyway.
2529
- const hosts = opts.host ? [opts.host] : [];
2538
+ const hosts = opts.device ? [opts.device] : [];
2530
2539
  if (hosts.length > 0) {
2531
2540
  // Remote unlock: the REMOTE enforces its own platform rules, so the
2532
2541
  // local darwin-only guard below does NOT apply. Only file-backed
@@ -204,7 +204,7 @@ export function registerSessionsBackfillCommand(sessionsCmd) {
204
204
  tools.action(async (_options, command) => {
205
205
  const options = command.optsWithGlobals();
206
206
  if (options.local && (options.fleet || mergeHosts(options).length > 0)) {
207
- console.error(chalk.red('--local cannot be combined with --fleet, --host, or --device.'));
207
+ console.error(chalk.red('--local cannot be combined with --fleet or --device.'));
208
208
  process.exitCode = 1;
209
209
  return;
210
210
  }
@@ -81,7 +81,7 @@ export declare function sessionMatchesQuery(s: SessionMeta, query: string): bool
81
81
  * `--print-cmd`.
82
82
  */
83
83
  export declare function browserFilterToArgv(f: BrowserFilter, query?: string): string[];
84
- /** Normalize a `--host`/`--device` token (`alias`, `user@host`, `host.domain`) to
84
+ /** Normalize a `--device`/`--device` token (`alias`, `user@host`, `host.domain`) to
85
85
  * the canonical machine id the rows carry in `.machine`, so a flag seed matches
86
86
  * (the `d` hotkey already cycles canonical ids). Mirrors sessions.ts `hostToken`. */
87
87
  export declare function normalizeDeviceSeed(host: string | undefined): string | undefined;
@@ -16,12 +16,12 @@ import { dynamicPicker } from '../lib/picker.js';
16
16
  import { isSessionTrackedAgent } from '../lib/session/types.js';
17
17
  import { discoverSessions } from '../lib/session/discover.js';
18
18
  import { gatherRemoteList } from '../lib/session/remote-list.js';
19
- import { resolveVersionAliasLoose } from '../lib/versions.js';
19
+ import { resolveVersionAliasLoose } from '../lib/installations/versions.js';
20
20
  import { AGENTS } from '../lib/agents.js';
21
21
  import { enrichTeamOrigins, safeTeamText, shouldShowTeamSessions } from '../lib/session/team-filter.js';
22
22
  import { listBookmarks, toggleBookmark } from '../lib/session/bookmarks.js';
23
23
  import { machineId, normalizeHost } from '../lib/session/sync/config.js';
24
- import { buildPreview } from './sessions-picker.js';
24
+ import { buildPreview, setRemotePreviewRepaint } from './sessions-picker.js';
25
25
  import { formatPickerLabel, pickerColumnsFor, ticketLabel, mergeLocalFirst, gatherActiveSessions, liveHostLabel, LIVE_ROW_PREFIX, cleanPreview, handlePickedSession, shouldIncludeLocal, remoteHostsToDial, matchesTeam, formatLiveStatusHeadline, isRunningLiveSession, matchesLiveStatus, parseAgentFilter, resolveRoutineName, } from './sessions.js';
26
26
  /**
27
27
  * Complete a seed into the filter the picker actually runs on.
@@ -164,7 +164,7 @@ export function browserFilterToArgv(f, query = '') {
164
164
  a.push(JSON.stringify(q));
165
165
  return a;
166
166
  }
167
- /** Normalize a `--host`/`--device` token (`alias`, `user@host`, `host.domain`) to
167
+ /** Normalize a `--device`/`--device` token (`alias`, `user@host`, `host.domain`) to
168
168
  * the canonical machine id the rows carry in `.machine`, so a flag seed matches
169
169
  * (the `d` hotkey already cycles canonical ids). Mirrors sessions.ts `hostToken`. */
170
170
  export function normalizeDeviceSeed(host) {
@@ -253,7 +253,7 @@ function copyToClipboard(text) {
253
253
  * The live index is fetched separately/lazily — it's the slow part and only the
254
254
  * running filter needs it, so a bare browse stays instant.
255
255
  *
256
- * `hosts` is the explicit `--host`/`--device` scope (if any): it restricts which
256
+ * `hosts` is the explicit `--device`/`--device` scope (if any): it restricts which
257
257
  * peers are dialed and whether local is included, honoring the flag's "scope,
258
258
  * not add" contract instead of always sweeping the whole fleet. */
259
259
  async function fetchRawPool(f, self, local, hosts, fixedFilters = false) {
@@ -699,6 +699,9 @@ export async function runSessionBrowser(initial = {}, opts = {}) {
699
699
  const body = buildPreview(s);
700
700
  return headline ? `${headline}\n${body}` : body;
701
701
  },
702
+ // A remote row's digest arrives over SSH after the pane painted — this is
703
+ // what lets its completion swap the metadata card for the full preview.
704
+ registerPreviewRepaint: setRemotePreviewRepaint,
702
705
  headerFor: (f) => unreachable.length > 0
703
706
  ? `${headerFor(f)} · ${chalk.yellow(`${unreachable.join(', ')}: unreachable`)}`
704
707
  : headerFor(f),
@@ -741,7 +744,8 @@ export async function runSessionBrowser(initial = {}, opts = {}) {
741
744
  }
742
745
  return undefined;
743
746
  },
744
- });
747
+ // A late digest fetch must not poke a closed prompt.
748
+ }).finally(() => setRemotePreviewRepaint(undefined));
745
749
  if (!picked)
746
750
  return;
747
751
  if (picked.action === 'focus') {
@@ -196,7 +196,7 @@ export function r2ExportGateError(g, isConfigured) {
196
196
  if (!g.toR2)
197
197
  return null;
198
198
  if (g.host && g.host.length > 0) {
199
- return "--to-r2 backs up THIS machine's sessions; it cannot be combined with --host.";
199
+ return "--to-r2 backs up THIS machine's sessions; it cannot be combined with --device.";
200
200
  }
201
201
  if (!isConfigured) {
202
202
  return ('R2 backup is not configured: the r2.backups secrets bundle is missing or locked.\n' +
@@ -266,7 +266,7 @@ export function resolveR2BackupKey() {
266
266
  */
267
267
  async function runRemoteExport(g, selectors, command) {
268
268
  if (g.encrypt) {
269
- process.stderr.write(chalk.yellow('Note: --encrypt is ignored with --host (the SSH stream is already encrypted). Encrypt a local bundle instead.\n'));
269
+ process.stderr.write(chalk.yellow('Note: --encrypt is ignored with --device (the SSH stream is already encrypted). Encrypt a local bundle instead.\n'));
270
270
  }
271
271
  const { bundles, errors } = await pullBundlesFromHosts(g.host, forwardExportArgs(g, selectors, command));
272
272
  for (const e of errors)
@@ -14,8 +14,7 @@
14
14
  */
15
15
  import chalk from 'chalk';
16
16
  import { getActiveSessions } from '../lib/session/active.js';
17
- import { resolveInjectTargetForSession } from '../lib/terminal/resolve.js';
18
- import { injectIntoTerminal } from '../lib/terminal/index.js';
17
+ import { injectIntoTerminal, resolveInjectTargetForSession } from '../lib/terminal/index.js';
19
18
  import { setHelpSections } from '../lib/help.js';
20
19
  /** Resolve a session id (short or full) to an addressable terminal target, via the
21
20
  * same resolver the watchdog uses so both agree on what is reachable. */
@@ -56,7 +55,7 @@ async function runInject(sessionId, text, options) {
56
55
  enter: options.enter !== false,
57
56
  combined: options.combined,
58
57
  socket: options.socket,
59
- host: options.host,
58
+ host: options.device,
60
59
  });
61
60
  if (options.json) {
62
61
  console.log(JSON.stringify(res));
@@ -78,7 +77,7 @@ export function registerSessionsInjectCommand(sessionsCmd) {
78
77
  .option('--pane <id>', 'Target a tmux pane id directly (e.g. %3), skipping session lookup')
79
78
  .option('--pty <id>', 'Target an agents-pty session id directly, skipping session lookup')
80
79
  .option('--socket <path>', 'tmux socket path (defaults to the session/shared socket)')
81
- .option('--host <target>', 'Deliver on a remote host over SSH (tmux/AppleScript backends)')
80
+ .option('--device <target>', 'Deliver on a remote device over SSH (tmux/AppleScript backends)')
82
81
  .option('--no-enter', 'Send only the text, without a trailing Enter')
83
82
  .option('--combined', 'Fuse text + Enter into ONE write (default: two writes, Ink-TUI safe)')
84
83
  .option('--json', 'Output the InjectResult as JSON');
@@ -99,7 +98,7 @@ export function registerSessionsInjectCommand(sessionsCmd) {
99
98
  - A session is addressable by id when it resolves to a precise split —
100
99
  tmux, iTerm, a VSCodium/Cursor/VS Code integrated terminal, or a pty
101
100
  (resolveInjectTargetForSession). Use --pane/--pty for direct targeting.
102
- - Built on the Terminal Engine (src/lib/terminal): --host runs the tmux /
101
+ - Built on the Terminal Engine (src/lib/terminal): --device runs the tmux /
103
102
  AppleScript spec over the same SSH transport the launch engine uses.
104
103
  `,
105
104
  });