@rbbtsn0w/adg 0.1.0-alpha.1

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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/bin/adg.ts +758 -0
  4. package/docs/agents-spec.md +132 -0
  5. package/docs/authoring.md +352 -0
  6. package/package.json +50 -0
  7. package/schemas/adg-plugin.schema.json +77 -0
  8. package/schemas/marketplace.schema.json +86 -0
  9. package/schemas/plugin-lock.schema.json +90 -0
  10. package/src/adapters/anthropic.ts +54 -0
  11. package/src/adapters/index.ts +24 -0
  12. package/src/adapters/openai.ts +37 -0
  13. package/src/adapters/reverse.ts +60 -0
  14. package/src/agents/claude.ts +124 -0
  15. package/src/agents/codex.ts +67 -0
  16. package/src/agents/index.ts +12 -0
  17. package/src/agents/registry.ts +30 -0
  18. package/src/agents/types.ts +47 -0
  19. package/src/commands/adapt.ts +36 -0
  20. package/src/commands/import.ts +69 -0
  21. package/src/commands/init.ts +146 -0
  22. package/src/commands/install.ts +411 -0
  23. package/src/commands/link.ts +61 -0
  24. package/src/commands/list.ts +28 -0
  25. package/src/commands/marketplace.ts +198 -0
  26. package/src/commands/migrate.ts +84 -0
  27. package/src/commands/multiselect-skills.ts +137 -0
  28. package/src/commands/remove.ts +136 -0
  29. package/src/commands/select-agents.ts +45 -0
  30. package/src/commands/select-components.ts +66 -0
  31. package/src/commands/select-plugins.ts +28 -0
  32. package/src/commands/select-scope.ts +21 -0
  33. package/src/commands/update.ts +85 -0
  34. package/src/commands/validate.ts +57 -0
  35. package/src/components.ts +90 -0
  36. package/src/deps.ts +64 -0
  37. package/src/fsutil.ts +38 -0
  38. package/src/hash.ts +61 -0
  39. package/src/lock.ts +57 -0
  40. package/src/manifest.ts +113 -0
  41. package/src/marketplace.ts +41 -0
  42. package/src/package.ts +74 -0
  43. package/src/paths.ts +129 -0
  44. package/src/semver.ts +67 -0
  45. package/src/skills.ts +88 -0
  46. package/src/sources.ts +159 -0
  47. package/src/types.ts +140 -0
  48. package/vendor/skills/LICENSE +29 -0
  49. package/vendor/skills/PROVENANCE.md +60 -0
  50. package/vendor/skills/ThirdPartyNoticeText.txt +117 -0
  51. package/vendor/skills/package.json +143 -0
  52. package/vendor/skills/src/add.ts +1999 -0
  53. package/vendor/skills/src/agents.ts +755 -0
  54. package/vendor/skills/src/blob.ts +567 -0
  55. package/vendor/skills/src/cli.ts +387 -0
  56. package/vendor/skills/src/constants.ts +3 -0
  57. package/vendor/skills/src/detect-agent.ts +62 -0
  58. package/vendor/skills/src/find.ts +357 -0
  59. package/vendor/skills/src/frontmatter.ts +16 -0
  60. package/vendor/skills/src/git-tree.ts +36 -0
  61. package/vendor/skills/src/git.ts +277 -0
  62. package/vendor/skills/src/install.ts +91 -0
  63. package/vendor/skills/src/installer.ts +1097 -0
  64. package/vendor/skills/src/list.ts +231 -0
  65. package/vendor/skills/src/local-lock.ts +182 -0
  66. package/vendor/skills/src/plugin-manifest.ts +183 -0
  67. package/vendor/skills/src/prompts/search-multiselect.ts +387 -0
  68. package/vendor/skills/src/providers/index.ts +14 -0
  69. package/vendor/skills/src/providers/registry.ts +51 -0
  70. package/vendor/skills/src/providers/types.ts +97 -0
  71. package/vendor/skills/src/providers/wellknown.ts +804 -0
  72. package/vendor/skills/src/remove.ts +323 -0
  73. package/vendor/skills/src/sanitize.ts +65 -0
  74. package/vendor/skills/src/self-cli.ts +20 -0
  75. package/vendor/skills/src/skill-lock.ts +329 -0
  76. package/vendor/skills/src/skills.ts +316 -0
  77. package/vendor/skills/src/source-parser.ts +438 -0
  78. package/vendor/skills/src/sync.ts +478 -0
  79. package/vendor/skills/src/telemetry.ts +186 -0
  80. package/vendor/skills/src/test-utils.ts +73 -0
  81. package/vendor/skills/src/types.ts +128 -0
  82. package/vendor/skills/src/update-source.ts +90 -0
  83. package/vendor/skills/src/update.ts +749 -0
  84. package/vendor/skills/src/use.ts +675 -0
