@phnx-labs/agents-cli 1.22.42 → 1.22.43

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 (122) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +1 -1
  3. package/dist/bin/agents +0 -0
  4. package/dist/bootstrap.js +25 -7
  5. package/dist/cli/command-registry.d.ts +0 -3
  6. package/dist/cli/command-registry.js +0 -8
  7. package/dist/commands/alias.d.ts +7 -4
  8. package/dist/commands/alias.js +33 -8
  9. package/dist/commands/auth.js +7 -3
  10. package/dist/commands/computer.js +20 -6
  11. package/dist/commands/daemon.js +1 -1
  12. package/dist/commands/doctor.d.ts +4 -2
  13. package/dist/commands/doctor.js +20 -5
  14. package/dist/commands/exec.js +3 -2
  15. package/dist/commands/feed.js +1 -30
  16. package/dist/commands/harness.js +3 -3
  17. package/dist/commands/monitors.js +1 -1
  18. package/dist/commands/org.js +9 -8
  19. package/dist/commands/profiles.js +2 -2
  20. package/dist/commands/routines.js +43 -25
  21. package/dist/commands/sessions-picker.js +124 -122
  22. package/dist/commands/setup.js +5 -1
  23. package/dist/commands/snapshot.d.ts +1 -1
  24. package/dist/commands/snapshot.js +4 -4
  25. package/dist/commands/status.d.ts +4 -2
  26. package/dist/commands/status.js +10 -7
  27. package/dist/commands/sync.d.ts +1 -0
  28. package/dist/commands/sync.js +29 -2
  29. package/dist/commands/view.js +6 -0
  30. package/dist/commands/webhook.js +1 -1
  31. package/dist/lib/accounting/rotate.d.ts +5 -3
  32. package/dist/lib/accounting/rotate.js +36 -7
  33. package/dist/lib/accounting/usage.d.ts +18 -4
  34. package/dist/lib/accounting/usage.js +138 -27
  35. package/dist/lib/agent-spec/agents.d.ts +7 -7
  36. package/dist/lib/agent-spec/agents.js +15 -15
  37. package/dist/lib/cloud/rush.d.ts +0 -15
  38. package/dist/lib/cloud/rush.js +0 -35
  39. package/dist/lib/crabbox/runtimes.d.ts +6 -2
  40. package/dist/lib/crabbox/runtimes.js +21 -5
  41. package/dist/lib/daemon/daemon.js +86 -58
  42. package/dist/lib/daemon/runner.d.ts +18 -1
  43. package/dist/lib/daemon/runner.js +105 -11
  44. package/dist/lib/devices/doctor-findings.js +1 -1
  45. package/dist/lib/devices/health-report.js +1 -1
  46. package/dist/lib/drift-sync.d.ts +1 -1
  47. package/dist/lib/drift-sync.js +2 -2
  48. package/dist/lib/drift.d.ts +1 -1
  49. package/dist/lib/exec.js +13 -3
  50. package/dist/lib/format.d.ts +9 -0
  51. package/dist/lib/format.js +16 -0
  52. package/dist/lib/github/pr-mergeable.d.ts +49 -0
  53. package/dist/lib/github/pr-mergeable.js +157 -0
  54. package/dist/lib/github/pr-verdict.d.ts +67 -0
  55. package/dist/lib/github/pr-verdict.js +72 -0
  56. package/dist/lib/harness/adapter.d.ts +6 -5
  57. package/dist/lib/hosts/passthrough.d.ts +10 -0
  58. package/dist/lib/hosts/passthrough.js +28 -6
  59. package/dist/lib/hosts/session-index.js +1 -1
  60. package/dist/lib/installations/shims.js +1 -1
  61. package/dist/lib/installations/versions.d.ts +40 -0
  62. package/dist/lib/installations/versions.js +57 -2
  63. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  64. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  65. package/dist/lib/menubar/install-menubar.js +19 -8
  66. package/dist/lib/monitors/config.d.ts +2 -2
  67. package/dist/lib/monitors/config.js +3 -2
  68. package/dist/lib/origin-machine.d.ts +18 -0
  69. package/dist/lib/origin-machine.js +34 -0
  70. package/dist/lib/perf/db.js +1 -1
  71. package/dist/lib/perf/spool.js +1 -1
  72. package/dist/lib/profiles.d.ts +7 -0
  73. package/dist/lib/profiles.js +26 -1
  74. package/dist/lib/sandbox.d.ts +24 -0
  75. package/dist/lib/sandbox.js +101 -0
  76. package/dist/lib/scheduling/routines.d.ts +18 -9
  77. package/dist/lib/scheduling/routines.js +16 -8
  78. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  79. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  80. package/dist/lib/secrets/agent.js +9 -1
  81. package/dist/lib/secrets/index.js +1 -1
  82. package/dist/lib/secrets/list-filter.js +1 -1
  83. package/dist/lib/service-manifest.d.ts +20 -0
  84. package/dist/lib/service-manifest.js +34 -0
  85. package/dist/lib/session/cloud.js +1 -1
  86. package/dist/lib/session/db.js +1 -1
  87. package/dist/lib/session/fork.js +1 -1
  88. package/dist/lib/session/live-metadata.js +1 -1
  89. package/dist/lib/session/origin-machine.d.ts +1 -18
  90. package/dist/lib/session/origin-machine.js +4 -34
  91. package/dist/lib/session/relative-time.d.ts +1 -44
  92. package/dist/lib/session/relative-time.js +4 -120
  93. package/dist/lib/session/remote-list.js +1 -1
  94. package/dist/lib/session/remote.js +2 -2
  95. package/dist/lib/session/short-id.d.ts +1 -17
  96. package/dist/lib/session/short-id.js +4 -20
  97. package/dist/lib/session/width.d.ts +1 -29
  98. package/dist/lib/session/width.js +4 -101
  99. package/dist/lib/snapshot.d.ts +2 -2
  100. package/dist/lib/snapshot.js +1 -1
  101. package/dist/lib/startup/command-registry.d.ts +4 -1
  102. package/dist/lib/startup/command-registry.js +11 -4
  103. package/dist/lib/teams/placement-probe.js +1 -1
  104. package/dist/lib/teams/scheduler.js +1 -1
  105. package/dist/lib/text/relative-time.d.ts +44 -0
  106. package/dist/lib/text/relative-time.js +120 -0
  107. package/dist/lib/text/short-id.d.ts +17 -0
  108. package/dist/lib/text/short-id.js +20 -0
  109. package/dist/lib/text/width.d.ts +29 -0
  110. package/dist/lib/text/width.js +101 -0
  111. package/dist/lib/triggers/handlers.d.ts +7 -0
  112. package/dist/lib/triggers/handlers.js +8 -0
  113. package/dist/lib/triggers/webhook.d.ts +1 -0
  114. package/dist/lib/triggers/webhook.js +2 -1
  115. package/dist/lib/view-types.d.ts +4 -0
  116. package/package.json +1 -1
  117. package/dist/commands/tickets.d.ts +0 -2
  118. package/dist/commands/tickets.js +0 -43
  119. package/dist/lib/observe-aliases.d.ts +0 -30
  120. package/dist/lib/observe-aliases.js +0 -38
  121. package/dist/lib/tickets/list.d.ts +0 -53
  122. package/dist/lib/tickets/list.js +0 -153
