@phnx-labs/agents-cli 1.22.47 → 1.22.49

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.
Files changed (249) hide show
  1. package/CHANGELOG.md +401 -17
  2. package/README.md +66 -32
  3. package/dist/bootstrap.js +4 -2
  4. package/dist/cli/command-registry.d.ts +1 -0
  5. package/dist/cli/command-registry.js +2 -0
  6. package/dist/commands/accounts.d.ts +58 -0
  7. package/dist/commands/accounts.js +206 -32
  8. package/dist/commands/artifacts.js +7 -6
  9. package/dist/commands/attach.js +1 -1
  10. package/dist/commands/browser.js +501 -103
  11. package/dist/commands/config.d.ts +0 -1
  12. package/dist/commands/config.js +0 -20
  13. package/dist/commands/daemon.d.ts +21 -0
  14. package/dist/commands/daemon.js +147 -12
  15. package/dist/commands/exec.js +52 -15
  16. package/dist/commands/focus.d.ts +14 -0
  17. package/dist/commands/focus.js +48 -5
  18. package/dist/commands/go.d.ts +3 -0
  19. package/dist/commands/go.js +16 -3
  20. package/dist/commands/inspect.js +2 -2
  21. package/dist/commands/lease.d.ts +1 -1
  22. package/dist/commands/lease.js +4 -3
  23. package/dist/commands/mailboxes.js +4 -3
  24. package/dist/commands/menubar.js +11 -4
  25. package/dist/commands/projects.d.ts +16 -1
  26. package/dist/commands/projects.js +58 -64
  27. package/dist/commands/resume.js +1 -1
  28. package/dist/commands/route.js +4 -4
  29. package/dist/commands/routines.js +3 -2
  30. package/dist/commands/run-broadcast.d.ts +1 -1
  31. package/dist/commands/run-broadcast.js +1 -1
  32. package/dist/commands/sessions-picker.d.ts +22 -0
  33. package/dist/commands/sessions-picker.js +48 -9
  34. package/dist/commands/sessions-trace.js +1 -1
  35. package/dist/commands/sessions.js +1 -0
  36. package/dist/commands/setup-secrets.js +23 -0
  37. package/dist/commands/share.d.ts +20 -5
  38. package/dist/commands/share.js +152 -52
  39. package/dist/commands/ssh.js +54 -7
  40. package/dist/commands/traces.d.ts +2 -0
  41. package/dist/commands/traces.js +184 -0
  42. package/dist/commands/view.d.ts +1 -1
  43. package/dist/commands/view.js +17 -34
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.js +5 -0
  46. package/dist/lib/accounting/usage.d.ts +14 -3
  47. package/dist/lib/accounting/usage.js +64 -18
  48. package/dist/lib/agent-spec/agents.js +11 -9
  49. package/dist/lib/browser/drivers/ssh.d.ts +16 -2
  50. package/dist/lib/browser/drivers/ssh.js +36 -9
  51. package/dist/lib/browser/ipc.js +8 -3
  52. package/dist/lib/browser/profiles.d.ts +35 -101
  53. package/dist/lib/browser/profiles.js +130 -301
  54. package/dist/lib/browser/registry.d.ts +39 -0
  55. package/dist/lib/browser/registry.js +149 -0
  56. package/dist/lib/browser/remote-control.d.ts +8 -6
  57. package/dist/lib/browser/remote-control.js +8 -6
  58. package/dist/lib/browser/resolve-target.d.ts +68 -0
  59. package/dist/lib/browser/resolve-target.js +250 -0
  60. package/dist/lib/browser/runtime-state.d.ts +40 -16
  61. package/dist/lib/browser/runtime-state.js +92 -25
  62. package/dist/lib/browser/service.d.ts +28 -9
  63. package/dist/lib/browser/service.js +139 -62
  64. package/dist/lib/browser/task-index.d.ts +70 -0
  65. package/dist/lib/browser/task-index.js +180 -0
  66. package/dist/lib/byok-usage.js +2 -2
  67. package/dist/lib/claude-statusline.d.ts +29 -0
  68. package/dist/lib/claude-statusline.js +139 -0
  69. package/dist/lib/cloud/host.d.ts +1 -1
  70. package/dist/lib/cloud/host.js +1 -1
  71. package/dist/lib/cloud/rush.js +1 -1
  72. package/dist/lib/computer/computer-rpc.js +2 -2
  73. package/dist/lib/computer/download.d.ts +15 -15
  74. package/dist/lib/computer/download.js +35 -98
  75. package/dist/lib/computer/ssh-tunnel.d.ts +0 -3
  76. package/dist/lib/computer/ssh-tunnel.js +12 -22
  77. package/dist/lib/config-keys.d.ts +2 -8
  78. package/dist/lib/config-keys.js +2 -13
  79. package/dist/lib/crabbox/cli.d.ts +1 -1
  80. package/dist/lib/crabbox/cli.js +2 -2
  81. package/dist/lib/crabbox/lease.d.ts +9 -0
  82. package/dist/lib/crabbox/lease.js +70 -15
  83. package/dist/lib/crabbox/runtimes.js +1 -1
  84. package/dist/lib/daemon/account-state-daemon-service.d.ts +16 -0
  85. package/dist/lib/daemon/account-state-daemon-service.js +26 -0
  86. package/dist/lib/daemon/browser-ipc-service.d.ts +20 -0
  87. package/dist/lib/daemon/browser-ipc-service.js +46 -0
  88. package/dist/lib/daemon/daemon.d.ts +3 -0
  89. package/dist/lib/daemon/daemon.js +212 -444
  90. package/dist/lib/daemon/device-probe-service.d.ts +26 -0
  91. package/dist/lib/daemon/device-probe-service.js +47 -0
  92. package/dist/lib/daemon/keychain-reap-service.d.ts +17 -0
  93. package/dist/lib/daemon/keychain-reap-service.js +32 -0
  94. package/dist/lib/daemon/monitor-engine-service.d.ts +22 -0
  95. package/dist/lib/daemon/monitor-engine-service.js +29 -0
  96. package/dist/lib/daemon/secrets-broker-service.d.ts +20 -0
  97. package/dist/lib/daemon/secrets-broker-service.js +66 -0
  98. package/dist/lib/daemon/self-heal-service.d.ts +27 -0
  99. package/dist/lib/daemon/self-heal-service.js +48 -0
  100. package/dist/lib/daemon/service.d.ts +102 -0
  101. package/dist/lib/daemon/service.js +98 -0
  102. package/dist/lib/daemon/session-index-service.d.ts +22 -0
  103. package/dist/lib/daemon/session-index-service.js +40 -0
  104. package/dist/lib/daemon/state-dir-check-service.d.ts +43 -0
  105. package/dist/lib/daemon/state-dir-check-service.js +63 -0
  106. package/dist/lib/daemon/supervisor.d.ts +87 -0
  107. package/dist/lib/daemon/supervisor.js +298 -0
  108. package/dist/lib/daemon/watchdog-service.d.ts +19 -0
  109. package/dist/lib/daemon/watchdog-service.js +40 -0
  110. package/dist/lib/daemon-health.d.ts +15 -0
  111. package/dist/lib/daemon-health.js +29 -5
  112. package/dist/lib/daemon-services.d.ts +8 -1
  113. package/dist/lib/daemon-services.js +55 -0
  114. package/dist/lib/daemon-ticks.d.ts +13 -2
  115. package/dist/lib/daemon-ticks.js +20 -18
  116. package/dist/lib/device-config.d.ts +0 -2
  117. package/dist/lib/device-config.js +1 -23
  118. package/dist/lib/devices/registry.d.ts +1 -1
  119. package/dist/lib/devices/registry.js +1 -1
  120. package/dist/lib/devices/stats-cache.d.ts +20 -0
  121. package/dist/lib/devices/stats-cache.js +49 -5
  122. package/dist/lib/devices/worker-pick.d.ts +48 -0
  123. package/dist/lib/devices/worker-pick.js +113 -0
  124. package/dist/lib/exec.d.ts +67 -13
  125. package/dist/lib/exec.js +85 -29
  126. package/dist/lib/harness/adapters/cursor.js +8 -11
  127. package/dist/lib/helper-download.d.ts +108 -0
  128. package/dist/lib/helper-download.js +194 -0
  129. package/dist/lib/helper-versions.d.ts +52 -0
  130. package/dist/lib/helper-versions.js +58 -0
  131. package/dist/lib/hooks/cache.js +11 -0
  132. package/dist/lib/hooks/install.js +2 -2
  133. package/dist/lib/hosts/credentials.d.ts +1 -1
  134. package/dist/lib/hosts/credentials.js +1 -1
  135. package/dist/lib/hosts/dispatch.d.ts +7 -1
  136. package/dist/lib/hosts/dispatch.js +24 -5
  137. package/dist/lib/hosts/passthrough.d.ts +8 -15
  138. package/dist/lib/hosts/passthrough.js +19 -16
  139. package/dist/lib/hosts/providers/devices.d.ts +1 -1
  140. package/dist/lib/hosts/providers/devices.js +1 -1
  141. package/dist/lib/hosts/reconnect.d.ts +179 -21
  142. package/dist/lib/hosts/reconnect.js +266 -45
  143. package/dist/lib/installations/migrate.d.ts +4 -5
  144. package/dist/lib/installations/migrate.js +6 -7
  145. package/dist/lib/installations/shims.d.ts +1 -1
  146. package/dist/lib/installations/shims.js +23 -13
  147. package/dist/lib/installations/versions.js +25 -2
  148. package/dist/lib/linear-autoclose.d.ts +1 -1
  149. package/dist/lib/linear-autoclose.js +1 -1
  150. package/dist/lib/loop.d.ts +2 -2
  151. package/dist/lib/loop.js +1 -1
  152. package/dist/lib/menubar/download-menubar.d.ts +47 -0
  153. package/dist/lib/menubar/download-menubar.js +60 -0
  154. package/dist/lib/menubar/install-menubar.d.ts +31 -7
  155. package/dist/lib/menubar/install-menubar.js +79 -21
  156. package/dist/lib/menubar/notify-desktop.d.ts +3 -3
  157. package/dist/lib/menubar/notify-desktop.js +6 -6
  158. package/dist/lib/model-tiers.d.ts +1 -1
  159. package/dist/lib/project-probe.d.ts +1 -1
  160. package/dist/lib/project-probe.js +1 -1
  161. package/dist/lib/project-pull.d.ts +1 -1
  162. package/dist/lib/project-pull.js +2 -2
  163. package/dist/lib/projects.d.ts +1 -1
  164. package/dist/lib/projects.js +1 -1
  165. package/dist/lib/sandbox.js +6 -7
  166. package/dist/lib/secrets/download-keychain.d.ts +47 -0
  167. package/dist/lib/secrets/download-keychain.js +70 -0
  168. package/dist/lib/secrets/install-helper.d.ts +20 -1
  169. package/dist/lib/secrets/install-helper.js +44 -3
  170. package/dist/lib/session/active.js +17 -1
  171. package/dist/lib/session/db.d.ts +11 -1
  172. package/dist/lib/session/db.js +138 -6
  173. package/dist/lib/session/discover.d.ts +21 -1
  174. package/dist/lib/session/discover.js +33 -5
  175. package/dist/lib/session/highlights.d.ts +49 -1
  176. package/dist/lib/session/highlights.js +95 -0
  177. package/dist/lib/session/host-link.d.ts +16 -2
  178. package/dist/lib/session/host-link.js +7 -1
  179. package/dist/lib/session/parse.js +33 -1
  180. package/dist/lib/session/remote/remote-list.d.ts +9 -0
  181. package/dist/lib/session/remote/remote-list.js +19 -2
  182. package/dist/lib/session/remote/watch.js +11 -2
  183. package/dist/lib/session/session-cache.d.ts +53 -0
  184. package/dist/lib/session/session-cache.js +88 -0
  185. package/dist/lib/session/state.js +1 -1
  186. package/dist/lib/session/tool-calls.d.ts +2 -0
  187. package/dist/lib/session/tool-calls.js +1 -1
  188. package/dist/lib/session/trajectory-html.d.ts +5 -1
  189. package/dist/lib/session/trajectory-html.js +42 -22
  190. package/dist/lib/session/trajectory-text.js +9 -2
  191. package/dist/lib/session/trajectory.js +53 -4
  192. package/dist/lib/session/types.d.ts +15 -0
  193. package/dist/lib/sha256-asset.d.ts +26 -0
  194. package/dist/lib/sha256-asset.js +41 -0
  195. package/dist/lib/share/backend.d.ts +95 -0
  196. package/dist/lib/share/backend.js +139 -0
  197. package/dist/lib/share/delete.d.ts +6 -2
  198. package/dist/lib/share/delete.js +8 -9
  199. package/dist/lib/share/html.d.ts +22 -0
  200. package/dist/lib/share/html.js +88 -0
  201. package/dist/lib/share/provision.d.ts +18 -4
  202. package/dist/lib/share/provision.js +38 -4
  203. package/dist/lib/share/publish.d.ts +39 -15
  204. package/dist/lib/share/publish.js +55 -26
  205. package/dist/lib/share/worker-template.js +171 -11
  206. package/dist/lib/sqlite.js +16 -3
  207. package/dist/lib/ssh-exec.d.ts +65 -0
  208. package/dist/lib/ssh-exec.js +120 -4
  209. package/dist/lib/startup/command-registry.js +1 -1
  210. package/dist/lib/startup/dev-build.js +3 -3
  211. package/dist/lib/state.d.ts +1 -1
  212. package/dist/lib/state.js +7 -3
  213. package/dist/lib/subagents-registry.js +1 -1
  214. package/dist/lib/terminal/index.d.ts +1 -1
  215. package/dist/lib/terminal/types.d.ts +1 -1
  216. package/dist/lib/terminal/types.js +1 -1
  217. package/dist/lib/tmux/orphan-reap.js +1 -1
  218. package/dist/lib/tmux/session.js +31 -0
  219. package/dist/lib/traces/backend.d.ts +29 -0
  220. package/dist/lib/traces/backend.js +46 -0
  221. package/dist/lib/traces/classify.d.ts +52 -0
  222. package/dist/lib/traces/classify.js +72 -0
  223. package/dist/lib/traces/config.d.ts +10 -0
  224. package/dist/lib/traces/config.js +2 -0
  225. package/dist/lib/traces/provision.d.ts +19 -0
  226. package/dist/lib/traces/provision.js +30 -0
  227. package/dist/lib/traces/sync.d.ts +150 -0
  228. package/dist/lib/traces/sync.js +447 -0
  229. package/dist/lib/traces/worker-template.d.ts +4 -0
  230. package/dist/lib/traces/worker-template.js +159 -0
  231. package/dist/lib/types.d.ts +18 -19
  232. package/dist/lib/types.js +14 -0
  233. package/dist/lib/usage-refresh.d.ts +1 -1
  234. package/dist/lib/usage-refresh.js +11 -8
  235. package/dist/lib/workflows.d.ts +1 -1
  236. package/package.json +4 -6
  237. package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
  238. package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +0 -24
  239. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  240. package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
  241. package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +0 -128
  242. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  243. package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +0 -26
  244. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  245. package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
  246. package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +0 -135
  247. package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
  248. package/dist/lib/usage-fleet.d.ts +0 -32
  249. package/dist/lib/usage-fleet.js +0 -125