@@ -0,0 +1,387 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';
4
+ import { basename, join, dirname } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { runAdd, parseAddOptions, initTelemetry } from './add.ts';
7
+ import { runFind } from './find.ts';
8
+ import { runInstallFromLock } from './install.ts';
9
+ import { runList } from './list.ts';
10
+ import { removeCommand, parseRemoveOptions } from './remove.ts';
11
+ import { runSync, parseSyncOptions } from './sync.ts';
12
+ import { flushTelemetry } from './telemetry.ts';
13
+ import { isRunningInAgent } from './detect-agent.ts';
14
+ import { runUpdate } from './update.ts';
15
+ import { runUse, parseUseOptions } from './use.ts';
16
+
17
+ const __dirname = dirname(fileURLToPath(import.meta.url));
18
+
19
+ function getVersion(): string {
20
+ try {
21
+ const pkgPath = join(__dirname, '..', 'package.json');
22
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
23
+ return pkg.version;
24
+ } catch {
25
+ return '0.0.0';
26
+ }
27
+ }
28
+
29
+ const VERSION = getVersion();
30
+ initTelemetry(VERSION);
31
+
32
+ const RESET = '\x1b[0m';
33
+ const BOLD = '\x1b[1m';
34
+ // 256-color grays - visible on both light and dark backgrounds
35
+ const DIM = '\x1b[38;5;102m'; // darker gray for secondary text
36
+ const TEXT = '\x1b[38;5;145m'; // lighter gray for primary text
37
+
38
+ const LOGO_LINES = [
39
+ '███████╗██╗ ██╗██╗██╗ ██╗ ███████╗',
40
+ '██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝',
41
+ '███████╗█████╔╝ ██║██║ ██║ ███████╗',
42
+ '╚════██║██╔═██╗ ██║██║ ██║ ╚════██║',
43
+ '███████║██║ ██╗██║███████╗███████╗███████║',
44
+ '╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝',
45
+ ];
46
+
47
+ // 256-color middle grays - visible on both light and dark backgrounds
48
+ const GRAYS = [
49
+ '\x1b[38;5;250m', // lighter gray
50
+ '\x1b[38;5;248m',
51
+ '\x1b[38;5;245m', // mid gray
52
+ '\x1b[38;5;243m',
53
+ '\x1b[38;5;240m',
54
+ '\x1b[38;5;238m', // darker gray
55
+ ];
56
+
57
+ function showLogo(): void {
58
+ console.log();
59
+ LOGO_LINES.forEach((line, i) => {
60
+ console.log(`${GRAYS[i]}${line}${RESET}`);
61
+ });
62
+ }
63
+
64
+ function showBanner(): void {
65
+ showLogo();
66
+ console.log();
67
+ console.log(`${DIM}The open agent skills ecosystem${RESET}`);
68
+ console.log();
69
+ console.log(
70
+ ` ${DIM}$${RESET} ${TEXT}npx skills add ${DIM}<package>${RESET} ${DIM}Add a new skill${RESET}`
71
+ );
72
+ console.log(
73
+ ` ${DIM}$${RESET} ${TEXT}npx skills use ${DIM}<package>@<skill>${RESET} ${DIM}Use a skill without installing${RESET}`
74
+ );
75
+ console.log(
76
+ ` ${DIM}$${RESET} ${TEXT}npx skills remove${RESET} ${DIM}Remove installed skills${RESET}`
77
+ );
78
+ console.log(
79
+ ` ${DIM}$${RESET} ${TEXT}npx skills list${RESET} ${DIM}List installed skills${RESET}`
80
+ );
81
+ console.log(
82
+ ` ${DIM}$${RESET} ${TEXT}npx skills find ${DIM}[query]${RESET} ${DIM}Search for skills${RESET}`
83
+ );
84
+ console.log();
85
+ console.log(
86
+ ` ${DIM}$${RESET} ${TEXT}npx skills update${RESET} ${DIM}Update installed skills${RESET}`
87
+ );
88
+ console.log();
89
+ console.log(
90
+ ` ${DIM}$${RESET} ${TEXT}npx skills experimental_install${RESET} ${DIM}Restore from skills-lock.json${RESET}`
91
+ );
92
+ console.log(
93
+ ` ${DIM}$${RESET} ${TEXT}npx skills init ${DIM}[name]${RESET} ${DIM}Create a new skill${RESET}`
94
+ );
95
+ console.log(
96
+ ` ${DIM}$${RESET} ${TEXT}npx skills experimental_sync${RESET} ${DIM}Sync skills from node_modules${RESET}`
97
+ );
98
+ console.log();
99
+ console.log(`${DIM}try:${RESET} npx skills add vercel-labs/agent-skills`);
100
+ console.log();
101
+ console.log(`Discover more skills at ${TEXT}https://skills.sh/${RESET}`);
102
+ console.log();
103
+ }
104
+
105
+ function showHelp(): void {
106
+ console.log(`
107
+ ${BOLD}Usage:${RESET} skills <command> [options]
108
+
109
+ ${BOLD}Manage Skills:${RESET}
110
+ add <package> Add a skill package (alias: a)
111
+ e.g. vercel-labs/agent-skills
112
+ https://github.com/vercel-labs/agent-skills
113
+ use <package>@<skill>
114
+ Generate a prompt for using one skill without installing it
115
+ remove [skills] Remove installed skills
116
+ list, ls List installed skills
117
+ find [query] Search for skills interactively
118
+
119
+ ${BOLD}Updates:${RESET}
120
+ update [skills...] Update skills to latest versions (alias: upgrade)
121
+
122
+ ${BOLD}Update Options:${RESET}
123
+ -g, --global Update global skills only
124
+ -p, --project Update project skills only
125
+ -y, --yes Skip scope prompt (auto-detect: project if in a project, else global)
126
+
127
+ ${BOLD}Project:${RESET}
128
+ experimental_install Restore skills from skills-lock.json
129
+ init [name] Initialize a skill (creates <name>/SKILL.md or ./SKILL.md)
130
+ experimental_sync Sync skills from node_modules into agent directories
131
+
132
+ ${BOLD}Add Options:${RESET}
133
+ -g, --global Install skill globally (user-level) instead of project-level
134
+ -a, --agent <agents> Specify agents to install to (use '*' for all agents)
135
+ -s, --skill <skills> Specify skill names to install (use '*' for all skills)
136
+ -l, --list List available skills in the repository without installing
137
+ -y, --yes Skip confirmation prompts
138
+ --copy Copy files instead of symlinking to agent directories
139
+ --all Shorthand for --skill '*' --agent '*' -y
140
+ --full-depth Search all subdirectories even when a root SKILL.md exists
141
+
142
+ ${BOLD}Use Options:${RESET}
143
+ -s, --skill <skill> Specify the skill to use
144
+ -a, --agent <agent> Start one supported agent interactively
145
+ --full-depth Search all subdirectories even when a root SKILL.md exists
146
+ --dangerously-accept-openclaw-risks
147
+ Allow unverified OpenClaw community skills
148
+
149
+ ${BOLD}Remove Options:${RESET}
150
+ -g, --global Remove from global scope
151
+ -a, --agent <agents> Remove from specific agents (use '*' for all agents)
152
+ -s, --skill <skills> Specify skills to remove (use '*' for all skills)
153
+ -y, --yes Skip confirmation prompts
154
+ --all Shorthand for --skill '*' --agent '*' -y
155
+
156
+ ${BOLD}Experimental Sync Options:${RESET}
157
+ -a, --agent <agents> Specify agents to install to (use '*' for all agents)
158
+ -y, --yes Skip confirmation prompts
159
+
160
+ ${BOLD}List Options:${RESET}
161
+ -g, --global List global skills (default: project)
162
+ -a, --agent <agents> Filter by specific agents
163
+ --json Output as JSON (machine-readable, no ANSI codes)
164
+
165
+ ${BOLD}Options:${RESET}
166
+ --help, -h Show this help message
167
+ --version, -v Show version number
168
+
169
+ ${BOLD}Examples:${RESET}
170
+ ${DIM}$${RESET} skills add vercel-labs/agent-skills
171
+ ${DIM}$${RESET} skills use vercel-labs/agent-skills@vercel-optimize | claude
172
+ ${DIM}$${RESET} skills use vercel-labs/agent-skills --skill vercel-optimize --agent claude-code
173
+ ${DIM}$${RESET} skills add vercel-labs/agent-skills -g
174
+ ${DIM}$${RESET} skills add vercel-labs/agent-skills --agent claude-code cursor
175
+ ${DIM}$${RESET} skills add vercel-labs/agent-skills --skill pr-review commit
176
+ ${DIM}$${RESET} skills remove ${DIM}# interactive remove${RESET}
177
+ ${DIM}$${RESET} skills remove web-design ${DIM}# remove by name${RESET}
178
+ ${DIM}$${RESET} skills rm --global frontend-design
179
+ ${DIM}$${RESET} skills list ${DIM}# list project skills${RESET}
180
+ ${DIM}$${RESET} skills ls -g ${DIM}# list global skills${RESET}
181
+ ${DIM}$${RESET} skills ls -a claude-code ${DIM}# filter by agent${RESET}
182
+ ${DIM}$${RESET} skills ls --json ${DIM}# JSON output${RESET}
183
+ ${DIM}$${RESET} skills find ${DIM}# interactive search${RESET}
184
+ ${DIM}$${RESET} skills find typescript ${DIM}# search by keyword${RESET}
185
+ ${DIM}$${RESET} skills update
186
+ ${DIM}$${RESET} skills update my-skill ${DIM}# update a single skill${RESET}
187
+ ${DIM}$${RESET} skills update -g ${DIM}# update global skills only${RESET}
188
+ ${DIM}$${RESET} skills experimental_install ${DIM}# restore from skills-lock.json${RESET}
189
+ ${DIM}$${RESET} skills init my-skill
190
+ ${DIM}$${RESET} skills experimental_sync ${DIM}# sync from node_modules${RESET}
191
+ ${DIM}$${RESET} skills experimental_sync -y ${DIM}# sync without prompts${RESET}
192
+
193
+ Discover more skills at ${TEXT}https://skills.sh/${RESET}
194
+ `);
195
+ }
196
+
197
+ function showRemoveHelp(): void {
198
+ console.log(`
199
+ ${BOLD}Usage:${RESET} skills remove [skills...] [options]
200
+
201
+ ${BOLD}Description:${RESET}
202
+ Remove installed skills from agents. If no skill names are provided,
203
+ an interactive selection menu will be shown.
204
+
205
+ ${BOLD}Arguments:${RESET}
206
+ skills Optional skill names to remove (space-separated)
207
+
208
+ ${BOLD}Options:${RESET}
209
+ -g, --global Remove from global scope (~/) instead of project scope
210
+ -a, --agent Remove from specific agents (use '*' for all agents)
211
+ -s, --skill Specify skills to remove (use '*' for all skills)
212
+ -y, --yes Skip confirmation prompts
213
+ --all Shorthand for --skill '*' --agent '*' -y
214
+
215
+ ${BOLD}Examples:${RESET}
216
+ ${DIM}$${RESET} skills remove ${DIM}# interactive selection${RESET}
217
+ ${DIM}$${RESET} skills remove my-skill ${DIM}# remove specific skill${RESET}
218
+ ${DIM}$${RESET} skills remove skill1 skill2 -y ${DIM}# remove multiple skills${RESET}
219
+ ${DIM}$${RESET} skills remove --global my-skill ${DIM}# remove from global scope${RESET}
220
+ ${DIM}$${RESET} skills rm --agent claude-code my-skill ${DIM}# remove from specific agent${RESET}
221
+ ${DIM}$${RESET} skills remove --all ${DIM}# remove all skills${RESET}
222
+ ${DIM}$${RESET} skills remove --skill '*' -a cursor ${DIM}# remove all skills from cursor${RESET}
223
+
224
+ Discover more skills at ${TEXT}https://skills.sh/${RESET}
225
+ `);
226
+ }
227
+
228
+ function runInit(args: string[]): void {
229
+ const cwd = process.cwd();
230
+ const skillName = args[0] || basename(cwd);
231
+ const hasName = args[0] !== undefined;
232
+
233
+ const skillDir = hasName ? join(cwd, skillName) : cwd;
234
+ const skillFile = join(skillDir, 'SKILL.md');
235
+ const displayPath = hasName ? `${skillName}/SKILL.md` : 'SKILL.md';
236
+
237
+ if (existsSync(skillFile)) {
238
+ console.log(`${TEXT}Skill already exists at ${DIM}${displayPath}${RESET}`);
239
+ return;
240
+ }
241
+
242
+ if (hasName) {
243
+ mkdirSync(skillDir, { recursive: true });
244
+ }
245
+
246
+ const skillContent = `---
247
+ name: ${skillName}
248
+ description: A brief description of what this skill does
249
+ ---
250
+
251
+ # ${skillName}
252
+
253
+ Instructions for the agent to follow when this skill is activated.
254
+
255
+ ## When to use
256
+
257
+ Describe when this skill should be used.
258
+
259
+ ## Instructions
260
+
261
+ 1. First step
262
+ 2. Second step
263
+ 3. Additional steps as needed
264
+ `;
265
+
266
+ writeFileSync(skillFile, skillContent);
267
+
268
+ console.log(`${TEXT}Initialized skill: ${DIM}${skillName}${RESET}`);
269
+ console.log();
270
+ console.log(`${DIM}Created:${RESET}`);
271
+ console.log(` ${displayPath}`);
272
+ console.log();
273
+ console.log(`${DIM}Next steps:${RESET}`);
274
+ console.log(` 1. Edit ${TEXT}${displayPath}${RESET} to define your skill instructions`);
275
+ console.log(
276
+ ` 2. Update the ${TEXT}name${RESET} and ${TEXT}description${RESET} in the frontmatter`
277
+ );
278
+ console.log();
279
+ console.log(`${DIM}Publishing:${RESET}`);
280
+ console.log(
281
+ ` ${DIM}GitHub:${RESET} Push to a repo, then ${TEXT}npx skills add <owner>/<repo>${RESET}`
282
+ );
283
+ console.log(
284
+ ` ${DIM}URL:${RESET} Host the file, then ${TEXT}npx skills add https://example.com/${displayPath}${RESET}`
285
+ );
286
+ console.log();
287
+ console.log(`Browse existing skills for inspiration at ${TEXT}https://skills.sh/${RESET}`);
288
+ console.log();
289
+ }
290
+
291
+ // ============================================
292
+ // Main
293
+ // ============================================
294
+
295
+ async function main(): Promise<void> {
296
+ const args = process.argv.slice(2);
297
+ const inAgent = await isRunningInAgent();
298
+
299
+ if (args.length === 0) {
300
+ if (!inAgent) {
301
+ showBanner();
302
+ }
303
+ return;
304
+ }
305
+
306
+ const command = args[0];
307
+ const restArgs = args.slice(1);
308
+
309
+ switch (command) {
310
+ case 'find':
311
+ case 'search':
312
+ case 'f':
313
+ case 's':
314
+ if (!inAgent) showLogo();
315
+ console.log();
316
+ await runFind(restArgs);
317
+ break;
318
+ case 'init':
319
+ if (!inAgent) showLogo();
320
+ console.log();
321
+ runInit(restArgs);
322
+ break;
323
+ case 'experimental_install': {
324
+ if (!inAgent) showLogo();
325
+ await runInstallFromLock(restArgs);
326
+ break;
327
+ }
328
+ case 'i':
329
+ case 'install':
330
+ case 'a':
331
+ case 'add': {
332
+ if (!inAgent) showLogo();
333
+ const { source: addSource, options: addOpts } = parseAddOptions(restArgs);
334
+ await runAdd(addSource, addOpts);
335
+ break;
336
+ }
337
+ case 'use': {
338
+ const {
339
+ source: useSource,
340
+ options: useOptions,
341
+ errors: useErrors,
342
+ } = parseUseOptions(restArgs);
343
+ await runUse(useSource, useOptions, useErrors);
344
+ break;
345
+ }
346
+ case 'remove':
347
+ case 'rm':
348
+ case 'r':
349
+ // Check for --help or -h flag
350
+ if (restArgs.includes('--help') || restArgs.includes('-h')) {
351
+ showRemoveHelp();
352
+ break;
353
+ }
354
+ const { skills, options: removeOptions } = parseRemoveOptions(restArgs);
355
+ await removeCommand(skills, removeOptions);
356
+ break;
357
+ case 'experimental_sync': {
358
+ if (!inAgent) showLogo();
359
+ const { options: syncOptions } = parseSyncOptions(restArgs);
360
+ await runSync(restArgs, syncOptions);
361
+ break;
362
+ }
363
+ case 'list':
364
+ case 'ls':
365
+ await runList(restArgs);
366
+ break;
367
+ case 'check':
368
+ case 'update':
369
+ case 'upgrade':
370
+ await runUpdate(restArgs);
371
+ break;
372
+ case '--help':
373
+ case '-h':
374
+ showHelp();
375
+ break;
376
+ case '--version':
377
+ case '-v':
378
+ console.log(VERSION);
379
+ break;
380
+
381
+ default:
382
+ console.log(`Unknown command: ${command}`);
383
+ console.log(`Run ${BOLD}skills --help${RESET} for usage.`);
384
+ }
385
+ }
386
+
387
+ main().finally(() => flushTelemetry().then(() => process.exit(0)));
@@ -0,0 +1,3 @@
1
+ export const AGENTS_DIR = '.agents';
2
+ export const SKILLS_SUBDIR = 'skills';
3
+ export const UNIVERSAL_SKILLS_DIR = '.agents/skills';
@@ -0,0 +1,62 @@
1
+ import { determineAgent, type AgentResult } from '@vercel/detect-agent';
2
+ import { setDetectedAgent } from './telemetry.ts';
3
+ import type { AgentType } from './types.ts';
4
+
5
+ let cachedResult: AgentResult | null = null;
6
+
7
+ /**
8
+ * Map from @vercel/detect-agent names to skills-cli AgentType identifiers.
9
+ * Only includes agents that exist in both systems.
10
+ */
11
+ const agentNameToType: Record<string, AgentType> = {
12
+ cursor: 'cursor',
13
+ 'cursor-cli': 'cursor',
14
+ claude: 'claude-code',
15
+ cowork: 'claude-code',
16
+ devin: 'universal', // Devin not in skills-cli agent list, use universal
17
+ replit: 'replit',
18
+ gemini: 'gemini-cli',
19
+ codex: 'codex',
20
+ antigravity: 'antigravity',
21
+ 'augment-cli': 'augment',
22
+ opencode: 'opencode',
23
+ 'github-copilot': 'github-copilot',
24
+ };
25
+
26
+ /**
27
+ * Detect if the CLI is being run inside an AI agent environment.
28
+ * Results are cached after the first call. Also updates telemetry with the agent name.
29
+ */
30
+ export async function detectAgent(): Promise<AgentResult> {
31
+ if (cachedResult) return cachedResult;
32
+ cachedResult = await determineAgent();
33
+ if (cachedResult.isAgent) {
34
+ setDetectedAgent(cachedResult.agent.name);
35
+ }
36
+ return cachedResult;
37
+ }
38
+
39
+ /**
40
+ * Returns true if the CLI is running inside a detected AI agent.
41
+ * When true, the CLI should skip interactive prompts and use sensible defaults.
42
+ */
43
+ export async function isRunningInAgent(): Promise<boolean> {
44
+ const result = await detectAgent();
45
+ return result.isAgent;
46
+ }
47
+
48
+ /**
49
+ * Returns the name of the detected agent, or null if not running in an agent.
50
+ */
51
+ export async function getAgentName(): Promise<string | null> {
52
+ const result = await detectAgent();
53
+ return result.isAgent ? result.agent.name : null;
54
+ }
55
+
56
+ /**
57
+ * Maps a detected agent name to the corresponding skills-cli AgentType.
58
+ * Returns null if the agent can't be mapped to a specific skills-cli agent.
59
+ */
60
+ export function getAgentType(agentName: string): AgentType | null {
61
+ return agentNameToType[agentName] ?? null;
62
+ }