@phnx-labs/agents-cli 1.22.84 → 1.22.86

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 (259) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +80 -53
  3. package/dist/bootstrap.d.ts +7 -6
  4. package/dist/bootstrap.js +20 -27
  5. package/dist/cli/command-registry.js +5 -1
  6. package/dist/commands/accounts.d.ts +6 -13
  7. package/dist/commands/accounts.js +330 -143
  8. package/dist/commands/alias.js +7 -3
  9. package/dist/commands/apply.js +1 -1
  10. package/dist/commands/auth-mint.d.ts +7 -3
  11. package/dist/commands/auth-mint.js +21 -9
  12. package/dist/commands/auth.js +2 -3
  13. package/dist/commands/browser.js +10 -10
  14. package/dist/commands/daemon.d.ts +7 -3
  15. package/dist/commands/daemon.js +40 -25
  16. package/dist/commands/doctor.js +28 -2
  17. package/dist/commands/exec.js +87 -39
  18. package/dist/commands/fleet-capture.js +21 -2
  19. package/dist/commands/harness-wizard.js +2 -2
  20. package/dist/commands/lease.js +7 -12
  21. package/dist/commands/profiles.d.ts +2 -2
  22. package/dist/commands/profiles.js +20 -13
  23. package/dist/commands/repo.js +3 -3
  24. package/dist/commands/run-account-picker.d.ts +3 -3
  25. package/dist/commands/run-account-picker.js +29 -30
  26. package/dist/commands/secrets-passthrough.d.ts +20 -0
  27. package/dist/commands/secrets-passthrough.js +43 -0
  28. package/dist/commands/setup-accounts.d.ts +3 -2
  29. package/dist/commands/setup-accounts.js +4 -4
  30. package/dist/commands/setup-secrets.d.ts +16 -21
  31. package/dist/commands/setup-secrets.js +43 -224
  32. package/dist/commands/ssh.js +2 -2
  33. package/dist/commands/sync.js +1 -1
  34. package/dist/commands/update.d.ts +10 -0
  35. package/dist/commands/update.js +43 -40
  36. package/dist/commands/versions.d.ts +11 -11
  37. package/dist/commands/versions.js +131 -83
  38. package/dist/commands/view.d.ts +1 -9
  39. package/dist/commands/view.js +41 -55
  40. package/dist/commands/webhook.js +5 -5
  41. package/dist/commands/workflows.js +2 -1
  42. package/dist/index.d.ts +12 -12
  43. package/dist/index.js +13 -42
  44. package/dist/lib/account-capabilities.d.ts +1 -1
  45. package/dist/lib/account-capabilities.js +1 -1
  46. package/dist/lib/account-catalog.d.ts +121 -6
  47. package/dist/lib/account-catalog.js +421 -7
  48. package/dist/lib/account-registry.d.ts +8 -30
  49. package/dist/lib/account-registry.js +36 -79
  50. package/dist/lib/account-schema.d.ts +1 -1
  51. package/dist/lib/account-schema.js +1 -1
  52. package/dist/lib/accounting/account-pool-collect.js +16 -4
  53. package/dist/lib/accounting/rotate.d.ts +20 -7
  54. package/dist/lib/accounting/rotate.js +89 -13
  55. package/dist/lib/accounting/usage.js +11 -16
  56. package/dist/lib/accounts/add.d.ts +138 -0
  57. package/dist/lib/accounts/add.js +651 -0
  58. package/dist/lib/accounts/migrate.d.ts +117 -0
  59. package/dist/lib/accounts/migrate.js +536 -0
  60. package/dist/lib/accounts/slots.d.ts +13 -0
  61. package/dist/lib/accounts/slots.js +100 -0
  62. package/dist/lib/agent-spec/agents.d.ts +16 -0
  63. package/dist/lib/agent-spec/agents.js +38 -4
  64. package/dist/lib/app-bundle-install.js +5 -4
  65. package/dist/lib/auth-health.d.ts +3 -0
  66. package/dist/lib/auth-health.js +11 -0
  67. package/dist/lib/auth-mint.d.ts +52 -16
  68. package/dist/lib/auth-mint.js +117 -39
  69. package/dist/lib/browser/chrome.d.ts +1 -1
  70. package/dist/lib/browser/chrome.js +5 -5
  71. package/dist/lib/byok-usage.js +3 -3
  72. package/dist/lib/claude-account-token.d.ts +47 -3
  73. package/dist/lib/claude-account-token.js +172 -50
  74. package/dist/lib/cloud/antigravity.js +4 -4
  75. package/dist/lib/cloud/cursor.js +4 -4
  76. package/dist/lib/crabbox/cli.d.ts +1 -1
  77. package/dist/lib/crabbox/cli.js +6 -6
  78. package/dist/lib/crabbox/runtimes.d.ts +3 -3
  79. package/dist/lib/crabbox/runtimes.js +5 -5
  80. package/dist/lib/daemon/account-state-daemon-service.d.ts +37 -1
  81. package/dist/lib/daemon/account-state-daemon-service.js +199 -3
  82. package/dist/lib/daemon/auth-sync-service.js +32 -1
  83. package/dist/lib/daemon/daemon.d.ts +6 -16
  84. package/dist/lib/daemon/daemon.js +52 -97
  85. package/dist/lib/daemon/daemon.test-fixture.d.ts +7 -9
  86. package/dist/lib/daemon/daemon.test-fixture.js +22 -40
  87. package/dist/lib/daemon/harness-update-service.d.ts +1 -1
  88. package/dist/lib/daemon/harness-update-service.js +1 -1
  89. package/dist/lib/daemon/runner.d.ts +15 -3
  90. package/dist/lib/daemon/runner.js +49 -24
  91. package/dist/lib/daemon-health.d.ts +1 -2
  92. package/dist/lib/daemon-health.js +7 -6
  93. package/dist/lib/daemon-services.d.ts +1 -1
  94. package/dist/lib/daemon-services.js +1 -11
  95. package/dist/lib/daemon-webhooks.d.ts +8 -7
  96. package/dist/lib/daemon-webhooks.js +10 -9
  97. package/dist/lib/device-config.js +1 -1
  98. package/dist/lib/devices/doctor-findings.d.ts +1 -1
  99. package/dist/lib/devices/harness-inventory.d.ts +39 -0
  100. package/dist/lib/devices/harness-inventory.js +126 -4
  101. package/dist/lib/doctor-diff.js +2 -1
  102. package/dist/lib/exec-account-home.d.ts +38 -0
  103. package/dist/lib/exec-account-home.js +164 -0
  104. package/dist/lib/exec.d.ts +30 -0
  105. package/dist/lib/exec.js +101 -31
  106. package/dist/lib/fleet/apply.d.ts +2 -2
  107. package/dist/lib/fleet/apply.js +4 -4
  108. package/dist/lib/fleet/auth-sync.js +4 -3
  109. package/dist/lib/fleet-shared-repo-sync.js +6 -9
  110. package/dist/lib/harness/adapter.d.ts +7 -7
  111. package/dist/lib/harness/adapter.js +10 -6
  112. package/dist/lib/harness/adapters/grok.js +8 -3
  113. package/dist/lib/harness/adapters/muse.js +1 -1
  114. package/dist/lib/harness/adapters/opencode.js +12 -3
  115. package/dist/lib/harness-auth-capabilities.d.ts +61 -0
  116. package/dist/lib/harness-auth-capabilities.js +52 -0
  117. package/dist/lib/helper-versions.d.ts +6 -4
  118. package/dist/lib/helper-versions.js +5 -4
  119. package/dist/lib/hosts/credential-transport.d.ts +10 -0
  120. package/dist/lib/hosts/credential-transport.js +37 -0
  121. package/dist/lib/hosts/dispatch.d.ts +7 -0
  122. package/dist/lib/hosts/dispatch.js +13 -6
  123. package/dist/lib/identity/client.d.ts +3 -3
  124. package/dist/lib/identity/client.js +3 -3
  125. package/dist/lib/installations/index.d.ts +1 -1
  126. package/dist/lib/installations/index.js +1 -1
  127. package/dist/lib/installations/migrate.js +9 -0
  128. package/dist/lib/installations/resolve.js +1 -1
  129. package/dist/lib/installations/shims.d.ts +21 -4
  130. package/dist/lib/installations/shims.js +86 -5
  131. package/dist/lib/installations/store.d.ts +43 -0
  132. package/dist/lib/installations/store.js +75 -7
  133. package/dist/lib/installations/versions.js +1 -1
  134. package/dist/lib/menubar/install-menubar.d.ts +3 -3
  135. package/dist/lib/menubar/install-menubar.js +3 -3
  136. package/dist/lib/native-accounts.d.ts +35 -0
  137. package/dist/lib/native-accounts.js +41 -0
  138. package/dist/lib/net-close.d.ts +11 -0
  139. package/dist/lib/net-close.js +25 -0
  140. package/dist/lib/openclaw-keychain.js +27 -1
  141. package/dist/lib/profiles.js +22 -9
  142. package/dist/lib/project-resources.js +1 -1
  143. package/dist/lib/reserved-stores.d.ts +53 -0
  144. package/dist/lib/reserved-stores.js +120 -0
  145. package/dist/lib/secrets-client.d.ts +199 -0
  146. package/dist/lib/secrets-client.js +718 -0
  147. package/dist/lib/secrets-policy.d.ts +235 -0
  148. package/dist/lib/secrets-policy.js +505 -0
  149. package/dist/lib/secrets-types.d.ts +188 -0
  150. package/dist/lib/secrets-types.js +24 -0
  151. package/dist/lib/self-heal/checks/shims.js +5 -3
  152. package/dist/lib/service-manifest.js +3 -4
  153. package/dist/lib/session/db.d.ts +18 -0
  154. package/dist/lib/session/db.js +47 -14
  155. package/dist/lib/session/sync/config.js +2 -2
  156. package/dist/lib/sha256-asset.d.ts +11 -16
  157. package/dist/lib/sha256-asset.js +11 -16
  158. package/dist/lib/share/config.js +14 -5
  159. package/dist/lib/signin-badge.d.ts +26 -0
  160. package/dist/lib/signin-badge.js +42 -0
  161. package/dist/lib/staleness/detectors/workflows.js +3 -105
  162. package/dist/lib/staleness/writers/workflows.js +2 -1
  163. package/dist/lib/state.d.ts +7 -4
  164. package/dist/lib/state.js +18 -7
  165. package/dist/lib/sync-umbrella.js +2 -2
  166. package/dist/lib/teams/agents.js +1 -1
  167. package/dist/lib/types.d.ts +74 -33
  168. package/dist/lib/view-types.d.ts +6 -3
  169. package/dist/lib/workflows-registry.d.ts +71 -0
  170. package/dist/lib/workflows-registry.js +280 -0
  171. package/dist/lib/workflows.d.ts +21 -21
  172. package/dist/lib/workflows.js +12 -327
  173. package/package.json +2 -3
  174. package/scripts/postinstall.js +35 -30
  175. package/dist/commands/secrets-import.d.ts +0 -18
  176. package/dist/commands/secrets-import.js +0 -74
  177. package/dist/commands/secrets-migrate.d.ts +0 -25
  178. package/dist/commands/secrets-migrate.js +0 -334
  179. package/dist/commands/secrets-rotate-passphrase.d.ts +0 -17
  180. package/dist/commands/secrets-rotate-passphrase.js +0 -96
  181. package/dist/commands/secrets-sync.d.ts +0 -11
  182. package/dist/commands/secrets-sync.js +0 -153
  183. package/dist/commands/secrets-vault.d.ts +0 -10
  184. package/dist/commands/secrets-vault.js +0 -130
  185. package/dist/commands/secrets.d.ts +0 -212
  186. package/dist/commands/secrets.js +0 -3030
  187. package/dist/lib/accounts/connect.d.ts +0 -176
  188. package/dist/lib/accounts/connect.js +0 -453
  189. package/dist/lib/daemon/keychain-reap-service.d.ts +0 -17
  190. package/dist/lib/daemon/keychain-reap-service.js +0 -32
  191. package/dist/lib/daemon/secrets-broker-service.d.ts +0 -21
  192. package/dist/lib/daemon/secrets-broker-service.js +0 -51
  193. package/dist/lib/secrets/agent.d.ts +0 -358
  194. package/dist/lib/secrets/agent.js +0 -1291
  195. package/dist/lib/secrets/audit.d.ts +0 -46
  196. package/dist/lib/secrets/audit.js +0 -101
  197. package/dist/lib/secrets/bundles.d.ts +0 -290
  198. package/dist/lib/secrets/bundles.js +0 -1547
  199. package/dist/lib/secrets/download-keychain.d.ts +0 -47
  200. package/dist/lib/secrets/download-keychain.js +0 -70
  201. package/dist/lib/secrets/drivers/rush.d.ts +0 -14
  202. package/dist/lib/secrets/drivers/rush.js +0 -90
  203. package/dist/lib/secrets/fallback.d.ts +0 -48
  204. package/dist/lib/secrets/fallback.js +0 -48
  205. package/dist/lib/secrets/filestore.d.ts +0 -222
  206. package/dist/lib/secrets/filestore.js +0 -1099
  207. package/dist/lib/secrets/headless.d.ts +0 -43
  208. package/dist/lib/secrets/headless.js +0 -56
  209. package/dist/lib/secrets/icloud-import.d.ts +0 -79
  210. package/dist/lib/secrets/icloud-import.js +0 -206
  211. package/dist/lib/secrets/index.d.ts +0 -451
  212. package/dist/lib/secrets/index.js +0 -1568
  213. package/dist/lib/secrets/install-helper.d.ts +0 -72
  214. package/dist/lib/secrets/install-helper.js +0 -245
  215. package/dist/lib/secrets/lease.d.ts +0 -25
  216. package/dist/lib/secrets/lease.js +0 -44
  217. package/dist/lib/secrets/linux.d.ts +0 -77
  218. package/dist/lib/secrets/linux.js +0 -393
  219. package/dist/lib/secrets/list-filter.d.ts +0 -109
  220. package/dist/lib/secrets/list-filter.js +0 -261
  221. package/dist/lib/secrets/mcp.d.ts +0 -93
  222. package/dist/lib/secrets/mcp.js +0 -211
  223. package/dist/lib/secrets/profiles.d.ts +0 -10
  224. package/dist/lib/secrets/profiles.js +0 -13
  225. package/dist/lib/secrets/push.d.ts +0 -133
  226. package/dist/lib/secrets/push.js +0 -273
  227. package/dist/lib/secrets/rc-hygiene.d.ts +0 -63
  228. package/dist/lib/secrets/rc-hygiene.js +0 -143
  229. package/dist/lib/secrets/read-backoff.d.ts +0 -27
  230. package/dist/lib/secrets/read-backoff.js +0 -64
  231. package/dist/lib/secrets/reaper.d.ts +0 -90
  232. package/dist/lib/secrets/reaper.js +0 -243
  233. package/dist/lib/secrets/remote.d.ts +0 -152
  234. package/dist/lib/secrets/remote.js +0 -344
  235. package/dist/lib/secrets/reserved-sync.d.ts +0 -66
  236. package/dist/lib/secrets/reserved-sync.js +0 -147
  237. package/dist/lib/secrets/scope.d.ts +0 -26
  238. package/dist/lib/secrets/scope.js +0 -29
  239. package/dist/lib/secrets/session-store.d.ts +0 -107
  240. package/dist/lib/secrets/session-store.js +0 -342
  241. package/dist/lib/secrets/sync-backend.d.ts +0 -48
  242. package/dist/lib/secrets/sync-backend.js +0 -13
  243. package/dist/lib/secrets/sync-commands.d.ts +0 -21
  244. package/dist/lib/secrets/sync-commands.js +0 -21
  245. package/dist/lib/secrets/sync.d.ts +0 -48
  246. package/dist/lib/secrets/sync.js +0 -237
  247. package/dist/lib/secrets/unlock-hints.d.ts +0 -27
  248. package/dist/lib/secrets/unlock-hints.js +0 -36
  249. package/dist/lib/secrets/usage-db.d.ts +0 -46
  250. package/dist/lib/secrets/usage-db.js +0 -96
  251. package/dist/lib/secrets/vault-age-helper.d.ts +0 -1
  252. package/dist/lib/secrets/vault-age-helper.js +0 -34
  253. package/dist/lib/secrets/vault.d.ts +0 -49
  254. package/dist/lib/secrets/vault.js +0 -399
  255. package/dist/lib/secrets/windows.d.ts +0 -81
  256. package/dist/lib/secrets/windows.js +0 -556
  257. package/scripts/install-helper.js +0 -97
  258. /package/dist/lib/{secrets/sync-passphrase.d.ts → sync-passphrase.d.ts} +0 -0
  259. /package/dist/lib/{secrets/sync-passphrase.js → sync-passphrase.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,101 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.22.86
4
+
5
+ - **Workers now materialize a slot for every registered Claude account, not only
6
+ the ones added through the v2 `accounts add` flow (PHNX-3940).** The daemon's
7
+ slot reconciliation skipped any account row without a `workerCredential` field —
8
+ every account registered before the v2 model — on the assumption that a legacy
9
+ row "resolves its token at spawn". That holds for `agents run claude#<name>` but
10
+ not for the interactive picker, so on a worker whose `auth` bundle already held
11
+ all eight setup-tokens `agents run claude --interactive --device auto` listed the
12
+ installed version labels, showed most of them `logged out`, and launching one put
13
+ a Claude login screen on a headless box. `reconcileLocalWorkerSlots` now resolves
14
+ each row through the same `reservedSyncTargets` the push plan uses (a v2 row's
15
+ reserved `__claude__` key, a legacy row's email-keyed `auth` token), so every
16
+ account whose token is on the box gets a `durable` slot with a 0600
17
+ `.oauth_token` and the seeded identity the adapter injects from. Two related
18
+ fixes ride along: the credential publisher is now a ready **headed** device
19
+ (`electPublisher`, headed-first then by name) instead of the alphabetically first
20
+ ready box, which had made a worker the fleet's source of truth; and slot
21
+ reconciliation runs first in the `auth-sync` tick, so a failed shared-state git
22
+ exchange no longer postpones local provisioning. Source:
23
+ `cli/src/lib/secrets/reserved-sync.ts`, `cli/src/lib/daemon/auth-sync-service.ts`.
24
+
25
+ - **`agents secrets` no longer recurses into the legacy `secrets` shim after an
26
+ in-place upgrade (PHNX-3989).** Boxes that ran agents-cli before the standalone
27
+ `secrets` engine still carry `~/.agents/.cache/shims/secrets`, a command shim that
28
+ `exec`s `agents secrets`. It sits first on PATH and survives an upgrade because its
29
+ baked entrypoint still exists, and 1.22.85 resolved the standalone with a plain
30
+ `which secrets` — so on every such box `agents secrets …` (and the daemon's
31
+ reserved-store sync, which uses the same resolver) re-entered itself through the
32
+ shim without bound. The resolver now skips agents-cli's own shims dir when looking
33
+ for the standalone (`SECRETS_BIN` still wins; a miss still fails loud with the
34
+ install command), and the self-heal shim pass removes that legacy `secrets` shim
35
+ even though its target install is alive, since it can only recurse. The package's
36
+ postinstall — which used to write that very shim on every install, so an upgrade
37
+ kept bringing it back — no longer writes a `secrets` alias at all and removes one
38
+ a previous install left behind; the bare-command aliases are now `sessions`,
39
+ `browser`, `pty`, and `teams`. Install the standalone with
40
+ `npm i -g @phnx-labs/secrets-cli` if `agents secrets` reports it missing.
41
+
42
+ ## 1.22.85
43
+
44
+ - **`agents run codex` marks an exhausted account so rotation stops re-picking it
45
+ (PHNX-3859).** When a headless codex run ended with `You've hit your usage limit
46
+ … try again at <date>` (or an out-of-credits refusal), that account's throttle
47
+ was never recorded, so the balanced picker kept selecting it from a stale usage
48
+ snapshot and every subsequent run died the same way instead of rotating to a
49
+ healthy sibling. Codex now persists a per-account refusal marker the same way
50
+ Claude already did — the usage cache is identity-keyed and shared across
51
+ harnesses — so `collectRunCandidates` excludes the dead account and picks a
52
+ healthy one. A usage limit is noted with its reset clock (it auto-clears when the
53
+ window resets), a genuine credit/quota exhaustion is noted clock-less (cleared by
54
+ a later successful run), and a limit with no parseable reset is left untouched
55
+ rather than persisted as an unexpirable marker. Source: `cli/src/lib/exec.ts`
56
+ (`classifyCodexRunRefusal`, `parseCodexUsageLimitReset`).
57
+
58
+ - **Account list and view render seams (PHNX-3940).** `agents accounts list <harness>` emits only that harness's group — a provider credential appears under the harnesses it authenticates that match the filter, and empty groups are omitted. `agents view <harness>` prints the ACCOUNT / IDENTITY / STATE / WHERE / USAGE / FIX header once per harness block. USAGE is its own column (bar + percent) between WHERE and FIX; FIX holds only the repair command and stays empty when the verdict is unverified with nothing to run. WHERE reads `this box` when only this device reports, and `accounts list --fleet` names devices whose daemon-state carries no account verdicts (older release) instead of leaving a blank column. `accounts migrate --dry-run` still counts a busy canonical as the kept install and says so. Source: `cli/src/lib/account-catalog.ts`, `cli/src/commands/accounts.ts`, `cli/src/commands/view.ts`, `cli/src/lib/devices/harness-inventory.ts`, `cli/src/lib/accounts/migrate.ts`.
59
+
60
+ - **Account slots and reserved credential stores (PHNX-3940).** Each account is a HOME-shaped slot at `~/.agents/.history/accounts/<harness>/<id>/` (device-doc `deviceAccounts.slots`, never central). A harness-auth capability table covers every installed agent; connect still drives claude/codex from that table. Secrets refuse user bundle names starting with `__`; reserved stores `__<harness>__` accept only a setup-token or API key. The legacy `auth` bundle stays a readable alias. Source: `cli/src/lib/accounts/slots.ts`, `cli/src/lib/harness-auth-capabilities.ts`, `cli/src/lib/secrets/reserved-stores.ts`.
61
+
62
+ - **One managed installation per harness (PHNX-3940, track T2).** `agents add <harness>` now installs or reuses the harness's single managed installation (label `main`) via `ensureHarnessInstallation`; `agents add <harness>@<release>` pins that SAME installation — identical to `agents update <harness> --to <release>` — instead of creating a second home, which now requires `--isolated`. Bare `agents update <harness>` updates the single managed installation (the `@<label>` selector stays for legacy layouts but is hidden from help), `agents view --versions` is a hidden legacy diagnostic, and account credential-slot dirs never appear as installations. Source: `cli/src/lib/installations/store.ts`, `cli/src/commands/versions.ts`, `cli/src/commands/update.ts`, `cli/src/commands/view.ts`.
63
+
64
+ - **Account lists now show live authentication verdicts, fleet coverage, and exact repair commands (PHNX-3940).** `agents accounts list [<harness>]` and `agents view <harness>` share one account-first renderer; `--json` emits the version 2 account schema, and `--fleet` renders accounts by device without exposing reserved credential stores. A provider credential that authenticates a harness appears in that harness's rows (`ready`/`missing`); one no harness uses is listed under Other accounts. Unfiltered `--json` emits one `kind: "provider"` entry per harness the credential authenticates (same `id`, each with its own `harness`), plus one `harness: null` entry for an orphan; a harness filter emits only that harness's entry. The daemon sends one important owner notification when an account changes from live to expired or revoked. Worker usage scope failures are shown as unverified, never as a credit claim.
65
+
66
+ - **`agents accounts add <harness> [name]` is the account onboarding verb (PHNX-3940, track T4).** On a headed device it reuses the harness's one managed installation, creates a HOME-shaped credential slot per account (no second installation), drives the native login into that slot, registers the fleet-wide account row (`provisioning`, `createdOn`), and mints the durable worker credential into the reserved `__<harness>__` store keyed by account id — claude via a `setup-token` drive in the slot (plus the legacy `auth` bundle key this release), codex/grok/cursor/opencode via `--api-key` or an interactive prompt (never derived from OAuth), codex additionally via `--per-device` for a ChatGPT-plan seat; `--no-worker-token` skips the mint with a warning, and an ambient `CLAUDE_CODE_OAUTH_TOKEN` refuses it. Workers are refused before any side effect, with the laptop command and the automatic provisioning named. **`agents accounts login <harness>#<name>`** re-authenticates into the SAME slot (fail-closed on an identity mismatch) and re-mints/re-syncs; a per-device harness (kimi) may log in on any box. **`agents accounts default <harness> [name]`** is the one write path for the per-harness default (picker with no name). The legacy `connect`, `name`, `label`, `mint`, `attach`, `detach`, `switch`, and `set-default` verbs still execute for one release but are hidden from help and print a one-line pointer to their replacement. The provider form `accounts add <name> --provider <p> --auth <t>` is unchanged when the first arg is not a harness id; mixing the forms fails loud as ambiguous. Source: `cli/src/lib/accounts/add.ts` (renamed from `connect.ts`, `runConnect` kept as an alias), `cli/src/lib/auth-mint.ts` (api-key collection flows in `MINT_FLOWS`, `seedReservedStoreKey`, `workerCredentialStoreKey`), `cli/src/commands/accounts.ts`.
67
+
68
+ - **Spawn and rotation read account slots, not extra installations (PHNX-3940, track T5).** `agents run <harness>#<name>` (and `--account`) now sets the spawn HOME to that account's slot on this device; the binary still comes from the one managed install unless `@<label>` pins it. A leftover `acct-*` home still resolves until migration; when no `homes` label was recorded, spawn matches the account's identity against each installed version home's own credential file (the pre-T5 fallback). A worker with the durable key present materializes the slot; a missing slot fails loud with the add/login hint rather than launching into a wrong home. Balanced/available rotation enumerates slots (plus leftover homes) and never launches a slot whose verdict is outside `{live, unverified}`. A routine pinned to a native account forwards `--account` so two slots sharing one managed binary still launch the selected login. The account picker shows account · verdict · usage. Symlink-adopted harnesses (droid, antigravity, gemini, …) hold one active slot per device — `accounts default` either repoints the adopted `~/.<config>` under the auth-op lock or fails loud without writing the default; a run whose adopted symlink does not point at the selected slot fails loud. Remote `--device` forwards `#name` unchanged so the peer resolves its own slot. Config-dir env pins (`GROK_HOME`, `OPENCODE_CONFIG_DIR`, XDG) are stripped so two slots in one install never inherit each other's dir. Source: `cli/src/commands/exec.ts`, `cli/src/lib/exec.ts`, `cli/src/lib/exec-account-home.ts`, `cli/src/lib/accounting/rotate.ts`, `cli/src/lib/daemon/runner.ts`, `cli/src/lib/harness/adapter.ts`.
69
+
70
+ - **Worker provisioning generalized to every portable account, per key and per role (PHNX-3940).** The daemon's `auth-sync` tick no longer syncs only the single legacy `auth` bundle: it plans per ACCOUNT and per KEY (`<ENV>_<accountId>`) over every account's reserved `__<harness>__` store (falling back to the legacy `auth` bundle for a claude row predating the slot model), so a newly-added account propagates to workers within one tick instead of being hidden behind a bundle-coarse "already present" verdict. Pushes target `role=worker` devices only — a headed (`personal`/`desktop`) peer receives the account row but never a durable key (credential-management.md invariant 7). After a key lands on a worker, the daemon materializes a slot for it (`ensureSlot` + the durable write: for claude, `.oauth_token` 0600 + seeded identity; an API-key harness gets a durable slot with no file; a token-less harness gets a per-device slot). An email-only worker slot now resolves its account/org identity from the fleet-synced registry row, so it reads as connected instead of "not connected here". The durable credential moves only over the existing encrypted SSH bundle push and is retained nowhere else; native OAuth/session files are never transported. Source: `cli/src/lib/secrets/reserved-sync.ts`, `cli/src/lib/claude-account-token.ts`, `cli/src/lib/native-accounts.ts`, `cli/src/lib/daemon/auth-sync-service.ts`, `cli/src/lib/agent-spec/agents.ts`.
71
+
72
+ - **Fold leftover per-account installations into one install plus credential slots (PHNX-3940, track T7).** `agents accounts migrate --dry-run` (default) inventories every installation dir per harness and prints the plan; `--apply` moves each credential-bearing unique identity's `home/` into `~/.agents/.history/accounts/<harness>/<id>/`, trashes empty logged-out homes and duplicate identities (reversible via `agents trash restore`), repoints the global default at the canonical install, and re-indexes `sessions.db` paths in the same transaction. The apply manifest is written with the plan before the first move and updated after each one so a crash lists exactly what moved; `agent@label` bindings are rewritten per-target (a duplicate home's binding follows the kept identity) rather than collapsed onto one bare-agent binding. A busy home is deferred, never moved. An ordinary upgrade only prints the dry-run report. `--device <name>` runs the same command on a fleet box. Routines without an explicit `account:` still resolve a provider binding or per-harness default into injected env. Source: `cli/src/lib/accounts/migrate.ts`, `cli/src/commands/accounts.ts`, `cli/src/lib/session/db.ts`, `cli/src/lib/daemon/runner.ts`.
73
+
74
+ - **Account model v2 docs, fleet guidance, and seam cleanups (PHNX-3940).** The credential, version, README, and AGENTS reference now describe the shipped one-managed-installation-plus-account-slots model rather than the pre-v2 per-account installations: `agents accounts add <harness> [name]` is the taught onboarding verb, `accounts connect`/`--versions` read as hidden/legacy, and the "no reserved bundle name" claim in `docs/credential-management.md` is resolved in favor of the code — `auth` is the reserved legacy alias for the `__claude__` store, reserved per-harness stores (`__<harness>__`) hold durable worker credentials, and provider accounts stay their own named bundles. The provisioning model is rewritten around `accounts add` plus the daemon's per-key/per-role reserved-store push (headed devices keep native login; workers receive only the durable key). `cli/AGENTS.md` login remediations teach `accounts login <harness>#<name>` on a headed device. Live FIX hints (`signin-badge` / account catalog empty-state) teach the same verbs — never the hidden `connect` alias. Spawn-home resolution in `docs/execution.md` matches the shipped order including spawn-time worker-slot provisioning and adopted-symlink target verification. Bare `agents update <harness>` now names the isolated/legacy installations it left untouched instead of moving the one managed install silently; `reserved-sync.ts` uses a single `AUTH_STORE_ALIAS` symbol; and the "nothing installed" hint teaches bare `agents add <harness>`. Source: `cli/docs/credential-management.md`, `cli/docs/version-management.md`, `cli/AGENTS.md`, `README.md`, `cli/src/commands/update.ts`, `cli/src/lib/secrets/reserved-sync.ts`, `cli/src/lib/installations/resolve.ts`.
75
+
76
+ - **Process client for the standalone `secrets` CLI (PHNX-3989).** New internal seam `cli/src/lib/secrets-client.ts` — the one bounded request/response client through which agents-cli will talk to the extracted standalone `secrets` executable, over its private fd-3/fd-4 pipe (`secrets __serve`). It resolves the executable (`$SECRETS_BIN`, else `secrets` on PATH; a miss fails loud with `npm i -g @phnx-labs/secrets-cli` and NO fallback to the embedded engine), caches one protocol-version handshake per process, and exposes async (`secretsRequest`) and bounded-sync (`secretsRequestSync`) primitives plus typed wrappers for the bundle/agent/keychain/store/remote/push operations agents-cli consumes. It defaults `SECRETS_HOME` to `~/.agents` so the standalone adopts existing stores in place, and bridges the caller's legacy `AGENTS_SECRETS_PASSPHRASE` onto the renamed `SECRETS_PASSPHRASE` the standalone reads so it can decrypt that same file store. No consumer is converted yet and the embedded engine is untouched — that is the next wave. Source: `cli/src/lib/secrets-client.ts`, `cli/docs/secrets-client.md`.
77
+
78
+ - **`agents secrets` is now a thin passthrough to the standalone `secrets` CLI, and its browser/ssh/apply/sync/webhook/doctor consumers move onto the process client (PHNX-3989).** `agents secrets <anything>` execs the installed `@phnx-labs/secrets-cli` binary verbatim — forwarding argv and flags unmodified, defaulting `SECRETS_HOME` to `~/.agents` so it adopts the existing store in place — and fails loud with `npm i -g @phnx-labs/secrets-cli` install guidance when the executable isn't found; there is no fallback to the in-repo engine (DIST-1). The old `commands/secrets.ts` registrar (and its `secrets-import`/`secrets-migrate`/`secrets-rotate-passphrase`/`secrets-sync`/`secrets-vault` siblings) stays in the tree, unregistered, until every other track's consumers convert. `agents setup secrets` is now install guidance plus a hand-off to the standalone's own interactive `secrets migrate`, dropping the old backend/policy wizard. `browser`, `ssh`, `apply`/`fleet apply`, `sync`, `webhooks serve`, `fleet capture`, `doctor`, and their library dependencies (`lib/browser/chrome.ts`, `lib/share/config.ts`, `lib/daemon-webhooks.ts`, `lib/sync-umbrella.ts`, `lib/fleet/apply.ts`) now resolve bundles, keychain items, and remote-sync pulls through `secrets-client.ts` instead of importing `lib/secrets/*` directly; fleet policy (the reserved `auth` bundle name and backend check) moves to a new agents-owned `lib/secrets-policy.ts` that calls the client rather than the engine. `secrets-client.ts` gains `bundleBackend`, `listRemoteBundles`/`pullBundle`, `scanUserRcFiles`/`masterPassphraseInEnv`, and the pure `secretsKeychainItem`/`keychainRef` naming helpers to cover these call sites. Source: `cli/src/commands/secrets-passthrough.ts`, `cli/src/commands/setup-secrets.ts`, `cli/src/lib/secrets-client.ts`, `cli/src/lib/secrets-policy.ts`, `cli/src/lib/net-close.ts`.
79
+
80
+ - **The run/exec hot path resolves secrets through the standalone `secrets` process client (PHNX-3989).** `agents run --secrets <bundle>` (incl. `--secrets-keys`, `--allow-expired`, and remote `bundle@host`), the crabbox `--lease` provider-token / tailscale reads, the Cursor and Antigravity cloud API-key reads, and the `--lease` Claude credential read now go through `cli/src/lib/secrets-client.ts` instead of the embedded `lib/secrets/*` engine — a missing `secrets` executable fails loud with install guidance, never a silent fallback (DIST-1). Bundle precedence (profile < account < auto-share < bundles < `--env`) and the agents-owned `bundle@host` policy (fleet-alias resolution, flag validation) stay in agents-cli and are passed into the client; behaviour is unchanged. Source: `cli/src/lib/exec.ts` context, `cli/src/commands/exec.ts`, `cli/src/lib/crabbox/{cli,runtimes}.ts`, `cli/src/lib/cloud/{cursor,antigravity}.ts`.
81
+
82
+ - **Accounts, profiles, and the reserved `auth` bundle now go through the standalone `secrets` CLI (PHNX-3989).** `agents accounts` (add / set-key / rename / remove / view / sync / mint), the harness profile token store (`agents harness add --from-secrets`, provider keys, legacy profile-auth migration), `agents lease setup`, the harness wizard's bundle browse, Claude usage/probe setup-token reads, and the Claude OAuth keychain read/write no longer load the embedded secrets engine: every read and write is one call on `cli/src/lib/secrets-client.ts`, which spawns the installed `secrets` executable. The seam is strict — a missing `secrets` fails loud with `npm i -g @phnx-labs/secrets-cli` and there is no fallback to the old engine. Fleet policy stays in agents-cli and is passed in: the reserved `auth` bundle's file-backend rule now lives in `cli/src/lib/secrets/reserved-stores.ts` (a keychain- or vault-backed `auth` still fails loud on read, and the standalone refuses to write one), and the SSH host-pinning guard for credential transport moved to `cli/src/lib/hosts/credential-transport.ts`. The client grew the wrappers these paths need (`renameBundle`, `rotateBundleSecret`, `bundleBackend`, `keychainUsesFileFallback`, sync siblings for the bundle and item writers) plus the raw item-naming helpers (`secretsKeychainItem`, `profileKeychainItem`, `keychainRef`, `parseBundleValue`). Setup-token reads memoize per process for 10 s instead of fingerprinting the engine's on-disk credential file (an in-process mint or rotation clears the memo). The suite installs the pinned published standalone once per machine (`tests/secrets-standalone.ts`, wired through vitest's global setup) and drives it for real — no in-memory keychain. Source: `cli/src/lib/account-registry.ts`, `cli/src/lib/profiles.ts`, `cli/src/lib/auth-mint.ts`, `cli/src/lib/claude-account-token.ts`, `cli/src/commands/accounts.ts`, `cli/src/commands/profiles.ts`.
83
+ - **Read-only status surfaces never hang or crash on a missing/broken `secrets` (PHNX-3989).** The synchronous client (`secretsRequestSync`) does its fd 3/4 wiring in a POSIX shell — request via a FIFO, response redirected onto stdout (`4>&1`) — so it works under the Bun runtime the suite spawns the CLI with (Bun's `spawnSync` drops numbered fds 3+, which had left the standalone deadlocked for 60 s and surfacing as `secrets returned a non-JSON response`). It is bounded to 3 s, and `agents view` / `agents accounts` / the `agents run` account-rotation pool now degrade to one clear line (`secretsUnavailable`) instead of hanging or aborting when the standalone can't answer. A non-JSON reply names the first 200 bytes it got on fd 4, and `SecretsClientError` serializes to a plain `{code, message}` so folding a failure into a `JSON.stringify`'d structure can't throw a circular-reference error. Source: `cli/src/lib/secrets-client.ts`, `cli/src/lib/account-catalog.ts`, `cli/src/lib/accounting/account-pool-collect.ts`, `cli/tests/secrets-standalone.ts`.
84
+
85
+ - **The in-repo secrets engine is gone — the standalone `@phnx-labs/secrets-cli` is the only implementation (PHNX-3989 Track D).** `cli/src/lib/secrets/**` (bundle storage, the broker, the keychain/file/vault backends, the keychain-helper Swift source) and the old `commands/secrets.ts`/`secrets-vault.ts`/`secrets-sync.ts`/`secrets-migrate.ts`/`secrets-import.ts`/`secrets-rotate-passphrase.ts` command files are deleted; every consumer (`account-registry.ts`, `auth-mint.ts`, `claude-account-token.ts`, `exec.ts`, `sync-umbrella.ts`, `crabbox/cli.ts`, `fleet/apply.ts`, `teams/agents.ts`, `devices/doctor-findings.ts`, `session/sync/config.ts`, `commands/{daemon,lease,profiles,sync,exec,repo}.ts`, and more) now resolves through `secrets-client.ts` exclusively. Shared wire types moved to a new pure `secrets-types.ts`; agents-owned reserved-store constants moved to a new leaf `reserved-stores.ts` (kept deliberately dependency-free to avoid a circular import with `secrets-policy.ts`'s fleet-sync helpers, which absorbed `reserved-sync.ts` and gained resource-profile scoping — `resolveSecretsContextForRun`/`resolveAllowedBundlesForActiveProfile`, wired into `agents run --secrets` per CTX-1). **The daemon no longer hosts or takes over the secrets broker (OWN-1):** `secrets-broker-service.ts` and `keychain-reap-service.ts` are deleted, `secrets-broker`/`keychain-reap` are gone from `DaemonServiceId`, and `agents daemon status`/`services` now only probes the broker's reachability (`socketPath`/health always `null`). The `__vault-age-helper`/`__secrets-get`/`__secrets-ping`/`__secrets-lock` intercepts are gone from `index.ts` (now a zero-static-import slim shell), and `bootstrap.ts` no longer reinstalls a keychain helper on upgrade. Release tooling that built/signed/verified the keychain helper (`scripts/build-keychain-helper.sh`, `scripts/verify-keychain-helper.sh`, `scripts/keychain-entitlements.plist`) is deleted, and `release-attestation-produce.sh`/`release.sh`/`release-manifest.sh`/`remote-sign-mac.sh`/`signing-home-base-probe.sh` no longer reference it — a release now signs only the menu-bar helper and the standalone CLI binary. `age-encryption` and the keychain-helper build deps are dropped from `package.json`. A new `scripts/packed-tarball.test.ts` proves the packed tarball ships no `dist/lib/secrets/`, no keychain-helper artifact, and no bundled `.app` of any kind — DIST-1, executed against a real `npm pack` + `tar tzf`, not grepped. Source: `cli/src/lib/{secrets-client,secrets-types,secrets-policy,reserved-stores}.ts`, `cli/src/index.ts`, `cli/src/bootstrap.ts`, `cli/src/lib/daemon/daemon.ts`, `cli/scripts/packed-tarball.test.ts`.
86
+
87
+ - **Workflows sync through one per-harness registry (PHNX-3993).** How each
88
+ workflows-capable harness stores a synced workflow (Claude bundle dir, Kimi flow
89
+ skill, Antigravity global_workflows file, Goose recipe, OpenClaw Lobster, Grok
90
+ Rhai) is declared once in `WORKFLOW_TARGETS`; sync, list, remove, the `agents
91
+ doctor` drift check, and the staleness detector are generic over it, where they
92
+ previously each branched on the harness id and the detector kept its own copy of
93
+ the ownership-marker parsers. Paths, markers, and error text are unchanged; a
94
+ foreign Kimi `<name>/` skill dir now blocks a sync the same way a foreign file
95
+ blocks the other harnesses instead of being written into. A completeness test
96
+ pins the table to `capableAgents('workflows')`. Source:
97
+ `cli/src/lib/workflows-registry.ts`.
98
+
3
99
  ## 1.22.84
4
100
 
5
101
  - **`agents feed watch` is cheap enough to leave running (PHNX-3939).** The watcher
package/README.md CHANGED
@@ -577,12 +577,12 @@ agents:
577
577
  Think `requirements.txt` for CLI coding agents, on steroids. A shim reads `agents.yaml` from the project root and routes `claude` / `codex` / `antigravity` / `grok` (and others) to the right version automatically. Each version gets its own isolated home -- switching backs up config and re-syncs resources.
578
578
 
579
579
  ```bash
580
- agents add claude@2.0.65 # Install a specific version
581
- agents add codex@latest # Install latest
582
- agents add codex@oldest # Install the oldest published version
580
+ agents add claude # Install the one managed installation (taught form)
581
+ agents add claude@2.0.65 # Pin that installation to a specific release (expert)
582
+ agents add codex@latest # Latest published release
583
583
  agents view # See everything installed
584
- agents accounts mint claude --account work # mint a setup-token into a named account
585
- agents run claude --account work
584
+ agents accounts add claude work # headed: login + worker credential + sync
585
+ agents run claude#work
586
586
  ```
587
587
 
588
588
  Multiple provider accounts to juggle? See [Accounts](#accounts) below.
@@ -1151,24 +1151,32 @@ Distinct from **Accounts** below: this is *your human identity*; those are the *
1151
1151
 
1152
1152
  ## Accounts
1153
1153
 
1154
- Choose an agent and an account, independently of its release number. Connect a
1155
- native account once on this device; its home, login, settings, and sessions stay
1156
- in place when the executable is updated.
1154
+ Choose an agent and an account, independently of its release number. Install the
1155
+ harness once; each account is a credential slot of that one install -- login,
1156
+ settings, and sessions stay in place when the executable is updated. Add an
1157
+ account on a headed (personal/desktop) device; workers pick up the durable
1158
+ credential automatically.
1157
1159
 
1158
1160
  ```bash
1159
- agents accounts connect codex work
1160
- agents accounts connect claude personal
1161
- agents accounts switch codex work
1162
- agents run codex#work
1163
- agents view codex # accounts and usage, one row per identity
1164
- agents view codex --versions # every retained installation and actual release
1165
- ```
1166
-
1167
- Connecting another account creates its own isolated home, even when it uses the
1168
- same release. Reconnecting a named account reuses its existing home. Old
1169
- release-named homes are adopted in place: no credential copying, directory moves,
1170
- or automatic duplicate deletion. Native login remains device-local; an account
1171
- known on another device is not necessarily connected here.
1161
+ agents add claude
1162
+ agents accounts add claude work # headed: native login + worker credential + sync
1163
+ agents accounts add codex personal
1164
+ agents accounts login claude#work # re-auth into the same slot
1165
+ agents accounts default claude work
1166
+ agents run claude#work
1167
+ agents accounts list
1168
+ agents view claude # accounts and usage, one row per identity
1169
+ agents view claude --versions # legacy diagnostic: every retained installation and actual release
1170
+ ```
1171
+
1172
+ `accounts add <harness> [name]` reuses the managed install, creates a HOME-shaped
1173
+ slot (no binary), drives the native login there, registers the fleet-wide row, and
1174
+ mints the worker credential (claude: `setup-token`; codex/grok/cursor/opencode:
1175
+ `--api-key` or a prompt). On a worker it refuses before any slot, install, or
1176
+ browser. An already-registered name or identity points at `accounts login`.
1177
+ `accounts login <harness>#<name>` re-auths into the same slot, fails closed on a
1178
+ different identity, and re-mints. Native login stays device-local; an account
1179
+ known on another device is not necessarily logged in here.
1172
1180
 
1173
1181
  Agents checks for updates to safely managed harness installations automatically.
1174
1182
  Disable this globally or per harness with `agents config set updates.auto false`
@@ -1177,30 +1185,44 @@ to inspect eligibility without installing, or `agents update codex` to update
1177
1185
  that harness's installations. Running sessions and deliberately pinned
1178
1186
  installations are protected. See [installation and update policy](cli/docs/version-management.md).
1179
1187
 
1180
- For unattended workers, give a **provider credential** a durable name and reuse it
1181
- across supported harnesses and machines:
1188
+ For a portable **provider credential** (API key / setup-token / bearer), the first
1189
+ arg is the account name, not a harness id:
1182
1190
 
1183
1191
  ```bash
1184
- agents accounts mint claude # drive `claude setup-token`, seed a named account + reserved auth bundle
1185
- agents accounts mint claude --token-stdin # already have a token
1186
1192
  agents accounts add work --provider anthropic --auth setup-token
1187
1193
  agents accounts add gateway --provider openrouter --auth api-key \
1188
1194
  --from-secrets openrouter.ai:OPENROUTER_API_KEY # import from an existing secrets bundle
1189
1195
  agents accounts add deepinfra --provider deepinfra --auth api-key
1190
1196
 
1191
- agents accounts switch claude # picker: usage %, headroom, signed-out / rate-limited
1192
- agents accounts switch claude work # skip the picker; same write as set-default
1193
- agents accounts set-default claude work # claude uses `work` when --account is omitted
1194
- agents accounts sync work --device yosemite-s0 # explicitly copy the bundle to a worker device
1197
+ agents accounts default claude work # claude uses `work` when --account is omitted
1198
+ agents accounts sync work --device yosemite-s0 # copy the bundle to a worker
1195
1199
  agents run claude --account work
1196
1200
  agents harness add deepinfra --account deepinfra
1197
1201
  ```
1198
1202
 
1199
- `agents accounts mint claude` (also `agents auth mint claude`) is the first-class replacement for the mint-auth recipe: it drives `claude setup-token` in a PTY, captures a well-formed `sk-ant-oat01-` token, and seeds both the named account and the reserved file-based `auth` bundle that usage/probe reads. Native rotating OAuth is never copied.
1203
+ Mixing `accounts add <harness>` with `--provider` fails loud as ambiguous. One
1204
+ provider account **is** one `agents secrets` bundle -- `accounts add` creates it
1205
+ with secrets policy `never`, so a background launch never raises Touch ID.
1206
+ Harness-native OAuth stays where the harness put it and is never copied.
1200
1207
 
1201
- One provider account **is** one `agents secrets` bundle -- `agents accounts add` creates it with secrets policy `never`, so a background agent launch on that account never raises Touch ID. `agents accounts` (no subcommand) lists provider bundles next to harness-native signed-in identities so you see both kinds of credential together; `accounts list` / `inspect <name>` / `set-key <name>` (rotate) / `rename` / `remove` manage a bundle by its stable id, independent of its current label. `accounts switch <harness>` is the fast picker over that default -- it writes the same binding as `set-default`, and balanced rotation already honors it.
1208
+ ```bash
1209
+ agents accounts list
1210
+ agents accounts rename claude#work cloud
1211
+ agents accounts logout claude#work
1212
+ agents accounts remove claude#cloud
1213
+ ```
1214
+
1215
+ `accounts list` shows native logins and provider credentials together. `rename` /
1216
+ `remove` / `view` take `<harness>#<name>` when the same name exists on several
1217
+ harnesses; an ambiguous bare name is refused. `logout` signs out a native OAuth
1218
+ login; API-key accounts use `remove`. `accounts sync <name> --device <device>`
1219
+ is the only way a provider credential crosses machines.
1202
1220
 
1203
- Harness-native OAuth logins (Claude Code's own `/login`, `codex login`, and so on) stay exactly where the harness put them -- agi-cli discovers and displays them but never copies, renames, or converts them into a provider bundle. Native `accounts name` / `attach` is only for harnesses agents-cli can isolate today (claude, codex, grok; muse when an email is present). A device-scoped login (kimi, droid, …) is refused with a named reason; provider `accounts add --provider` is unrestricted. Native **labels** (`agents accounts label codex personal`) bind to a stable identityKey on the central account row in `agents.yaml`, which `agents repo push/pull` already syncs fleet-wide, so `codex#personal` selects the same login on every box. `accounts sync <name> --device <device>` is the only way a **provider** account credential crosses machines, and it's explicit: nothing copies OAuth automatically. Selection order for a run is explicit `--account`, then `accounts set-default` / `switch` for that harness, then the harness's native/balanced account behavior.
1221
+ Selection order for a run is explicit `--account` / `<harness>#<name>`, then
1222
+ `accounts default` for that harness, then the harness's native/balanced behavior.
1223
+ The hidden `connect` / `name` / `label` / `mint` / `attach` / `detach` /
1224
+ `switch` / `set-default` verbs are still accepted this release and print their
1225
+ replacement (`add` / `login` / `default` / `run <harness>#<name>`).
1204
1226
 
1205
1227
  ---
1206
1228
 
@@ -1225,23 +1247,25 @@ agents run claude "charge a test card" --secrets prod-stripe
1225
1247
 
1226
1248
  Merge order: profile env < `--secrets` < `--env K=V`. A missing keychain item aborts before the child starts.
1227
1249
 
1228
- ### Cross-machine sync via iCloud Keychain
1250
+ ### Cross-machine sync
1229
1251
 
1230
- Secret bundles sync through iCloud Keychain by default. Sign into the same iCloud account on another Mac (with iCloud Keychain enabled) and the bundle appears there within seconds — no copy-paste, no `.env` files emailed to yourself, no shared secret stores. Pass `--no-icloud-sync` when creating a bundle if it should stay device-local.
1252
+ Secrets are provided by the standalone [`@phnx-labs/secrets-cli`](https://github.com/phnx-labs/secrets-cli)
1253
+ engine (`agents setup secrets` checks whether it's installed). Its `push`/`pull`
1254
+ verbs move a bundle between machines by encrypting it and round-tripping it
1255
+ through `api.prix.dev` — no copy-paste, no `.env` files emailed to yourself:
1231
1256
 
1232
1257
  ```bash
1233
1258
  # On laptop:
1234
1259
  agents secrets create npm-tokens
1235
- agents secrets add npm-tokens NPM_TOKEN # value lives in iCloud Keychain
1260
+ agents secrets add npm-tokens NPM_TOKEN # value lives in the local keychain/file store
1261
+ agents secrets push npm-tokens # encrypt + upload
1236
1262
 
1237
- # On another Mac (same iCloud account):
1238
- agents secrets list # npm-tokens is already there;
1263
+ # On another machine:
1264
+ agents secrets pull npm-tokens # decrypt + restore locally
1239
1265
  agents run claude "..." --secrets npm-tokens # injects NPM_TOKEN automatically
1240
1266
  ```
1241
1267
 
1242
- Under the hood, synced bundles route writes through a notarized helper app (`Agents CLI.app`) that holds the entitlement macOS requires for `kSecAttrSynchronizable`. Bundles created with `--no-icloud-sync` stay device-local.
1243
-
1244
- Bundle definitions sync via iCloud Keychain too — no `agents repo push` needed for secrets, no recreate step on each Mac. Nothing about secrets ever lives in plaintext on disk.
1268
+ Nothing about a secret's value ever lives in plaintext on disk, on either end.
1245
1269
 
1246
1270
  ### Per-secret metadata and rotation
1247
1271
 
@@ -1301,8 +1325,8 @@ some of it is planned (RUSH-2290), and the section marks what is landed vs inten
1301
1325
 
1302
1326
  ### Daemon
1303
1327
 
1304
- Routines, the secrets broker, browser IPC, and the watchdog pass all run inside
1305
- one always-on daemon per device. `agents daemon` is its runtime surface:
1328
+ Routines, browser IPC, and the watchdog pass all run inside one always-on
1329
+ daemon per device. `agents daemon` is its runtime surface:
1306
1330
 
1307
1331
  ```bash
1308
1332
  agents daemon # identity + duplicates + per-service health (same as status)
@@ -1316,9 +1340,9 @@ agents daemon disable # persist daemon.enabled: false -- nothing auto-sta
1316
1340
  agents daemon enable # clear the kill switch
1317
1341
 
1318
1342
  agents daemon reload # SIGHUP -- reload jobs, re-evaluate scheduler.enabled, no restart
1319
- agents daemon services # health of the two hosted services (secrets broker, browser IPC)
1343
+ agents daemon services # health of every hosted service (browser IPC, scheduler, ...)
1320
1344
  agents daemon services list # every toggleable service and its current on/off state
1321
- agents daemon services enable secrets-broker
1345
+ agents daemon services enable scheduler
1322
1346
  agents daemon services disable browser-ipc # stop hosting browser IPC without stopping the daemon
1323
1347
  agents browser stop --service # browser-scoped alias; next browser action requiring IPC re-enables it
1324
1348
  agents routines stop # disable/reload only the scheduler service
@@ -1326,9 +1350,9 @@ agents daemon logs -f --level warn --since 1h
1326
1350
  agents daemon doctor # one-shot health check; non-zero exit on problems
1327
1351
  ```
1328
1352
 
1329
- Each hosted responsibility (secrets broker, browser IPC, scheduler, monitors,
1330
- watchdog, device probe, self-heal, self-update, keychain reap, account-state refresh,
1331
- state-dir checks) is an independent toggle in `~/.agents/daemon/services.yaml`.
1353
+ Each hosted responsibility (browser IPC, scheduler, monitors, watchdog, device
1354
+ probe, self-heal, self-update, account-state refresh, state-dir checks) is an
1355
+ independent toggle in `~/.agents/daemon/services.yaml`.
1332
1356
  Self-update checks npm on its own schedule, installs + verifies a newer
1333
1357
  agents-cli with the same primitives `agents upgrade` uses, then exits so the OS
1334
1358
  supervisor relaunches the daemon onto the new code — the daemon used to run
@@ -1590,7 +1614,7 @@ Extras clone into `~/.agents-system/.repos/<alias>/` and ship the same layout as
1590
1614
 
1591
1615
  ## Security & Privacy
1592
1616
 
1593
- **The CLI binary has no built-in telemetry or phone-home path.** Routine commands run locally; explicit features such as cloud dispatch and iCloud Keychain sync send only the data needed for the action you invoke. Here's exactly what `agi-cli` stores locally and why.
1617
+ **The CLI binary has no built-in telemetry or phone-home path.** Routine commands run locally; explicit features such as cloud dispatch and secrets push/pull send only the data needed for the action you invoke. Here's exactly what `agi-cli` stores locally and why.
1594
1618
 
1595
1619
  ### Event log
1596
1620
 
@@ -1635,14 +1659,17 @@ The index lives at `~/.agents/.history/sessions/sessions.db` (SQLite + FTS5). A
1635
1659
 
1636
1660
  ### Secrets
1637
1661
 
1638
- API keys and credentials are stored in macOS Keychain, never in plaintext files. Bundle definitions also live in Keychain.
1662
+ Secrets are provided by the standalone `@phnx-labs/secrets-cli` engine, stored
1663
+ in the OS keychain or an encrypted file store — never in plaintext files.
1664
+ Bundle definitions live alongside their values.
1639
1665
 
1640
1666
  ```bash
1641
1667
  agents secrets create my-keys
1642
- agents secrets add my-keys API_KEY # Prompts for value, stores in Keychain
1668
+ agents secrets add my-keys API_KEY # Prompts for value, stores in the keychain/file backend
1643
1669
  ```
1644
1670
 
1645
- By default, secrets sync via iCloud Keychain to your other Macs. With `--no-icloud-sync`, they stay device-local. See [Secrets](#secrets) for full usage.
1671
+ Move a bundle to another machine with `secrets push`/`secrets pull` (encrypted
1672
+ round trip through `api.prix.dev`). See [Secrets](#secrets) for full usage.
1646
1673
 
1647
1674
  ### Summary
1648
1675
 
@@ -1650,7 +1677,7 @@ By default, secrets sync via iCloud Keychain to your other Macs. With `--no-iclo
1650
1677
  |------|----------|--------------|---------|
1651
1678
  | Event log | `~/.agents/.cache/logs/` | You only (0600) | `AGENTS_DISABLE_EVENT_LOG=1` |
1652
1679
  | Session index | `~/.agents/.history/sessions/` | You only | Delete the directory |
1653
- | Secrets | macOS Keychain | You + apps you authorize | Don't use `agents secrets` |
1680
+ | Secrets | OS keychain / encrypted file store | You + apps you authorize | Don't use `agents secrets` |
1654
1681
  | Config | `~/.agents/` | You only | N/A |
1655
1682
 
1656
1683
  ---
@@ -1747,7 +1774,7 @@ For full transparency: `agi-cli` keeps a local event log at `~/.agents/.cache/lo
1747
1774
 
1748
1775
  macOS and Linux. Windows via WSL works but isn't first-class yet.
1749
1776
 
1750
- **macOS-only features:** Keychain-based secrets (`agents secrets`, `agents accounts add`) require macOS. Default iCloud sync for bundles requires macOS + iCloud Keychain enabled; use `--no-icloud-sync` for device-local bundles. On Linux, use environment variables or `.env` files for API keys. Native Linux credential store support is planned.
1777
+ **macOS-only features:** `agents accounts add` requires macOS. `agents secrets` itself is cross-platform — macOS Keychain, Linux libsecret, or the `file` backend everywhere, including Windows (non-WSL) via environment variables or a `.env` file as a fallback when neither native store applies.
1751
1778
 
1752
1779
  Interactive runs spawn directly by default. Enable `tmux.enabled` on a device to
1753
1780
  give each run an addressable pane for `agents message`, injection, and `agents
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * Full CLI bootstrap — loaded only after index.ts's argv fast paths miss.
3
3
  *
4
- * RUSH-2335: `src/index.ts` is a slim shell that statically imports only the
5
- * leaf `lib/secrets/sync-commands.js` so `__secrets-*` / `__vault-age-helper` /
6
- * `__shim` / `__daemon-run` can exit without evaluating the
7
- * commander + self-update + command-registry graph (~140ms saved per
8
- * synchronous broker read). Everything below that shell lands here via
9
- * `await import('./bootstrap.js')`.
4
+ * RUSH-2335: `src/index.ts` is a slim shell so `__shim` / `__daemon-run` and
5
+ * the other hidden fast paths can exit without evaluating the commander +
6
+ * self-update + command-registry graph. Everything below that shell lands
7
+ * here via `await import('./bootstrap.js')`. The `__secrets-*` / synchronous
8
+ * broker fast paths that used to justify this shell's one static import moved
9
+ * with the standalone `secrets` engine (PHNX-3989) — `index.ts` now has no
10
+ * static imports at all above this line.
10
11
  *
11
12
  * This module is the previous body of `index.ts` (command registration, update
12
13
  * checks, first-run setup, migrations, parse). Side-effecting top-level code
package/dist/bootstrap.js CHANGED
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * Full CLI bootstrap — loaded only after index.ts's argv fast paths miss.
3
3
  *
4
- * RUSH-2335: `src/index.ts` is a slim shell that statically imports only the
5
- * leaf `lib/secrets/sync-commands.js` so `__secrets-*` / `__vault-age-helper` /
6
- * `__shim` / `__daemon-run` can exit without evaluating the
7
- * commander + self-update + command-registry graph (~140ms saved per
8
- * synchronous broker read). Everything below that shell lands here via
9
- * `await import('./bootstrap.js')`.
4
+ * RUSH-2335: `src/index.ts` is a slim shell so `__shim` / `__daemon-run` and
5
+ * the other hidden fast paths can exit without evaluating the commander +
6
+ * self-update + command-registry graph. Everything below that shell lands
7
+ * here via `await import('./bootstrap.js')`. The `__secrets-*` / synchronous
8
+ * broker fast paths that used to justify this shell's one static import moved
9
+ * with the standalone `secrets` engine (PHNX-3989) — `index.ts` now has no
10
+ * static imports at all above this line.
10
11
  *
11
12
  * This module is the previous body of `index.ts` (command registration, update
12
13
  * checks, first-run setup, migrations, parse). Side-effecting top-level code
@@ -381,27 +382,9 @@ async function installResolvedPackage(metadata) {
381
382
  `The box has the new package but no working \`agents\` — relink manually: ${relink}`);
382
383
  }
383
384
  }
384
- // The npm install above runs with --ignore-scripts, so the postinstall that
385
- // installs the macOS Keychain helper never fires on upgrade. Force-refresh the
386
- // helper here so a user upgrading FROM a broken build (e.g. the entitlement-less
387
- // 1.20.4 helper that fails SecItemAdd with -34018) gets the fixed, signed bundle
388
- // immediately — instead of waiting for the lazy staleness check in
389
- // getKeychainHelperPath() to repair it on their next secret operation. The new
390
- // package is already on disk, so the dynamic import resolves the freshly-installed
391
- // helper module + bundle. Best-effort: an upgrade must never fail because the
392
- // helper could not be reinstalled (the lazy staleness check in
393
- // getKeychainHelperPath() still repairs it on the next secret operation).
394
- if (process.platform === 'darwin') {
395
- try {
396
- const { ensureKeychainHelperInstalledAsync } = await import('./lib/secrets/install-helper.js');
397
- // Async + download-capable: an upgrade to a tarball that dropped the
398
- // bundle fetches the verified release asset instead of no-op'ing.
399
- await ensureKeychainHelperInstalledAsync({ forceReinstall: true });
400
- }
401
- catch {
402
- // Non-fatal.
403
- }
404
- }
385
+ // The macOS Keychain helper this used to force-refresh on upgrade moved with
386
+ // the standalone `secrets` engine (PHNX-3989) — it downloads and verifies its
387
+ // own helper release now, off this CLI's upgrade path entirely.
405
388
  }
406
389
  /** Present an interactive upgrade prompt (TTY) or a one-line hint (non-TTY). */
407
390
  async function promptUpgrade(latestVersion) {
@@ -1214,6 +1197,16 @@ catch (err) {
1214
1197
  console.error(err.message);
1215
1198
  process.exit(1);
1216
1199
  }
1200
+ // The standalone `secrets` CLI is a required external dependency (DIST-1);
1201
+ // when it is missing or a request to it fails, the sync/async client throws
1202
+ // a typed SecretsClientError whose message is user-actionable install
1203
+ // guidance (e.g. SECRETS_BIN_MISSING). Handling it at this choke point means
1204
+ // every call site (doctor, browser, share, …) prints one clear line and
1205
+ // exits 1 instead of dumping a Node stacktrace, without a per-call try/catch.
1206
+ if (err.name === 'SecretsClientError') {
1207
+ console.error(err.message);
1208
+ process.exit(1);
1209
+ }
1217
1210
  }
1218
1211
  throw err;
1219
1212
  }
@@ -60,7 +60,11 @@ export const loadRestore = async () => (await import('../commands/trash.js')).re
60
60
  export const loadDoctor = async () => (await import('../commands/doctor.js')).registerDoctorCommand;
61
61
  export const loadRoute = async () => (await import('../commands/route.js')).registerRouteCommands;
62
62
  export const loadHarness = async () => (await import('../commands/harness.js')).registerHarnessCommands;
63
- export const loadSecrets = async () => (await import('../commands/secrets.js')).registerSecretsCommands;
63
+ // PHNX-3989: `agents secrets` is a thin passthrough to the standalone
64
+ // `secrets` CLI (secrets-passthrough.ts). The legacy in-repo engine and its
65
+ // own command registrar are gone (Track D, tasks.md item 7) — the standalone
66
+ // `@phnx-labs/secrets-cli` package is the only implementation.
67
+ export const loadSecrets = async () => (await import('../commands/secrets-passthrough.js')).registerSecretsCommands;
64
68
  export const loadMenubar = async () => (await import('../commands/menubar.js')).registerMenubarCommands;
65
69
  export const loadSync = async () => (await import('../commands/sync.js')).registerSyncCommand;
66
70
  export const loadRefreshRules = async () => (await import('../commands/refresh-rules.js')).registerRefreshRulesCommand;
@@ -2,6 +2,7 @@ import type { Command } from 'commander';
2
2
  import type { AgentId } from '../lib/types.js';
3
3
  import { collectRunCandidates, type RotateCandidate } from '../lib/accounting/rotate.js';
4
4
  import { type Profile } from '../lib/profiles.js';
5
+ import { type NativeAccountCatalogRow, type ProviderAccountCatalogRow } from '../lib/account-catalog.js';
5
6
  import { type UnifiedAccount } from '../lib/account-registry.js';
6
7
  export declare function nativeIdentityFromSource(raw: string): Promise<{
7
8
  agent: AgentId;
@@ -43,19 +44,11 @@ export declare function parseBundleKey(raw: string): {
43
44
  bundle: string;
44
45
  key: string;
45
46
  };
46
- /** Pure text renderer for `agents accounts list` — grouped, column-aligned, labels first-class. */
47
- export declare function renderAccountList(records: {
48
- name: string;
49
- provider: string;
50
- auth: string;
51
- }[], native: {
52
- agent: AgentId;
53
- name?: string;
54
- display: string;
55
- versions: string[];
56
- isDefault?: boolean;
57
- state?: 'connected' | 'reconnect-needed';
58
- }[]): string;
47
+ /** Compatibility export for tests/consumers; the canonical renderer is shared with view. */
48
+ export declare function renderAccountList(native: NativeAccountCatalogRow[], providers?: ProviderAccountCatalogRow[], opts?: {
49
+ harness?: AgentId;
50
+ localDevice?: string;
51
+ }): string;
59
52
  /** One labelable signed-in identity, folded across every version it is signed into. */
60
53
  export interface LabelIdentity {
61
54
  identityKey: string;