package/CHANGELOG.md CHANGED
@@ -1,5 +1,77 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.22.43
4
+
5
+ - **Rush Cloud no longer has a helper that reads the interactive Claude login (RUSH-2359 / incident #1767).** Dispatch already sends an email-only account manifest (SING-1b) and never uploaded a token; the leftover `readClaudeCredentialsBlob` still read Keychain / `.credentials.json` — the exact shape that captured a `claude setup-token` TTY banner as an Authorization header. That helper is deleted. `--lease` SING-1b detection now reads the wrapped rotating blob itself and ignores anything that is not `{ claudeAiOauth.accessToken }`. Source: `apps/cli/src/lib/cloud/rush.ts`, `apps/cli/src/lib/crabbox/runtimes.ts`.
6
+
7
+ - **fix: `agents sync <agent>` self-heals version pointers left aimed at an uninstalled version (RUSH-2471).** `removeVersion` reassigns the default and clears the `~/.<agent>` config symlink only when it removes the pointed-at version, so a version-home whose launch binary vanished by any other route — grok self-updating its per-version binary out from under the old dir, a manual delete, a half-finished install that seeded the home but never landed the binary — left the global default and/or the symlink resolving to a dead version. Because `agents use <agent>@<v>` sets the default and the symlink together, both dangled in lockstep once `<v>`'s binary went away: `agents sync <agent>` would print `Repointed <agent> config symlink …` and then still fail `<agent>@<v> is not installed`, because the version to sync is resolved from the raw global default. `agents sync <agent>` now repoints the global default, the isolated default, and the config symlink off any not-installed version before resolving — the default to the newest non-isolated installed version (never auto-promoting an isolated install), the symlink to the resolved default else the newest non-isolated installed version (the user's real `~/.<agent>` is never repointed at an isolated install). A pointer already on an installed version (a deliberate `agents use` choice), a real config directory, and isolated-only agents are left untouched. Source: `apps/cli/src/lib/installations/versions.ts`, `apps/cli/src/commands/sync.ts`.
8
+
9
+ - **Session preview groups metadata into verb-led rows (RUSH-2757, part 3).** `agents sessions preview` (and the picker pane) replaces the flat labeled block (`Prompt/Todos/Dirs/Repos/Changes/Artifacts/Skills/Plugins/Hooks/Links/Errors/Meta/Tools/Tests`) with five scannable verb rows in a fixed gutter — `Asked` (the originating prompt, quoted), `Doing` (checklist progress, team lineage, sub-agents), `Made` (file deltas, reads, artifacts, plan, PR), `Health` (errors + last test verdict, absent when clean), `Cost` (msgs, tokens, tool mix) — then `Latest` (the full wrapped last message, formerly `Last response:`) and one width-capped `Details ▸` fold (session id, skills, plugins, hooks, links, dirs, repos) that shows `… +N more` instead of wrapping and swamping the pane. Msgs/tokens/session-id move out of the header's third line into `Cost`/`Details`, so they render once. The metadata-only card (remote/unindexed sessions) uses the same rows. Source: `apps/cli/src/commands/sessions-picker.ts` (`formatCompactPreview`, `formatMetaOnlyBody`, `formatHeader`, `joinWidthCapped` — now ANSI-aware).
10
+
11
+ - **`pr-merge-on-green` can actually select a PR (RUSH-2848).** The built-in's poll ran `gh pr list --author @me` with no `--repo`, so `gh` inferred the repository from cwd; the daemon's cwd is not a git repo and every poll returned empty. The poll now walks registered project slugs (`~/.agents/projects/*.yaml`), canonicalizes renamed repos (`phnx-labs/agents-cli` → `phnx-labs/agi-cli`), and lists with `--repo`. Verdict matches `merge-guard.sh`: a formal GitHub `APPROVED` review **or** an APPROVE comment on THIS PR (carried-from citations do not count). Hidden `agents _internal mergeable-prs` prints `owner/repo#n` (cwd-independent). Source: `apps/cli/src/lib/github/pr-verdict.ts`, `apps/cli/src/lib/github/pr-mergeable.ts`. Companion: phnx-labs/.agents-system#347.
12
+
13
+ - **BREAKING: nest `agents status` under `agents sync status` (RUSH-2864).** `status` was the unified sync-drift report sitting as its own top-level command next to `sync`. It now lives as `agents sync status` (`--json` UnifiedSyncStatus contract and `--yes` reconcile unchanged). Top-level `agents status` is gone, not deprecated: it reports `unknown command`, and `status` is retired from distance-1 auto-correct. `agents sync <agent>` still treats the positional as an agent spec; `status` is reserved as the subcommand. `agents sync status --device` from a non-TTY does not inherit umbrella `--yes` (that flag is reconcile on this command, not "don't prompt"). Source: `apps/cli/src/commands/{status,sync}.ts`, `apps/cli/src/lib/hosts/passthrough.ts`, `apps/cli/src/lib/startup/command-registry.ts`.
14
+
15
+ - **Custom harnesses (deepseek, kimi-chat, glm, …) now work in routines and monitors, and their profiles survive fleet sync (RUSH-2930).** `agents routines add --agent deepseek` and `agents monitors add --run deepseek` used to refuse any name outside the native registry; both now accept a custom harness (`agents harness list`), and the daemon delegates the job to `agents run <name>` — the same path workflow jobs take — so the profile's host binary, model env, and provider auth resolve exactly as an interactive run. The profile pins its own host version and auth, so `@version` pins, balanced rotation, and account-env injection don't apply to these jobs. Separately, `agents harness add/fork/edit` and the legacy-auth migration stored the account's per-device **id** in the profile, while profiles sync fleet-wide via `agents repo push` — every synced custom harness then died on other machines with `Unknown account '<uuid>'`. The portable account **name** is stored now, and a profile with a dangling ref reports which harness is broken and the exact `agents harness edit <name> --account <name>` repair instead of the bare registry error. Source: `apps/cli/src/lib/daemon/runner.ts`, `apps/cli/src/lib/scheduling/routines.ts`, `apps/cli/src/lib/monitors/config.ts`, `apps/cli/src/commands/{routines,harness,profiles}.ts`, `apps/cli/src/lib/profiles.ts`.
16
+
17
+ - **BREAKING: remove the top-level `agents tickets` command (RUSH-2932).** Ticket reads go through `linear` (linear-cli) and `gh issue`. `agents tickets` reports `unknown command`, and `tickets` is retired from distance-1 auto-correct. AGI EXT now calls those CLIs directly. Source: `apps/cli/src/cli/command-registry.ts`, `apps/cli/src/lib/startup/command-registry.ts`, `apps/ext/src/vscode/tasks.vscode.ts`.
18
+
19
+ - **Expired cached usage windows read as unknown, not 0% (RUSH-2936).** A cached Claude usage window whose reset time had passed was zeroed but kept, so a frozen cache (Anthropic has been 429-ing `/api/oauth/usage` per account since ~Aug 5) rendered every account as `S: 0% (now) W: 0% (now)` with `usageStatus: "available"` — and balanced rotation kept dispatching into genuinely rate-limited accounts (RUSH-2858). `deserializeClaudeUsageSnapshot` now drops expired windows (the same rule the Grok collector already applied); an all-expired snapshot deserializes to null, the dead cache entry self-cleans, `agents view` renders `usage unavailable` plus the recorded throttle reason, and rotation falls back to the coarse cached status instead of trusting a fake 0%. Source: `apps/cli/src/lib/accounting/usage.ts`.
20
+
21
+ - **`agents doctor <agent>@<version>` no longer marks every missing resource critical (RUSH-2947).** Target mode's `computeVerdict` hardcoded `severity: 'critical'` for any `status: 'missing'` resource of any kind, while fleet mode's `FINDING_SEVERITY` — whose own docblock calls it "the single source of truth" — rates the same fact `warning` for everything except `missing-hook`/`missing-plugin`. A missing command, skill, permission, subagent, rule, or MCP entry now reads `warning` in target mode too, matching fleet mode; a missing hook or plugin stays `critical` in both. `computeVerdict` reads severity from `FINDING_SEVERITY` via a new `missingResourceSeverity(kind)` helper instead of re-hardcoding it. Source: `apps/cli/src/commands/doctor.ts`.
22
+
23
+ - **BREAKING: nest `agents alias` under `agents setup alias` (RUSH-2965).** Setting up a PATH shorthand is a setup action, not its own noun. `agents setup alias add/list/remove` keep the same shim behavior (`~/.agents/.cache/shims/` + `~/.agents/aliases.json`). Top-level `agents alias` is gone, not deprecated: it reports `unknown command`, and `alias` is retired from distance-1 auto-correct. Source: `apps/cli/src/commands/{alias,setup}.ts`, `apps/cli/src/lib/startup/command-registry.ts`.
24
+
25
+ - **Block service-manager registration under a redirected HOME on macOS/Linux (RUSH-2968).**
26
+ `launchctl` and `systemctl --user` are per-user-session and ignore `$HOME`, so a CLI
27
+ running under a sandbox/redirected HOME (including every vitest fork) still talked to
28
+ the user's real service manager. `service-manifest.ts` already namespaces the job
29
+ label, but that only changes the identifier — the registration still lands in real
30
+ `launchd`/`systemd` (measured: 89 dead `…sandbox-<hash>` services accumulated in one
31
+ user's real launchd from test runs, KeepAlive-retrying torn-down executables). Every
32
+ registration path now consults `serviceManagerRegistrationAllowed()` (false when
33
+ `isolatedHomeSuffix()` is non-null) and skips with a stated reason rather than
34
+ touching the real service manager: daemon `startDaemon`/`stopDaemon`, menubar
35
+ `restartMenubarLaunchAgent`/`disableMenubarService`, secrets
36
+ `retireLegacySecretsAgentService`, and `agents computer start`. A test seam
37
+ `AGENTS_SERVICE_MANAGER_ALLOW_REDIRECTED_HOME=1` lets the existing shim-based tests
38
+ continue to exercise the registration code path. Source:
39
+ `apps/cli/src/lib/service-manifest.ts`, `apps/cli/src/lib/daemon/daemon.ts`,
40
+ `apps/cli/src/lib/menubar/install-menubar.ts`, `apps/cli/src/lib/secrets/agent.ts`,
41
+ `apps/cli/src/commands/computer.ts`.
42
+
43
+ - **BREAKING: the top-level `agents inbox` command is removed — use `agents feed` (RUSH-2984).** `inbox` was a Phase-3 observe alias that re-parsed as `agents feed` (needs-you is already the feed default), the same leftover class as `timeline` (RUSH-2692). It is gone entirely, not deprecated: `agents inbox` now reports `unknown command`, and `inbox` is retired from distance-1 auto-correct. `agents feed` / `feed post` / `feed post --blocked` are unchanged. Source: `apps/cli/src/commands/feed.ts`, `apps/cli/src/lib/startup/command-registry.ts`, `apps/cli/src/bootstrap.ts`.
44
+
45
+ - `agents auth` and `agents org` now print a clean one-line error (and a structured `{"error"}` payload under `--json`) for signed-out, expired-token, and bad-input states, instead of dumping a raw Node stack trace.
46
+
47
+ - Fixed balanced Claude account rotation recording session-limit refusals until their stated reset, skipping those accounts, and surfacing `session-limited` in `agents view` instead of idle usage.
48
+
49
+ - Sandboxed monitor `--run` and routine children now inherit this host's GitHub CLI auth (RUSH-2860). A monitor fire recorded `ok` while the spawned child had no `~/.config/gh`, so `gh auth status` reported "not logged into any GitHub hosts" and the PR it was meant to act on stayed open. The routine sandbox overlay replaces `HOME` with a disposable dir, and `gh` was never linked into it. `prepareJobHome` now links the host's `gh` config dir into the overlay (and only that — `~/.agents` is deliberately not linked, since it holds the secrets master key and the encrypted store), `buildSpawnEnv` pins `GH_CONFIG_DIR` and forwards `GH_TOKEN`/`GITHUB_TOKEN`, and the runner refuses to launch when a routine's own `env:` overrides `GH_CONFIG_DIR` such that this host's gh auth would still be hidden — a regression tripwire rather than a runtime guarantee. Not covered on Windows, where `gh` stores config under `%AppData%\GitHub CLI`.
50
+
51
+ - **`agents webhooks` now advertises `/hooks/slack`.** The receiver has accepted signed
52
+ Slack deliveries since the Slack bridge landed, but `agents webhooks serve` and
53
+ `agents daemon webhooks list` still printed only `/hooks/github, /hooks/linear` — the
54
+ one URL you must paste into the Slack app was missing from the banner. The slash-command
55
+ ack now also says "replying in this channel", matching where the reply actually posts
56
+ (a slash command carries no thread). Source: `apps/cli/src/commands/webhook.ts`,
57
+ `apps/cli/src/commands/daemon.ts`, `apps/cli/src/lib/triggers/webhook.ts`.
58
+
59
+ - **Slack/webhook handlers that run an agent actually dispatch now.** A `run.agent` or
60
+ `run.workflow` webhook handler was gated by the *routine* activation manifest
61
+ (`~/.agents/devices/<machine>/agents.yaml`). A handler is not a routine, so its name
62
+ could never be a member — on any box that had materialized that manifest, every
63
+ delivery was recorded `skipped` with an empty allowlist (`can only run on: `) while the
64
+ receiver logged it as `fired`, and `agents routines enable <handler>` refuses the name,
65
+ so there was no way out. Verified live: a real HMAC-signed `/agents` slash command
66
+ reached the public receiver, acked 200, and started no agent. The job now carries
67
+ `dispatchedBy: 'webhook'`, the same escape RUSH-2681 gave monitors; a handler's
68
+ `routine:` delegate still keeps its gate.
69
+ - **`{{slack.response_url}}` is now available to handler prompts.** It was parsed off the
70
+ wire but never reached the `{{slack.*}}` namespace. Slack accepts a POST there for 30
71
+ minutes with no token and no channel membership, so it is the only reply that works
72
+ before the app has been invited to a channel — the shipped example handler now uses it.
73
+ Source: `apps/cli/src/lib/triggers/handlers.ts`, `apps/cli/src/lib/scheduling/routines.ts`.
74
+
3
75
  ## 1.22.42
4
76
 
5
77
  - **Plan-tier gates for `agents accounts` and `agents insights` (RUSH-2424).** A new `apps/cli/src/lib/entitlement.ts` reads the live subscription tier from `GET /api/v1/billing/subscription?agent=agi-cli` (the session token in `~/.rush/user.yaml`), caches it on disk for 15 minutes, and stays offline-tolerant: a stale cache is honored over a failed network call, and no session file at all resolves straight to the free tier. `agents accounts add` / `name` / `attach` now cap registered accounts at 3 per harness on free, 10 on paid/admin — a 4th add on free refuses before any write (`free plan is capped at 3 claude accounts (3/3). agents upgrade — up to 10 per harness.`) and the 3rd prints a one-line notice. Downgrading a plan never deletes a credential: over-cap accounts fall out of `accounts switch`/`set-default` (excluded from `listSwitchableAccounts`) and are listed `dormant (upgrade to reactivate)` in `agents accounts`. `agents insights` keeps top-line counts, harness mix, `insights mix`, and `agents perf` free on every tier; the Friction / Friction-thrash / Dissatisfaction-corrections sections, grouping `--by account` (the default), and `--narrative` are paid — a gated section is replaced by the in-voice notice `Friction and account-split analysis are on the paid plan.` in both the text report and `--json` (a new `plan: {tierName, isPaid}` field, `groups: null` when the account breakdown is gated, and the friction/correction facet keys stripped per group otherwise). Source: `apps/cli/src/lib/entitlement.ts`, `apps/cli/src/commands/accounts.ts`, `apps/cli/src/commands/insights.ts`.
package/README.md CHANGED
@@ -190,7 +190,7 @@ agents run claude@
190
190
  agents run codex@ "review this branch"
191
191
  ```
192
192
 
193
- `--strategy balanced` spreads work across available versions of the same agent -- useful when you have multiple accounts and want to avoid burning through one. When every account is rate-limited, the run exits nonzero naming each excluded account and the earliest window reset (use `--strategy pinned` to force the default) -- it never launches into an exhausted account.
193
+ `--strategy balanced` spreads work across available versions of the same agent -- useful when you have multiple accounts and want to avoid burning through one. When a Claude run reports a session limit, agents-cli records the stated reset time, shows `session-limited` in `agents view`, and excludes that account until the reset. When every account is rate-limited, the run exits nonzero naming each excluded account and the earliest window reset (use `--strategy pinned` to force the default) -- it never launches into an exhausted account.
194
194
 
195
195
  ### Don't care which harness? `agents run auto`
196
196
 
package/dist/bin/agents CHANGED
Binary file
package/dist/bootstrap.js CHANGED
@@ -256,12 +256,12 @@ Run and dispatch:
256
256
  pty Drive interactive terminal programs (REPLs, TUIs) via a persistent PTY session
257
257
  artifacts Publish what an agent made (plans, reports, visuals) to a shareable link
258
258
 
259
- Observe (read the fleet — no store merge; aliases point at the real readers):
260
- feed / inbox Needs-you inbox (open blocks waiting on you)
259
+ Observe (read the fleet — no store merge):
260
+ feed Needs-you inbox (open blocks waiting on you); agent posts = feed --filter updates
261
261
  sessions --active Live agents (who is running right now)
262
262
  events Unified ops + activity event trail
263
263
  audit Tamper-evident run-dispatch log (not events)
264
- status Sync/drift only (not the live fleet snapshot)
264
+ sync status Sync/drift only (not the live fleet snapshot)
265
265
  devices snapshot One-process inventory + active sessions poll
266
266
 
267
267
  Credentials:
@@ -726,10 +726,13 @@ function registerHqTombstoneCommand(p) {
726
726
  }
727
727
  /**
728
728
  * Hidden `agents _internal <sub>` namespace for machine-to-machine calls that
729
- * are not user-facing. The first subcommand is `friction`, used by shell guard
730
- * hooks (git-guard, rm-guard, …) to self-report a block into the event log
731
- * before they exit 2 they run before any `agents` process exists, so they
732
- * cannot emit in-process.
729
+ * are not user-facing. Subcommands:
730
+ * - `friction` — shell guard hooks (git-guard, rm-guard, …) self-report a
731
+ * block into the event log before they exit 2; they run before any
732
+ * `agents` process exists, so they cannot emit in-process.
733
+ * - `mergeable-prs` — the `pr-merge-on-green` built-in poll. Prints
734
+ * `owner/repo#n` for this user's CI-green, non-author-approved open PRs
735
+ * (cwd-independent `--repo`). Empty stdout is a silent observation.
733
736
  */
734
737
  function registerInternalCommand(p) {
735
738
  const internal = p.command('_internal', { hidden: true });
@@ -749,6 +752,21 @@ function registerInternalCommand(p) {
749
752
  });
750
753
  process.exit(0);
751
754
  });
