@phnx-labs/agents-cli 1.22.39 → 1.22.41

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 (569) hide show
  1. package/CHANGELOG.md +316 -0
  2. package/README.md +116 -70
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +45 -27
  5. package/dist/browser.js +2 -2
  6. package/dist/cli/command-registry.d.ts +135 -0
  7. package/dist/cli/command-registry.js +259 -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.d.ts +15 -0
  13. package/dist/commands/browser.js +318 -131
  14. package/dist/commands/budget.d.ts +7 -6
  15. package/dist/commands/budget.js +8 -7
  16. package/dist/commands/cloud.js +17 -20
  17. package/dist/commands/commands.js +1 -1
  18. package/dist/commands/computer-actions.d.ts +1 -35
  19. package/dist/commands/computer-actions.js +13 -181
  20. package/dist/commands/computer.d.ts +28 -3
  21. package/dist/commands/computer.js +93 -65
  22. package/dist/commands/config.js +16 -3
  23. package/dist/commands/cost.d.ts +2 -1
  24. package/dist/commands/cost.js +7 -6
  25. package/dist/commands/daemon.js +151 -4
  26. package/dist/commands/detach.js +1 -1
  27. package/dist/commands/doctor.js +19 -11
  28. package/dist/commands/events.js +1 -1
  29. package/dist/commands/exec.d.ts +2 -50
  30. package/dist/commands/exec.js +160 -215
  31. package/dist/commands/factory.js +1 -1
  32. package/dist/commands/feed.d.ts +2 -2
  33. package/dist/commands/feed.js +12 -23
  34. package/dist/commands/fleet-capture.js +25 -27
  35. package/dist/commands/focus.d.ts +2 -3
  36. package/dist/commands/focus.js +34 -9
  37. package/dist/commands/go.js +15 -5
  38. package/dist/commands/harness.d.ts +3 -3
  39. package/dist/commands/harness.js +53 -5
  40. package/dist/commands/hooks.js +1 -1
  41. package/dist/commands/import.js +2 -2
  42. package/dist/commands/insights.d.ts +5 -5
  43. package/dist/commands/insights.js +15 -9
  44. package/dist/commands/inspect.d.ts +2 -3
  45. package/dist/commands/inspect.js +4 -16
  46. package/dist/commands/logs.d.ts +2 -2
  47. package/dist/commands/logs.js +9 -9
  48. package/dist/commands/mcp.js +2 -2
  49. package/dist/commands/memory.js +1 -1
  50. package/dist/commands/message.d.ts +1 -1
  51. package/dist/commands/message.js +7 -7
  52. package/dist/commands/mine.d.ts +11 -8
  53. package/dist/commands/mine.js +11 -10
  54. package/dist/commands/models.js +1 -1
  55. package/dist/commands/modes.js +1 -1
  56. package/dist/commands/monitors.js +23 -6
  57. package/dist/commands/output.d.ts +7 -6
  58. package/dist/commands/output.js +11 -10
  59. package/dist/commands/packages.js +4 -4
  60. package/dist/commands/perf.js +1 -1
  61. package/dist/commands/permissions.js +49 -32
  62. package/dist/commands/plugins.d.ts +1 -1
  63. package/dist/commands/plugins.js +3 -3
  64. package/dist/commands/profiles.d.ts +6 -9
  65. package/dist/commands/profiles.js +8 -321
  66. package/dist/commands/projects.d.ts +9 -0
  67. package/dist/commands/projects.js +140 -8
  68. package/dist/commands/prune.js +5 -13
  69. package/dist/commands/refresh-rules.js +1 -1
  70. package/dist/commands/repo.d.ts +5 -7
  71. package/dist/commands/repo.js +34 -18
  72. package/dist/commands/resource-view.js +4 -0
  73. package/dist/commands/resume.d.ts +11 -7
  74. package/dist/commands/resume.js +82 -98
  75. package/dist/commands/route.d.ts +12 -0
  76. package/dist/commands/route.js +261 -0
  77. package/dist/commands/routines.d.ts +2 -3
  78. package/dist/commands/routines.js +120 -145
  79. package/dist/commands/rules.js +1 -1
  80. package/dist/commands/run-account-picker.d.ts +1 -1
  81. package/dist/commands/run-account-picker.js +2 -2
  82. package/dist/commands/run-broadcast.d.ts +21 -0
  83. package/dist/commands/run-broadcast.js +89 -0
  84. package/dist/commands/run-cloud.js +1 -1
  85. package/dist/commands/secrets-vault.d.ts +10 -0
  86. package/dist/commands/{login.js → secrets-vault.js} +34 -14
  87. package/dist/commands/secrets.d.ts +4 -4
  88. package/dist/commands/secrets.js +158 -159
  89. package/dist/commands/sessions-backfill.js +1 -1
  90. package/dist/commands/sessions-browser.d.ts +1 -1
  91. package/dist/commands/sessions-browser.js +9 -5
  92. package/dist/commands/sessions-export.js +2 -2
  93. package/dist/commands/sessions-inject.js +4 -5
  94. package/dist/commands/sessions-migrate.js +16 -27
  95. package/dist/commands/sessions-picker.d.ts +14 -0
  96. package/dist/commands/sessions-picker.js +209 -13
  97. package/dist/commands/sessions-resume.d.ts +7 -3
  98. package/dist/commands/sessions-resume.js +81 -33
  99. package/dist/commands/sessions-share.d.ts +25 -0
  100. package/dist/commands/sessions-share.js +166 -0
  101. package/dist/commands/sessions-stats.js +2 -2
  102. package/dist/commands/sessions.d.ts +75 -68
  103. package/dist/commands/sessions.js +144 -180
  104. package/dist/commands/setup-browser.js +1 -1
  105. package/dist/commands/setup-computer.js +1 -1
  106. package/dist/commands/setup-fleet.js +3 -0
  107. package/dist/commands/setup-mine.d.ts +7 -3
  108. package/dist/commands/setup-mine.js +13 -8
  109. package/dist/commands/setup-preferences.js +2 -2
  110. package/dist/commands/setup-secrets.js +2 -2
  111. package/dist/commands/setup-watchdog.js +2 -2
  112. package/dist/commands/setup.js +7 -2
  113. package/dist/commands/share.d.ts +65 -0
  114. package/dist/commands/share.js +253 -20
  115. package/dist/commands/skills.js +3 -3
  116. package/dist/commands/snapshot.d.ts +2 -2
  117. package/dist/commands/snapshot.js +9 -9
  118. package/dist/commands/ssh.d.ts +1 -1
  119. package/dist/commands/ssh.js +186 -64
  120. package/dist/commands/subagents.js +1 -1
  121. package/dist/commands/sync.js +24 -9
  122. package/dist/commands/teams.d.ts +2 -2
  123. package/dist/commands/teams.js +9 -18
  124. package/dist/commands/tmux.js +5 -1
  125. package/dist/commands/trash.js +1 -1
  126. package/dist/commands/usage.d.ts +1 -1
  127. package/dist/commands/usage.js +2 -2
  128. package/dist/commands/utils.d.ts +4 -14
  129. package/dist/commands/utils.js +6 -27
  130. package/dist/commands/versions.js +2 -2
  131. package/dist/commands/view.d.ts +9 -77
  132. package/dist/commands/view.js +23 -8
  133. package/dist/commands/watchdog.js +1 -1
  134. package/dist/commands/webhook.js +25 -34
  135. package/dist/commands/workflows.js +1 -1
  136. package/dist/index.js +1 -1
  137. package/dist/lib/account-capabilities.d.ts +39 -0
  138. package/dist/lib/account-capabilities.js +59 -0
  139. package/dist/lib/account-catalog.js +1 -1
  140. package/dist/lib/account-registry.d.ts +66 -0
  141. package/dist/lib/account-registry.js +151 -5
  142. package/dist/lib/{rotate.d.ts → accounting/rotate.d.ts} +4 -4
  143. package/dist/lib/{rotate.js → accounting/rotate.js} +8 -8
  144. package/dist/lib/{usage.d.ts → accounting/usage.d.ts} +4 -4
  145. package/dist/lib/{usage.js → accounting/usage.js} +11 -11
  146. package/dist/lib/agent-spec/provider.js +1 -1
  147. package/dist/lib/agents.d.ts +72 -4
  148. package/dist/lib/agents.js +231 -199
  149. package/dist/lib/answer-router.d.ts +2 -2
  150. package/dist/lib/ask-classifier.d.ts +1 -1
  151. package/dist/lib/ask-classifier.js +1 -1
  152. package/dist/lib/audit/log.js +1 -1
  153. package/dist/lib/auth-health.d.ts +1 -1
  154. package/dist/lib/auth-health.js +2 -2
  155. package/dist/lib/brand.js +1 -1
  156. package/dist/lib/browser/caller-identity.d.ts +28 -0
  157. package/dist/lib/browser/caller-identity.js +156 -0
  158. package/dist/lib/browser/cdp.js +5 -1
  159. package/dist/lib/browser/chrome.js +12 -1
  160. package/dist/lib/browser/drivers/ssh.d.ts +1 -1
  161. package/dist/lib/browser/drivers/ssh.js +3 -2
  162. package/dist/lib/browser/hygiene.d.ts +10 -2
  163. package/dist/lib/browser/hygiene.js +7 -4
  164. package/dist/lib/browser/ipc.d.ts +22 -2
  165. package/dist/lib/browser/ipc.js +185 -21
  166. package/dist/lib/browser/profiles.d.ts +69 -5
  167. package/dist/lib/browser/profiles.js +135 -13
  168. package/dist/lib/browser/remote-control.d.ts +2 -2
  169. package/dist/lib/browser/remote-control.js +3 -3
  170. package/dist/lib/browser/runtime-state.d.ts +79 -0
  171. package/dist/lib/browser/runtime-state.js +119 -1
  172. package/dist/lib/browser/service.d.ts +137 -2
  173. package/dist/lib/browser/service.js +492 -54
  174. package/dist/lib/browser/sessions-list.d.ts +2 -1
  175. package/dist/lib/browser/sessions-list.js +4 -13
  176. package/dist/lib/browser/types.d.ts +19 -1
  177. package/dist/lib/budget/config.js +1 -1
  178. package/dist/lib/budget/ledger.js +1 -1
  179. package/dist/lib/byok-usage.js +1 -1
  180. package/dist/lib/capabilities.js +3 -15
  181. package/dist/lib/catchup.d.ts +1 -1
  182. package/dist/lib/catchup.js +1 -1
  183. package/dist/lib/cloud/dispatch.js +1 -1
  184. package/dist/lib/cloud/host.d.ts +3 -3
  185. package/dist/lib/cloud/host.js +5 -5
  186. package/dist/lib/cloud/rush.d.ts +9 -21
  187. package/dist/lib/cloud/rush.js +33 -120
  188. package/dist/lib/cloud/types.d.ts +2 -2
  189. package/dist/lib/commands.js +3 -13
  190. package/dist/lib/computer/actions.d.ts +36 -0
  191. package/dist/lib/computer/actions.js +162 -0
  192. package/dist/lib/computer/dispatch.d.ts +2 -2
  193. package/dist/lib/computer/dispatch.js +2 -2
  194. package/dist/lib/computer/sessions-list.d.ts +3 -3
  195. package/dist/lib/computer/sessions-list.js +2 -2
  196. package/dist/lib/config-keys.d.ts +2 -1
  197. package/dist/lib/config-keys.js +8 -4
  198. package/dist/lib/config-machine-keys.d.ts +4 -2
  199. package/dist/lib/config-machine-keys.js +5 -2
  200. package/dist/lib/crabbox/lease.js +9 -1
  201. package/dist/lib/crabbox/runtimes.d.ts +32 -7
  202. package/dist/lib/crabbox/runtimes.js +72 -30
  203. package/dist/lib/{daemon.d.ts → daemon/daemon.d.ts} +59 -1
  204. package/dist/lib/{daemon.js → daemon/daemon.js} +237 -49
  205. package/dist/lib/daemon-services.d.ts +1 -1
  206. package/dist/lib/daemon-services.js +5 -0
  207. package/dist/lib/daemon-ticks.d.ts +25 -0
  208. package/dist/lib/daemon-ticks.js +31 -1
  209. package/dist/lib/daemon-webhooks.d.ts +104 -0
  210. package/dist/lib/daemon-webhooks.js +215 -0
  211. package/dist/lib/device-config.d.ts +85 -75
  212. package/dist/lib/device-config.js +280 -142
  213. package/dist/lib/devices/config-migration.d.ts +29 -34
  214. package/dist/lib/devices/config-migration.js +209 -130
  215. package/dist/lib/devices/connect.d.ts +2 -2
  216. package/dist/lib/devices/connect.js +2 -2
  217. package/dist/lib/devices/discovery-policy.d.ts +30 -0
  218. package/dist/lib/devices/discovery-policy.js +101 -0
  219. package/dist/lib/devices/fleet-inventory.js +8 -3
  220. package/dist/lib/devices/harness-inventory.d.ts +1 -1
  221. package/dist/lib/devices/harness-inventory.js +12 -3
  222. package/dist/lib/devices/known-hosts.js +1 -1
  223. package/dist/lib/devices/pool.d.ts +10 -5
  224. package/dist/lib/devices/pool.js +5 -7
  225. package/dist/lib/devices/registry.d.ts +1 -1
  226. package/dist/lib/devices/registry.js +1 -1
  227. package/dist/lib/devices/resolve-profile.d.ts +2 -2
  228. package/dist/lib/devices/resolve-profile.js +2 -2
  229. package/dist/lib/devices/resolve-target.d.ts +1 -1
  230. package/dist/lib/devices/resolve-target.js +4 -4
  231. package/dist/lib/devices/self-host.d.ts +1 -1
  232. package/dist/lib/devices/self-host.js +3 -3
  233. package/dist/lib/devices/ssh-config.d.ts +1 -1
  234. package/dist/lib/devices/stats-cache.js +1 -1
  235. package/dist/lib/devices/sync.d.ts +3 -1
  236. package/dist/lib/devices/sync.js +3 -3
  237. package/dist/lib/doctor-diff.js +4 -4
  238. package/dist/lib/drift-sync.js +2 -2
  239. package/dist/lib/drift.js +2 -2
  240. package/dist/lib/event-families.d.ts +1 -1
  241. package/dist/lib/event-stream.d.ts +1 -1
  242. package/dist/lib/event-stream.js +2 -2
  243. package/dist/lib/events-ingest.js +2 -2
  244. package/dist/lib/exec.d.ts +4 -4
  245. package/dist/lib/exec.js +11 -11
  246. package/dist/lib/factory/snapshot.d.ts +1 -1
  247. package/dist/lib/factory/snapshot.js +1 -1
  248. package/dist/lib/{activity.d.ts → feed/activity.d.ts} +1 -1
  249. package/dist/lib/{activity.js → feed/activity.js} +7 -7
  250. package/dist/lib/{events.d.ts → feed/events.d.ts} +2 -2
  251. package/dist/lib/{events.js → feed/events.js} +5 -5
  252. package/dist/lib/{feed.js → feed/feed.js} +4 -4
  253. package/dist/lib/feed-outcome.d.ts +1 -1
  254. package/dist/lib/feed-policy.d.ts +1 -1
  255. package/dist/lib/feed-policy.js +1 -1
  256. package/dist/lib/feed-post.d.ts +1 -1
  257. package/dist/lib/feed-post.js +1 -1
  258. package/dist/lib/feed-ranking.d.ts +1 -1
  259. package/dist/lib/fleet/apply.d.ts +0 -6
  260. package/dist/lib/fleet/apply.js +18 -45
  261. package/dist/lib/fleet/auth-sync.d.ts +16 -35
  262. package/dist/lib/fleet/auth-sync.js +16 -75
  263. package/dist/lib/fleet/capture.js +8 -6
  264. package/dist/lib/fleet/manifest.js +23 -11
  265. package/dist/lib/fleet/types.d.ts +19 -7
  266. package/dist/lib/fleet-cache.d.ts +1 -1
  267. package/dist/lib/fleet-cache.js +1 -1
  268. package/dist/lib/format.d.ts +19 -0
  269. package/dist/lib/format.js +44 -1
  270. package/dist/lib/friction-heuristics.d.ts +1 -1
  271. package/dist/lib/git.d.ts +24 -1
  272. package/dist/lib/git.js +82 -38
  273. package/dist/lib/heal.js +3 -3
  274. package/dist/lib/hooks.d.ts +18 -0
  275. package/dist/lib/hooks.js +113 -1
  276. package/dist/lib/hosts/credentials.d.ts +30 -10
  277. package/dist/lib/hosts/credentials.js +38 -26
  278. package/dist/lib/hosts/dispatch.d.ts +3 -3
  279. package/dist/lib/hosts/dispatch.js +3 -3
  280. package/dist/lib/hosts/option.d.ts +3 -3
  281. package/dist/lib/hosts/option.js +7 -8
  282. package/dist/lib/hosts/passthrough.d.ts +17 -17
  283. package/dist/lib/hosts/passthrough.js +67 -50
  284. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  285. package/dist/lib/hosts/providers/devices.js +1 -1
  286. package/dist/lib/hosts/reconcile.d.ts +1 -1
  287. package/dist/lib/hosts/reconcile.js +1 -1
  288. package/dist/lib/hosts/reconnect.d.ts +1 -1
  289. package/dist/lib/hosts/reconnect.js +2 -2
  290. package/dist/lib/hosts/registry.d.ts +5 -5
  291. package/dist/lib/hosts/registry.js +5 -5
  292. package/dist/lib/hosts/remote-cmd.d.ts +10 -10
  293. package/dist/lib/hosts/remote-cmd.js +25 -18
  294. package/dist/lib/hosts/remote-os.d.ts +4 -4
  295. package/dist/lib/hosts/remote-os.js +4 -4
  296. package/dist/lib/hosts/remote-session-id.d.ts +2 -2
  297. package/dist/lib/hosts/remote-session-id.js +2 -2
  298. package/dist/lib/hosts/routing-flag.d.ts +3 -3
  299. package/dist/lib/hosts/routing-flag.js +4 -5
  300. package/dist/lib/hosts/run-target.d.ts +4 -4
  301. package/dist/lib/hosts/run-target.js +4 -4
  302. package/dist/lib/hosts/session-index.d.ts +2 -2
  303. package/dist/lib/hosts/session-index.js +1 -1
  304. package/dist/lib/hosts/session-marker.d.ts +1 -1
  305. package/dist/lib/hosts/session-marker.js +1 -1
  306. package/dist/lib/hosts/types.d.ts +2 -2
  307. package/dist/lib/hosts/types.js +2 -2
  308. package/dist/lib/import.js +1 -1
  309. package/dist/lib/{migrate.d.ts → installations/migrate.d.ts} +13 -1
  310. package/dist/lib/{migrate.js → installations/migrate.js} +160 -40
  311. package/dist/lib/installations/resolve.js +1 -1
  312. package/dist/lib/installations/strategies.js +1 -1
  313. package/dist/lib/installations/update.js +2 -2
  314. package/dist/lib/{versions.d.ts → installations/versions.d.ts} +12 -3
  315. package/dist/lib/{versions.js → installations/versions.js} +51 -31
  316. package/dist/lib/isolation-boundary-report.js +1 -1
  317. package/dist/lib/linear-projects.d.ts +28 -0
  318. package/dist/lib/linear-projects.js +30 -0
  319. package/dist/lib/loop.js +1 -1
  320. package/dist/lib/mailbox-gc.js +1 -1
  321. package/dist/lib/mailbox.js +1 -1
  322. package/dist/lib/mcp-registry.d.ts +62 -0
  323. package/dist/lib/mcp-registry.js +177 -0
  324. package/dist/lib/mcp.d.ts +5 -0
  325. package/dist/lib/mcp.js +124 -307
  326. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  327. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  328. package/dist/lib/menubar/install-menubar.d.ts +7 -0
  329. package/dist/lib/menubar/install-menubar.js +24 -6
  330. package/dist/lib/menubar/snapshot.d.ts +7 -0
  331. package/dist/lib/menubar/snapshot.js +8 -6
  332. package/dist/lib/models.js +1 -1
  333. package/dist/lib/monitors/config.d.ts +12 -0
  334. package/dist/lib/monitors/config.js +3 -0
  335. package/dist/lib/monitors/dispatch.js +26 -5
  336. package/dist/lib/monitors/engine.js +10 -0
  337. package/dist/lib/monitors/sources/webhook.d.ts +1 -1
  338. package/dist/lib/monitors/state.d.ts +42 -0
  339. package/dist/lib/monitors/state.js +30 -0
  340. package/dist/lib/notify.d.ts +1 -1
  341. package/dist/lib/observe-aliases.d.ts +3 -3
  342. package/dist/lib/observe-aliases.js +3 -21
  343. package/dist/lib/output/git-output.js +2 -2
  344. package/dist/lib/overdue.d.ts +1 -1
  345. package/dist/lib/overdue.js +1 -1
  346. package/dist/lib/permissions-registry.d.ts +65 -0
  347. package/dist/lib/permissions-registry.js +599 -0
  348. package/dist/lib/permissions.d.ts +24 -13
  349. package/dist/lib/permissions.js +52 -271
  350. package/dist/lib/picker.d.ts +16 -0
  351. package/dist/lib/picker.js +33 -3
  352. package/dist/lib/placement.d.ts +1 -1
  353. package/dist/lib/placement.js +4 -4
  354. package/dist/lib/platform/paths.d.ts +8 -0
  355. package/dist/lib/platform/paths.js +11 -0
  356. package/dist/lib/platform/posixpath.js +3 -3
  357. package/dist/lib/{plugin-marketplace.d.ts → plugins/plugin-marketplace.d.ts} +1 -1
  358. package/dist/lib/{plugin-marketplace.js → plugins/plugin-marketplace.js} +2 -2
  359. package/dist/lib/{plugins.d.ts → plugins/plugins.d.ts} +1 -1
  360. package/dist/lib/{plugins.js → plugins/plugins.js} +7 -7
  361. package/dist/lib/{skills.d.ts → plugins/skills.d.ts} +1 -1
  362. package/dist/lib/{skills.js → plugins/skills.js} +7 -7
  363. package/dist/lib/pricing/cost.d.ts +1 -1
  364. package/dist/lib/pricing/cost.js +1 -1
  365. package/dist/lib/profiles-presets.d.ts +1 -1
  366. package/dist/lib/profiles-presets.js +1 -1
  367. package/dist/lib/profiles.js +2 -2
  368. package/dist/lib/project-import.js +4 -1
  369. package/dist/lib/project-key.js +7 -0
  370. package/dist/lib/project-launch.d.ts +1 -1
  371. package/dist/lib/project-launch.js +3 -3
  372. package/dist/lib/project-pull.d.ts +128 -0
  373. package/dist/lib/project-pull.js +384 -0
  374. package/dist/lib/project-root.d.ts +2 -2
  375. package/dist/lib/project-root.js +2 -2
  376. package/dist/lib/project-status.js +1 -1
  377. package/dist/lib/projects.d.ts +23 -0
  378. package/dist/lib/projects.js +29 -6
  379. package/dist/lib/refresh.d.ts +12 -1
  380. package/dist/lib/refresh.js +16 -9
  381. package/dist/lib/registry.d.ts +9 -2
  382. package/dist/lib/registry.js +11 -4
  383. package/dist/lib/resources.d.ts +2 -2
  384. package/dist/lib/resources.js +2 -2
  385. package/dist/lib/routers.d.ts +81 -0
  386. package/dist/lib/routers.js +153 -0
  387. package/dist/lib/routine-context.d.ts +1 -0
  388. package/dist/lib/routine-context.js +7 -2
  389. package/dist/lib/routine-notify-owner.d.ts +1 -1
  390. package/dist/lib/routine-notify.d.ts +1 -1
  391. package/dist/lib/routine-notify.js +1 -1
  392. package/dist/lib/routine-process-cleanup.d.ts +1 -1
  393. package/dist/lib/routine-readiness.d.ts +1 -1
  394. package/dist/lib/routine-readiness.js +11 -4
  395. package/dist/lib/routines-placement.d.ts +12 -2
  396. package/dist/lib/routines-placement.js +20 -3
  397. package/dist/lib/routines-project.d.ts +1 -1
  398. package/dist/lib/routines-project.js +1 -1
  399. package/dist/lib/rules/compile.d.ts +1 -0
  400. package/dist/lib/rules/compile.js +10 -2
  401. package/dist/lib/rules/rules.js +1 -1
  402. package/dist/lib/run-notify.js +1 -1
  403. package/dist/lib/runner.d.ts +80 -2
  404. package/dist/lib/runner.js +261 -67
  405. package/dist/lib/sandbox.d.ts +1 -1
  406. package/dist/lib/scheduler.d.ts +1 -1
  407. package/dist/lib/scheduler.js +1 -1
  408. package/dist/lib/{routines.d.ts → scheduling/routines.d.ts} +54 -9
  409. package/dist/lib/{routines.js → scheduling/routines.js} +173 -14
  410. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  411. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  412. package/dist/lib/secrets/agent.js +2 -2
  413. package/dist/lib/secrets/audit.js +1 -1
  414. package/dist/lib/secrets/bundles.d.ts +4 -4
  415. package/dist/lib/secrets/bundles.js +8 -8
  416. package/dist/lib/secrets/headless.d.ts +16 -0
  417. package/dist/lib/secrets/headless.js +21 -0
  418. package/dist/lib/secrets/index.js +1 -1
  419. package/dist/lib/secrets/list-filter.d.ts +1 -1
  420. package/dist/lib/secrets/list-filter.js +2 -2
  421. package/dist/lib/secrets/push.d.ts +1 -1
  422. package/dist/lib/secrets/push.js +10 -12
  423. package/dist/lib/secrets/remote.d.ts +21 -17
  424. package/dist/lib/secrets/remote.js +39 -23
  425. package/dist/lib/secrets/vault.js +2 -2
  426. package/dist/lib/self-heal/checks/shadowing.js +1 -1
  427. package/dist/lib/self-heal/checks/shims.js +1 -1
  428. package/dist/lib/self-update.d.ts +39 -4
  429. package/dist/lib/self-update.js +78 -25
  430. package/dist/lib/serve/control.d.ts +1 -1
  431. package/dist/lib/serve/control.js +4 -4
  432. package/dist/lib/serve/data.d.ts +1 -1
  433. package/dist/lib/serve/data.js +1 -1
  434. package/dist/lib/serve/stream.js +1 -1
  435. package/dist/lib/service-manifest.d.ts +29 -0
  436. package/dist/lib/service-manifest.js +80 -0
  437. package/dist/lib/session/active.d.ts +59 -7
  438. package/dist/lib/session/active.js +158 -17
  439. package/dist/lib/session/bash-command.js +1 -1
  440. package/dist/lib/session/claude-accounts.d.ts +1 -1
  441. package/dist/lib/session/claude-accounts.js +1 -1
  442. package/dist/lib/session/db.d.ts +10 -2
  443. package/dist/lib/session/db.js +25 -6
  444. package/dist/lib/session/discover.d.ts +77 -0
  445. package/dist/lib/session/discover.js +130 -25
  446. package/dist/lib/session/fork.js +1 -1
  447. package/dist/lib/session/inject.d.ts +1 -1
  448. package/dist/lib/session/insights.d.ts +1 -1
  449. package/dist/lib/session/insights.js +1 -1
  450. package/dist/lib/session/live-metadata.d.ts +15 -0
  451. package/dist/lib/session/live-metadata.js +76 -0
  452. package/dist/lib/session/migrate-targets.d.ts +1 -1
  453. package/dist/lib/session/recovery.d.ts +1 -1
  454. package/dist/lib/session/recovery.js +2 -2
  455. package/dist/lib/session/remote-active.d.ts +10 -1
  456. package/dist/lib/session/remote-active.js +8 -3
  457. package/dist/lib/session/remote-bundle.d.ts +1 -1
  458. package/dist/lib/session/remote-bundle.js +2 -2
  459. package/dist/lib/session/remote-list.d.ts +15 -4
  460. package/dist/lib/session/remote-list.js +40 -3
  461. package/dist/lib/session/remote.d.ts +5 -5
  462. package/dist/lib/session/remote.js +13 -17
  463. package/dist/lib/session/resume-command.d.ts +3 -2
  464. package/dist/lib/session/resume-command.js +4 -3
  465. package/dist/lib/session/resume-owner.d.ts +3 -3
  466. package/dist/lib/session/resume-owner.js +3 -3
  467. package/dist/lib/session/session-cache.d.ts +12 -0
  468. package/dist/lib/session/session-cache.js +2 -0
  469. package/dist/lib/session/share-html.d.ts +55 -0
  470. package/dist/lib/session/share-html.js +319 -0
  471. package/dist/lib/session/shell-programs.js +1 -1
  472. package/dist/lib/session/state.js +5 -5
  473. package/dist/lib/session/team-filter.d.ts +1 -1
  474. package/dist/lib/session/team-filter.js +1 -1
  475. package/dist/lib/session/types.d.ts +3 -3
  476. package/dist/lib/session/width.d.ts +2 -2
  477. package/dist/lib/session/width.js +2 -2
  478. package/dist/lib/settings-manifest.d.ts +2 -0
  479. package/dist/lib/settings-manifest.js +81 -3
  480. package/dist/lib/share/delete.d.ts +21 -0
  481. package/dist/lib/share/delete.js +42 -0
  482. package/dist/lib/share/publish.d.ts +120 -0
  483. package/dist/lib/share/publish.js +243 -18
  484. package/dist/lib/share/worker-template.js +172 -9
  485. package/dist/lib/shims.js +35 -7
  486. package/dist/lib/smart-launch.d.ts +4 -4
  487. package/dist/lib/smart-launch.js +6 -4
  488. package/dist/lib/snapshot.d.ts +4 -4
  489. package/dist/lib/snapshot.js +2 -2
  490. package/dist/lib/ssh-exec.d.ts +1 -1
  491. package/dist/lib/ssh-exec.js +2 -2
  492. package/dist/lib/ssh-tunnel.d.ts +10 -10
  493. package/dist/lib/ssh-tunnel.js +12 -12
  494. package/dist/lib/staleness/checkers/hooks.d.ts +1 -1
  495. package/dist/lib/staleness/checkers/hooks.js +1 -1
  496. package/dist/lib/staleness/detectors/permissions.js +0 -23
  497. package/dist/lib/staleness/detectors/plugins.js +1 -1
  498. package/dist/lib/staleness/fingerprint.js +1 -1
  499. package/dist/lib/staleness/layers.d.ts +1 -1
  500. package/dist/lib/staleness/layers.js +1 -1
  501. package/dist/lib/staleness/writers/mcp.js +3 -1
  502. package/dist/lib/staleness/writers/plugins.js +1 -1
  503. package/dist/lib/staleness/writers/types.d.ts +8 -0
  504. package/dist/lib/startup/command-registry.d.ts +6 -147
  505. package/dist/lib/startup/command-registry.js +40 -303
  506. package/dist/lib/startup/dev-build.d.ts +0 -21
  507. package/dist/lib/startup/dev-build.js +29 -8
  508. package/dist/lib/state.d.ts +19 -1
  509. package/dist/lib/state.js +120 -51
  510. package/dist/lib/subagents.js +1 -1
  511. package/dist/lib/sync-status.js +1 -1
  512. package/dist/lib/sync-umbrella.d.ts +6 -1
  513. package/dist/lib/sync-umbrella.js +9 -4
  514. package/dist/lib/teams/agents.js +2 -2
  515. package/dist/lib/teams/registry.js +1 -1
  516. package/dist/lib/terminal/backends/vscodium-agent.js +1 -1
  517. package/dist/lib/terminal/engine.js +1 -1
  518. package/dist/lib/terminal/index.d.ts +4 -0
  519. package/dist/lib/terminal/index.js +3 -0
  520. package/dist/lib/terminal/inject.d.ts +2 -2
  521. package/dist/lib/terminal/inject.js +2 -2
  522. package/dist/lib/terminal/transport.js +1 -1
  523. package/dist/lib/tmux/index.d.ts +1 -1
  524. package/dist/lib/tmux/index.js +1 -1
  525. package/dist/lib/tmux/session.d.ts +21 -5
  526. package/dist/lib/tmux/session.js +76 -22
  527. package/dist/lib/triggers/handlers.d.ts +38 -3
  528. package/dist/lib/triggers/handlers.js +58 -7
  529. package/dist/lib/triggers/webhook.d.ts +113 -5
  530. package/dist/lib/triggers/webhook.js +223 -44
  531. package/dist/lib/types.d.ts +19 -7
  532. package/dist/lib/usage-fleet.d.ts +1 -1
  533. package/dist/lib/usage-fleet.js +1 -1
  534. package/dist/lib/usage-refresh.d.ts +1 -1
  535. package/dist/lib/usage-refresh.js +3 -3
  536. package/dist/lib/version-duplicates.js +2 -2
  537. package/dist/lib/view-types.d.ts +56 -0
  538. package/dist/lib/view-types.js +1 -0
  539. package/dist/lib/watchdog/rotate.d.ts +2 -2
  540. package/dist/lib/watchdog/rotate.js +3 -3
  541. package/dist/lib/watchdog/runner.d.ts +2 -3
  542. package/dist/lib/watchdog/runner.js +3 -4
  543. package/dist/lib/workflows.js +1 -1
  544. package/dist/lib/wrap.d.ts +33 -0
  545. package/dist/lib/wrap.js +70 -0
  546. package/package.json +2 -1
  547. package/scripts/postinstall.js +2 -2
  548. package/dist/commands/bench.d.ts +0 -2
  549. package/dist/commands/bench.js +0 -101
  550. package/dist/commands/cp.d.ts +0 -84
  551. package/dist/commands/cp.js +0 -231
  552. package/dist/commands/login.d.ts +0 -2
  553. package/dist/lib/resources/commands.d.ts +0 -46
  554. package/dist/lib/resources/commands.js +0 -211
  555. package/dist/lib/resources/hooks.d.ts +0 -16
  556. package/dist/lib/resources/hooks.js +0 -153
  557. package/dist/lib/resources/mcp.d.ts +0 -34
  558. package/dist/lib/resources/mcp.js +0 -250
  559. package/dist/lib/resources/memory.d.ts +0 -15
  560. package/dist/lib/resources/memory.js +0 -46
  561. package/dist/lib/resources/permissions.d.ts +0 -13
  562. package/dist/lib/resources/permissions.js +0 -202
  563. package/dist/lib/resources/rules.d.ts +0 -46
  564. package/dist/lib/resources/rules.js +0 -179
  565. package/dist/lib/resources/skills.d.ts +0 -37
  566. package/dist/lib/resources/skills.js +0 -247
  567. package/dist/lib/resources/subagents.d.ts +0 -46
  568. package/dist/lib/resources/subagents.js +0 -202
  569. /package/dist/lib/{feed.d.ts → feed/feed.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,321 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.22.41
4
+
5
+ - **BREAKING: the top-level `agents timeline` command is removed — use `agents feed --filter updates` (RUSH-2692).** `timeline` was a pure alias of `agents feed --filter updates` (its own description said so), a second door to one stream against the CLI-surface convention of one owned noun with no duplicated surface. It is gone entirely, not deprecated: `agents timeline` now reports `unknown command`, and `timeline` is retired from distance-1 auto-correct so a stale invocation fails loudly instead of running a neighbouring command. `agents feed --filter updates` is unchanged, and the sibling observe aliases `agents inbox` and `agents roster` are unaffected. Source: `apps/cli/src/commands/feed.ts`, `apps/cli/src/lib/observe-aliases.ts`, `apps/cli/src/lib/startup/command-registry.ts`, `apps/cli/src/bootstrap.ts`.
6
+
7
+ - **Session preview leads with the title and wraps the last response to the pane (RUSH-2757).** `agents sessions preview` now opens its header with the session's title (`session.label` — an agent-generated name / `/rename` / the `--name` launch handle) instead of burying it, and the agent's last response is wrapped to the terminal width rather than running off the right edge as one long line. Wrapping measures visible width (ANSI-aware), so coloured output is not miscounted, and lines that already fit keep their rendered-markdown indentation. Source: `apps/cli/src/commands/sessions-picker.ts`, `apps/cli/src/lib/wrap.ts`.
8
+
9
+ - **`release-manifest.sh` helper digests are keyed by path relative to `--repo-root`, and `release-attestation-produce.sh` now writes the helper manifest it needs (RUSH-2766).** `hash_tree` used to bake the ABSOLUTE file path into every helper's `input-digest`, so a digest recorded in one worktree could never match the same recomputation elsewhere — `require_helpers` structurally could not pass for any release, and v1.22.40 was finished only by hand-recomputing the manifest inside a fixed-path worktree on `mac-mini` and re-uploading it to the GitHub release. Paths are now hashed relative to the repo root, so the same digest reproduces across machines and worktrees (demonstrated: identical `sha256:` for all three helpers computed from two independent checkouts). Separately, `release.sh` has always consumed `release-manifest.json` (`require` at :231, `upload_release_proof` at :976) with no producer writing it — the same consumer-without-producer gap RUSH-2749 fixed for the attestation itself. `release-attestation-produce.sh` now writes/updates it alongside `ATTEST.json`: an unchanged helper carries its prior record forward, `keychain`/`menubar` are re-recorded from the fresh signed assets this script's own Darwin block builds, and a drifted `computer-mac` digest with no prior record fails the producer closed rather than shipping a stale or missing helper record. Source: `apps/cli/scripts/release-manifest.sh`, `apps/cli/scripts/release-attestation-produce.sh`, `apps/cli/docs/release.md`.
10
+
11
+ - **BREAKING: `agents secrets` no longer prints bundle values — the plaintext export and bundle-key `get` are removed; run commands under `agents secrets exec` instead (RUSH-2774).** The `eval "$(agents secrets export <bundle> --plaintext)"` one-liner put every value of a bundle onto stdout, which inside a coding-agent session means the model's context and the synced session transcript — and agents copied it reflexively from the CLI's own help and scripts. `secrets export` is now transfer-only (`--device`, `--to-1password`, `--to-file`; anything else refuses, naming the alternatives); `secrets get <bundle> <KEY>` refuses, naming `agents secrets exec <bundle> -- printenv <KEY>`; `secrets view --reveal` refuses inside an agent session (`AGENTS_RUNTIME`/`AGENT_SESSION_ID`/`CLAUDECODE` markers) and its non-TTY `--reveal --plaintext` escape is gone; the raw-item `secrets get <item>` stays available everywhere — fleet shell hooks running inside sessions capture single ad-hoc tokens into their own variables, the accepted narrower residual. The SSH remote resolve behind `secrets exec --device` and `run --secrets <b>@<host>` still works: it rides a hidden, marker-gated transport (`AGENTS_SECRETS_REMOTE_TRANSPORT`), so a newer CLI keeps resolving from an older remote during a fleet rollout, while an older CLI against a newer remote fails loud with an upgrade hint. First-party scripts (`sandbox.sh`, both `release.sh`) now re-enter themselves under `agents secrets exec`, so values ride the child environment and never touch stdout. Migration for eval scripts: `agents secrets exec <bundle> -- <your command>`, or `VAR="$(agents secrets exec <bundle> -- printenv KEY)"` for a single value. Spec: SEC-9/SEC-9b/SEC-9c, SEC-GAP-10. Source: `apps/cli/src/commands/secrets.ts`, `apps/cli/src/lib/secrets/{headless,remote}.ts`, `apps/cli/scripts/{sandbox,release}.sh`, `apps/ext/scripts/release.sh`.
12
+
13
+ - **Fix a publish crash on any non-latin1 label, meta value, or repo name (RUSH-2784).** `fetch` encodes header values as a ByteString, so a title containing an ellipsis, a curly quote, an emoji, or CJK text threw `TypeError: Cannot convert argument to a ByteString` mid-publish — an unhandled stack trace after the body had already been read and the OG cover uploaded. Every free-text header (`x-share-label`, `x-share-repo`, `x-share-host`, `x-share-meta`, and the provenance set) now goes through `toHeaderValue()`, which transliterates common typographic punctuation to ASCII and drops the rest of the non-latin1 range. Still lossy for a title in a non-latin script, which publishes as `(unnamed)`; full Unicode needs percent-encoding plus a matching Worker decode, tracked as RUSH-2786. Source: `apps/cli/src/lib/share/publish.ts`.
14
+
15
+ - **`agents sessions share <id>` publishes a session as a link (RUSH-2784).** Sharing a session took three commands and a detour through the external artifacts-cli, so nobody ran it — every piece already existed (`sessions render` produces a redacted transcript, and the R2-backed share Worker has served artifacts for a month), but nothing wired them together. One verb now renders the session as a self-contained branded HTML page and publishes it: `agents sessions share a1b2c3d4` prints `https://share.agents-cli.sh/<you>/session-a1b2c3d4`. **Unlisted by default**, unlike `agents artifacts share` — a transcript carries file paths, command output, and error text, so it stays out of the public gallery until `--public` asks for it (the URL is still world-readable: unlisted is a capability URL, not a secret). The page is escaped rather than passed through, so a session that merely printed a `<script>` tag does not ship an executable one. Publishing inherits the existing email/credential scan and the 30d default expiry; `--reasoning fold` keeps the model's reasoning in collapsible sections, `--expire never` opts out of decay. Source: `apps/cli/src/commands/sessions-share.ts`, `apps/cli/src/lib/session/share-html.ts`, `apps/cli/src/lib/share/publish.ts`.
16
+
17
+ - **`agents browser use [name]` is the one command for choosing this machine's default browser profile (RUSH-2820).** A name writes the existing device-scoped `browser.profile` config key; a bare interactive invocation opens a picker over configured profiles and installed browsers, while a headless invocation prints the current default and usage. `--unset` and `auto` restore auto-detect. `agents browser profiles use` is an alias, and the hidden `profiles set-default` compatibility alias now points users to `browser use`. Source: `apps/cli/src/commands/browser.ts`.
18
+
19
+ - **Claude workspace trust now carries across pinned version homes (#2776).** Every pinned claude version gets an isolated home, and workspace trust (`projects[<path>].hasTrustDialogAccepted` in `.claude.json`) never carried into a new one — so the first interactive launch of each newly pinned version re-showed the workspace-trust dialog once per project, complete with the "this folder pre-approves N tool permissions" warning on repos trusted for months (headless runs skip the dialog, so the re-prompt could surface weeks after pinning and read as a trust regression). `agents add` / `agents use` now carry trust via a new `claude-trust` manifest strategy that projects ONLY the accepted trust flags out of the source `.claude.json` — the login (`oauthAccount`) and per-session stats stay per-version, same posture as the removed `.codex/auth.json` carry. A target entry's stamped-default `false` is promoted (Claude Code never persists a decline), all its other keys are preserved, the target is backed up before modification, and the write is atomic (a running Claude session rewrites this exact file). Codex was already covered: `projects.*.trust_level` rides along in `config.toml`. Source: `apps/cli/src/lib/settings-manifest.ts`.
20
+
21
+ - **Arc is a recognized browser type, and `agents browser` now refuses to drive it with a clear error instead of crashing it (#2779, #2778).** `arc` joins the Chromium-family `BrowserType` (detected at `/Applications/Arc.app`, macOS-only; `agents browser profiles seed` creates an `arc-local` profile). But Arc answers `Browser.getVersion` while exposing **zero** CDP page targets and **crashing** the moment a new tab is requested (`Target.createTarget`), so it is not actually drivable. Every tab-creating path now routes through one guard (`createPageTarget`) that throws an actionable "use Comet/Chrome/Chromium/Brave" error for an Arc profile rather than crashing the user's Arc window. The browser skill documents this and teaches showing a review doc/plan/report via `agents browser navigate --url file://<path>` (one reused tab, refreshed in place) instead of a raw `open <file>` that spawns a duplicate tab every call. Source: `apps/cli/src/lib/browser/service.ts`, `apps/cli/src/lib/browser/chrome.ts`, `apps/cli/src/lib/browser/cdp.ts`, `skills/browser/SKILL.md`.
22
+
23
+ - **Slack can now trigger an agent on your box and reply in-thread.** The signed webhook receiver (`agents webhooks serve` and the daemon `webhook-receiver`) accepts a third source, `POST /hooks/slack`: it verifies Slack's `v0` request signature with a 5-minute replay guard, answers the one-time `url_verification` handshake, and parses both slash commands (`/agents AGI: …`) and `app_mention` events. A matching `~/.agents/webhooks/*.yml` handler with `source: slack` (and optional `command`/`channel` filters) runs an agent scoped to the project named in the message — a handler may now template `project`/`cwd` from the delivery (`project: "{{slack.project}}"`), with the new `{{slack.*}}` namespace exposing `prompt`, `project`, `channel`, `thread_ts`, `user`, `text`, and `command`. The agent replies into the same thread through the existing `agents send --channel slack --to <channel> --thread <ts>` — no new outbound code. The receiver bundle gains `SLACK_SIGNING_SECRET` (and `SLACK_BOT_TOKEN` when the reply uses the Slack Web API). Setup, a ready-to-paste app manifest, and an example handler are in `docs/routines.md` and `docs/examples/slack/`. Source: `apps/cli/src/lib/triggers/webhook.ts`, `apps/cli/src/lib/triggers/handlers.ts`, `apps/cli/src/lib/daemon-webhooks.ts`, `apps/cli/src/commands/webhook.ts`.
24
+
25
+ ## 1.22.40
26
+
27
+ ---
28
+ type: feat
29
+ scope: devices
30
+ ---
31
+
32
+ **Device approvals and dismissals now follow the user DotAgents repo across the fleet
33
+ (RUSH-2377).** `agents devices register`, `add`, `sync`, `ignore`, `unignore`, and
34
+ `remove` persist a three-state decision under the central `agents.yaml`
35
+ `fleet.discovery` map: `approved`, `ignored`, or absent/pending. After
36
+ `agents repo pull user`, the CLI reconciles those portable decisions into the local
37
+ `.history/devices` registry and ignore-list, resolving approved connection details
38
+ live from Tailscale. IPs, SSH users/auth, and reachability remain machine-local and
39
+ never enter Git. Source: `apps/cli/src/lib/devices/discovery-policy.ts`,
40
+ `apps/cli/src/commands/{ssh,repo}.ts`.
41
+
42
+ - **Legacy tmux `pane-died` hooks now self-heal at attach and daemon startup instead of relying on a poll that no longer exists (RUSH-2435).** The 5-minute `tmux-reconcile` daemon routine that used to retrofit a stale hook onto a managed tmux session was deleted in an earlier pass (RUSH-2495), leaving `reconcileSessionHooks` with zero production callers — a session a pre-fix binary left with a stale hook had nothing to repair it. `reconcileSessionHooks` (full sweep) now runs once at daemon startup and once from the upgrade-time migration (`runMigration`) as the version-skew one-shot, and the new `ensureSessionHookRepaired(name, socket)` repairs a single session right before it's attached to — wired into `prepareSessionForResume` (native `agents run --resume`) and the manual `agents focus`/`agents go`/`agents tmux attach` attach paths. Both share one non-destructive `repairSessionHookIfStale` implementation so the full sweep and the single-session repair can never drift on what counts as repaired. `docs/routines.md` and `docs/specifications.md` no longer describe the deleted `builtin-routines.ts`/`tmux-reconcile` machinery as live. Source: `apps/cli/src/lib/tmux/session.ts`, `apps/cli/src/lib/tmux/index.ts`, `apps/cli/src/lib/daemon.ts`, `apps/cli/src/lib/migrate.ts`, `apps/cli/src/commands/focus.ts`, `apps/cli/src/commands/go.ts`, `apps/cli/src/commands/tmux.ts`.
43
+
44
+ - **`agents sessions resume <id>` / `focus <id>` for a local indexed session no longer runs the write-heavy discovery scan or dials the fleet, so a crash-restart storm of resumes stops crashing on `database is locked` (RUSH-2477).** After a machine crashes and reboots, every previously-open tab relaunched `sessions resume <id>` at once. Each resume ran the full `discoverSessions` path, whose `tryClaimScan`/`releaseScan` bookkeeping are `BEGIN IMMEDIATE` writer transactions (`lib/sqlite.ts`), so even a process that *skipped* the scan still took the writer lock — dozens at once exhausted `busy_timeout` and threw an unhandled `SQLITE_BUSY` ("database is locked"), and on a local miss the resume fanned out over SSH to the whole fleet before the tailnet was up, hanging and printing the doubled `unreachable … skipped` list. The direct-id path now resolves against the local SQLite index first through a new `resolveIndexedSessionById` (`lib/session/discover.ts`) — a plain WAL read (`skipExistenceCheck`) with the same origin-machine attribution and managed scoping every indexed read gets, no scan claim and no fleet fan-out. `focusAction` (`commands/focus.ts`) takes that fast path for a local indexed id: on a single logical match owned by this box it routes straight to recovery (joining a still-live pane via the local live index, or resuming a crashed one in place); a genuine miss, an ambiguous prefix, or a peer-owned row falls through to the existing fleet resolver unchanged. `dedupeSessionsByLogicalId` collapses the self-vs-attribution split of one id, so a full uuid that used to read as "ambiguous (2 sessions)" now resolves to one. Verified: >= 20 concurrent `resolveIndexedSessionById` calls complete with zero `SQLITE_BUSY`, and the resolve issues no SSH fan-out. Source: `apps/cli/src/lib/session/discover.ts`, `apps/cli/src/commands/focus.ts`.
45
+
46
+ - **`agents monitors` now correctly reports a failed action dispatch — `ok:false` and the specific reason — when the runner declines to start or fails to start the agent process (RUSH-2500).** Previously, `dispatchAction` in `lib/monitors/dispatch.ts` treated any non-throwing return from `executeJobDetached` as success (`ok: true`). But `executeJobDetached` calls `runWithAttempt`, which can return a `RunMeta` with `status: 'skipped'`, `'blocked'`, or `'failed'` without throwing — e.g. when the non-overlap `active_run` guard fires because a prior monitor-triggered run is still live, or when the auth preflight fast-path (dead-verdict credit exhaustion) marks the run `failed` and returns instead of throwing. The skipped or failed run was recorded in `~/.history/runs/` with the real status, but the fire record in `~/.history/monitors/` got `ok: true`, so `monitors runs` showed success while `monitors logs` showed `skipped`. The engine's drought escalation also got a false healthy signal and never notified the owner. The fix checks `runMeta.status` after `executeJobDetached` and returns `{ ok: false, error: runMeta.errorMessage ?? runMeta.status }` for `skipped`, `blocked`, or `failed` results, making the fire record agree with the runner record. Applies to both `run` and `routine` action types. Source: `apps/cli/src/lib/monitors/dispatch.ts`.
47
+
48
+ - **`agents sessions --active` now distinguishes "genuinely nothing running" from "discovery failed and was silently swallowed" (RUSH-2507).** Previously `getActiveSessions` folded every tmux/teams/terminals source failure into a bare `[]` — a wedged tmux server, a spawn error, or a nonzero `list-panes` exit read identically to an idle machine, and the same collapse happened on the fleet fan-out side, where an unreachable/skipped peer or a failed device-list load produced the exact same "No active agent sessions." as a genuinely idle fleet. `listTmuxAgentSessions` now throws `TmuxDiscoveryDegradedError` when the tmux socket exists but couldn't be read (still returning `[]` when no socket has ever existed — that case is legitimately empty), and the new `describeActiveDiscoveryHealth()` re-probes it only on an empty result to report which local source degraded. `RemoteActiveResult` now carries `skipped`/`discoveryFailed` from `gatherRemoteAgentsJson` instead of dropping them. The empty-result message in `agents sessions --active` names the degraded source or unheard peer instead of a flat "No active agent sessions.". Source: `apps/cli/src/lib/session/active.ts`, `apps/cli/src/lib/session/remote-active.ts`, `apps/cli/src/lib/session/session-cache.ts`, `apps/cli/src/commands/sessions.ts`.
49
+
50
+ ---
51
+ type: feat
52
+ scope: projects
53
+ ---
54
+
55
+ `agents projects pull <name>` fast-forwards every fleet checkout of a named project to
56
+ its remote's default branch.
57
+
58
+ - **Safety contract:** dirty trees, checkouts on a non-default branch, and local commits
59
+ ahead of upstream are blocked and reported — never overwritten. Fast-forward only; no
60
+ rebase, no reset.
61
+ - **Every checkout is verified against the project's declared repo slug before it is
62
+ fast-forwarded, on every fleet device** — a bound path that hosts a different repo is
63
+ blocked. A checkout whose `origin` cannot be resolved to a slug is blocked too.
64
+ - **Missing checkouts are skipped** (never cloned) and do not drive a non-zero exit.
65
+ Blocked or failed checkouts do.
66
+ - **Fleet fan-out** reuses the same `gatherRemoteAgentsJson` seam as `projects status`,
67
+ with a 120-second per-device timeout for large repos and slow links.
68
+ - `--device` / `--devices` scope the pull to one or more named fleet boxes.
69
+ - `--json` emits a machine-readable result array (one row per path per device), and
70
+ reports devices that did not answer (`unavailable`) or answered unverifiably
71
+ (`unverified`) on stderr — matching `projects status --json`.
72
+ - **A device whose answer cannot be verified is reported as `unverified` and drives a
73
+ non-zero exit**, rather than being silently folded in as a device with nothing to
74
+ report.
75
+ - `agents projects pull-local` (hidden peer command) is the per-device fast-forward
76
+ runner invoked by the fleet fan-out. It receives the full `{path, expectedSlug}` target
77
+ list, so slug verification runs on remote devices exactly as it does locally, and a
78
+ malformed or spoofed peer response is rejected loudly rather than partially applied.
79
+
80
+ - **`routines.test.ts`: daemon spawned by `startIsolatedDaemon` no longer inherits the real production `AGENTS_HISTORY_DIR` (RUSH-2545).** The test helper spread `...process.env` into the daemon's environment without overriding `AGENTS_HISTORY_DIR`, so the detached daemon process read its `~/.agents/.history` record — the live production history — and its SIGTERM sweep killed real tmux-wrapped Claude and cgraph-mcp processes on every five-minute tick while the test suite ran. The fix adds `AGENTS_HISTORY_DIR: path.join(home, '.agents', '.history')` to the daemon spawn env so the sweep is fully confined to the test's tmp directory. A new regression test (`daemon env isolation — AGENTS_HISTORY_DIR must not leak`) reads `/proc/<pid>/environ` on Linux to assert the daemon's env carries the isolated path, not the parent vitest process's real one. Source: `apps/cli/src/commands/routines.test.ts`.
81
+
82
+ - **The daemon hosts signed webhook receivers as a supervised service (RUSH-2548).**
83
+ Public Linear/GitHub → agent webhooks no longer depend on a `nohup`'d
84
+ `agents webhooks serve` tied to an agent session: declare a receiver with
85
+ `agents daemon webhooks add --secrets-bundle <name> [--port n] [--funnel-port 443]`
86
+ and the daemon's new `webhook-receiver` service binds it, restarts it on crash,
87
+ and brings it back after a reboot. `agents daemon webhooks list [--json]` and
88
+ `agents daemon webhooks remove <port>` manage the declarations. The signing
89
+ secret resolves headlessly through the secrets broker, so there is no
90
+ `AGENTS_SECRETS_PASSPHRASE`; a locked bundle fails that receiver loud in
91
+ `agents daemon logs` instead of binding ingress it cannot verify. Source:
92
+ `apps/cli/src/lib/daemon-webhooks.ts`, `apps/cli/src/commands/daemon.ts`.
93
+ - **Webhook deliveries are acked before dispatch, not after (RUSH-2548).** The
94
+ receiver held the HTTP response open for the whole 15-20s agent run, which
95
+ exceeded Linear's delivery timeout and filled its Delivery failures log with
96
+ timeouts and retries. A verified delivery is now answered
97
+ `202 {"ok":true,"accepted":true,"deliveryId":…}` immediately and dispatched
98
+ afterwards. Delivery-id dedup is unchanged, including for a retry that lands
99
+ mid-dispatch; the response body no longer carries `fired`/`runs`/`handlers`,
100
+ and a post-ack failure surfaces as the new `webhook.failed` event plus a line
101
+ in the receiver's log. Source: `apps/cli/src/lib/triggers/webhook.ts`.
102
+
103
+ - **Add named routers -- `agents route` (RUSH-2556, RUSH-2562, RUSH-2563, RUSH-2564).** A router is a reusable, task-typed allowlist of harnesses x models/tiers x linked accounts -- a generalization of a profile (a profile is a router pinned to one harness and one account). `routers` is a new `ResourceKind`, resolved project > user > system like other resources; `agents route create/list/show/allow/link-account/unlink-account/rm` manage it. Harness ids and model/tier tokens are validated on `create`/`allow` against the real agent registry and each harness's resolved tier map/catalog -- an unknown token fails loud, printing the invalid token, and writes nothing. Source: `apps/cli/src/lib/routers.ts`, `apps/cli/src/commands/route.ts`.
104
+
105
+ - **The browser tab reaper now actually runs, and you can trigger it on demand (RUSH-2622).** `agents browser done`/`stop` always closed a task's tabs, but agents routinely never called them, so leftover tabs piled up in the shared profile window. The daemon now closes them itself, on a 5-minute tick: a task whose owning agent session has exited, or one idle past `browser.task-idle-minutes` (default 30, new device config key — `0` disables idle reaping only, a dead-session task is still closed). `agents browser gc [--dry-run] [--idle-minutes <n>]` runs the same pass on demand. Only tabs the daemon opened for that task are ever touched — a tab you opened yourself, or the shared profile window, is never closed. Source: `apps/cli/src/lib/browser/hygiene.ts`, `apps/cli/src/lib/daemon.ts` (`runBrowserTaskReap`), `apps/cli/src/lib/device-config.ts` (`browser.task-idle-minutes`), `apps/cli/src/commands/browser.ts` (`gc`).
106
+
107
+ - **The macOS menu-bar helper now recovers an alive-but-frozen daemon after sleep/wake (RUSH-2636).** Its separate launchd process reads the daemon heartbeat as well as the PID; after a confirmed stale heartbeat it runs one scoped `agents daemon restart` and reports the recovery. Missing, malformed, or PID-mismatched heartbeat state fails closed. Source: `apps/cli/menubar/Sources/MenubarHelper/DaemonLiveness.swift`, `apps/cli/menubar/Sources/MenubarHelper/StatusItemController.swift`.
108
+
109
+ - **`daemon.ts`: the launchd Label / systemd unit name is namespaced under a redirected HOME (RUSH-2639, residual).** An earlier RUSH-2639 fix baked the caller's HOME into the daemon's plist/unit *content* so a service-manager-started daemon lands in the right sandbox — but `launchctl unload`/`load`/`list` route by the service **identifier** alone, and that identifier (`com.phnx-labs.agents-daemon` / `agents-daemon.service`) was still one literal, global string. Confirmed directly against real `launchctl`: when a different plist is already loaded under that label, a new instance's own `unload` (written to be a no-op for a plist that was never loaded) silently kills the *other* job instead — exactly what let concurrent hermetic test forks (and a developer's own test suite next to their real always-on daemon) collide. The identifier is now namespaced with a hash of HOME whenever HOME differs from `os.userInfo().homedir` (the OS/passwd record, which ignores `$HOME`) — every hermetic test process, never a real interactive/production invocation. Source: `apps/cli/src/lib/daemon.ts`.
110
+
111
+ - **Fixed the macOS test regression introduced by the vitest HOME sandbox, which blocked release 1.22.40.** RUSH-2639 sandboxed `$HOME` for the whole suite so tests can no longer write into the developer's real `~/.agents`. macOS resolves the login keychain *from* `$HOME`, so `usage.test.ts`'s `setKeychainToken` call had no keychain to write and died with `security: SecKeychainItemCreateFromContent (<default>): The authorization was canceled`. It surfaced only in the release matrix — PR CI runs Linux, which has no keychain — so it halted a release after the changelog was folded and the PR opened, rather than failing on the PR that introduced it. The test now installs an in-memory backend via the existing `setKeychainBackendForTest` seam, which is strictly better than what it did before: writing a token into the real login keychain was the same class of bug RUSH-2639 exists to prevent. Source: `apps/cli/src/lib/__tests__/usage.test.ts`.
112
+
113
+ ---
114
+ type: fix
115
+ scope: services
116
+ ---
117
+
118
+ **The menu-bar helper's and the `agents computer` helper's launchd plists now carry HOME, closing the last RUSH-2639 escape.** The earlier RUSH-2639 fixes covered exactly one of the three service manifests this CLI writes: the daemon's. `generateServicePlist` (menu bar) declared only `PATH`/`AGENTS_NODE`/`AGENTS_ENTRY`/`AGENTS_BIN`, and `renderLaunchAgentPlist` (computer helper) had no `EnvironmentVariables` dict at all. launchd applies that dict on top of the **login session's** environment, never the environment of whoever called `launchctl bootstrap`, so both helpers resolved the account home whatever home their caller was running under. The menu-bar helper reaches the CLI through its baked `AGENTS_NODE`/`AGENTS_ENTRY`, and every `agents` invocation runs the audit hook → `readMeta` → `ensureAgentsDir`, so each call bootstrapped that home's `~/.agents` (`.system`, `.history`, `.cache`, `routines`). Under the hermetic test harness that is a write into the developer's or the CI runner's REAL home — the macOS-only leak that failed the 1.22.40 release matrix. Captured live on a CI runner: pid `10817`, parent `1` (launchd), executable `<sandbox>/Library/Application Support/agents-cli/MenubarHelper.app/Contents/MacOS/MenubarHelper`, registered under the bare label `com.phnx-labs.agents-menubar` while the real `~/Library/LaunchAgents` held no phnx plist. Both manifests now bake `HOME` + `AGENTS_REAL_HOME`, and both identifiers get the HOME-namespacing the daemon's already had, so a sandboxed instance can no longer bootout the operator's live helper. The rule lives in one module, `apps/cli/src/lib/service-manifest.ts`, with a per-generator test so a fourth manifest cannot ship without it. Production identifiers and behavior are unchanged: the namespace suffix is empty whenever HOME matches the passwd home. Source: `apps/cli/src/lib/service-manifest.ts`, `apps/cli/src/lib/menubar/install-menubar.ts`, `apps/cli/src/commands/computer.ts`, `apps/cli/src/lib/daemon.ts`.
119
+
120
+ - **fix: the vitest suite can no longer write into the developer's real `~/.agents` (RUSH-2639).** `tests/setup.ts` pinned only specific hot spots (`AGENTS_DEVICES_DIR`, `AGENTS_EVENTS_PATH`, hook-shim/cache/logs/perf/state dirs) to fork-private temp dirs, leaving `HOME` itself untouched — and `state.ts`'s `HOME` (and several sibling modules') is a module-level constant captured once at import time, so any test or subprocess spawn that didn't happen to override `HOME` before its first import resolved against the real home. Two confirmed live offenders: `src/lib/routines.test.ts` wrote fixture routine YAML into the real `~/.agents/routines/` and `~/.agents/.system/routines/`, and a `src/lib/daemon.test.ts` describe block registered/reaped real daemon-instance pid markers under `~/.agents/.cache/helpers/daemon/instances/`. `tests/setup.ts` now redirects `HOME`/`USERPROFILE` to a fork-private sandbox before any test file's imports run, so every HOME-derived path — including ones with no dedicated escape hatch, and subprocesses spawned with `env: {...process.env}` — resolves under the sandbox with no per-test effort; new CI-only leak tripwires assert the real `~/.agents` top level and `~/.claude/settings.json` are untouched. A new `tests/global-setup.ts` also sweeps stale `/tmp/agents-vitest-*` dirs left behind by killed workers from past runs. Source: `apps/cli/tests/setup.ts`, `apps/cli/tests/global-setup.ts`, `apps/cli/vitest.config.ts`.
121
+
122
+ - **Routines: a terminal run no longer wedges the scheduler's active-run slot (RUSH-2640).** A run that reached any terminal state (failed / timeout / completed) used to keep holding the slot while its recorded pid stayed alive, so every later scheduled fire was refused with `already has an active run` while the routine sat silently dead. The slot is now released the moment a run reaches a terminal state; a still-`running` record is also aged out once it passes its own timeout, and the daemon no longer stamps its own never-dying pid on a run's provisional claim (which was what made the slot look permanently occupied and drew the process reaper at the daemon itself). A routine whose run failed now fires again on its next slot with no daemon restart. Three or more consecutive slot-skips for the same routine are surfaced in the daemon log instead of accumulating silently. Source: `apps/cli/src/lib/runner.ts`.
123
+
124
+ ---
125
+ type: fix
126
+ scope: menubar, extension
127
+ ---
128
+
129
+ Resolve the standalone Linear CLI from executable GUI-safe paths before ticket creation, and show the underlying launch error when creation fails.
130
+
131
+ - **Branding: rebrand the OSS product name from agents-cli to agi-cli in user-facing prose, docs, and repo-path URLs, now that the GitHub repo itself has been renamed `phnx-labs/agi-cli` (RUSH-2660).** Root `README.md`, `CONTRIBUTING.md`, `DESIGN.md`, `SECURITY.md`, `NPM_CONSOLIDATION.md`, `apps/ext/README.md`, `assets/videos/README.md`, `demo/src/scenes.ts`, `packages/agi-cli/README.md`, `packages/swarmify-mirror/README.md`, and the `apps/cli/docs/` markdown headers **and body prose** that use "agents-cli" as the product name now read "agi-cli". Every `github.com/phnx-labs/agents-cli` reference in those user-facing files, plus the `repository`/`bugs`/`homepage` URL fields in `packages/agi-cli/package.json` and `packages/swarmify-mirror/package.json` and the hardcoded repo defaults in `apps/cli/scripts/release.sh`, root `scripts/release.sh`, `scripts/bottle.sh`, `.github/ISSUE_TEMPLATE/config.yml`, and `scripts/release.test.sh` (plus the companion `apps/ext/app/package.json` `repository.url` its test asserts against), now point at `phnx-labs/agi-cli`. This is docs/branding only — no runtime behavior change. Not touched: the npm package `name` fields (`@phnx-labs/agents-cli` stays canonical; the package-name flip is a separate ticket), the `npm install -g @phnx-labs/agents-cli` line in `apps/cli/scripts/install.sh`, the `agents-cli` shell-rc marker in `src/lib/shims.ts`, `~/.agents`/`~/.agents-system`, the `agents`/`ag` command names, the VS Code ext identity (`swarmify`/`swarm-ext`), keychain-item naming patterns (`agents-cli.<provider>.token`, `agents-cli.hmackey`, etc.), literal runtime message strings quoted in docs (e.g. `doctor.ts`'s `"older agents-cli — can't report per-version sign-in"`), and repo-path/project-name examples in code blocks. Source: `README.md`, `apps/cli/docs/*.md`, `packages/agi-cli/package.json`, `packages/swarmify-mirror/package.json`, `apps/cli/scripts/release.sh`, `scripts/release.sh`, `scripts/bottle.sh`, `.github/ISSUE_TEMPLATE/config.yml`, `scripts/release.test.sh`.
132
+
133
+ - **Affected-test Linux CI gate (RUSH-2666).** The required `Tests / test` check is one GitHub-hosted Linux job: `scripts/ci-scope.ts` plus `apps/cli/ci/test-ownership.yaml` select the companion, statically related, and declared-owner tests, fail immediately on an unmapped path, and reuse a proof only for the exact candidate tree. Windows is post-merge best-effort and does not block merge or release. Source: `scripts/ci-scope.ts`, `.github/workflows/tests.yml`.
134
+
135
+ - **Ordinary `release.sh` promotes the exact pretested tarball instead of rebuilding and notarizing (RUSH-2666).** Functional proof is an immutable attestation bound to the candidate tree, toolchain, lockfile digest, and test-policy version — parent commits and nearby SHAs are rejected, and a missing record fails with that exact key. Helpers are reused from the release manifest or the release stops; sign/notarize is outside this path. The home base install-smokes the attested `.tgz` and publishes those bytes (`npm publish <tgz>`, OIDC provenance when GitHub's token exchange is present). Target: ordinary release P99 ≤180 seconds. Source: `apps/cli/scripts/release.sh`, `apps/cli/scripts/release-attestation.sh`, `apps/cli/scripts/release-manifest.sh`, `apps/cli/scripts/release-install-smoke.sh`.
136
+
137
+ - **`agents permissions list` now answers for every harness whose permissions the CLI writes, not 3 of them (RUSH-2676).** `applyPermissionsToVersion` writes claude, opencode, codex, cursor, antigravity, grok, kimi, droid, copilot, kiro, openclaw and hermes, but the read side was a hand-written 3-arm switch: `readAgentPermissions` returned `null` for everything except claude/opencode/codex, and the config-file import behind `agents permissions add <path>` gated on a `.claude`/`.opencode`/`.codex` substring, which also excluded kiro/goose/hermes twice over because their configs are YAML. So permissions were installed and then reported as absent — measured against the real write path, 13 written, 3 reported back. A new `PERMISSION_TARGETS` registry (`apps/cli/src/lib/permissions-registry.ts`) declares each harness's config path plus how to read it back into the canonical `PermissionSet`, mirroring `SUBAGENT_TARGETS`; a completeness test pins the key set to `capableAgents('allowlist')`, so a newly added allowlist harness cannot be written-but-unreadable. Path detection now matches each harness's own declared filename, longest suffix winning, so `.kiro/settings/permissions.yaml` is never claimed by a shorter match. The registry also owns the canonical↔native tool vocabularies (`GROK_TOOL_BY_CANONICAL`, `KIRO_CAPABILITY_BY_TOOL`, and the rest), which `permissions.ts` imports for the forward serializers, so the two directions cannot drift into disagreeing about what `fs_read` means. Every reverse projection is lossy in a way the harness's format forces — Kiro collapses `Read`/`Grep`/`Glob` onto `fs_read`, Kimi expands one Bash arg-glob into two picomatch patterns, Codex has no rule list at all — and each target names its own loss rather than pretending the round trip is exact. `agents permissions list` renders the canonical allow/deny for the harnesses that had no renderer; claude, opencode and codex keep their native renderings.
138
+
139
+ - **BREAKING: Goose no longer supports permissions.** `goose` reads `allowlist: false` in the capability table, and its converter, writer, detector and config path are gone. Goose's `permission.yaml` gates whole tools (`developer__shell`, `developer__text_editor`), so several distinct canonical rules collapse onto one entry and cannot be read back faithfully — a half-supported capability that reported success while losing information. `agents sync goose` no longer writes `.config/goose/permission.yaml`, and `applyPermissionsToVersion('goose', …)` now refuses with `Agent 'goose' does not support permissions` rather than silently writing a lossy approximation. An existing `permission.yaml` on disk is left untouched; nothing removes it. Goose keeps hooks, MCP, skills, commands, plugins, subagents and workflows.
140
+
141
+ - **MCP sync no longer writes nothing and calls it success (RUSH-2677).** `capabilities.mcp` is `true` for every harness, but the code behind it was four independent `switch (agentId)` chains with four different membership sets — a config-path resolver, a config writer, an installer, and a parser. A harness present in one and absent from another resolved a real path and then fell straight through the writer: no file, no error, and `agents sync <that harness>` printed `Already in sync`. Antigravity was the visible case, and pi, muse and warp had writers the installer never called. They are now one table, `MCP_TARGETS` (`apps/cli/src/lib/mcp-registry.ts`), pinned to `capableAgents('mcp')` by a completeness test — so a newly added harness must declare a format, or declare with a stated reason that its format is not implemented. **A refusal now reaches the user**: `installMcpServers` reports it, the staleness writer forwards it instead of discarding it, and `agents sync` prints a `Not written to <agent>@<version>:` block naming the harness and the reason (copilot, amp, kiro and goose are the four with no schema verified against an installed CLI). Three path bugs fell out of the consolidation, each verified against the harness itself: **antigravity** MCP goes to `~/.gemini/config/mcp_config.json` in the user's REAL home — only `~/.gemini/antigravity-cli` is symlinked into a version home, so a version-home path lands where agy never reads — and its remote transport is keyed `serverUrl`, not `url`; **grok** MCP is `[mcp_servers.<name>]` in `~/.grok/config.toml`, so the resolver no longer answers `.grok/mcp.json` and the parser no longer reads that TOML as JSON; **kimi** is read back from the `.kimi-code/mcp.json` the installer writes rather than `.kimi-code/settings.json`, so a synced server stops reporting as missing. Claude's user-scope MCP path is `~/.claude.json`, where Claude reads `mcpServers`. A malformed existing config is now **refused rather than rewritten from scratch** — these files hold far more than MCP (hermes' whole `config.yaml`, openclaw's `openclaw.json`), and the previous parse-or-reset would have destroyed the rest of them. Source: `apps/cli/src/lib/mcp-registry.ts`, `apps/cli/src/lib/mcp.ts`, `apps/cli/src/lib/agents.ts`, `apps/cli/src/lib/staleness/writers/mcp.ts`, `apps/cli/src/commands/sync.ts`.
142
+
143
+ - **A monitor's `--run` action actually runs now — every one of them was silently skipped, fleet-wide (RUSH-2681).** Detection worked (the poll ran, the regex matched, the fire was recorded), but the action never executed: `agents monitors logs <name>` showed the run as `skipped` with no output. A monitor synthesizes a one-off `JobConfig` named after itself and hands it to the routines dispatch seam (`executeJobDetached`), which gates it on `checkJobDeviceEligibility` → `jobRunsOnThisDevice`. That function consulted the per-device ROUTINES activation manifest first and short-circuited on its answer — and a monitor's name can never be in that manifest, because nothing under `monitors/` ever writes one. Every fire therefore recorded `skipReason: "wrong_owner"` with the empty-allowlist message `Job '<name>' can only run on: `. Measured on one box at 1.22.39: 5 of 5 fires skipped, zero successful action runs ever. The synthesized job now carries an explicit `dispatchedBy: 'monitor'` marker and `jobRunsOnThisDevice` skips the routine activation manifest for it — a monitor already resolves exactly-once ownership through its own `device:` pin (`monitorRunsOnThisDevice`) before dispatching, so re-gating on the routines manifest was double-gating on the wrong key. The exemption is deliberately narrow: a monitor's `routine` action fires a real routine, which keeps its activation gate, so a routine that is defined but not activated on this device is still refused with `wrong_owner`. Monitor names are NOT registered into the device routines manifest — that would conflate two ownership models and pollute `agents routines`.
144
+
145
+ A second gate sat directly behind it and would have kept every `run` action inert on its own: with the manifest no longer swallowing the job first, the run was `blocked` with `execution_context_missing`, because `resolveJobExecutionContext` refuses an agent job carrying neither `project` nor `cwd` (`lib/routine-context.ts`) and `MonitorConfig` had no field able to supply one. Monitors now take an optional `cwd` (`agents monitors add … --cwd <path>`, home-relative or `~/…`) and the synthesized job defaults it to the execution target's home, which stays portable across a `runOn:` SSH hop. Verified end to end on one box: the same monitor fires `skipped` / `skipReason: "wrong_owner"` / no output on installed 1.22.39, and `completed` with its agent's captured output on the fixed build. Source: `apps/cli/src/lib/monitors/dispatch.ts`, `apps/cli/src/lib/monitors/config.ts`, `apps/cli/src/commands/monitors.ts`, `apps/cli/src/lib/routines.ts`.
146
+
147
+ `dispatchedBy` is runtime-only and closed at both ends of the schema boundary: `writeJob` strips it and `readJobFileResult` refuses a routine definition that carries it (inert-and-loud, like the existing `device:`/`devices:` guards), so a hand-authored YAML cannot use the marker to fire a routine on every box regardless of activation — the daemon's load path never calls `validateJob`.
148
+
149
+ - **`agents sessions preview <id>` (and the id behind `resume`/`focus`) no longer says "No session matching" for a session that is actually running (RUSH-2682).** Transcript indexing was lazy — only `discoverSessions` wrote the index and nothing scheduled it — so a session THIS box just started was listed as running by `agents sessions --active` while `agents sessions preview <id>` answered "No session matching" until an unrelated `agents sessions*` call happened to scan. Measured on zion (agents-cli 1.22.39): a locally-started session took 7.6 minutes to enter the index, while peer sessions arriving via sync landed in ~0s — a box indexed other machines faster than itself. Three fixes: (1) the id resolver now unions the indexed rows with the live-session registry (the same source `--active` reads) on a cold id miss, so a running session resolves and renders even with no transcript row yet — locally and, because the fan-out peer answers from the same union, cross-device; (2) the daemon incrementally scans this host's transcript dirs into the local index every 20s, so a locally-started session is discoverable within seconds instead of on the next unrelated invocation; (3) the cold-miss repair now waits (bounded) for a concurrent scan to finish instead of returning the pre-scan snapshot as if it were the answer. Source: `apps/cli/src/lib/session/live-metadata.ts`, `apps/cli/src/commands/sessions.ts` (`computeLocalMetadataMatches`, `liveMetadataMatches`), `apps/cli/src/lib/session/discover.ts` (`waitForScanToSettle`), `apps/cli/src/lib/session/db.ts` (`scanInProgressByLivePid`), `apps/cli/src/lib/daemon-ticks.ts` (`runSessionIndexWarmTick`), `apps/cli/src/lib/daemon.ts`.
150
+
151
+ - **`agents artifacts share` now carries provenance and a title, and `agents artifacts share list` is a real "what have I shared" gallery, not just slugs (RUSH-2683).** Every publish auto-captures `agent` (`AGENTS_AGENT_NAME`), `session` (`AGENTS_SESSION_ID`/`AGENT_SESSION_ID`), `host` (`os.hostname()`), `repo` (the current git repo), and `date` from the exec env/git/clock — never invented, sent only when the environment genuinely carries it. `--label <text>` (alias `--title`) sets a human display title shown in the gallery and `share list`; omit it and one is derived from the HTML `<title>`, a Markdown frontmatter `title:`, or the filename, with a one-line nudge toward `--label` in the human output — never a blocking prompt. `--meta key=value` (repeatable) attaches structured metadata (recommended keys: `kind`, `project`, `ticket`, `status`); reserved keys (`agent`/`session`/`host`/`repo`/`date`/`label`/`label-source`) are rejected client-side and enforced again in the Worker. `agents artifacts share list` gains `--agent`/`--session`/`--label-contains` filters (named to avoid a real, pre-existing option-name collision with the parent `share` command — see below) and returns `label`/`agent`/`session`/`host`/`repo`/`revisionCount`/`meta` per item (every `--meta key=value` an agent attached is readable again, in both `--json` and the human table — not write-only); the JSON shape is an additive superset of the prior one. Reserved provenance/label keys are now stripped from stored `--meta` **unconditionally** in the Worker (not just overwritten when the matching provenance header happens to be present), so a same-named `--meta` entry can't smuggle through on a publish that carries no agent/session/host/repo/date at all. The pre-publish email/credential scan now also covers `--label` and every `--meta` value (previously body-only), since both land in the same public `customMetadata` as the page itself — gated by the same `--force`. An explicit `--label`/derived title with an embedded newline is sanitized to a single line before use, instead of crashing the publish on an invalid header value. Republishing an existing slug now keeps the prior version — R2 has no native object versioning, so the Worker copies the current object to `<slug>/rev-<ts>-<rand>` before overwriting the canonical key (default keep-all; `--no-revision` skips it). The new `agents artifacts share revisions <target>` command lists a slug's retained history, newest first, via `--for-user`/`--revisions-json` (see below for why not `--github-user`/`--json`); revisions never appear on the public gallery or in `share list` beyond a `revisionCount`, and each keeps its own recorded expiry. The Worker template changed (customMetadata capture, revision-on-overwrite, the `?revisions=json` route, gallery/listing display) — existing endpoints need `agents artifacts share update` to adopt it (`agents artifacts share status` reports when one is due). Verified against the live production `share.agents-cli.sh` endpoint: publish, list with filters, and revisions all round-trip real provenance. **Also discovered, and fixed where introduced here: commander resolves a long option name against the whole ancestor chain, not per-command, so a subcommand option sharing a name with the parent `share` command's own option is silently dropped even when passed alone** (verified with an isolated commander repro). This is pre-existing on `share list`/`update`/`delete` (predates this change) and out of scope to fix CLI-wide here — a real generalized fix needs `enablePositionalOptions()` audited across 552 commands, tracked as RUSH-2687; `list`'s new filters were named to sidestep it too (`--label-contains` instead of `--label`), though its own `--json`/`--github-user` remain affected. `share revisions` is new in this change, so it was given non-colliding names from the start instead of shipping a fourth broken instance: `--for-user` (not `--github-user`) and `--revisions-json` (not `--json`). `agents artifacts share delete` / `agents unshare` now also delete a target's retained revisions by default (`--keep-revisions` to leave them) — a republished-then-deleted share previously left its prior world-readable version(s) live until the bucket's 366-day lifecycle sweep; fetching the revisions list to purge is best-effort and never blocks the primary page delete. Known limitation, tracked as RUSH-2701: the revision copy-then-overwrite isn't atomic, so two genuinely concurrent publishes to the same slug can race and silently drop the losing writer's content (no worse than pre-revisions last-write-wins, but it breaks the "keep-all" guarantee for that narrow case). Source: `apps/cli/src/lib/share/publish.ts`, `apps/cli/src/lib/share/worker-template.ts`, `apps/cli/src/lib/share/delete.ts`, `apps/cli/src/commands/share.ts`.
152
+
153
+ - **The menu bar no longer groups a session under its harness name or a machine name, and its header now shows the installed CLI version (RUSH-2688).** The ACTIVE dropdown grouped a Codex cloud task under a project literally named `codex`: a queued Codex Cloud task carries no local cwd and no repo, and the menu's cold-start cloud reader keyed the group `repo ?? provider ?? "cloud"`, so a repo-less task fell through to the provider — the harness name — as its "project" (a repo-less task on zion: `repo=NULL, provider='codex', prompt='Read README.md…'`). The one project-key derivation is now explicit and shared: a working dir → its repo (worktree-aware); a row with no local cwd → its own repo when the provider names one (`phnx-labs/agents-cli` → `agents-cli`, grouping cloud work with the matching local repo), else the single explicit `cloud` bucket — never the harness or a machine name, no fallback chain (`activeSessionProjectKey` in `src/commands/sessions.ts`, `LocalState.groupKey` in the helper). Separately, the dropdown header hardcoded `agents-cli`; it now reads `agents-cli <version>` from the snapshot's `cliVersion` (`getCliVersion()`, the value `agents --version` prints), resolved at runtime so a menu-bar helper left running across an `agents` upgrade shows the stale version at a glance. Source: `apps/cli/src/commands/sessions.ts`, `apps/cli/src/lib/menubar/snapshot.ts`, `apps/cli/menubar/Sources/MenubarHelper/{LocalState,StatusItemController,Models,ActiveSessionSelfTest}.swift`.
154
+
155
+ - **`agents monitors runs`/`view` now show a fire's REAL outcome, reconciled against the run's current status, instead of the frozen `ok` written at fire time (RUSH-2690).** `dispatchAction` (`lib/monitors/dispatch.ts`) only checks a synchronous snapshot: `executeJobDetached` writes `status: 'running'` before spawning and returns immediately (`lib/runner.ts`'s `executeJobDetachedClaimed`), while the real outcome — `completed`, `failed`, `timeout`, or a process that exits with no captured output — lands later, asynchronously, in that function's own `settle()` on child exit/error. RUSH-2500/RUSH-2681 fixed the SYNCHRONOUS skip/blocked/wrong-owner cases; this closes the async gap. A `run` action's fire record was persisted with `ok: true` off that transient `running` state and nothing ever revisited it, so `agents monitors runs` showed a healthy fire history forever while `agents monitors logs` (which reads the run record fresh) already showed `skipped`/`failed` — the exact divergence the ticket reproduced (fire `ok` at T, run `skipped` 3ms later). `resolveFireOutcome` (`lib/monitors/state.ts`) re-reads the run's real, current status by `runId` at render time and corrects `ok` against it; `agents monitors runs` and `agents monitors view`'s Recent fires now call it instead of trusting the stored `ok`, and `runs` also surfaces the corrected status inline (`ok (run failed)`) when it diverges from the frozen write. The engine additionally stamps a best-effort `runStatusAtFire` on the fire record (schema-compatible, additive) so a future daemon-tick reconciliation pass has a cheap signal for exactly which historical fires were frozen mid-flight. Source: `apps/cli/src/lib/monitors/state.ts`, `apps/cli/src/lib/monitors/engine.ts`, `apps/cli/src/commands/monitors.ts`.
156
+
157
+ - **`agents sessions preview <id>` can no longer render a DIFFERENT session's transcript (RUSH-2691).** For every harness except Claude, the live-row transcript lookup took a session id and threw it away: it answered `WHERE agent = ? AND cwd = ? ORDER BY last_activity DESC LIMIT 1`, i.e. the newest transcript in that cwd. With two same-harness agents in one directory — measured on this fleet: two codex sessions in one checkout, ids `01a00504-8ac6-…` and `01a00504-8bd8-…` — both rows resolved to a third session's file. Before 1.22.39 that only mis-set a status badge; once the live row began backing `preview`/`resume`/`focus` it started showing users another session's content, and the picker cached that body against the wrong id. A known id now selects its own transcript, and an id the index has not reached yet renders the honest "not indexed here" card instead of a neighbour's. The id-less fallback (a single session in a cwd) is unchanged. Source: `apps/cli/src/lib/session/active.ts`.
158
+
159
+ - **The daemon's session-index tick now reports what it actually indexed, and stops paying for a listing query it never used (RUSH-2691).** The tick scanned correctly — that part of the warm index worked — but it called `discoverSessions()` with no options, so the number it reported came from that function's trailing listing query, whose cwd filter defaults to `process.cwd()` (the daemon's, `$HOME`) and caps at 50. The count therefore meant "sessions whose cwd is exactly `$HOME`, max 50": `0` on any normal box, every 20 seconds, regardless of how much the scan had indexed, with nothing logged either way. The query was also not free — it ran an `archived_at`-writing existence check and a Linear fetch on every tick. The tick now calls a new `scanSessionsIncremental` (the scan half of `discoverSessions`, split out so both share one implementation), reports transcripts actually parsed, and skips the listing query. The daemon logs when a tick indexes something or yields the scan claim, so a tick that goes quiet is visible rather than silent. `scanOpenCodeIncremental` and `scanOpenClawIncremental` gained the progress callback the other eleven scanners already had, so the count covers every harness. Source: `apps/cli/src/lib/daemon-ticks.ts`, `apps/cli/src/lib/session/discover.ts`, `apps/cli/src/lib/daemon.ts`.
160
+
161
+ - **Deleted eight unreachable resource handlers (RUSH-2695).** `apps/cli/src/lib/resources/` held ten `ResourceHandler` implementations, and eight of them — commands, hooks, mcp, memory, permissions, rules, skills, subagents — had no consumer anywhere outside their own test files. This was not harmless dead weight: RUSH-2677 was filed against `McpHandler.sync` as the site of a silent MCP no-op, pointing the fix at a code path that never runs, and the real defect turned out to be in `installMcpServers`. Eight dead handlers is eight ways to repeat that. `resources/workflows.ts` stays — it is genuinely live (`lib/resources.ts:16`, `:530`) — as does `resources/types.ts`, which it imports. Note `lib/resources.ts` (singular, `resolveResource`/`listResources`) is a different, live module; conflating it with the `lib/resources/` directory is what made this look like a whole-layer deletion at first. Refactor only, no behavior change. Source: `apps/cli/src/lib/resources/`.
162
+
163
+ - **`agents sync --yes` and the `--device all` fan-out no longer report a refused write as a clean sync (RUSH-2700).** RUSH-2677 made a declined resource visible, but only on the interactive and per-agent surfaces: `agents sync <agent>@all --json` and the umbrella payload still emitted a hardcoded `ok: true` and omitted `declined` entirely, and `refresh()` returned `void` so the umbrella never saw a decline in the first place. Since the fleet fan-out injects `--json` on each peer, a harness whose MCP config format is unimplemented (copilot, amp, kiro, goose) reported success fleet-wide while writing nothing — the exact silent-success class RUSH-2677 set out to remove, surviving on the surface machines read. `refresh()` now returns the declines it collected and prints a `Not written:` block on the human path; the umbrella carries them; both JSON emitters derive `ok` from whether anything was refused; and the fan-out roster renders `N not written` for a peer that declined, instead of a flat green `ok`. Audited every `emitJson` call site in `commands/sync.ts` rather than only the two that were reported: three payload shapes can carry a decline and all three now do — the rest are failure payloads, `nothing to sync`, dry runs, `repo-git`, or `launch`, none of which run a resource sync (`runLaunchSync` returns a `LaunchSyncResult` and never calls `syncResourcesToVersion`). Documented in `docs/resource-sync.md` alongside the `pruned` precedent. Source: `apps/cli/src/lib/refresh.ts`, `apps/cli/src/lib/sync-umbrella.ts`, `apps/cli/src/commands/sync.ts`, `apps/cli/src/lib/hosts/passthrough.ts`.
164
+
165
+ - **`agents permissions add ~/.config/opencode/opencode.json` now imports instead of printing "No permission sets found" (RUSH-2702).** Harness detection built its match suffixes by calling each registry target's `home('')`, and OpenCode's entry probes the filesystem to choose between the two spellings OpenCode accepts (`opencode.jsonc` / `opencode.json`). With an empty root that probe resolved against `process.cwd()`, so the same file detected differently depending on where the CLI happened to be run. Detection now reads an explicit `altSuffixes` list covering **both** spellings OpenCode accepts, so the probe can no longer change which harness a path resolves to (`home('')`/`project('')` are still consulted, but every spelling they could return is already an explicit candidate); resolving a real root still probes, which is correct there. Regression-tested for each spelling from a cwd carrying decoy configs and from a bare one — the decoy cwd is what reproduces the bug, which is why single-cwd coverage passed before.
166
+
167
+ - **The capability matrix in `docs/concepts.md` said Goose supports permissions.** RUSH-2676 removed that support and updated `AGENTS.md` and `docs/resource-sync.md`, but missed `concepts.md` — in the very table whose header names `src/lib/agents.ts` as its source of truth. Both the row and the prose list of allowlist-gated agents now match the code.
168
+
169
+ - **New browser profiles are machine-local by default, and `agents browser profiles prune` cleans up the dead ones (RUSH-2716).** A profile pins an OS-specific `binary:` path and a locally chosen CDP port, so the fleet-synced copy was already wrong on every other box — and because agents mint throwaway profiles freely, every ad-hoc one was landing in the shared `agents.yaml` and syncing to the whole fleet as junk that nothing removed. `agents browser profiles create <name>` now writes to this machine's own `devices/<machine>/agents.yaml`; pass `--fleet` for a profile that really is fleet config (a remote `ssh://` endpoint, or a shape you want on every box). Existing profiles are **not** migrated — this only decides where a NEW entry is written, so a fleet profile created before this change keeps syncing. The auto-detected `default` stays machine-local regardless, as it has since 1.22.38. `agents browser profiles prune` removes local profiles that are dead — their browser is not installed here, or they have never been started — with `--dry-run` to preview, `--fleet` to opt into the synced ones (removing one removes it from EVERY machine), and `--json`. It never removes a profile that is in use (live browser, SSH tunnel, or open task on any of its runtime dirs, composites included), this machine's configured default, or the auto `default`. Source: `apps/cli/src/lib/browser/profiles.ts`, `apps/cli/src/lib/browser/runtime-state.ts`, `apps/cli/src/commands/browser.ts`.
170
+
171
+ - **`agents browser profiles list` no longer breaks its own columns, and `default` means one thing again (RUSH-2710).** The name column was a bare `padEnd(20)`, which returns a longer name unchanged rather than bounding it, so any profile named past 20 characters shifted every later column on its row out of alignment. Columns are now sized to the content, capped at 28 characters, and truncated with an ellipsis — via one `padColumn` helper every column goes through, never a bare `padEnd`. Separately, the listing used the word "default" for two different things with no way to tell them apart: the profile literally NAMED `default` (the auto-detected one) and whichever profile this machine resolves a bare `agents browser start` to (`agents config set browser.profile <name>`), which are frequently not the same profile. Only the second is a marker now — a `*` in a leading column with a legend naming it — so `default` in the name column always means the profile of that name. A new `SCOPE` column says whether each entry is `local` (this machine) or `fleet` (synced), and `--json` carries `scope` plus `isConfiguredDefault`. Source: `apps/cli/src/lib/browser/profiles.ts` (`formatProfilesTable`, `padColumn`), `apps/cli/src/commands/browser.ts`.
172
+
173
+ ### Added
174
+ - `agents routines add`/`edit` accept the same launch-target vocabulary as `agents run` (RUSH-2719): `--agent <agent[@version]>` splits into persisted bare `agent` + exact `version` fields (previously the compound string failed validation with `agent must be one of: ...`); `--strategy pinned|available|balanced` (and `--balanced`) persists a per-routine selection policy that overrides the firing device's `run.<agent>.strategy`; `--run-on auto` places the job body on a healthy, signed-in, unloaded fleet device re-picked at each fire via the same picker as `agents run --device auto`.
175
+
176
+ ### Removed
177
+ - `gemini` is no longer a routine target: dropped from `ROUTINE_AGENT_COMMANDS`, so `routines add --help` stops advertising a hard-deprecated harness the add-gate refuses anyway. A legacy on-disk gemini routine still lands a visible `blocked` run record with the deprecation message (the RUSH-2202 gate now keys on deprecation alone, not command-table membership).
178
+
179
+ ### Fixed
180
+ - A hard-deprecated harness pinned with `@version` no longer slips past the `routines add` deprecation gate (the check ran `resolveAgentName` on the raw compound string and silently matched nothing).
181
+ - A routine pinned to a version that is not installed locally now saves paused with `pinned <agent>@<version> is not installed on the target` and an `agents add` repair, instead of activating and failing at fire time.
182
+
183
+ - **Branding: fix the remaining agi-cli hero + marketing-domain inconsistencies the first rebrand pass missed.** Root `README.md` hero (`<h1>`/logo `alt`) now reads "agi-cli" instead of "agents", and the marketing-domain references in `README.md`, `DESIGN.md`, `demo/src/AgentsDemo.tsx`, and `apps/cli/docs/README.md` now point at `agi-cli.sh` (the live marketing domain) instead of the retired `agents-cli.sh`. This is docs/branding only — no runtime behavior change. Not touched: the `share.agents-cli.sh` links (that subdomain is not live on `agi-cli.sh`), the npm package name `@phnx-labs/agents-cli` and its install lines, and historical `CHANGELOG.md`/`.changelog/` entries. Source: `README.md`, `DESIGN.md`, `demo/src/AgentsDemo.tsx`, `apps/cli/docs/README.md`.
184
+
185
+ - **`agents browser` resolves the task from the caller's identity — no more `No task specified` / `export AGENTS_BROWSER_TASK=…` in the common path.** `--task` and `$AGENTS_BROWSER_TASK` still win when set; otherwise the CLI stamps `sessionId`/`launchId` once inside `sendIPCRequest` (from the session-tracker state file at the harness pid, else the process-table anchor via `agentKindFromComm`, stamped as `launchId` so the reaper never treats it as a dead session) and the daemon picks the single live task for that caller. Multiple tasks list label/id/url/age and name `--task`; page verbs create a task when none resolve; observation verbs and `done`/`stop` never create. Tasks get a human `label` (`--title`, else first navigated host, else `untitled`) while the short machine id remains the address. After a daemon restart, live tasks rehydrate from `tasks.json` via the profile endpoint. Version reconciliation restarts the daemon *forward only* so an older CLI rides a newer daemon. `status --profile <bare>` matches composite `name@endpoint` keys. Grammar: `navigate [url]` (alias `goto`), `evaluate [expr]` (alias `eval`), `logs --task`. Errors name a next command. Source: `apps/cli/src/commands/browser.ts`, `apps/cli/src/lib/browser/{service,ipc,types,caller-identity}.ts`.
186
+
187
+ - **CLI surface consolidation — nest or remove overlapping top-level commands.**
188
+ - Synced vault unlock/lock moves to `agents secrets vault unlock|lock` (replaces top-level `login`/`logout`). Harness-native OAuth sign-out is `agents accounts logout <harness>` (API-key accounts keep `accounts remove`).
189
+ - Spend caps live under `agents config budget` (was top-level `budget`).
190
+ - Cost and shipped-output rollups nest under `agents insights cost` / `agents insights output`.
191
+ - White-label manage verbs nest under `agents setup mine` (`init`/`list`/`toggle`/`remove`); top-level `mine` is gone.
192
+ - Fleet poll snapshot moves to `agents devices snapshot` (not config).
193
+ - Matrix runs use `agents run --broadcast` (with `--list-tasks` / `--results` / `--task`); top-level `bench` is removed.
194
+ - Top-level `agents profiles` is removed — use `agents harness` (same `~/.agents/profiles/*.yml`).
195
+ - Top-level `agents cp` is removed — use plain `scp` (or `scp -3` for host-to-host); no fleet broadcast advantage.
196
+ - Top-level `agents resume` folds into `agents sessions resume` (strict id/prompt path + multi-select picker).
197
+ - Top-level `agents roster` is removed — use `agents sessions --active`.
198
+ Source: `apps/cli/src/commands/{secrets-vault,accounts,budget,config,cost,output,insights,mine,setup-mine,snapshot,ssh,exec,run-broadcast,harness,profiles,resume,sessions-resume}.ts`, `apps/cli/src/lib/startup/command-registry.ts`.
199
+
200
+ - **Device config moves to per-device files; agent pins leave the tracked tree.** The `agents devices config <name>` store is now three layers, read in order — built-in default < fleet default < per-device value: per-device settings land in the TRACKED `~/.agents/devices/<name>/agents.yaml` `config:` block (conflict-free by construction — each machine writes only its own folder), and a new `--fleet` flag (`agents devices config --fleet <key> <value>`) writes fleet-wide defaults to central `fleet.defaults.config`. This supersedes #2458's central `fleet.devices.<name>.config` block, which a one-time migration folds into the per-device docs (central wins); the same migration extracts `agents:`/`isolatedAgents:` pins from the tracked docs into the untracked `~/.agents/.history/devices/pins-<host>.json` — the root-cause fix for the commit churn that kept `devices/` gitignored — and folds the legacy `auto-launch.json` in too. Reads report effective values; `--json` gains a per-key `source` (`device` | `fleet` | `default`); the TTY menu shows effective values and edits the device layer. Shims resolve default pins from the pins JSON first (device-doc and central fallbacks kept for unmigrated installs); `agents fleet capture --from-pins` now records only this machine's pins (peer pins no longer sync). AGI EXT reads the same per-device docs layered over `fleet.defaults.config`. Source: `apps/cli/src/lib/device-config.ts`, `apps/cli/src/lib/state.ts`, `apps/cli/src/lib/devices/config-migration.ts`, `apps/cli/src/lib/shims.ts`, `apps/ext/src/core/deviceAutoLaunch.ts`.
201
+
202
+ - **A project renamed in Linear kept its old label in `agents projects` forever — `linear.name` was written once and never refreshed.** `agents projects link` knew the current name (it printed it in the success line) but wrote only the id: `def.linear = { ...def.linear, projectId: p.id }` spread the prior block, preserving the stale `name`. `projects import --from-linear` did not write the field at all. Nothing in the tree ever set it, so every recorded label dated from some older version. Measured on a real registry after a workspace consolidated six Linear projects into three: `agents-cli.yaml` read `name: Agents CLI` for a project the board calls **AGI**, `rush-app.yaml` read `Rush App` for **Rush**, and three defs still pointed at project ids Linear had deleted. The label is not inert — `apps/ext/src/core/managedProjects.ts` surfaces it as `linearProjectName` in the AGI EXT Fleet panel, and agents read it when naming the work, so both reported a project name that no longer existed. `link` and `import` now write `name` from the live Linear row every run, `link` reports the replacement (`renaming "Agents CLI" → "AGI" (Linear is authoritative)`) and drops a `url` belonging to the project it just unlinked, and the `projects status` card leads with the name instead of the bare uuid (`linear AGI 8eb8f5b1-…`). Re-run `agents projects link <name> --linear "<project>"` to repair an existing def. Source: `apps/cli/src/commands/projects.ts`, `apps/cli/src/lib/project-import.ts`.
203
+
204
+ - **One canonical `formatBytes`, and byte sizes now read the same everywhere.** Five
205
+ copies had drifted into three different renderings of the same number. Four of the five
206
+ call sites change output at some boundary: `agents prune` showed `1.50 GB` where every
207
+ other surface showed `1.5 GB`; session artifact sizes capped at `MB`, so a 1.4 GiB
208
+ transcript rendered as `1433.6 MB`; and `agents share` plus the browser artifact list
209
+ capped at `GB`, so a 2.3 TiB entry rendered as `2355 GB` and now reads `2.3 TB`. Only
210
+ `agents inspect` is byte-identical to before — its implementation is the one all five
211
+ now share. Source: `apps/cli/src/lib/format.ts`,
212
+ `apps/cli/src/commands/{prune,share,inspect,sessions}.ts`,
213
+ `apps/cli/src/lib/browser/sessions-list.ts`.
214
+
215
+ - **Capability version gates now honor OpenClaw's `-N` rebuild suffix.** `supports()` and
216
+ the command version gate each carried a private `compareVersions` that split on `.` and
217
+ dropped the trailing `-N`, so `2026.2.19-2` compared equal to `2026.2.19`. Both now use
218
+ the canonical comparator in `lib/agent-spec/primitives.ts`, which treats a higher `-N`
219
+ as newer. No capability currently declares a `-N` floor, so nothing changes today — the
220
+ gate is simply no longer wrong for the version scheme OpenClaw actually ships. Source:
221
+ `apps/cli/src/lib/capabilities.ts`, `apps/cli/src/lib/commands.ts`.
222
+
223
+ - **`SESSION_AGENTS` and the sessions command surface documented accurately.** The spec
224
+ said "exactly these 12" while the code has 13 (`muse` was missing), and both it and
225
+ `SES-IF-2` required a `sessions sync` subcommand that has never existed. The command
226
+ list also omitted seven real subcommands (`render`, `bookmark`, `stats`, `insights`,
227
+ `optimize`, `watch`, `backfill resources`) while still listing verbs that
228
+ `655b22512` retired behind `resume`. Source: `apps/cli/docs/specifications.md`,
229
+ `apps/cli/docs/architecture.md`.
230
+
231
+ - **The sessions picker now shows a real preview for a peer's session, not just its metadata.** Arrow onto a row another device owns in `agents sessions` (the fleet browser or the query picker) and the pane fetches that peer's already-computed preview digest over SSH — prompt, checklist, dirs, changes, skills, errors, tests, and last response, the same card a local row gets — repainting in place when it lands (a "fetching preview from <device> over SSH…" note shows meanwhile, and an unreachable peer degrades to the old metadata card without re-dialing on every keystroke). Peer-supplied digest strings are scrubbed of terminal escapes before they reach the TTY, and a version-skewed peer that can't answer the digest envelope falls back cleanly. Source: `apps/cli/src/commands/sessions-picker.ts` (`sanitizeRemoteDigest`), `apps/cli/src/lib/session/remote-list.ts` (`fetchPeerPreviewDigest`), `apps/cli/src/lib/picker.ts` (`registerPreviewRepaint`).
232
+
233
+ - **Resource pickers number their rows.** The interactive lists behind `agents inspect <repo> --commands` (and the other resource views built on the same picker — plugins, skills, hooks) prefix every row with its position in the filtered list (` 1.` … `12.`), right-aligned so labels stay columnar. Where the caller prints a total — `agents inspect` shows `commands (12)` above the picker — the row numbers read against it. Filtering renumbers from 1 over the matches. Source: `apps/cli/src/lib/picker.ts` (`PickerConfig.numbered`), `apps/cli/src/commands/resource-view.ts`.
234
+
235
+ ### Breaking
236
+
237
+ - **Fleet routing: `--device` / `-D` only.** The `-H`/`--host` routing flag is
238
+ removed from every command that used it for remote dispatch. Use
239
+ `--device <name>` (or `-D`). Scripts using `--host` for fleet routing must
240
+ switch. Legacy `--host` is still *stripped* from forwarded remote argv for
241
+ mixed-version fleets, but is no longer registered or documented as a user
242
+ flag. Unchanged: `agents hosts` noun, Docker `-H`/`--host`, webhook bind
243
+ host, harness model `--host`.
244
+
245
+ - **Unify native logins and provider credentials under one account model (RUSH-2527).**
246
+ `agents accounts name <agent@version> <name>` gives a durable name to a
247
+ harness's own signed-in login — metadata only in `meta.accounts.native` (a
248
+ stable id + identity key + scope), never the harness's OAuth/session credential,
249
+ which stays in the harness home. Native and provider accounts now share one name
250
+ namespace and one `accounts` / `accounts view` renderer (text + `--json`). New
251
+ positional grammar: `accounts name <source> <name>`,
252
+ `accounts attach <account> <target>` / `detach <account> <target>`, and
253
+ `accounts sync <account> <device>`. Only version-scoped nameable harnesses
254
+ (Claude/Codex/Grok, plus Muse when a live email is present) can be named
255
+ or attached, always to an exact `agent@version`. Device-scoped harnesses
256
+ (Cursor/OpenCode/Antigravity/Kimi/Droid) are unsupported for native
257
+ naming — their API-key path is a provider account. `attach`
258
+ validates the live identity before binding and injects no secret or env;
259
+ `resolveAccountSelection` resolves explicit → exact-target binding →
260
+ device-scoped binding → per-harness default. `remove` refuses while a binding, a
261
+ default, or a harness profile still references the account. Bindings are honored
262
+ end-to-end: `agents run` and routines select the bound account at spawn — a
263
+ provider account injects its env, a native account is validated live and pins
264
+ the installed version that holds it (never forwarded/injected, fails closed for
265
+ a remote/cloud target or a cross-harness login) — and `agents view` plus the
266
+ fleet/harness inventories render the durable account name. Source:
267
+ `apps/cli/src/lib/account-registry.ts`, `apps/cli/src/lib/account-capabilities.ts`,
268
+ `apps/cli/src/commands/accounts.ts`, `apps/cli/src/commands/exec.ts`,
269
+ `apps/cli/src/lib/runner.ts`, `apps/cli/src/commands/view.ts`,
270
+ `apps/cli/src/lib/devices/{fleet,harness}-inventory.ts`, `apps/cli/src/lib/types.ts`.
271
+
272
+ - **`agents cloud run` (Rush) never reads or uploads a native Claude OAuth login
273
+ (RUSH-2527, SING-1b, breaking).** Two changes: (1) the account manifest sent on
274
+ every non-balanced dispatch no longer includes a `cred_fp` hash computed by
275
+ reading each Claude version's OAuth token — it carries **version + account email
276
+ only**; (2) the token-upload retry path is **removed entirely** — the
277
+ `--upload-account-tokens` flag, the `AGENTS_RUSH_UPLOAD_TOKENS` env var, the
278
+ recorded consent file, and `buildAccountTokensPayload` are gone. There is no
279
+ consented way to copy a rotating harness login to the cloud (it would be
280
+ invalidated on its next refresh and log the fleet out). When Rush Cloud asks for
281
+ a token (a new account or a rotation), dispatch now **fails loud** and steers to a
282
+ portable provider account: `agents accounts add <name> --provider anthropic --auth
283
+ api-key` (or `setup-token`), then dispatch under that account. Source:
284
+ `apps/cli/src/lib/cloud/rush.ts`, `apps/cli/src/commands/cloud.ts`.
285
+
286
+ - **`agents run --host --copy-creds` and `agents run --lease` no longer copy a
287
+ native OAuth / session login to another device (RUSH-2527, breaking for those
288
+ flags).** Both used to serialize each signed-in runtime's rotating login — the
289
+ Claude OAuth token and codex/grok/gemini `auth.json` files — onto a persistent
290
+ host (`--copy-creds`) or an ephemeral leased box (`--lease`) so it booted
291
+ logged-in. A rotating harness login copied across machines is invalidated on its
292
+ next server-side token refresh and logs the rest of the fleet out, and the
293
+ fleet-auth contract forbids it on every device, ephemeral or not
294
+ (`docs/specifications.md` SING-1b). Both now **fail loud** when asked to copy a
295
+ signed-in native runtime and steer to the portable, non-rotating path: create a
296
+ provider account (`agents accounts add`) and push it with `agents accounts sync
297
+ <name> --device <host>` (a policy-`never` bundle, safe to reuse on many devices).
298
+ A profile-dispatch `--lease` run carrying its own portable auth (a BYOK gateway)
299
+ still works; only the native-login copy is refused. Explicit `agents accounts
300
+ sync` and `secrets export --host` are unchanged. Sources:
301
+ `apps/cli/src/lib/hosts/credentials.ts`, `apps/cli/src/lib/crabbox/runtimes.ts`
302
+ (`buildCredentialScript`); shared predicate `isNativeOAuthRuntime`.
303
+
304
+ - **`agents apply` / `agents fleet apply` no longer propagates a harness login
305
+ between devices (RUSH-2527, SING-1b).** `login: sync` used to copy each agent's
306
+ portable login file (Claude `.credentials.json`, codex/grok/opencode/kimi/
307
+ antigravity `auth.json`) from the source box to every target — a rotating token
308
+ that a single refresh then invalidates fleet-wide. `apply` now emits no
309
+ `push-login` action and captures no credential (`snapshotAuth` reads nothing);
310
+ every `login: sync` agent that needs a login is surfaced as **needs-login** with
311
+ the honest reason and the portable alternative — log in on the box itself, or
312
+ `agents accounts sync <name> --device <host>` a policy-`never` provider account.
313
+ The internal `apply --recv-auth` receive path is gone. Sources: `apps/cli/src/lib/fleet/auth-sync.ts`
314
+ (`isCredentialSafeToPropagate`), `apps/cli/src/lib/fleet/apply.ts`,
315
+ `apps/cli/src/commands/apply.ts`.
316
+
317
+ - **$HOME is never compiled as a "project" ruleset anymore, ending the double injection of the entire ruleset into every session (RUSH-2725).** `compileRulesForProject` treated any cwd with `.agents/rules` as a project — and the user layer's own home at `~/.agents` satisfies that test — so it wrote a compiled `~/AGENTS.md` plus per-agent symlinks (`~/CLAUDE.md`, `~/GEMINI.md`, …), and every session whose cwd sat under the home directory then loaded the whole ruleset twice: once as global memory from the version home, once as "project" memory from `~/`. Measured on one machine: ~145 KB / ~36,000 duplicated tokens per session, on every agent, on every box — and the two copies also diverged, so an agent resolving the stale project copy silently missed the newest rules. The compiler now consults the same reserved-root predicate `getProjectAgentsDir` already used (`isReservedAgentsDir` in `state.ts`: the user layer, the system layer, or a git checkout of either canonical DotAgents repo never compile as a project), and a one-shot migration deletes the compiled `~/AGENTS.md`, its per-agent symlinks, and header-carrying copy fallbacks already written on each machine — hand-authored files without the compiled header are untouched. Source: `apps/cli/src/lib/rules/compile.ts`, `apps/cli/src/lib/state.ts`, `apps/cli/src/lib/installations/migrate.ts` (`removeHomeCompiledProjectRules`).
318
+
3
319
  ## 1.22.39
4
320
 
5
321
  - **The auto-detected `default` browser profile no longer sits in the fleet-shared `agents.yaml`, which was wedging `agents repos pull user` fleet-wide (RUSH-2161).** `browser` is a central key because named profiles a user creates are real fleet config, but the one `default` entry inside it is machine-local: its `binary` is an OS-specific path and its endpoint is a locally chosen free port. `createProfile`/`updateProfile` have routed that entry to the per-device file since 1.22.38 (`isMachineLocalProfile`), but nothing removed the copy older versions had already written into the shared file, and `serializeCentral` could not — it deletes whole device-scoped KEYS, and `browser` is not one. So the stale entry stayed committed and every box rewrote it with its own browser. Measured across three boxes all running 1.22.38: zion `chrome` + `/Applications/Google Chrome.app/...`, yosemite-s1 `brave` + `/opt/brave.com/brave/brave`, mark-1 the same shape, each with an empty `deviceBrowser`. Because the pull refuses when an incoming change touches a locally modified path, a permanently dirty `agents.yaml` blocked fleet config sync outright — those boxes sat 5, 8 and 79 commits behind, so merged config (a `notify.owner` block, device roles) reached zero machines. A new migration moves the entry into `devices/<machine>/agents.yaml` and deletes it from central, writing the device file first so a crash cannot lose the profile and keeping an existing device entry when one is already there. Central is edited through a YAML `Document`, so the hand-written comments in the committed file survive rather than being flattened by a re-stringify — which would have re-created the same churn. Named profiles are untouched. Source: `apps/cli/src/lib/migrate.ts`, `apps/cli/src/bootstrap.ts`.