@@ -6,7 +6,7 @@
6
6
  * can spawn subagents freely). Every guard — `max_iterations`, `budget`, the
7
7
  * `until: signal` condition, SIGINT/SIGTERM — lives OUTSIDE the agent, so the
8
8
  * agent cannot vote past a kill-switch (the standard answer to runaway-loop and
9
- * runaway-cost failure modes; see docs/entrypoints-and-loops.md).
9
+ * runaway-cost failure modes; see docs/execution.md).
10
10
  *
11
11
  * Structure mirrors the teams supervisor (`runSupervisor` in teams/supervisor.ts):
12
12
  * a bounded for-loop with a hard cap, a SIGINT/SIGTERM trap that flips a stop
@@ -21,7 +21,7 @@
21
21
  import type { AgentId } from './types.js';
22
22
  import type { ExecOptions } from './exec.js';
23
23
  import { type Checkpoint } from './checkpoint.js';
24
- /** Loop block config (docs/entrypoints-and-loops.md → "The loop block"). */
24
+ /** Loop block config; see docs/execution.md. */
25
25
  export interface LoopConfig {
26
26
  /** Stop condition. `signal` reads loop-signal.json; absence is fail-closed. */
27
27
  until?: 'signal';
package/dist/lib/loop.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * can spawn subagents freely). Every guard — `max_iterations`, `budget`, the
7
7
  * `until: signal` condition, SIGINT/SIGTERM — lives OUTSIDE the agent, so the
