@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.
- package/LICENSE +21 -0
- package/README.md +308 -0
- package/bin/adg.ts +758 -0
- package/docs/agents-spec.md +132 -0
- package/docs/authoring.md +352 -0
- package/package.json +50 -0
- package/schemas/adg-plugin.schema.json +77 -0
- package/schemas/marketplace.schema.json +86 -0
- package/schemas/plugin-lock.schema.json +90 -0
- package/src/adapters/anthropic.ts +54 -0
- package/src/adapters/index.ts +24 -0
- package/src/adapters/openai.ts +37 -0
- package/src/adapters/reverse.ts +60 -0
- package/src/agents/claude.ts +124 -0
- package/src/agents/codex.ts +67 -0
- package/src/agents/index.ts +12 -0
- package/src/agents/registry.ts +30 -0
- package/src/agents/types.ts +47 -0
- package/src/commands/adapt.ts +36 -0
- package/src/commands/import.ts +69 -0
- package/src/commands/init.ts +146 -0
- package/src/commands/install.ts +411 -0
- package/src/commands/link.ts +61 -0
- package/src/commands/list.ts +28 -0
- package/src/commands/marketplace.ts +198 -0
- package/src/commands/migrate.ts +84 -0
- package/src/commands/multiselect-skills.ts +137 -0
- package/src/commands/remove.ts +136 -0
- package/src/commands/select-agents.ts +45 -0
- package/src/commands/select-components.ts +66 -0
- package/src/commands/select-plugins.ts +28 -0
- package/src/commands/select-scope.ts +21 -0
- package/src/commands/update.ts +85 -0
- package/src/commands/validate.ts +57 -0
- package/src/components.ts +90 -0
- package/src/deps.ts +64 -0
- package/src/fsutil.ts +38 -0
- package/src/hash.ts +61 -0
- package/src/lock.ts +57 -0
- package/src/manifest.ts +113 -0
- package/src/marketplace.ts +41 -0
- package/src/package.ts +74 -0
- package/src/paths.ts +129 -0
- package/src/semver.ts +67 -0
- package/src/skills.ts +88 -0
- package/src/sources.ts +159 -0
- package/src/types.ts +140 -0
- package/vendor/skills/LICENSE +29 -0
- package/vendor/skills/PROVENANCE.md +60 -0
- package/vendor/skills/ThirdPartyNoticeText.txt +117 -0
- package/vendor/skills/package.json +143 -0
- package/vendor/skills/src/add.ts +1999 -0
- package/vendor/skills/src/agents.ts +755 -0
- package/vendor/skills/src/blob.ts +567 -0
- package/vendor/skills/src/cli.ts +387 -0
- package/vendor/skills/src/constants.ts +3 -0
- package/vendor/skills/src/detect-agent.ts +62 -0
- package/vendor/skills/src/find.ts +357 -0
- package/vendor/skills/src/frontmatter.ts +16 -0
- package/vendor/skills/src/git-tree.ts +36 -0
- package/vendor/skills/src/git.ts +277 -0
- package/vendor/skills/src/install.ts +91 -0
- package/vendor/skills/src/installer.ts +1097 -0
- package/vendor/skills/src/list.ts +231 -0
- package/vendor/skills/src/local-lock.ts +182 -0
- package/vendor/skills/src/plugin-manifest.ts +183 -0
- package/vendor/skills/src/prompts/search-multiselect.ts +387 -0
- package/vendor/skills/src/providers/index.ts +14 -0
- package/vendor/skills/src/providers/registry.ts +51 -0
- package/vendor/skills/src/providers/types.ts +97 -0
- package/vendor/skills/src/providers/wellknown.ts +804 -0
- package/vendor/skills/src/remove.ts +323 -0
- package/vendor/skills/src/sanitize.ts +65 -0
- package/vendor/skills/src/self-cli.ts +20 -0
- package/vendor/skills/src/skill-lock.ts +329 -0
- package/vendor/skills/src/skills.ts +316 -0
- package/vendor/skills/src/source-parser.ts +438 -0
- package/vendor/skills/src/sync.ts +478 -0
- package/vendor/skills/src/telemetry.ts +186 -0
- package/vendor/skills/src/test-utils.ts +73 -0
- package/vendor/skills/src/types.ts +128 -0
- package/vendor/skills/src/update-source.ts +90 -0
- package/vendor/skills/src/update.ts +749 -0
- 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,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
|
+
}
|