@phnx-labs/agents-cli 1.20.61 → 1.20.62

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.
@@ -266,6 +266,28 @@ function buildKiroDetector() {
266
266
  },
267
267
  };
268
268
  }
269
+ function buildOpenClawDetector() {
270
+ return {
271
+ kind: 'permissions',
272
+ agent: 'openclaw',
273
+ list({ versionHome }) {
274
+ const configPath = path.join(versionHome, '.openclaw', 'openclaw.json');
275
+ if (!fs.existsSync(configPath))
276
+ return [];
277
+ try {
278
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
279
+ const tools = config.tools;
280
+ const hasAllow = Array.isArray(tools?.alsoAllow) && tools.alsoAllow.length > 0;
281
+ const hasDeny = Array.isArray(tools?.deny) && tools.deny.length > 0;
282
+ if (hasAllow || hasDeny) {
283
+ return discoverPermissionGroups().map(g => g.name);
284
+ }
285
+ }
286
+ catch { /* parse fail */ }
287
+ return [];
288
+ },
289
+ };
290
+ }
269
291
  const handlers = {
270
292
  claude: buildClaudeDetector,
271
293
  codex: buildCodexDetector,
@@ -278,6 +300,7 @@ const handlers = {
278
300
  cursor: buildCursorDetector,
279
301
  droid: buildDroidDetector,
280
302
  kiro: buildKiroDetector,
303
+ openclaw: buildOpenClawDetector,
281
304
  };
282
305
  export const permissionsDetectors = lazyAgentMap(() => {
283
306
  const m = {};
@@ -2,6 +2,8 @@
2
2
  * Subagents detector. Claude/Gemini/Grok: flat .md files under `<agentDir>/agents/`.
3
3
  * Codex: flat .toml files under `<versionHome>/.codex/agents/`.
4
4
  * Droid: flat .md files under `<versionHome>/.factory/droids/`.
5
+ * Cursor: flat .md files under `<versionHome>/.cursor/agents/`.
6
+ * ForgeCode: flat .md files under `<versionHome>/.forge/agents/`.
5
7
  * OpenClaw: subdirectories containing AGENTS.md under `<versionHome>/.openclaw/`.
6
8
  * Mirrors versions.ts:521-539.
7
9
  */
@@ -74,6 +76,20 @@ function buildCopilotDetector() {
74
76
  },
75
77
  };
76
78
  }
79
+ function buildCursorDetector() {
80
+ return {
81
+ kind: 'subagents',
82
+ agent: 'cursor',
83
+ list({ versionHome }) {
84
+ const agentsDir = path.join(versionHome, '.cursor', 'agents');
85
+ if (!fs.existsSync(agentsDir))
86
+ return [];
87
+ return fs.readdirSync(agentsDir)
88
+ .filter(f => f.endsWith('.md'))
89
+ .map(f => f.replace(/\.md$/, ''));
90
+ },
91
+ };
92
+ }
77
93
  function buildOpenclawDetector() {
78
94
  return {
79
95
  kind: 'subagents',
@@ -117,6 +133,23 @@ function buildKiroDetector() {
117
133
  },
118
134
  };
119
135
  }
136
+ function buildForgeDetector() {
137
+ return buildFlatMdAgentsDetector('forge', '.forge');
138
+ }
139
+ function buildGooseDetector() {
140
+ return {
141
+ kind: 'subagents',
142
+ agent: 'goose',
143
+ list({ versionHome }) {
144
+ const agentsDir = path.join(versionHome, '.config', 'goose', 'agents');
145
+ if (!fs.existsSync(agentsDir))
146
+ return [];
147
+ return fs.readdirSync(agentsDir)
148
+ .filter(f => f.endsWith('.yaml'))
149
+ .map(f => f.replace(/\.yaml$/, ''));
150
+ },
151
+ };
152
+ }
120
153
  function buildOpenCodeDetector() {
121
154
  return {
122
155
  kind: 'subagents',
@@ -157,6 +190,9 @@ const handlers = {
157
190
  droid: buildDroidDetector,
158
191
  openclaw: buildOpenclawDetector,
159
192
  kiro: buildKiroDetector,
193
+ cursor: buildCursorDetector,
194
+ forge: buildForgeDetector,
195
+ goose: buildGooseDetector,
160
196
  };
161
197
  export const subagentsDetectors = lazyAgentMap(() => {
162
198
  const m = {};
@@ -25,6 +25,7 @@ import { safeJoin } from '../../paths.js';
25
25
  import { markdownToToml } from '../../convert.js';
26
26
  import { commandAppliesTo, parseCommandMetadata } from '../../commands.js';
27
27
  import { installCommandSkillToVersion, shouldInstallCommandAsSkill } from '../../command-skills.js';
28
+ import { installGooseCommandToVersion } from '../../goose-commands.js';
28
29
  import { resolveCommandSource, trustedSkillRoots } from './sources.js';
29
30
  import { lazyAgentMap } from './lazy-map.js';
30
31
  function buildCommandsWriter(agent) {
@@ -59,6 +60,12 @@ function buildCommandsWriter(agent) {
59
60
  if (!installed.success)
60
61
  continue;
61
62
  }
63
+ else if (agent === 'goose') {
64
+ // Goose: recipe YAML + config.yaml slash_commands entry, not a file copy.
65
+ const installed = installGooseCommandToVersion(versionHome, cmd, srcFile);
66
+ if (!installed.success)
67
+ continue;
68
+ }
62
69
  else if (agentConfig.format === 'toml') {
63
70
  const content = fs.readFileSync(srcFile, 'utf-8');
64
71
  const tomlContent = markdownToToml(cmd, content);
@@ -36,7 +36,7 @@ function buildHooksWriter(agent) {
36
36
  // registerHooksForGrok — file copy alone only sees top-level available.hooks
37
37
  // names (RUSH-1353). Copilot/Kiro/Goose load managed *.json under their
38
38
  // hooks dirs the same way.
39
- if (agent === 'claude' || agent === 'codex' || agent === 'gemini' || agent === 'antigravity' || agent === 'kimi' || agent === 'droid' || agent === 'copilot' || agent === 'kiro' || agent === 'goose' || agent === 'cursor' || agent === 'grok') {
39
+ if (agent === 'claude' || agent === 'codex' || agent === 'gemini' || agent === 'antigravity' || agent === 'kimi' || agent === 'droid' || agent === 'copilot' || agent === 'kiro' || agent === 'goose' || agent === 'cursor' || agent === 'grok' || agent === 'hermes') {
40
40
  registerHooksToSettings(agent, versionHome);
41
41
  }
42
42
  return { synced };
@@ -3,8 +3,9 @@
3
3
  * .md file under their native agents directory. Codex writes TOML under
4
4
  * `.codex/agents/`.
5
5
  * Droid (Factory AI) flattens each into a custom droid .md under
6
- * `<versionHome>/.factory/droids/`. OpenClaw copies the full subagent
7
- * directory (with AGENT.md renamed to AGENTS.md) into
6
+ * `<versionHome>/.factory/droids/`. Cursor flattens each into a custom
7
+ * subagent .md under `<versionHome>/.cursor/agents/`. OpenClaw copies the
8
+ * full subagent directory (with AGENT.md renamed to AGENTS.md) into
8
9
  * `<versionHome>/.openclaw/<name>/`.
9
10
  *
10
11
  * Source-side discovery is `listInstalledSubagents` from lib/subagents.ts —
@@ -14,7 +15,7 @@
14
15
  import * as fs from 'fs';
15
16
  import * as path from 'path';
16
17
  import { capableAgents } from '../../capabilities.js';
17
- import { listInstalledSubagents, transformSubagentForClaude, transformSubagentForCodex, transformSubagentForCopilot, writeKimiSubagentFiles, buildKimiSubagentsParentYaml, KIMI_SUBAGENTS_PARENT_FILE, transformSubagentForOpenCode, transformSubagentForAntigravity, transformSubagentForDroid, transformSubagentForKiro, syncSubagentToOpenclaw, parseSubagentFrontmatter, } from '../../subagents.js';
18
+ import { listInstalledSubagents, transformSubagentForClaude, transformSubagentForCodex, transformSubagentForCopilot, writeKimiSubagentFiles, buildKimiSubagentsParentYaml, KIMI_SUBAGENTS_PARENT_FILE, transformSubagentForOpenCode, transformSubagentForAntigravity, transformSubagentForDroid, transformSubagentForForge, transformSubagentForKiro, transformSubagentForCursor, transformSubagentForGoose, syncSubagentToOpenclaw, parseSubagentFrontmatter, } from '../../subagents.js';
18
19
  import { safeJoin } from '../../paths.js';
19
20
  import { lazyAgentMap } from './lazy-map.js';
20
21
  function buildSubagentsWriter(agent) {
@@ -83,6 +84,24 @@ function buildSubagentsWriter(agent) {
83
84
  fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.json`), transformSubagentForKiro(sub.path));
84
85
  synced.push(sub.name);
85
86
  }
87
+ else if (agent === 'cursor') {
88
+ const agentsDir = path.join(versionHome, '.cursor', 'agents');
89
+ fs.mkdirSync(agentsDir, { recursive: true });
90
+ fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.md`), transformSubagentForCursor(sub.path));
91
+ synced.push(sub.name);
92
+ }
93
+ else if (agent === 'forge') {
94
+ const agentsDir = path.join(versionHome, '.forge', 'agents');
95
+ fs.mkdirSync(agentsDir, { recursive: true });
96
+ fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.md`), transformSubagentForForge(sub.path));
97
+ synced.push(sub.name);
98
+ }
99
+ else if (agent === 'goose') {
100
+ const agentsDir = path.join(versionHome, '.config', 'goose', 'agents');
101
+ fs.mkdirSync(agentsDir, { recursive: true });
102
+ fs.writeFileSync(safeJoin(agentsDir, `${sub.name}.yaml`), transformSubagentForGoose(sub.path));
103
+ synced.push(sub.name);
104
+ }
86
105
  }
87
106
  catch { /* per-item sync failure: skip */ }
88
107
  }
@@ -68,6 +68,27 @@ export declare function transformSubagentForDroid(subagentDir: string): string;
68
68
  * See GitHub docs for custom agents.
69
69
  */
70
70
  export declare const transformSubagentForCopilot: typeof transformSubagentForDroid;
71
+ /**
72
+ * Transform a subagent into a Cursor CLI custom subagent `.md` file.
73
+ *
74
+ * Cursor loads subagents from `.cursor/agents/*.md` (project) or
75
+ * `~/.cursor/agents/*.md` (user) — Markdown with YAML frontmatter
76
+ * (name, description, model; also readonly/is_background, which our
77
+ * frontmatter schema doesn't carry). Cursor has no `color` field, so this is
78
+ * an alias of transformSubagentForDroid, same as Copilot.
79
+ * See https://cursor.com/docs/subagents.
80
+ */
81
+ export declare const transformSubagentForCursor: typeof transformSubagentForDroid;
82
+ /**
83
+ * Transform a subagent into a ForgeCode custom subagent `.md` file.
84
+ *
85
+ * ForgeCode loads named agents from `.forge/agents/*.md` (project) or
86
+ * `~/.forge/agents/*.md` (user) — Markdown with YAML frontmatter (id, title,
87
+ * description, tools, model, temperature) + a system-prompt body. ForgeCode has
88
+ * no `color` field, so this is an alias of transformSubagentForDroid, same as
89
+ * Copilot/Cursor. See https://forgecode.dev/docs/agent-definition-guide/.
90
+ */
91
+ export declare const transformSubagentForForge: typeof transformSubagentForDroid;
71
92
  /**
72
93
  * Transform a subagent into Antigravity's custom-agent markdown shape.
73
94
  *
@@ -138,6 +159,17 @@ export declare function transformSubagentForCodex(subagentDir: string): string;
138
159
  * set so the subagent can actually run.
139
160
  */
140
161
  export declare function transformSubagentForKiro(subagentDir: string): string;
162
+ /**
163
+ * Transform a subagent into a Goose recipe YAML file.
164
+ *
165
+ * Goose has no dedicated subagent file format — a named subagent IS a recipe.
166
+ * Goose resolves named agents from `~/.config/goose/agents/<name>.yaml` (global)
167
+ * and delegates to them by name in autonomous mode. The recipe schema mirrors the
168
+ * one agents-cli already emits for Goose workflow recipes (`writeGooseSubrecipe`):
169
+ * `version`, `title`, `description`, `instructions`, `prompt`, plus an optional
170
+ * `settings.goose_model`. See goose-docs.ai context-engineering/subagents.
171
+ */
172
+ export declare function transformSubagentForGoose(subagentDir: string): string;
141
173
  /**
142
174
  * Sync a subagent to an OpenClaw workspace
143
175
  * Copies full directory, renames AGENT.md to AGENTS.md
@@ -274,6 +274,27 @@ export function transformSubagentForDroid(subagentDir) {
274
274
  * See GitHub docs for custom agents.
275
275
  */
276
276
  export const transformSubagentForCopilot = transformSubagentForDroid;
277
+ /**
278
+ * Transform a subagent into a Cursor CLI custom subagent `.md` file.
279
+ *
280
+ * Cursor loads subagents from `.cursor/agents/*.md` (project) or
281
+ * `~/.cursor/agents/*.md` (user) — Markdown with YAML frontmatter
282
+ * (name, description, model; also readonly/is_background, which our
283
+ * frontmatter schema doesn't carry). Cursor has no `color` field, so this is
284
+ * an alias of transformSubagentForDroid, same as Copilot.
285
+ * See https://cursor.com/docs/subagents.
286
+ */
287
+ export const transformSubagentForCursor = transformSubagentForDroid;
288
+ /**
289
+ * Transform a subagent into a ForgeCode custom subagent `.md` file.
290
+ *
291
+ * ForgeCode loads named agents from `.forge/agents/*.md` (project) or
292
+ * `~/.forge/agents/*.md` (user) — Markdown with YAML frontmatter (id, title,
293
+ * description, tools, model, temperature) + a system-prompt body. ForgeCode has
294
+ * no `color` field, so this is an alias of transformSubagentForDroid, same as
295
+ * Copilot/Cursor. See https://forgecode.dev/docs/agent-definition-guide/.
296
+ */
297
+ export const transformSubagentForForge = transformSubagentForDroid;
277
298
  /**
278
299
  * Transform a subagent into Antigravity's custom-agent markdown shape.
279
300
  *
@@ -493,6 +514,45 @@ export function transformSubagentForKiro(subagentDir) {
493
514
  }
494
515
  return JSON.stringify(config, null, 2);
495
516
  }
517
+ /**
518
+ * Transform a subagent into a Goose recipe YAML file.
519
+ *
520
+ * Goose has no dedicated subagent file format — a named subagent IS a recipe.
521
+ * Goose resolves named agents from `~/.config/goose/agents/<name>.yaml` (global)
522
+ * and delegates to them by name in autonomous mode. The recipe schema mirrors the
523
+ * one agents-cli already emits for Goose workflow recipes (`writeGooseSubrecipe`):
524
+ * `version`, `title`, `description`, `instructions`, `prompt`, plus an optional
525
+ * `settings.goose_model`. See goose-docs.ai context-engineering/subagents.
526
+ */
527
+ export function transformSubagentForGoose(subagentDir) {
528
+ const agentMd = path.join(subagentDir, 'AGENT.md');
529
+ const frontmatter = parseSubagentFrontmatter(agentMd);
530
+ const body = getSubagentBody(agentMd);
531
+ if (!frontmatter) {
532
+ throw new Error(`Invalid AGENT.md in ${subagentDir}`);
533
+ }
534
+ const files = fs.readdirSync(subagentDir)
535
+ .filter(f => f.endsWith('.md') && f !== 'AGENT.md')
536
+ .sort();
537
+ let prompt = body || frontmatter.description || frontmatter.name;
538
+ for (const file of files) {
539
+ const content = fs.readFileSync(path.join(subagentDir, file), 'utf-8').trim();
540
+ const sectionName = file.replace('.md', '');
541
+ const title = sectionName.charAt(0).toUpperCase() + sectionName.slice(1).toLowerCase();
542
+ prompt += `\n\n## ${title}\n\n${content}`;
543
+ }
544
+ const recipe = {
545
+ version: '1.0.0',
546
+ title: frontmatter.name || path.basename(subagentDir),
547
+ description: frontmatter.description || frontmatter.name || path.basename(subagentDir),
548
+ instructions: prompt,
549
+ prompt,
550
+ };
551
+ if (frontmatter.model) {
552
+ recipe.settings = { goose_model: frontmatter.model };
553
+ }
554
+ return yaml.stringify(recipe);
555
+ }
496
556
  /**
497
557
  * Sync a subagent to an OpenClaw workspace
498
558
  * Copies full directory, renames AGENT.md to AGENTS.md
@@ -609,6 +669,51 @@ export function installSubagentToAgent(subagentDir, subagentName, agent, agentHo
609
669
  return { success: false, error: String(err) };
610
670
  }
611
671
  }
672
+ else if (agent === 'cursor') {
673
+ // Cursor: flattened .md custom subagent under ~/.cursor/agents/
674
+ const agentsDir = path.join(agentHome, '.cursor', 'agents');
675
+ if (!fs.existsSync(agentsDir)) {
676
+ fs.mkdirSync(agentsDir, { recursive: true });
677
+ }
678
+ try {
679
+ const transformed = transformSubagentForCursor(subagentDir);
680
+ fs.writeFileSync(safeJoin(agentsDir, `${subagentName}.md`), transformed);
681
+ return { success: true };
682
+ }
683
+ catch (err) {
684
+ return { success: false, error: String(err) };
685
+ }
686
+ }
687
+ else if (agent === 'forge') {
688
+ // ForgeCode: flattened .md custom subagent under ~/.forge/agents/
689
+ const agentsDir = path.join(agentHome, '.forge', 'agents');
690
+ if (!fs.existsSync(agentsDir)) {
691
+ fs.mkdirSync(agentsDir, { recursive: true });
692
+ }
693
+ try {
694
+ const transformed = transformSubagentForForge(subagentDir);
695
+ fs.writeFileSync(safeJoin(agentsDir, `${subagentName}.md`), transformed);
696
+ return { success: true };
697
+ }
698
+ catch (err) {
699
+ return { success: false, error: String(err) };
700
+ }
701
+ }
702
+ else if (agent === 'goose') {
703
+ // Goose: recipe YAML custom-agent file under ~/.config/goose/agents/
704
+ const agentsDir = path.join(agentHome, '.config', 'goose', 'agents');
705
+ if (!fs.existsSync(agentsDir)) {
706
+ fs.mkdirSync(agentsDir, { recursive: true });
707
+ }
708
+ try {
709
+ const transformed = transformSubagentForGoose(subagentDir);
710
+ fs.writeFileSync(safeJoin(agentsDir, `${subagentName}.yaml`), transformed);
711
+ return { success: true };
712
+ }
713
+ catch (err) {
714
+ return { success: false, error: String(err) };
715
+ }
716
+ }
612
717
  else {
613
718
  // Other agents don't support subagents yet
614
719
  return { success: false, error: `Agent '${agent}' does not support subagents` };
@@ -670,6 +775,27 @@ export function removeSubagentFromAgent(subagentName, agent, agentHome) {
670
775
  }
671
776
  return { success: true };
672
777
  }
778
+ else if (agent === 'cursor') {
779
+ const targetPath = safeJoin(path.join(agentHome, '.cursor', 'agents'), `${subagentName}.md`);
780
+ if (fs.existsSync(targetPath)) {
781
+ fs.unlinkSync(targetPath);
782
+ }
783
+ return { success: true };
784
+ }
785
+ else if (agent === 'forge') {
786
+ const targetPath = safeJoin(path.join(agentHome, '.forge', 'agents'), `${subagentName}.md`);
787
+ if (fs.existsSync(targetPath)) {
788
+ fs.unlinkSync(targetPath);
789
+ }
790
+ return { success: true };
791
+ }
792
+ else if (agent === 'goose') {
793
+ const targetPath = safeJoin(path.join(agentHome, '.config', 'goose', 'agents'), `${subagentName}.yaml`);
794
+ if (fs.existsSync(targetPath)) {
795
+ fs.unlinkSync(targetPath);
796
+ }
797
+ return { success: true };
798
+ }
673
799
  else {
674
800
  return { success: true }; // No-op for unsupported agents
675
801
  }
@@ -886,6 +1012,61 @@ export function listSubagentsForAgent(agentId, home) {
886
1012
  });
887
1013
  }
888
1014
  }
1015
+ else if (agentId === 'cursor') {
1016
+ // Cursor: flat `<name>.md` files under ~/.cursor/agents/
1017
+ const agentsDir = path.join(home, '.cursor', 'agents');
1018
+ if (!fs.existsSync(agentsDir))
1019
+ return subagents;
1020
+ for (const file of fs.readdirSync(agentsDir)) {
1021
+ if (!file.endsWith('.md'))
1022
+ continue;
1023
+ const filePath = path.join(agentsDir, file);
1024
+ if (!fs.statSync(filePath).isFile())
1025
+ continue;
1026
+ const name = file.replace(/\.md$/, '');
1027
+ const frontmatter = parseSubagentFrontmatter(filePath) ?? { name, description: '' };
1028
+ subagents.push({ name, path: filePath, files: [file], frontmatter });
1029
+ }
1030
+ }
1031
+ else if (agentId === 'forge') {
1032
+ // ForgeCode: flat `<name>.md` files under ~/.forge/agents/
1033
+ const agentsDir = path.join(home, '.forge', 'agents');
1034
+ if (!fs.existsSync(agentsDir))
1035
+ return subagents;
1036
+ for (const file of fs.readdirSync(agentsDir)) {
1037
+ if (!file.endsWith('.md'))
1038
+ continue;
1039
+ const filePath = path.join(agentsDir, file);
1040
+ if (!fs.statSync(filePath).isFile())
1041
+ continue;
1042
+ const name = file.replace(/\.md$/, '');
1043
+ const frontmatter = parseSubagentFrontmatter(filePath) ?? { name, description: '' };
1044
+ subagents.push({ name, path: filePath, files: [file], frontmatter });
1045
+ }
1046
+ }
1047
+ else if (agentId === 'goose') {
1048
+ // Goose: recipe YAML files under ~/.config/goose/agents/
1049
+ const agentsDir = path.join(home, '.config', 'goose', 'agents');
1050
+ if (!fs.existsSync(agentsDir))
1051
+ return subagents;
1052
+ for (const file of fs.readdirSync(agentsDir)) {
1053
+ if (!file.endsWith('.yaml'))
1054
+ continue;
1055
+ const filePath = path.join(agentsDir, file);
1056
+ if (!fs.statSync(filePath).isFile())
1057
+ continue;
1058
+ const name = file.replace(/\.yaml$/, '');
1059
+ let frontmatter;
1060
+ try {
1061
+ const recipe = yaml.parse(fs.readFileSync(filePath, 'utf-8'));
1062
+ frontmatter = { name: recipe?.title || name, description: recipe?.description || '' };
1063
+ }
1064
+ catch {
1065
+ continue;
1066
+ }
1067
+ subagents.push({ name, path: filePath, files: [file], frontmatter });
1068
+ }
1069
+ }
889
1070
  return subagents;
890
1071
  }
891
1072
  /**
@@ -984,6 +1165,42 @@ export function diffVersionSubagents(agent, version) {
984
1165
  }
985
1166
  }
986
1167
  }
1168
+ else if (agent === 'cursor') {
1169
+ const agentsDir = path.join(versionHome, '.cursor', 'agents');
1170
+ if (fs.existsSync(agentsDir)) {
1171
+ for (const file of fs.readdirSync(agentsDir)) {
1172
+ if (!file.endsWith('.md'))
1173
+ continue;
1174
+ const name = path.basename(file, '.md');
1175
+ if (!discovered.has(name))
1176
+ orphans.push(name);
1177
+ }
1178
+ }
1179
+ }
1180
+ else if (agent === 'forge') {
1181
+ const agentsDir = path.join(versionHome, '.forge', 'agents');
1182
+ if (fs.existsSync(agentsDir)) {
1183
+ for (const file of fs.readdirSync(agentsDir)) {
1184
+ if (!file.endsWith('.md'))
1185
+ continue;
1186
+ const name = path.basename(file, '.md');
1187
+ if (!discovered.has(name))
1188
+ orphans.push(name);
1189
+ }
1190
+ }
1191
+ }
1192
+ else if (agent === 'goose') {
1193
+ const agentsDir = path.join(versionHome, '.config', 'goose', 'agents');
1194
+ if (fs.existsSync(agentsDir)) {
1195
+ for (const file of fs.readdirSync(agentsDir)) {
1196
+ if (!file.endsWith('.yaml'))
1197
+ continue;
1198
+ const name = path.basename(file, '.yaml');
1199
+ if (!discovered.has(name))
1200
+ orphans.push(name);
1201
+ }
1202
+ }
1203
+ }
987
1204
  return { agent, version, orphans: orphans.sort() };
988
1205
  }
989
1206
  /**
@@ -1071,6 +1288,27 @@ export function removeSubagentFromVersion(agent, version, subagentName) {
1071
1288
  fs.renameSync(targetPath, path.join(trashDir, `${subagentName}.json.${stamp}`));
1072
1289
  }
1073
1290
  }
1291
+ else if (agent === 'cursor') {
1292
+ const targetPath = path.join(versionHome, '.cursor', 'agents', `${subagentName}.md`);
1293
+ if (fs.existsSync(targetPath)) {
1294
+ fs.mkdirSync(trashDir, { recursive: true, mode: 0o700 });
1295
+ fs.renameSync(targetPath, path.join(trashDir, `${subagentName}.md.${stamp}`));
1296
+ }
1297
+ }
1298
+ else if (agent === 'forge') {
1299
+ const targetPath = path.join(versionHome, '.forge', 'agents', `${subagentName}.md`);
1300
+ if (fs.existsSync(targetPath)) {
1301
+ fs.mkdirSync(trashDir, { recursive: true, mode: 0o700 });
1302
+ fs.renameSync(targetPath, path.join(trashDir, `${subagentName}.md.${stamp}`));
1303
+ }
1304
+ }
1305
+ else if (agent === 'goose') {
1306
+ const targetPath = path.join(versionHome, '.config', 'goose', 'agents', `${subagentName}.yaml`);
1307
+ if (fs.existsSync(targetPath)) {
1308
+ fs.mkdirSync(trashDir, { recursive: true, mode: 0o700 });
1309
+ fs.renameSync(targetPath, path.join(trashDir, `${subagentName}.yaml.${stamp}`));
1310
+ }
1311
+ }
1074
1312
  return { success: true };
1075
1313
  }
1076
1314
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phnx-labs/agents-cli",
3
- "version": "1.20.61",
3
+ "version": "1.20.62",
4
4
  "description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",