@phnx-labs/agents-cli 1.22.58 → 1.22.59
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.
- package/CHANGELOG.md +238 -0
- package/README.md +29 -0
- package/dist/bootstrap.js +32 -1
- package/dist/commands/monitors.js +187 -23
- package/dist/commands/routines.test-fixture.js +5 -0
- package/dist/commands/send.d.ts +2 -1
- package/dist/commands/send.js +7 -5
- package/dist/commands/sessions-stats.js +37 -5
- package/dist/commands/sessions.js +39 -5
- package/dist/commands/ssh.js +12 -1
- package/dist/commands/versions.js +12 -4
- package/dist/commands/view.js +7 -2
- package/dist/lib/auto-pull-worker.js +7 -2
- package/dist/lib/cloud/rush.d.ts +7 -0
- package/dist/lib/cloud/rush.js +29 -1
- package/dist/lib/daemon/daemon.d.ts +22 -0
- package/dist/lib/daemon/daemon.js +39 -0
- package/dist/lib/daemon/session-index-service.js +9 -1
- package/dist/lib/daemon-ticks.d.ts +15 -0
- package/dist/lib/daemon-ticks.js +26 -0
- package/dist/lib/device-config.d.ts +5 -1
- package/dist/lib/device-config.js +2 -2
- package/dist/lib/devices/health.js +5 -1
- package/dist/lib/devices/pool.d.ts +25 -2
- package/dist/lib/devices/pool.js +32 -2
- package/dist/lib/devices/stats-cache.d.ts +0 -6
- package/dist/lib/devices/stats-cache.js +2 -9
- package/dist/lib/doctor-diff.d.ts +14 -0
- package/dist/lib/doctor-diff.js +43 -2
- package/dist/lib/git.d.ts +38 -0
- package/dist/lib/git.js +58 -0
- package/dist/lib/hosts/ready.d.ts +8 -0
- package/dist/lib/hosts/ready.js +13 -2
- package/dist/lib/installations/versions.d.ts +17 -0
- package/dist/lib/installations/versions.js +53 -2
- package/dist/lib/monitors/config.d.ts +71 -3
- package/dist/lib/monitors/config.js +100 -12
- package/dist/lib/monitors/pid-watch.d.ts +35 -0
- package/dist/lib/monitors/pid-watch.js +45 -0
- package/dist/lib/monitors/remote.d.ts +18 -0
- package/dist/lib/monitors/remote.js +11 -0
- package/dist/lib/permissions.js +7 -2
- package/dist/lib/plugins/plugins.d.ts +17 -3
- package/dist/lib/plugins/plugins.js +84 -9
- package/dist/lib/pty-server.d.ts +14 -0
- package/dist/lib/pty-server.js +49 -5
- package/dist/lib/secrets/drivers/rush.js +5 -0
- package/dist/lib/self-update.d.ts +42 -0
- package/dist/lib/self-update.js +88 -0
- package/dist/lib/session/cloud.js +5 -0
- package/dist/lib/session/db.d.ts +32 -6
- package/dist/lib/session/db.js +128 -12
- package/dist/lib/smart-launch.d.ts +6 -0
- package/dist/lib/smart-launch.js +5 -2
- package/dist/lib/staleness/writers/plugins.js +5 -2
- package/dist/lib/staleness/writers/subagents.js +13 -3
- package/dist/lib/state.d.ts +7 -4
- package/dist/lib/state.js +7 -4
- package/dist/lib/subagents.js +8 -2
- package/dist/lib/teams/scheduler.d.ts +10 -0
- package/dist/lib/teams/scheduler.js +8 -0
- package/dist/lib/traces/sync.d.ts +113 -6
- package/dist/lib/traces/sync.js +193 -19
- package/dist/lib/view-types.d.ts +12 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,245 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.22.59
|
|
4
|
+
|
|
5
|
+
- **`agents devices disable/prefer` now actually change `--device auto` placement (PHNX-2092).**
|
|
6
|
+
The per-device `auto-launch.enabled` / `auto-launch.preferred` flags (written by
|
|
7
|
+
`agents devices disable/enable` and `prefer/unprefer`, and by `agents devices config
|
|
8
|
+
<name> auto-launch.*`) were stored and synced but never consulted by the CLI's one
|
|
9
|
+
placement path, so a disabled box was still picked and a preferred box got no boost.
|
|
10
|
+
They now feed the single automatic-placement rule: `filterAutoPool` drops any device
|
|
11
|
+
with `auto-launch.enabled` = false from EVERY auto path (`run`, `teams`, `ssh auto`,
|
|
12
|
+
the AGI EXT launch commands, which resolve placement through the CLI) exactly as a
|
|
13
|
+
`personal`/`desktop` role does, and `pickBestDevice` ranks an `auto-launch.preferred`
|
|
14
|
+
device ahead of its load-equal peers — after the signed-in tier, before load, so an
|
|
15
|
+
operator boost overrides load-based ordering without overriding hard health. A
|
|
16
|
+
fleet-wide default (`--fleet`) reaches doc-less devices via the candidate roster. No
|
|
17
|
+
second placement path was added — the existing `filterAutoPool`/`pickBestDevice`
|
|
18
|
+
rule was extended. Source: `cli/src/lib/devices/pool.ts`,
|
|
19
|
+
`cli/src/lib/teams/scheduler.ts`, `cli/src/lib/smart-launch.ts`.
|
|
20
|
+
|
|
21
|
+
- **`agents sessions stats` coverage now reports scan coverage, not with-usage,
|
|
22
|
+
so a completed backfill clears the "run the backfill" hint (PHNX-2301).** The
|
|
23
|
+
coverage line read `sessionsWithUsage / sessionsIndexed` — a ratio that stays
|
|
24
|
+
near-zero (~1.2% on a real fleet) even after `agents sessions backfill
|
|
25
|
+
resources` has fully run, because most sessions genuinely invoke no
|
|
26
|
+
skill/slash-command and a non-recording harness contributes none by
|
|
27
|
+
construction. The nag therefore never cleared and the low number read as a
|
|
28
|
+
coverage bug when it was not. `resourceUsageCoverage()` now also returns
|
|
29
|
+
`scanned` — the count of sessions carrying a `resource_scan_ledger` row at the
|
|
30
|
+
current `RESOURCE_INDEX_VERSION`, the honest "has the backfill folded in
|
|
31
|
+
history?" signal (the ledger is stamped for EVERY scanned session, including
|
|
32
|
+
ones that invoked nothing). The human line shows both — `N/T sessions scanned ·
|
|
33
|
+
M carry an explicit invocation` — and the backfill hint keys on
|
|
34
|
+
`scanned/total`, so it appears only when history really is un-scanned. The
|
|
35
|
+
`--json` `coverage` object gains `sessionsScanned` alongside the unchanged
|
|
36
|
+
`sessionsWithUsage`/`sessionsIndexed` (SES-IF-4b envelope preserved;
|
|
37
|
+
`schemaVersion` bumped to 2), and `signal.recording` now names the recorded set
|
|
38
|
+
(`skills: claude+kimi`, `commands: claude`) so a machine consumer can tell a
|
|
39
|
+
zero from a non-recording harness apart from genuine non-use. The zero-invoked
|
|
40
|
+
heading reads "never explicitly invoked" to match. Recording coverage itself is
|
|
41
|
+
unchanged — extending the `Skill`-tool set to another harness needs a verified
|
|
42
|
+
transcript tool-name, not a blind capability-table edit. Source:
|
|
43
|
+
`cli/src/lib/session/db.ts` (`resourceUsageCoverage`),
|
|
44
|
+
`cli/src/commands/sessions-stats.ts`.
|
|
45
|
+
|
|
46
|
+
- **Menu bar: favorite (pin) devices below the current Mac (PHNX-2376).** Each
|
|
47
|
+
device's submenu in the menu bar's DEVICES section now has a **★ Favorite /
|
|
48
|
+
Unfavorite** toggle. A favorited device renders with a ★ and sorts immediately
|
|
49
|
+
below the current machine (`<name> (this Mac)`), above all other devices, with a
|
|
50
|
+
divider between the favorites and the rest. "Favorite" reuses the EXISTING
|
|
51
|
+
per-device `auto-launch.preferred` config that automatic placement already
|
|
52
|
+
honors (PHNX-2092) — the toggle writes `agents devices config <name>
|
|
53
|
+
auto-launch.preferred on|off`, not a new store — so a box favorited from the
|
|
54
|
+
menu bar is also boosted in `--device auto` placement, and vice-versa. Source:
|
|
55
|
+
`cli/menubar/Sources/MenubarHelper/StatusItemController.swift`,
|
|
56
|
+
`cli/menubar/Sources/MenubarHelper/AgentsCLI.swift`.
|
|
57
|
+
|
|
58
|
+
- **Built-in monitors ship visible + enabled, `monitors list` is fleet-aware, and built-ins are tagged `(built-in)` (PHNX-2506).** A monitor shipped in the system mirror (`~/.agents/.system/monitors/`) used to be the lone system-layer resource that shipped **disabled and untagged** — `readMonitorFile` special-cased system scope to `enabled: false`, so a shipped built-in read `off` on every install and nobody could tell it came from the system layer. It now defaults to enabled like every other system resource (rules, hooks, commands, skills), on for every install unless the user shadows it with `enabled: false` (via `agents monitors pause`, which materializes a user copy — the system mirror stays pull-only; there is deliberately no `enable`/`disable` verb). Each monitor now carries its read-time `scope` (`user`/`system`), so `agents monitors list` tags a built-in `(built-in)` and `--json` emits `scope` + `builtin`, mirroring routines. And `agents monitors list` now **fans out across the fleet** (the same `gatherRemoteAgentsJson` sweep `sessions --active` and the add-time duplicate guard use), so every monitor on every device is visible with the box it lives on — the original "monitors shouldn't be device-local" complaint was a **visibility** gap, not a git-sync one (monitors are per-work-item watchers and are deliberately NOT synced through the DotAgents repo). `--local` pins the listing to this device; a peer answering the fan-out reports itself only, so the duplicate guard's bare-array contract is unchanged. **Enabled-by-default is not, on its own, permission to fire on every daemon (SING-9a).** A shared-input built-in — one whose source polls a fleet-shared queue such as `gh pr list --author @me`, `pr-merge-on-green` being the canonical case — is placed on a single owner **in code**, not just by a `device:` pin in the shipped YAML: an unpinned `scope: system` monitor is treated as shared-input unless it sets `sharedInput: false`, and fires only on the resolved owner (`interactive.host`, else the sole box on a single-device fleet, else nowhere) via `requiresSingleOwner` / `monitorRunsOnThisDevice`. So even a built-in whose YAML forgot the pin can never fan out across the fleet and race to merge the same PR. A device-local built-in (input = the firing box's own state) opts back into fleet-wide firing with `sharedInput: false`; a user monitor keeps its fleet-wide default and opts into owner-only with `sharedInput: true`. Source: `cli/src/lib/monitors/config.ts`, `cli/src/lib/monitors/remote.ts`, `cli/src/commands/monitors.ts`, `cli/src/lib/state.ts`.
|
|
59
|
+
|
|
60
|
+
- **A version-home plugin left behind by a marketplace move is now reconciled
|
|
61
|
+
away instead of shadowing the current copy (PHNX-2618).** Plugin orphan
|
|
62
|
+
detection keyed on plugin **name** alone, but a version home installs plugins
|
|
63
|
+
per **marketplace** (`marketplaces/<name>/plugins/<plugin>`). When a plugin
|
|
64
|
+
moved marketplaces — e.g. `code` once shipped from the user repo (the
|
|
65
|
+
`agents-cli` marketplace) and later from the system repo (`agents-system`) —
|
|
66
|
+
the stale `agents-cli` copy was never cleaned, because the name `code` was
|
|
67
|
+
still active via `agents-system`. Fleet boxes then carried **two** `code`
|
|
68
|
+
plugins: the current one, plus a shadow serving skills the repo deleted on
|
|
69
|
+
purpose (`code:quality` / `code:ship` / `code:verify`), and resolution order
|
|
70
|
+
decided which `code:review` an agent got. `cleanOrphanedPluginSkills` /
|
|
71
|
+
`diffVersionPlugins` now key on the `(marketplace, name)` pair: an installed
|
|
72
|
+
copy whose marketplace source repo is present but no longer ships that plugin
|
|
73
|
+
is trashed (soft-deleted to `~/.agents/.trash/plugins/`), even when another
|
|
74
|
+
marketplace still ships the same name — so a plain `agents sync` reconciles the
|
|
75
|
+
shadow away. When a marketplace's source repo is **absent** (a project we're
|
|
76
|
+
not in, a removed extra repo) the original name-only test is kept, so an
|
|
77
|
+
unrelated sync from another cwd never trashes a plugin whose source simply is
|
|
78
|
+
not reachable right now. Source: `cli/src/lib/plugins/plugins.ts`
|
|
79
|
+
(`cleanOrphanedPluginSkills`, `diffVersionPlugins`, `isOrphanMarketplacePlugin`),
|
|
80
|
+
`cli/src/lib/staleness/writers/plugins.ts`,
|
|
81
|
+
`cli/src/lib/installations/versions.ts`.
|
|
82
|
+
|
|
83
|
+
- **`agents sessions --device all/fleet --json` now actually searches the whole fleet (PHNX-2673).** The documented "search the whole fleet" sentinel was filtered to an empty host set — correct for `--active` and the interactive listing, which fan out by default — but the HISTORICAL `--json` listing does not fan out by default (it stays a deterministic local slice for scripts), so the sentinel was silently dropped and a fleet-wide historical query returned local rows only. Naming devices explicitly (`--device box-a --device box-b`) reached the fleet; `--device all` did not. The `--json` listing path now remembers the sentinel and runs the SAME peer SSH sweep the interactive listing uses (`gatherRemoteList` over the registered online devices, whole-index per peer), merging peer rows in machine-first. A bare `--json` (no `--device`) stays local-only, `--local` still pins to this machine, and dead peers are skipped, never fatal. Source: `cli/src/commands/sessions.ts`.
|
|
84
|
+
|
|
85
|
+
- **`agents pty` now works on macOS/arm64 and Node 25/26 (PHNX-2740).** The pinned
|
|
86
|
+
`@homebridge/node-pty-prebuilt-multiarch@0.13.1` shipped no darwin-arm64 prebuild
|
|
87
|
+
above Node 24 (ABI 137), so on a Mac running Node 25 (ABI 141) or 26 (ABI 147) the
|
|
88
|
+
native binding never resolved and every pty command died with a bare
|
|
89
|
+
`Cannot find module '.../pty.node'` MODULE_NOT_FOUND. Bumped to `0.14.1`, which
|
|
90
|
+
publishes darwin-arm64 (and darwin-x64) prebuilds through ABI 147, covering current
|
|
91
|
+
Node. The PTY sidecar now also **fails loud** when the binding genuinely can't load:
|
|
92
|
+
instead of a raw MODULE_NOT_FOUND it prints the platform, the running Node ABI, and a
|
|
93
|
+
concrete remediation (`npm rebuild @homebridge/node-pty-prebuilt-multiarch` / reinstall
|
|
94
|
+
the CLI), preserving the underlying error. Source: `cli/package.json`,
|
|
95
|
+
`cli/src/lib/pty-server.ts`.
|
|
96
|
+
|
|
97
|
+
- **An upgrade can no longer strand a box with the package installed but no working `agents` command (PHNX-2768).** `agents upgrade` (and every `agents fleet update` box, which runs it) now **owns the global bin links**: after installing and verifying the new version, it checks that `<prefix>/bin/{agents,ag,browser,computer}` resolve to the freshly-installed copy and **restores any the package manager dropped**. This closes the failure that left zion upgraded to 1.22.40 with `/opt/homebrew/bin/{agents,ag,browser,computer}` gone — every `agents` invocation "command not found" until the links were relinked by hand. It covers the sibling entrypoints (`ag`/`browser`/`computer`), not just `agents`. A link it cannot make resolve fails the upgrade **loud** (non-zero exit), so a genuinely-broken box is reported `failed` by the rollout instead of a stranded `ok`/`unverified`. Scope: the npm-prefix POSIX layout — bun and Windows use their own bin shims. Source: `cli/src/lib/self-update.ts` (`ensureGlobalBinLinks`), `cli/src/bootstrap.ts`, `cli/src/commands/ssh.ts`.
|
|
98
|
+
|
|
99
|
+
- **The auto-pulled system repo is verified against its expected origin before a
|
|
100
|
+
fast-forward — a repointed origin is refused, not executed (PHNX-2957).** The
|
|
101
|
+
system repo (`~/.agents/.system/`) ships **hooks** that register as shell
|
|
102
|
+
`command` strings run on every tool event, and its checkout auto-fast-forwards
|
|
103
|
+
from `origin` (on `agents use`, and on the opt-in `AGENTS_AUTO_PULL=1`
|
|
104
|
+
background worker). Neither path verified that `origin` was the repo the
|
|
105
|
+
operator actually chose — so an `origin` repointed to an attacker's fork (or a
|
|
106
|
+
clone seeded from one) would silently fast-forward arbitrary hook code that then
|
|
107
|
+
ran as shell on the next command. Both pull sites now route through
|
|
108
|
+
`tryAutoPullSystemRepo`, which pulls only when `origin` is the canonical system
|
|
109
|
+
repo (`isSystemRepoRemote`) or the exact `AGENTS_SYSTEM_REPO` the operator
|
|
110
|
+
pointed at; an unexpected origin is **refused loud** (`agents use` prints the
|
|
111
|
+
offending remote and the re-point/`AGENTS_SYSTEM_REPO` fix), never pulled. The
|
|
112
|
+
canonical system repo and a legitimate `AGENTS_SYSTEM_REPO` override still sync
|
|
113
|
+
exactly as before — no regression to trusted pulls. Source:
|
|
114
|
+
`cli/src/lib/git.ts` (`isExpectedSystemRepoRemote`, `tryAutoPullSystemRepo`),
|
|
115
|
+
`cli/src/commands/versions.ts`, `cli/src/lib/auto-pull-worker.ts`.
|
|
116
|
+
|
|
117
|
+
- **`agents monitors add --watch-pid <pid>` (PHNX-3023).** A reliable, daemon-polled
|
|
118
|
+
watcher for a backgrounded process — the fix for "will re-invoke me" watchers that
|
|
119
|
+
never fire because a harness's exit hook only wakes the agent when the watched
|
|
120
|
+
process dies, and a watch loop (`gh pr checks --watch`, a long sleep, a tick poll)
|
|
121
|
+
never itself exits. `--watch-pid` has the monitor engine's own poll loop check the
|
|
122
|
+
pid's liveness independent of the arming session, defaults its condition to fire on
|
|
123
|
+
exit, and fails loud at creation time when the pid is already dead instead of
|
|
124
|
+
silently arming a watcher that can never fire. Source: `cli/src/lib/monitors/pid-watch.ts`,
|
|
125
|
+
`cli/src/commands/monitors.ts`.
|
|
126
|
+
|
|
127
|
+
- **`agents doctor --fix` now reconciles hooks / permissions / subagents / rule
|
|
128
|
+
aliases on Windows instead of an unactionable "hold" (PHNX-3187).** On win-mini
|
|
129
|
+
`--fix` healed commands/skills/rules/plugins but reported hooks, permissions,
|
|
130
|
+
subagents, and the `CLAUDE`/`GEMINI` rule aliases as "couldn't reconcile" and
|
|
131
|
+
left the box permanently red — with real guards (`git-guard`, `rm-guard`,
|
|
132
|
+
`secrets-guard`, `ask-user-question-guard`, `public-artifact-guard`)
|
|
133
|
+
uninstalled. Four Windows-specific defects, each fixed at its source: (1)
|
|
134
|
+
**subagents** — `parseSubagentFrontmatter`/`getSubagentBody` split on `'\n'`
|
|
135
|
+
and compared the fence with `=== '---'`, so a git-CRLF-checked-out `AGENT.md`
|
|
136
|
+
(`'---\r'`) was rejected and the subagent silently dropped from discovery, so
|
|
137
|
+
it could never be installed; now CRLF-robust (`/\r?\n/`). (2) **permissions** —
|
|
138
|
+
`buildPermissionsFromGroups` extracted rules with a line regex anchored on the
|
|
139
|
+
closing quote (`"$`), which a trailing `\r` broke, extracting zero rules and
|
|
140
|
+
writing an empty permission set; now CRLF-robust. (3) **rule aliases** — git
|
|
141
|
+
checks the `rules/CLAUDE.md` and `rules/GEMINI.md` symlinks out as plain text
|
|
142
|
+
files on Windows, so `lstat().isSymbolicLink()` was false and the diff treated
|
|
143
|
+
them as independent rule sources no sync could ever produce; a new
|
|
144
|
+
`isCheckedOutSymlink` detector skips them on every platform. (4) **hooks** —
|
|
145
|
+
the heal pass fed the resource diff's extensionless hook names
|
|
146
|
+
(`git-guard`) back to the sync writer, whose `available.hooks` set carries the
|
|
147
|
+
source filename **with** its extension (`git-guard.sh`), so the exact-set match
|
|
148
|
+
found nothing and no flagged hook could be written; a new basename-tolerant
|
|
149
|
+
`resolveHookSelection` maps them, and the orphan sweep still prunes any stale
|
|
150
|
+
extensionless hook copy left in a version home (one would be invisible on
|
|
151
|
+
Windows, lacking both an extension and an exec bit). The subagents writer also now
|
|
152
|
+
surfaces a per-item write failure with its reason instead of swallowing it in a
|
|
153
|
+
bare `catch`, so a genuine failure fails loud rather than reading as a silent
|
|
154
|
+
"hold". Source: `cli/src/lib/subagents.ts`, `cli/src/lib/permissions.ts`,
|
|
155
|
+
`cli/src/lib/doctor-diff.ts`, `cli/src/lib/installations/versions.ts`,
|
|
156
|
+
`cli/src/lib/staleness/writers/subagents.ts`.
|
|
157
|
+
|
|
158
|
+
- Fix the `agents-cli` discovery skill/plugin install commands to use the real GitHub
|
|
159
|
+
repo path `phnx-labs/agi-cli` (they pointed at `phnx-labs/agents-cli`, which only
|
|
160
|
+
resolved via GitHub's rename redirect). The npm package stays `@phnx-labs/agents-cli`.
|
|
161
|
+
Also maps the plugin manifests + skill to `agents-cli-plugin.test.ts` in CI impact
|
|
162
|
+
analysis so a manifest/skill edit runs its test on the PR. (PHNX-3337 review follow-up)
|
|
163
|
+
|
|
164
|
+
- **Ship a cross-harness `agents-cli` discovery skill + Claude plugin marketplace (PHNX-3337).**
|
|
165
|
+
New `skills/agents-cli/SKILL.md` is an authoritative skill whose `description`
|
|
166
|
+
carries the exact intents a developer types — *run multiple coding agents in
|
|
167
|
+
parallel*, *manage multiple Claude Code accounts*, *I hit my usage limit*,
|
|
168
|
+
*resume a session on another machine*, *pin the agent CLI version* — each with a
|
|
169
|
+
verified `agents` command recipe (`teams`, `accounts`, `run --fallback`/`-b`/`auto`,
|
|
170
|
+
`sessions resume`, `add`/`use`). A repo-root `.claude-plugin/marketplace.json` +
|
|
171
|
+
`.claude-plugin/plugin.json` make the repo installable via
|
|
172
|
+
`claude plugin marketplace add phnx-labs/agents-cli` and `npx skills add
|
|
173
|
+
phnx-labs/agents-cli`; the plugin's `source: "./"` bundles the discovery skill
|
|
174
|
+
plus the existing per-command skills. Harness parity is registry-driven, not
|
|
175
|
+
per-harness copies: the one SKILL.md is authored once and the existing
|
|
176
|
+
capability-gated skill sync (`supports(agent, 'skills', …)`) fans it into every
|
|
177
|
+
skill-capable harness home. `claude plugin validate .` passes on the committed
|
|
178
|
+
manifest, and a real (no-mock) test reads the repo-root files and runs the CLI's
|
|
179
|
+
own `validateClaudePluginManifest`. Source:
|
|
180
|
+
`skills/agents-cli/SKILL.md`, `.claude-plugin/marketplace.json`,
|
|
181
|
+
`.claude-plugin/plugin.json`, `cli/src/lib/plugins/agents-cli-plugin.test.ts`,
|
|
182
|
+
`README.md`.
|
|
183
|
+
|
|
184
|
+
- **`agents cloud providers` no longer reports Rush as `ready` when the session token is expired (PHNX-3382).** `capabilities().available` checked only that `~/.rush/user.yaml` existed — it returned `true` even for an expired session, so the provider appeared ready but every dispatch failed with a cryptic HTTP 401. `readToken()` also silently returned an expired token, giving the same bad error on every cloud call (`dispatch`, `status`, `list`, `stream`, `cancel`, `message`). Both paths now check `expires_at` (Unix seconds): `capabilities()` returns `available: false` for a missing file, missing token, or expired session; `readToken()` throws `Rush session expired at <ISO>. Run 'rush login' to refresh.` — an actionable message instead of a 401. The exported `isRushSessionValid(yamlPath?)` helper is testable in isolation. Source: `cli/src/lib/cloud/rush.ts`.
|
|
185
|
+
|
|
186
|
+
- **Traces: session duration is populated for every harness, and the console duration median is active-time, not calendar span (PHNX-3457).** Only claude/codex/droid/gemini/opencode ever derived a `duration_ms` at scan; rush/grok/kimi/cursor/muse/antigravity left it NULL — 52% of sessions, 100% of the dominant `rush` usage — so the Evals console median was computed over only the ~48% that carried it and skewed misleadingly short. `resolveDurationMs` now fills the span at the single upsert boundary from the timestamps the row already stores (a v43→v44 migration backfills existing rows in place, no re-parse), so every harness gets a span. The `agents traces sync` index shard's `medianMs`/`p90Ms` now run over **active time** — span minus every idle gap > 120s (before the first tool call, between calls measured from each call's end, and after the last call to the session end), derived from the ordered `tool_calls` already loaded — so a session resumed after hours or left idle mid-turn no longer inflates them (it killed a 345h calendar-span outlier). The stat keys are unchanged, so the fleet-aggregate worker keeps averaging them; the raw span stays available per session as `SessionDetail.meta.spanMs`, which also gains `activeMs`. Source: `cli/src/lib/session/db.ts`, `cli/src/lib/traces/sync.ts`.
|
|
187
|
+
- **Traces: treemap tiles are drillable — each topic bucket carries example session refs (PHNX-3408).** The `agents traces sync` index shard now emits up to 30 most-recent `sessions` (`{id,title}`) per topic bucket, so the Evals console can drill from a treemap tile into that category's session list instead of rendering every tile display-only. The tile's `count` stays the true total. Source: `cli/src/lib/traces/sync.ts`.
|
|
188
|
+
|
|
189
|
+
- **`agents run --device auto` no longer lands a launch on a fleet box that is logged out for the target harness (PHNX-3466).**
|
|
190
|
+
The `--device auto` placement gate already excluded a device whose harness reads
|
|
191
|
+
signed-out — but it judged a REMOTE candidate by `agents view --json`'s display
|
|
192
|
+
`signedIn`, which is true whenever the box's active/global HOME carries a login even
|
|
193
|
+
if the per-version home the isolated run actually launches has no credential of its
|
|
194
|
+
own. The LOCAL candidate, by contrast, used the strict per-version launch truth
|
|
195
|
+
(`collectRunCandidates` → `isLaunchableSignedIn`). So a worker whose selected harness
|
|
196
|
+
version home was not launchable passed the remote gate, got picked, and the launch
|
|
197
|
+
died at spawn — from AGI EXT the dispatched tab exited 1 and vanished. `agents view
|
|
198
|
+
--json` now emits a per-version `launchable` field (the same `isLaunchableSignedIn`
|
|
199
|
+
signal the local path uses), and remote placement (`viewAgentAccountEligibility`)
|
|
200
|
+
gates on it, so both paths agree. A device with no launchable account for the harness
|
|
201
|
+
is excluded from the `--device auto` candidate set; when that empties the pool the
|
|
202
|
+
existing fail-loud `no healthy device` error fires instead of a silently-lost launch.
|
|
203
|
+
An older remote CLI that omits `launchable` falls back to `signedIn`, so a rolling
|
|
204
|
+
fleet does not regress. No second placement path was added — the single CLI gate is
|
|
205
|
+
hardened, so both the CLI and AGI EXT (which delegates placement to it) benefit.
|
|
206
|
+
Source: `cli/src/commands/view.ts`, `cli/src/lib/view-types.ts`,
|
|
207
|
+
`cli/src/lib/hosts/ready.ts`.
|
|
208
|
+
|
|
209
|
+
- **`agents traces sync` now emits SEGMENTED active-time medians so the console can
|
|
210
|
+
headline agent runs, not the corpus blend (PHNX-3472).** 63% of sessions are
|
|
211
|
+
one-shot queries (≤2 messages, ~15s active), so the blended `medianMs`/`p90Ms` sat
|
|
212
|
+
at ~15s while substantial agent runs have a ~15-minute median — the blend headlined
|
|
213
|
+
neither. The index-shard `stats` now classify each session as an AGENT run (any tool
|
|
214
|
+
call OR more than 8 messages) or INTERACTIVE, and carry `agentMedianMs`/`agentP90Ms`
|
|
215
|
+
(active-time median/p90 over agent sessions), `interactiveMedianMs`, and
|
|
216
|
+
`measuredFraction` (share of sessions with a non-null duration) alongside the
|
|
217
|
+
unchanged blended `medianMs`/`p90Ms`. Reuses the PHNX-3457 active-time computation
|
|
218
|
+
(span minus idle gaps > 120s); no calendar span reintroduced. Source:
|
|
219
|
+
`cli/src/lib/traces/sync.ts`.
|
|
220
|
+
|
|
221
|
+
- **`agents traces sync` classifies session kind and EXCLUDES internal utility calls
|
|
222
|
+
from the Evals corpus (PHNX-3474).** ~68% of the raw corpus is machine plumbing —
|
|
223
|
+
single-shot calls (no tool call AND ≤2 messages) plus known internal-prompt
|
|
224
|
+
signatures (title generation, watchdog ticks, commit-message writes, factory
|
|
225
|
+
workers), all spawned under the `claude` harness by the Rush app — and it poisoned
|
|
226
|
+
every console statistic (count, median, need-attention, tool-error-rate). Each
|
|
227
|
+
session now carries a `kind` (`utility` vs `agent`, `classifySessionKind` in
|
|
228
|
+
`traces/sync.ts`) and every index statistic is computed over the AGENT set ONLY:
|
|
229
|
+
`sessionsImported` is the real agent count (not the raw row count), and the
|
|
230
|
+
medians / `needAttention` / `toolErrorRate` / topic-bucket counts all exclude
|
|
231
|
+
utility. A new top-level `utilityCount` reports how many were dropped. Each session
|
|
232
|
+
ref (topic-tile `sessions[]` and `needsAttention`) also emits `kind` and `harness`
|
|
233
|
+
so the console can filter by both. Pure reclassification — utility rows are tagged
|
|
234
|
+
and excluded at shard-build time, never deleted from `sessions.db`. Source:
|
|
235
|
+
`cli/src/lib/traces/sync.ts`.
|
|
236
|
+
</content>
|
|
237
|
+
</invoke>
|
|
238
|
+
|
|
3
239
|
## 1.22.58
|
|
4
240
|
|
|
241
|
+
- **`agents notify` is deprecated in favor of `agents feed post` (PHNX-3323).** The command still works for existing callers, but it now prints a stderr deprecation notice naming `agents feed post` as the replacement, and `agents notify --help` carries a `[DEPRECATED]` label and examples that use `agents feed post`. Source: `cli/src/commands/send.ts`.
|
|
242
|
+
|
|
5
243
|
- **A remote browser task survives a browser-daemon restart on the driving box (PHNX-2663).** When the local daemon restarted, its in-memory task map was rebuilt from disk for local-CDP profiles but **skipped `ssh://` tunnelled tasks** — so an agent driving a browser host over `--device` got "Unknown browser task" / "Tab not found" for a tab that was still alive on the far side, and gave up. `attachRunningProfile` now re-establishes the SSH tunnel and reconnects CDP for a tunnelled task during rehydrate (reusing `connectSSH`, which attaches to the already-running remote browser via `isOwnTunnel` — it never launches one), carrying the tunnel teardown so it can't leak across the next restart. A failed reconnect falls through to disk reconcile exactly like the local-CDP path. Source: `cli/src/lib/browser/service.ts`.
|
|
6
244
|
|
|
7
245
|
- **`agents prune cleanup` no longer over-reports source-present hooks as orphans (PHNX-2693).** Orphan detection diffed the hook files in a version home against the *registered-hook manifest*, but sync copies helper / test / benchmark scripts into every version home alongside registered hooks without registering them — so each one (e.g. `permission-handler`, `verify-work-state`, `*_test`, `benchmark_*`) read as an orphan, and `agents prune cleanup [hooks | --all]` offered to trash ~1000 in-use files across version homes. It now diffs against the resolved **source** set (user + system + enabled extras hook dirs), so a hook present in any configured source is never an orphan, exactly as the command's own help promised — while a genuinely dead file (present in a home, absent from every source) is still flagged. Same detector backs `agents doctor`'s `orphan` warning. Source: `cli/src/lib/hooks/install.ts`.
|
package/README.md
CHANGED
|
@@ -59,6 +59,20 @@ Everything here — and every other command in this README — is free and needs
|
|
|
59
59
|
The command surface teaches setup through `agents setup` and group-level `--help`.
|
|
60
60
|
The durable system model starts at [`cli/docs/README.md`](cli/docs/README.md).
|
|
61
61
|
|
|
62
|
+
**What `agents setup` installs, and what auto-updates.** Setup clones a small public
|
|
63
|
+
**system repo** (`phnx-labs/.agents-system`) into `~/.agents/.system/`. It ships the
|
|
64
|
+
default resources — including **hooks**, which run as shell commands on tool events —
|
|
65
|
+
and its checkout **fast-forwards from its origin** when you run `agents use` (and, only
|
|
66
|
+
if you opt in with `AGENTS_AUTO_PULL=1`, in the background). Two safeguards bound that:
|
|
67
|
+
the pull is `merge --ff-only` (it can never rewrite your local history), and it is
|
|
68
|
+
**verified against the expected origin** — a checkout whose `origin` is not the canonical
|
|
69
|
+
system repo (or the exact repo you named in `AGENTS_SYSTEM_REPO`) is refused, never
|
|
70
|
+
pulled, so a repointed remote cannot slip hook code onto your machine. To pin or opt out:
|
|
71
|
+
set `AGENTS_SYSTEM_REPO=gh:you/your-fork` to track your own audited copy, run
|
|
72
|
+
`agents setup --no-system-repo` to skip the clone entirely, or check out a specific tag
|
|
73
|
+
in `~/.agents/.system/` (a fast-forward only advances a moving branch, so a detached tag
|
|
74
|
+
stays put).
|
|
75
|
+
|
|
62
76
|
**Learn (concepts):** [Loop + graph engineering](https://agi-cli.sh/learn/loop-and-graph-engineering) · [Teams as graph engineering](https://agi-cli.sh/learn/teams-graph-engineering) · [Sessions · index + cross-device](https://agi-cli.sh/learn/sessions-index) · [Distributed fleet execution](https://agi-cli.sh/learn/distributed-fleet). Also: [harness engineering](https://agi-cli.sh/learn/harness-engineering) · [visual longform](https://share.agents-cli.sh/muqsitnawaz/agents-loop-and-graph-engineering).
|
|
63
77
|
|
|
64
78
|
Already installed? `agents upgrade` updates agi-cli itself to the latest version (`agents upgrade 1.2.3` for a specific version or dist-tag, `-y` to skip the confirm prompt). The command is `upgrade` on every platform -- do not reach for `agents update`, which updates an installed **agent harness**, not agi-cli (and on macOS, `agents helper update` is a third thing: it reinstalls the keychain helper).
|
|
@@ -898,6 +912,21 @@ Skills, commands, and subagents are declarative and never trip the gate. The gat
|
|
|
898
912
|
|
|
899
913
|
Plugins live in the user repo (`~/.agents/plugins/`), not inside any single version home. Switching Claude via `agents use claude@<v>` re-syncs the plugin into the new version automatically — no re-install. New Claude versions added later pick it up on their first sync. Project-level `<repo>/.agents/plugins/<name>/` overrides a same-named user plugin (resolution is project > user > system, same as every other resource).
|
|
900
914
|
|
|
915
|
+
### Install the agents-cli skill in any agent
|
|
916
|
+
|
|
917
|
+
This repo is itself a Claude plugin marketplace and a [skills.sh](https://skills.sh) source. The `agents-cli` skill teaches any coding agent (Claude Code, Codex, Cursor, …) how to drive the `agents` CLI — so when you ask *"how do I run multiple coding agents in parallel?"* the agent surfaces `agents teams` instead of guessing.
|
|
918
|
+
|
|
919
|
+
```bash
|
|
920
|
+
# Claude Code — add this repo as a marketplace, then install the plugin
|
|
921
|
+
claude plugin marketplace add phnx-labs/agi-cli
|
|
922
|
+
claude plugin install agents-cli@agents-cli
|
|
923
|
+
|
|
924
|
+
# skills.sh — install the skill directly from the repo
|
|
925
|
+
npx skills add phnx-labs/agi-cli
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
The manifest is `.claude-plugin/marketplace.json` (validate with `claude plugin validate .`); the skill source is [`skills/agents-cli/SKILL.md`](skills/agents-cli/SKILL.md). Its `description` carries the exact intents the runtime matches against — *run multiple coding agents in parallel*, *manage multiple Claude Code accounts*, *I hit my usage limit*, *resume a session on another machine*, *pin the agent CLI version* — each with a verified command recipe.
|
|
929
|
+
|
|
901
930
|
---
|
|
902
931
|
|
|
903
932
|
## Make it yours
|
package/dist/bootstrap.js
CHANGED
|
@@ -29,7 +29,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
29
29
|
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
30
30
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
31
31
|
const VERSION = packageJson.version;
|
|
32
|
-
import { NPM_PACKAGE_NAME, deriveGlobalPrefix, detectPackageManager, installPackageIntoPrefix, installPackageWithBun, verifyInstalledVersion, refreshAliasShims, downloadVerifiedTarball, sweepStaleInstallStaging, } from './lib/self-update.js';
|
|
32
|
+
import { NPM_PACKAGE_NAME, deriveGlobalPrefix, detectPackageManager, ensureGlobalBinLinks, installPackageIntoPrefix, installPackageWithBun, verifyInstalledVersion, refreshAliasShims, downloadVerifiedTarball, sweepStaleInstallStaging, } from './lib/self-update.js';
|
|
33
33
|
import { registerUpgradeCommand } from './commands/upgrade.js';
|
|
34
34
|
// Detect dev/working-tree builds and default the noisy startup steps off.
|
|
35
35
|
// Three cases trip this:
|
|
@@ -350,6 +350,32 @@ async function installResolvedPackage(metadata) {
|
|
|
350
350
|
}
|
|
351
351
|
verifyInstalledVersion(packageRoot, metadata.version);
|
|
352
352
|
refreshAliasShims(packageRoot);
|
|
353
|
+
// PHNX-2768: the npm install above can leave the package at the new version
|
|
354
|
+
// but the global bin links GONE — the state that stranded zion (package at
|
|
355
|
+
// 1.22.40, `/opt/homebrew/bin/{agents,ag,browser,computer}` missing, every
|
|
356
|
+
// `agents` invocation "command not found"). The upgrade OWNS those links, so
|
|
357
|
+
// it restores any that npm dropped and fails LOUD when one cannot be made to
|
|
358
|
+
// resolve — never returning a box the package upgraded but cannot run. Only
|
|
359
|
+
// the npm-prefix POSIX layout has these symlinks; bun and Windows use their
|
|
360
|
+
// own bin shims and are out of scope.
|
|
361
|
+
if (detectPackageManager(packageRoot) !== 'bun' && process.platform !== 'win32') {
|
|
362
|
+
const prefix = deriveGlobalPrefix(packageRoot);
|
|
363
|
+
const repairs = ensureGlobalBinLinks(packageRoot, prefix);
|
|
364
|
+
const repaired = repairs.filter((r) => r.action === 'repaired');
|
|
365
|
+
const failed = repairs.filter((r) => r.action === 'failed');
|
|
366
|
+
if (repaired.length > 0) {
|
|
367
|
+
console.error(chalk.yellow(`Relinked ${repaired.map((r) => r.name).join(', ')} in ${path.join(prefix, 'bin')} — the install left them missing.`));
|
|
368
|
+
}
|
|
369
|
+
if (failed.length > 0) {
|
|
370
|
+
const relink = failed
|
|
371
|
+
.map((r) => `ln -sf ${path.relative(path.dirname(r.linkPath), r.target)} ${r.linkPath}`)
|
|
372
|
+
.join(' && ');
|
|
373
|
+
throw new Error(`upgraded to ${metadata.version} but could not restore the ` +
|
|
374
|
+
`${failed.map((r) => r.name).join(', ')} command link${failed.length === 1 ? '' : 's'} in ` +
|
|
375
|
+
`${path.join(prefix, 'bin')} (${failed.map((r) => r.error).join('; ')}). ` +
|
|
376
|
+
`The box has the new package but no working \`agents\` — relink manually: ${relink}`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
353
379
|
// The npm install above runs with --ignore-scripts, so the postinstall that
|
|
354
380
|
// installs the macOS Keychain helper never fires on upgrade. Force-refresh the
|
|
355
381
|
// helper here so a user upgrading FROM a broken build (e.g. the entitlement-less
|
|
@@ -727,6 +753,11 @@ async function runUpgrade(version, options) {
|
|
|
727
753
|
return;
|
|
728
754
|
spinner.fail(`Upgrade failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
729
755
|
console.log(chalk.gray(`Run manually: agents upgrade ${version ? version + ' ' : ''}--yes`));
|
|
756
|
+
// A failed upgrade MUST exit non-zero (PHNX-2768). The fleet rollout
|
|
757
|
+
// keys a box `ok` on `agents upgrade` exiting 0 alone; exiting 0 on
|
|
758
|
+
// failure is what let a stranded box (package upgraded, bin links gone)
|
|
759
|
+
// be reported merely `unverified` instead of `failed`.
|
|
760
|
+
process.exitCode = 1;
|
|
730
761
|
}
|
|
731
762
|
}
|
|
732
763
|
function registerUpgradeRuntimeCommand(p) {
|