@phnx-labs/agents-cli 1.20.77 → 1.20.82

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 (212) hide show
  1. package/CHANGELOG.md +589 -0
  2. package/README.md +27 -25
  3. package/dist/bin/agents +0 -0
  4. package/dist/commands/activity.d.ts +9 -0
  5. package/dist/commands/activity.js +153 -24
  6. package/dist/commands/apply.js +11 -4
  7. package/dist/commands/cli.js +1 -1
  8. package/dist/commands/commands.d.ts +1 -1
  9. package/dist/commands/commands.js +7 -6
  10. package/dist/commands/defaults.js +3 -11
  11. package/dist/commands/doctor.d.ts +74 -0
  12. package/dist/commands/doctor.js +718 -40
  13. package/dist/commands/events.js +1 -1
  14. package/dist/commands/exec.js +53 -8
  15. package/dist/commands/feed.d.ts +4 -0
  16. package/dist/commands/feed.js +87 -11
  17. package/dist/commands/harness.js +2 -2
  18. package/dist/commands/hooks.js +1 -1
  19. package/dist/commands/import.js +8 -4
  20. package/dist/commands/logs.js +6 -0
  21. package/dist/commands/models.js +1 -1
  22. package/dist/commands/packages.js +6 -6
  23. package/dist/commands/permissions.js +1 -1
  24. package/dist/commands/profiles.js +1 -1
  25. package/dist/commands/pull.d.ts +1 -1
  26. package/dist/commands/pull.js +4 -4
  27. package/dist/commands/repo.d.ts +78 -0
  28. package/dist/commands/repo.js +195 -11
  29. package/dist/commands/routines.js +16 -4
  30. package/dist/commands/rules.js +13 -12
  31. package/dist/commands/secrets.d.ts +3 -1
  32. package/dist/commands/secrets.js +108 -34
  33. package/dist/commands/sessions-browser.d.ts +45 -3
  34. package/dist/commands/sessions-browser.js +118 -12
  35. package/dist/commands/sessions-export.d.ts +3 -0
  36. package/dist/commands/sessions-export.js +13 -10
  37. package/dist/commands/sessions-inject.d.ts +7 -4
  38. package/dist/commands/sessions-inject.js +18 -18
  39. package/dist/commands/sessions-picker.d.ts +15 -1
  40. package/dist/commands/sessions-picker.js +90 -7
  41. package/dist/commands/sessions-resume.d.ts +16 -0
  42. package/dist/commands/sessions-resume.js +14 -13
  43. package/dist/commands/sessions.d.ts +126 -1
  44. package/dist/commands/sessions.js +365 -42
  45. package/dist/commands/set.d.ts +15 -0
  46. package/dist/commands/set.js +79 -0
  47. package/dist/commands/setup-fleet.d.ts +21 -0
  48. package/dist/commands/setup-fleet.js +201 -0
  49. package/dist/commands/setup-secrets.d.ts +20 -0
  50. package/dist/commands/setup-secrets.js +223 -0
  51. package/dist/commands/setup.js +17 -3
  52. package/dist/commands/skills.js +1 -1
  53. package/dist/commands/ssh.js +9 -1
  54. package/dist/commands/sync.js +7 -2
  55. package/dist/commands/teams-picker.js +0 -1
  56. package/dist/commands/teams.d.ts +33 -1
  57. package/dist/commands/teams.js +208 -44
  58. package/dist/commands/versions.js +10 -5
  59. package/dist/commands/view.d.ts +1 -0
  60. package/dist/commands/view.js +11 -0
  61. package/dist/index.js +8 -13
  62. package/dist/lib/acp/harnesses.js +0 -7
  63. package/dist/lib/activity.d.ts +156 -0
  64. package/dist/lib/activity.js +282 -0
  65. package/dist/lib/agents.d.ts +9 -23
  66. package/dist/lib/agents.js +72 -100
  67. package/dist/lib/auto-pull.d.ts +16 -8
  68. package/dist/lib/auto-pull.js +23 -28
  69. package/dist/lib/browser/service.js +3 -0
  70. package/dist/lib/browser/types.d.ts +7 -0
  71. package/dist/lib/capabilities.js +6 -2
  72. package/dist/lib/crabbox/lease.js +2 -2
  73. package/dist/lib/crabbox/setup-copy.d.ts +4 -4
  74. package/dist/lib/crabbox/setup-copy.js +4 -4
  75. package/dist/lib/daemon.d.ts +26 -40
  76. package/dist/lib/daemon.js +63 -123
  77. package/dist/lib/devices/fleet-divergence.d.ts +101 -0
  78. package/dist/lib/devices/fleet-divergence.js +188 -0
  79. package/dist/lib/devices/fleet-inventory.d.ts +19 -0
  80. package/dist/lib/devices/fleet-inventory.js +57 -0
  81. package/dist/lib/devices/fleet.d.ts +1 -1
  82. package/dist/lib/devices/fleet.js +1 -1
  83. package/dist/lib/devices/health-report.d.ts +10 -2
  84. package/dist/lib/devices/health-report.js +32 -1
  85. package/dist/lib/doctor-diff.d.ts +20 -0
  86. package/dist/lib/doctor-diff.js +6 -1
  87. package/dist/lib/drift.d.ts +31 -11
  88. package/dist/lib/drift.js +58 -7
  89. package/dist/lib/events.d.ts +8 -1
  90. package/dist/lib/events.js +10 -1
  91. package/dist/lib/exec.js +35 -8
  92. package/dist/lib/feed-post.d.ts +28 -1
  93. package/dist/lib/feed-post.js +110 -2
  94. package/dist/lib/fleet/apply.js +8 -1
  95. package/dist/lib/fleet/auth-sync.d.ts +18 -1
  96. package/dist/lib/fleet/auth-sync.js +25 -11
  97. package/dist/lib/fleet/remote-login.js +5 -0
  98. package/dist/lib/git.d.ts +27 -14
  99. package/dist/lib/git.js +138 -43
  100. package/dist/lib/hooks.d.ts +42 -0
  101. package/dist/lib/hooks.js +137 -93
  102. package/dist/lib/hosts/dispatch.d.ts +28 -1
  103. package/dist/lib/hosts/dispatch.js +33 -5
  104. package/dist/lib/hosts/option.js +2 -2
  105. package/dist/lib/hosts/passthrough.d.ts +22 -1
  106. package/dist/lib/hosts/passthrough.js +238 -13
  107. package/dist/lib/hosts/remote-cmd.js +2 -0
  108. package/dist/lib/hosts/run-target.d.ts +2 -0
  109. package/dist/lib/hosts/run-target.js +1 -0
  110. package/dist/lib/hq/floor.d.ts +1 -1
  111. package/dist/lib/hq/floor.js +6 -1
  112. package/dist/lib/mcp.js +3 -71
  113. package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +2 -0
  114. package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
  115. package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
  116. package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +15 -2
  117. package/dist/lib/menubar/notify-desktop.d.ts +15 -0
  118. package/dist/lib/menubar/notify-desktop.js +41 -5
  119. package/dist/lib/merged-resources.d.ts +11 -0
  120. package/dist/{commands/resources.js → lib/merged-resources.js} +11 -19
  121. package/dist/lib/permissions.d.ts +0 -32
  122. package/dist/lib/permissions.js +4 -157
  123. package/dist/lib/picker.js +1 -1
  124. package/dist/lib/platform/process.d.ts +16 -5
  125. package/dist/lib/platform/process.js +54 -0
  126. package/dist/lib/plugins.d.ts +0 -8
  127. package/dist/lib/plugins.js +4 -110
  128. package/dist/lib/project-resources.js +4 -1
  129. package/dist/lib/refresh.d.ts +5 -3
  130. package/dist/lib/refresh.js +7 -5
  131. package/dist/lib/resources/commands.js +4 -1
  132. package/dist/lib/resources/mcp.js +0 -4
  133. package/dist/lib/resources/permissions.d.ts +1 -1
  134. package/dist/lib/resources/permissions.js +1 -5
  135. package/dist/lib/resources/rules.js +4 -1
  136. package/dist/lib/resources/skills.js +4 -1
  137. package/dist/lib/resources/subagents.js +4 -0
  138. package/dist/lib/resources/types.d.ts +1 -1
  139. package/dist/lib/routines.d.ts +20 -0
  140. package/dist/lib/routines.js +6 -0
  141. package/dist/lib/run-defaults.d.ts +1 -0
  142. package/dist/lib/run-defaults.js +9 -0
  143. package/dist/lib/runner.d.ts +0 -12
  144. package/dist/lib/runner.js +71 -29
  145. package/dist/lib/sandbox.js +0 -16
  146. package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
  147. package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +2 -0
  148. package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
  149. package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
  150. package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +13 -1
  151. package/dist/lib/secrets/agent.d.ts +18 -0
  152. package/dist/lib/secrets/agent.js +131 -17
  153. package/dist/lib/secrets/audit.d.ts +46 -0
  154. package/dist/lib/secrets/audit.js +56 -0
  155. package/dist/lib/secrets/bundles.d.ts +12 -9
  156. package/dist/lib/secrets/bundles.js +47 -31
  157. package/dist/lib/secrets/index.d.ts +2 -1
  158. package/dist/lib/secrets/index.js +8 -2
  159. package/dist/lib/secrets/remote.d.ts +75 -2
  160. package/dist/lib/secrets/remote.js +139 -5
  161. package/dist/lib/secrets/scope.d.ts +26 -0
  162. package/dist/lib/secrets/scope.js +29 -0
  163. package/dist/lib/secrets/session-store.d.ts +10 -0
  164. package/dist/lib/secrets/session-store.js +64 -11
  165. package/dist/lib/secrets/sync.js +3 -3
  166. package/dist/lib/session/active.d.ts +117 -26
  167. package/dist/lib/session/active.js +199 -53
  168. package/dist/lib/session/actor-sidecar.d.ts +23 -0
  169. package/dist/lib/session/actor-sidecar.js +101 -0
  170. package/dist/lib/session/db.d.ts +41 -1
  171. package/dist/lib/session/db.js +173 -8
  172. package/dist/lib/session/digest.js +126 -21
  173. package/dist/lib/session/discover.d.ts +19 -2
  174. package/dist/lib/session/discover.js +32 -11
  175. package/dist/lib/session/hook-sessions.d.ts +9 -0
  176. package/dist/lib/session/hook-sessions.js +57 -8
  177. package/dist/lib/session/origin-machine.d.ts +18 -0
  178. package/dist/lib/session/origin-machine.js +34 -0
  179. package/dist/lib/session/pid-registry.d.ts +13 -0
  180. package/dist/lib/session/render.d.ts +2 -0
  181. package/dist/lib/session/render.js +1 -1
  182. package/dist/lib/session/state.d.ts +1 -0
  183. package/dist/lib/session/state.js +1 -1
  184. package/dist/lib/session/sync/config.js +2 -2
  185. package/dist/lib/session/types.d.ts +16 -0
  186. package/dist/lib/smart-launch.d.ts +86 -0
  187. package/dist/lib/smart-launch.js +172 -0
  188. package/dist/lib/staleness/detectors/commands.js +2 -2
  189. package/dist/lib/staleness/detectors/permissions.js +1 -45
  190. package/dist/lib/staleness/writers/commands.js +4 -5
  191. package/dist/lib/staleness/writers/hooks.js +1 -1
  192. package/dist/lib/startup/command-registry.d.ts +1 -2
  193. package/dist/lib/startup/command-registry.js +2 -4
  194. package/dist/lib/subagents-registry.js +5 -12
  195. package/dist/lib/subagents.d.ts +0 -10
  196. package/dist/lib/subagents.js +0 -12
  197. package/dist/lib/teams/agents.d.ts +0 -2
  198. package/dist/lib/teams/agents.js +10 -27
  199. package/dist/lib/teams/index.d.ts +1 -1
  200. package/dist/lib/teams/index.js +1 -1
  201. package/dist/lib/types.d.ts +17 -9
  202. package/dist/lib/usage.d.ts +28 -5
  203. package/dist/lib/usage.js +271 -8
  204. package/dist/lib/versions.js +7 -1
  205. package/dist/lib/watchdog/watchdog.d.ts +1 -1
  206. package/dist/lib/watchdog/watchdog.js +25 -13
  207. package/package.json +1 -2
  208. package/dist/commands/check.d.ts +0 -15
  209. package/dist/commands/check.js +0 -180
  210. package/dist/commands/resources.d.ts +0 -5
  211. package/dist/lib/secrets/account-token.d.ts +0 -20
  212. package/dist/lib/secrets/account-token.js +0 -64