8
8
  * agent cannot vote past a kill-switch (the standard answer to runaway-loop and
9
- * runaway-cost failure modes; see docs/entrypoints-and-loops.md).
9
+ * runaway-cost failure modes; see docs/execution.md).
10
10
  *
11
11
  * Structure mirrors the teams supervisor (`runSupervisor` in teams/supervisor.ts):
12
12
  * a bounded for-loop with a hard cap, a SIGINT/SIGTERM trap that flips a stop
@@ -0,0 +1,47 @@
1
+ /**
2
+ * On-demand download + verification of the macOS menu-bar helper
3
+ * ("MenubarHelper.app").
4
+ *
5
+ * Mirrors the ComputerHelper download model (`../computer/download.ts`): the
6
+ * helper ships as a signed + notarized `.app` zipped as a GitHub release asset
7
+ * on the helper's own `menubar/v<x.y.z>` tag, NOT the CLI's tag (see
8
+ * `helper-versions.ts`). A fresh `npm i -g` machine whose tarball lacks a
9
+ * bundled copy fetches the asset for the pinned helper version, verifies its
10
+ * sha256 + code signature before install.
11
+ *
12
+ * The one difference — and the reason this is not the ComputerHelper spec — is
13
+ * the DESIGNATED-REQUIREMENT pin. macOS keys the menu bar's Accessibility (TCC)
14
+ * grant to the bundle's designated requirement (bundle id
15
+ * `com.phnx-labs.agents-menubar` + Developer ID Team `2HTP252L87`), and
16
+ * re-validates each new version against it. A downloaded bundle whose DR drops
17
+ * either pin would silently revoke the user's grant, so `MENUBAR_HELPER_SPEC`
18
+ * sets `expectedBundleId` and the shared `verifyHelperApp` enforces the DR
19
+ * before the bundle is ever installed. This matches the release-time gate in
20
+ * `scripts/verify-menubar-helper.sh`.
21
+ */
22
+ import { type HelperSpec } from '../helper-download.js';
23
+ /** The zipped `.app` release asset name. */
24
+ export declare const MENUBAR_HELPER_ASSET = "MenubarHelper.app.zip";
25
+ /** The bundle directory name once extracted. */
26
+ export declare const MENUBAR_HELPER_APP_NAME = "MenubarHelper.app";
27
+ /** The bundle id the Accessibility grant (and thus the designated requirement)
28
+ * is keyed to — the same value `install-menubar.ts`'s `SERVICE_LABEL_BASE` and
29
+ * `scripts/verify-menubar-helper.sh` pin. */
30
+ export declare const MENUBAR_HELPER_BUNDLE_ID = "com.phnx-labs.agents-menubar";
31
+ /** MenubarHelper identity + verification policy — DR-pinned (see docblock). */
32
+ export declare const MENUBAR_HELPER_SPEC: HelperSpec;
33
+ /** Release-asset URLs for the menu-bar helper zip + its checksum at `v<version>`. */
34
+ export declare function menubarHelperAssetUrls(version: string): {
35
+ zip: string;
36
+ sha256: string;
37
+ };
38
+ /** Cache dir for the downloaded menu-bar helper, one subdir per release tag. */
39
+ export declare function menubarHelperCacheDir(version: string): string;
40
+ /** Verify a menu-bar helper `.app`: codesign + Team + DR pin + notarization. */
41
+ export declare function verifyMenubarHelper(appPath: string): void;
42
+ /**
43
+ * Download the menu-bar helper release asset for `version`, verify sha256 +
44
+ * signature + DR pin, and return the path to the extracted `MenubarHelper.app`
45
+ * in the cache. A missing asset is a hard error naming the exact tag.
46
+ */
47
+ export declare function downloadMenubarHelperApp(version: string): Promise<string>;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * On-demand download + verification of the macOS menu-bar helper
3
+ * ("MenubarHelper.app").
4
+ *
5
+ * Mirrors the ComputerHelper download model (`../computer/download.ts`): the
6
+ * helper ships as a signed + notarized `.app` zipped as a GitHub release asset
7
+ * on the helper's own `menubar/v<x.y.z>` tag, NOT the CLI's tag (see
8
+ * `helper-versions.ts`). A fresh `npm i -g` machine whose tarball lacks a
9
+ * bundled copy fetches the asset for the pinned helper version, verifies its
10
+ * sha256 + code signature before install.
11
+ *
12
+ * The one difference — and the reason this is not the ComputerHelper spec — is
13
+ * the DESIGNATED-REQUIREMENT pin. macOS keys the menu bar's Accessibility (TCC)
14
+ * grant to the bundle's designated requirement (bundle id
15
+ * `com.phnx-labs.agents-menubar` + Developer ID Team `2HTP252L87`), and
16
+ * re-validates each new version against it. A downloaded bundle whose DR drops
17
+ * either pin would silently revoke the user's grant, so `MENUBAR_HELPER_SPEC`
18
+ * sets `expectedBundleId` and the shared `verifyHelperApp` enforces the DR
19
+ * before the bundle is ever installed. This matches the release-time gate in
20
+ * `scripts/verify-menubar-helper.sh`.
21
+ */
22
+ import { EXPECTED_TEAM_ID, downloadHelperApp, helperAssetUrls, helperCacheDir, verifyHelperApp, } from '../helper-download.js';
23
+ /** The zipped `.app` release asset name. */
24
+ export const MENUBAR_HELPER_ASSET = 'MenubarHelper.app.zip';
25
+ /** The bundle directory name once extracted. */
26
+ export const MENUBAR_HELPER_APP_NAME = 'MenubarHelper.app';
27
+ /** The bundle id the Accessibility grant (and thus the designated requirement)
28
+ * is keyed to — the same value `install-menubar.ts`'s `SERVICE_LABEL_BASE` and
29
+ * `scripts/verify-menubar-helper.sh` pin. */
30
+ export const MENUBAR_HELPER_BUNDLE_ID = 'com.phnx-labs.agents-menubar';
31
+ /** MenubarHelper identity + verification policy — DR-pinned (see docblock). */
32
+ export const MENUBAR_HELPER_SPEC = {
33
+ helper: 'menubar',
34
+ assetName: MENUBAR_HELPER_ASSET,
35
+ appName: MENUBAR_HELPER_APP_NAME,
36
+ cacheSubdir: ['menubar', 'mac-helper'],
37
+ expectedTeamId: EXPECTED_TEAM_ID,
38
+ expectedBundleId: MENUBAR_HELPER_BUNDLE_ID,
39
+ localBuildHint: 'menubar/scripts/build.sh release, then cp -R menubar/dist/MenubarHelper.app bin/MenubarHelper.app',
40
+ };
41
+ /** Release-asset URLs for the menu-bar helper zip + its checksum at `v<version>`. */
42
+ export function menubarHelperAssetUrls(version) {
43
+ return helperAssetUrls(MENUBAR_HELPER_SPEC, version);
44
+ }
45
+ /** Cache dir for the downloaded menu-bar helper, one subdir per release tag. */
46
+ export function menubarHelperCacheDir(version) {
47
+ return helperCacheDir(MENUBAR_HELPER_SPEC, version);
48
+ }
49
+ /** Verify a menu-bar helper `.app`: codesign + Team + DR pin + notarization. */
50
+ export function verifyMenubarHelper(appPath) {
51
+ verifyHelperApp(appPath, MENUBAR_HELPER_SPEC);
52
+ }
53
+ /**
54
+ * Download the menu-bar helper release asset for `version`, verify sha256 +
55
+ * signature + DR pin, and return the path to the extracted `MenubarHelper.app`
56
+ * in the cache. A missing asset is a hard error naming the exact tag.
57
+ */
58
+ export function downloadMenubarHelperApp(version) {
59
+ return downloadHelperApp(MENUBAR_HELPER_SPEC, version);
60
+ }
@@ -14,6 +14,20 @@
14
14
  * migration (`installMenubarLaunchAgent` in migrate.ts) honors, so a disabled