755
+ internal
756
+ .command('mergeable-prs')
757
+ .description('Print owner/repo#n for CI-green, non-author-approved open PRs (pr-merge-on-green poll)')
758
+ .action(async () => {
759
+ try {
760
+ const { listMergeableRefs } = await import('./lib/github/pr-mergeable.js');
761
+ const refs = await listMergeableRefs();
762
+ if (refs)
763
+ process.stdout.write(`${refs}\n`);
764
+ }
765
+ catch {
766
+ // Empty observation — never write stderr (command.ts would treat it
767
+ // as the poll result and fire `mode: every` on the error text).
768
+ }
769
+ });
752
770
  }
753
771
  /** Runtime action for the shared `agents upgrade [version]` command definition. */
754
772
  async function runUpgrade(version, options) {
@@ -57,7 +57,6 @@ export declare const loadTrash: ModuleLoader;
57
57
  export declare const loadRestore: ModuleLoader;
58
58
  export declare const loadDoctor: ModuleLoader;
59
59
  export declare const loadApply: ModuleLoader;
60
- export declare const loadStatus: ModuleLoader;
61
60
  export declare const loadRoute: ModuleLoader;
62
61
  export declare const loadHarness: ModuleLoader;
63
62
  export declare const loadSecrets: ModuleLoader;
@@ -70,7 +69,6 @@ export declare const loadUsage: ModuleLoader;
70
69
  export declare const loadInsights: ModuleLoader;
71
70
  export declare const loadPerf: ModuleLoader;
72
71
  export declare const loadTrends: ModuleLoader;
73
- export declare const loadAlias: ModuleLoader;
74
72
  export declare const loadPty: ModuleLoader;
75
73
  export declare const loadTmux: ModuleLoader;
76
74
  export declare const loadWatchdog: ModuleLoader;
@@ -85,7 +83,6 @@ export declare const loadUninstall: ModuleLoader;
85
83
  export declare const loadUpgrade: ModuleLoader;
86
84
  export declare const loadSessions: ModuleLoader;
87
85
  export declare const loadTeams: ModuleLoader;
88
- export declare const loadTickets: ModuleLoader;
89
86
  export declare const loadCloud: ModuleLoader;
90
87
  export declare const loadMessage: ModuleLoader;
91
88
  export declare const loadSend: ModuleLoader;
@@ -59,7 +59,6 @@ export const loadTrash = async () => (await import('../commands/trash.js')).regi
59
59
  export const loadRestore = async () => (await import('../commands/trash.js')).registerRestoreCommand;
60
60
  export const loadDoctor = async () => (await import('../commands/doctor.js')).registerDoctorCommand;
61
61
  export const loadApply = async () => (await import('../commands/apply.js')).registerApplyCommand;
62
- export const loadStatus = async () => (await import('../commands/status.js')).registerStatusCommand;
63
62
  export const loadRoute = async () => (await import('../commands/route.js')).registerRouteCommands;
64
63
  export const loadHarness = async () => (await import('../commands/harness.js')).registerHarnessCommands;
65
64
  export const loadSecrets = async () => (await import('../commands/secrets.js')).registerSecretsCommands;
@@ -73,7 +72,6 @@ export const loadInsights = async () => (await import('../commands/insights.js')
73
72
  export const loadPerf = async () => (await import('../commands/perf.js')).registerPerfCommand;
74
73
  // Thin deprecated alias of `agents insights mix` — no second mix implementation.
75
74
  export const loadTrends = async () => (await import('../commands/trends.js')).registerTrendsCommand;
76
- export const loadAlias = async () => (await import('../commands/alias.js')).registerAliasCommand;
77
75
  export const loadPty = async () => (await import('../commands/pty.js')).registerPtyCommands;
78
76
  export const loadTmux = async () => (await import('../commands/tmux.js')).registerTmuxCommands;
79
77
  export const loadWatchdog = async () => (await import('../commands/watchdog.js')).registerWatchdogCommand;
@@ -88,7 +86,6 @@ export const loadUninstall = async () => (await import('../commands/uninstall.js
88
86
  export const loadUpgrade = async () => (await import('../commands/upgrade.js')).registerUpgradeCommand;
89
87
  export const loadSessions = async () => (await import('../commands/sessions.js')).registerSessionsCommands;
90
88
  export const loadTeams = async () => (await import('../commands/teams.js')).registerTeamsCommands;
91
- export const loadTickets = async () => (await import('../commands/tickets.js')).registerTicketsCommand;
92
89
  export const loadCloud = async () => (await import('../commands/cloud.js')).registerCloudCommands;
93
90
  export const loadMessage = async () => (await import('../commands/message.js')).registerMessageCommand;
94
91
  export const loadSend = async () => (await import('../commands/send.js')).registerSendCommand;
@@ -179,7 +176,6 @@ export const COMMAND_LOADERS = {
179
176
  restore: [loadRestore],
180
177
  doctor: [loadDoctor],
181
178
  apply: [loadApply],
182
- status: [loadStatus],
183
179
  route: [loadRoute],
184
180
  harness: [loadHarness],
185
181
  harnesses: [loadHarness],
@@ -193,7 +189,6 @@ export const COMMAND_LOADERS = {
193
189
  insights: [loadInsights],
194
190
  perf: [loadPerf],
195
191
  trends: [loadTrends],
196
- alias: [loadAlias],
197
192
  pty: [loadPty],
198
193
  tmux: [loadTmux],
199
194
  watchdog: [loadWatchdog],
@@ -216,14 +211,11 @@ export const COMMAND_LOADERS = {
216
211
  upgrade: [loadUpgrade],
217
212
  sessions: [loadSessions],
218
213
  teams: [loadTeams],
219
- tickets: [loadTickets],
220
214
  cloud: [loadCloud],
221
215
  message: [loadMessage],
222
216
  send: [loadSend],
223
217
  notify: [loadSend],
224
218
  feed: [loadFeed],
225
- // Observe-umbrella alias of feed (the `timeline` alias was removed in RUSH-2692).
226
- inbox: [loadFeed],
227
219
  mailboxes: [loadMailboxes],
228
220
  mailbox: [loadMailboxes],
229
221
  serve: [loadServe],
@@ -1,11 +1,14 @@
1
1
  /**
2
- * Alias command -- create top-level shim binaries that expand to `agents <subcommand>`.
2
+ * `agents setup alias` -- create top-level shim binaries that expand to
3
+ * `agents <subcommand>`. Nested under setup because the user is configuring
4
+ * this machine's PATH shortcuts, not operating a separate noun (RUSH-2965).
3
5
  *
4
- * Generates executable scripts in ~/.agents/shims/ (already on PATH from the
5
- * standard agents-cli install). Running `teams` becomes equivalent to
6
+ * Generates executable scripts in ~/.agents/.cache/shims/ (already on PATH from
7
+ * the standard agents-cli install). Running `teams` becomes equivalent to
6
8
  * `agents teams`. Aliases are tracked in ~/.agents/aliases.json so we can
7
9
  * list, regenerate, or remove them without scanning the shims directory
8
10
  * (which also holds agent CLI shims like claude/codex/gemini).
9
11
  */
10
12
  import type { Command } from 'commander';
11
- export declare function registerAliasCommand(program: Command): void;
13
+ /** Register `agents setup alias` under the parent `setup` command. */
14
+ export declare function registerAliasCommand(setupCmd: Command): void;
@@ -4,7 +4,10 @@ import * as path from 'path';
4
4
  import { getUserAgentsDir } from '../lib/state.js';
5
5
  import { getShimsDir } from '../lib/installations/shims.js';
6
6
  import { ALL_AGENT_IDS, AGENTS } from '../lib/agents.js';
7
- const ALIASES_FILE = path.join(getUserAgentsDir(), 'aliases.json');
7
+ import { setHelpSections } from '../lib/help.js';
8
+ function aliasesFile() {
9
+ return path.join(getUserAgentsDir(), 'aliases.json');
10
+ }
8
11
  /** Names that would clobber an agent CLI shim or the `agents` binary itself. */
9
12
  function reservedNames() {
10
13
  const reserved = new Set(['agents']);
@@ -13,10 +16,11 @@ function reservedNames() {
13
16
  return reserved;
14
17
  }
15
18
  function readAliases() {
16
- if (!fs.existsSync(ALIASES_FILE))
19
+ const file = aliasesFile();
20
+ if (!fs.existsSync(file))
17
21
  return {};
18
22
  try {
19
- const parsed = JSON.parse(fs.readFileSync(ALIASES_FILE, 'utf-8'));
23
+ const parsed = JSON.parse(fs.readFileSync(file, 'utf-8'));
20
24
  return parsed && typeof parsed === 'object' ? parsed : {};
21
25
  }
22
26
  catch {
@@ -24,8 +28,9 @@ function readAliases() {
24
28
  }
25
29
  }
26
30
  function writeAliases(map) {
27
- fs.mkdirSync(path.dirname(ALIASES_FILE), { recursive: true });
28
- fs.writeFileSync(ALIASES_FILE, JSON.stringify(map, null, 2) + '\n', 'utf-8');
31
+ const file = aliasesFile();
32
+ fs.mkdirSync(path.dirname(file), { recursive: true });
33
+ fs.writeFileSync(file, JSON.stringify(map, null, 2) + '\n', 'utf-8');
29
34
  }
30
35
  function shimPath(name) {
31
36
  return path.join(getShimsDir(), name);
@@ -46,10 +51,30 @@ function isAliasShim(filePath) {
46
51
  return false;
47
52
  }
48
53
  }
49
- export function registerAliasCommand(program) {
50
- const cmd = program
54
+ /** Register `agents setup alias` under the parent `setup` command. */
55
+ export function registerAliasCommand(setupCmd) {
56
+ const cmd = setupCmd
51
57
  .command('alias')
52
58
  .description('Create shorthand binaries that expand to `agents <subcommand>`');
59
+ setHelpSections(cmd, {
60
+ examples: `
61
+ # Make \`teams\` run \`agents teams\`
62
+ agents setup alias add teams
63
+
64
+ # Shorthand for a longer expansion
65
+ agents setup alias add sess sessions preview
66
+
67
+ agents setup alias list
68
+ agents setup alias remove teams
69
+ `,
70
+ notes: `
71
+ Writes an executable shim into ~/.agents/.cache/shims/ (already on PATH after
72
+ \`agents setup\`) and records it in ~/.agents/aliases.json.
73
+
74
+ Names that collide with the agents binary or an agent CLI (claude, codex,
75
+ grok, …) are refused. Top-level \`agents alias\` is gone — use this group.
76
+ `,
77
+ });
53
78
  cmd
54
79
  .command('add <name> [expansion...]')
55
80
  .description('Create an alias shim. If expansion is omitted, defaults to <name>.')
@@ -106,7 +131,7 @@ export function registerAliasCommand(program) {
106
131
  const map = readAliases();
107
132
  const entries = Object.entries(map);
108
133
  if (entries.length === 0) {
109
- console.log(chalk.gray('No aliases. Try: agents alias add teams'));
134
+ console.log(chalk.gray('No aliases. Try: agents setup alias add teams'));
110
135
  return;
111
136
  }
112
137
  const width = entries.reduce((max, [n]) => Math.max(max, n.length), 0);
@@ -1,5 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { setHelpSections } from '../lib/help.js';
3
+ import { runOrDie } from '../lib/format.js';
3
4
  import { clearPrixSession, fetchWhoAmI, pollDeviceToken, PrixApiError, readPrixSession, resolvePrixToken, startDeviceAuthorization, writePrixSession, } from '../lib/prix-account.js';
4
5
  function sleep(ms) {
5
6
  return new Promise(resolve => setTimeout(resolve, ms));
@@ -90,10 +91,13 @@ function runAuthLogout() {
90
91
  }
91
92
  export function registerAuthCommand(program) {
92
93
  const auth = program.command('auth').description('Sign in to your Rush account (shared by `agents org` and paid tiers)');
93
- auth.command('login').description('Sign in via the device-code flow').action(async () => runAuthLogin());
94
+ auth.command('login').description('Sign in via the device-code flow').action(() => runOrDie(() => runAuthLogin()));
94
95
  auth.command('whoami').description('Show the signed-in account').option('--json', 'Machine-readable output')
95
- .action((o, command) => runAuthWhoami(!!(o.json || command.optsWithGlobals().json)));
96
- auth.command('logout').description('Clear the local `agents auth login` session').action(() => runAuthLogout());
96
+ .action((o, command) => {
97
+ const json = !!(o.json || command.optsWithGlobals().json);
98
+ return runOrDie(() => runAuthWhoami(json), { json });
99
+ });
100
+ auth.command('logout').description('Clear the local `agents auth login` session').action(() => runOrDie(() => runAuthLogout()));
97
101
  setHelpSections(auth, {
98
102
  examples: `agents auth login
99
103
  agents auth whoami
@@ -14,7 +14,7 @@ import { makeClaudeResponder, resolveApiKey, DEFAULT_CLAUDE_MODEL, DEFAULT_CLAUD
14
14
  import { TASK_PREVIEW_MAX_CHARS } from '../lib/computer/sessions-list.js';
15
15
  import { runComputerSessionsCommand } from './computer-sessions-picker.js';
16
16
  import { truncate } from '../lib/feed/events.js';
17
- import { namespacedServiceLabel, serviceManifestHomeEnv } from '../lib/service-manifest.js';
17
+ import { namespacedServiceLabel, serviceManifestHomeEnv, serviceManagerRegistrationAllowed } from '../lib/service-manifest.js';
18
18
  // Help groups — mirror `agents browser` so the mental model carries over.
19
19
  const COMPUTER_HELP_GROUPS = [
20
20
  { title: 'Installation', names: ['setup'] },
@@ -564,6 +564,10 @@ export async function activateComputerHelperMacLocal() {
564
564
  const uid = process.getuid?.();
565
565
  if (typeof uid !== 'number')
566
566
  throw new Error('cannot resolve uid');
567
+ const reg = serviceManagerRegistrationAllowed();
568
+ if (!reg.allowed) {
569
+ throw new Error(reg.reason);
570
+ }
567
571
  const domain = `gui/${uid}`;
568
572
  // Render the policy file BEFORE bootstrap so the daemon reads a fresh allow
569
573
  // list at startup (fail-safe: missing/unparseable → everything denied).
@@ -843,11 +847,21 @@ function registerStopCommand(program) {
843
847
  process.exit(1);
844
848
  }
845
849
  const domain = `gui/${uid}`;
846
- try {
847
- execFileSync('/bin/launchctl', ['bootout', domain, plistPath], { stdio: 'pipe' });
848
- }
849
- catch {
850
- // already gone — fine
850
+ // Same invariant as the start path: a redirected-HOME process must never
851
+ // talk to the real launchd (RUSH-2968). Stop has a local fallback the
852
+ // plist/socket cleanup below — so skip the bootout with the reason
853
+ // rather than throwing like start does.
854
+ const reg = serviceManagerRegistrationAllowed();
855
+ if (!reg.allowed) {
856
+ console.warn(`skipping launchctl bootout: ${reg.reason}`);
857
+ }
858
+ else {
859
+ try {
860
+ execFileSync('/bin/launchctl', ['bootout', domain, plistPath], { stdio: 'pipe' });
861
+ }
862
+ catch {
863
+ // already gone — fine
864
+ }
851
865
  }
852
866
  // launchd unlinks the socket when the daemon exits; helper also has an
853
867
  // atexit unlink. Best-effort cleanup if either path didn't fire.
@@ -761,7 +761,7 @@ function runWebhooksList(json) {
761
761
  const port = hostedReceiverPort(r);
762
762
  const funnel = r.funnel ? chalk.cyan(` public :${r.funnel.publicPort}`) : chalk.gray(' localhost only');
763
763
  console.log(` 127.0.0.1:${String(port).padEnd(6)} ${chalk.gray(`bundle ${r.bundle}`)}${funnel}`);
764
- console.log(chalk.gray(` endpoints: /hooks/github, /hooks/linear · ${r.rateLimit ?? DEFAULT_WEBHOOK_RATE_LIMIT}/min per source`));
764
+ console.log(chalk.gray(` endpoints: /hooks/github, /hooks/linear, /hooks/slack · ${r.rateLimit ?? DEFAULT_WEBHOOK_RATE_LIMIT}/min per source`));
765
765
  }
766
766
  console.log(chalk.gray(`\nConfig: ${getDaemonWebhooksConfigPath()}`));
767
767
  console.log(chalk.gray('Changes take effect on the next daemon restart.'));
@@ -78,9 +78,11 @@ export type IssueSeverity = 'critical' | 'warning' | 'info';
78
78
  *
79
79
  * Severity model (agent-agnostic — applies to every agent doctor inspects):
80
80
  * - critical (silent breakage): an unwired hook, a missing/unparseable
81
- * settings.json, a MISSING resource.
81
+ * settings.json, a MISSING hook or plugin.
82
82
  * - warning (stale / drift): a source layer behind origin, a DIVERGENT resource,
83
- * a stale / never-synced version.
83
+ * a stale / never-synced version, a MISSING resource of any other kind
84
+ * (see `missingResourceSeverity`, which reads this split from
85
+ * `FINDING_SEVERITY` — RUSH-2947).
84
86
  * - info (orphan): an EXTRA resource → `agents prune cleanup`.
85
87
  */
86
88
  export interface VerdictIssue {
@@ -669,6 +669,19 @@ const AUTO_FIXABLE_CATEGORIES = new Set([
669
669
  export function verdictIsAutoFixable(v) {
670
670
  return v.issues.some((i) => AUTO_FIXABLE_CATEGORIES.has(i.category));
671
671
  }
672
+ /**
673
+ * Missing-resource severity for one `DoctorKind`, read from `FINDING_SEVERITY`
674
+ * (the fleet-mode rubric) so target mode agrees with it kind by kind instead of
675
+ * re-hardcoding its own. Hooks and plugins map to their dedicated critical
676
+ * finding kinds; every other kind maps to the generic 'missing-resource' warning.
677
+ */
678
+ function missingResourceSeverity(kind) {
679
+ if (kind === 'hooks')
680
+ return FINDING_SEVERITY['missing-hook'];
681
+ if (kind === 'plugins')
682
+ return FINDING_SEVERITY['missing-plugin'];
683
+ return FINDING_SEVERITY['missing-resource'];
684
+ }
672
685
  /**
673
686
  * Fold a version report's divergences into a triaged verdict — one severity-tagged
674
687
  * finding per unwired hook, missing/divergent/extra resource, and behind-origin
@@ -718,16 +731,18 @@ export function computeVerdict(report) {
718
731
  });
719
732
  }
720
733
  }
721
- // ── critical: missing resources (declared in sources, absent from home) ──
734
+ // ── missing resources (declared in sources, absent from home) — severity
735
+ // follows FINDING_SEVERITY: hooks/plugins are critical, everything else warns ──
722
736
  for (const kind of DOCTOR_ALL_KINDS) {
723
737
  for (const r of report.kinds[kind]) {
724
738
  if (r.status !== 'missing')
725
739
  continue;
740
+ const severity = missingResourceSeverity(kind);
726
741
  issues.push({
727
- severity: 'critical', category: 'missing', subject: r.name,
742
+ severity, category: 'missing', subject: r.name,
728
743
  impact: `declared in sources but absent from the version home (${kind})`,
729
744
  fix: fixCmd,
730
- text: `${r.name} missing`, color: 'red',
745
+ text: `${r.name} missing`, color: severity === 'critical' ? 'red' : 'yellow',
731
746
  });
732
747
  }
733
748
  }
@@ -1739,10 +1754,10 @@ export function registerDoctorCommand(program) {
1739
1754
  console.log(line);
1740
1755
  }
1741
1756
  // Point at the interactive reconcile when anything is out of sync — each
1742
- // finding carries its own fix, but `agents status` is the one place that
1757
+ // finding carries its own fix, but `agents sync status` is the one place that
1743
1758
  // reviews and applies them together (opt-in, never auto-fires here).
1744
1759
  if (syncRows.some((r) => r.status !== 'fresh' || (r.unwiredHooks ?? 0) > 0) || repoBehindMarkers.some((m) => m.behind > 0)) {
1745
- console.log(chalk.gray('\nRun `agents status` to review and sync what has drifted.'));
1760
+ console.log(chalk.gray('\nRun `agents sync status` to review and sync what has drifted.'));
1746
1761
  }
1747
1762
  // A routine runs on exactly one device. Each of these named several and
1748
1763
  // used to fire once per device — duplicate agent runs on every schedule.
@@ -3015,8 +3015,9 @@ agents run auto --device yosemite-s0 "fix the flaky test" # pin the device
3015
3015
  let exitCode;
3016
3016
  let ranAgent = agent;
3017
3017
  let ranVersion = defaultVersion;
3018
- if (fallback.length > 0) {
3019
- // fallback requires a prompt enforced above, narrow the type here.
3018
+ if (fallback.length > 0 || (rotationResult !== null && prompt !== undefined && !options.interactive)) {
3019
+ // Fallback and balanced runs need captured output so a clean-exit
3020
+ // session-limit refusal can update account availability.
3020
3021
  // The sink reports which chain entry actually executed (may differ from
3021
3022
  // the primary after a rate-limit handoff) so the audit record is honest.
3022
3023
  const sink = {};
@@ -312,7 +312,7 @@ export async function loadSessionMetasForFeedEnrichment(load) {
312
312
  export function registerFeedCommand(program) {
313
313
  const feed = program
314
314
  .command('feed')
315
- .description('Operator inbox + agent status posts (alias: inbox = needs-you). Agent progress = --filter updates')
315
+ .description('Operator inbox + agent status posts. Default is needs-you; agent progress = --filter updates')
316
316
  .option('--json', 'Output as JSON (each block stamped with its outcome + ask class)')
317
317
  .option('--filter <view>', 'What to show: needs (default) · updates · all', 'needs')
318
318
  .option('--flat', 'List one block per agent instead of grouping by outcome')
@@ -642,35 +642,6 @@ export function registerFeedCommand(program) {
642
642
  renderOutcomeGroup(g, self);
643
643
  await renderTrailingActivity();
644
644
  });
645
- // Observe-umbrella aliases (Phase 3): intentional second names, not deprecations.
646
- // Re-parse into `feed` so flags/help stay single-sourced. See lib/observe-aliases.ts.
647
- registerFeedObserveAliases(program);
648
- }
649
- /**
650
- * `inbox` → feed. Loaded with the feed module so the lazy COMMAND_LOADERS entry
651
- * for `inbox` also gets the real `feed` command registered for re-parse.
652
- */
653
- function registerFeedObserveAliases(program) {
654
- const reparse = async (alias) => {
655
- const { expandObserveAlias } = await import('../lib/observe-aliases.js');
656
- const rest = process.argv.slice(3);
657
- const expanded = expandObserveAlias(alias, rest);
658
- if (!expanded) {
659
- console.error(chalk.red(`Unknown observe alias: ${alias}`));
660
- process.exit(1);
661
- }
662
- if (process.stderr.isTTY)
663
- process.stderr.write(chalk.gray(`${expanded.note}\n`));
664
- await program.parseAsync(['node', 'agents', ...expanded.argv]);
665
- };
666
- program
667
- .command('inbox')
668
- .description('Needs-you inbox (alias of `agents feed`). Open blocks waiting on you.')
669
- .allowUnknownOption()
670
- .allowExcessArguments()
671
- .action(async () => {
672
- await reparse('inbox');
673
- });
674
645
  }
675
646
  /**
676
647
  * Mirror a written post to the configured sinks (`feed.broadcast` in
@@ -73,7 +73,7 @@ export function buildFork(source, name, opts) {
73
73
  const account = findAccount(opts.account);
74
74
  if (!account)
75
75
  throw new Error(`Unknown account '${opts.account}'.`);
76
- profile.account = account.id;
76
+ profile.account = account.name;
77
77
  profile.provider = account.provider;
78
78
  }
79
79
  return profile;
@@ -97,7 +97,7 @@ export function buildFork(source, name, opts) {
97
97
  const account = findAccount(opts.account);
98
98
  if (!account)
99
99
  throw new Error(`Unknown account '${opts.account}'.`);
100
- profile.account = account.id;
100
+ profile.account = account.name;
101
101
  profile.provider = account.provider;
102
102
  }
103
103
  return profile;
@@ -162,7 +162,7 @@ export function buildEdit(name, opts) {
162
162
  const account = findAccount(opts.account);
163
163
  if (!account)
164
164
  throw new Error(`Unknown account '${opts.account}'.`);
165
- edited.account = account.id;
165
+ edited.account = account.name;
166
166
  edited.provider = account.provider;
167
167
  }
168
168
  if (opts.version === '')
@@ -440,7 +440,7 @@ export function registerMonitorsCommands(program) {
440
440
  .option('--dedupe-key <expr>', 'Regex whose first match is the "same event" signature (default: full output)')
441
441
  .option('--every', 'Fire on every observation (no dedupe) — rate-limit this')
442
442
  // ACTION
443
- .option('--run <agent>', 'Spawn an agent (claude, codex, ...) with the prompt on fire')
443
+ .option('--run <agent>', 'Spawn an agent (claude, codex, ..., or a custom harness from agents harness list) with the prompt on fire')
444
444
  .option('--prompt <prompt>', 'Prompt for --run; {event} is replaced with the fired event')
445
445
  .option('--mode <mode>', 'Execution mode for --run: plan, edit, auto, or skip')
446
446
  .option('--effort <effort>', 'Reasoning effort for --run: low | medium | high | xhigh | max | auto')