@@ -22,7 +22,6 @@ import { shouldInstallCommandAsSkill, installCommandSkillToVersion } from './com
22
22
  import { copyPluginToMarketplace, syncMarketplaceManifest, registerMarketplace, unregisterMarketplace, addPluginToSettings, removePluginFromSettings, removePluginFromMarketplace, registerDroidInstalledPlugin, unregisterDroidInstalledPlugin, isDroidPluginInstalled, registerCopilotInstalledPlugin, unregisterCopilotInstalledPlugin, marketplaceIsEmpty, removeEmptyMarketplaceDir, isInstalledInMarketplace, marketplaceRoot, discoverMarketplaces, marketplaceNameFor, MARKETPLACE_NAME, PROJECT_MARKETPLACE_NAME, SYSTEM_MARKETPLACE_NAME, } from './plugin-marketplace.js';
23
23
  const PLUGIN_MANIFEST_DIR = '.claude-plugin';
24
24
  const PLUGIN_MANIFEST_FILE = 'plugin.json';
25
- const GEMINI_EXTENSION_MANIFEST_FILE = 'gemini-extension.json';
26
25
  const HERMES_PLUGIN_MANIFEST_FILE = 'plugin.yaml';
27
26
  const USER_CONFIG_FILE = '.user-config.json';
