@phnx-labs/agents-cli 1.22.22 → 1.22.24
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 +402 -0
- package/README.md +13 -6
- package/dist/bin/agents +0 -0
- package/dist/commands/attach.d.ts +2 -0
- package/dist/commands/attach.js +32 -7
- package/dist/commands/defaults.js +2 -0
- package/dist/commands/doctor.js +20 -7
- package/dist/commands/exec.js +100 -34
- package/dist/commands/feed.d.ts +18 -0
- package/dist/commands/feed.js +44 -1
- package/dist/commands/focus.d.ts +108 -5
- package/dist/commands/focus.js +455 -32
- package/dist/commands/fork.d.ts +20 -2
- package/dist/commands/fork.js +91 -64
- package/dist/commands/go.d.ts +39 -1
- package/dist/commands/go.js +112 -7
- package/dist/commands/harness-wizard.d.ts +206 -0
- package/dist/commands/harness-wizard.js +403 -0
- package/dist/commands/harness.d.ts +12 -0
- package/dist/commands/harness.js +97 -101
- package/dist/commands/insights.js +6 -2
- package/dist/commands/inspect.js +39 -5
- package/dist/commands/menubar.js +6 -1
- package/dist/commands/models.js +1 -0
- package/dist/commands/modes.d.ts +12 -0
- package/dist/commands/modes.js +147 -0
- package/dist/commands/resume.js +10 -3
- package/dist/commands/secrets-sync.js +11 -13
- package/dist/commands/secrets.d.ts +2 -0
- package/dist/commands/secrets.js +79 -47
- package/dist/commands/sessions-browser.d.ts +35 -0
- package/dist/commands/sessions-browser.js +140 -14
- package/dist/commands/sessions-resume.d.ts +23 -3
- package/dist/commands/sessions-resume.js +73 -19
- package/dist/commands/sessions.d.ts +91 -5
- package/dist/commands/sessions.js +359 -125
- package/dist/commands/setup-secrets.js +1 -1
- package/dist/commands/sync.js +246 -42
- package/dist/commands/view.js +2 -0
- package/dist/commands/watchdog.js +13 -2
- package/dist/index.js +2 -1
- package/dist/lib/agent-modes.d.ts +49 -0
- package/dist/lib/agent-modes.js +70 -0
- package/dist/lib/agents.d.ts +1 -1
- package/dist/lib/agents.js +132 -0
- package/dist/lib/codex-policy.d.ts +17 -0
- package/dist/lib/codex-policy.js +48 -0
- package/dist/lib/crabbox/lease.d.ts +25 -0
- package/dist/lib/crabbox/lease.js +62 -0
- package/dist/lib/daemon.js +70 -0
- package/dist/lib/doctor-diff.d.ts +3 -0
- package/dist/lib/doctor-diff.js +15 -13
- package/dist/lib/event-stream.d.ts +3 -1
- package/dist/lib/event-stream.js +14 -1
- package/dist/lib/exec.d.ts +16 -0
- package/dist/lib/exec.js +175 -62
- package/dist/lib/feed-broadcast.d.ts +1 -20
- package/dist/lib/feed-broadcast.js +31 -1
- package/dist/lib/hooks/cache.js +36 -3
- package/dist/lib/hooks.d.ts +19 -7
- package/dist/lib/hooks.js +100 -40
- package/dist/lib/hosts/session-index.d.ts +4 -0
- package/dist/lib/hosts/session-index.js +7 -0
- package/dist/lib/manifest.d.ts +12 -2
- package/dist/lib/manifest.js +60 -5
- package/dist/lib/mcp.js +44 -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 +52 -2
- package/dist/lib/menubar/install-menubar.js +128 -6
- package/dist/lib/models.d.ts +0 -5
- package/dist/lib/models.js +48 -0
- package/dist/lib/plugin-marketplace.js +9 -0
- package/dist/lib/pricing/prices.json +119 -92
- package/dist/lib/pricing/table.js +13 -0
- package/dist/lib/refresh.d.ts +5 -0
- package/dist/lib/refresh.js +37 -33
- package/dist/lib/remote-agents-json.d.ts +29 -1
- package/dist/lib/remote-agents-json.js +47 -10
- package/dist/lib/resource-inventory.d.ts +79 -0
- package/dist/lib/resource-inventory.js +122 -0
- package/dist/lib/resources/mcp.js +2 -0
- package/dist/lib/resources/permissions.js +3 -0
- package/dist/lib/resources/types.d.ts +2 -1
- package/dist/lib/resources.js +8 -5
- package/dist/lib/run-defaults.d.ts +2 -0
- package/dist/lib/run-defaults.js +23 -2
- package/dist/lib/runner.js +50 -36
- 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/bundles.js +157 -65
- package/dist/lib/secrets/filestore.d.ts +5 -3
- package/dist/lib/secrets/filestore.js +12 -8
- package/dist/lib/secrets/index.d.ts +15 -1
- package/dist/lib/secrets/index.js +148 -53
- package/dist/lib/secrets/reaper.d.ts +97 -0
- package/dist/lib/secrets/reaper.js +219 -0
- package/dist/lib/secrets/remote.d.ts +29 -0
- package/dist/lib/secrets/remote.js +37 -1
- package/dist/lib/secrets/sync-passphrase.d.ts +27 -0
- package/dist/lib/secrets/sync-passphrase.js +78 -0
- package/dist/lib/session/active.d.ts +36 -1
- package/dist/lib/session/active.js +60 -19
- package/dist/lib/session/actor-sidecar.d.ts +14 -0
- package/dist/lib/session/actor-sidecar.js +67 -4
- package/dist/lib/session/db.d.ts +1 -1
- package/dist/lib/session/db.js +32 -1
- package/dist/lib/session/discover.js +168 -0
- package/dist/lib/session/parse.d.ts +10 -0
- package/dist/lib/session/parse.js +98 -0
- package/dist/lib/session/recovery.d.ts +37 -0
- package/dist/lib/session/recovery.js +95 -0
- package/dist/lib/session/remote-list.d.ts +10 -1
- package/dist/lib/session/remote-list.js +2 -8
- package/dist/lib/session/remote.d.ts +57 -3
- package/dist/lib/session/remote.js +90 -26
- package/dist/lib/session/resume-command.d.ts +6 -0
- package/dist/lib/session/resume-command.js +8 -0
- package/dist/lib/session/session-cache.d.ts +173 -0
- package/dist/lib/session/session-cache.js +399 -0
- package/dist/lib/session/types.d.ts +1 -1
- package/dist/lib/session/types.js +1 -1
- package/dist/lib/session/width.d.ts +1 -1
- package/dist/lib/session/width.js +12 -2
- package/dist/lib/shims.d.ts +2 -2
- package/dist/lib/shims.js +62 -8
- package/dist/lib/staleness/writers/hooks.js +1 -1
- package/dist/lib/startup/command-registry.d.ts +1 -0
- package/dist/lib/startup/command-registry.js +2 -0
- package/dist/lib/sync-umbrella.d.ts +5 -0
- package/dist/lib/sync-umbrella.js +5 -4
- package/dist/lib/tmux/session.d.ts +4 -2
- package/dist/lib/tmux/session.js +5 -5
- package/dist/lib/types.d.ts +3 -1
- package/dist/lib/usage.d.ts +13 -0
- package/dist/lib/usage.js +215 -0
- package/dist/lib/versions.js +13 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,407 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.22.24
|
|
4
|
+
|
|
5
|
+
- **`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`.
|
|
6
|
+
|
|
7
|
+
- **`agents secrets setup` no longer tells you to set `AGENTS_SECRETS_PASSPHRASE`, and
|
|
8
|
+
`docs/secrets.md` stops recommending the shell-rc export it flags as a leak
|
|
9
|
+
(RUSH-1968).** The file-backend note read `set AGENTS_SECRETS_PASSPHRASE for headless
|
|
10
|
+
encrypted-file reads`, implying a requirement; headless reads have worked with no
|
|
11
|
+
passphrase since the store began auto-provisioning a 0600 machine-local key, so it now
|
|
12
|
+
says so and names the real path. The docs were worse than merely stale: they called an
|
|
13
|
+
rc export *"Recommended for shared/CI machines"* and the 0600 key file *"identical to"*
|
|
14
|
+
it, which is how a master key ended up in `~/.zshenv` on seven worker boxes. That
|
|
15
|
+
equivalence is inverted — the key file is read by one process, an rc export is inherited
|
|
16
|
+
by every child and readable from `/proc/<pid>/environ` — and the section also named a
|
|
17
|
+
pre-#479 key path (`~/.agents/.cache/secrets/.passphrase`, now
|
|
18
|
+
`~/.agents/.secrets-key/passphrase`) and a TTY prompt step `getPassphrase` no longer
|
|
19
|
+
has. A new `docs-hygiene.test.ts` pins those claims against the shipped doc so the
|
|
20
|
+
advice cannot drift back. Source: `apps/cli/docs/secrets.md`,
|
|
21
|
+
`apps/cli/src/commands/setup-secrets.ts`, `apps/cli/src/lib/secrets/filestore.ts`.
|
|
22
|
+
|
|
23
|
+
- **`agents secrets push`/`pull`, `agents sync --secrets`, and `agents secrets
|
|
24
|
+
export --to-file` / `import --from-file` read `AGENTS_SYNC_PASSPHRASE` now;
|
|
25
|
+
`AGENTS_SECRETS_PASSPHRASE` is the file store's master key and nothing else
|
|
26
|
+
(RUSH-1968).** One variable meant two different secrets: the local file store's master
|
|
27
|
+
key, and the passphrase that seals a bundle for transport. The store stopped needing a
|
|
28
|
+
passphrase once it auto-provisioned a machine-local key, but headless `push`/`pull`
|
|
29
|
+
still hard-failed without one — so the only way to get unattended sync on a worker box
|
|
30
|
+
was to export the **master key** fleet-wide, handing every same-user process the key to
|
|
31
|
+
the whole store. Splitting them means a box that only needs headless sync sets
|
|
32
|
+
`AGENTS_SYNC_PASSPHRASE` and never has the master key in its environment. The old name
|
|
33
|
+
still works for sync as a deprecated fallback — warned exactly once per process, so a
|
|
34
|
+
`push --all` over many bundles does not flood stderr — so scripted CI and release
|
|
35
|
+
automation keep working across the upgrade. The headless error now names the new
|
|
36
|
+
variable (`A sync passphrase is required. Run from a TTY, or set
|
|
37
|
+
AGENTS_SYNC_PASSPHRASE.`), and `agents sync`'s skip line with it — it previously read
|
|
38
|
+
`no passphrase available`, naming nothing an operator could act on. Note the legacy
|
|
39
|
+
fallback only works where that value is also the store's master key, since the old name
|
|
40
|
+
still keys the store; that coupling is the thing being retired. Resolution moved to
|
|
41
|
+
one chokepoint so the once-per-process promise holds rather than being per-call-site. Also
|
|
42
|
+
corrects `SEC-29a`, which claimed the variable applied "exclusively" to the file and
|
|
43
|
+
age-vault backends: the age-vault backend never reads it (it is gated by `agents
|
|
44
|
+
login`), and sync plus the portable `--to-file` envelope were two more consumers — the
|
|
45
|
+
new `SEC-29b` states the split as a normative invariant. Source:
|
|
46
|
+
`apps/cli/src/lib/secrets/sync-passphrase.ts`, `apps/cli/src/commands/secrets-sync.ts`,
|
|
47
|
+
`apps/cli/src/commands/sync.ts`, `apps/cli/src/lib/sync-umbrella.ts`.
|
|
48
|
+
|
|
49
|
+
- Added `--team` as an alias for `agents sessions --teams`. (RUSH-1995)
|
|
50
|
+
- Added absolute `agents secrets unlock --until <date>` expiry, mutually exclusive with relative `--ttl`. (RUSH-1960)
|
|
51
|
+
- Added persisted per-agent-version reasoning effort defaults and surfaced them in `agents view`. (RUSH-2005)
|
|
52
|
+
|
|
53
|
+
- **`agents feed` no longer crashes when the session index is locked (RUSH-2006).**
|
|
54
|
+
Outcome enrichment calls `discoverSessions` against `sessions.db`; under concurrent
|
|
55
|
+
scanner/daemon pressure that open can throw `SQLITE_BUSY` / "database is locked"
|
|
56
|
+
and take down the whole feed. A lock error now degrades to an empty meta set with a
|
|
57
|
+
stderr warning so blocks still render. Source: `apps/cli/src/commands/feed.ts`.
|
|
58
|
+
|
|
59
|
+
- **`agents events --event` / filtered activity reads no longer miss matches under
|
|
60
|
+
`--limit` (RUSH-2093).** The unified reader capped activity records *before*
|
|
61
|
+
applying the event-type filter, so a rare match older than the newest-N routine
|
|
62
|
+
rows (e.g. one `pr.opened` under twenty `file.edited`) was silently dropped. Event
|
|
63
|
+
types are now passed into `readRecentActivity` so the cap counts matching rows; a
|
|
64
|
+
non-`activity` `--module` skips the activity half entirely. Source:
|
|
65
|
+
`apps/cli/src/lib/event-stream.ts`.
|
|
66
|
+
|
|
67
|
+
- **`agents mcp add` no longer strips comments from `agents.yaml`.** The
|
|
68
|
+
write path (`writeManifest` / `serializeManifest` in `src/lib/manifest.ts`)
|
|
69
|
+
used plain `yaml.stringify`, which dropped every hand-written comment on
|
|
70
|
+
every add. It now round-trips via `yaml.parseDocument` and edits only the
|
|
71
|
+
keys that changed — the same approach `serializeCentral` already uses for
|
|
72
|
+
the central meta file (RUSH-2090).
|
|
73
|
+
|
|
74
|
+
- **Hook cache refresh is now single-flight, backs off on failure, and logs its
|
|
75
|
+
real exit code (RUSH-2121).** The background refresh in the hook cache shim
|
|
76
|
+
acquires an atomic `mkdir` lock, so concurrent hook invocations no longer
|
|
77
|
+
stampede into N parallel refreshes; a persistently-failing refresh records a
|
|
78
|
+
failure timestamp and is skipped until a 60s backoff elapses instead of
|
|
79
|
+
re-firing on every invocation; and the refresh now emits a `hook.cache.refresh`
|
|
80
|
+
event carrying the subshell's real exit code instead of a hardcoded `0`.
|
|
81
|
+
Source: `apps/cli/src/lib/hooks/cache.ts`.
|
|
82
|
+
|
|
83
|
+
- **`agents sync --host all` no longer fails every peer with `unknown option
|
|
84
|
+
'--json'`.** Fleet fan-out injects `--json` on each remote so the roster can
|
|
85
|
+
parse per-device results, but `sync` never registered the flag. Register
|
|
86
|
+
`--json` on `agents sync` and emit a machine-readable umbrella/agent/repo
|
|
87
|
+
payload so peers accept the flag and return parseable stdout (RUSH-2216).
|
|
88
|
+
Source: `apps/cli/src/commands/sync.ts`.
|
|
89
|
+
|
|
90
|
+
- **A wedged keychain can no longer pile up `agents` processes (RUSH-2231, RUSH-2232).**
|
|
91
|
+
A stalled macOS `coreauthd` used to hang the signed keychain helper's XPC receive
|
|
92
|
+
forever, so every secrets-touching `agents` command blocked and dozens of helper
|
|
93
|
+
processes plus their `<defunct>` zombies accumulated and made the machine sluggish.
|
|
94
|
+
Two fixes: **(Layer 1)** every keychain-helper `spawnSync` is now bounded and
|
|
95
|
+
hard-killed (SIGKILL) on timeout — 8s for never-prompt verbs (`has`/`set`/`delete`/
|
|
96
|
+
`list*`), 60s for the may-prompt reads (`get`/`get-batch`/`migrate-*`) — surfacing a
|
|
97
|
+
typed timeout error and arming the read back-off instead of hanging.
|
|
98
|
+
**(Layer 3)** the daemon reaps the backlog: a 5-minute tick kills orphaned helpers
|
|
99
|
+
(reparented to PID 1, past a 30s grace) and, two-sweep-debounced, the helper child of
|
|
100
|
+
an `agents` proc stuck past 90s (child first, escalating to the parent only if it
|
|
101
|
+
stays wedged) — never touching a process whose start-time can't be captured or whose
|
|
102
|
+
path doesn't match the helper. Any keychain touch now also opportunistically starts
|
|
103
|
+
the daemon so the reaper runs even on a secrets-only box. Source:
|
|
104
|
+
`apps/cli/src/lib/secrets/index.ts`, `apps/cli/src/lib/secrets/reaper.ts`,
|
|
105
|
+
`apps/cli/src/lib/daemon.ts`.
|
|
106
|
+
|
|
107
|
+
- **`agents inspect` and `agents doctor` now report harness-scoped hook inventory as capable, on-disk, wired, and unmanaged state.** Their JSON output carries the same state sets from `getResourceInventory`, so a harness with hook files or native wiring no longer collapses to a misleading `Hooks (0)` summary. Inventory is keyed by agent harness and installed version, not by configured model. Source: `apps/cli/src/lib/resource-inventory.ts`, `apps/cli/src/commands/inspect.ts`, `apps/cli/src/lib/doctor-diff.ts`.
|
|
108
|
+
|
|
109
|
+
- **Fix: the keychain-helper reaper never reaped on macOS.** The daemon reaper shelled `ps -o etimes` — a GNU/Linux procps keyword that macOS `ps` rejects with a non-zero exit — so `execFileSync` threw on every tick and `reapOrphanedKeychainProcesses` returned `reaped: 0` on its only supported platform, leaving orphaned/wedged `Agents CLI` helper processes to pile up. Switched to the portable BSD `etime` keyword (`[[dd-]hh:]mm:ss`) with a parser to seconds. This also un-quarantines the darwin integration test that #2153 had to `it.skip` to unblock releases: that test's symlink fixture was correct all along — it read `reaped: 0` only because the reaper's own `ps etimes` call threw before parsing anything. Verified on macOS 15.4.1: 20/20 reaper tests pass, the integration test reaping a real orphaned sleeper. Source: `apps/cli/src/lib/secrets/reaper.ts`, `reaper.test.ts`.
|
|
110
|
+
|
|
111
|
+
- **`agents modes [agent[@version]]` lists the permission modes a harness accepts.** The modes analog of `agents models`: for Claude / Codex / Cursor / …, shows which `--mode plan|edit|auto|skip` values work, the native CLI flags, the native default (`*`), any configured `run.defaults` mode, and degrade notes (e.g. plan→edit on Cursor). `agents inspect` also prints the mode list next to capabilities, and `agents run --help` / `agents models` point at the new command. Source: `apps/cli/src/commands/modes.ts`, `apps/cli/src/lib/agent-modes.ts`.
|
|
112
|
+
|
|
113
|
+
- **`agents insights --all` now works as an alias for `--since all`.** It previously
|
|
114
|
+
exited with `unknown option '--all'` — a hard failure in the middle of a report the
|
|
115
|
+
user asked for, on the spelling most people reach for first. An explicit `--since`
|
|
116
|
+
still wins, so `--all --since 7d` resolves to 7d rather than silently contradicting
|
|
117
|
+
itself. Source: `apps/cli/src/commands/insights.ts`.
|
|
118
|
+
|
|
119
|
+
- **Coexisting agents-cli installs no longer fight over the menu-bar helper.** The
|
|
120
|
+
helper lives at one path in Application Support, but every install on the box runs
|
|
121
|
+
the startup self-heal, and both the version stamp and the plist's baked
|
|
122
|
+
`AGENTS_ENTRY` record whichever copy acted last — so each copy read the others'
|
|
123
|
+
marks as drift and recopied the app bundle over them. Recopying replaces the
|
|
124
|
+
executable under the running helper and kills it, launchd `KeepAlive` restarts it,
|
|
125
|
+
and the next copy repeats it: a new pid every 5-15 seconds, 578 launches in one
|
|
126
|
+
observed helper log, and a status item that never stayed visible while
|
|
127
|
+
`agents menubar status` still reported `running: yes` (a pid always existed). The
|
|
128
|
+
plist's `AGENTS_ENTRY` is now treated as the owner and only the owner reinstalls
|
|
129
|
+
freely; a same-install upgrade keeps its entry path, so `npm update` still installs
|
|
130
|
+
the new helper normally. Another install still gets there — immediately if the
|
|
131
|
+
recorded owner is gone from disk, otherwise at most once an hour — so a stale copy
|
|
132
|
+
that merely still sits on disk can't freeze the menu bar for whichever install the
|
|
133
|
+
user actually upgrades. Repairs (a missing helper executable, a Developer-ID heal)
|
|
134
|
+
are never gated, and `agents menubar setup` bypasses the gate as the immediate
|
|
135
|
+
manual fix. An ad-hoc/dev-signed build never wins the timed takeover — recopying
|
|
136
|
+
an un-notarized bundle over a good one gets it rejected as "damaged" — though it
|
|
137
|
+
can still adopt a helper whose owner is gone. Two installs that are both invoked
|
|
138
|
+
regularly still trade ownership at the cooldown, so the helper restarts about once
|
|
139
|
+
an hour until one is removed; that is bounded rather than converged, and the real
|
|
140
|
+
fix remains a single install. `agents menubar status` no longer promises that a
|
|
141
|
+
stale helper "runs on next `agents` startup", which is not guaranteed on a
|
|
142
|
+
multi-install box. Fixes #2109. Source:
|
|
143
|
+
`apps/cli/src/lib/menubar/install-menubar.ts`.
|
|
144
|
+
|
|
145
|
+
- **Muse Code global binary is visible to `agents view` / `isVersionInstalled`.**
|
|
146
|
+
Muse installs a single self-updating launcher at `~/.local/bin/muse` (same
|
|
147
|
+
shape as droid), but `getBinaryPath` still resolved a version-home
|
|
148
|
+
`node_modules/.bin/muse` that never exists. After `agents import muse` /
|
|
149
|
+
`agents add muse`, version dirs now resolve to that global path so managed
|
|
150
|
+
view, collapse, and live-version bookkeeping match what actually executes;
|
|
151
|
+
install no longer writes a self-referential shim symlink. Source:
|
|
152
|
+
`apps/cli/src/lib/versions.ts`.
|
|
153
|
+
|
|
154
|
+
- **Muse multi-version isolation matches Claude/Codex (XDG pin, not bare symlink).**
|
|
155
|
+
Claude/Codex isolate per version with `CLAUDE_CONFIG_DIR` / `CODEX_HOME`.
|
|
156
|
+
Muse has no dedicated config env; it reads `$XDG_CONFIG_HOME/muse` and
|
|
157
|
+
`$XDG_DATA_HOME/muse`. After `agents import muse`, `~/.config/muse` is a
|
|
158
|
+
symlink into the version home — Muse refuses that path with
|
|
159
|
+
`Agent Definition filesystem source failed: SymlinkOrReparse` and exits 1
|
|
160
|
+
(the Zion `agents run muse@0.1.0` failure). Managed launches now pin
|
|
161
|
+
`XDG_CONFIG_HOME` + `XDG_DATA_HOME` into the version home from `buildExecEnv`,
|
|
162
|
+
the main shim, and versioned aliases (`muse@0.1.0`), the same way Claude pins
|
|
163
|
+
`CLAUDE_CONFIG_DIR`. Muse is also listed in `CONFIG_ENV_ISOLATED_AGENTS` so
|
|
164
|
+
`--isolated` installs are honest. Source: `apps/cli/src/lib/{exec,shims}.ts`.
|
|
165
|
+
|
|
166
|
+
- **Scheduled routines now run on a per-account `claude setup-token` when one is
|
|
167
|
+
provisioned, instead of throwing it away.** `buildRoutineSpawnEnv` unconditionally
|
|
168
|
+
deleted `CLAUDE_CODE_OAUTH_TOKEN`, so even after `buildExecEnv` injected a long-lived,
|
|
169
|
+
non-rotating setup-token from the reserved file-backed `auth` bundle
|
|
170
|
+
(`resolveClaudeSetupToken`), a routine still fell back to the version home's rotating
|
|
171
|
+
`.credentials.json` login. With one Claude account signed into several version homes
|
|
172
|
+
(or several fleet boxes), that rotating login is the single-use-refresh-token
|
|
173
|
+
revocation storm — one home's refresh silently revokes every sibling copy, so an
|
|
174
|
+
unattended routine keeps landing on a just-revoked token and dies with `auth_failed:
|
|
175
|
+
OAuth access token has been revoked` / `Please run /login`, even though `agents view`
|
|
176
|
+
shows the account healthy. The delete now distinguishes the two flavours: a
|
|
177
|
+
per-account setup-token (keyed to this home's own account) is re-asserted and KEPT; an
|
|
178
|
+
inherited *ambient* token (a shared value the daemon env happened to carry — the
|
|
179
|
+
RUSH-1822 fleet-logout path) is still stripped so a routine never runs on it.
|
|
180
|
+
Provision the token with `/fleet:mint-auth`. Source:
|
|
181
|
+
`apps/cli/src/lib/runner.ts` (`buildRoutineSpawnEnv`).
|
|
182
|
+
|
|
183
|
+
- **Resolved secrets no longer appear in `ps` for tmux-launched agents
|
|
184
|
+
(RUSH-2100).** An interactive `agents run` wraps the agent in tmux via
|
|
185
|
+
`exec env K=V … <agent>`, which put the entire exec env — every resolved
|
|
186
|
+
secrets-bundle value — into the pane's command line, readable by any process of
|
|
187
|
+
the same user. On one fleet box six live processes carried
|
|
188
|
+
`AGENTS_SECRETS_PASSPHRASE`, the key that decrypts every file-backed bundle on
|
|
189
|
+
that machine. The pane now sources a `0600` env file and unlinks it before
|
|
190
|
+
`exec`, so only the file path is argv-visible; a missing file aborts the pane
|
|
191
|
+
rather than launching half-configured. Every key routes through the file, not a
|
|
192
|
+
curated "secret-bearing" subset, so a newly added credential is covered without
|
|
193
|
+
anyone maintaining a list. Source: `apps/cli/src/lib/exec.ts`,
|
|
194
|
+
`apps/cli/docs/specifications.md` (SEC-8a).
|
|
195
|
+
|
|
196
|
+
## 1.22.23
|
|
197
|
+
|
|
198
|
+
- **Daemon-warmed cross-surface session-status cache (RUSH-2062).** Menubar,
|
|
199
|
+
Factory, watchdog, and CLI used to each re-run a full `sessions --active`
|
|
200
|
+
gather (~9s / ~170MB) with no sharing. The daemon now warms a local active-
|
|
201
|
+
session snapshot every 15s; those surfaces read the warm file when fresh.
|
|
202
|
+
`session/remote.ts` is cache-first too — a reachable host skips SSH while its
|
|
203
|
+
cache is within the freshness window (it used to replay only on
|
|
204
|
+
unreachable). Immutable per-session fields (topic, label, cwd, …) are memoized
|
|
205
|
+
by transcript mtime; live status never rides that memo. Source:
|
|
206
|
+
`apps/cli/src/lib/session/session-cache.ts`, `apps/cli/src/lib/session/remote.ts`,
|
|
207
|
+
`apps/cli/src/lib/daemon.ts`.
|
|
208
|
+
|
|
209
|
+
- **`agents sessions <id>` / `agents resume <id>` resolve across the fleet fast, with
|
|
210
|
+
early-exit and SSH cancellation (RUSH-2203).** The cross-machine resolve fanned out
|
|
211
|
+
with `await Promise.all` and no cancellation, so one slow or unreachable peer stalled
|
|
212
|
+
the whole lookup to the 12s per-peer timeout even after a fast peer already returned
|
|
213
|
+
the exact match — a full-UUID resolve on a fleet with an offline box took ~16-40s. A
|
|
214
|
+
**full-UUID** resolve (globally unique) now opts into a cancellable, early-exit
|
|
215
|
+
fan-out: the first peer holding it resolves the sweep and SIGTERMs every
|
|
216
|
+
still-outstanding peer, and a local UUID hit resolves with **zero** SSH.
|
|
217
|
+
`agents resume <label>` auto-resumes the one exact-label match; labels are not globally
|
|
218
|
+
unique, so they stay all-settle (a same-label session may live on another peer) — a
|
|
219
|
+
unique label resumes, a cross-machine collision surfaces as an ambiguity. The not-found
|
|
220
|
+
message reports the actual sweep result (devices searched, which were unreachable)
|
|
221
|
+
instead of the misleading "search with `--device <host>`" — fleet search is already the
|
|
222
|
+
default. `--device all` / `--devices` are accepted and mean "the whole fleet". The
|
|
223
|
+
all-settle default is unchanged for the shared fan-out's other callers (tool-search,
|
|
224
|
+
program-count) and for labels / ambiguous short-id prefixes, which still wait for every
|
|
225
|
+
peer. Source:
|
|
226
|
+
`apps/cli/src/lib/remote-agents-json.ts`, `apps/cli/src/lib/session/remote-list.ts`,
|
|
227
|
+
`apps/cli/src/commands/sessions.ts`, `apps/cli/src/commands/resume.ts`.
|
|
228
|
+
|
|
229
|
+
- **`agents sessions focus` gains device + live-state scoping and multi-select tabs
|
|
230
|
+
(RUSH-2206).** `focus` now honors `--device/--host <name>` (scope the picker to a
|
|
231
|
+
device's live sessions) and the same live-state filters `sessions --active` defines
|
|
232
|
+
(`--orphan`/`--crashed`/`--waiting`/`--idle`/`--working`/`--closed`/`--abandoned`/
|
|
233
|
+
`--queued`/`--unknown`) — they compose, so `agents sessions focus --orphan --device
|
|
234
|
+
yosemite-s0` lists only that host's orphans. The interactive picker is now
|
|
235
|
+
multi-select: check several sessions and each opens as a new tab in the terminal
|
|
236
|
+
you're in (Ghostty / iTerm / tmux, auto-detected), reusing `resume`'s batch open and
|
|
237
|
+
flood guard. Per tab, live semantics hold — a tmux session is joined (a second
|
|
238
|
+
client, no fork), local or remote over SSH; a session with no attach rail resumes a
|
|
239
|
+
copy in the tab, reported never silently dropped. `focus <id>` direct-jump and
|
|
240
|
+
`--attach-only` (old `go`) behavior are unchanged. Source:
|
|
241
|
+
`apps/cli/src/commands/focus.ts`, `apps/cli/src/commands/go.ts`.
|
|
242
|
+
|
|
243
|
+
- **`agents harness edit` is now wizard-capable, on a shared step engine (RUSH-2219).**
|
|
244
|
+
Run `agents harness edit <name>` with no flags in a terminal and it walks each field
|
|
245
|
+
(model, endpoint, auth, version, fallback, description) pre-filled with the harness's
|
|
246
|
+
current values — where before it was flag-only and errored without one. Both `add`/`fork`
|
|
247
|
+
and `edit` now drive one shared step engine: every step is skippable by the matching flag,
|
|
248
|
+
so scripting stays non-interactive and a flagless non-interactive `edit` still errors as
|
|
249
|
+
before. Endpoint and version prompts are gated by the host's API format (a host with no
|
|
250
|
+
custom-endpoint slot, or one that self-updates, shows the field disabled with a reason
|
|
251
|
+
instead of silently accepting a value the run would drop). This is the foundation the
|
|
252
|
+
model catalog, connection test, edit matrix, and cross-host portability build on.
|
|
253
|
+
Source: `apps/cli/src/commands/harness-wizard.ts`, `apps/cli/src/commands/harness.ts`.
|
|
254
|
+
|
|
255
|
+
- **Codex launches now default to safe writable access instead of an offline
|
|
256
|
+
read-only sandbox.** When no configured run default exists, omitting `--mode`
|
|
257
|
+
selects a managed workspace profile with network access, on-request approvals,
|
|
258
|
+
`~/.agents`, and regenerable build caches. Explicit `--mode plan` remains
|
|
259
|
+
filesystem-read-only but now retains network access. The same policy covers
|
|
260
|
+
`agents run`, fallback attempts, resumes, routines, direct `codex` shims,
|
|
261
|
+
versioned aliases, and Windows shim passthrough; only explicit `skip` disables
|
|
262
|
+
the sandbox and approvals. Source: `apps/cli/src/lib/codex-policy.ts`.
|
|
263
|
+
|
|
264
|
+
- **Phone forwards are shaped to a text, not a wall.** `agents feed post`
|
|
265
|
+
(`--level important` / `--blocked`), `agents notify`, and `agents send --to owner`
|
|
266
|
+
all forward to the owner's phone through one seam, `composeBroadcastMessage`; it now
|
|
267
|
+
keeps the post **title** (the scannable headline) and truncates a long **body** to a
|
|
268
|
+
short excerpt marked `… (full in feed)` (caps: 500 chars / 8 lines). The full post is
|
|
269
|
+
untouched in the feed — only the outbound phone copy is shortened — so a requested
|
|
270
|
+
long write is not lost, and enforcing it at this seam covers every sink (owner alias,
|
|
271
|
+
in-process `channel:`, spawned `command:` via `{message}`), which a per-command shell
|
|
272
|
+
hook cannot. Source: `apps/cli/src/lib/feed-broadcast.ts` (`truncateBroadcastBody`).
|
|
273
|
+
|
|
274
|
+
- **`agents run --lease` self-cleans its warm pool.** Each lease now auto-stops **expired, idle** boxes in the run's profile pool (an expired box can never be reused, so it was pure cost the 1h-idle `agents lease gc` window left running). Conservative: only a box that is running, in the same profile+netMode pool, past its lease expiry, and untouched for a grace window is stopped — a mid-boot or in-use box is never touched. Skipped when an explicit `--box <slug>` is named. Source: `apps/cli/src/lib/crabbox/lease.ts`.
|
|
275
|
+
|
|
276
|
+
- **Muse Code (Meta) harness support.** `muse` is a first-class agent: install via
|
|
277
|
+
`curl -fsSL https://dev.meta.ai/install.sh | sh`, run with `agents run muse`,
|
|
278
|
+
and use in teams. Modes map to Muse safety flags (`--disable-write` /
|
|
279
|
+
`--disable-approval` / `--yolo`); `--model` and `--reasoning-effort` are
|
|
280
|
+
forwarded; headless is `muse exec` with `--json`; interactive resume is
|
|
281
|
+
`muse resume <id>` (id immediately after the verb), headless resume is
|
|
282
|
+
`--session-id`. Sessions under `~/.local/share/muse/sessions/` (plus version
|
|
283
|
+
homes) are discovered and parsed; usage shows Meta Model API rate limits when
|
|
284
|
+
a key is present, otherwise local 7-day token totals. MCP writes to
|
|
285
|
+
`~/.config/muse/settings.json` (`mcp_servers`, `schema_version: 1`). Model
|
|
286
|
+
catalog: `muse-spark-1.2` (default), `1.1`, `1.2-contributor` with offline
|
|
287
|
+
pricing. Aliases: `muse-code`, `meta-muse`. Hooks write Claude-shaped
|
|
288
|
+
matcher groups into `~/.config/muse/settings.json` (`schema_version: 1`);
|
|
289
|
+
plugins use the Claude marketplace layout under the XDG data plugin store
|
|
290
|
+
(`~/.local/share/muse/plugins`) with `.muse-plugin` manifests. Allowlist
|
|
291
|
+
stays false (Muse uses approval-mode + sandbox, not tool-name allow/deny).
|
|
292
|
+
Source: `apps/cli/src/lib/{agents,exec,models,usage,mcp,hooks,plugins,
|
|
293
|
+
plugin-marketplace,runner,shims}.ts`, `apps/cli/src/lib/session/*`.
|
|
294
|
+
|
|
295
|
+
- **Release CI no longer re-runs the six-job cross-platform matrix on `v*` tags.**
|
|
296
|
+
The expensive `ci.yml` matrix (ubuntu + macOS + Windows × Node 22/24) still
|
|
297
|
+
runs on `release/**` branch pushes and manual `workflow_dispatch`, but not when
|
|
298
|
+
a version tag is pushed. `release.sh` tags the exact commit that already passed
|
|
299
|
+
the release-branch matrix, so the post-tag matrix was pure cost. Source:
|
|
300
|
+
`.github/workflows/ci.yml`.
|
|
301
|
+
|
|
302
|
+
- **`claude-opus-5` and `claude-sonnet-5` were unpriced, so every session using them
|
|
303
|
+
cost $0.** The pricing table carried `claude-opus-4`, `claude-sonnet-4`,
|
|
304
|
+
`claude-fable-5` and `claude-mythos-5` but not the Opus/Sonnet 5 line. Matching is
|
|
305
|
+
dash-bounded (`getModelPricing`), so `claude-opus-5` cannot fall back to the
|
|
306
|
+
`claude-opus-4` entry — it resolved to null, and an unpriced model contributes
|
|
307
|
+
nothing rather than erroring. On one real index that silently zeroed **526 sessions**,
|
|
308
|
+
478 of them the current default model, understating `agents cost`, `agents output`
|
|
309
|
+
and `agents insights` alike. Rates from the published table: Opus 5 $5/$25 per MTok
|
|
310
|
+
(cache write $6.25, cache read $0.50); Sonnet 5 $2/$10 (cache write $2.50, cache read
|
|
311
|
+
$0.20). Source: `apps/cli/src/lib/pricing/prices.json`.
|
|
312
|
+
|
|
313
|
+
- **Schema v34 reprices the sessions that were zeroed.** Adding prices alone fixes
|
|
314
|
+
nothing already indexed: `cost_usd` is computed at scan time and the scanner skips any
|
|
315
|
+
transcript whose `(file_mtime_ms, file_size)` is unchanged, so those rows would keep
|
|
316
|
+
their NULL forever. They cannot be repaired in place either — the row stores
|
|
317
|
+
`token_count` and `output_tokens` but not the uncached-input / cache-read / cache-write
|
|
318
|
+
split the price table needs. So v34 flushes `scan_ledger`, the same remedy v5 → v6 used
|
|
319
|
+
for this exact column when cost was introduced. One slower scan, then correct numbers.
|
|
320
|
+
Source: `apps/cli/src/lib/session/db.ts`.
|
|
321
|
+
|
|
322
|
+
**Sonnet 5's $2/$10 is introductory pricing that ends 2026-08-31.** From 2026-09-01 the
|
|
323
|
+
standard rate is $3/$15. The table holds one current rate per model with no notion of an
|
|
324
|
+
effective date, so that entry must be updated then or Sonnet 5 spend reads ~33% low.
|
|
325
|
+
Called out at the top of `table.ts`.
|
|
326
|
+
|
|
327
|
+
- **`agents sessions --orphan`/`--active`: cross-harness live discovery + richer rows (RUSH-2205).**
|
|
328
|
+
Two fixes. (1) The headless `ps`-scan recognized only 6 agent executables, so a
|
|
329
|
+
bare-headless `grok`/`kimi`/`antigravity`/`openclaw`/`hermes`/`rush` run was
|
|
330
|
+
silently dropped from the live views; the comm→kind map is now derived from
|
|
331
|
+
`SESSION_AGENTS` × the AGENTS registry (`cliCommand`), so every discoverable
|
|
332
|
+
harness surfaces. (2) Each live row now shows the agent **version** and a human
|
|
333
|
+
**created · idle** time cell, and backfills the **ticket/PR/label** from the
|
|
334
|
+
indexed session history onto orphan rows that lack them, with the label/topic on
|
|
335
|
+
its own line — grouped-by-directory layout unchanged, rows stay width-safe.
|
|
336
|
+
Source: `apps/cli/src/lib/session/active.ts`, `apps/cli/src/commands/sessions.ts`.
|
|
337
|
+
|
|
338
|
+
- **`agents doctor --check` verdict lines now carry a `check:` prefix and a total
|
|
339
|
+
version count**, so CI logs and log-scrapers get one consistent, grep-alike shape
|
|
340
|
+
whether the result is clean or drifted: `check: ok — 3 version(s) in sync` /
|
|
341
|
+
`check: drift — 2 stale, 1 never-synced across 3 version(s)`. The per-version
|
|
342
|
+
status badge for a never-synced version now reads `never-synced` (its real
|
|
343
|
+
status) instead of the unrelated `cold` label, and all three badges
|
|
344
|
+
(`stale`/`never-synced`/`unwired`) share one fixed-width column so the rows
|
|
345
|
+
align. Source: `apps/cli/src/commands/doctor.ts` (`runCheckGate`).
|
|
346
|
+
|
|
347
|
+
- **`agents secrets export --host --remote-backend file` no longer requires
|
|
348
|
+
`AGENTS_SECRETS_PASSPHRASE`.** Since the file store became passphrase-free
|
|
349
|
+
(auto-provisioning a 0600 machine-local key under `~/.agents/.secrets-key/`), the
|
|
350
|
+
remote `import --backend file` reads headlessly under that key with no passphrase
|
|
351
|
+
and no Touch ID — but the export path still hard-failed unless a passphrase was
|
|
352
|
+
set, and forcing one made the remote bundle require that shared passphrase to
|
|
353
|
+
read, defeating the headless use it was for. The passphrase is now **optional**:
|
|
354
|
+
with none set, the remote command carries no `AGENTS_SECRETS_PASSPHRASE`
|
|
355
|
+
read/export prologue and the .env is the only stdin, so the remote keys the bundle
|
|
356
|
+
under its own machine-local key (headless reads); set `AGENTS_SECRETS_PASSPHRASE`
|
|
357
|
+
locally only to opt into a shared off-disk key, which is still forwarded over ssh
|
|
358
|
+
stdin (never argv). This unblocks hands-off Linux-driven releases that provision
|
|
359
|
+
`apple.com` on a headless macOS sign host. Windows targets are still refused
|
|
360
|
+
cleanly. Source: `apps/cli/src/lib/secrets/remote.ts`,
|
|
361
|
+
`apps/cli/src/commands/secrets.ts`.
|
|
362
|
+
|
|
363
|
+
- **Docs: the per-command secrets Touch-ID contract is now written down and
|
|
364
|
+
accurate.** The `view --reveal` (1.22.14) and `exec` (1.22.21) interactive-unlock
|
|
365
|
+
changes shipped in code + CHANGELOG only; the reference docs still implied every
|
|
366
|
+
value command behaves the same. `docs/secrets.md` and the `secrets` skill now
|
|
367
|
+
carry an explicit Touch-ID matrix (deliberate `view --reveal`/`exec` at a real
|
|
368
|
+
terminal → one sheet on a locked bundle; `get`/`export` automation primitives →
|
|
369
|
+
never prompt, fail closed to `agents secrets unlock`; anything an agent launches →
|
|
370
|
+
broker-only), `specifications.md` adds **SEC-13b** + a `Prompts?` column on the
|
|
371
|
+
materialization table + `GWT-S2b`, and the skill's stale hold-window facts are
|
|
372
|
+
corrected (7-day default, screen-lock does not drop the hold). Docs-only; no
|
|
373
|
+
behavior change. Source: `apps/cli/docs/secrets.md`,
|
|
374
|
+
`apps/cli/docs/specifications.md`, `skills/secrets/SKILL.md`.
|
|
375
|
+
|
|
376
|
+
- **Resume session identities through one live-first path across the fleet.**
|
|
377
|
+
`agents sessions resume <selector>` accepts a full UUID, unique UUID prefix,
|
|
378
|
+
durable tmux name (`ag-codex-c1f3d813`), or unique alias suffix (`c1f3d813`). It
|
|
379
|
+
resolves the owning device, rechecks whether the process and pane are alive,
|
|
380
|
+
attaches a live pane, and otherwise resumes the harness-native conversation with
|
|
381
|
+
its recorded version, cwd, and mode. Retained dead tmux panes no longer count as
|
|
382
|
+
attachable, and native resume no longer collides with an existing live wrapper.
|
|
383
|
+
Source: `apps/cli/src/commands/focus.ts`,
|
|
384
|
+
`apps/cli/src/commands/sessions-resume.ts`, `apps/cli/src/lib/exec.ts`.
|
|
385
|
+
|
|
386
|
+
- **`agents fork` is now `agents sessions fork`.** Forking is a session operation, so
|
|
387
|
+
it lives under the `sessions` group next to `resume`/`focus` — `agents sessions fork
|
|
388
|
+
<id>` branches a conversation into a new, independent copy you can continue separately,
|
|
389
|
+
leaving the original untouched. The old top-level `agents fork` keeps working as a
|
|
390
|
+
hidden alias, so nothing that scripted it breaks. For a harness without a native copy
|
|
391
|
+
(anything but Claude today), the command now fails loud and names the manual branch —
|
|
392
|
+
start a fresh agent and seed it with `/continue <id>` — instead of only saying
|
|
393
|
+
"unsupported". Source: `apps/cli/src/commands/fork.ts`,
|
|
394
|
+
`apps/cli/src/commands/sessions.ts`.
|
|
395
|
+
|
|
396
|
+
- **Muse Code global binary is visible to `agents view` / `isVersionInstalled`.**
|
|
397
|
+
Muse installs a single self-updating launcher at `~/.local/bin/muse` (same
|
|
398
|
+
shape as droid), but `getBinaryPath` still resolved a version-home
|
|
399
|
+
`node_modules/.bin/muse` that never exists. After `agents import muse` /
|
|
400
|
+
`agents add muse`, version dirs now resolve to that global path so managed
|
|
401
|
+
view, collapse, and live-version bookkeeping match what actually executes;
|
|
402
|
+
install no longer writes a self-referential shim symlink. Source:
|
|
403
|
+
`apps/cli/src/lib/versions.ts`.
|
|
404
|
+
|
|
3
405
|
## 1.22.22
|
|
4
406
|
|
|
5
407
|
- **New: `agents insights` — how you work, split by the Claude account that did the
|
package/README.md
CHANGED
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
|
|
33
33
|
<a href="https://factory.ai" title="Factory AI Droid"><strong>Droid</strong></a>
|
|
34
34
|
|
|
35
|
+
<a href="https://dev.meta.ai/docs/muse-code" title="Meta Muse Code"><strong>Muse</strong></a>
|
|
36
|
+
|
|
35
37
|
<a href="https://omp.sh" title="Oh My Pi"><strong>Pi</strong></a>
|
|
36
38
|
</p>
|
|
37
39
|
|
|
@@ -218,7 +220,11 @@ otherwise the first permission option offered by the server. The same last-resor
|
|
|
218
220
|
warning applies.
|
|
219
221
|
|
|
220
222
|
Codex has no native smart-classifier mode, so `agents run codex --mode auto` resolves
|
|
221
|
-
to sandboxed `edit` and can still prompt. `
|
|
223
|
+
to sandboxed `edit` and can still prompt. When `--mode` is omitted for Codex, the same
|
|
224
|
+
safe writable mode is used: the workspace, `~/.agents`, and regenerable toolchain caches
|
|
225
|
+
are writable; network access is enabled; and approvals are requested on demand. An
|
|
226
|
+
explicit `--mode plan` keeps the filesystem read-only while leaving network access on.
|
|
227
|
+
`agents run codex --mode skip` is different:
|
|
222
228
|
it bypasses approvals **and** removes the sandbox. `full` remains an alias for `skip`,
|
|
223
229
|
but new scripts should use the explicit `skip` name.
|
|
224
230
|
|
|
@@ -297,6 +303,7 @@ agents sessions --idle # stopped between turns (fleet-wide)
|
|
|
297
303
|
agents sessions --orphan # agent outlived its terminal client
|
|
298
304
|
agents sessions --crashed # terminal and agent disappeared uncleanly
|
|
299
305
|
agents sessions focus a1b2c3d4 # jump back into one — attach in place, or resume
|
|
306
|
+
agents sessions focus claude@latest --device yosemite-s0 # pick latest there
|
|
300
307
|
```
|
|
301
308
|
|
|
302
309
|
On a terminal, `agents sessions --active` (and a bare `agents sessions`) open the **interactive session browser** — one filter you drive with single keys, re-pulled live across the fleet:
|
|
@@ -307,7 +314,7 @@ On a terminal, `agents sessions --active` (and a bare `agents sessions`) open th
|
|
|
307
314
|
| `r` | running only | `--active` |
|
|
308
315
|
| `f` | favorites only | `--favorites` |
|
|
309
316
|
| `*` | star / unstar the highlighted session | `agents sessions favorite <id>` |
|
|
310
|
-
| `c` | team sessions | `--teams` |
|
|
317
|
+
| `c` | team sessions | `--team` (alias: `--teams`) |
|
|
311
318
|
| `a` | agent (cycles) | `-a` |
|
|
312
319
|
| `d` | device (cycles) | `--device` |
|
|
313
320
|
| `p` | this repo ↔ all dirs | `--all` |
|
|
@@ -326,7 +333,7 @@ Filters **stack** (they AND together), the active set shows in the header, and t
|
|
|
326
333
|
| --- | --- |
|
|
327
334
|
|  |  |
|
|
328
335
|
|
|
329
|
-
Each live session resolves to `working`, `waiting_input` (with why -- a question, a plan review, or a permission prompt), `idle`, or a lifecycle state such as `orphaned`, `crashed`, `closed`, `abandoned`, `queued`, or `unknown`. Pass the matching flag (`--working`, `--idle`, `--waiting`, `--orphan`, `--crashed`, `--closed`, `--abandoned`, `--queued`, `--unknown`) directly; each implies `--active`, and several flags form a union. The fleet fan-out is already the default; `--local` opts out. `--all` instead widens historical directory and time scope. Rows also carry badges for the PR, worktree, and ticket. `agents sessions focus [
|
|
336
|
+
Each live session resolves to `working`, `waiting_input` (with why -- a question, a plan review, or a permission prompt), `idle`, or a lifecycle state such as `orphaned`, `crashed`, `closed`, `abandoned`, `queued`, or `unknown`. Pass the matching flag (`--working`, `--idle`, `--waiting`, `--orphan`, `--crashed`, `--closed`, `--abandoned`, `--queued`, `--unknown`) directly; each implies `--active`, and several flags form a union. The fleet fan-out is already the default; `--local` opts out. `--all` instead widens historical directory and time scope. Rows also carry badges for the PR, worktree, and ticket. `agents sessions focus [selector]` accepts the same agent/version, device, time, team, project, skill/plugin, favorite, and live-state filters as the session browser. A unique id focuses directly; an agent/version or text selector always opens the preview picker. Immediately before attach it checks the tmux pane process: a living pane is joined in place, while a dead/missing pane enters recovery instead of showing tmux's `Pane is dead` screen.
|
|
330
337
|
|
|
331
338
|
Landing on a session cold? `agents sessions <id>` prints a catch-up digest: an inferred title, files changed grouped by directory (created / modified / deleted), a histogram of which tools did the work (including parsed Bash commands -- `git`, `npm`, `ffmpeg`, `ssh`, and so on), and the last test verdict -- the signals to reload a task in seconds.
|
|
332
339
|
|
|
@@ -345,11 +352,11 @@ agents resume 019fd0c8-b3e9-77a2-a1a4-444698c4d897 # original harness/version/d
|
|
|
345
352
|
agents run auto --resume 019fd0c8-b3e9-77a2-a1a4-444698c4d897 # adapt if its account is unavailable
|
|
346
353
|
```
|
|
347
354
|
|
|
348
|
-
`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
|
|
355
|
+
`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 healthy, its isolated home performs native resume. 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. 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.
|
|
349
356
|
|
|
350
357
|
### Send an agent to the background — and bring it back
|
|
351
358
|
|
|
352
|
-
Running 30 agents and drowning in terminal tabs? `agents sessions detach <id>` stops a session's interactive process and keeps it working **headless** in the background -- it drives its task to done unattended, no tab, lower cost. `agents sessions attach <id>` brings it back
|
|
359
|
+
Running 30 agents and drowning in terminal tabs? `agents sessions detach <id>` stops a session's interactive process and keeps it working **headless** in the background -- it drives its task to done unattended, no tab, lower cost. `agents sessions attach <id>` brings it back through the same origin-device recovery decision: native resume in the exact healthy origin home, or same-harness `/continue` when that home is unavailable, with the full indexed history (including whatever it did while backgrounded).
|
|
353
360
|
|
|
354
361
|
```
|
|
355
362
|
agents sessions detach a1b2c3d4 # go headless in the background, keep working
|
|
@@ -684,7 +691,7 @@ tools:
|
|
|
684
691
|
---
|
|
685
692
|
```
|
|
686
693
|
|
|
687
|
-
Workflows that need to write — post PR comments, edit files, send Slack — should run with `--mode edit`, or `--mode auto` on Claude Code and GitHub Copilot. Reserve `--mode skip` (legacy alias: `full`) for last-resort bypasses. `agents run` defaults to `--mode plan`
|
|
694
|
+
Workflows that need to write — post PR comments, edit files, send Slack — should run with `--mode edit`, or `--mode auto` on Claude Code and GitHub Copilot. Reserve `--mode skip` (legacy alias: `full`) for last-resort bypasses. `agents run` defaults to `--mode plan` for other harnesses; Codex defaults to its safe writable profile. An explicit Codex `--mode plan` is read-only with network access.
|
|
688
695
|
|
|
689
696
|
Resolution is project > user > system: a `<repo>/.agents/workflows/<name>/` overrides a same-named workflow in `~/.agents/workflows/`. Commit project workflows with your repo so teammates get the same pipeline.
|
|
690
697
|
|
package/dist/bin/agents
CHANGED
|
Binary file
|
|
@@ -6,5 +6,7 @@
|
|
|
6
6
|
* history, the exact inverse of `agents sessions detach`.
|
|
7
7
|
*/
|
|
8
8
|
import type { Command } from 'commander';
|
|
9
|
+
import type { SessionMeta } from '../lib/session/types.js';
|
|
9
10
|
export declare function registerAttachCommand(program: Command): void;
|
|
10
11
|
export declare function attachAction(id: string): Promise<void>;
|
|
12
|
+
export declare function attachRecoveryArgs(session: Pick<SessionMeta, 'id'>): string[];
|
package/dist/commands/attach.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { runOnPeer } from '../lib/session/remote-list.js';
|
|
3
|
+
import { sessionRecoveryPeer } from '../lib/session/recovery.js';
|
|
4
|
+
import { resolveSessionMetadataValue, resumeSessionInPlace } from './sessions.js';
|
|
4
5
|
import { readDetachRecord, clearDetachRecord, isHeadlessAlive } from '../lib/session/detached.js';
|
|
5
6
|
export function registerAttachCommand(program) {
|
|
6
7
|
program
|
|
@@ -12,16 +13,37 @@ export function registerAttachCommand(program) {
|
|
|
12
13
|
});
|
|
13
14
|
}
|
|
14
15
|
export async function attachAction(id) {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
const outcome = await resolveSessionMetadataValue(id);
|
|
17
|
+
if (outcome.kind === 'partial') {
|
|
18
|
+
console.error(chalk.red(`Could not resolve session while these devices were unavailable: ${outcome.failedPeers.join(', ')}`));
|
|
19
|
+
process.exitCode = 2;
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (outcome.kind === 'not-found') {
|
|
20
23
|
console.error(chalk.red(`No session matching "${id}".`));
|
|
21
24
|
console.error(chalk.gray(' See your sessions: agents sessions'));
|
|
22
25
|
process.exitCode = 1;
|
|
23
26
|
return;
|
|
24
27
|
}
|
|
28
|
+
if (outcome.kind === 'ambiguous') {
|
|
29
|
+
console.error(chalk.red(`"${id}" matches ${outcome.candidates.length} sessions. Pass the full session id.`));
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const meta = outcome.session;
|
|
34
|
+
// Route the WHOLE attach operation to the origin, not just its eventual
|
|
35
|
+
// resume. The detach record and headless PID are device-local; clearing them
|
|
36
|
+
// here would leave the real background continuation running beside a second
|
|
37
|
+
// process on the owning machine.
|
|
38
|
+
const peer = sessionRecoveryPeer(meta);
|
|
39
|
+
if (peer) {
|
|
40
|
+
const routed = await runOnPeer(attachRecoveryArgs(meta), peer, { tty: true });
|
|
41
|
+
if (routed === 'no-target') {
|
|
42
|
+
console.error(chalk.red(`Cannot attach ${meta.shortId}: origin device ${peer} is not a registered reachable peer.`));
|
|
43
|
+
process.exitCode = 1;
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
25
47
|
// If it's backgrounded, stop the headless continuation first so two processes
|
|
26
48
|
// don't resume the same transcript at once.
|
|
27
49
|
const rec = readDetachRecord(meta.id);
|
|
@@ -39,3 +61,6 @@ export async function attachAction(id) {
|
|
|
39
61
|
console.log(chalk.gray(`Attaching ${meta.agent} ${meta.id.slice(0, 8)} — resuming interactively…`));
|
|
40
62
|
await resumeSessionInPlace(meta);
|
|
41
63
|
}
|
|
64
|
+
export function attachRecoveryArgs(session) {
|
|
65
|
+
return ['sessions', 'attach', session.id];
|
|
66
|
+
}
|
|
@@ -47,11 +47,13 @@ export function registerDefaultsCommands(program) {
|
|
|
47
47
|
.description('Set defaults for an agent/version selector')
|
|
48
48
|
.option('--mode <mode>', "Default mode: plan, edit, auto, skip. 'full' accepted as alias for skip.")
|
|
49
49
|
.option('--model <model>', 'Default model or model alias, forwarded via --model')
|
|
50
|
+
.option('--effort <effort>', 'Default reasoning effort: low, medium, high, xhigh, max, or auto')
|
|
50
51
|
.action((selector, options) => {
|
|
51
52
|
try {
|
|
52
53
|
const entry = setRunDefault(selector, {
|
|
53
54
|
...(options.mode !== undefined ? { mode: options.mode } : {}),
|
|
54
55
|
...(options.model !== undefined ? { model: options.model } : {}),
|
|
56
|
+
...(options.effort !== undefined ? { effort: options.effort } : {}),
|
|
55
57
|
});
|
|
56
58
|
console.log(chalk.green('Set run default:'));
|
|
57
59
|
console.log(` ${formatRunDefaultEntry(entry)}`);
|