15
15
  * menu bar never silently comes back on the next release.
16
16
  */
17
+ /**
18
+ * The bundled executable's basename (RUSH-3101) — what launchd execs directly
19
+ * inside `Contents/MacOS/`, bypassing LaunchServices name resolution. Before
20
+ * this it was `MenubarHelper`, so that raw Mach-O basename is exactly what
21
+ * macOS showed in System Settings > Privacy & Security > Accessibility and in
22
+ * the "would like to control this computer" prompt. Renaming this constant
23
+ * alone does NOT touch the bundle id, Team ID, or designated requirement
24
+ * (`SERVICE_LABEL_BASE`, `MENUBAR_HELPER_BUNDLE_ID` in download-menubar.ts) —
25
+ * those are what keep the existing Accessibility grant alive across upgrades.
26
+ * Every basename-matching check reads this constant rather than re-deriving
27
+ * the string; the Swift side has its own equal in
28
+ * `menubar/Sources/MenubarHelper/HelperIdentity.swift`.
29
+ */
30
+ export declare const MENUBAR_HELPER_EXECUTABLE_NAME = "AGI Menu";
17
31
  /**
18
32
  * launchd Label for this process's helper — the production identifier for a
19
33
  * real invocation, namespaced under a redirected HOME (RUSH-2639). launchd
@@ -22,9 +36,9 @@
22
36
  */
23
37
  export declare function serviceLabel(): string;
24
38
  /**
25
- * Absolute path to the installed MenubarHelper executable if it exists on disk,
26
- * else null. The desktop notifier (notify-desktop.ts) routes daemon
27
- * notifications through this one-shot (`MenubarHelper --notify ...`) so they
39
+ * Absolute path to the installed menu-bar helper executable if it exists on
40
+ * disk, else null. The desktop notifier (notify-desktop.ts) routes daemon
41
+ * notifications through this one-shot (`"AGI Menu" --notify ...`) so they
28
42
  * carry the agents-cli mark rather than the generic osascript icon. Null on
29
43
  * non-darwin or when the helper is not installed (menu bar disabled, a Linux
30
44
  * package, or a dev checkout without a built bundle).
@@ -61,6 +75,7 @@ export declare function hasDeveloperIdSignature(appPath: string): boolean;
61
75
  */
62
76
  export declare function ensureMenubarAppInstalled(opts?: {
63
77
  forceReinstall?: boolean;
78
+ sourceAppPath?: string;
64
79
  }): string | null;
65
80
  export declare function generateServicePlist(execPath: string): string;
66
81
  /**
@@ -106,11 +121,20 @@ export declare function restartMenubarHelperAfterSwap(uid: number, ownProcesses:
106
121
  * Install + start the menu-bar helper as a launchd user service (idempotent).
107
122
  * Clears the sticky opt-out, installs the .app, writes the plist, and
108
123
  * bootstraps it into the GUI domain. Returns false on non-darwin or when no
109
- * helper bundle ships with this install.
124
+ * helper bundle can be resolved for this install.
125
+ *
126
+ * ASYNC and download-capable: this is the EXPLICIT user-initiated path
127
+ * (`agents menubar enable`). When no bundled/local `.app` ships (a fresh
128
+ * `npm i -g` machine whose tarball lacks the bundle), it fetches the signed +
129
+ * notarized release asset for the running CLI version — verified (sha256 +
130
+ * codesign + Team + designated-requirement pin + notarization) before install
131
+ * — and starts the service from that cached copy. The startup self-heal never
132
+ * routes here: it calls `startMenubarServiceFromSource` and stays sync +
133
+ * network-free, no-opping when no local source exists.
110
134
  */
