@phnx-labs/agents-cli 1.20.87 → 1.20.89
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 +323 -0
- package/README.md +12 -4
- package/dist/bin/agents +0 -0
- package/dist/commands/commands.js +7 -7
- package/dist/commands/doctor.d.ts +0 -19
- package/dist/commands/doctor.js +219 -305
- package/dist/commands/exec.js +7 -19
- package/dist/commands/factory.js +26 -2
- package/dist/commands/funnel.js +16 -1
- package/dist/commands/inspect.js +3 -5
- package/dist/commands/menubar.js +117 -34
- package/dist/commands/routines.js +25 -3
- package/dist/commands/secrets-rotate-passphrase.d.ts +17 -0
- package/dist/commands/secrets-rotate-passphrase.js +96 -0
- package/dist/commands/secrets.js +2 -0
- package/dist/commands/sessions.d.ts +7 -1
- package/dist/commands/sessions.js +40 -12
- package/dist/commands/ssh.js +3 -3
- package/dist/commands/usage.d.ts +3 -2
- package/dist/commands/usage.js +2 -9
- package/dist/commands/webhook.js +7 -2
- package/dist/lib/agents.d.ts +31 -1
- package/dist/lib/agents.js +55 -0
- package/dist/lib/command-skills.d.ts +10 -0
- package/dist/lib/command-skills.js +14 -0
- package/dist/lib/commands.js +28 -2
- package/dist/lib/daemon.d.ts +29 -0
- package/dist/lib/daemon.js +75 -6
- package/dist/lib/devices/doctor-findings.d.ts +167 -0
- package/dist/lib/devices/doctor-findings.js +893 -0
- package/dist/lib/devices/fleet-divergence.d.ts +22 -0
- package/dist/lib/devices/fleet-divergence.js +34 -10
- package/dist/lib/devices/fleet-inventory.d.ts +17 -6
- package/dist/lib/devices/fleet-inventory.js +56 -8
- package/dist/lib/events.d.ts +1 -1
- package/dist/lib/exec.d.ts +14 -3
- package/dist/lib/exec.js +41 -8
- package/dist/lib/factory/snapshot.d.ts +78 -0
- package/dist/lib/factory/snapshot.js +209 -0
- package/dist/lib/fs-atomic.d.ts +14 -1
- package/dist/lib/fs-atomic.js +35 -3
- package/dist/lib/funnel.d.ts +1 -0
- package/dist/lib/funnel.js +8 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +2 -2
- package/dist/lib/menubar/install-menubar.d.ts +53 -2
- package/dist/lib/menubar/install-menubar.js +183 -28
- package/dist/lib/platform/process.d.ts +2 -0
- package/dist/lib/platform/process.js +5 -3
- package/dist/lib/project-resources.js +34 -20
- package/dist/lib/resources.d.ts +8 -0
- package/dist/lib/resources.js +34 -1
- package/dist/lib/routines-placement.d.ts +2 -1
- package/dist/lib/routines-placement.js +8 -4
- package/dist/lib/routines.d.ts +57 -1
- package/dist/lib/routines.js +74 -1
- package/dist/lib/runner.d.ts +16 -1
- package/dist/lib/runner.js +58 -16
- package/dist/lib/sandbox.d.ts +2 -0
- package/dist/lib/sandbox.js +38 -0
- 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 +9 -34
- package/dist/lib/secrets/filestore.d.ts +152 -34
- package/dist/lib/secrets/filestore.js +676 -123
- package/dist/lib/secrets/rc-hygiene.d.ts +0 -6
- package/dist/lib/secrets/rc-hygiene.js +0 -24
- package/dist/lib/session/active.d.ts +6 -6
- package/dist/lib/session/active.js +6 -6
- package/dist/lib/session/discover.d.ts +5 -0
- package/dist/lib/session/discover.js +137 -1
- package/dist/lib/session/parse.d.ts +2 -0
- package/dist/lib/session/parse.js +76 -37
- package/dist/lib/session/remote-active.d.ts +4 -1
- package/dist/lib/session/remote-active.js +8 -2
- package/dist/lib/session/sync/agents.js +0 -0
- package/dist/lib/session/types.d.ts +1 -1
- package/dist/lib/session/types.js +1 -1
- package/dist/lib/session/viewing-in.d.ts +31 -0
- package/dist/lib/session/viewing-in.js +47 -0
- package/dist/lib/staleness/detectors/commands.js +14 -5
- package/dist/lib/staleness/types.d.ts +2 -0
- package/dist/lib/staleness/writers/commands.js +13 -7
- package/dist/lib/state.d.ts +17 -0
- package/dist/lib/state.js +30 -2
- package/dist/lib/triggers/handlers.d.ts +95 -0
- package/dist/lib/triggers/handlers.js +384 -0
- package/dist/lib/triggers/webhook.d.ts +10 -2
- package/dist/lib/triggers/webhook.js +65 -11
- package/dist/lib/usage.d.ts +72 -1
- package/dist/lib/usage.js +21 -27
- package/dist/lib/versions.js +30 -13
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,328 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.20.89
|
|
4
|
+
|
|
5
|
+
- **Webhook handler layer for one-off agent/workflow/command/routine triggers.**
|
|
6
|
+
Routines still fire from signed webhooks, but a new `~/.agents/webhooks/*.yml`
|
|
7
|
+
layer can also run one-off actions: `run.agent`, `run.workflow`, `run.command`,
|
|
8
|
+
or delegate to an existing `routine`. Handlers support the same source/event/
|
|
9
|
+
action/label/repo/branch filters as routine triggers, plus Linear
|
|
10
|
+
`stateTo`/`stateFrom` state-change filters. Prompts and commands can use
|
|
11
|
+
`{{issue.identifier}}`, `{{updatedFrom.state.name}}`, etc. The receiver emits
|
|
12
|
+
`webhook.received`, `webhook.authorized`, `webhook.rejected`, `webhook.matched`,
|
|
13
|
+
`webhook.fired`, `webhook.handler.start`, and `webhook.handler.end` events.
|
|
14
|
+
Source: `apps/cli/src/lib/triggers/handlers.ts`,
|
|
15
|
+
`apps/cli/src/lib/triggers/webhook.ts`, `apps/cli/src/lib/routines.ts`,
|
|
16
|
+
`apps/cli/src/commands/routines.ts`, `apps/cli/docs/03-routines.md`.
|
|
17
|
+
|
|
18
|
+
- **`agents routines add` gains `--state-to` and `--state-from` filters for Linear
|
|
19
|
+
triggers.** A Linear routine or handler can now fire only on a specific state
|
|
20
|
+
transition (for example `--state-to Plan`), instead of on every issue update.
|
|
21
|
+
|
|
22
|
+
- **Values substituted into `run.command` are shell-quoted.** A webhook context is
|
|
23
|
+
built from an external payload, and fields like `issue.title` or a GitHub
|
|
24
|
+
`pull_request` title are free text any outside contributor can set — pasted raw
|
|
25
|
+
into a shell command they would be a command-injection sink. Substituted values
|
|
26
|
+
are now single-quoted (POSIX `sh`), so a payload stays one inert argument while
|
|
27
|
+
the operator's own template keeps its pipes, redirects, and `&&`. On Windows,
|
|
28
|
+
where `exec` runs through `cmd.exe` and these quoting rules do not hold, a
|
|
29
|
+
`run.command` containing `{{…}}` is refused with a clear error rather than run.
|
|
30
|
+
`run.prompt` is unaffected — it never reaches a shell.
|
|
31
|
+
Source: `apps/cli/src/lib/routines.ts` (`substituteWebhookCommand`,
|
|
32
|
+
`assertShellSubstitutionSupported`), `apps/cli/src/lib/triggers/handlers.ts`.
|
|
33
|
+
|
|
34
|
+
- **The `Cmd-Shift-O` quick-dispatch bar now lists the repo's open Linear tickets,
|
|
35
|
+
and dispatches one on a click (RUSH-2098).** The panel only captured NEW work;
|
|
36
|
+
it now also shows what already exists. Switching the repo dropdown switches the
|
|
37
|
+
Linear project (the repo name is matched against `linear projects` reduced to
|
|
38
|
+
lowercase alphanumerics, so `agents-cli` finds "Agents CLI" with nothing to
|
|
39
|
+
configure; a worktree resolves to its parent repo, and a repo that matches no
|
|
40
|
+
project says so and lets you pick one, remembered per repo). Rows are ranked
|
|
41
|
+
urgent-first — Linear priority, then overdue, then in progress, then newest —
|
|
42
|
+
and typing filters them, so an existing ticket surfaces before Return files a
|
|
43
|
+
duplicate. Clicking a row (or `⌘1`–`⌘5`) dispatches that ticket to the selected
|
|
44
|
+
agents in the picked repo: **Run** claims it and implements it, **Plan** posts a
|
|
45
|
+
plan as a ticket comment. `⌘`-click opens it in Linear instead. The list renders
|
|
46
|
+
from a 90-second warm cache so the panel still appears instantly. Source:
|
|
47
|
+
`apps/cli/menubar/Sources/MenubarHelper/LinearTickets.swift`,
|
|
48
|
+
`apps/cli/menubar/Sources/MenubarHelper/PromptPanel.swift`,
|
|
49
|
+
`apps/cli/menubar/Sources/MenubarHelper/AgentsCLI.swift`.
|
|
50
|
+
|
|
51
|
+
- **Fixed: a menu-bar dispatch whose child printed more than ~64 KiB hung forever
|
|
52
|
+
and never notified.** The helper read a monitored child's stdout only from the
|
|
53
|
+
process-termination handler, so a child that filled the pipe buffer blocked on
|
|
54
|
+
write, never exited, and the completion callback never fired — two `linear`
|
|
55
|
+
processes were left wedged by a single ticket fetch. Both monitored paths (the
|
|
56
|
+
ticket agent and `linear create`) now drain stdout, and feed stdin, on a
|
|
57
|
+
background queue while the child runs. Source:
|
|
58
|
+
`apps/cli/menubar/Sources/MenubarHelper/AgentsCLI.swift`.
|
|
59
|
+
|
|
60
|
+
- **The daemon warns when it was launched from an ephemeral root.** A daemon
|
|
61
|
+
started from a temp dir (`/tmp`, `/var/folders`, `/dev/shm`) or a git worktree
|
|
62
|
+
resolves its own job modules by dynamic `import()` rooted at the launch entry
|
|
63
|
+
(`getAgentsBinPath` → `process.argv[1]`). When that directory is later removed
|
|
64
|
+
— a `/tmp` cleanup, a review/verify checkout teardown, `git worktree remove` —
|
|
65
|
+
the long-lived daemon keeps ENOENT-ing on every routine's imports
|
|
66
|
+
(`auto-dispatch.ts`, `routines-placement.ts`, `devices/fleet.ts`), silently
|
|
67
|
+
wedging until restart. `anchorDaemonCwd` already rescues the cwd, but nothing
|
|
68
|
+
can re-root a deleted module tree. `runDaemon` now calls
|
|
69
|
+
`warnEphemeralDaemonRoot` at startup, so the risk is logged the moment the
|
|
70
|
+
daemon comes up — including a direct `agents __daemon-run` that never passes
|
|
71
|
+
through the launch-time `validateDaemonBinary` check. That launch-time check is
|
|
72
|
+
also broadened from git-worktree-only to any ephemeral root via the shared
|
|
73
|
+
`describeEphemeralDaemonRoot` predicate. The fix for a wedged daemon is
|
|
74
|
+
unchanged: run it from the globally installed binary
|
|
75
|
+
(`npm i -g @phnx-labs/agents-cli`) so its entry roots at a stable version home.
|
|
76
|
+
Source: `apps/cli/src/lib/daemon.ts`
|
|
77
|
+
(`describeEphemeralDaemonRoot`, `warnEphemeralDaemonRoot`, `validateDaemonBinary`).
|
|
78
|
+
|
|
79
|
+
- **A `README.md` / `AGENTS.md` sitting in a resource directory is no longer
|
|
80
|
+
installed as a resource.** `listResources` skipped only dotfiles, so every `.md`
|
|
81
|
+
beside the actual resources was materialized as one: `commands/README.md` — which
|
|
82
|
+
the system repo has shipped for months — installed a bogus `/README` slash command
|
|
83
|
+
into every agent home, and adding per-directory `AGENTS.md` docs would have added
|
|
84
|
+
`/AGENTS`, `/CLAUDE`, and `/GEMINI` alongside it. `README`, `AGENTS`, `CLAUDE`, and
|
|
85
|
+
`GEMINI` are now filtered from both `listResources` and `resolveResource` for every
|
|
86
|
+
kind **except `rules`**, where `AGENTS.md` *is* the resource (the composed ruleset
|
|
87
|
+
that syncs as each agent's memory file). The check tests `!entry.isDirectory()`
|
|
88
|
+
rather than `isFile()`, because a `Dirent` for a symlink reports
|
|
89
|
+
`isFile() === false` and `CLAUDE.md`/`GEMINI.md` are symlinks to `AGENTS.md` by
|
|
90
|
+
convention — a resource *directory* named `agents/` is still a real resource.
|
|
91
|
+
Verified against the real installed layers: 30 commands with `README` leaking
|
|
92
|
+
before, 29 with none after.
|
|
93
|
+
- **`agents commands list` and the command picker no longer offer a name that
|
|
94
|
+
cannot be opened.** `listCentralCommands` and `discoverCommands`
|
|
95
|
+
(`src/lib/commands.ts`) run their own `readdirSync` scans rather than going
|
|
96
|
+
through `listResources`, so they kept offering `README` while
|
|
97
|
+
`agents commands view README` answered "not found" — a listed-but-unopenable
|
|
98
|
+
name. Both now share the one exported `isDirectoryDoc` predicate, so every
|
|
99
|
+
enumerator agrees. Verified: 27 names with `README` before, 26 with none after.
|
|
100
|
+
- **`agents commands add/remove/view` no longer suggest `README` as the example
|
|
101
|
+
command name.** With `README` reserved as a directory doc, the six hardcoded
|
|
102
|
+
examples in the help text and non-interactive hints named a command that can never
|
|
103
|
+
exist. They now use `plan`, which actually ships.
|
|
104
|
+
|
|
105
|
+
- **File-backed secrets bundles no longer require `AGENTS_SECRETS_PASSPHRASE` on
|
|
106
|
+
macOS.** The encrypted file store now silently auto-provisions a stable
|
|
107
|
+
machine-local key (a 0600 file under `~/.agents/.secrets-key/`, kept outside the
|
|
108
|
+
encrypted store) on first use on **every** platform, macOS included — no prompt,
|
|
109
|
+
no Touch ID, nothing to set or remember. Previously a file-backed bundle on a Mac
|
|
110
|
+
hard-failed unless `AGENTS_SECRETS_PASSPHRASE` was exported, which blocked
|
|
111
|
+
headless reads (e.g. the `auth` bundle the usage/auth reader consults) and
|
|
112
|
+
frequently hung. Setting `AGENTS_SECRETS_PASSPHRASE` still works and takes
|
|
113
|
+
precedence — use it to hold the key off disk or to share one bundle's ciphertext
|
|
114
|
+
across boxes under a common key. Source: `apps/cli/src/lib/secrets/filestore.ts`,
|
|
115
|
+
`apps/cli/src/lib/secrets/bundles.ts`.
|
|
116
|
+
|
|
117
|
+
- **Menu-bar & daemon notifications now use the current agents-cli mark, not the
|
|
118
|
+
legacy logo.** A desktop notification from the menu-bar helper or the routines
|
|
119
|
+
daemon showed the old `assets/logo.png` gradient "A" — outdated, and blank in the
|
|
120
|
+
notification's left-hand app-icon slot. `MenubarHelper.app`'s `AppIcon.icns` is
|
|
121
|
+
now generated from the current brand mark (`assets/app-icon.svg` → `app-icon.png`:
|
|
122
|
+
the lime-tile lowercase `a` shared with the agi-cli web favicon and the menu-bar
|
|
123
|
+
glyph), which drives both the notification's right-hand `contentImage` and its
|
|
124
|
+
left-hand app icon. The installer also registers the bundle with LaunchServices
|
|
125
|
+
(`lsregister -f`) at its `~/Library/Application Support` path so the OS can resolve
|
|
126
|
+
that app icon. Source: `apps/cli/menubar/scripts/build.sh`,
|
|
127
|
+
`apps/cli/src/lib/menubar/install-menubar.ts`, `assets/app-icon.svg`.
|
|
128
|
+
|
|
129
|
+
- **The menu bar is a single instance, always.** Two copies of the helper could
|
|
130
|
+
run at once — launchd's `KeepAlive` service plus a LaunchServices/`open` launch
|
|
131
|
+
of the same `.app` — putting two agents marks in the menu bar, and the second
|
|
132
|
+
copy could hold `Cmd-Shift-V`/`Cmd-Shift-O` (`RegisterEventHotKey` is
|
|
133
|
+
first-come). The helper now takes an `flock` on
|
|
134
|
+
`~/.agents/.cache/state/menubar.lock` at launch and holds it for its lifetime;
|
|
135
|
+
a helper that cannot take the lock pops the **running** helper's menu open and
|
|
136
|
+
exits 0, since re-launching a menu-bar app means "show me the one I already
|
|
137
|
+
have". An `flock` rather than a pid file: the kernel releases it when the
|
|
138
|
+
holder dies, so a `SIGKILL`ed helper cannot leave a stale "already running"
|
|
139
|
+
that blocks every later launch. Source:
|
|
140
|
+
`apps/cli/menubar/Sources/MenubarHelper/SingleInstance.swift`,
|
|
141
|
+
`apps/cli/menubar/Sources/MenubarHelper/StatusItemController.swift`.
|
|
142
|
+
|
|
143
|
+
- **`agents menubar setup` configures the menu bar end-to-end.** One idempotent
|
|
144
|
+
command for a machine that is wrong — never configured, helper down, or showing
|
|
145
|
+
a duplicate icon. It ends every running helper, installs/refreshes the bundle,
|
|
146
|
+
checks its code signature, writes the launchd login item (`RunAtLoad` +
|
|
147
|
+
`KeepAlive`), clears a previous `agents menubar disable`, and verifies exactly
|
|
148
|
+
one helper came back up — reporting each as its own step and exiting nonzero if
|
|
149
|
+
it cannot reach that state. `--check` reports without changing; `--json` emits
|
|
150
|
+
the step list. Source: `apps/cli/src/commands/menubar.ts`,
|
|
151
|
+
`apps/cli/src/lib/menubar/install-menubar.ts`.
|
|
152
|
+
|
|
153
|
+
- **`agents menubar status` now shows a duplicate.** Live helper processes were
|
|
154
|
+
collapsed to a boolean `running`, so two copies of the *installed* bundle — the
|
|
155
|
+
duplicate a user actually sees — reported as healthy. `--json` now carries an
|
|
156
|
+
`instances` array (copies of the installed bundle) beside the existing
|
|
157
|
+
`foreignInstances`, and the text readout names every extra pid and points at
|
|
158
|
+
`agents menubar setup`. Source:
|
|
159
|
+
`apps/cli/src/lib/menubar/install-menubar.ts` (`classifyMenubarProcesses`).
|
|
160
|
+
|
|
161
|
+
- **Quick-dispatch ticket list: one-row filter + sort, and a scrollable list.**
|
|
162
|
+
The ticket controls sit on a single row of popups next to the Linear project
|
|
163
|
+
(project · filter · sort) — not a chip matrix or two-column block. Quick filter
|
|
164
|
+
options: All open, Todo, Doing, Backlog, P1 only, P2 only, Overdue. Quick sort
|
|
165
|
+
options: Urgent first, Newest, Oldest, Due date, Priority (flat list, no
|
|
166
|
+
status grouping). Filter and sort picks are remembered across summons. Ticket
|
|
167
|
+
rows scroll inside a fixed viewport so more than five matches stay reachable
|
|
168
|
+
without growing the panel. Source:
|
|
169
|
+
`apps/cli/menubar/Sources/MenubarHelper/LinearTickets.swift`,
|
|
170
|
+
`apps/cli/menubar/Sources/MenubarHelper/PromptPanel.swift`.
|
|
171
|
+
|
|
172
|
+
- **`release.sh` now takes a release lease, and refuses to bump past an
|
|
173
|
+
unpublished tag.** Releases run from whichever fleet box an agent happens to be
|
|
174
|
+
on, so two agents could enter the pipeline at once; the collision only surfaced
|
|
175
|
+
at the publish gate (`merged tree != built tree -- refusing to publish`), after
|
|
176
|
+
one run had already merged and tagged, leaving the version merged but unshipped.
|
|
177
|
+
A new `scripts/release-lease.sh` holds mutual exclusion on `origin` as an orphan
|
|
178
|
+
commit at `refs/release-lock/held` — a second claimant's push can never be a
|
|
179
|
+
fast-forward, so git's rejection *is* the failed lock acquisition. The lease is
|
|
180
|
+
claimed before the first mutation and dropped by the existing cleanup trap on
|
|
181
|
+
every exit path. Because a healthy release routinely outlives any sane
|
|
182
|
+
expiry — the CI matrix alone has run 57 minutes and release 1.20.77 took 186
|
|
183
|
+
minutes — the lease is **renewed** by a background renewer for the whole run,
|
|
184
|
+
and the squash-merge, the tag, and the publish each **verify** ownership first,
|
|
185
|
+
failing closed if it can no longer be proven. A lease that stops being renewed
|
|
186
|
+
is reclaimable after 30 minutes, and reclaiming names the dead holder instead
|
|
187
|
+
of silently overwriting it. Separately,
|
|
188
|
+
`release.sh` now refuses to cut a new version while an older `v*` tag exists
|
|
189
|
+
that npm never received, and points at the re-run that finishes it — bumping
|
|
190
|
+
past an unpublished tag is what turned a one-version gap into npm 1.20.78 vs
|
|
191
|
+
main 1.20.81. Source: `apps/cli/scripts/release-lease.sh`,
|
|
192
|
+
`apps/cli/scripts/release.sh`.
|
|
193
|
+
|
|
194
|
+
- **`agents funnel down` disables a public Funnel port from the same wrapper used
|
|
195
|
+
to enable ingress.** Webhook ingress now has a complete local receiver runbook:
|
|
196
|
+
keep GitHub/Linear signing keys in `agents secrets`, bind the receiver to
|
|
197
|
+
`127.0.0.1`, expose it with `agents funnel up`, rotate one source secret at a
|
|
198
|
+
time, and turn the public port off with `agents funnel down` before stopping or
|
|
199
|
+
moving the receiver. Source: `apps/cli/src/commands/funnel.ts`,
|
|
200
|
+
`apps/cli/src/lib/funnel.ts`, `apps/cli/docs/03-routines.md`.
|
|
201
|
+
|
|
202
|
+
- **New `agents secrets rotate-passphrase` re-keys the encrypted file store under
|
|
203
|
+
a new master passphrase, atomically (RUSH-1975).** Until now there was no
|
|
204
|
+
supported way to rotate the file-store passphrase — `rekey` only renames macOS
|
|
205
|
+
keychain service names and `rotate <bundle> <key>` replaces a single secret
|
|
206
|
+
value, so a leaked passphrase (RUSH-1968) could only be remediated by a
|
|
207
|
+
hand-rolled non-atomic script or an export-to-plaintext round-trip (the exact
|
|
208
|
+
exposure being fixed). The new command decrypts every `<item>.enc` under the
|
|
209
|
+
current key, re-encrypts under a freshly generated one, and swaps both the
|
|
210
|
+
ciphertext and the 0600 key file by directory rename after verifying every item
|
|
211
|
+
round-trips. A crash at any point self-heals on the next *rotate* run to a single
|
|
212
|
+
readable store — content-aware recovery probes which key actually decrypts the
|
|
213
|
+
live store (not merely which files are present) and classifies the WHOLE store:
|
|
214
|
+
it completes the rotation forward or rolls back only when one key opens every
|
|
215
|
+
item, and if a later `secrets set` contaminated a crashed rotation into a MIXED
|
|
216
|
+
store (items under two keys at once, or a store dir recreated by an interstitial
|
|
217
|
+
write after the crash left it absent, so its backup holds items the live dir does
|
|
218
|
+
not) it refuses with an actionable error and preserves every recovery artifact
|
|
219
|
+
rather than sweeping the only copy of a key or the backed-up ciphertext — so a
|
|
220
|
+
crash anywhere in the swap can never orphan the store, even when a write landed in
|
|
221
|
+
between. The rotation and every store write run under
|
|
222
|
+
one cross-process lock, so a `secrets set` or a second rotation can never
|
|
223
|
+
interleave with a swap in the first place. No plaintext secret or passphrase is
|
|
224
|
+
ever written to disk, argv, or a log. Items
|
|
225
|
+
that don't decrypt under the current key (orphan caches, stale test artifacts)
|
|
226
|
+
are carried through verbatim, never re-keyed. Dry-run by default (`--commit` to
|
|
227
|
+
apply). A dry run never re-keys, but it *does* heal an interrupted rotation —
|
|
228
|
+
that is how a crashed store becomes readable again without re-keying it — and it
|
|
229
|
+
says so instead of claiming nothing was written. Refuses while the secrets-agent
|
|
230
|
+
holds live unlocks or while
|
|
231
|
+
`AGENTS_SECRETS_PASSPHRASE` is exported in the environment, unless `--force`.
|
|
232
|
+
Headless-safe and Linux-first. Source: `apps/cli/src/lib/secrets/filestore.ts`,
|
|
233
|
+
`apps/cli/src/commands/secrets-rotate-passphrase.ts`.
|
|
234
|
+
|
|
235
|
+
- **`agents sessions --active --json` now reports who is watching each session.**
|
|
236
|
+
The `viewingIn` field carries the same string the table prints — `codium tab 3`,
|
|
237
|
+
`ghostty tab 2`, or `detached` for a live tmux pane with **no client attached**
|
|
238
|
+
(its terminal was closed or crashed). It is `null` both for a session that isn't
|
|
239
|
+
tmux-hosted and for one whose pane the locator could not resolve — `detached` is
|
|
240
|
+
claimed only when the pane was actually located, so absence of evidence is never
|
|
241
|
+
reported as evidence of absence. Previously the JSON path returned
|
|
242
|
+
before the locator pass ran, so the field never appeared and a machine consumer
|
|
243
|
+
could not tell a session someone is looking at from an orphaned one — which is
|
|
244
|
+
exactly what the Factory extension's `Agents: Resume` picker ranks by. The JSON
|
|
245
|
+
path resolves tmux clients only — no osascript — so scriptable output keeps the
|
|
246
|
+
cheapness the old ordering was protecting; a Ghostty-attached client resolves as
|
|
247
|
+
`ghostty` without its tab number. Peers running an older CLI that still emits the
|
|
248
|
+
`{app, tab}` object are normalized at the fan-out boundary, so a mixed-version
|
|
249
|
+
fleet sweep stays correct. Source: `apps/cli/src/lib/session/viewing-in.ts`
|
|
250
|
+
(`viewingInLabel`, `parseViewingIn`), `apps/cli/src/commands/sessions.ts`
|
|
251
|
+
(`serializeActiveSessionsForJson`, `enrichTmuxLocators`),
|
|
252
|
+
`apps/cli/src/lib/session/remote-active.ts`.
|
|
253
|
+
|
|
254
|
+
- **Webhook handlers gain `run.env` and `host` placement.** A handler can now
|
|
255
|
+
inject environment variables into the process it spawns (`run.env`), and choose
|
|
256
|
+
where that run executes (`host`). `host` takes a device name (`yosemite-s0`), or
|
|
257
|
+
`fleet` to pick any eligible online worker, or `fleet/<platform>` /
|
|
258
|
+
`<platform>/fleet` (also a bare `linux` / `macos` / `windows`) to restrict that
|
|
259
|
+
pick to one platform. A fleet expression that matches no eligible device fails
|
|
260
|
+
loudly rather than silently falling back to the local machine, so `fleet/linux`
|
|
261
|
+
can never land on a macOS box. Omitting `host` runs locally, as before.
|
|
262
|
+
Source: `apps/cli/src/lib/triggers/handlers.ts` (`resolveHandlerHost`),
|
|
263
|
+
`apps/cli/src/lib/routines-placement.ts` (`pickFleetDevice` platform filter),
|
|
264
|
+
`apps/cli/src/lib/routines.ts` (`JobConfig.env`), `apps/cli/src/lib/runner.ts`.
|
|
265
|
+
|
|
266
|
+
## 1.20.88
|
|
267
|
+
|
|
268
|
+
- **`agents doctor` redesigned into a prioritized, fleet-aware, per-version
|
|
269
|
+
readout (RUSH-2069).** Comprehensive by default (no `--verbose`): a top
|
|
270
|
+
`✗ CRITICAL — needs you now (N)` section lists every critical across the whole
|
|
271
|
+
fleet worst-first (`device · harness@version · account · message → remediation`),
|
|
272
|
+
then a `─── by computer ───` section gives each device its warnings plus a
|
|
273
|
+
compact accounts/versions line showing every installed version and its account
|
|
274
|
+
(provable ✓ / ✗). A single-machine `agents doctor` collapses to the CRITICAL
|
|
275
|
+
section plus one `▸ <machine>` block. Severity: provable logged-out, a missing
|
|
276
|
+
hook/plugin, a broken CLI, and a never-synced version whose declared resources
|
|
277
|
+
are therefore absent are CRITICAL; drift, version-skew, repo-behind/-drift,
|
|
278
|
+
orphans, and an unprovable logout are WARNINGS. Sign-in is
|
|
279
|
+
now probed **per installed version** (each version's own home + the global
|
|
280
|
+
credential via the new `credentialPresence`), so a per-version logged-out claim
|
|
281
|
+
is made only when both are absent, agents with no inspectable identity never
|
|
282
|
+
report logged-out, and the login remediation is
|
|
283
|
+
version-targeted (`agents run <agent>@<version>` for the isolated set;
|
|
284
|
+
gemini/antigravity/droid/cursor say the login is shared). Older fleet boxes that
|
|
285
|
+
can't report per-version sign-in surface an "older agents-cli — upgrade"
|
|
286
|
+
warning. The readout is de-duplicated so one root cause is one line: a version's
|
|
287
|
+
missing hooks/plugins and drifted resources collapse to a count plus two
|
|
288
|
+
examples (`32 hooks missing (incl. 'a', 'b')`), the same problem on several
|
|
289
|
+
versions of one agent reads as `claude (5 versions)` with an agent-wide fix
|
|
290
|
+
(isolated copies stay on their own line, since the sweep skips them), every
|
|
291
|
+
orphan row on a machine folds into one cleanup-only line, and a version that
|
|
292
|
+
already listed its drifted resources no longer also says "sources changed since
|
|
293
|
+
last sync". The two advisories that predate the redesign are findings now, not
|
|
294
|
+
separate blocks: credential-shaped exports in shell rc files (RUSH-1968) and the
|
|
295
|
+
Windows execution policy that blocks `agents.ps1`. The duplicate-version-home
|
|
296
|
+
hook check keeps its text output too — differing copies are critical, identical
|
|
297
|
+
ones a warning, one row per agent rather than one per hook — and so does the
|
|
298
|
+
Host CLIs check, as a `host CLIs` warning naming `agents cli install <name>`.
|
|
299
|
+
Remediations reach every version in their row: a row collapsed across versions
|
|
300
|
+
uses `agents sync <agent>@all --yes` (a bare `agents sync <agent>` would fix only
|
|
301
|
+
the default version), a cross-device resource gap says `agents repo pull` rather
|
|
302
|
+
than the central-to-home `agents doctor --fix`, and a diverged config repo names
|
|
303
|
+
its own alias instead of always saying `user`.
|
|
304
|
+
`agents doctor --json` adds a `findings` array and a per-version
|
|
305
|
+
`fleet.signIn` map; the existing `clis`/`sync`/`orphans`/`fleet`/`signIn`/`repos`
|
|
306
|
+
fields are unchanged. Source: `apps/cli/src/lib/devices/doctor-findings.ts`,
|
|
307
|
+
`apps/cli/src/lib/devices/fleet-inventory.ts`, `apps/cli/src/lib/agents.ts`,
|
|
308
|
+
`apps/cli/src/commands/doctor.ts`.
|
|
309
|
+
|
|
310
|
+
- **Run Cursor routines safely (RUSH-2080).** Routines configured with `agent: cursor` now reuse the same-device login under the default sandbox, trust the configured workspace without `--yolo`, warn when a requested read-only plan is elevated to writable edit mode (including `loop:` jobs), and record successful runs correctly. Source: `apps/cli/src/lib/runner.ts`.
|
|
311
|
+
|
|
312
|
+
- **`agents sessions` now discovers, indexes, and renders Cursor agent transcripts (RUSH-2081).**
|
|
313
|
+
Cursor writes its conversation to `projects/<encoded-cwd>/agent-transcripts/<uuid>/<uuid>.jsonl`
|
|
314
|
+
and metadata to `chats/<workspace-hash>/<uuid>/meta.json`. Discovery starts from the transcript
|
|
315
|
+
and joins metadata by UUID, so abandoned chats with no transcript never become empty rows.
|
|
316
|
+
Cursor is installed outside agents-cli's managed version homes, so users with any managed
|
|
317
|
+
agent version must pass `--unmanaged` to include Cursor rows.
|
|
318
|
+
Source: `apps/cli/src/lib/session/discover.ts`, `apps/cli/src/lib/session/parse.ts`.
|
|
319
|
+
|
|
320
|
+
- **Fix Cursor usage and account inspection (RUSH-2082).** `agents usage` now derives support from the usage library so Cursor, Grok, and future usage sources cannot drift from the command, and `agents run cursor@` can inspect Cursor's active account. Source: `apps/cli/src/commands/usage.ts`, `apps/cli/src/lib/agents.ts`.
|
|
321
|
+
|
|
322
|
+
- **Sync Cursor commands to the IDE and cursor-agent CLI (RUSH-2083).** Shared commands now remain available as typed IDE slash commands and are also generated as Agent Skills for cursor-agent, while preserving user-authored files in `.cursor/commands/`. Source: `apps/cli/src/lib/command-skills.ts`.
|
|
323
|
+
|
|
324
|
+
- **Daemon routines resolve `agents` on `~/.local/bin` installs.** The generated daemon service (systemd + launchd) now puts the `agents` shim's own directory on `PATH`, not only the Node runtime dir. On a box where the shim lives outside the Node bin dir (a `~/.local/bin` global install, a separate npm prefix), the daemon's `PATH` previously carried only the Node dir, so every scheduled `command` routine — the always-on watchdog included — shelled out to a bare `agents` that resolved to nothing and died with `exit 127`. Source: `apps/cli/src/lib/daemon.ts`.
|
|
325
|
+
|
|
3
326
|
## 1.20.87
|
|
4
327
|
|
|
5
328
|
- **`agents devices enable|disable|prefer|unprefer <name>` control which machines
|
package/README.md
CHANGED
|
@@ -165,7 +165,7 @@ agents run codex@ "review this branch"
|
|
|
165
165
|
|
|
166
166
|
A trailing `@` opens an account picker before either an interactive or prompt-based run. Each installed version shows its account identity, exact version, login state, plan, and every available session, weekly, or monthly limit. Logged-out, rate-limited, and out-of-credit accounts remain visible with the reason they cannot be selected; signed-in accounts whose provider does not expose quota data stay selectable and say `limits unavailable`. The choice pins only that run and does not change your default version.
|
|
167
167
|
|
|
168
|
-
Account selection is available for Claude, Codex, Antigravity, Grok, Kimi, Droid, and OpenCode. It requires a terminal and cannot be combined with `--resume`, `--strategy`/`--balanced`, `--lease`, or `--host`/`--device`; profiles and workflows must use their concrete host agent instead.
|
|
168
|
+
Account selection is available for Claude, Codex, Gemini, Cursor, Antigravity, Grok, Kimi, Droid, and OpenCode. It requires a terminal and cannot be combined with `--resume`, `--strategy`/`--balanced`, `--lease`, or `--host`/`--device`; profiles and workflows must use their concrete host agent instead.
|
|
169
169
|
|
|
170
170
|
### Chain agents
|
|
171
171
|
|
|
@@ -1002,16 +1002,24 @@ Other useful commands: `agents doctor` checks CLI availability and resource sync
|
|
|
1002
1002
|
On macOS, `agents-cli` puts a status item in your menu bar -- a live glance at what your agents are doing, plus a Spotlight-style bar for filing work without breaking focus.
|
|
1003
1003
|
|
|
1004
1004
|
```bash
|
|
1005
|
-
agents menubar
|
|
1005
|
+
agents menubar setup # configure end-to-end: one instance, started at login
|
|
1006
1006
|
agents menubar status # is it installed and running?
|
|
1007
1007
|
```
|
|
1008
1008
|
|
|
1009
|
+
There is only ever **one** agents mark: the helper takes a lock at launch, so a
|
|
1010
|
+
second copy surfaces the running one's menu and exits instead of adding a
|
|
1011
|
+
duplicate icon. `agents menubar setup` is the recovery command when a machine is
|
|
1012
|
+
already wrong -- it ends any duplicate, installs the bundle, wires the login
|
|
1013
|
+
item, and verifies exactly one helper came back up.
|
|
1014
|
+
|
|
1009
1015
|
The dropdown surfaces a **NEEDS YOU** queue (agents waiting on a question, a plan review, or a permission prompt), the running roster, and a routines summary -- the same live state as `agents sessions --active`, one click away.
|
|
1010
1016
|
|
|
1011
1017
|
### Quick-issue bar (⌘⇧O)
|
|
1012
1018
|
|
|
1013
1019
|
Press `Cmd-Shift-O` anywhere for a thin capture surface: type a one-line note, `Cmd-V` to paste, and attach one or more recent screenshots (double-click a thumbnail to preview it in full). Submit, and a headless agent picks the right project from your recent sessions, investigates, and files the Linear ticket itself -- you never leave what you were doing.
|
|
1014
1020
|
|
|
1021
|
+
The bar also lists the **open Linear tickets of the repo you picked**, urgent first. Switching the repo switches the Linear project; typing filters the list, so an existing ticket shows up before you file a duplicate; and clicking a row (or `⌘1`-`⌘5`) dispatches that ticket to the selected agents -- **Run** implements it, **Plan** posts a plan as a ticket comment.
|
|
1022
|
+
|
|
1015
1023
|
<p align="center">
|
|
1016
1024
|
<img src="assets/menubar-quickissue.svg" alt="The Cmd-Shift-O quick-issue bar: a one-line note with attached screenshot thumbnails that a headless agent turns into a filed Linear ticket" width="100%" />
|
|
1017
1025
|
</p>
|
|
@@ -1116,7 +1124,7 @@ Which DotAgents resources each agent CLI can load. Source of truth: [src/lib/age
|
|
|
1116
1124
|
| Antigravity | yes | yes | yes | yes | yes | yes | yes | no | `AGENTS.md` | no |
|
|
1117
1125
|
| Grok Build | yes | yes | yes | yes | yes | skills ($name) | yes | no | `AGENTS.md` | no |
|
|
1118
1126
|
| OpenClaw | yes | yes | yes | no | yes | gateway | yes | yes | `workspace/AGENTS.md` | no |
|
|
1119
|
-
| Cursor | yes |
|
|
1127
|
+
| Cursor | yes | yes | yes | yes | yes | IDE + skills ($name) | yes | >= 2026.1.22 | `.cursorrules` | no |
|
|
1120
1128
|
| OpenCode | yes | no | yes | >= 1.1.1 | yes | yes | no | no | `AGENTS.md` | no |
|
|
1121
1129
|
| Copilot | yes | no | yes | no | yes | yes | no | no | `AGENTS.md` | no |
|
|
1122
1130
|
| Amp | yes | no | yes | no | yes | yes | no | no | `AGENTS.md` | no |
|
|
@@ -1125,7 +1133,7 @@ Which DotAgents resources each agent CLI can load. Source of truth: [src/lib/age
|
|
|
1125
1133
|
| Roo Code | yes | no | yes | no | yes | yes | no | no | `AGENTS.md` | no |
|
|
1126
1134
|
| Droid | yes | yes | yes | >= 0.57.5 | >= 0.26.0 | yes | yes | yes | `AGENTS.md` | no |
|
|
1127
1135
|
|
|
1128
|
-
**Legend:** `yes` / `no` = synced or skipped at install time. `skills ($name)` = no file-based slash-command dir; behavior ships as a generated skill invoked with `$command`. `gateway` = OpenClaw resolves slash commands at runtime, not from synced files. Version suffixes are enforced at sync time — out-of-range versions are skipped with a clear message.
|
|
1136
|
+
**Legend:** `yes` / `no` = synced or skipped at install time. `skills ($name)` = no file-based slash-command dir; behavior ships as a generated skill invoked with `$command`. `IDE + skills ($name)` = an IDE command file plus a generated skill for the CLI. `gateway` = OpenClaw resolves slash commands at runtime, not from synced files. Version suffixes are enforced at sync time — out-of-range versions are skipped with a clear message.
|
|
1129
1137
|
|
|
1130
1138
|
**Host CLIs** (`agents cli`) are separate: YAML manifests under `~/.agents/cli/` install binaries onto your PATH (`gh`, `higgsfield`, etc.). They are not copied into per-agent version homes.
|
|
1131
1139
|
|
package/dist/bin/agents
CHANGED
|
Binary file
|
|
@@ -35,7 +35,7 @@ Examples:
|
|
|
35
35
|
agents commands add
|
|
36
36
|
|
|
37
37
|
# Install specific commands by name
|
|
38
|
-
agents commands add --names
|
|
38
|
+
agents commands add --names plan,debug --agents codex@0.116.0
|
|
39
39
|
|
|
40
40
|
When to use:
|
|
41
41
|
- Project setup: 'agents commands add gh:team/commands' to sync everyone's workflow
|
|
@@ -90,7 +90,7 @@ Examples:
|
|
|
90
90
|
agents commands add
|
|
91
91
|
|
|
92
92
|
# Install specific commands to a single version
|
|
93
|
-
agents commands add --names
|
|
93
|
+
agents commands add --names plan,debug --agents codex@0.116.0
|
|
94
94
|
|
|
95
95
|
# Pull commands from GitHub and sync to all installed agents
|
|
96
96
|
agents commands add gh:user/repo --agents claude,codex,cursor
|
|
@@ -125,7 +125,7 @@ Examples:
|
|
|
125
125
|
else {
|
|
126
126
|
if (!isInteractiveTerminal()) {
|
|
127
127
|
requireInteractiveSelection('Selecting commands from ~/.agents/commands/', [
|
|
128
|
-
'agents commands add --names
|
|
128
|
+
'agents commands add --names plan,debug --agents codex',
|
|
129
129
|
'agents commands add gh:user/repo --agents codex',
|
|
130
130
|
]);
|
|
131
131
|
}
|
|
@@ -272,7 +272,7 @@ Examples:
|
|
|
272
272
|
.addHelpText('after', `
|
|
273
273
|
Examples:
|
|
274
274
|
# Remove a command by name
|
|
275
|
-
agents commands remove
|
|
275
|
+
agents commands remove plan
|
|
276
276
|
|
|
277
277
|
# Interactive: pick commands to remove
|
|
278
278
|
agents commands remove
|
|
@@ -305,7 +305,7 @@ Examples:
|
|
|
305
305
|
}
|
|
306
306
|
if (!isInteractiveTerminal()) {
|
|
307
307
|
requireInteractiveSelection('Selecting commands to remove', [
|
|
308
|
-
'agents commands remove
|
|
308
|
+
'agents commands remove plan',
|
|
309
309
|
]);
|
|
310
310
|
}
|
|
311
311
|
try {
|
|
@@ -422,7 +422,7 @@ Examples:
|
|
|
422
422
|
.addHelpText('after', `
|
|
423
423
|
Examples:
|
|
424
424
|
# View a specific command
|
|
425
|
-
agents commands view
|
|
425
|
+
agents commands view plan
|
|
426
426
|
|
|
427
427
|
# Interactive picker
|
|
428
428
|
agents commands view
|
|
@@ -437,7 +437,7 @@ Examples:
|
|
|
437
437
|
}
|
|
438
438
|
if (!isInteractiveTerminal()) {
|
|
439
439
|
requireInteractiveSelection('Selecting a command to view', [
|
|
440
|
-
'agents commands view
|
|
440
|
+
'agents commands view plan',
|
|
441
441
|
]);
|
|
442
442
|
}
|
|
443
443
|
try {
|
|
@@ -22,30 +22,11 @@
|
|
|
22
22
|
* apply pending sync.
|
|
23
23
|
*/
|
|
24
24
|
import type { Command } from 'commander';
|
|
25
|
-
import { type FleetDivergenceReport } from '../lib/devices/fleet-divergence.js';
|
|
26
25
|
import { type VersionResourceReport } from '../lib/doctor-diff.js';
|
|
27
26
|
import { type DuplicateVersionHook } from '../lib/hooks.js';
|
|
28
27
|
import { type SyncStatusRow, type OrphanRow } from '../lib/drift.js';
|
|
29
28
|
import { type FetchStatusMarker } from '../lib/auto-pull.js';
|
|
30
29
|
export declare function wrapLine(prefix: string, text: string, width?: number): string[];
|
|
31
|
-
/**
|
|
32
|
-
* Windows-only advisory lines. When the effective PowerShell execution policy
|
|
33
|
-
* blocks unsigned local `.ps1` scripts (`Restricted`/`AllSigned`), the generated
|
|
34
|
-
* `agents.ps1` launcher fails in PowerShell even when it is on PATH. Surface the
|
|
35
|
-
* remediation; the `.cmd` companion still works, so this is a warning, not an
|
|
36
|
-
* error, and doctor never auto-changes the policy. Pure — returns `[]` on
|
|
37
|
-
* non-Windows or a permissive policy, so it is testable without invoking
|
|
38
|
-
* PowerShell.
|
|
39
|
-
*/
|
|
40
|
-
export declare function execPolicyWarningLines(platform: NodeJS.Platform, policy: string | null): string[];
|
|
41
|
-
/**
|
|
42
|
-
* Render the cross-device divergence section for `agents doctor --devices`
|
|
43
|
-
* (RUSH-2027): a clean all-clear when the fleet agrees, otherwise the specific
|
|
44
|
-
* gaps — a resource/version present here but missing on a box, or a diverged
|
|
45
|
-
* config repo — grouped by device, each a plain-language line. Devices that
|
|
46
|
-
* couldn't be compared (offline / older CLI) are named so the readout is honest.
|
|
47
|
-
*/
|
|
48
|
-
export declare function renderFleetDivergence(report: FleetDivergenceReport): string[];
|
|
49
30
|
export type IssueSeverity = 'critical' | 'warning' | 'info';
|
|
50
31
|
/**
|
|
51
32
|
* One triaged health finding. `severity`/`category`/`subject`/`impact`/`fix` are
|