@phnx-labs/agents-cli 1.22.25 → 1.22.27
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 +427 -0
- package/README.md +35 -3
- package/dist/bin/agents +0 -0
- package/dist/browser.js +14 -4
- package/dist/commands/apply.js +52 -8
- package/dist/commands/bench.d.ts +2 -0
- package/dist/commands/bench.js +101 -0
- package/dist/commands/browser.js +35 -0
- package/dist/commands/doctor.js +32 -10
- package/dist/commands/exec.js +17 -16
- package/dist/commands/insights.d.ts +25 -19
- package/dist/commands/insights.js +146 -38
- package/dist/commands/output.js +100 -25
- package/dist/commands/reconnect.d.ts +46 -0
- package/dist/commands/reconnect.js +109 -0
- package/dist/commands/resume.d.ts +11 -0
- package/dist/commands/resume.js +51 -0
- package/dist/commands/routines.js +2 -2
- package/dist/commands/secrets.d.ts +2 -8
- package/dist/commands/secrets.js +29 -105
- package/dist/commands/sessions-picker.js +12 -7
- package/dist/commands/sessions.d.ts +47 -1
- package/dist/commands/sessions.js +349 -37
- package/dist/commands/setup-secrets.d.ts +1 -0
- package/dist/commands/setup-secrets.js +1 -1
- package/dist/commands/setup.d.ts +26 -3
- package/dist/commands/setup.js +105 -46
- package/dist/commands/ssh.js +184 -11
- package/dist/commands/teams.d.ts +6 -0
- package/dist/commands/teams.js +46 -3
- package/dist/commands/trends.d.ts +8 -0
- package/dist/commands/trends.js +10 -156
- package/dist/index.js +17 -21
- package/dist/lib/agents.d.ts +11 -0
- package/dist/lib/agents.js +29 -2
- package/dist/lib/analytics/dashboard.d.ts +10 -6
- package/dist/lib/analytics/dashboard.js +6 -4
- package/dist/lib/analytics/mix-commands.d.ts +53 -0
- package/dist/lib/analytics/mix-commands.js +229 -0
- package/dist/lib/analytics/recipes.d.ts +19 -14
- package/dist/lib/analytics/recipes.js +4 -2
- package/dist/lib/auth-health.d.ts +47 -3
- package/dist/lib/auth-health.js +74 -15
- package/dist/lib/bench/index.d.ts +4 -0
- package/dist/lib/bench/index.js +4 -0
- package/dist/lib/bench/runner.d.ts +16 -0
- package/dist/lib/bench/runner.js +111 -0
- package/dist/lib/bench/schema.d.ts +5 -0
- package/dist/lib/bench/schema.js +91 -0
- package/dist/lib/bench/storage.d.ts +5 -0
- package/dist/lib/bench/storage.js +32 -0
- package/dist/lib/bench/types.d.ts +40 -0
- package/dist/lib/bench/types.js +1 -0
- package/dist/lib/browser/ipc.d.ts +26 -0
- package/dist/lib/browser/ipc.js +139 -24
- package/dist/lib/browser/profiles.d.ts +11 -0
- package/dist/lib/browser/profiles.js +1 -1
- package/dist/lib/browser/stream.d.ts +14 -0
- package/dist/lib/browser/stream.js +71 -0
- package/dist/lib/channels/owner-sink.d.ts +27 -0
- package/dist/lib/channels/owner-sink.js +93 -0
- package/dist/lib/claude-account-token.d.ts +2 -0
- package/dist/lib/claude-account-token.js +27 -1
- package/dist/lib/crabbox/cli.d.ts +2 -0
- package/dist/lib/crabbox/cli.js +2 -0
- package/dist/lib/crabbox/lease.js +7 -1
- package/dist/lib/daemon.js +20 -0
- package/dist/lib/devices/connect.d.ts +2 -0
- package/dist/lib/devices/connect.js +7 -0
- package/dist/lib/devices/doctor-findings.d.ts +10 -1
- package/dist/lib/devices/doctor-findings.js +47 -1
- package/dist/lib/devices/harness-inventory.d.ts +97 -0
- package/dist/lib/devices/harness-inventory.js +0 -0
- package/dist/lib/devices/registry.d.ts +2 -0
- package/dist/lib/devices/ssh-config.js +3 -0
- package/dist/lib/devices/windows-ssh-enrollment.d.ts +20 -0
- package/dist/lib/devices/windows-ssh-enrollment.js +98 -0
- package/dist/lib/exec.bench.d.ts +1 -0
- package/dist/lib/exec.bench.js +186 -0
- package/dist/lib/exec.js +18 -8
- package/dist/lib/fleet/apply.d.ts +59 -3
- package/dist/lib/fleet/apply.js +191 -12
- package/dist/lib/fleet/remote-login.d.ts +4 -3
- package/dist/lib/fleet/remote-login.js +11 -9
- package/dist/lib/fleet/types.d.ts +21 -2
- package/dist/lib/gemini-settings.d.ts +0 -1
- package/dist/lib/gemini-settings.js +12 -7
- package/dist/lib/hooks/cache.js +15 -0
- package/dist/lib/hooks.d.ts +8 -5
- package/dist/lib/hooks.js +10 -6
- package/dist/lib/hosts/dispatch.js +7 -3
- package/dist/lib/hosts/passthrough.d.ts +45 -0
- package/dist/lib/hosts/passthrough.js +59 -8
- package/dist/lib/hosts/progress.d.ts +2 -1
- package/dist/lib/hosts/progress.js +4 -3
- package/dist/lib/hosts/providers/devices.js +1 -0
- package/dist/lib/hosts/ready.d.ts +6 -2
- package/dist/lib/hosts/ready.js +33 -8
- package/dist/lib/hosts/reconcile.d.ts +1 -1
- package/dist/lib/hosts/reconcile.js +16 -7
- package/dist/lib/hosts/reconnect.d.ts +56 -21
- package/dist/lib/hosts/reconnect.js +128 -71
- package/dist/lib/hosts/registry.d.ts +2 -2
- package/dist/lib/hosts/registry.js +3 -5
- package/dist/lib/hosts/remote-cmd.d.ts +17 -0
- package/dist/lib/hosts/remote-cmd.js +29 -0
- package/dist/lib/hosts/tasks.d.ts +2 -0
- package/dist/lib/hosts/types.d.ts +1 -0
- package/dist/lib/hosts/types.js +3 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/install-menubar.d.ts +9 -6
- package/dist/lib/menubar/install-menubar.js +20 -9
- package/dist/lib/models.d.ts +30 -1
- package/dist/lib/models.js +42 -144
- package/dist/lib/pricing/cost.d.ts +9 -0
- package/dist/lib/pricing/cost.js +24 -0
- package/dist/lib/pricing/index.d.ts +1 -1
- package/dist/lib/pricing/index.js +1 -1
- package/dist/lib/redact.js +8 -3
- package/dist/lib/remote-agents-json.d.ts +32 -0
- package/dist/lib/remote-agents-json.js +47 -16
- package/dist/lib/resource-profiles.js +1 -2
- package/dist/lib/routine-notify-owner.d.ts +102 -0
- package/dist/lib/routine-notify-owner.js +232 -0
- package/dist/lib/routines.d.ts +10 -0
- package/dist/lib/routines.js +14 -2
- package/dist/lib/runner.d.ts +9 -4
- package/dist/lib/runner.js +182 -30
- package/dist/lib/sandbox.d.ts +0 -2
- package/dist/lib/sandbox.js +2 -19
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/agent.js +3 -2
- package/dist/lib/secrets/lease.d.ts +25 -0
- package/dist/lib/secrets/lease.js +44 -0
- package/dist/lib/secrets/push.d.ts +94 -0
- package/dist/lib/secrets/push.js +145 -0
- package/dist/lib/secrets/reaper.d.ts +15 -1
- package/dist/lib/secrets/reaper.js +30 -3
- package/dist/lib/self-update.d.ts +20 -5
- package/dist/lib/self-update.js +93 -16
- package/dist/lib/session/db.d.ts +38 -3
- package/dist/lib/session/db.js +273 -16
- package/dist/lib/session/discover.d.ts +22 -1
- package/dist/lib/session/discover.js +239 -51
- package/dist/lib/session/insights.d.ts +37 -0
- package/dist/lib/session/insights.js +219 -9
- package/dist/lib/session/recovery.d.ts +17 -1
- package/dist/lib/session/recovery.js +111 -4
- package/dist/lib/session/remote-list.d.ts +10 -9
- package/dist/lib/session/remote-list.js +25 -23
- package/dist/lib/session/resume-owner.d.ts +55 -0
- package/dist/lib/session/resume-owner.js +69 -0
- package/dist/lib/session/team-filter.d.ts +65 -0
- package/dist/lib/session/team-filter.js +98 -3
- package/dist/lib/session/tool-index.js +133 -22
- package/dist/lib/session/tool-store.d.ts +26 -2
- package/dist/lib/session/tool-store.js +36 -17
- package/dist/lib/session/types.d.ts +33 -0
- package/dist/lib/smart-launch.d.ts +31 -5
- package/dist/lib/smart-launch.js +43 -7
- package/dist/lib/ssh-exec.d.ts +27 -0
- package/dist/lib/ssh-exec.js +42 -3
- package/dist/lib/ssh-tunnel.d.ts +3 -2
- package/dist/lib/ssh-tunnel.js +25 -16
- package/dist/lib/startup/command-registry.d.ts +2 -0
- package/dist/lib/startup/command-registry.js +6 -0
- package/dist/lib/teams/agents.d.ts +13 -0
- package/dist/lib/teams/agents.js +75 -7
- package/dist/lib/teams/placement-probe.d.ts +21 -0
- package/dist/lib/teams/placement-probe.js +135 -0
- package/dist/lib/teams/scheduler.d.ts +74 -1
- package/dist/lib/teams/scheduler.js +187 -10
- package/dist/lib/tmux/session.d.ts +8 -0
- package/dist/lib/tmux/session.js +22 -0
- package/dist/lib/types.d.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,422 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.22.27
|
|
4
|
+
|
|
5
|
+
- **`agents sessions --teams` groups sessions by team (RUSH-1997).** Instead of one flat list with a `[team/handle]` tag, `--teams` now prints a report grouped by team: each team names its spawner (the orchestrator session that created it) and spawn time, and every teammate row shows its mode + handle. Team-flagged spawns that carry no teammate `meta.json` — headless `agents run` sessions, or teammates whose team record aged out — sink into a trailing `(no team)` bucket, so a real `agents teams` teammate and a bare SDK spawn are never shown as the same thing. `--teams --flat`/`--tree` keep the plain inline table, and a search query keeps the interactive picker. `TeamOrigin` (also on `--teams --json`) now carries the teammate's `startedAt` spawn time and a `source` (`meta` = teammate, `entrypoint` = bare spawn). Source: `apps/cli/src/lib/session/team-filter.ts`, `apps/cli/src/commands/sessions.ts`.
|
|
6
|
+
|
|
7
|
+
- **`agents run --device auto` and `agents teams add --device auto` now choose from live fleet health instead of 14-day launch affinity (RUSH-2001).** The picker probes candidates in parallel, excludes unreachable, overloaded, and missing-agent machines, prefers signed-in candidates with the lowest normalized load, and keeps execution local when no remote is better. Remote readiness now uses `agents view --json`, preserving the installed/sign-in split instead of treating every remote sign-in state as unknown. Source: `apps/cli/src/lib/smart-launch.ts`, `apps/cli/src/lib/teams/placement-probe.ts`, `apps/cli/src/lib/hosts/ready.ts`, `apps/cli/src/commands/exec.ts`, `apps/cli/src/commands/teams.ts`.
|
|
8
|
+
|
|
9
|
+
- **`agents devices harnesses` / `agents devices accounts` — per-device harness + account readiness (RUSH-2003).** Two new fleet lenses: `harnesses` lists every installed `agent@version` across the fleet with its account, signed-in state, quota (highest usage-window utilization; `*` = cached snapshot), and a single `ready` verdict (signed in AND not rate-limited); `accounts` collapses that to one row per account, naming which harnesses share it. Both SSH-probe each online device (bounded like `fleet ping`, so one unreachable box can't stall the glance) and read the daemon-warmed usage cache — `--refresh` (`--live`) forces a live quota read. Scope with `--agents <csv>` / `--device <csv>`; `--json` emits per-host rows (harnesses) or account groups (accounts). Source: `apps/cli/src/lib/devices/harness-inventory.ts`, `apps/cli/src/commands/ssh.ts`.
|
|
10
|
+
|
|
11
|
+
- **A session that ran on another device now resumes ON that device, and a typo'd
|
|
12
|
+
command with `--host` says `unknown command` (RUSH-2022).** Two bugs found while
|
|
13
|
+
recovering ~15 sessions after a machine crash, both of which sent recovery down the
|
|
14
|
+
wrong path.
|
|
15
|
+
|
|
16
|
+
(1) **`agents resume <id>` restarted a remote session locally.** The harness keeps its
|
|
17
|
+
conversation state on the machine that produced the session, but nothing checked which
|
|
18
|
+
machine that was — so a peer-owned session started the agent here, against state this
|
|
19
|
+
box had never seen (`sessions-resume.ts` even swapped in `process.cwd()` when the
|
|
20
|
+
recorded directory did not exist locally). `agents resume` now re-runs itself on the
|
|
21
|
+
owning device over SSH; `--here` overrides. The bare `agents sessions` picker routes
|
|
22
|
+
the same way, and `agents sessions attach` hops as an **attach** (its detach record and
|
|
23
|
+
the headless process it stops both live on the owner). The multi-select
|
|
24
|
+
`agents sessions resume` inherits it: each tab it opens runs the canonical
|
|
25
|
+
`agents resume <id>`, which now routes itself, and its no-tab-backend path routes
|
|
26
|
+
explicitly. Root cause of
|
|
27
|
+
the population that made this common: a run dispatched with `agents run --device
|
|
28
|
+
<box>` was indexed with no origin machine at all, so the index claimed the dispatching
|
|
29
|
+
box; it now records `<box>`, which also means such a run finally shows up under
|
|
30
|
+
`agents sessions --host <box>`. Source: `apps/cli/src/lib/session/resume-owner.ts`,
|
|
31
|
+
`apps/cli/src/lib/hosts/session-index.ts`, `apps/cli/src/commands/resume.ts`.
|
|
32
|
+
|
|
33
|
+
The hop carries its "don't route again" pin as an exported env var, not a flag, so it
|
|
34
|
+
works against a peer still on an older CLI. Sessions indexed *before* this release keep
|
|
35
|
+
their old machine tag — re-dispatch or a fresh scan corrects them.
|
|
36
|
+
|
|
37
|
+
(2) **The `--host`/`--device` router answered for commands that do not exist.** It runs
|
|
38
|
+
before commander parses, so `agents session resume --host <box>` (one letter off
|
|
39
|
+
`sessions`, which *does* accept `--host`) reported `` `agents session` does not support
|
|
40
|
+
--host/--device `` — a true statement about a command nobody typed and the opposite of
|
|
41
|
+
the truth for the one they meant. Unknown names now fall through to `unknown command
|
|
42
|
+
'<name>'` with a did-you-mean, and the spellcheck can suggest the lazily-registered
|
|
43
|
+
groups (`sessions`/`teams`/`cloud`/…) it previously could not see. A real command with
|
|
44
|
+
no remote semantics still gets the flag-support error. Source:
|
|
45
|
+
`apps/cli/src/lib/hosts/passthrough.ts`, `apps/cli/src/lib/startup/command-registry.ts`.
|
|
46
|
+
|
|
47
|
+
- **`agents publish` is in the lazy command table.** `commands/packages.ts` registers it at
|
|
48
|
+
top level but the registry did not list it, so it only resolved through the
|
|
49
|
+
unknown-command fallback that loads the whole command tree. Found by the new test that
|
|
50
|
+
pins the command-name set against the real tree.
|
|
51
|
+
|
|
52
|
+
- **A mistyped command keeps its `--host`.** The distance-1 auto-correct now runs *before*
|
|
53
|
+
the router instead of after commander gave up, so `agents docto --host <box>` corrects to
|
|
54
|
+
`doctor` **and** runs on `<box>` — previously the corrected command re-parsed locally with
|
|
55
|
+
a `--host` it did not accept. Four routing-table entries naming commands that do not exist
|
|
56
|
+
(`cli`, `packages`, `versions`, `daemon`) were removed; a test now keeps both routing
|
|
57
|
+
tables to real command names.
|
|
58
|
+
|
|
59
|
+
- **Cross-machine `agents … --json` fan-out caps each peer's stdout at 16 MiB
|
|
60
|
+
instead of buffering it unbounded (RUSH-2065).** The shared fan-out
|
|
61
|
+
(`gatherRemoteAgentsJson`, behind `agents sessions --active`, `agents feed`, and
|
|
62
|
+
every other fleet-wide JSON sweep) streamed each peer's output into memory with
|
|
63
|
+
no ceiling, under one `Promise.all` — so a single peer returning a corrupt or
|
|
64
|
+
pathologically large payload could retain ~170 MB and OOM the whole sweep. Each
|
|
65
|
+
peer's capture now stops and SIGKILLs the connection once it would exceed the
|
|
66
|
+
ceiling, treating that box as unreachable (reported in `skipped`) so the rest of
|
|
67
|
+
the fleet still renders. The bound and the UTF-8-safe accumulator now live once
|
|
68
|
+
in `apps/cli/src/lib/ssh-exec.ts`, shared with the `agents sessions` browse
|
|
69
|
+
fan-out that already had the guard. Source: `apps/cli/src/lib/remote-agents-json.ts`,
|
|
70
|
+
`apps/cli/src/lib/ssh-exec.ts`, `apps/cli/src/lib/session/remote-list.ts`.
|
|
71
|
+
|
|
72
|
+
- **Auth-health probes once per account, not once per version home (RUSH-2111).**
|
|
73
|
+
The daemon's every-3-minute auth-health refresh fanned `probeLocalFleetAuth`
|
|
74
|
+
over *every* installed version home at once, so a box with several Claude homes
|
|
75
|
+
signed into one account fired that many concurrent requests at the same
|
|
76
|
+
provider OAuth endpoint — racing its rate limit into a `429` that then parked
|
|
77
|
+
the whole box's usage reads behind a `Retry-After` penalty (`usage-backoff.ts`
|
|
78
|
+
survives that penalty; this removes its cause). Installs are now grouped by
|
|
79
|
+
account and the live probe runs once per (agent, account), fanning the one
|
|
80
|
+
verdict out to each home's per-version cache row. Homes with no resolvable
|
|
81
|
+
account are still probed individually. Source: `apps/cli/src/lib/auth-health.ts`.
|
|
82
|
+
|
|
83
|
+
- **Fallback-chain agents now receive their own active rules preset before dispatch (RUSH-2129).** `runWithFallback` resolves each attempted entry's harness/version home and runs the same skip-fast preset synchronization as the primary `agents run` path, so a rate-limit handoff cannot launch against stale rules. Source: `apps/cli/src/lib/exec.ts`, `apps/cli/src/lib/rules/run-sync.ts`.
|
|
84
|
+
|
|
85
|
+
- **Gemini hard-deprecation: routines daemon can no longer execute a legacy Gemini routine (RUSH-2202).** RUSH-2060 gated `agents add`/`import`/`sync`/`run`/`routines add` against a hard-deprecated harness, but the routines daemon's own executor (`runner.ts`) had no equivalent gate — a Gemini routine written before RUSH-2060, or synced/edited on disk directly, would still fire and try to build a `gemini …` command against a backend Google retired. `executeJob`/`executeJobDetached` now reject a hard-deprecated agent up front, before any version/account resolution or sandbox prep, and record a `failed` run with the same deprecation message every other entry point already shows. Also removed the now-unreachable Gemini model-catalog extractor (`models.ts`), Factory's Gemini model-catalog fetch (`agentModels.ts`), and the dead Gemini sandbox-config writer (`sandbox.ts`/`gemini-settings.ts` — its generic JSON helpers stay, since Antigravity's permission writer reuses them), plus a stale `profiles.md` doc line still listing `gemini` as a live profile agent. Source: `apps/cli/src/lib/runner.ts`, `apps/cli/src/lib/models.ts`, `apps/cli/src/lib/sandbox.ts`, `apps/cli/src/lib/gemini-settings.ts`, `apps/factory/src/core/agentModels.ts`.
|
|
86
|
+
|
|
87
|
+
- **Routine transcripts now archive as `origin='routine'` sessions (RUSH-2271).** A
|
|
88
|
+
Claude (and Codex) routine writes its transcript to the per-version `CLAUDE_CONFIG_DIR`
|
|
89
|
+
/ `CODEX_HOME` home, not the sandbox overlay the archiver scanned — so routine runs
|
|
90
|
+
were indexed as ordinary `origin='cli'` sessions and never linked to their routine or
|
|
91
|
+
run. `archiveRoutineTranscripts` now reads the same per-version home `buildExecEnv`
|
|
92
|
+
writes to (re-pointed to each failover attempt's account as the chain advances), scoped
|
|
93
|
+
by a pre-spawn baseline so it copies only that run's transcript out of the shared home,
|
|
94
|
+
and `agents sessions --routine` shows them again. Kimi relocates too but its
|
|
95
|
+
routine-archive discovery reader is a separate follow-up. Source:
|
|
96
|
+
`apps/cli/src/lib/runner.ts`, `apps/cli/src/lib/routines.ts`.
|
|
97
|
+
|
|
98
|
+
- **Release lease detects a holder killed from outside (RUSH-2274).** An externally
|
|
99
|
+
killed release (SIGKILL, a severed ssh, a rebooted box) left its lease on `origin`
|
|
100
|
+
and `scripts/release-lease.sh status` read `held` for up to the 30-minute TTL with
|
|
101
|
+
nothing actually releasing. The lease now records the holding `host`, `pid`, and
|
|
102
|
+
that pid's start time, and `status` reports `holder-alive=yes|no|unknown`. A holder
|
|
103
|
+
that is provably gone is reclaimed by the next `claim` immediately instead of
|
|
104
|
+
waiting out the TTL, and a new `release-lease.sh clear` drops such a lease without
|
|
105
|
+
starting a release. A live holder is never taken at any age, an unprobeable one
|
|
106
|
+
(another box, or a lease from an older release) still falls back to the TTL, and a
|
|
107
|
+
reused pid or an unreaped zombie counts as dead rather than as a live release.
|
|
108
|
+
Source: `apps/cli/scripts/release-lease.sh`, `apps/cli/scripts/release.sh`.
|
|
109
|
+
|
|
110
|
+
- **`agents output` and the session index no longer under-count Windows hosts
|
|
111
|
+
(RUSH-2286).** A Windows box could report zero token burn / zero sessions even
|
|
112
|
+
when it was actively used, because two per-harness scanners in
|
|
113
|
+
`session/discover.ts` failed on Windows: the OpenClaw scan gated on `which
|
|
114
|
+
openclaw`, which is POSIX-only (`which` throws ENOENT on Windows, so the whole
|
|
115
|
+
OpenClaw scan silently returned before indexing anything), and the Grok scanner
|
|
116
|
+
recovered a session's version from `summary.grok_home` with a `/`-only regex
|
|
117
|
+
that never matched a backslash-separated Windows path. The OpenClaw presence
|
|
118
|
+
check now uses the cross-platform `hasCommand`, its `openclaw` invocations route
|
|
119
|
+
through `execFileShellSpec` so a Windows `.cmd`/`.ps1` shim actually launches,
|
|
120
|
+
and the Grok version regex normalizes separators first. Separately, JSON relayed
|
|
121
|
+
from a Windows peer over SSH (`agents output --host <win> --json`,
|
|
122
|
+
`agents sessions … --json`) is now stripped of any PowerShell `#< CLIXML`
|
|
123
|
+
banner before parsing (`stripClixml` in `hosts/remote-cmd.ts`), so a fleet-wide
|
|
124
|
+
rollup that folds in a Windows box no longer drops it on a `JSON.parse` failure.
|
|
125
|
+
The banner strip is applied at every remote-`--json` boundary a Windows peer's
|
|
126
|
+
output flows through: the `remote-agents-json` fan-out, the session
|
|
127
|
+
`remote-list` list/payload/tool-search parsers, the `--host` fleet passthrough
|
|
128
|
+
(`agents view --host all`), and `agents output`'s per-device fetch.
|
|
129
|
+
Source: `apps/cli/src/lib/session/discover.ts`,
|
|
130
|
+
`apps/cli/src/lib/hosts/remote-cmd.ts`, `apps/cli/src/lib/hosts/passthrough.ts`,
|
|
131
|
+
`apps/cli/src/lib/remote-agents-json.ts`,
|
|
132
|
+
`apps/cli/src/lib/session/remote-list.ts`, `apps/cli/src/commands/output.ts`.
|
|
133
|
+
|
|
134
|
+
- **`agents output` now reports the burn split and a `--pricing no-cache` scenario (RUSH-2287).**
|
|
135
|
+
The productivity rollup collapsed token burn into a single counter. It now
|
|
136
|
+
breaks the burn into uncached **input** / **cache-read** / **cache-write** tokens
|
|
137
|
+
wherever the harness records a per-message cache split (Claude, Codex, Gemini,
|
|
138
|
+
Droid) — a `burn split:` line in the text report and the three counts on `burn`
|
|
139
|
+
and every `breakdown` row in `--json`. New `--pricing no-cache` reprices cached
|
|
140
|
+
tokens at the model's full input rate to model "what would this cost with caching
|
|
141
|
+
off?"; the text report leads with that figure (breakdown column `burn(nc)`) while
|
|
142
|
+
`--json` always carries **both** `costUsd` and `costUsdNoCache` so a dashboard can
|
|
143
|
+
choose. The saving is surfaced in actual mode too (`caching: actual $X vs no-cache
|
|
144
|
+
$Y`). Backed by four new session columns (`input_tokens`, `cache_read_tokens`,
|
|
145
|
+
`cache_write_tokens`, `cost_usd_nocache`, schema v37) populated at scan time;
|
|
146
|
+
pre-upgrade sessions show total-only until re-scanned. Source:
|
|
147
|
+
`apps/cli/src/commands/output.ts`, `apps/cli/src/lib/session/{db,discover}.ts`,
|
|
148
|
+
`apps/cli/src/lib/pricing/cost.ts`.
|
|
149
|
+
|
|
150
|
+
- **Routine failures now reach the owner's phone, not just the local desktop (RUSH-2288).**
|
|
151
|
+
A `failed`/`timeout` routine finish, or a pre-spawn failure such as `auth_failed`, now
|
|
152
|
+
also pings the owner over the same channel stack `agents notify` uses (the
|
|
153
|
+
`owner.channels` in `humans.yaml`, or the legacy `notify.owner`), delivered in-process by
|
|
154
|
+
the daemon — no shelling out to `ssh mac-mini agents notify`. This closes the gap where a
|
|
155
|
+
failed scheduled routine on a headless fleet box was invisible, and specifically covers
|
|
156
|
+
the `auth_failed` case the per-routine `agents notify` prompt can never send (its agent
|
|
157
|
+
never spawned). If the primary owner channel cannot deliver from the box, the daemon walks
|
|
158
|
+
the remaining configured channels as fallbacks (Telegram and intrusive/voice channels are
|
|
159
|
+
excluded). Green routines of any kind stay silent, the existing desktop thresholds are
|
|
160
|
+
unchanged, and delivery is deduped per job+runId. Source:
|
|
161
|
+
`apps/cli/src/lib/routine-notify-owner.ts`, `apps/cli/src/lib/daemon.ts`.
|
|
162
|
+
|
|
163
|
+
- Add `agents bench list`, `agents bench run`, and `agents bench results`: benchmark cells fan out through the existing `agents run` path with isolated fixture copies, bounded concurrency, custom harness names, wall-time/exit/token capture, and durable JSON results under `~/.agents/.history/bench/` (RUSH-2302, RUSH-2303).
|
|
164
|
+
|
|
165
|
+
- **New user quickstart: install, harnesses, teams, fleet.** `apps/cli/docs/QUICKSTART.md` walks a fresh install through `agents setup`, adding and logging into harnesses, a minimal `agents teams` smoke test, and setting up a fleet (`agents devices sync`, `agents devices set-interactive`, `agents apply`) — linked from `docs/README.md` and the root README's Quickstart. Docs only — no runtime change. Source: `apps/cli/docs/QUICKSTART.md`, `apps/cli/docs/README.md`, `README.md`.
|
|
166
|
+
|
|
167
|
+
- **`agents insights` detects agent silent stalls (model goes idle until you resume).**
|
|
168
|
+
When the assistant is last to speak and the next user message is ≥5 minutes later,
|
|
169
|
+
facets count duration-bucketed `silent stall: 5-15m` / `15-60m` / `1h+` friction
|
|
170
|
+
signals; resume nudges (`continue`, `keep going`, …) after that silence also count
|
|
171
|
+
as `resume after silent stall`. Report, actions, `--narrative`, and
|
|
172
|
+
`/sessions-insights` instruct models to call these out (not reframe as "user was
|
|
173
|
+
slow"). Extractor version bumped to 5 so cached facets recompute. Source:
|
|
174
|
+
`apps/cli/src/lib/session/insights.ts`, `commands/insights.ts`,
|
|
175
|
+
`docs/06-observability.md`.
|
|
176
|
+
|
|
177
|
+
- **`agents insights` splits silent stalls by harness and model.** The By-agent/account
|
|
178
|
+
table now shows per-group stall and resume-nudge counts (so laziness is visible without
|
|
179
|
+
`--json`). Stalls are also attributed to the model that last spoke
|
|
180
|
+
(`silentStallsByModel`, "Silent stalls by model" section). Extractor version 6.
|
|
181
|
+
Source: `apps/cli/src/lib/session/insights.ts`, `commands/insights.ts`.
|
|
182
|
+
|
|
183
|
+
- **Redact Claude OAuth setup-tokens (`sk-ant-oat01-…`) from logs and exports, and reject a malformed one before it reaches the auth header (#1767).** The log redactor masked API keys (`sk-ant-api03-…`) but not OAuth setup-tokens — the generic `sk-` rule can't reach an `oat01` token because the hyphen after `ant` breaks its run — so a captured setup-token could leak verbatim into a run log or session export. `resolveClaudeSetupToken` also now validates the stored value: a corrupt `auth` bundle entry (e.g. a captured `claude setup-token` TTY banner+ANSI blob, the exact #1767 shape) is refused instead of being injected as `CLAUDE_CODE_OAUTH_TOKEN` → an invalid `Authorization: Bearer` header that crashes the run; the caller falls back to the normal login. Source: `apps/cli/src/lib/redact.ts`, `apps/cli/src/lib/claude-account-token.ts`.
|
|
184
|
+
|
|
185
|
+
- **Stop the interactive host auto-reconnect spinning forever on a flapping link
|
|
186
|
+
(#1884).** A reattach only refills the retry budget now if it reached the host
|
|
187
|
+
**and** held the remote pane for at least 10 seconds. Before, the budget refilled
|
|
188
|
+
on the preflight probe alone, so a link that reconnected and dropped the user
|
|
189
|
+
straight back out — or an attach that died at TTY negotiation every time — printed
|
|
190
|
+
`Reconnecting … (attempt 1/6)` on every cycle forever and `MAX_ATTEMPTS` bounded
|
|
191
|
+
nothing. A link that keeps dropping now spends the budget and gives up with a
|
|
192
|
+
message that says so ("kept dropping again within 10 seconds of getting back in"),
|
|
193
|
+
distinct from the unreachable-host "couldn't reconnect". A session that blinks all
|
|
194
|
+
day and reconnects into a working pane each time is unaffected. Source:
|
|
195
|
+
`apps/cli/src/lib/hosts/reconnect.ts`, `docs/hosts.md`.
|
|
196
|
+
|
|
197
|
+
- **`agents models claude` no longer lists bare legacy ids that 404 (#1892).** The
|
|
198
|
+
native-binary id-scan fallback (`scanClaudeCatalogIds`, used when the curated maps
|
|
199
|
+
come up empty) is now word-boundary anchored and matches the id body atomically, so
|
|
200
|
+
it can't scrape a bare-major prefix (`claude-sonnet-4`) out of the binary's own dotted
|
|
201
|
+
`claude-sonnet-4.6` "Typo in model ID" troubleshooting string, out of a suffix-glued
|
|
202
|
+
token (`claude-opus-4-1x`), or out of a token glued to a preceding identifier char. The
|
|
203
|
+
existing `dropBareLegacyIds` sibling-drop still removes the standalone
|
|
204
|
+
`.includes("claude-opus-4")` prefix-check artifacts; genuine bare currents
|
|
205
|
+
(`claude-sonnet-5`) are kept. Catalog output is unchanged across all shipped Claude
|
|
206
|
+
binaries. Source: `apps/cli/src/lib/models.ts`.
|
|
207
|
+
|
|
208
|
+
- **Make ended-session focus open the correct recovery target (#2108).** `agents sessions focus <id>` now reaps metadata-less dead tmux panes, proves the indexed transcript belongs to the exact active version home before native resume, launches Claude from the transcript's original project directory, and passes replacement-version `/continue` as an interactive positional prompt. Source: `apps/cli/src/lib/session/recovery.ts`, `apps/cli/src/lib/tmux/session.ts`, `apps/cli/src/lib/exec.ts`.
|
|
209
|
+
|
|
210
|
+
- **The multi-install warning now inventories copies outside `PATH` and flags
|
|
211
|
+
legacy installs that can corrupt the shared macOS helper bundle (#2147).**
|
|
212
|
+
Discovery covers NVM, fnm, Volta, Bun, common npm global prefixes, and npm's
|
|
213
|
+
`_npx` cache in addition to resolving every `agents` entry on `PATH`. Dev
|
|
214
|
+
installs are no longer hidden: a copy without the atomic
|
|
215
|
+
`app-bundle-install` module is labelled `unsafe legacy helper installer —
|
|
216
|
+
remove this copy`, because invoking it can still replace a live `.app` with a
|
|
217
|
+
partial bundle. Source: `apps/cli/src/lib/self-update.ts`,
|
|
218
|
+
`apps/cli/src/index.ts`.
|
|
219
|
+
|
|
220
|
+
- **Newest signed agents-cli install owns the menu-bar helper (#2210).** On multi-install Macs (e.g. Homebrew + nvm), a newer release now takes over the helper immediately and an older install can no longer reclaim or downgrade it. Equal-version foreign installs keep the existing owner; missing-helper, Developer-ID repair, and unversioned legacy cooldown behavior are unchanged. Source: `apps/cli/src/lib/menubar/install-menubar.ts`.
|
|
221
|
+
|
|
222
|
+
- **Layered resource listing is ~40% faster.** `getActiveResourceProfile()` read
|
|
223
|
+
`agents.yaml` twice per call — once up front, then again inside
|
|
224
|
+
`getActiveResourceProfileName()` — and `listResources()` calls it once per
|
|
225
|
+
resolved resource, so a listing paid two memoized `readMeta()` round-trips
|
|
226
|
+
(`ensureAgentsDir()` plus four `stat`s each) for every entry. Reading it only
|
|
227
|
+
after the profile name is known drops one of them. Measured on `yosemite-s1`
|
|
228
|
+
against the real `~/.agents`: one pass over all eight resource kinds (135
|
|
229
|
+
entries) went 10.52 ms → 6.23 ms, and `agents doctor --json` spends ~243 ms in
|
|
230
|
+
this path across 95 listings. No behavior change: the read count is never
|
|
231
|
+
higher on any path and is unchanged whenever a profile name resolves — the one
|
|
232
|
+
saved read is the up-front one that the `if (!name) return null;` guard now
|
|
233
|
+
skips. The `ensureAgentsDir()` side effect is unchanged because
|
|
234
|
+
`getActiveResourceProfileName()` always reaches `readMeta()`, via
|
|
235
|
+
`brand.ts` `listBrands()` when a brand is set and via
|
|
236
|
+
`resource-profiles.ts` otherwise. Source:
|
|
237
|
+
`apps/cli/src/lib/resource-profiles.ts`.
|
|
238
|
+
|
|
239
|
+
- **Routine session discovery now supports an interactive picker and fuzzy names (RUSH-1998).** `agents sessions --routine` opens a routine picker on a TTY with each routine's last run, run count, and latest-run session count; the selected sessions are grouped by run ID and timestamp. `--routine <name>` accepts exact, substring, or unambiguous typo matches, and `--routines` is an alias for the same session filter.
|
|
240
|
+
|
|
241
|
+
- **Secret leases now have one scoped, time-boxed domain model (RUSH-2254).** A lease names one bundle, an explicit validated key subset, an absolute expiry, harness scope, and sleep-persistence posture. Durations use the broker's 1-minute to 30-day safety bounds, duplicate keys normalize once, unknown keys fail closed, and expired leases cannot project values. Source: `apps/cli/src/lib/secrets/lease.ts`.
|
|
242
|
+
|
|
243
|
+
- **Fleet devices accept an explicit SSH private-key path (RUSH-2265).** `agents devices set <name> --auth key --identity-file <path>` stores the path on that device and every shared SSH invocation passes it to OpenSSH with `-i`, so devices no longer depend on whichever key the ambient ssh agent happens to offer. Switching a device from password to key auth also removes stale password-bundle metadata from the registry.
|
|
244
|
+
|
|
245
|
+
- **`agents doctor` diagnoses Windows OpenSSH public-key enrollment (RUSH-2266).** On Windows it reads the effective `AuthorizedKeysFile`, selects the ProgramData administrator file or per-user profile file, verifies a public-key record is present, and checks that the administrator file grants `FullControl` to only `SYSTEM` and `Administrators`. The audit is read-only and never reads or prints private keys or passwords; fleet doctor forwards a locally authored summary and directs operators to run doctor on that box for details.
|
|
246
|
+
|
|
247
|
+
## 1.22.26
|
|
248
|
+
|
|
249
|
+
- Make bare `agents setup` a re-runnable onboarding hub with live capability status and direct access to browser, computer, secrets, fleet, share, watchdog, and preference wizards.
|
|
250
|
+
|
|
251
|
+
- **`agents apply --provision-secrets` pushes the manifest's declared secrets
|
|
252
|
+
bundles to each device, instead of only printing a reminder (RUSH-1968).** This
|
|
253
|
+
gap is a direct cause of the ticket: an operator who needed secrets on a worker
|
|
254
|
+
box had no supported path — `apply` said "recreate manually" and nothing else —
|
|
255
|
+
so they hand-exported the file store's master key across the fleet. The
|
|
256
|
+
provisioning primitive now exists, and `apply` runs it as a fifth reconcile
|
|
257
|
+
phase, last, because it is the most sensitive mutation `apply` performs.
|
|
258
|
+
|
|
259
|
+
It is **off by default** and is a **flag, not a manifest field**: `agents.yaml`
|
|
260
|
+
is shared, so a file-level default would mean someone else's `apply -y` silently
|
|
261
|
+
ships credential values. Three gates, and every refusal still prints a
|
|
262
|
+
`needs-secret` reminder so a skipped device is never silent — the flag must be
|
|
263
|
+
set, the device must be reachable, and its host key must be **pinned** (the same
|
|
264
|
+
bar `agents exec --copy-creds` sets, EXEC-34).
|
|
265
|
+
|
|
266
|
+
**Backend follows the platform: `file` on Linux, `keychain` on macOS/Windows.**
|
|
267
|
+
That is the load-bearing default — a headless Linux box has no keychain and its
|
|
268
|
+
file store auto-provisions its OWN machine-local key, so each device gets an
|
|
269
|
+
unshared at-rest key and **no passphrase is forwarded**. That is the direct
|
|
270
|
+
alternative to the fleet-wide shared secret this ticket is about.
|
|
271
|
+
|
|
272
|
+
With provisioning on, `apply` runs one extra `agents secrets list --json` per
|
|
273
|
+
device (metadata only — names and timestamps, never values) and skips a bundle
|
|
274
|
+
the device already has; without that, every run re-resolves the bundle locally
|
|
275
|
+
and a resolve can prompt for Touch ID, so a converged fleet would nag on every
|
|
276
|
+
apply. It compares presence, not content — `--force` re-pushes regardless. The
|
|
277
|
+
`--plan` matrix gains a `secrets` column, shown only when the manifest declares
|
|
278
|
+
bundles, and names the flag when the capability is available but off. Source:
|
|
279
|
+
`apps/cli/src/lib/secrets/push.ts` (extracted from the `export --host` action so
|
|
280
|
+
a lib no longer needs a command module), `apps/cli/src/lib/fleet/apply.ts`,
|
|
281
|
+
`apps/cli/src/commands/apply.ts`.
|
|
282
|
+
|
|
283
|
+
- **`agents teams` auto-scheduling is health-, harness-, and load-aware, and fails loud when no pool device can run the agent (RUSH-2002).** Placing an unpinned teammate onto a `--devices` pool used to be a pure roster count that could land it on an unreachable box, an overloaded one, or one where its agent isn't installed. `teams start` now probes the pool once (reachability + load from the same snapshot `agents devices` shows, plus whether the teammate's agent is installed there) and: excludes unreachable / overloaded (`loaded` headroom) / `agents.max-concurrent`-capped / not-installed devices, then ranks the survivors by agent installed + signed in, then lower load, then fewer running teammates. If no pool device can run a pending teammate's agent, `teams start` fails loud — `No device in the team pool can run claude@2.1.112. Run 'agents devices ping' to see which devices have the agent installed + signed in.` — instead of stranding the teammate or silently falling back to a local run; `--force` downgrades it to a warning. A probe that could not reach the pool does not trigger the failure (no false positives). The pick stays pure and fully unit-tested; `teams add` is unchanged (no probe on the add path). Source: `apps/cli/src/lib/teams/scheduler.ts`, `apps/cli/src/lib/teams/placement-probe.ts`, `apps/cli/src/lib/teams/agents.ts`, `apps/cli/src/commands/teams.ts`.
|
|
284
|
+
|
|
285
|
+
- **`agents reconnect [session-id]` re-enters a dropped remote agent terminal, and the auto-reconnect no longer dead-ends on a dead pane (RUSH-2085).** When the network dropped during `agents run --device <box>` and the peer's tmux pane was gone by the time the link came back, the reattach ran `agents sessions focus <id> --local --attach-only`, which hard-failed with `No live session matching …` and dropped the user at a bare shell with the id scrolled off screen. Two fixes: the auto-reconnect reattach now runs `agents sessions focus <id> --local` (no `--attach-only`), so a surviving pane is joined and a dead one RESUMES in place instead of dead-ending; and a new `agents reconnect` (also `agents sessions reconnect`) is the manual companion for after the auto-loop gave up or a VS Code terminal tab closed — attach the live pane if it survived, else resume the session. With no id it targets the most recent session started from the current directory (the terminal that most likely just dropped), not the full fleet picker. The exhausted / remote-exit notices now print the exact `agents reconnect <id>` command instead of a raw id and a shell prompt. Source: `apps/cli/src/lib/hosts/reconnect.ts`, `apps/cli/src/commands/reconnect.ts`.
|
|
286
|
+
|
|
287
|
+
- **`agents routines add` now rejects an agent the local daemon can't fire, at add time (RUSH-2102).** `--agent opencode` (or any real, installable agent outside the daemon's `AGENT_COMMANDS` table — currently `claude`, `codex`, `gemini`, `cursor`, `kimi`, `droid`, `muse`) used to pass `validateJob` because it only checked the agent against the full agent registry, not the daemon-runnable subset — the routine was written to disk and only failed once the scheduler fired it (`Unsupported agent for daemon jobs: opencode`). `validateJob` now rejects it immediately for the default local placement, with an error naming the supported agents. Routines placed with `hostStrategy: host`/`fleet`/`cloud` are unaffected — those dispatch through `agents run`/a cloud provider, not this table, so a wider agent set is legitimately supported there. Source: `apps/cli/src/lib/routines.ts`, `apps/cli/src/lib/agents.ts`.
|
|
288
|
+
|
|
289
|
+
- **OpenClaw's capability table no longer claims `hooks: true` with zero hooks
|
|
290
|
+
ever installed (RUSH-2122).** `registerHooksToSettings` has no `openclaw`
|
|
291
|
+
branch and silently returned `{ registered: [], errors: [] }` for it, so
|
|
292
|
+
`agents sync openclaw` reported success while installing nothing, and
|
|
293
|
+
`agents doctor` treated the agent as hooks-capable with no way to detect the
|
|
294
|
+
gap. OpenClaw only exposes a fixed set of internal, named hooks (e.g.
|
|
295
|
+
`boot-md`, which runs `BOOT.md` on gateway restart) — there is no general
|
|
296
|
+
event->shell-command registration surface an agents-cli `hooks.yaml`
|
|
297
|
+
manifest could target — so `capabilities.hooks` and `supportsHooks` now read
|
|
298
|
+
`false`, matching what the CLI can actually do. A new completeness test
|
|
299
|
+
(`hooks-capability-completeness.test.ts`) pins every `hooks: true` agent to a
|
|
300
|
+
real branch in `registerHooksToSettings` so a capability flip can never ship
|
|
301
|
+
again without a registrar behind it. Source: `apps/cli/src/lib/agents.ts`,
|
|
302
|
+
`apps/cli/src/lib/hooks-capability-completeness.test.ts`.
|
|
303
|
+
|
|
304
|
+
- **`agents browser stream` keeps one Node process and browser-daemon IPC socket warm across repeated actions (RUSH-2149).** The newline-delimited JSON interface sends every request through the existing browser daemon and its cached CDP connection, so screenshot/click loops no longer need a fresh `agents` process or IPC connection per action. `--task` (or `AGENTS_BROWSER_TASK`) supplies the default task, a `start` response becomes the default for later lines, and malformed input returns an error response without ending the stream. Fleet-remote `start` requests enforce the same device-local `browser remote-control` consent gate as the ordinary command. Source: `apps/cli/src/lib/browser/ipc.ts`, `apps/cli/src/lib/browser/stream.ts`, `apps/cli/src/commands/browser.ts`.
|
|
305
|
+
|
|
306
|
+
- **`agents sessions backfill tools` reads a growing transcript incrementally, and
|
|
307
|
+
the search index compacts itself (RUSH-2208).** Incremental discovery already
|
|
308
|
+
appended tool calls for a Claude/Codex session that grew; the backfill did not.
|
|
309
|
+
Every `ensureToolIndex` pass re-read the transcript from byte 0 and deleted the
|
|
310
|
+
session's stored evidence to rewrite it, so a session backfilled N times cost N
|
|
311
|
+
full parses of an ever-larger file — measured on a 4.5 MiB, 4000-call transcript
|
|
312
|
+
that grew by 20 calls: 344 ms and 4020 calls re-parsed, now 12 ms and 20 calls.
|
|
313
|
+
Schema v36 adds a resume point to `tool_scan_ledger` (`parsed_offset`, the byte
|
|
314
|
+
just past the last complete record consumed, and `parser_state`, the collector
|
|
315
|
+
snapshot at that offset), so a transcript that only grew is read from where the
|
|
316
|
+
last pass stopped and merged into what is already stored; the batch byte budget
|
|
317
|
+
now counts the bytes a pass actually reads rather than the file's size, so one
|
|
318
|
+
bounded batch covers far more growing sessions. A different extractor version, a
|
|
319
|
+
mismatched ledger path, a file shorter than what was parsed, or an unreadable
|
|
320
|
+
snapshot still re-reads the whole file. Two related fixes ride along:
|
|
321
|
+
`tool_call_text` rows are addressed by the `rowid` of the call they describe
|
|
322
|
+
instead of the UNINDEXED `call_key`, which made every delete a full scan of the
|
|
323
|
+
FTS index, and the scan path now runs a bounded, threshold-gated FTS `'merge'`
|
|
324
|
+
after each batch of writes, so index health no longer depends on someone running
|
|
325
|
+
`agents sessions optimize` by hand. Source: `apps/cli/src/lib/session/tool-index.ts`,
|
|
326
|
+
`apps/cli/src/lib/session/tool-store.ts`, `apps/cli/src/lib/session/db.ts`.
|
|
327
|
+
|
|
328
|
+
- **OpenCode session scans re-index only the sessions that changed (RUSH-2210).** OpenCode
|
|
329
|
+
keeps every session in one shared `opencode.db`, and the scanner stamped each session
|
|
330
|
+
with that whole file's mtime/size. Any write to any session therefore invalidated every
|
|
331
|
+
indexed session, so a single new turn re-emitted up to 1000 sessions — and the indexer
|
|
332
|
+
re-opened `opencode.db` once per re-emitted session to re-parse a transcript that had
|
|
333
|
+
not moved. Each session is now stamped with its own newest write time (across its
|
|
334
|
+
`session` row, its messages, and its parts) and the byte length of its message + part
|
|
335
|
+
payloads, so an unchanged session is skipped; the file-level stat stays only as the
|
|
336
|
+
cheap "nothing changed at all" short-circuit, and a scan opens `opencode.db` once
|
|
337
|
+
instead of once per session. The stamp deliberately does not rely on
|
|
338
|
+
`session.time_updated` alone, which real databases leave hours behind the session's
|
|
339
|
+
newest part. A side effect: `sessions.file_size` for an OpenCode row is now that
|
|
340
|
+
session's payload size instead of the whole database's size, so the tool-backfill byte
|
|
341
|
+
budget and its 16 MiB in-memory parser cap finally reflect the real cost of parsing
|
|
342
|
+
that one session. Source: `apps/cli/src/lib/session/discover.ts`.
|
|
343
|
+
|
|
344
|
+
- **Session query hot path is indexable again (RUSH-2211).** The default `agents
|
|
345
|
+
sessions` listing sort (`ORDER BY IFNULL(last_activity, timestamp) DESC`)
|
|
346
|
+
wrapped the sort column in `IFNULL()`, which defeats `idx_sessions_last_activity`
|
|
347
|
+
and forces a full table sort on every list/resume query; a new migration
|
|
348
|
+
backfills `last_activity` so it's unconditionally `NOT NULL` and the sort now
|
|
349
|
+
runs on the bare column (`EXPLAIN QUERY PLAN` confirms `USING INDEX
|
|
350
|
+
idx_sessions_last_activity`). The post-query existence check now batches
|
|
351
|
+
`fs.existsSync` per directory instead of one stat syscall per row — real
|
|
352
|
+
transcript trees put many sessions in one project directory, so this collapses
|
|
353
|
+
thousands of stats into a handful of `readdirSync` calls with the same result.
|
|
354
|
+
Interactive label search (`ftsSearch`) no longer runs a leading-wildcard
|
|
355
|
+
`LOWER(label) LIKE '%q%'` scan of the whole `sessions` table on every keystroke;
|
|
356
|
+
it now queries the already-indexed FTS5 `label` column. Source:
|
|
357
|
+
`apps/cli/src/lib/session/db.ts`.
|
|
358
|
+
|
|
359
|
+
- **The standalone `browser` binary now routes `--host`/`--device` (RUSH-2214).** `browser start --host <box>` dispatches to the remote over SSH, exactly like `agents browser start --host <box>` already did — previously the standalone bin dropped the flag with `unknown option '--host'` because it never entered the top-level router. A self-named or absent host still runs locally. Source: `apps/cli/src/browser.ts`, `apps/cli/src/lib/hosts/passthrough.ts`.
|
|
360
|
+
|
|
361
|
+
- **`agents run --device` no longer reports a host as unreachable when the SSH probe times out (RUSH-2249).** The ready probe (`readyProbe` in `hosts/ready.ts`) now disables SSH multiplexing so a stale control socket cannot hang the local client, and it checks `r.timedOut` before parsing stdout — a slow login shell (nvm/sdkman init, cold node startup) producing an empty stdout was silently treated as "not reachable". A timeout now surfaces a distinct, actionable error that names the cause and suggests `agents ssh <host> agents view` to confirm manually, rather than the misleading "not reachable over SSH" message. Source: `apps/cli/src/lib/hosts/ready.ts`.
|
|
362
|
+
|
|
363
|
+
- **`agents teams start` nudges the operator toward feed milestones (RUSH-2250).**
|
|
364
|
+
After launching teammates, `teams start` now prints a one-line tip — teammates are
|
|
365
|
+
briefed to post IMPORTANT milestones to the feed (watch them with
|
|
366
|
+
`agents feed timeline`), and team progress is watched with `agents teams status
|
|
367
|
+
<team>`. Print-only in both the single-wave and `--watch` paths (suppressed under
|
|
368
|
+
`--json`); no engine behavior changes. Pairs with the `.agents-system` guidance
|
|
369
|
+
that instructs teammates to post those milestones. Source:
|
|
370
|
+
`apps/cli/src/commands/teams.ts`.
|
|
371
|
+
|
|
372
|
+
- **`secrets list` no longer skips every biometry-ACL'd item, so `hold`/`always`-policy
|
|
373
|
+
bundles are readable again (RUSH-2251).** A regression first shipped in v1.22.10 added
|
|
374
|
+
`kSecUseAuthenticationUI: kSecUseAuthenticationUISkip` to the keychain helper's `list`
|
|
375
|
+
data-protection pass. `UISkip` makes `SecItemCopyMatching` silently omit every item
|
|
376
|
+
protected by a biometry access control — which is exactly the value items `set` writes —
|
|
377
|
+
so enumeration returned only the no-ACL metadata and `never`-policy items. Every consumer
|
|
378
|
+
that builds its keychain read set from that enumeration (`secrets exec`/`get`/`unlock`/
|
|
379
|
+
`view --reveal`/`export`, `agents run --secrets`, `ssh`, `browser`, `share`) then reported
|
|
380
|
+
the real secrets as `stored item '…' not found`, and `unlock` could not even warm the
|
|
381
|
+
broker to work around it. The DP pass is now attributes-only with **no** `kSecUseAuthenticationUI`
|
|
382
|
+
key: `kSecReturnAttributes` without `kSecReturnData` never evaluates the ACL, so it
|
|
383
|
+
neither prompts for Touch ID nor filters the ACL'd items out — restoring the design the
|
|
384
|
+
code comment already described. The RUSH-2233 timeout bound on that pass is unchanged.
|
|
385
|
+
Source: `apps/cli/src/lib/secrets/keychain-helper.swift`.
|
|
386
|
+
|
|
387
|
+
- **Hook-cache background refresh recovers from an orphaned single-flight lock (RUSH-2259).**
|
|
388
|
+
The stale-while-revalidate lock (`<cache>.bg.lck`) was only released by the
|
|
389
|
+
background refresh's `EXIT` trap, so a hard kill (SIGKILL, OOM, reboot) that
|
|
390
|
+
skipped the trap orphaned the dir and every future refresh's `mkdir` failed —
|
|
391
|
+
permanently stalling background refresh while stale cache was served forever.
|
|
392
|
+
The shim now reclaims a lock older than a 5-minute TTL before acquiring, so a
|
|
393
|
+
dead lock self-heals on the next fire. Source: `apps/cli/src/lib/hooks/cache.ts`.
|
|
394
|
+
|
|
395
|
+
- **`agents doctor` now fails loud when this box cannot reach the owner-delivery lane (RUSH-2262).** The feed/notify owner lane (`agents notify`, `agents feed post --level important` / `--blocked`) delivers over the rush-backed owner channel (iMessage), which only works from a context that has `rush` on PATH and can read its keychain-bound session — so a headless Linux fleet box (no rush) or a non-GUI SSH session on a mac (login keychain locked) silently could not escalate a blocked agent, surfacing only as an after-the-fact `owner failed: …` line. `agents doctor` had no signal for it. A new critical finding, `owner-sink-unreachable`, probes the same transport from the same context doctor runs in (`which rush` + `rush whoami`, never `~/.rush/user.yaml`, since the token is a keychain item) and reports `owner → unreachable: rush CLI not on this box's PATH` / `rush has no usable session here` with the fix. It fires only when owner delivery is configured for the fleet, so an un-opted-in box is never flagged; `agents notify --dry-run` is not this check (it short-circuits before the `which rush` preflight and reports success even where rush is absent). Source: `apps/cli/src/lib/channels/owner-sink.ts`, `apps/cli/src/lib/devices/doctor-findings.ts`, `apps/cli/src/commands/doctor.ts`.
|
|
396
|
+
|
|
397
|
+
- **`agents insights` owns counter mix; `agents trends` is a deprecated alias.** The
|
|
398
|
+
former top-level `trends` tree (harness/model mix, tools-per-session, token ratios,
|
|
399
|
+
secrets/browser recipes, raw usage query) now lives under `agents insights mix` and
|
|
400
|
+
`agents insights <recipe>` / `query` / `recipes`. Bare `agents insights` remains the
|
|
401
|
+
behavioural report (transcript content, account split). `agents trends` still works
|
|
402
|
+
but prints one deprecation line and runs the same mix tree — no second implementation.
|
|
403
|
+
**Why:** two peer "analytics" verbs (`insights` + `trends`) taught agents and humans
|
|
404
|
+
to guess; one verb, two engines (content vs counters). Latency stays on `agents perf`;
|
|
405
|
+
quota on `agents usage`; skill/slash popularity on `agents sessions stats`. Source:
|
|
406
|
+
`apps/cli/src/lib/analytics/mix-commands.ts`, `commands/insights.ts`,
|
|
407
|
+
`commands/trends.ts`, `docs/06-observability.md`.
|
|
408
|
+
|
|
409
|
+
- **The keychain reaper no longer kills the auto-lock-on-sleep watcher (RUSH-2232 follow-up).**
|
|
410
|
+
The reaper (shipped in 1.22.23) classified a process as a reap target purely by the
|
|
411
|
+
helper binary path, which also matches the broker's deliberately long-lived
|
|
412
|
+
`watch-lock` watcher — a healthy child of the live daemon that wipes the in-memory
|
|
413
|
+
secret store on sleep. Its class-(b) rule ("helper child of a live parent, older than
|
|
414
|
+
90s") therefore killed the watcher on its second sweep (~10 min after the daemon
|
|
415
|
+
started hosting the broker), silently disabling auto-lock-on-sleep. Reap-eligibility
|
|
416
|
+
now matches the full command line and excludes the `watch-lock` verb, so only the
|
|
417
|
+
short-lived keychain reads/writes a wedged `coreauthd` can hang are ever reaped.
|
|
418
|
+
Source: `apps/cli/src/lib/secrets/reaper.ts` (`isReapableHelperCommand`).
|
|
419
|
+
|
|
3
420
|
## 1.22.25
|
|
4
421
|
|
|
5
422
|
---
|
|
@@ -168,6 +585,16 @@ Add Cursor Cloud Agents as a native cloud provider so `agents run cursor --cloud
|
|
|
168
585
|
|
|
169
586
|
- **`agents run --lease` now shares one warm pool across repositories by default (RUSH-2225).** Repo sandbox/CI `profile:` labels no longer split lease reuse into one idle box per repo; a dedicated lease pool is explicit with `.crabbox.yaml` `leaseProfile:`. An empty pool keeps its newly warmed box for later callers. Concurrent runs attach with crabbox `--reclaim` and launch with separate working trees, agent homes, and credential files, so callers share compute without clobbering run state. Switching repos re-syncs the checkout, trading cache latency for lower idle-compute cost. Source: `apps/cli/src/lib/crabbox/config.ts`, `apps/cli/src/lib/crabbox/lease.ts`, `apps/cli/src/commands/exec.ts`.
|
|
170
587
|
|
|
588
|
+
- **`agents sessions insights` turns multi-harness session history into an action list
|
|
589
|
+
(RUSH-2280).** The existing `agents insights` command is now also nested under the
|
|
590
|
+
sessions noun, accepts repeatable `--agent` filters, and reports deterministic offline
|
|
591
|
+
friction/thrash, owner corrections, automatable repeats, harness split, and ranked
|
|
592
|
+
rule/skill/automation/product actions with evidence counts and shortened sample session
|
|
593
|
+
ids. `/sessions-insights` is a thin agent entry over the same CLI implementation;
|
|
594
|
+
`--narrative` remains opt-in and receives aggregate data only. Source:
|
|
595
|
+
`apps/cli/src/commands/insights.ts`, `apps/cli/src/lib/session/insights.ts`,
|
|
596
|
+
`.agents/commands/sessions-insights.md`.
|
|
597
|
+
|
|
171
598
|
- **`agents sessions focus` recovers dead panes and shares the sessions browser's selectors (GH-2108).** A retained tmux `remain-on-exit` pane is probed through `#{pane_dead}` immediately before attach, so dead or missing panes no longer open a `Pane is dead` screen. `focus` accepts session ids, topic/path searches, `agent@version` selectors (including per-device `latest`/`oldest`), device, project/time, team/routine, skill/plugin, favorites, and the complete live-state union. Focus, resume, attach, and `run --resume` now use one recovery decision on the origin device: a healthy exact origin performs native resume; otherwise balanced selection chooses a healthy version of the same harness and sends `/continue <id>` to read the indexed transcript, including transcripts retained under version trash. Host-dispatched rows persist the dispatch host as their origin, and `attach` routes its detach-record cleanup there before resuming. No usable same-harness version fails with the device, origin version, and account-health reason. Source: `apps/cli/src/commands/focus.ts`, `apps/cli/src/commands/sessions-browser.ts`, `apps/cli/src/lib/session/recovery.ts`.
|
|
172
599
|
|
|
173
600
|
- **`agents secrets setup` no longer tells you to set `AGENTS_SECRETS_PASSPHRASE`, and
|
package/README.md
CHANGED
|
@@ -45,11 +45,14 @@ https://agents-cli.sh/demo.mp4
|
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
47
|
npm install -g @phnx-labs/agents-cli # or: curl -fsSL agi-cli.sh | sh
|
|
48
|
-
agents setup # first-time setup
|
|
48
|
+
agents setup # first-time setup, or re-open the capability hub
|
|
49
|
+
agents setup status # readiness for browser, computer, fleet, and more
|
|
49
50
|
agents run claude "explain this repo" # run any agent on your existing subscription
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
`agents setup` is interactive and idempotent -- safe to re-run on a
|
|
53
|
+
`agents setup` is interactive and idempotent -- safe to re-run on any machine. Once core setup exists, it opens a status-aware menu for browser, computer, secrets, fleet, share, watchdog, and device preferences; each choice delegates to the same wizard available under `agents setup <capability>`. In CI or another non-TTY, bare setup prints the checklist without prompting. The `agi-cli.sh` one-liner installs this same canonical `@phnx-labs/agents-cli` package. Prefer bun? `bun install -g @phnx-labs/agents-cli` works too.
|
|
54
|
+
|
|
55
|
+
Full path -- installing harnesses, logging in, smoke-testing `agents teams`, and setting up your own fleet: [`apps/cli/docs/QUICKSTART.md`](apps/cli/docs/QUICKSTART.md).
|
|
53
56
|
|
|
54
57
|
Already installed? `agents upgrade` updates agents-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 -- there is no `agents update` (on macOS, `agents helper update` is a different command that reinstalls the keychain helper, not agents-cli).
|
|
55
58
|
|
|
@@ -295,8 +298,16 @@ agents sessions backfill tools --fleet
|
|
|
295
298
|
agents sessions stats
|
|
296
299
|
agents sessions stats --zero # only the never-invoked (dead weight)
|
|
297
300
|
agents sessions backfill resources # fold historical sessions into the usage index
|
|
301
|
+
|
|
302
|
+
# Friction, owner corrections, repeated recipes, and ranked actions across harnesses
|
|
303
|
+
agents sessions insights --since 30d
|
|
304
|
+
agents sessions insights --agent claude --agent codex --json
|
|
305
|
+
# Top-level alias
|
|
306
|
+
agents insights --since 7d
|
|
298
307
|
```
|
|
299
308
|
|
|
309
|
+
`sessions insights` is deterministic and offline by default. It caches per-session facets, compares harnesses, and emits an actions table with evidence counts plus shortened sample session ids. `--narrative` is opt-in and receives aggregates only, never raw transcripts. The installed `/sessions-insights` slash command invokes the same CLI source of truth.
|
|
310
|
+
|
|
300
311
|
Interactive picker when you're in a terminal. Structured output (`--json`, `--markdown`, filtered by role or turn count) when piped.
|
|
301
312
|
|
|
302
313
|
Backed by a SQLite + FTS5 index at `~/.agents/.history/sessions/sessions.db` with incremental scanning -- warm reads in ~100ms. Tool-call evidence is redacted and bounded before it is cached; repeated `--query` clauses must match distinct calls in one session. Tool queries read SQLite only: `agents sessions backfill tools` performs the one-time historical parse, while normal incremental scans index new and changed sessions. The index stores ordered static Bash program sites, so `--count` reports occurrences, containing tool calls, and distinct sessions without reparsing. `--fleet` executes one origin partition per device, so synced mirrors cannot duplicate compact evidence or counts returned over SSH; transcript bodies stay on their origin machine. This uses relational SQLite rows and literal FTS5 only, with no embeddings, vector database, or model calls. External tools can consume `--json` output as a programmatic observability layer; see [docs/05-sessions.md](apps/cli/docs/05-sessions.md) for the schemas and [docs/06-observability.md](apps/cli/docs/06-observability.md) for the consumption patterns.
|
|
@@ -361,7 +372,7 @@ agents resume 019fd0c8-b3e9-77a2-a1a4-444698c4d897 # original harness/version/d
|
|
|
361
372
|
agents run auto --resume 019fd0c8-b3e9-77a2-a1a4-444698c4d897 # adapt if its account is unavailable
|
|
362
373
|
```
|
|
363
374
|
|
|
364
|
-
`agents sessions resume` reopens several sessions in whatever terminal you're in -- auto-detected across iTerm, Ghostty, tmux, and the VSCodium agent-terminal, or forced with `--iterm` / `--ghostty` / `--tmux` / `--vscodium`. `agents resume <id>` resumes one session without requiring you to name its harness: exact IDs take a local SQLite fast path, then resolve fleet-wide and recover on the source device. If the origin version is installed, signed in, and
|
|
375
|
+
`agents sessions resume` reopens several sessions in whatever terminal you're in -- auto-detected across iTerm, Ghostty, tmux, and the VSCodium agent-terminal, or forced with `--iterm` / `--ghostty` / `--tmux` / `--vscodium`. `agents resume <id>` resumes one session without requiring you to name its harness: exact IDs take a local SQLite fast path, then resolve fleet-wide and recover on the source device. If the origin version is installed, signed in, healthy, and still owns the indexed transcript, its isolated home performs native resume. Claude launches that native resume from the original project directory recorded before the first turn, so its `projects/<cwd-key>` lookup reaches the conversation even when the session later changed directories. Otherwise a healthy version of the **same harness** starts with `/continue <id>`, which reads the indexed transcript even when the old version home is retained under version trash or the same version number was reinstalled into a new home. It never native-resumes from a different isolated home. Back them with **tmux** and the runs turn durable: detach, close your editor, reboot the GUI -- the session is still alive to `agents tmux attach`. The whole `agents tmux` subsystem (persistent multiplexer sessions that survive editor restarts and can be shared with other tools) sits underneath.
|
|
365
376
|
|
|
366
377
|
### Send an agent to the background — and bring it back
|
|
367
378
|
|
|
@@ -537,6 +548,9 @@ agents fleet status # online/offline rollup + NEEDS ATTENTIO
|
|
|
537
548
|
agents fleet status --verbose # full per-device auth/CLI/sync/version grid
|
|
538
549
|
agents fleet status --live # force a live resource probe (alias of --refresh)
|
|
539
550
|
agents fleet status --json --strict # scriptable fleet health gate
|
|
551
|
+
agents devices harnesses # per device: agent@version · account · signed · quota · ready
|
|
552
|
+
agents devices accounts # same, one row per account (which harnesses share it)
|
|
553
|
+
agents devices harnesses --agents claude,codex --json # scoped, machine-readable
|
|
540
554
|
agents doctor --check --devices # CI drift gate across every registered device
|
|
541
555
|
|
|
542
556
|
# Your Tailscale fleet, auto-discovered
|
|
@@ -585,6 +599,18 @@ endpoint — e.g. codex/grok — benign), `◐degraded` (soft/self-healing: expi
|
|
|
585
599
|
rate-limited), and `○revoked` (server rejected — re-login now). Only `○` means a real
|
|
586
600
|
re-login is needed. Run `agents fleet ping` to force a live re-verification across the fleet.
|
|
587
601
|
|
|
602
|
+
`agents devices harnesses` answers "what can each box actually run right now?" — one row
|
|
603
|
+
per installed `agent@version` across the fleet with its **account**, **signed-in**,
|
|
604
|
+
**quota** (highest usage-window utilization; `*` = from the cached snapshot), and a single
|
|
605
|
+
**ready** verdict (signed in AND not rate-limited). It SSH-probes each online device
|
|
606
|
+
(bounded, so one unreachable box can't stall the glance) and reuses the daemon-warmed usage
|
|
607
|
+
cache, so it never blocks on a per-account network fetch — pass `--refresh` (`--live`) for a
|
|
608
|
+
live quota read. `agents devices accounts` is the same data through the **identity lens**:
|
|
609
|
+
one row per account, collapsing the installs that share it (e.g. five claude versions on one
|
|
610
|
+
email) and naming which harnesses use it — the fast way to see which accounts are logged in
|
|
611
|
+
and healthy across every machine. Scope either with `--agents <csv>` / `--device <csv>`, and
|
|
612
|
+
add `--json` for the machine-readable per-host rows.
|
|
613
|
+
|
|
588
614
|
**Hosts** (`agents hosts`) are git-synced dispatch targets in `agents.yaml`; **devices** (`agents devices`) are your Tailscale machines in a local registry. Both ride SSH and feed one host pool: devices appear in `agents hosts list` and capability routing without a second enrollment. On `--host` runs every `agents run` option is either forwarded (`--effort --env --timeout --loop …`), rejected loud (`--secrets` never crosses SSH implicitly), or consumed locally — nothing silently drops. See [docs/00-concepts.md](apps/cli/docs/00-concepts.md#devices--hosts).
|
|
589
615
|
|
|
590
616
|
Every `--host` command rides one multiplexed SSH engine, tuned for driving a fleet from a small laptop: the first call to a machine opens a control socket and every later call reuses it (no repeat TCP+auth handshake), connections carry keepalive so a dropped link dies in ~45 s instead of zombying, and following a remote run polls in a single round-trip per cycle. Measured against a Tailscale-relayed host: repeated calls **~6–7× faster**, dispatch readiness **~2×**, and the follow loop **~21× faster with 50% fewer local ssh spawns**. Design: [docs/09-ssh-transport.md](apps/cli/docs/09-ssh-transport.md) · reproduce: `node scripts/bench-ssh.mjs <host>`.
|
|
@@ -820,6 +846,12 @@ agents browser done # Close task's tabs when finished
|
|
|
820
846
|
|
|
821
847
|
# Need to address a different task in the same shell? Override per call:
|
|
822
848
|
agents browser screenshot --task other-flow
|
|
849
|
+
|
|
850
|
+
# Repeated observe/action loops: one Node process and daemon socket stay warm.
|
|
851
|
+
printf '%s\n' \
|
|
852
|
+
'{"action":"screenshot","path":"/tmp/page.jpg"}' \
|
|
853
|
+
'{"action":"click","atX":320,"atY":540}' \
|
|
854
|
+
| agents browser stream --task "$AGENTS_BROWSER_TASK"
|
|
823
855
|
```
|
|
824
856
|
|
|
825
857
|
### Why this works where Playwright fails
|
package/dist/bin/agents
CHANGED
|
Binary file
|
package/dist/browser.js
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { registerBrowserSubcommands } from './commands/browser.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
import { maybeRunStandaloneOnHost } from './lib/hosts/passthrough.js';
|
|
5
|
+
async function main() {
|
|
6
|
+
// `browser … --host <box>` routes to a remote over SSH, exactly like
|
|
7
|
+
// `agents browser … --host <box>` does through index.ts. Standalone-only:
|
|
8
|
+
// this binary never enters index.ts, so without this the flag was dropped.
|
|
9
|
+
if (await maybeRunStandaloneOnHost('browser')) {
|
|
10
|
+
process.exit(process.exitCode ?? 0);
|
|
11
|
+
}
|
|
12
|
+
const program = new Command();
|
|
13
|
+
program.name('browser').description('Browser automation via CDP');
|
|
14
|
+
registerBrowserSubcommands(program);
|
|
15
|
+
program.parse();
|
|
16
|
+
}
|
|
17
|
+
void main();
|