111
135
  export declare function enableMenubarService(opts?: {
112
136
  clearOptOut?: boolean;
113
- }): boolean;
137
+ }): Promise<boolean>;
114
138
  /**
115
139
  * Pure staleness decision (no I/O) so the truth table is unit-testable. The
116
140
  * installed service is stale when the helper binary is gone, or when it was
@@ -296,7 +320,7 @@ export declare function processesToEnd(status: Pick<MenubarStatus, 'instances' |
296
320
  * 4. login item — write the plist (RunAtLoad + KeepAlive) and bootstrap it
297
321
  * 5. single — verify exactly one helper came back up
298
322
  */
299
- export declare function runMenubarSetup(): SetupResult;
323
+ export declare function runMenubarSetup(): Promise<SetupResult>;
300
324
  /** A live MenubarHelper process: its pid and the executable it is running. */
301
325
  export interface MenubarProcess {
302
326
  pid: number;
@@ -320,7 +344,7 @@ export interface MenubarProcess {
320
344
  *
321
345
  * Identity comes from `comm` (the resolved executable), never from a substring
322
346
  * of the command line: matching the latter flags any shell that merely mentions
323
- * MenubarHelper. `command` is consulted only to drop `--notify` one-shots.
347
+ * the helper's name. `command` is consulted only to drop `--notify` one-shots.
324
348
  */
325
349
  export declare function classifyMenubarProcesses(commOutput: string, commandOutput: string, installedExec: string): {
326
350
  own: MenubarProcess[];
@@ -25,9 +25,25 @@ import { getCliVersion, resolveAgentsBin, resolveInstalledLayout } from '../vers
25
25
  import { copyAppBundle, withInstallLock } from '../app-bundle-install.js';
26
26
  import { compareVersions } from '../agent-spec/primitives.js';
27
27
  import { namespacedServiceLabel, serviceManifestHomeEnv, serviceManagerRegistrationAllowed } from '../service-manifest.js';
28
+ import { downloadMenubarHelperApp } from './download-menubar.js';
29
+ import { helperFloor } from '../helper-versions.js';
28
30
  const APP_BUNDLE_NAME = 'MenubarHelper.app';
29
31
  const INSTALL_DIR_NAME = 'agents-cli';
30
32
  const SERVICE_LABEL_BASE = 'com.phnx-labs.agents-menubar';
33
+ /**
34
+ * The bundled executable's basename (RUSH-3101) — what launchd execs directly
35
+ * inside `Contents/MacOS/`, bypassing LaunchServices name resolution. Before
36
+ * this it was `MenubarHelper`, so that raw Mach-O basename is exactly what
37
+ * macOS showed in System Settings > Privacy & Security > Accessibility and in
38
+ * the "would like to control this computer" prompt. Renaming this constant
39
+ * alone does NOT touch the bundle id, Team ID, or designated requirement
40
+ * (`SERVICE_LABEL_BASE`, `MENUBAR_HELPER_BUNDLE_ID` in download-menubar.ts) —
41
+ * those are what keep the existing Accessibility grant alive across upgrades.
42
+ * Every basename-matching check reads this constant rather than re-deriving
43
+ * the string; the Swift side has its own equal in
44
+ * `menubar/Sources/MenubarHelper/HelperIdentity.swift`.
45
+ */
46
+ export const MENUBAR_HELPER_EXECUTABLE_NAME = 'AGI Menu';
31
47
  /**
32
48
  * launchd Label for this process's helper — the production identifier for a
33
49
  * real invocation, namespaced under a redirected HOME (RUSH-2639). launchd
@@ -83,12 +99,12 @@ function readInstalledMenubarVersion() {
83
99
  }
84
100
  /** Executable inside the installed bundle. */
85
101
  function installedExecutablePath() {
86
- return path.join(installedAppPath(), 'Contents', 'MacOS', 'MenubarHelper');
102
+ return path.join(installedAppPath(), 'Contents', 'MacOS', MENUBAR_HELPER_EXECUTABLE_NAME);
87
103
  }
88
104
  /**
89
- * Absolute path to the installed MenubarHelper executable if it exists on disk,
90
- * else null. The desktop notifier (notify-desktop.ts) routes daemon
91
- * notifications through this one-shot (`MenubarHelper --notify ...`) so they
105
+ * Absolute path to the installed menu-bar helper executable if it exists on
106
+ * disk, else null. The desktop notifier (notify-desktop.ts) routes daemon
107
+ * notifications through this one-shot (`"AGI Menu" --notify ...`) so they
92
108
  * carry the agents-cli mark rather than the generic osascript icon. Null on
93
109
  * non-darwin or when the helper is not installed (menu bar disabled, a Linux
94
110
  * package, or a dev checkout without a built bundle).
@@ -119,7 +135,7 @@ export function menubarServiceInstalled() {
119
135
  * Locate the source `.app` shipped alongside the compiled JS.
120
136
  * 1. dist/lib/menubar/MenubarHelper.app — npm install layout (sibling of this file)
121
137
  * 2. <repo>/bin/MenubarHelper.app — raw working tree (tsx/dev)
122
- * 3. apps/cli/menubar/dist/MenubarHelper.app — fresh local build
138
+ * 3. cli/menubar/dist/MenubarHelper.app — fresh local build
123
139
  * 4. <on-disk install>/dist/lib/menubar/MenubarHelper.app — Bun single-file
124
140
  * binary: `import.meta.url` is a virtual `/$bunfs/` path, so the sibling
125
141
  * candidates above can't see the on-disk bundle; recover it via the
@@ -229,7 +245,12 @@ export function hasDeveloperIdSignature(appPath) {
229
245
  export function ensureMenubarAppInstalled(opts = {}) {
230
246
  if (!onDarwin())
231
247
  return null;
232
- const src = sourceAppPath();
248
+ // An explicit `sourceAppPath` (a pre-downloaded cache path from the explicit
249
+ // enable/setup path) overrides local discovery. This function itself does NO
250
+ // network — the download happens in the async callers before they hand a path
251
+ // here, so the sync startup self-heal that calls it with no override stays
252
+ // network-free and simply no-ops when `sourceAppPath()` finds nothing.
253
+ const src = opts.sourceAppPath ?? sourceAppPath();
233
254
  if (!src)
234
255
  return null;
235
256
  const dest = installedAppPath();
@@ -393,15 +414,18 @@ export function restartMenubarHelperAfterSwap(uid, ownProcesses, exec = execFile
393
414
  }
394
415
  }
395
416
  /**
396
- * Install + start the menu-bar helper as a launchd user service (idempotent).
397
- * Clears the sticky opt-out, installs the .app, writes the plist, and
398
- * bootstraps it into the GUI domain. Returns false on non-darwin or when no
399
- * helper bundle ships with this install.
417
+ * Sync install + start core: install the given (already-on-disk) source `.app`
418
+ * and start the launchd service. NO network — the source `.app` must already be
419
+ * local (a bundled/local copy for the sync startup self-heal, or a pre-downloaded
420
+ * cache path for the explicit async enable/setup path). Returns false on
421
+ * non-darwin, when no source resolves, or when the bundle fails the Gatekeeper
422
+ * check. Shared by the sync self-heal (`installMenubarLaunchAgentOnUpgrade`) and
423
+ * the async `enableMenubarService`.
400
424
  */
401
- export function enableMenubarService(opts = { clearOptOut: true }) {
425
+ function startMenubarServiceFromSource(opts = {}) {
402
426
  if (!onDarwin())
403
427
  return false;
404
- const exec = ensureMenubarAppInstalled({ forceReinstall: true });
428
+ const exec = ensureMenubarAppInstalled({ forceReinstall: true, sourceAppPath: opts.sourceAppPath });
405
429
  if (!exec)
406
430
  return false;
407
431
  // Never bootstrap a helper macOS will reject at launch: an invalid signature
@@ -420,6 +444,29 @@ export function enableMenubarService(opts = { clearOptOut: true }) {
420
444
  installAndStartService(exec);
421
445
  return true;
422
446
  }
447
+ /**
448
+ * Install + start the menu-bar helper as a launchd user service (idempotent).
449
+ * Clears the sticky opt-out, installs the .app, writes the plist, and
450
+ * bootstraps it into the GUI domain. Returns false on non-darwin or when no
451
+ * helper bundle can be resolved for this install.
452
+ *
453
+ * ASYNC and download-capable: this is the EXPLICIT user-initiated path
454
+ * (`agents menubar enable`). When no bundled/local `.app` ships (a fresh
455
+ * `npm i -g` machine whose tarball lacks the bundle), it fetches the signed +
456
+ * notarized release asset for the running CLI version — verified (sha256 +
457
+ * codesign + Team + designated-requirement pin + notarization) before install
458
+ * — and starts the service from that cached copy. The startup self-heal never
459
+ * routes here: it calls `startMenubarServiceFromSource` and stays sync +
460
+ * network-free, no-opping when no local source exists.
461
+ */
462
+ export async function enableMenubarService(opts = { clearOptOut: true }) {
463
+ if (!onDarwin())
464
+ return false;
465
+ let src = sourceAppPath();
466
+ if (!src)
467
+ src = await downloadMenubarHelperApp(helperFloor('menubar'));
468
+ return startMenubarServiceFromSource({ ...opts, sourceAppPath: src });
469
+ }
423
470
  /** Drop the sticky `agents menubar disable` sentinel. */
424
471
  function clearMenubarOptOut() {
425
472
  try {
@@ -714,7 +761,7 @@ export function installMenubarLaunchAgentOnUpgrade() {
714
761
  if (!sourceAppPath())
715
762
  return;
716
763
  if (!menubarServiceInstalled()) {
717
- enableMenubarService({ clearOptOut: false });
764
+ startMenubarServiceFromSource({ clearOptOut: false });
718
765
  return;
719
766
  }
720
767
  // Re-enable (recopy helper + rewrite plist) when the version drifted OR the
@@ -735,7 +782,7 @@ export function installMenubarLaunchAgentOnUpgrade() {
735
782
  // false without installing when the bundle fails the Gatekeeper check, and
736
783
  // stamping first would spend the shared cooldown on a no-op — locking every
737
784
  // non-owner out for another hour while nothing had been fixed.
738
- if (enableMenubarService({ clearOptOut: false })) {
785
+ if (startMenubarServiceFromSource({ clearOptOut: false })) {
739
786
  stampMenubarHeal();
740
787
  // One-time: the ad-hoc -> Developer ID transition leaves a dead TCC row
741
788
  // under the old identity (tccutil on zion reset it 11 times across
@@ -839,7 +886,7 @@ function endProcess(pid) {
839
886
  * 4. login item — write the plist (RunAtLoad + KeepAlive) and bootstrap it
840
887
  * 5. single — verify exactly one helper came back up
841
888
  */
842
- export function runMenubarSetup() {
889
+ export async function runMenubarSetup() {
843
890
  const steps = [];
844
891
  const step = (name, outcome, detail) => {
845
892
  steps.push({ name, outcome, detail });
@@ -849,9 +896,20 @@ export function runMenubarSetup() {
849
896
  return { steps, configured: false, status: getMenubarStatus() };
850
897
  }
851
898
  const before = getMenubarStatus();
852
- if (!sourceAppPath()) {
853
- step('bundle', 'failed', 'no AGI Menu bundle ships with this install');
854
- return { steps, configured: false, status: before };
899
+ // Explicit user-initiated path: when no bundled/local `.app` ships (a fresh
900
+ // `npm i -g` machine whose tarball lacks the bundle), fetch the signed +
901
+ // notarized release asset for this CLI version. Verified (sha256 + codesign +
902
+ // Team + designated-requirement pin + notarization) before install; the
903
+ // cached copy is the source for `ensureMenubarAppInstalled` below.
904
+ let src = sourceAppPath();
905
+ if (!src) {
906
+ try {
907
+ src = await downloadMenubarHelperApp(helperFloor('menubar'));
908
+ }
909
+ catch (e) {
910
+ step('bundle', 'failed', `no AGI Menu bundle ships with this install, and the release-asset download failed: ${e.message}`);
911
+ return { steps, configured: false, status: before };
912
+ }
855
913
  }
856
914
  // 3 before 1: end the running copies BEFORE swapping the bundle underneath
857
915
  // them, so no helper keeps a status item alive on a binary that no longer
@@ -868,7 +926,7 @@ export function runMenubarSetup() {
868
926
  else {
869
927
  step('duplicates', 'ok', 'no helper was running');
870
928
  }
871
- const exec = ensureMenubarAppInstalled({ forceReinstall: true });
929
+ const exec = ensureMenubarAppInstalled({ forceReinstall: true, sourceAppPath: src });
872
930
  if (!exec) {
873
931
  step('bundle', 'failed', 'could not install the helper bundle');
874
932
  return { steps, configured: false, status: getMenubarStatus() };
@@ -946,14 +1004,14 @@ function parsePsLines(psOutput) {
946
1004
  *
947
1005
  * Identity comes from `comm` (the resolved executable), never from a substring
948
1006
  * of the command line: matching the latter flags any shell that merely mentions
949
- * MenubarHelper. `command` is consulted only to drop `--notify` one-shots.
1007
+ * the helper's name. `command` is consulted only to drop `--notify` one-shots.
950
1008
  */
951
1009
  export function classifyMenubarProcesses(commOutput, commandOutput, installedExec) {
952
1010
  const commands = parsePsLines(commandOutput);
953
1011
  const own = [];
954
1012
  const foreign = [];
955
1013
  for (const [pid, executable] of parsePsLines(commOutput)) {
956
- if (path.basename(executable) !== 'MenubarHelper')
1014
+ if (path.basename(executable) !== MENUBAR_HELPER_EXECUTABLE_NAME)
957
1015
  continue;
958
1016
  // `--notify` is a one-shot that posts a notification and exits; it runs the
959
1017
  // installed binary but never claims the status item or the chords.
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * The one place the daemon (overdue routines, heal, routine start/finish/output)
5
5
  * emits a native desktop notification. On macOS it routes through the installed
6
- * `MenubarHelper.app` companion — a one-shot `MenubarHelper --notify` invocation —
6
+ * `MenubarHelper.app` companion — a one-shot `"AGI Menu" --notify` invocation —
7
7
  * so the notification is attributed to that bundle and carries the agents-cli
8
8
  * mark instead of the generic AppleScript icon. A banner carries two images: the
9
9
  * agents-cli app icon on the LEFT (the sender) and, when the event belongs to one
@@ -48,7 +48,7 @@ export interface DesktopNotification {
48
48
  */
49
49
  agent?: string;
50
50
  }
51
- /** Argv for the MenubarHelper one-shot notify mode. Exported for tests. */
51
+ /** Argv for the "AGI Menu" one-shot notify mode. Exported for tests. */
52
52
  export declare function buildMenubarNotifyArgs(n: DesktopNotification): string[];
53
53
  /** AppleScript for the osascript degradation path. Exported for tests. */
54
54
  export declare function buildOsascriptNotifyArgs(n: DesktopNotification): string[];
@@ -67,7 +67,7 @@ export declare function buildOsascriptNotifyArgs(n: DesktopNotification): string
67
67
  */
68
68
  export declare function spawnDetachedQuiet(command: string, args: string[], timeoutMs?: number): ChildProcess;
69
69
  /**
70
- * Fire a native desktop notification, branded via the MenubarHelper companion on
70
+ * Fire a native desktop notification, branded via the "AGI Menu" companion on
71
71
  * macOS. Best-effort — any failure is swallowed so a notification hiccup never
72
72
  * blocks or crashes the daemon.
73
73
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * The one place the daemon (overdue routines, heal, routine start/finish/output)
5
5
  * emits a native desktop notification. On macOS it routes through the installed
6
- * `MenubarHelper.app` companion — a one-shot `MenubarHelper --notify` invocation —
6
+ * `MenubarHelper.app` companion — a one-shot `"AGI Menu" --notify` invocation —
7
7
  * so the notification is attributed to that bundle and carries the agents-cli
8
8
  * mark instead of the generic AppleScript icon. A banner carries two images: the
9
9
  * agents-cli app icon on the LEFT (the sender) and, when the event belongs to one
@@ -32,7 +32,7 @@ import { resolveInstalledMenubarExecutable } from './install-menubar.js';
32
32
  * only if the child never self-exits.
33
33
  */
34
34
  const NOTIFY_TIMEOUT_MS = 4000;
35
- /** Argv for the MenubarHelper one-shot notify mode. Exported for tests. */
35
+ /** Argv for the "AGI Menu" one-shot notify mode. Exported for tests. */
36
36
  export function buildMenubarNotifyArgs(n) {
37
37
  const args = ['--notify', '--title', n.title, '--body', n.body];
38
38
  if (n.subtitle)
@@ -88,7 +88,7 @@ export function spawnDetachedQuiet(command, args, timeoutMs = NOTIFY_TIMEOUT_MS)
88
88
  return child;
89
89
  }
90
90
  /**
91
- * Fire a native desktop notification, branded via the MenubarHelper companion on
91
+ * Fire a native desktop notification, branded via the "AGI Menu" companion on
92
92
  * macOS. Best-effort — any failure is swallowed so a notification hiccup never
93
93
  * blocks or crashes the daemon.
94
94
  */
@@ -98,9 +98,9 @@ export function notifyDesktop(n) {
98
98
  if (platform === 'darwin') {
99
99
  const exec = resolveInstalledMenubarExecutable();
100
100
  if (exec) {
101
- // Branded path: the notification is attributed to MenubarHelper.app, so it
102
- // shows the agents-cli mark and its click action is handled by the running
103
- // helper's UNUserNotificationCenter delegate.
101
+ // Branded path: the notification is attributed to MenubarHelper.app
102
+ // ("AGI Menu" on disk), so it shows the agents-cli mark and its click
103
+ // action is handled by the running helper's UNUserNotificationCenter delegate.
104
104
  spawnDetachedQuiet(exec, buildMenubarNotifyArgs(n));
105
105
  return;
106
106
  }
@@ -7,7 +7,7 @@
7
7
  * actually ships — so `--model cheap|default|best|ultra` works on `agents run`
8
8
  * and `agents teams add` alike, funnelling through `resolveModel()`.
9
9
  *
10
- * Ranking signal, in priority (see apps/cli/docs — model ranking mechanisms):
10
+ * Ranking signal, in priority (see cli/docs — model ranking mechanisms):
11
11
  * 1. Provider-declared lineup — the catalog's own family names / descriptions
12
12
  * (opus/sonnet/haiku/fable; Codex "frontier / balanced / fast"). Most
13
13
  * drift-proof: the provider tells us its own ranking.
@@ -58,7 +58,7 @@ export declare function probeProjectWorkspaces(paths: string[]): RepoWorkspaceSt
58
58
  */
59
59
  export declare function workspaceTargetsForDef(def: ProjectDef): string[];
60
60
  /**
61
- * Parse a peer's `projects probe --json` stdout, tagging each row with the
61
+ * Parse a peer's `projects probe` stdout, tagging each row with the
62
62
  * machine that answered. Defensive against version skew / partial output, the
63
63
  * same boundary contract as `parseRemoteActive`: non-JSON or a non-array
64
64
  * yields `[]`, and rows without a `path`/`present` core are dropped.
@@ -96,7 +96,7 @@ export function workspaceTargetsForDef(def) {
96
96
  return projectProbeTargets(def);
97
97
  }
98
98
  /**
99
- * Parse a peer's `projects probe --json` stdout, tagging each row with the
99
+ * Parse a peer's `projects probe` stdout, tagging each row with the
100
100
  * machine that answered. Defensive against version skew / partial output, the
101
101
  * same boundary contract as `parseRemoteActive`: non-JSON or a non-array
102
102
  * yields `[]`, and rows without a `path`/`present` core are dropped.
@@ -93,7 +93,7 @@ export declare function decodePullTargets(raw: string): ProjectRepoTarget[];
93
93
  export declare function pullProjectTargets(targets: ProjectRepoTarget[], host?: string): Promise<ProjectPullResult[]>;
94
94
  export declare function buildPullEnvelope(results: ProjectPullResult[], targets: ProjectRepoTarget[]): ProjectPullEnvelope;
95
95
  /**
96
- * Parse a peer's `projects pull-local --json` stdout. Fails CLOSED **and
96
+ * Parse a peer's `projects pull-local` stdout. Fails CLOSED **and
97
97
  * LOUD**: any structural anomaly (wrong schema version, wrong kind, machine
98
98
  * mismatch, fingerprint mismatch, non-array results, malformed rows) returns
99
99
  * `{ items: [], valid: false }` rather than silently accepting a partial or
@@ -66,7 +66,7 @@ export function encodePullTargets(targets) {
66
66
  * test can exercise the real caller-side arguments rather than a retyped copy.
67
67
  */
68
68
  export function pullLocalArgs(targets) {
69
- return ['projects', 'pull-local', '--json', '--targets', encodePullTargets(targets)];
69
+ return ['projects', 'pull-local', '--targets', encodePullTargets(targets)];
70
70
  }
71
71
  /**
72
72
  * Decode the `--targets` argument back into targets on the peer. THROWS on any
@@ -226,7 +226,7 @@ export function buildPullEnvelope(results, targets) {
226
226
  // Envelope parser (fail-closed — every validation failure returns [])
227
227
  // ---------------------------------------------------------------------------
228
228
  /**
229
- * Parse a peer's `projects pull-local --json` stdout. Fails CLOSED **and
229
+ * Parse a peer's `projects pull-local` stdout. Fails CLOSED **and
230
230
  * LOUD**: any structural anomaly (wrong schema version, wrong kind, machine
231
231
  * mismatch, fingerprint mismatch, non-array results, malformed rows) returns
232
232
  * `{ items: [], valid: false }` rather than silently accepting a partial or
@@ -204,7 +204,7 @@ export declare function projectDirsAbs(def: ProjectDef, opts: {
204
204
  * with `expandLocalHome` and resolved, so this matches sessions whose cwd shares
205
205
  * this machine's home layout. A session recorded on a different-home machine
206
206
  * (`/Users/x/…` vs `/home/x/…`) will not match until the fleet-wide,
207
- * home-relative variant lands (see the deferred item in docs/projects.md).
207
+ * home-relative variant lands (see docs/concepts.md).
208
208
  */
209
209
  export declare function projectNameForCwd(cwd: string | undefined, defs: ProjectDef[]): string | undefined;
210
210
  /**
@@ -429,7 +429,7 @@ function isUnder(child, parent) {
429
429
  * with `expandLocalHome` and resolved, so this matches sessions whose cwd shares
430
430
  * this machine's home layout. A session recorded on a different-home machine
431
431
  * (`/Users/x/…` vs `/home/x/…`) will not match until the fleet-wide,
432
- * home-relative variant lands (see the deferred item in docs/projects.md).
432
+ * home-relative variant lands (see docs/concepts.md).
433
433
  */
434
434
  export function projectNameForCwd(cwd, defs) {
435
435
  if (!cwd)
@@ -209,11 +209,11 @@ export function assertSandboxForwardsHostGhAuth(spawnEnv) {
209
209
  }
210
210
  /** Link this host's Cursor login and CLI config into the disposable overlay. */
211
211
  export function generateCursorConfig(overlayHome) {
212
- const realConfigHome = process.env.XDG_CONFIG_HOME || path.join(resolveRealHome(), '.config');
213
- const realAuth = path.join(realConfigHome, 'cursor', 'auth.json');
212
+ const realCursorDir = path.join(process.env.AGENTS_REAL_HOME || resolveRealHome(), '.cursor');
213
+ const realAuth = path.join(realCursorDir, 'auth.json');
214
214
  if (!fs.existsSync(realAuth))
215
215
  return;
216
- const overlayCursorDir = path.join(overlayHome, '.config', 'cursor');
216
+ const overlayCursorDir = path.join(overlayHome, '.cursor');
217
217
  fs.mkdirSync(overlayCursorDir, { recursive: true });
218
218
  const overlayAuth = path.join(overlayCursorDir, 'auth.json');
219
219
  if (process.platform === 'win32') {
@@ -227,10 +227,9 @@ export function generateCursorConfig(overlayHome) {
227
227
  else {
228
228
  fs.symlinkSync(realAuth, overlayAuth);
229
229
  }
230
- // Setting XDG_CONFIG_HOME makes Cursor look for cli-config.json beside auth.json.
231
- // This file carries account identity (authId, displayName, email, userId) as
232
- // well as preferences, so it must remain linked rather than copied.
233
- const realCliConfig = path.join(resolveRealHome(), '.cursor', 'cli-config.json');
230
+ // cli-config.json carries account identity alongside the file-store token, so
231
+ // it must remain linked rather than copied.
232
+ const realCliConfig = path.join(realCursorDir, 'cli-config.json');
234
233
  if (fs.existsSync(realCliConfig)) {
235
234
  const overlayCliConfig = path.join(overlayCursorDir, 'cli-config.json');
236
235
  try {
@@ -0,0 +1,47 @@
1
+ /**
2
+ * On-demand download + verification of the macOS keychain broker helper
3
+ * ("Agents CLI.app").
4
+ *
5
+ * Mirrors the ComputerHelper / MenubarHelper download model
6
+ * (`../helper-download.ts`): the helper ships as a signed + notarized `.app`
7
+ * zipped as a GitHub release asset on the helper's own `keychain/v<x.y.z>` tag,
8
+ * NOT the CLI's tag (see `helper-versions.ts`). A fresh `npm i -g`
9
+ * machine whose tarball lacks a bundled copy fetches the asset for the running
10
+ * CLI version, verifies its sha256 + code signature before install.
11
+ *
12
+ * Unlike the menu-bar helper, the keychain helper pins NO designated
13
+ * requirement (no `expectedBundleId`). The menu-bar `expectedBundleId` exists
14
+ * because macOS keys the Accessibility (TCC) grant to the bundle's designated
15
+ * requirement, so a substituted bundle whose DR does not pin (id, team) would
16
+ * silently revoke that upgrade-stable grant. The keychain helper has no such
17
+ * DR-keyed grant to protect: its items are gated by the access-group
18
+ * entitlement (`keychain-helper.swift` → `kSecAttrAccessGroup`, the
19
+ * `keychain-access-groups` entitlement) plus a biometry `SecAccessControl`
20
+ * (user presence) — NOT a `SecTrustedApplication` ACL keyed to a bundle-id/DR.
21
+ * The release-time gate `scripts/verify-keychain-helper.sh` correspondingly
22
+ * pins the executable's sha256, not a designated requirement. So Team +
23
+ * notarization is the verification boundary here, exactly like ComputerHelper.
24
+ */
25
+ import { type HelperSpec } from '../helper-download.js';
26
+ /** The zipped `.app` release asset name (the bundle name has a space). */
27
+ export declare const KEYCHAIN_HELPER_ASSET = "Agents_CLI.app.zip";
28
+ /** The bundle directory name once extracted. */
29
+ export declare const KEYCHAIN_HELPER_APP_NAME = "Agents CLI.app";
30
+ /** Keychain-helper identity + verification policy — Team + notarization only,
31
+ * no DR pin (see docblock). */
32
+ export declare const KEYCHAIN_HELPER_SPEC: HelperSpec;
33
+ /** Release-asset URLs for the keychain helper zip + its checksum at `v<version>`. */
34
+ export declare function keychainHelperAssetUrls(version: string): {
35
+ zip: string;
36
+ sha256: string;
37
+ };
38
+ /** Cache dir for the downloaded keychain helper, one subdir per release tag. */
39
+ export declare function keychainHelperCacheDir(version: string): string;
40
+ /** Verify a keychain helper `.app`: codesign + Team + notarization (no DR pin). */
41
+ export declare function verifyKeychainHelper(appPath: string): void;
42
+ /**
43
+ * Download the keychain helper release asset for `version`, verify sha256 +
44
+ * signature, and return the path to the extracted `Agents CLI.app` in the
45
+ * cache. A missing asset is a hard error naming the exact tag.
46
+ */
47
+ export declare function downloadKeychainHelperApp(version: string): Promise<string>;