@phnx-labs/agents-cli 1.22.24 → 1.22.25
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 +167 -1
- package/README.md +14 -4
- package/dist/bin/agents +0 -0
- package/dist/commands/cloud.js +9 -5
- package/dist/commands/doctor.d.ts +24 -0
- package/dist/commands/doctor.js +100 -9
- package/dist/commands/exec.js +19 -16
- package/dist/commands/feed.d.ts +5 -0
- package/dist/commands/feed.js +21 -1
- package/dist/commands/focus.js +2 -2
- package/dist/commands/menubar.js +8 -0
- package/dist/commands/routines.d.ts +3 -0
- package/dist/commands/routines.js +70 -47
- package/dist/commands/run-cloud.js +1 -1
- package/dist/commands/sessions-browser.d.ts +1 -1
- package/dist/commands/sessions-browser.js +27 -7
- package/dist/commands/sessions-resume.js +3 -2
- package/dist/commands/sessions.d.ts +13 -1
- package/dist/commands/sessions.js +24 -2
- package/dist/commands/setup-watchdog.js +5 -10
- package/dist/commands/setup.js +1 -1
- package/dist/commands/teams.js +3 -2
- package/dist/commands/watchdog.d.ts +3 -4
- package/dist/commands/watchdog.js +26 -66
- package/dist/index.js +36 -1
- package/dist/lib/agents.js +126 -21
- package/dist/lib/cloud/cursor.d.ts +79 -0
- package/dist/lib/cloud/cursor.js +228 -0
- package/dist/lib/cloud/registry.js +2 -0
- package/dist/lib/cloud/types.d.ts +7 -2
- package/dist/lib/cloud/types.js +14 -0
- package/dist/lib/crabbox/cli.d.ts +2 -2
- package/dist/lib/crabbox/config.d.ts +7 -8
- package/dist/lib/crabbox/config.js +14 -14
- package/dist/lib/crabbox/lease.d.ts +11 -4
- package/dist/lib/crabbox/lease.js +40 -8
- package/dist/lib/crabbox/setup-copy.d.ts +5 -0
- package/dist/lib/crabbox/setup-copy.js +17 -1
- package/dist/lib/daemon.js +27 -1
- package/dist/lib/device-config.js +7 -0
- package/dist/lib/devices/doctor-findings.d.ts +7 -1
- package/dist/lib/devices/doctor-findings.js +40 -1
- package/dist/lib/events.d.ts +9 -0
- package/dist/lib/events.js +58 -0
- package/dist/lib/exec.d.ts +3 -3
- package/dist/lib/exec.js +24 -10
- package/dist/lib/feed-outcome.d.ts +3 -0
- package/dist/lib/feed-outcome.js +18 -10
- package/dist/lib/feed.d.ts +4 -0
- package/dist/lib/hosts/passthrough.d.ts +21 -0
- package/dist/lib/hosts/passthrough.js +39 -12
- package/dist/lib/mcp.js +5 -1
- 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/snapshot.d.ts +15 -0
- package/dist/lib/menubar/snapshot.js +40 -0
- package/dist/lib/plugins.js +13 -1
- package/dist/lib/resources/mcp.js +3 -0
- package/dist/lib/routine-process-cleanup.d.ts +9 -0
- package/dist/lib/routine-process-cleanup.js +73 -0
- package/dist/lib/runner.js +5 -5
- 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 +1 -20
- package/dist/lib/secrets/filestore.d.ts +2 -0
- package/dist/lib/secrets/filestore.js +13 -0
- package/dist/lib/secrets/rc-hygiene.d.ts +14 -0
- package/dist/lib/secrets/rc-hygiene.js +14 -1
- package/dist/lib/session/active.d.ts +4 -0
- package/dist/lib/session/db.js +8 -2
- package/dist/lib/session/remote-list.d.ts +2 -0
- package/dist/lib/session/remote-list.js +1 -0
- package/dist/lib/session/session-cache.d.ts +4 -4
- package/dist/lib/session/session-cache.js +4 -4
- package/dist/lib/shims.js +21 -1
- package/dist/lib/signin-badge.js +2 -0
- package/dist/lib/startup/command-registry.d.ts +15 -0
- package/dist/lib/startup/command-registry.js +42 -0
- package/dist/lib/teams/agents.js +1 -1
- package/dist/lib/teams/parsers.d.ts +1 -1
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/versions.js +16 -1
- package/dist/lib/watchdog/service.d.ts +17 -0
- package/dist/lib/watchdog/service.js +39 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,173 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.22.25
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
issue: 2108
|
|
7
|
+
type: fixed
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
`agents sessions focus ... --active` now excludes closed and crashed registry rows; explicit lifecycle filters such as `--closed` and `--crashed` still select them. Per-device `latest` / `oldest` selectors also wait for the peer's filtered index result instead of widening to live rows whose version is unknown.
|
|
11
|
+
|
|
12
|
+
- **`agents doctor` now reports the file-store master key when it is live in the
|
|
13
|
+
process environment, not just when it is exported from a shell rc file
|
|
14
|
+
(RUSH-1968).** `rc-hygiene.ts` scans FILES, which leaves a real hole: a value
|
|
15
|
+
inherited by a long-lived process outlives the rc line that set it, so an operator
|
|
16
|
+
who deletes `~/.zshenv:8` gets a clean `rc-secret-export` while every shell, editor
|
|
17
|
+
and agent started before the edit still carries the key and hands it to everything
|
|
18
|
+
they spawn. Confirmed on `yosemite-s1`, which has zero rc exports and still had the
|
|
19
|
+
value in its environment. The new `env-secret-export` warning names that state and
|
|
20
|
+
says the deletion is not sufficient; like every other finding it reports only that
|
|
21
|
+
the variable is set, never its value. Expected inside a release sign context
|
|
22
|
+
(`headless-sign-context.sh` sets it deliberately), which the message says so an
|
|
23
|
+
operator on the home base does not chase it. Source:
|
|
24
|
+
`apps/cli/src/lib/secrets/rc-hygiene.ts` (`masterPassphraseInEnv`),
|
|
25
|
+
`apps/cli/src/lib/devices/doctor-findings.ts`, `apps/cli/src/commands/doctor.ts`.
|
|
26
|
+
|
|
27
|
+
- **`agents doctor --devices` now reports a remote box's secret hygiene, and its
|
|
28
|
+
inventory probe no longer times out on a slow box (RUSH-1968).** The fan-out ran
|
|
29
|
+
each remote's own `doctor --json` but parsed only `.fleet`, discarding the
|
|
30
|
+
`findings` the remote had already computed — so a leaking box read as clean from
|
|
31
|
+
anywhere but itself. The remote's `rc-secret-export` / `env-secret-export` rows
|
|
32
|
+
now ride back, but the remote contributes exactly one thing: the **kind**. Severity,
|
|
33
|
+
message and remediation are generated locally, and `device` is overwritten with the
|
|
34
|
+
name that was dialled. Each of those matters separately — a remediation is a command
|
|
35
|
+
a human copies and runs, a message is the one place a secret value could re-enter a
|
|
36
|
+
readout that otherwise never prints one, a severity decides the CRITICAL section, and
|
|
37
|
+
a device name decides which box gets blamed. The cost is detail: the fleet row names
|
|
38
|
+
the box and the kind, and says to run `agents doctor` there for the file and line.
|
|
39
|
+
Only those two kinds forward — sign-in and divergence rows are recomputed centrally
|
|
40
|
+
and would otherwise double.
|
|
41
|
+
|
|
42
|
+
Separately, the probe's 30s timeout was below the real cost of the command it
|
|
43
|
+
runs — `doctor --json` measures 57s on `yosemite-m0` and 136s on an idle box — so
|
|
44
|
+
every slow device silently contributed nothing at all: no inventory, no sign-in,
|
|
45
|
+
no divergence. Raised to 180s, matching `ChildProcess.doctorTimeout`, which was set
|
|
46
|
+
to 180 for this same command for this same reason. Source:
|
|
47
|
+
`apps/cli/src/commands/doctor.ts` (`asRemoteSecretFindings`, `probeFleetInventory`).
|
|
48
|
+
|
|
49
|
+
- **Feed and menu-bar session counts now use the `agents sessions --active` lifecycle model (RUSH-1993).**
|
|
50
|
+
Feed outcome headers count distinct mailbox agents in every state, so repeated
|
|
51
|
+
open blocks from one agent cannot make `needs you` exceed `agents`. Feed rows
|
|
52
|
+
replace generic `terminal` with a known host app and label routine-spawned
|
|
53
|
+
sessions as `routine:<name>`. The menu-bar snapshot backfills the same routine
|
|
54
|
+
metadata as active-session JSON and renders the full canonical status set
|
|
55
|
+
(`working`, `waiting`, `idle`, `queued`, `orphan`, `crashed`, `closed`,
|
|
56
|
+
`abandoned`, `unknown`) without reclassifying warm rows from attention files.
|
|
57
|
+
Source: `apps/cli/src/commands/feed.ts`, `apps/cli/src/commands/sessions.ts`,
|
|
58
|
+
`apps/cli/src/lib/feed-outcome.ts`, `apps/cli/src/lib/menubar/snapshot.ts`,
|
|
59
|
+
`apps/cli/menubar/Sources/MenubarHelper/{LocalState,StatusItemController}.swift`.
|
|
60
|
+
|
|
61
|
+
- **A typo'd command with `--host` said the opposite of the truth (RUSH-2022).** The
|
|
62
|
+
`--host`/`--device` router runs before commander parses, so `agents session resume
|
|
63
|
+
--host <box>` (one letter off `sessions`, which *does* accept `--host`) reported
|
|
64
|
+
`` `agents session` does not support --host/--device `` — a true statement about a
|
|
65
|
+
command nobody typed. Unknown names now fall through to `unknown command '<name>'`
|
|
66
|
+
with a did-you-mean, and the spellcheck can suggest the lazily-registered groups
|
|
67
|
+
(`sessions`/`teams`/`cloud`/…) it previously could not see. A real command with no
|
|
68
|
+
remote semantics still gets the flag-support error. Source:
|
|
69
|
+
`apps/cli/src/lib/hosts/passthrough.ts`, `apps/cli/src/lib/startup/command-registry.ts`.
|
|
70
|
+
|
|
71
|
+
- **`agents publish` is in the lazy command table.** `commands/packages.ts` registers it
|
|
72
|
+
at top level but the registry did not list it, so it only resolved through the
|
|
73
|
+
unknown-command fallback that loads the whole command tree. Found by the new test
|
|
74
|
+
that pins the command-name set against the real tree.
|
|
75
|
+
|
|
76
|
+
- **A mistyped command keeps its `--host`.** The distance-1 auto-correct now re-checks
|
|
77
|
+
routing after correcting the name, so `agents docto --host <box>` corrects to
|
|
78
|
+
`doctor` **and actually routes to `<box>`** — previously the corrected command
|
|
79
|
+
re-parsed locally with a `--host` it silently dropped (a regression caught in review:
|
|
80
|
+
it used to fail loudly with the wrong message, corrected-but-unrouted made it fail
|
|
81
|
+
silently instead). `apps/cli/src/index.ts`.
|
|
82
|
+
|
|
83
|
+
- **Cursor now supports `--mode plan` headless and interactive (RUSH-2101).** The
|
|
84
|
+
capability registry previously listed only `edit` and `skip`, so `agents run cursor --mode plan`
|
|
85
|
+
and routine jobs silently degraded to writable `edit`. `cursor-agent` has supported `--plan`
|
|
86
|
+
since the 2026-01-16 CLI release; the registry, `AGENT_COMMANDS` flag mapping, and the routine
|
|
87
|
+
runner now forward it correctly. Source: `apps/cli/src/lib/agents.ts`, `apps/cli/src/lib/exec.ts`,
|
|
88
|
+
`apps/cli/src/lib/runner.ts`.
|
|
89
|
+
|
|
90
|
+
- **`agents sessions resume` picker now filters in-memory on every keystroke instead of re-querying the database (RUSH-2212).** The `filter` callback in the multi-select picker was calling `filterSessionsByQuery`, which runs a full-text search scan against `sessions.db` on every character typed. It now uses the same cheap in-memory substring match (`sessionMatchesQuery`) the session browser already applies, so the picker stays responsive regardless of library size. Source: `apps/cli/src/commands/sessions-resume.ts`.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
type: minor
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
Add Cursor Cloud Agents as a native cloud provider so `agents run cursor --cloud` and `agents cloud run --agent cursor` dispatch through Cursor's v1 REST API, with status, streaming, cancellation, and follow-up runs.
|
|
97
|
+
|
|
98
|
+
- **A starved `coreauthd` can no longer hang `secrets list` forever (RUSH-2233).**
|
|
99
|
+
The keychain helper's `list` runs two passes, and the data-protection pass omits
|
|
100
|
+
`kSecUseAuthenticationUI: …Fail` on purpose (that flag drops every biometry-ACL
|
|
101
|
+
item even when authentication is healthy). Omitting it means the query still
|
|
102
|
+
reaches LocalAuthentication/`coreauthd`, which has no deadline of its own — a
|
|
103
|
+
wedged `coreauthd` left `SecItemCopyMatching` blocked for the life of the
|
|
104
|
+
process. That is *why* helpers accumulated for the bounded-spawn + reaper work
|
|
105
|
+
in RUSH-2231/2232 to clean up. The pass now runs on a background thread behind
|
|
106
|
+
a 3-second wait: on timeout the helper logs one line to stderr, skips the pass,
|
|
107
|
+
and prints whatever the file-keychain pass produced — the same handling the
|
|
108
|
+
screen-locked `errSecInteractionNotAllowed` case already got. Set
|
|
109
|
+
`AGENTS_KEYCHAIN_LIST_TIMEOUT_MS` to override the deadline;
|
|
110
|
+
`AGENTS_KEYCHAIN_BOUNDED_TEST=1` runs the helper's headless self-test for the
|
|
111
|
+
bounded wait. Source: `apps/cli/src/lib/secrets/keychain-helper.swift`.
|
|
112
|
+
|
|
113
|
+
- **Use one three-minute AGI Menu snapshot and one watchdog executor (RUSH-2260).**
|
|
114
|
+
The menu bar now reads routines, 40 indexed recent sessions, the daemon-warmed
|
|
115
|
+
active-session cache, and persisted watchdog state in one subprocess every three
|
|
116
|
+
minutes; `doctor --json` remains independently limited to 15 minutes. The menu no
|
|
117
|
+
longer executes watchdog ticks. The daemon is the sole automatic watchdog executor,
|
|
118
|
+
warms active sessions on the same three-minute cadence, is gated by device-local
|
|
119
|
+
`watchdog.enabled`, and cleans failed/timeout routine process groups that are still
|
|
120
|
+
alive before they can overlap a replacement run. Source:
|
|
121
|
+
`apps/cli/src/lib/menubar/snapshot.ts`, `apps/cli/src/lib/daemon.ts`,
|
|
122
|
+
`apps/cli/src/lib/routine-process-cleanup.ts`.
|
|
123
|
+
|
|
124
|
+
- **Add Warp Agent CLI (Oz) as a harness (RUSH-2261).** `warp` is now a
|
|
125
|
+
first-class harness: `agents add warp`, `agents run warp`, `agents teams add
|
|
126
|
+
<team> warp`, resource sync, and `agents view` all work. The CLI command is
|
|
127
|
+
`oz` (the shared Warp binary); install is self-updating via
|
|
128
|
+
`brew install --cask oz` (macOS) / `oz-stable` apt|yum|pacman (Linux), config
|
|
129
|
+
lives under `~/.warp/`, the rules/context file is `AGENTS.md`, and auth is
|
|
130
|
+
`oz login` (browser OAuth) or a `WARP_API_KEY` token for headless/CI.
|
|
131
|
+
Capabilities are truthful and gated by `supports()`: MCP (Claude
|
|
132
|
+
`.mcp.json` schema at `~/.warp/.mcp.json`, stdio + http with headers) and
|
|
133
|
+
skills are on; hooks, allowlist, commands, plugins, subagents, workflows, and
|
|
134
|
+
memory are off (Oz exposes no matching install surface). Sessions are not
|
|
135
|
+
indexed — Oz stores conversations server-side (retrieved with auth via
|
|
136
|
+
`oz run conversation get <id>`), so there is no local transcript for
|
|
137
|
+
`agents sessions`. No usage bar — Oz exposes no usage/limits endpoint.
|
|
138
|
+
Source: `apps/cli/src/lib/{agents,exec,mcp}.ts`.
|
|
139
|
+
|
|
140
|
+
`scripts/release.sh` now runs orchestration in a fresh release-owned worktree, so a dirty shared checkout or feature branch no longer blocks or contaminates a release.
|
|
141
|
+
|
|
142
|
+
- **Plugin discovery warns instead of silently skipping a directory with no
|
|
143
|
+
`.claude-plugin/plugin.json` (RUSH-2270).** A `plugins/<name>/` directory missing
|
|
144
|
+
(or with a malformed) manifest was invisible to `agents plugins list`/`info`/`sync`,
|
|
145
|
+
`agents doctor`, and the marketplace materialize-into-version-homes step, with zero
|
|
146
|
+
diagnostic anywhere in the chain — no `agents sync`/`agents repo pull` could
|
|
147
|
+
surface it, since discovery dropped it before any of those ran. Found via a real
|
|
148
|
+
case: the `work` plugin merged to `phnx-labs/.agents-system` without its manifest
|
|
149
|
+
and sat invisible for a full merge cycle; the same fix run against this box's own
|
|
150
|
+
`~/.agents/plugins/duck` found it missing one too. `discoverPluginsInDir` now
|
|
151
|
+
writes one `agents-cli:` warning to stderr naming the directory and the missing
|
|
152
|
+
manifest path, matching the existing advisory-not-fatal pattern
|
|
153
|
+
`syncMarketplaceManifest` already uses for a malformed (as opposed to missing)
|
|
154
|
+
manifest. Source: `apps/cli/src/lib/plugins.ts`.
|
|
155
|
+
|
|
156
|
+
- **Muse login is recognized under `providers.meta` (balanced no longer signed_out).**
|
|
157
|
+
Live `muse login` writes `~/.config/muse/auth.json` as
|
|
158
|
+
`{ schema_version, providers: { meta: { access_token, user_email, … } } }`.
|
|
159
|
+
The presence detector only walked one object level, so it never saw the token
|
|
160
|
+
under `providers.meta` and reported signed-out after a successful OAuth —
|
|
161
|
+
`agents run muse` under balanced then failed with "excluded: 0.1.0
|
|
162
|
+
(signed_out)". Detection now recurses into nested provider slots and surfaces
|
|
163
|
+
`user_email` when present. Source: `apps/cli/src/lib/agents.ts`.
|
|
164
|
+
|
|
165
|
+
- **File-backed secret resolution now fails on decryption errors instead of treating unreadable ciphertext as an absent value (RUSH-2264).** A wrong `AGENTS_SECRETS_PASSPHRASE` or tampered encrypted value now reports the affected file-store item and stops before launching a consumer with an empty secret such as `HCLOUD_TOKEN`. Source: `apps/cli/src/lib/secrets/filestore.ts`, `apps/cli/src/lib/secrets/bundles.ts`.
|
|
166
|
+
|
|
3
167
|
## 1.22.24
|
|
4
168
|
|
|
169
|
+
- **`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
|
+
|
|
5
171
|
- **`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
172
|
|
|
7
173
|
- **`agents secrets setup` no longer tells you to set `AGENTS_SECRETS_PASSPHRASE`, and
|
|
@@ -108,7 +274,7 @@
|
|
|
108
274
|
|
|
109
275
|
- **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
276
|
|
|
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
|
|
277
|
+
- **`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 Antigravity). `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
278
|
|
|
113
279
|
- **`agents insights --all` now works as an alias for `--since all`.** It previously
|
|
114
280
|
exited with `unknown option '--all'` — a hard failure in the middle of a report the
|
package/README.md
CHANGED
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
<a href="https://dev.meta.ai/docs/muse-code" title="Meta Muse Code"><strong>Muse</strong></a>
|
|
36
36
|
|
|
37
37
|
<a href="https://omp.sh" title="Oh My Pi"><strong>Pi</strong></a>
|
|
38
|
+
|
|
39
|
+
<a href="https://docs.warp.dev/reference/cli" title="Warp Agent CLI (Oz)"><strong>Warp</strong></a>
|
|
38
40
|
</p>
|
|
39
41
|
|
|
40
42
|
https://agents-cli.sh/demo.mp4
|
|
@@ -147,6 +149,13 @@ agents run antigravity "Write tests for the fixed code"
|
|
|
147
149
|
|
|
148
150
|
Each resolves to the project-pinned version with skills, MCP servers, and permissions already synced. Single-typo names auto-correct across every command — `agents view cladue` resolves to `claude`, `agents add codx@latest` to `codex`.
|
|
149
151
|
|
|
152
|
+
`agents run claude "task" --lease` reuses one shared warm crabbox pool across
|
|
153
|
+
repositories by default. Concurrent runs share the box but execute in isolated
|
|
154
|
+
`~/workspaces/<repo>-<run>` directories with separate agent homes and credential
|
|
155
|
+
files. Add `leaseProfile: private-hot-box` to
|
|
156
|
+
`.crabbox.yaml` only when a repo intentionally needs a dedicated warm pool;
|
|
157
|
+
cross-repo reuse trades re-sync latency for lower idle-compute cost.
|
|
158
|
+
|
|
150
159
|
### Rate-limited? Keep working.
|
|
151
160
|
|
|
152
161
|
```bash
|
|
@@ -405,7 +414,7 @@ agents watchdog --nudge # actually inject "Continue." into the stalled split
|
|
|
405
414
|
agents watchdog --watch # daemon loop: a tick every --interval
|
|
406
415
|
```
|
|
407
416
|
|
|
408
|
-
`agents watchdog` detects a stalled session, resolves the *exact* terminal split it lives in (tmux, iTerm, VSCodium, or a raw pty), and injects a nudge -- `Continue.` by default, or set `--text`. It's dry by default; `--nudge` acts on a single tick
|
|
417
|
+
`agents watchdog` detects a stalled session, resolves the *exact* terminal split it lives in (tmux, iTerm, VSCodium, or a raw pty), and injects a nudge -- `Continue.` by default, or set `--text`. It's dry by default; `--nudge` acts on a single tick. `agents watchdog on|off` controls the device-local daemon pass, which runs once every three minutes. Steer a single run with `agents watchdog policy <id> off | keep | handsoff`.
|
|
409
418
|
|
|
410
419
|
A stalled session whose tail shows a hard account limit ("You've hit your weekly limit · resets …") is **rotated in place** instead of nudged: the watchdog gates on the same healthy-account selection `agents run auto` makes (zero healthy → one skip event per cooldown window, terminal untouched), injects the harness's exit sequence, relaunches `agents run auto --interactive --session-id <uuid>` in the *same* tab, then replays the old session's resume once the new TUI is live. Default on; `agents watchdog rotate off` disables it (nudging stays on).
|
|
411
420
|
|
|
@@ -609,10 +618,10 @@ Team state is observable via `agents teams list --json` / `agents teams status -
|
|
|
609
618
|
|
|
610
619
|
## Cloud
|
|
611
620
|
|
|
612
|
-
Some work shouldn't tie up your laptop. `agents cloud run` hands a task to a managed provider that clones the repo, plans, implements, tests, and opens a PR -- while your terminal stays free.
|
|
621
|
+
Some work shouldn't tie up your laptop. `agents cloud run` hands a task to a managed provider that clones the repo, plans, implements, tests, and opens a PR -- while your terminal stays free. The `host` provider dispatches the same way onto machines you own: `agents cloud run "…" --host gpu-box` (tasks track in `agents cloud ps` and `agents hosts ps` alike).
|
|
613
622
|
|
|
614
623
|
<p align="center">
|
|
615
|
-
<img src="assets/cloud.svg" alt="agents cloud run dispatches one prompt to a managed provider (Rush, Codex, Factory, or Antigravity) that
|
|
624
|
+
<img src="assets/cloud.svg" alt="agents cloud run dispatches one prompt to a managed provider (Rush, Codex, Cursor, Factory, or Antigravity) that runs while you keep working" width="100%" />
|
|
616
625
|
</p>
|
|
617
626
|
|
|
618
627
|
```bash
|
|
@@ -626,7 +635,7 @@ agents cloud message <id> "also update the changelog" # steer it mid-run
|
|
|
626
635
|
agents cloud cancel <id>
|
|
627
636
|
```
|
|
628
637
|
|
|
629
|
-
|
|
638
|
+
Five managed backends behind one interface (`agents cloud providers`):
|
|
630
639
|
|
|
631
640
|
| Provider | What runs | Notes |
|
|
632
641
|
|---|---|---|
|
|
@@ -634,6 +643,7 @@ Four managed backends behind one interface (`agents cloud providers`):
|
|
|
634
643
|
| `codex` | A pre-built Codex Cloud environment | Target it with `--env`. |
|
|
635
644
|
| `factory` | `droid exec` on a cloud VM | Computer-use; pick the box with `--computer`. |
|
|
636
645
|
| `antigravity` | Gemini managed agents | Antigravity harness in a remote sandbox. |
|
|
646
|
+
| `cursor` | Cursor Cloud Agents | v1 REST API with repo, status, SSE, cancel, and follow-up runs. |
|
|
637
647
|
|
|
638
648
|
Auto-routes each `--agent` to its native cloud, or pin the backend with `--provider`. Instead of dispatching now, register a run as an **event trigger** with `--on pull_request` (also `push`, `issue_comment`, `workflow_run`) -- it persists as a trigger-bound routine that fires on the event. `--json` on every subcommand for scripting.
|
|
639
649
|
|
package/dist/bin/agents
CHANGED
|
Binary file
|
package/dist/commands/cloud.js
CHANGED
|
@@ -25,14 +25,15 @@ export function statusColor(status) {
|
|
|
25
25
|
export function registerCloudCommands(program) {
|
|
26
26
|
const cloud = program
|
|
27
27
|
.command('cloud', { hidden: true })
|
|
28
|
-
.description('Dispatch and manage cloud agent tasks across providers (Rush, Codex, Factory, Antigravity).')
|
|
28
|
+
.description('Dispatch and manage cloud agent tasks across providers (Rush, Codex, Cursor, Factory, Antigravity, Host).')
|
|
29
29
|
.addHelpText('after', `
|
|
30
30
|
Each agent runs in its own cloud. Pass --agent and the provider is auto-selected
|
|
31
|
-
(claude→rush, codex→codex, droid→factory, antigravity→antigravity); --provider overrides.
|
|
31
|
+
(claude→rush, codex→codex, cursor→cursor, droid→factory, antigravity→antigravity); --provider overrides.
|
|
32
32
|
|
|
33
33
|
Providers:
|
|
34
34
|
rush Rush Cloud — Claude against a GitHub repo + branch → PR
|
|
35
35
|
codex Codex Cloud — runs in a pre-built Codex environment (--env)
|
|
36
|
+
cursor Cursor Cloud Agents — v1 REST API, with optional GitHub repos
|
|
36
37
|
factory Factory Droid Computer — droid exec on a cloud VM (--computer)
|
|
37
38
|
antigravity Gemini Managed Agents — Antigravity harness in a remote sandbox
|
|
38
39
|
|
|
@@ -49,6 +50,9 @@ Examples:
|
|
|
49
50
|
# Codex Cloud against a saved environment
|
|
50
51
|
agents cloud run "add pytest fixtures for the new billing module" --provider codex --env env_a1b2c3 --agent codex --timeout 30m
|
|
51
52
|
|
|
53
|
+
# Cursor Cloud Agents against a GitHub repository
|
|
54
|
+
agents cloud run "fix the flaky parser test" --agent cursor --repo acme/example
|
|
55
|
+
|
|
52
56
|
# Factory pod targeting a specific computer (Droid)
|
|
53
57
|
agents cloud run "QA the new onboarding flow end-to-end" --provider factory --computer linux-vm-1 --agent droid
|
|
54
58
|
|
|
@@ -74,9 +78,9 @@ Examples:
|
|
|
74
78
|
cloud
|
|
75
79
|
.command('run [prompt]')
|
|
76
80
|
.description('Dispatch a task to a cloud agent.')
|
|
77
|
-
.option('--provider <id>', 'Cloud backend: rush, codex, factory, antigravity, host (overrides agent auto-routing)')
|
|
78
|
-
.option('--agent <name>', 'Agent to run: claude, codex, droid, antigravity (auto-routes to its native cloud)')
|
|
79
|
-
.option('--repo <owner/repo>', 'GitHub repository. Repeatable for multi-repo dispatch (Rush Cloud
|
|
81
|
+
.option('--provider <id>', 'Cloud backend: rush, codex, cursor, factory, antigravity, host (overrides agent auto-routing)')
|
|
82
|
+
.option('--agent <name>', 'Agent to run: claude, codex, cursor, droid, antigravity (auto-routes to its native cloud)')
|
|
83
|
+
.option('--repo <owner/repo>', 'GitHub repository. Repeatable for multi-repo dispatch (Rush or Cursor Cloud).', (value, previous) => {
|
|
80
84
|
const acc = Array.isArray(previous) ? previous : [];
|
|
81
85
|
acc.push(value);
|
|
82
86
|
return acc;
|
|
@@ -22,11 +22,35 @@
|
|
|
22
22
|
* apply pending sync.
|
|
23
23
|
*/
|
|
24
24
|
import type { Command } from 'commander';
|
|
25
|
+
import { type DoctorFinding } from '../lib/devices/doctor-findings.js';
|
|
25
26
|
import { type VersionResourceReport } from '../lib/doctor-diff.js';
|
|
26
27
|
import { type DuplicateVersionHook } from '../lib/hooks.js';
|
|
27
28
|
import { type SyncStatusRow, type OrphanRow } from '../lib/drift.js';
|
|
28
29
|
import { type FetchStatusMarker } from '../lib/auto-pull.js';
|
|
29
30
|
export declare function wrapLine(prefix: string, text: string, width?: number): string[];
|
|
31
|
+
export declare function asRemoteSecretFindings(raw: unknown, device: string): DoctorFinding[];
|
|
32
|
+
/**
|
|
33
|
+
* Fetch a device's harness inventory by running its top-level `agents doctor
|
|
34
|
+
* --json` (which carries the `fleet` field, RUSH-2027). Separate from
|
|
35
|
+
* {@link probeFleetTarget} — that forwards `teams doctor --json` for per-agent
|
|
36
|
+
* readiness, a different payload. Returns the parsed {@link FleetInventory} or
|
|
37
|
+
* null (unreachable, non-zero exit, unparseable, or an older CLI with no
|
|
38
|
+
* `fleet` field); a null is skipped by the comparator, never a false gap.
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* How long one remote `doctor --json` probe may take.
|
|
42
|
+
*
|
|
43
|
+
* 180s, matching `ChildProcess.doctorTimeout`, which was set to 180 for this
|
|
44
|
+
* same command for this same reason. The previous 30s sat BELOW the command's
|
|
45
|
+
* real cost — 56s measured on `yosemite-m0`, 136s on an idle box — so every slow
|
|
46
|
+
* device silently contributed nothing at all: no inventory, no sign-in, no
|
|
47
|
+
* divergence, no secret findings. A ceiling under the true cost does not make a
|
|
48
|
+
* probe cheap, it makes it always fail.
|
|
49
|
+
*
|
|
50
|
+
* This does not multiply by device count: `fanOutDevices` is `Promise.all`, so
|
|
51
|
+
* whole-fleet wall time is bounded near the slowest box, not 180s x N.
|
|
52
|
+
*/
|
|
53
|
+
export declare const FLEET_INVENTORY_TIMEOUT_MS = 180000;
|
|
30
54
|
export type IssueSeverity = 'critical' | 'warning' | 'info';
|
|
31
55
|
/**
|
|
32
56
|
* One triaged health finding. `severity`/`category`/`subject`/`impact`/`fix` are
|
package/dist/commands/doctor.js
CHANGED
|
@@ -8,7 +8,7 @@ import { enterDoctorOverviewGate, writeDoctorOverviewCache } from '../lib/device
|
|
|
8
8
|
import { fleetDialTarget } from '../lib/devices/connect.js';
|
|
9
9
|
import { compareFleetInventories } from '../lib/devices/fleet-divergence.js';
|
|
10
10
|
import { collectLocalFleetInventory } from '../lib/devices/fleet-inventory.js';
|
|
11
|
-
import { buildLocalFindings, fleetDivergenceToFindings, signInToFindings, renderFindings, } from '../lib/devices/doctor-findings.js';
|
|
11
|
+
import { buildLocalFindings, fleetDivergenceToFindings, signInToFindings, renderFindings, remediationFor, FINDING_SEVERITY, } from '../lib/devices/doctor-findings.js';
|
|
12
12
|
import { getCliVersion } from '../lib/version.js';
|
|
13
13
|
import { resolveHost } from '../lib/hosts/registry.js';
|
|
14
14
|
import { sshExecAsync } from '../lib/ssh-exec.js';
|
|
@@ -31,7 +31,7 @@ import { listCliStatus, listCliStatusAsync } from '../lib/cli-resources.js';
|
|
|
31
31
|
import { setHelpSections } from '../lib/help.js';
|
|
32
32
|
import { heal, healChangedAnything } from '../lib/heal.js';
|
|
33
33
|
import { getEffectiveExecutionPolicy } from '../lib/platform/winpath.js';
|
|
34
|
-
import { scanUserRcFiles } from '../lib/secrets/rc-hygiene.js';
|
|
34
|
+
import { scanUserRcFiles, masterPassphraseInEnv } from '../lib/secrets/rc-hygiene.js';
|
|
35
35
|
import { terminalWidth, truncateToWidth, stringWidth, padToWidth } from '../lib/session/width.js';
|
|
36
36
|
import { readRepoBehindMarkers } from '../lib/auto-pull.js';
|
|
37
37
|
import * as fs from 'fs';
|
|
@@ -80,6 +80,70 @@ function printWrappedLine(prefix, text) {
|
|
|
80
80
|
for (const line of wrapLine(prefix, text))
|
|
81
81
|
console.log(chalk.gray(line));
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Narrow a remote `findings` array to the secret-hygiene rows, or `[]`.
|
|
85
|
+
*
|
|
86
|
+
* Deliberately NOT "forward every remote finding". The aggregator already
|
|
87
|
+
* rebuilds a remote's sign-in rows from its inventory and its divergence rows
|
|
88
|
+
* from the comparator, so forwarding wholesale would double them; and pulling a
|
|
89
|
+
* remote's orphan/drift rows into a fleet readout is a much larger UX change
|
|
90
|
+
* than this fix. The two secret kinds are the ones that are BOTH unrecomputable
|
|
91
|
+
* centrally and security-relevant, which is exactly why they were being lost.
|
|
92
|
+
*
|
|
93
|
+
* **The remote contributes exactly one thing: the KIND.** Severity, message and
|
|
94
|
+
* remediation are all generated HERE. That is not defensiveness for its own
|
|
95
|
+
* sake — the remote runs its own agents-cli, whose version and integrity we do
|
|
96
|
+
* not control, and each forwarded string is load-bearing in a different way:
|
|
97
|
+
*
|
|
98
|
+
* - `remediation` is a command a human copies and runs. Accepting it from the
|
|
99
|
+
* wire is an injection channel, full stop.
|
|
100
|
+
* - `message` is the one place a secret VALUE could re-enter a readout that
|
|
101
|
+
* otherwise guarantees it never prints one. A local builder cannot leak what
|
|
102
|
+
* it never receives.
|
|
103
|
+
* - `severity` decides the CRITICAL section, so a remote could otherwise
|
|
104
|
+
* promote its own warning and bury real criticals under it.
|
|
105
|
+
* - `device` is overwritten with the name we dialled, so no box can pin a
|
|
106
|
+
* finding on another.
|
|
107
|
+
*
|
|
108
|
+
* The cost is detail: the fleet row says which box and which kind, not which
|
|
109
|
+
* file and line. Run `agents doctor` on that box for the specifics — the
|
|
110
|
+
* message says so.
|
|
111
|
+
*/
|
|
112
|
+
const REMOTE_FORWARDED_KINDS = ['rc-secret-export', 'env-secret-export'];
|
|
113
|
+
/** Canonical, locally-authored text for a forwarded kind. Never the remote's. */
|
|
114
|
+
const REMOTE_SECRET_MESSAGE = {
|
|
115
|
+
'rc-secret-export': 'a credential-shaped export was found in this box\'s shell rc files'
|
|
116
|
+
+ ' — run `agents doctor` there for the file and line',
|
|
117
|
+
'env-secret-export': 'AGENTS_SECRETS_PASSPHRASE is set in this box\'s process environment'
|
|
118
|
+
+ ' — run `agents doctor` there for detail',
|
|
119
|
+
};
|
|
120
|
+
export function asRemoteSecretFindings(raw, device) {
|
|
121
|
+
if (!Array.isArray(raw))
|
|
122
|
+
return [];
|
|
123
|
+
const seen = new Set();
|
|
124
|
+
const out = [];
|
|
125
|
+
for (const item of raw) {
|
|
126
|
+
if (!item || typeof item !== 'object' || Array.isArray(item))
|
|
127
|
+
continue;
|
|
128
|
+
const kind = item.kind;
|
|
129
|
+
if (typeof kind !== 'string')
|
|
130
|
+
continue;
|
|
131
|
+
if (!REMOTE_FORWARDED_KINDS.includes(kind))
|
|
132
|
+
continue;
|
|
133
|
+
if (seen.has(kind))
|
|
134
|
+
continue; // one row per kind per box
|
|
135
|
+
seen.add(kind);
|
|
136
|
+
const k = kind;
|
|
137
|
+
const base = {
|
|
138
|
+
severity: FINDING_SEVERITY[k],
|
|
139
|
+
kind: k,
|
|
140
|
+
device,
|
|
141
|
+
message: REMOTE_SECRET_MESSAGE[k],
|
|
142
|
+
};
|
|
143
|
+
out.push({ ...base, remediation: remediationFor({ ...base, remediation: '' }) });
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
83
147
|
async function resolveFleetTargets(opts) {
|
|
84
148
|
const singleName = opts.host || opts.device;
|
|
85
149
|
if (singleName) {
|
|
@@ -155,15 +219,32 @@ async function probeFleetTarget(target) {
|
|
|
155
219
|
* null (unreachable, non-zero exit, unparseable, or an older CLI with no
|
|
156
220
|
* `fleet` field); a null is skipped by the comparator, never a false gap.
|
|
157
221
|
*/
|
|
222
|
+
/**
|
|
223
|
+
* How long one remote `doctor --json` probe may take.
|
|
224
|
+
*
|
|
225
|
+
* 180s, matching `ChildProcess.doctorTimeout`, which was set to 180 for this
|
|
226
|
+
* same command for this same reason. The previous 30s sat BELOW the command's
|
|
227
|
+
* real cost — 56s measured on `yosemite-m0`, 136s on an idle box — so every slow
|
|
228
|
+
* device silently contributed nothing at all: no inventory, no sign-in, no
|
|
229
|
+
* divergence, no secret findings. A ceiling under the true cost does not make a
|
|
230
|
+
* probe cheap, it makes it always fail.
|
|
231
|
+
*
|
|
232
|
+
* This does not multiply by device count: `fanOutDevices` is `Promise.all`, so
|
|
233
|
+
* whole-fleet wall time is bounded near the slowest box, not 180s x N.
|
|
234
|
+
*/
|
|
235
|
+
export const FLEET_INVENTORY_TIMEOUT_MS = 180_000;
|
|
158
236
|
async function probeFleetInventory(target) {
|
|
159
237
|
const isWin = /^win/i.test((target.os ?? '').trim());
|
|
160
238
|
const remoteCmd = buildRemoteAgentsInvocation(['doctor', '--json'], undefined, isWin ? 'windows' : undefined, isWin ? undefined : { PATH: '$HOME/.agents/.cache/shims:$HOME/.local/bin:$PATH' });
|
|
161
|
-
const res = await sshExecAsync(target.sshTarget, remoteCmd, { timeoutMs:
|
|
239
|
+
const res = await sshExecAsync(target.sshTarget, remoteCmd, { timeoutMs: FLEET_INVENTORY_TIMEOUT_MS, multiplex: true });
|
|
162
240
|
if (res.code !== 0)
|
|
163
241
|
return null;
|
|
164
242
|
try {
|
|
165
243
|
const parsed = JSON.parse(res.stdout);
|
|
166
|
-
return
|
|
244
|
+
return {
|
|
245
|
+
inventory: asFleetInventory(parsed.fleet),
|
|
246
|
+
secretFindings: asRemoteSecretFindings(parsed.findings, target.name),
|
|
247
|
+
};
|
|
167
248
|
}
|
|
168
249
|
catch {
|
|
169
250
|
return null;
|
|
@@ -252,19 +333,22 @@ async function runDevicesDoctor(opts) {
|
|
|
252
333
|
fanOutDevices(targets, probeFleetTarget),
|
|
253
334
|
fanOutDevices(targets, probeFleetInventory),
|
|
254
335
|
]);
|
|
255
|
-
const
|
|
336
|
+
const payloadByName = new Map();
|
|
256
337
|
for (const r of inventoryResults)
|
|
257
|
-
|
|
338
|
+
payloadByName.set(r.name, r.status === 'ok' ? (r.value ?? null) : null);
|
|
258
339
|
results.push(...remoteResults.map((r) => {
|
|
259
|
-
const
|
|
340
|
+
const payload = payloadByName.get(r.name) ?? null;
|
|
341
|
+
const inventory = payload?.inventory ?? undefined;
|
|
342
|
+
const secretFindings = payload?.secretFindings;
|
|
260
343
|
if (r.status === 'ok' && r.value)
|
|
261
|
-
return { ...r.value, inventory
|
|
344
|
+
return { ...r.value, inventory, secretFindings };
|
|
262
345
|
return {
|
|
263
346
|
name: r.name,
|
|
264
347
|
online: false,
|
|
265
348
|
error: r.error ?? String(r.reason ?? 'skipped'),
|
|
266
349
|
agents: {},
|
|
267
|
-
inventory
|
|
350
|
+
inventory,
|
|
351
|
+
secretFindings,
|
|
268
352
|
};
|
|
269
353
|
}));
|
|
270
354
|
// Cross-device divergence: compare every device's inventory against the local
|
|
@@ -314,6 +398,7 @@ async function runDevicesDoctor(opts) {
|
|
|
314
398
|
duplicateHooks: inspectDuplicateVersionHooks(cwd),
|
|
315
399
|
hostClis: toHostCliInput(listCliStatus(cwd)),
|
|
316
400
|
rcSecrets: scanUserRcFiles(),
|
|
401
|
+
masterPassphraseInEnv: masterPassphraseInEnv(),
|
|
317
402
|
execPolicy: process.platform === 'win32'
|
|
318
403
|
? { platform: process.platform, policy: getEffectiveExecutionPolicy() }
|
|
319
404
|
: undefined,
|
|
@@ -335,6 +420,11 @@ async function runDevicesDoctor(opts) {
|
|
|
335
420
|
});
|
|
336
421
|
continue;
|
|
337
422
|
}
|
|
423
|
+
// Secret hygiene the aggregator cannot see for itself — the remote's shell
|
|
424
|
+
// rc files and its process environment. Without this the fleet readout
|
|
425
|
+
// reports a leaking box as clean (RUSH-1968).
|
|
426
|
+
if (r.secretFindings?.length)
|
|
427
|
+
findings.push(...r.secretFindings);
|
|
338
428
|
if (r.inventory?.signIn) {
|
|
339
429
|
findings.push(...signInToFindings(r.name, r.inventory.signIn));
|
|
340
430
|
accounts[r.name] = r.inventory.signIn;
|
|
@@ -1389,6 +1479,7 @@ export function registerDoctorCommand(program) {
|
|
|
1389
1479
|
duplicateHooks,
|
|
1390
1480
|
hostClis: toHostCliInput(hostClis),
|
|
1391
1481
|
rcSecrets: scanUserRcFiles(),
|
|
1482
|
+
masterPassphraseInEnv: masterPassphraseInEnv(),
|
|
1392
1483
|
// getEffectiveExecutionPolicy spawns powershell — a doomed process on
|
|
1393
1484
|
// POSIX, where the advisory never applies. Probe only on Windows.
|
|
1394
1485
|
execPolicy: process.platform === 'win32'
|
package/dist/commands/exec.js
CHANGED
|
@@ -568,8 +568,8 @@ export function registerRunCommand(program) {
|
|
|
568
568
|
.option('--bare', 'With --lease, skip copying your local ~/.agents setup (skills/hooks/commands/MCP) onto the box.')
|
|
569
569
|
.option('--tailscale', 'Lease the box onto your tailnet (reachable only over Tailscale) rather than a public IP.')
|
|
570
570
|
.option('--no-tailscale', 'Force a public-IP lease even when a reuse context would default to Tailscale.')
|
|
571
|
-
.option('--cloud', 'Vendor cloud placement: dispatch to the agent\'s native cloud (claude→rush, codex→codex, droid→factory, antigravity→antigravity) and stream the result. Same dispatch as `agents cloud run --agent <agent>`; tracked by `agents cloud list/status/logs`. Same as --where cloud. Mutually exclusive with --host/--lease and local-run flags.')
|
|
572
|
-
.option('--provider <id>', 'With --cloud: override the agent\'s native cloud provider (rush | codex | factory | antigravity | host).')
|
|
571
|
+
.option('--cloud', 'Vendor cloud placement: dispatch to the agent\'s native cloud (claude→rush, codex→codex, cursor→cursor, droid→factory, antigravity→antigravity) and stream the result. Same dispatch as `agents cloud run --agent <agent>`; tracked by `agents cloud list/status/logs`. Same as --where cloud. Mutually exclusive with --host/--lease and local-run flags.')
|
|
572
|
+
.option('--provider <id>', 'With --cloud: override the agent\'s native cloud provider (rush | codex | cursor | factory | antigravity | host).')
|
|
573
573
|
.option('--repo <owner/repo>', 'With --cloud: GitHub repository. Repeatable for multi-repo dispatch (Rush Cloud only).', (val, prev) => [...prev, val], [])
|
|
574
574
|
.option('--branch <name>', 'With --cloud: target git branch.')
|
|
575
575
|
.option('--cloud-env <id>', 'With --cloud: Codex Cloud environment ID (run\'s --env is the KEY=VAL passthrough, so the cloud env id gets its own flag).');
|
|
@@ -657,8 +657,8 @@ export function registerRunCommand(program) {
|
|
|
657
657
|
Models (cheap|default|best|ultra): agents models <agent[@version]>
|
|
658
658
|
|
|
659
659
|
Headless plan support (a prompt makes the run headless):
|
|
660
|
-
plan works headless on claude, codex, droid, opencode.
|
|
661
|
-
kimi, grok,
|
|
660
|
+
plan works headless on claude, codex, cursor, droid, opencode.
|
|
661
|
+
kimi, grok, antigravity have no headless plan mode — a headless
|
|
662
662
|
--mode plan auto-downgrades to --mode auto (with a stderr warning).
|
|
663
663
|
Interactive plan (omit the prompt) works everywhere it is listed.
|
|
664
664
|
|
|
@@ -1019,19 +1019,21 @@ export function registerRunCommand(program) {
|
|
|
1019
1019
|
const leaseSecretsBundle = process.env.AGENTS_LEASE_SECRETS_BUNDLE;
|
|
1020
1020
|
const nowSecs = Math.floor(Date.now() / 1000);
|
|
1021
1021
|
let reuseSlug = options.box;
|
|
1022
|
-
//
|
|
1023
|
-
//
|
|
1024
|
-
//
|
|
1025
|
-
// pool-reuse match interchangeable with a fresh warmup.
|
|
1022
|
+
// Lease runs share one default warm pool across repositories. The generic
|
|
1023
|
+
// `.crabbox.yaml profile:` remains available to repo sandbox/CI scripts;
|
|
1024
|
+
// `leaseProfile:` is the explicit opt-in for a dedicated lease hot box.
|
|
1026
1025
|
const repoRoot = gitToplevel(leaseCwd);
|
|
1027
|
-
const {
|
|
1028
|
-
const poolProfile = repoRoot ?
|
|
1026
|
+
const { readCrabboxLeaseProfile } = await import('../lib/crabbox/config.js');
|
|
1027
|
+
const poolProfile = repoRoot ? readCrabboxLeaseProfile(repoRoot) : 'default';
|
|
1029
1028
|
if (options.lease && !reuseSlug && !options.fresh) {
|
|
1030
|
-
const { crabboxList } = await import('../lib/crabbox/cli.js');
|
|
1031
|
-
const {
|
|
1029
|
+
const { crabboxList, poolReusableBoxes } = await import('../lib/crabbox/cli.js');
|
|
1030
|
+
const { formatBoxRow } = await import('./lease.js');
|
|
1032
1031
|
let warm = [];
|
|
1033
1032
|
try {
|
|
1034
|
-
warm =
|
|
1033
|
+
warm = poolReusableBoxes(crabboxList({ secretsBundle: leaseSecretsBundle }), {
|
|
1034
|
+
profile: poolProfile,
|
|
1035
|
+
nowSecs,
|
|
1036
|
+
});
|
|
1035
1037
|
}
|
|
1036
1038
|
catch {
|
|
1037
1039
|
warm = []; // crabbox unavailable / no creds → the pool check in leaseAndRun decides
|
|
@@ -1102,7 +1104,7 @@ export function registerRunCommand(program) {
|
|
|
1102
1104
|
}
|
|
1103
1105
|
}
|
|
1104
1106
|
const { detectSignedInRuntimes, resolveClaudeCredentialsBlob, inferLeaseRuntime, profileNeedsBaseRuntimeCredentials } = await import('../lib/crabbox/runtimes.js');
|
|
1105
|
-
const { leaseAndRun } = await import('../lib/crabbox/lease.js');
|
|
1107
|
+
const { leaseAndRun, leaseWorkspaceId } = await import('../lib/crabbox/lease.js');
|
|
1106
1108
|
const { boxAddress } = await import('./lease.js');
|
|
1107
1109
|
const { getConfiguredRunStrategy, resolveRunVersion } = await import('../lib/rotate.js');
|
|
1108
1110
|
const { profileExists, readProfile, resolveProfileEnv } = await import('../lib/profiles.js');
|
|
@@ -1197,7 +1199,7 @@ export function registerRunCommand(program) {
|
|
|
1197
1199
|
? 'the box is kept after the run'
|
|
1198
1200
|
: options.fresh
|
|
1199
1201
|
? 'the box is destroyed after the run'
|
|
1200
|
-
: '
|
|
1202
|
+
: 'the shared-pool box is kept after the run';
|
|
1201
1203
|
console.error(chalk.gray(`${boxLifecycle} · shipping ${whatShips}${credentialRuntimes.length > 0 && leaseEmail ? ` (${leaseEmail})` : ''}; ${boxAfterRun}.`));
|
|
1202
1204
|
// Read the Claude OAuth token from the local Keychain (silent) so it can be
|
|
1203
1205
|
// written to ~/.claude/.credentials.json on the box — otherwise Claude boots
|
|
@@ -1279,6 +1281,7 @@ export function registerRunCommand(program) {
|
|
|
1279
1281
|
reuseBox: reuseSlug,
|
|
1280
1282
|
fresh: options.fresh,
|
|
1281
1283
|
profile: poolProfile,
|
|
1284
|
+
workspaceId: leaseWorkspaceId(repoRoot ?? leaseCwd),
|
|
1282
1285
|
copySetup,
|
|
1283
1286
|
netMode,
|
|
1284
1287
|
onData: (chunk) => router.push(chunk),
|
|
@@ -2455,7 +2458,7 @@ export function registerRunCommand(program) {
|
|
|
2455
2458
|
process.exit(1);
|
|
2456
2459
|
}
|
|
2457
2460
|
// Default CLI mode is the generic 'plan'. Agents without a read-only
|
|
2458
|
-
// mode (antigravity,
|
|
2461
|
+
// mode (antigravity, kiro, …) degrade via resolveMode to their
|
|
2459
2462
|
// safest native mode (modes[0], typically edit). That covers both the
|
|
2460
2463
|
// implicit default and an explicit `--mode plan`, so multi-agent
|
|
2461
2464
|
// scripts can pass a uniform plan flag without per-agent branching.
|
package/dist/commands/feed.d.ts
CHANGED
|
@@ -42,6 +42,8 @@ export declare function prepareLocalFeedBlocks(localBlocks: OpenBlock[], opts: {
|
|
|
42
42
|
dispatch: OpenBlock[];
|
|
43
43
|
filter: ReturnType<typeof filterBlocksForFeed>;
|
|
44
44
|
};
|
|
45
|
+
/** Specific host app + routine provenance for one feed row. */
|
|
46
|
+
export declare function formatFeedRuntime(block: Pick<OpenBlock, 'runtime' | 'origin' | 'routineName'>): string;
|
|
45
47
|
/** Human summary line for one outcome rollup. */
|
|
46
48
|
export declare function formatOutcomeHeader(group: OutcomeGroup): string;
|
|
47
49
|
/** Map active sessions into the lightweight hints outcome enrichment needs. */
|
|
@@ -59,6 +61,9 @@ export declare function sessionHintsFromActive(sessions: Array<{
|
|
|
59
61
|
worktree?: {
|
|
60
62
|
slug?: string;
|
|
61
63
|
};
|
|
64
|
+
host?: string;
|
|
65
|
+
origin?: 'cli' | 'routine';
|
|
66
|
+
routineName?: string;
|
|
62
67
|
}>): SessionOutcomeHint[];
|
|
63
68
|
/**
|
|
64
69
|
* True when a SQLite open/query failed because another writer holds the lock.
|