28
27
  const SOURCE_FILE = '.source';
@@ -518,13 +517,16 @@ export function syncPluginToVersion(plugin, agent, versionHome, options = {}) {
518
517
  if (!pluginSupportsAgent(plugin, agent)) {
519
518
  return result;
520
519
  }
520
+ if (!isCapable(agent, 'plugins')) {
521
+ return result;
522
+ }
521
523
  // OpenCode uses TS/JS modules under ~/.config/opencode/plugins/, not the
522
524
  // Claude marketplace layout. Install those modules and return early.
523
525
  if (agent === 'opencode') {
524
526
  // Trust gate (RUSH-1756): OpenCode plugins are raw executable TS/JS modules,
525
527
  // so they must clear the same consent check as every other exec surface
526
528
  // before install — this branch used to return early, bypassing the gate the
527
- // Gemini/Hermes/marketplace branches all apply.
529
+ // Hermes/marketplace branches all apply.
528
530
  const enablePlugin = options.allowExecSurfaces === true || !hasPluginExecSurfaces(inspectPluginCapabilities(plugin.root));
529
531
  if (!enablePlugin) {
530
532
  return result;
@@ -535,27 +537,6 @@ export function syncPluginToVersion(plugin, agent, versionHome, options = {}) {
535
537
  result.skills.push(plugin.name);
536
538
  return result;
537
539
  }
538
- // Gemini CLI loads extensions from $HOME/.gemini/extensions/<name>/.
539
- // Copy the plugin bundle as an extension and synthesize gemini-extension.json.
540
- if (agent === 'gemini') {
541
- const enablePlugin = options.allowExecSurfaces === true || !hasPluginExecSurfaces(inspectPluginCapabilities(plugin.root));
542
- if (!enablePlugin) {
543
- return result;
544
- }
545
- const ok = installGeminiPlugin(plugin, versionHome);
546
- result.success = ok;
547
- if (ok) {
548
- result.skills = plugin.skills.map(s => `${plugin.name}:${s}`);
549
- result.commands = plugin.commands.map(c => `${plugin.name}:${c}`);
550
- result.agentDefs = plugin.agentDefs.map(a => `${plugin.name}:${a}`);
551
- result.bin = plugin.bin;
552
- result.hooks = plugin.hooks;
553
- result.mcp = plugin.hasMcp;
554
- result.settings = plugin.hasSettings;
555
- result.permissions = pluginHasPermissions(plugin);
556
- }
557
- return result;
558
- }
559
540
  // Goose loads Open Plugins from $HOME/.agents/plugins/<name>/ (same layout as
560
541
  // agents-cli's source tree). Under the shim HOME is the version home.
561
542
  if (agent === 'goose') {
@@ -965,53 +946,6 @@ export function removeOpenCodePlugin(pluginName, versionHome) {
965
946
  }
966
947
  return removed;
967
948
  }
968
- // ─── Gemini extensions ───────────────────────────────────────────────────────
969
- /**
970
- * Gemini CLI extensions live under `$HOME/.gemini/extensions/<name>/` and
971
- * require a `gemini-extension.json` manifest at the extension root.
972
- */
973
- export function geminiExtensionsDir(versionHome) {
974
- return path.join(versionHome, '.gemini', 'extensions');
975
- }
976
- function readPluginMcpConfigForGemini(pluginRoot) {
977
- const mcpPath = path.join(pluginRoot, '.mcp.json');
978
- if (!fs.existsSync(mcpPath))
979
- return undefined;
980
- try {
981
- const parsed = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));
982
- if (!parsed.mcpServers || typeof parsed.mcpServers !== 'object')
983
- return undefined;
984
- return rewriteGeminiExtensionVars(parsed.mcpServers);
985
- }
986
- catch {
987
- return undefined;
988
- }
989
- }
990
- function rewriteGeminiExtensionVars(value) {
991
- if (typeof value === 'string') {
992
- return value
993
- .replace(/\$\{CLAUDE_PLUGIN_ROOT\}/g, '${extensionPath}')
994
- .replace(/\$\{CLAUDE_PLUGIN_DATA\}/g, '${extensionPath}/.data');
995
- }
996
- if (Array.isArray(value))
997
- return value.map(rewriteGeminiExtensionVars);
998
- if (value && typeof value === 'object') {
999
- return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, rewriteGeminiExtensionVars(item)]));
1000
- }
1001
- return value;
1002
- }
1003
- function writeGeminiExtensionManifest(plugin, destRoot) {
1004
- const manifest = {
1005
- name: plugin.manifest.name,
1006
- version: plugin.manifest.version,
1007
- description: plugin.manifest.description,
1008
- };
1009
- const mcpServers = readPluginMcpConfigForGemini(destRoot);
1010
- if (mcpServers && Object.keys(mcpServers).length > 0) {
1011
- manifest.mcpServers = mcpServers;
1012
- }
1013
- fs.writeFileSync(path.join(destRoot, GEMINI_EXTENSION_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`, 'utf-8');
1014
- }
1015
949
  /**
1016
950
  * Security (RUSH-1755): `fs.cpSync(..., { recursive: true })` copies symlinks
1017
951
  * verbatim (dereference defaults to false), so a malicious plugin can ship a
@@ -1078,36 +1012,6 @@ function stripEscapingSymlinks(destRoot, sourceRoot) {
1078
1012
  walk(destRoot);
1079
1013
  return removed;
1080
1014
  }
1081
- export function installGeminiPlugin(plugin, versionHome) {
1082
- const destRoot = path.join(geminiExtensionsDir(versionHome), plugin.name);
1083
- try {
1084
- if (fs.existsSync(destRoot)) {
1085
- fs.rmSync(destRoot, { recursive: true, force: true });
1086
- }
1087
- fs.cpSync(plugin.root, destRoot, { recursive: true });
1088
- stripEscapingSymlinks(destRoot, plugin.root);
1089
- const userConfig = loadUserConfig(plugin.name);
1090
- if (Object.keys(userConfig).length > 0) {
1091
- expandUserConfigInDir(destRoot, userConfig);
1092
- }
1093
- writeGeminiExtensionManifest(plugin, destRoot);
1094
- fs.writeFileSync(path.join(destRoot, '.agents-cli-managed'), `plugin=${plugin.name}\n`, 'utf-8');
1095
- return true;
1096
- }
1097
- catch {
1098
- return false;
1099
- }
1100
- }
1101
- export function isGeminiPluginInstalled(pluginName, versionHome) {
1102
- return fs.existsSync(path.join(geminiExtensionsDir(versionHome), pluginName, GEMINI_EXTENSION_MANIFEST_FILE));
1103
- }
1104
- export function removeGeminiPlugin(pluginName, versionHome) {
1105
- const destRoot = path.join(geminiExtensionsDir(versionHome), pluginName);
1106
- if (!fs.existsSync(destRoot))
1107
- return false;
1108
- fs.rmSync(destRoot, { recursive: true, force: true });
1109
- return true;
1110
- }
1111
1015
  // ─── Goose plugins (Open Plugins under .agents/plugins/) ─────────────────────
1112
1016
  /**
1113
1017
  * Goose auto-discovers Open Plugins at `$HOME/.agents/plugins/<name>/`.
@@ -1254,9 +1158,6 @@ export function isPluginSynced(plugin, agent, versionHome) {
1254
1158
  if (agent === 'opencode') {
1255
1159
  return isOpenCodePluginInstalled(plugin.name, versionHome);
1256
1160
  }
1257
- if (agent === 'gemini') {
1258
- return isGeminiPluginInstalled(plugin.name, versionHome);
1259
- }
1260
1161
  if (agent === 'goose') {
1261
1162
  return isGoosePluginInstalled(plugin.name, versionHome);
1262
1163
  }
@@ -1297,13 +1198,6 @@ export function removePluginFromVersion(pluginName, pluginRoot, agent, versionHo
1297
1198
  }
1298
1199
  return result;
1299
1200
  }
1300
- // Gemini: remove extension directory from ~/.gemini/extensions/.
1301
- if (agent === 'gemini') {
1302
- if (removeGeminiPlugin(pluginName, versionHome)) {
1303
- result.skills.push(pluginName);
1304
- }
1305
- return result;
1306
- }
1307
1201
  // Goose: remove Open Plugin directory from versionHome/.agents/plugins/.
1308
1202
  if (agent === 'goose') {
1309
1203
  if (removeGoosePlugin(pluginName, versionHome)) {
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
- import { AGENTS, agentConfigDirName } from './agents.js';
3
+ import { AGENTS, agentConfigDirName, isAgentHardDeprecated } from './agents.js';
4
4
  import { supports } from './capabilities.js';
5
5
  import { buildCommandSkillContent, commandSkillName, readSkillSourceCommandMarker, shouldInstallCommandAsSkill } from './command-skills.js';
6
6
  import { commandAppliesTo, parseCommandMetadata } from './commands.js';
@@ -16,6 +16,9 @@ export function projectAgentRoot(projectRoot, agent) {
16
16
  return path.join(projectRoot, agentConfigDirName(agent));
17
17
  }
18
18
  export function syncProjectResourcesToAgent(agent, version, projectAgentsDir) {
19
+ if (isAgentHardDeprecated(agent)) {
20
+ return { synced: [], skipped: [] };
21
+ }
19
22
  const projectRoot = path.dirname(projectAgentsDir);
20
23
  const agentRoot = projectAgentRoot(projectRoot, agent);
21
24
  const manifest = loadProjectManifest(agentRoot);
@@ -3,9 +3,11 @@
3
3
  * sync resources into installed version homes, register hooks, add shims to
4
4
  * PATH, prompt for missing default versions, install declared host-CLIs.
5
5
  *
6
- * Used by `agents repo refresh` (user-facing) and any other caller that needs
7
- * to re-derive local state from declared configuration. Does NOT do any git
8
- * operations — that lives in `agents repo pull`.
6
+ * The reconcile stage behind `agents sync` (the umbrella `--local` path calls
7
+ * this; see sync-umbrella.ts) and any other caller that needs to re-derive local
8
+ * state from declared configuration. Does NOT do any git operations — that lives
9
+ * in `agents repo pull`. (Also still reachable via the deprecated, hidden
10
+ * `agents repo refresh` alias.)
9
11
  */
10
12
  import type { AgentId } from './types.js';
11
13
  export interface RefreshOptions {
@@ -3,9 +3,11 @@
3
3
  * sync resources into installed version homes, register hooks, add shims to
4
4
  * PATH, prompt for missing default versions, install declared host-CLIs.
5
5
  *
6
- * Used by `agents repo refresh` (user-facing) and any other caller that needs
7
- * to re-derive local state from declared configuration. Does NOT do any git
8
- * operations — that lives in `agents repo pull`.
6
+ * The reconcile stage behind `agents sync` (the umbrella `--local` path calls
7
+ * this; see sync-umbrella.ts) and any other caller that needs to re-derive local
8
+ * state from declared configuration. Does NOT do any git operations — that lives
9
+ * in `agents repo pull`. (Also still reachable via the deprecated, hidden
10
+ * `agents repo refresh` alias.)
9
11
  */
10
12
  import * as fs from 'fs';
11
13
  import * as path from 'path';
@@ -13,7 +15,7 @@ import chalk from 'chalk';
13
15
  import ora from 'ora';
14
16
  import { select, confirm } from '@inquirer/prompts';
15
17
  import { capableAgents } from './capabilities.js';
16
- import { AGENTS, ALL_AGENT_IDS, getAllCliStates, registerMcpToTargets, agentLabel, } from './agents.js';
18
+ import { AGENTS, MANAGED_AGENT_IDS, getAllCliStates, registerMcpToTargets, agentLabel, } from './agents.js';
17
19
  import { readManifest, MANIFEST_FILENAME } from './manifest.js';
18
20
  import { getUserAgentsDir } from './state.js';
19
21
  import { installVersion, listInstalledVersions, isVersionIsolated, getGlobalDefault, setGlobalDefault, getVersionHomePath, syncResourcesToVersion, getAvailableResources, getActuallySyncedResources, getNewResources, getProjectOnlyResources, hasNewResources, promptNewResourceSelection, promptResourceSelection, resolveConfiguredAgentTargets, } from './versions.js';
@@ -114,7 +116,7 @@ export async function refresh(options = {}) {
114
116
  }
115
117
  // 3. Sync resources to default version homes
116
118
  const cliStates = await getAllCliStates();
117
- const agentsToSync = agentFilter ? [agentFilter] : ALL_AGENT_IDS;
119
+ const agentsToSync = agentFilter ? [agentFilter] : MANAGED_AGENT_IDS;
118
120
  const available = getAvailableResources();
119
121
  for (const agentId of agentsToSync) {
120
122
  if (!cliStates[agentId]?.installed && listInstalledVersions(agentId).length === 0)
@@ -8,7 +8,7 @@
8
8
  import * as fs from 'fs';
9
9
  import * as path from 'path';
10
10
  import { getProjectAgentsDir, getUserAgentsDir, getSystemAgentsDir, getEnabledExtraRepos, } from '../state.js';
11
- import { AGENTS, agentConfigDirName } from '../agents.js';
11
+ import { AGENTS, agentConfigDirName, isAgentHardDeprecated } from '../agents.js';
12
12
  import { markdownToToml } from '../convert.js';
13
13
  /**
14
14
  * Get the commands directory for a given layer root.
@@ -162,6 +162,9 @@ export class CommandsHandler {
162
162
  * Copies/transforms commands as needed for the agent's expected format.
163
163
  */
164
164
  sync(agent, versionHome, cwd) {
165
+ if (isAgentHardDeprecated(agent)) {
166
+ return;
167
+ }
165
168
  const agentConfig = AGENTS[agent];
166
169
  const targetFormat = this.format(agent);
167
170
  const targetDir = path.join(versionHome, agentConfigDirName(agent), this.targetDir(agent));
@@ -115,8 +115,6 @@ export function getMcpConfigPath(agent, versionHome) {
115
115
  return path.join(versionHome, '.config', 'opencode', 'opencode.jsonc');
116
116
  case 'cursor':
117
117
  return path.join(versionHome, '.cursor', 'mcp.json');
118
- case 'gemini':
119
- return path.join(versionHome, '.gemini', 'settings.json');
120
118
  case 'openclaw':
121
119
  return path.join(versionHome, '.openclaw', 'openclaw.json');
122
120
  case 'antigravity':
@@ -126,8 +124,6 @@ export function getMcpConfigPath(agent, versionHome) {
126
124
  return path.join(versionHome, '.grok', 'mcp.json');
127
125
  case 'hermes':
128
126
  return path.join(versionHome, '.hermes', 'config.yaml');
129
- case 'forge':
130
- return path.join(versionHome, '.forge', '.mcp.json');
131
127
  default:
132
128
  return null;
133
129
  }
@@ -4,7 +4,7 @@
4
4
  * Permissions are stored as YAML files in permissions/ directories at each layer.
5
5
  * Resolution: project > user > system (higher layer wins on name conflict).
6
6
  * Unlike other resources, permissions merge into agent-specific config files
7
- * (Claude/Gemini: settings.json, Codex: config.toml, OpenCode: opencode.jsonc).
7
+ * (Claude: settings.json, Codex: config.toml, OpenCode: opencode.jsonc).
8
8
  */
9
9
  import type { ResourceHandler } from './types.js';
10
10
  import type { PermissionSet } from '../types.js';
@@ -4,7 +4,7 @@
4
4
  * Permissions are stored as YAML files in permissions/ directories at each layer.
5
5
  * Resolution: project > user > system (higher layer wins on name conflict).
6
6
  * Unlike other resources, permissions merge into agent-specific config files
7
- * (Claude/Gemini: settings.json, Codex: config.toml, OpenCode: opencode.jsonc).
7
+ * (Claude: settings.json, Codex: config.toml, OpenCode: opencode.jsonc).
8
8
  */
9
9
  import * as fs from 'fs';
10
10
  import * as path from 'path';
@@ -65,8 +65,6 @@ function getAgentConfigPath(agent, versionHome) {
65
65
  return path.join(versionHome, '.claude', 'settings.json');
66
66
  case 'codex':
67
67
  return path.join(versionHome, '.codex', 'config.toml');
68
- case 'gemini':
69
- return path.join(versionHome, '.gemini', 'settings.json');
70
68
  case 'opencode':
71
69
  return path.join(versionHome, '.config', 'opencode', 'opencode.jsonc');
72
70
  case 'kimi':
@@ -79,8 +77,6 @@ function getAgentConfigPath(agent, versionHome) {
79
77
  return path.join(versionHome, '.openclaw', 'openclaw.json');
80
78
  case 'copilot':
81
79
  return path.join(versionHome, '.copilot', 'permissions-config.json');
82
- case 'forge':
83
- return path.join(versionHome, '.forge', 'permissions.yaml');
84
80
  case 'hermes':
85
81
  return path.join(versionHome, '.hermes', 'config.yaml');
86
82
  case 'goose':
@@ -9,7 +9,7 @@
9
9
  * - All unique subrules across layers are unioned
10
10
  */
11
11
  import * as fs from 'fs';
12
- import { agentConfigDirName } from '../agents.js';
12
+ import { agentConfigDirName, isAgentHardDeprecated } from '../agents.js';
13
13
  import * as path from 'path';
14
14
  import { getSystemRulesDir, getUserRulesDir, getProjectAgentsDir, getEnabledExtraRepos, } from '../state.js';
15
15
  const SUBRULES_DIR = 'subrules';
@@ -158,6 +158,9 @@ export const RulesHandler = {
158
158
  return resolveRule(name, getLayerDirs(cwd));
159
159
  },
160
160
  sync(agent, versionHome, _cwd) {
161
+ if (isAgentHardDeprecated(agent)) {
162
+ return;
163
+ }
161
164
  // Rules sync is handled by the compose module and syncResourcesToVersion.
162
165
  // This method ensures the agent config directory exists.
163
166
  // The actual composition and write happens in versions.ts via composeRulesFromState().
@@ -5,7 +5,7 @@
5
5
  * Format is the same for all agents. Resolution order: project > user > system.
6
6
  */
7
7
  import * as fs from 'fs';
8
- import { AGENTS, agentConfigDirName } from '../agents.js';
8
+ import { AGENTS, agentConfigDirName, isAgentHardDeprecated } from '../agents.js';
9
9
  import * as path from 'path';
10
10
  import * as yaml from 'yaml';
11
11
  import { getSystemSkillsDir, getUserSkillsDir, getProjectAgentsDir, getEnabledExtraRepos, } from '../state.js';
@@ -201,6 +201,9 @@ export function createSkillsHandler(provider = defaultProvider) {
201
201
  return null;
202
202
  },
203
203
  sync(agent, versionHome, cwd) {
204
+ if (isAgentHardDeprecated(agent)) {
205
+ return;
206
+ }
204
207
  // Agents that read directly from central ~/.agents/skills/ (e.g. Gemini,
205
208
  // Goose via the Summon extension) should not get a per-version copy.
206
209
  if (AGENTS[agent]?.nativeAgentsSkillsDir) {
@@ -8,6 +8,7 @@ import * as fs from 'fs';
8
8
  import * as path from 'path';
9
9
  import * as yaml from 'yaml';
10
10
  import { getProjectAgentsDir, getUserSubagentsDir, getSystemSubagentsDir, getEnabledExtraRepos, } from '../state.js';
11
+ import { isAgentHardDeprecated } from '../agents.js';
11
12
  /** Get layer directories for subagent resolution. */
12
13
  function getLayerDirs(cwd) {
13
14
  const projectDir = getProjectAgentsDir(cwd);
@@ -155,6 +156,9 @@ export class SubagentsHandler {
155
156
  * Copies YAML files to the target directory.
156
157
  */
157
158
  sync(agent, versionHome, cwd) {
159
+ if (isAgentHardDeprecated(agent)) {
160
+ return;
161
+ }
158
162
  const targetDir = path.join(versionHome, this.targetDir(agent));
159
163
  // Ensure target directory exists
160
164
  if (!fs.existsSync(targetDir)) {
@@ -5,7 +5,7 @@
5
5
  * - Union: All resources from all layers are combined
6
6
  * - Override on name conflict: Higher layer wins (project > user > system)
7
7
  */
8
- export type AgentId = 'claude' | 'codex' | 'gemini' | 'cursor' | 'opencode' | 'openclaw' | 'copilot' | 'kiro' | 'goose' | 'antigravity' | 'grok' | 'kimi' | 'droid' | 'hermes' | 'forge';
8
+ export type AgentId = 'claude' | 'codex' | 'gemini' | 'cursor' | 'opencode' | 'openclaw' | 'copilot' | 'kiro' | 'goose' | 'antigravity' | 'grok' | 'kimi' | 'droid' | 'hermes';
9
9
  export type Layer = 'system' | 'user' | 'project';
10
10
  export type ResourceKind = 'command' | 'hook' | 'skill' | 'rule' | 'mcp' | 'permission' | 'subagent' | 'workflow' | 'memory';
11
11
  /** A resolved resource with its origin layer. */
@@ -187,6 +187,14 @@ export interface JobConfig {
187
187
  resume?: string;
188
188
  /** When set, executeJob runs this job through the loop driver instead of once. */
189
189
  loop?: LoopConfig;
190
+ /**
191
+ * Actor id of whoever CREATED this routine (`resolveActor().id`, stamped by
192
+ * `writeJob` at creation and preserved across edits). Propagated into each
193
+ * fired run's env and RunMeta so an unattended cron traces back to the person
194
+ * who scheduled it, not the `UNRESOLVED@<host>` a live resolve would give.
195
+ * RUSH-2020.
196
+ */
197
+ actor?: string;
190
198
  }
191
199
  /** Metadata for a single job execution, persisted as JSON in the run directory. */
192
200
  export interface RunMeta {
@@ -216,6 +224,18 @@ export interface RunMeta {
216
224
  cloudTaskId?: string;
217
225
  /** Cloud provider id when the run was cloud-dispatched. */
218
226
  cloudProvider?: string;
227
+ /**
228
+ * Actor id of the routine's CREATOR (stamped at creation, carried from the job
229
+ * config). Answers "whose scheduled run is this" for an unattended cron fire,
230
+ * where resolving the actor live would only yield `UNRESOLVED@<host>`. RUSH-2020.
231
+ */
232
+ actor?: string;
233
+ /**
234
+ * Actor id that TRIGGERED this particular run (`resolveActor().id` at fire
235
+ * time): a person for a manual `agents routines run`, `UNRESOLVED@<host>` for
236
+ * an unattended scheduled fire. Distinct from {@link actor} (the creator).
237
+ */
238
+ triggeredBy?: string;
219
239
  }
220
240
  /**
221
241
  * Finalize a run record with a terminal status, computing `duration` from
@@ -15,6 +15,7 @@ import { safeJoin, isSafeSegmentName } from './paths.js';
15
15
  import { atomicWriteFileSync } from './fs-atomic.js';
16
16
  import { ALL_AGENT_IDS } from './agents.js';
17
17
  import { machineId, normalizeHost } from './machine-id.js';
18
+ import { resolveActor } from './actor.js';
18
19
  export const HOST_STRATEGIES = ['local', 'host', 'fleet', 'cloud'];
19
20
  /** Canonical set of accepted GitHub trigger events — single source for validation. */
20
21
  export const GITHUB_TRIGGER_EVENTS = [
@@ -268,6 +269,11 @@ function readJobFile(filePath) {
268
269
  */
269
270
  export function writeJob(config) {
270
271
  ensureAgentsDir();
272
+ // Stamp the creator once (RUSH-2020). An edit re-writes a config loaded from
273
+ // disk, which already carries `actor`, so this preserves the original creator;
274
+ // only a brand-new routine (no actor yet) gets the current resolver.
275
+ if (!config.actor)
276
+ config.actor = resolveActor().id;
271
277
  const jobsDir = getRoutinesDir();
272
278
  const ymlPath = safeJoin(jobsDir, config.name + '.yml');
273
279
  const yamlPath = safeJoin(jobsDir, config.name + '.yaml');
@@ -36,6 +36,7 @@ export declare function parseRunDefaultSelector(input: string): ParsedRunDefault
36
36
  export declare function resolveRunDefaultsFromConfig(runConfig: RunConfig | undefined, agent: AgentId, version?: string | null): ResolvedRunDefaults;
37
37
  export declare function resolveRunDefaultsFromConfigs(runConfigs: Array<RunConfig | undefined>, agent: AgentId, version?: string | null): ResolvedRunDefaults;
38
38
  export declare function resolveRunDefaults(agent: AgentId, version?: string | null, startPath?: string): ResolvedRunDefaults;
39
+ export declare function formatRunDefaultEntry(entry: RunDefaultEntry): string;
39
40
  export declare function listRunDefaults(): RunDefaultEntry[];
40
41
  export declare function setRunDefault(selectorInput: string, defaultsInput: RunDefaultsInput): RunDefaultEntry;
41
42
  export declare function unsetRunDefault(selectorInput: string): boolean;
@@ -15,6 +15,7 @@ import { ALL_MODES } from './types.js';
15
15
  import { AGENTS } from './agents.js';
16
16
  import { readMeta, updateMeta } from './state.js';
17
17
  import { getProjectRunConfigs } from './run-config.js';
18
+ import chalk from 'chalk';
18
19
  const VERSION_RE = /^(?:\*|latest|(?!.*\.\.)[A-Za-z0-9._+-]{1,64})$/;
19
20
  function isAgentId(value) {
20
21
  return value in AGENTS;
@@ -128,6 +129,14 @@ export function resolveRunDefaults(agent, version, startPath = process.cwd()) {
128
129
  const projectRunConfigs = getProjectRunConfigs(startPath).reverse();
129
130
  return resolveRunDefaultsFromConfigs([readMeta().run, ...projectRunConfigs], agent, version);
130
131
  }
132
+ export function formatRunDefaultEntry(entry) {
133
+ const parts = [];
134
+ if (entry.defaults.mode)
135
+ parts.push(`mode ${chalk.white(entry.defaults.mode)}`);
136
+ if (entry.defaults.model)
137
+ parts.push(`model ${chalk.white(entry.defaults.model)}`);
138
+ return `${chalk.cyan(entry.selector.padEnd(22))} ${parts.join(' ')}`;
139
+ }
131
140
  export function listRunDefaults() {
132
141
  const defaults = readMeta().run?.defaults ?? {};
133
142
  return Object.entries(defaults)
@@ -64,18 +64,6 @@ export declare function dispatchesViaAgentsRun(config: Pick<JobConfig, 'workflow
64
64
  * with `agents run`.
65
65
  */
66
66
  export declare function buildRoutineSpawnEnv(baseEnv: Record<string, string>, agent: AgentId, version: string | undefined, timezone?: string): Record<string, string>;
67
- /**
68
- * Execute a job synchronously (waits for completion or timeout before resolving).
69
- *
70
- * When `config.loop` is set the job is routed through the loop driver (`runLoop`
71
- * from loop.ts) instead of a single spawn — same driver as `agents run --loop` and
72
- * workflow `loop:` blocks (issue #400). The optional `deps` parameter provides
73
- * injectable seams (runIteration, sleep, writeCheckpoint) used by tests; production
74
- * callers omit it and get the defaults.
75
- *
76
- * Single-shot path: pre-flight version/account selection + mid-run rate-limit
77
- * failover across healthy same-agent accounts (RUSH-1016).
78
- */
79
67
  export declare function executeJob(config: JobConfig, deps?: LoopDeps): Promise<RunResult>;
80
68
  /**
81
69
  * Optional lifecycle callbacks for a detached routine run. The daemon passes an