ai-agent-skills 1.6.1 → 1.7.0
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/README.md +17 -18
- package/cli.js +257 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,16 +29,14 @@
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
#
|
|
33
|
-
npx ai-agent-skills browse
|
|
34
|
-
|
|
35
|
-
# Install from our curated catalog
|
|
32
|
+
# Install a skill to ALL agents with one command
|
|
36
33
|
npx ai-agent-skills install frontend-design
|
|
37
34
|
|
|
38
|
-
# Install
|
|
35
|
+
# Install to a specific agent only
|
|
39
36
|
npx ai-agent-skills install frontend-design --agent cursor
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
|
|
38
|
+
# Browse skills interactively
|
|
39
|
+
npx ai-agent-skills browse
|
|
42
40
|
|
|
43
41
|
# Install from any GitHub repo
|
|
44
42
|
npx ai-agent-skills install anthropics/skills
|
|
@@ -48,7 +46,7 @@ npx ai-agent-skills install anthropics/skills/pdf # specific skill
|
|
|
48
46
|
npx ai-agent-skills install ./my-custom-skill
|
|
49
47
|
```
|
|
50
48
|
|
|
51
|
-
|
|
49
|
+
**One command. Every agent.** By default, skills install to Claude Code, Cursor, Codex, Amp, VS Code, Copilot, Goose, Letta, and OpenCode simultaneously.
|
|
52
50
|
|
|
53
51
|
## Why This Exists
|
|
54
52
|
|
|
@@ -58,7 +56,7 @@ This repo curates the best in one place. Quality over quantity. All skills follo
|
|
|
58
56
|
|
|
59
57
|
## Compatible Agents
|
|
60
58
|
|
|
61
|
-
Works with **Claude Code**, **Cursor**, **Amp**, **VS Code**, **GitHub Copilot**, **Goose**, **Letta**,
|
|
59
|
+
Works with **Claude Code**, **Cursor**, **Codex**, **Amp**, **VS Code**, **GitHub Copilot**, **Goose**, **Letta**, and **OpenCode**.
|
|
62
60
|
|
|
63
61
|
## Available Skills
|
|
64
62
|
|
|
@@ -133,12 +131,11 @@ npx ai-agent-skills list
|
|
|
133
131
|
npx ai-agent-skills list --category development
|
|
134
132
|
npx ai-agent-skills list --installed --agent cursor
|
|
135
133
|
|
|
136
|
-
# Install
|
|
137
|
-
npx ai-agent-skills install <name> #
|
|
138
|
-
npx ai-agent-skills install <
|
|
139
|
-
npx ai-agent-skills install <owner/repo
|
|
140
|
-
npx ai-agent-skills install ./path # from local path
|
|
141
|
-
npx ai-agent-skills install <name> --agent cursor # for specific agent
|
|
134
|
+
# Install (defaults to ALL agents)
|
|
135
|
+
npx ai-agent-skills install <name> # installs to ALL agents
|
|
136
|
+
npx ai-agent-skills install <name> --agent cursor # install to specific agent only
|
|
137
|
+
npx ai-agent-skills install <owner/repo> # from GitHub (all agents)
|
|
138
|
+
npx ai-agent-skills install ./path # from local path (all agents)
|
|
142
139
|
npx ai-agent-skills install <name> --dry-run # preview only
|
|
143
140
|
|
|
144
141
|
# Manage installed skills
|
|
@@ -156,15 +153,17 @@ npx ai-agent-skills config --default-agent cursor
|
|
|
156
153
|
|
|
157
154
|
### Supported Agents
|
|
158
155
|
|
|
156
|
+
By default, `install` targets **all agents**. Use `--agent <name>` to install to a specific one.
|
|
157
|
+
|
|
159
158
|
| Agent | Flag | Install Location |
|
|
160
159
|
|-------|------|------------------|
|
|
161
|
-
| Claude Code | `--agent claude`
|
|
160
|
+
| Claude Code | `--agent claude` | `~/.claude/skills/` |
|
|
162
161
|
| Cursor | `--agent cursor` | `.cursor/skills/` |
|
|
162
|
+
| Codex | `--agent codex` | `~/.codex/skills/` |
|
|
163
163
|
| Amp | `--agent amp` | `~/.amp/skills/` |
|
|
164
164
|
| VS Code / Copilot | `--agent vscode` | `.github/skills/` |
|
|
165
165
|
| Goose | `--agent goose` | `~/.config/goose/skills/` |
|
|
166
|
-
| OpenCode | `--agent opencode` | `~/.opencode/
|
|
167
|
-
| Codex | `--agent codex` | `~/.codex/skills/` |
|
|
166
|
+
| OpenCode | `--agent opencode` | `~/.opencode/skill/` |
|
|
168
167
|
| Letta | `--agent letta` | `~/.letta/skills/` |
|
|
169
168
|
| Portable | `--agent project` | `.skills/` (works with any agent) |
|
|
170
169
|
|
package/cli.js
CHANGED
|
@@ -24,7 +24,7 @@ const AGENT_PATHS = {
|
|
|
24
24
|
copilot: path.join(process.cwd(), '.github', 'skills'),
|
|
25
25
|
project: path.join(process.cwd(), '.skills'),
|
|
26
26
|
goose: path.join(os.homedir(), '.config', 'goose', 'skills'),
|
|
27
|
-
opencode: path.join(os.homedir(), '.opencode', 'skill'),
|
|
27
|
+
opencode: path.join(os.homedir(), '.config', 'opencode', 'skill'),
|
|
28
28
|
codex: path.join(os.homedir(), '.codex', 'skills'),
|
|
29
29
|
letta: path.join(os.homedir(), '.letta', 'skills'),
|
|
30
30
|
};
|
|
@@ -70,6 +70,41 @@ function saveConfig(config) {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
// ============ SKILL METADATA SUPPORT ============
|
|
74
|
+
|
|
75
|
+
const SKILL_META_FILE = '.skill-meta.json';
|
|
76
|
+
|
|
77
|
+
function writeSkillMeta(skillPath, meta) {
|
|
78
|
+
try {
|
|
79
|
+
const metaPath = path.join(skillPath, SKILL_META_FILE);
|
|
80
|
+
const now = new Date().toISOString();
|
|
81
|
+
const metadata = {
|
|
82
|
+
...meta,
|
|
83
|
+
// Preserve original installedAt if it exists, otherwise set it
|
|
84
|
+
installedAt: meta.installedAt || now,
|
|
85
|
+
// Always update the updatedAt timestamp
|
|
86
|
+
updatedAt: now
|
|
87
|
+
};
|
|
88
|
+
fs.writeFileSync(metaPath, JSON.stringify(metadata, null, 2));
|
|
89
|
+
return true;
|
|
90
|
+
} catch (e) {
|
|
91
|
+
// Non-fatal - skill still works without metadata
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function readSkillMeta(skillPath) {
|
|
97
|
+
try {
|
|
98
|
+
const metaPath = path.join(skillPath, SKILL_META_FILE);
|
|
99
|
+
if (fs.existsSync(metaPath)) {
|
|
100
|
+
return JSON.parse(fs.readFileSync(metaPath, 'utf8'));
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {
|
|
103
|
+
// Ignore - treat as legacy skill
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
73
108
|
// ============ SECURITY VALIDATION ============
|
|
74
109
|
|
|
75
110
|
function validateSkillName(name) {
|
|
@@ -151,6 +186,7 @@ function parseArgs(args) {
|
|
|
151
186
|
param: null,
|
|
152
187
|
agents: [], // New: array of agents
|
|
153
188
|
allAgents: false, // New: --all-agents flag
|
|
189
|
+
explicitAgent: false, // Track if user explicitly specified agent(s)
|
|
154
190
|
installed: false,
|
|
155
191
|
all: false,
|
|
156
192
|
dryRun: false,
|
|
@@ -163,6 +199,7 @@ function parseArgs(args) {
|
|
|
163
199
|
|
|
164
200
|
// --agents claude,cursor,codex (multiple agents)
|
|
165
201
|
if (arg === '--agents') {
|
|
202
|
+
result.explicitAgent = true;
|
|
166
203
|
const value = args[i + 1] || '';
|
|
167
204
|
value.split(',').forEach(a => {
|
|
168
205
|
const agent = a.trim();
|
|
@@ -174,6 +211,7 @@ function parseArgs(args) {
|
|
|
174
211
|
}
|
|
175
212
|
// --agent cursor (single agent, backward compatible)
|
|
176
213
|
else if (arg === '--agent' || arg === '-a') {
|
|
214
|
+
result.explicitAgent = true;
|
|
177
215
|
let agentValue = args[i + 1] || defaultAgent;
|
|
178
216
|
agentValue = agentValue.replace(/^-+/, '');
|
|
179
217
|
if (validAgents.includes(agentValue) && !result.agents.includes(agentValue)) {
|
|
@@ -183,6 +221,7 @@ function parseArgs(args) {
|
|
|
183
221
|
}
|
|
184
222
|
// --all-agents (install to all known agents)
|
|
185
223
|
else if (arg === '--all-agents') {
|
|
224
|
+
result.explicitAgent = true;
|
|
186
225
|
result.allAgents = true;
|
|
187
226
|
}
|
|
188
227
|
else if (arg === '--installed' || arg === '-i') {
|
|
@@ -205,6 +244,7 @@ function parseArgs(args) {
|
|
|
205
244
|
else if (arg.startsWith('--')) {
|
|
206
245
|
const potentialAgent = arg.replace(/^--/, '');
|
|
207
246
|
if (validAgents.includes(potentialAgent)) {
|
|
247
|
+
result.explicitAgent = true;
|
|
208
248
|
if (!result.agents.includes(potentialAgent)) {
|
|
209
249
|
result.agents.push(potentialAgent);
|
|
210
250
|
}
|
|
@@ -362,6 +402,12 @@ function installSkill(skillName, agent = 'claude', dryRun = false) {
|
|
|
362
402
|
|
|
363
403
|
copyDir(sourcePath, destPath);
|
|
364
404
|
|
|
405
|
+
// Write metadata for update tracking
|
|
406
|
+
writeSkillMeta(destPath, {
|
|
407
|
+
source: 'registry',
|
|
408
|
+
name: skillName
|
|
409
|
+
});
|
|
410
|
+
|
|
365
411
|
success(`\nInstalled: ${skillName}`);
|
|
366
412
|
info(`Agent: ${agent}`);
|
|
367
413
|
info(`Location: ${destPath}`);
|
|
@@ -469,32 +515,133 @@ function listInstalledSkills(agent = 'claude') {
|
|
|
469
515
|
log(`${colors.dim}Uninstall: npx ai-agent-skills uninstall <name> --agent ${agent}${colors.reset}`);
|
|
470
516
|
}
|
|
471
517
|
|
|
472
|
-
|
|
518
|
+
// Update from bundled registry
|
|
519
|
+
function updateFromRegistry(skillName, agent, destPath, dryRun) {
|
|
520
|
+
const sourcePath = path.join(SKILLS_DIR, skillName);
|
|
521
|
+
|
|
522
|
+
if (!fs.existsSync(sourcePath)) {
|
|
523
|
+
error(`Skill "${skillName}" not found in repository.`);
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (dryRun) {
|
|
528
|
+
log(`\n${colors.bold}Dry Run${colors.reset} (no changes made)\n`);
|
|
529
|
+
info(`Would update: ${skillName} (from registry)`);
|
|
530
|
+
info(`Agent: ${agent}`);
|
|
531
|
+
info(`Path: ${destPath}`);
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
|
|
473
535
|
try {
|
|
474
|
-
|
|
536
|
+
fs.rmSync(destPath, { recursive: true });
|
|
537
|
+
copyDir(sourcePath, destPath);
|
|
538
|
+
|
|
539
|
+
// Write metadata
|
|
540
|
+
writeSkillMeta(destPath, {
|
|
541
|
+
source: 'registry',
|
|
542
|
+
name: skillName
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
success(`\nUpdated: ${skillName}`);
|
|
546
|
+
info(`Agent: ${agent}`);
|
|
547
|
+
info(`Location: ${destPath}`);
|
|
548
|
+
return true;
|
|
475
549
|
} catch (e) {
|
|
476
|
-
error(e.message);
|
|
550
|
+
error(`Failed to update skill: ${e.message}`);
|
|
477
551
|
return false;
|
|
478
552
|
}
|
|
553
|
+
}
|
|
479
554
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
const
|
|
555
|
+
// Update from GitHub repository
|
|
556
|
+
function updateFromGitHub(meta, skillName, agent, destPath, dryRun) {
|
|
557
|
+
const { execFileSync } = require('child_process');
|
|
558
|
+
const repo = meta.repo;
|
|
559
|
+
|
|
560
|
+
// Validate repo format
|
|
561
|
+
if (!repo || typeof repo !== 'string' || !repo.includes('/')) {
|
|
562
|
+
error(`Invalid repository in metadata: ${repo}`);
|
|
563
|
+
error(`Try reinstalling the skill from GitHub.`);
|
|
564
|
+
return false;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (dryRun) {
|
|
568
|
+
log(`\n${colors.bold}Dry Run${colors.reset} (no changes made)\n`);
|
|
569
|
+
info(`Would update: ${skillName} (from github:${repo})`);
|
|
570
|
+
info(`Agent: ${agent}`);
|
|
571
|
+
info(`Path: ${destPath}`);
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
const tempDir = path.join(os.tmpdir(), `ai-skills-update-${Date.now()}`);
|
|
576
|
+
|
|
577
|
+
try {
|
|
578
|
+
info(`Updating ${skillName} from ${repo}...`);
|
|
579
|
+
const repoUrl = `https://github.com/${repo}.git`;
|
|
580
|
+
execFileSync('git', ['clone', '--depth', '1', repoUrl, tempDir], { stdio: 'pipe' });
|
|
581
|
+
|
|
582
|
+
// Determine source path in cloned repo
|
|
583
|
+
let sourcePath;
|
|
584
|
+
if (meta.isRootSkill) {
|
|
585
|
+
sourcePath = tempDir;
|
|
586
|
+
} else if (meta.skillPath) {
|
|
587
|
+
// Check if skills/ subdirectory exists
|
|
588
|
+
const skillsSubdir = path.join(tempDir, 'skills', meta.skillPath);
|
|
589
|
+
const directPath = path.join(tempDir, meta.skillPath);
|
|
590
|
+
sourcePath = fs.existsSync(skillsSubdir) ? skillsSubdir : directPath;
|
|
591
|
+
} else {
|
|
592
|
+
sourcePath = tempDir;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (!fs.existsSync(sourcePath) || !fs.existsSync(path.join(sourcePath, 'SKILL.md'))) {
|
|
596
|
+
error(`Skill not found in repository ${repo}`);
|
|
597
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
fs.rmSync(destPath, { recursive: true });
|
|
602
|
+
copyDir(sourcePath, destPath);
|
|
603
|
+
|
|
604
|
+
// Preserve metadata
|
|
605
|
+
writeSkillMeta(destPath, meta);
|
|
606
|
+
|
|
607
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
608
|
+
|
|
609
|
+
success(`\nUpdated: ${skillName}`);
|
|
610
|
+
info(`Source: github:${repo}`);
|
|
611
|
+
info(`Agent: ${agent}`);
|
|
612
|
+
info(`Location: ${destPath}`);
|
|
613
|
+
return true;
|
|
614
|
+
} catch (e) {
|
|
615
|
+
error(`Failed to update from GitHub: ${e.message}`);
|
|
616
|
+
try { fs.rmSync(tempDir, { recursive: true }); } catch {}
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Update from local path
|
|
622
|
+
function updateFromLocalPath(meta, skillName, agent, destPath, dryRun) {
|
|
623
|
+
const sourcePath = meta.path;
|
|
624
|
+
|
|
625
|
+
if (!sourcePath || typeof sourcePath !== 'string') {
|
|
626
|
+
error(`Invalid path in metadata.`);
|
|
627
|
+
error(`Try reinstalling the skill from the local path.`);
|
|
628
|
+
return false;
|
|
629
|
+
}
|
|
483
630
|
|
|
484
631
|
if (!fs.existsSync(sourcePath)) {
|
|
485
|
-
error(`
|
|
632
|
+
error(`Source path no longer exists: ${sourcePath}`);
|
|
486
633
|
return false;
|
|
487
634
|
}
|
|
488
635
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
636
|
+
// Verify it's still a valid skill directory
|
|
637
|
+
if (!fs.existsSync(path.join(sourcePath, 'SKILL.md'))) {
|
|
638
|
+
error(`Source is no longer a valid skill (missing SKILL.md): ${sourcePath}`);
|
|
492
639
|
return false;
|
|
493
640
|
}
|
|
494
641
|
|
|
495
642
|
if (dryRun) {
|
|
496
643
|
log(`\n${colors.bold}Dry Run${colors.reset} (no changes made)\n`);
|
|
497
|
-
info(`Would update: ${skillName}`);
|
|
644
|
+
info(`Would update: ${skillName} (from local:${sourcePath})`);
|
|
498
645
|
info(`Agent: ${agent}`);
|
|
499
646
|
info(`Path: ${destPath}`);
|
|
500
647
|
return true;
|
|
@@ -504,16 +651,57 @@ function updateSkill(skillName, agent = 'claude', dryRun = false) {
|
|
|
504
651
|
fs.rmSync(destPath, { recursive: true });
|
|
505
652
|
copyDir(sourcePath, destPath);
|
|
506
653
|
|
|
654
|
+
// Preserve metadata
|
|
655
|
+
writeSkillMeta(destPath, meta);
|
|
656
|
+
|
|
507
657
|
success(`\nUpdated: ${skillName}`);
|
|
658
|
+
info(`Source: local:${sourcePath}`);
|
|
508
659
|
info(`Agent: ${agent}`);
|
|
509
660
|
info(`Location: ${destPath}`);
|
|
510
661
|
return true;
|
|
511
662
|
} catch (e) {
|
|
512
|
-
error(`Failed to update
|
|
663
|
+
error(`Failed to update from local path: ${e.message}`);
|
|
513
664
|
return false;
|
|
514
665
|
}
|
|
515
666
|
}
|
|
516
667
|
|
|
668
|
+
function updateSkill(skillName, agent = 'claude', dryRun = false) {
|
|
669
|
+
try {
|
|
670
|
+
validateSkillName(skillName);
|
|
671
|
+
} catch (e) {
|
|
672
|
+
error(e.message);
|
|
673
|
+
return false;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
const destDir = AGENT_PATHS[agent] || AGENT_PATHS.claude;
|
|
677
|
+
const destPath = path.join(destDir, skillName);
|
|
678
|
+
|
|
679
|
+
if (!fs.existsSync(destPath)) {
|
|
680
|
+
error(`Skill "${skillName}" is not installed for ${agent}.`);
|
|
681
|
+
log(`\nUse 'install' to add it first.`);
|
|
682
|
+
return false;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Read metadata to determine source
|
|
686
|
+
const meta = readSkillMeta(destPath);
|
|
687
|
+
|
|
688
|
+
if (!meta) {
|
|
689
|
+
// Legacy skill without metadata - try registry
|
|
690
|
+
return updateFromRegistry(skillName, agent, destPath, dryRun);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// Route to correct update method based on source
|
|
694
|
+
switch (meta.source) {
|
|
695
|
+
case 'github':
|
|
696
|
+
return updateFromGitHub(meta, skillName, agent, destPath, dryRun);
|
|
697
|
+
case 'local':
|
|
698
|
+
return updateFromLocalPath(meta, skillName, agent, destPath, dryRun);
|
|
699
|
+
case 'registry':
|
|
700
|
+
default:
|
|
701
|
+
return updateFromRegistry(skillName, agent, destPath, dryRun);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
517
705
|
function updateAllSkills(agent = 'claude', dryRun = false) {
|
|
518
706
|
const installed = getInstalledSkills(agent);
|
|
519
707
|
|
|
@@ -905,6 +1093,14 @@ async function installFromGitHub(source, agent = 'claude', dryRun = false) {
|
|
|
905
1093
|
}
|
|
906
1094
|
|
|
907
1095
|
copyDir(skillPath, destPath);
|
|
1096
|
+
|
|
1097
|
+
// Write metadata for update tracking
|
|
1098
|
+
writeSkillMeta(destPath, {
|
|
1099
|
+
source: 'github',
|
|
1100
|
+
repo: `${owner}/${repo}`,
|
|
1101
|
+
skillPath: skillName
|
|
1102
|
+
});
|
|
1103
|
+
|
|
908
1104
|
success(`\nInstalled: ${skillName} from ${owner}/${repo}`);
|
|
909
1105
|
info(`Location: ${destPath}`);
|
|
910
1106
|
} else if (isRootSkill) {
|
|
@@ -928,6 +1124,14 @@ async function installFromGitHub(source, agent = 'claude', dryRun = false) {
|
|
|
928
1124
|
}
|
|
929
1125
|
|
|
930
1126
|
copyDir(tempDir, destPath);
|
|
1127
|
+
|
|
1128
|
+
// Write metadata for update tracking
|
|
1129
|
+
writeSkillMeta(destPath, {
|
|
1130
|
+
source: 'github',
|
|
1131
|
+
repo: `${owner}/${repo}`,
|
|
1132
|
+
isRootSkill: true
|
|
1133
|
+
});
|
|
1134
|
+
|
|
931
1135
|
success(`\nInstalled: ${skillName} from ${owner}/${repo}`);
|
|
932
1136
|
info(`Location: ${destPath}`);
|
|
933
1137
|
} else {
|
|
@@ -947,6 +1151,14 @@ async function installFromGitHub(source, agent = 'claude', dryRun = false) {
|
|
|
947
1151
|
}
|
|
948
1152
|
|
|
949
1153
|
copyDir(skillPath, destPath);
|
|
1154
|
+
|
|
1155
|
+
// Write metadata for update tracking
|
|
1156
|
+
writeSkillMeta(destPath, {
|
|
1157
|
+
source: 'github',
|
|
1158
|
+
repo: `${owner}/${repo}`,
|
|
1159
|
+
skillPath: entry.name
|
|
1160
|
+
});
|
|
1161
|
+
|
|
950
1162
|
log(` ${colors.green}✓${colors.reset} ${entry.name}`);
|
|
951
1163
|
installed++;
|
|
952
1164
|
}
|
|
@@ -1005,6 +1217,13 @@ function installFromLocalPath(source, agent = 'claude', dryRun = false) {
|
|
|
1005
1217
|
}
|
|
1006
1218
|
|
|
1007
1219
|
copyDir(sourcePath, destPath);
|
|
1220
|
+
|
|
1221
|
+
// Write metadata for update tracking
|
|
1222
|
+
writeSkillMeta(destPath, {
|
|
1223
|
+
source: 'local',
|
|
1224
|
+
path: sourcePath
|
|
1225
|
+
});
|
|
1226
|
+
|
|
1008
1227
|
success(`\nInstalled: ${skillName} from local path`);
|
|
1009
1228
|
info(`Location: ${destPath}`);
|
|
1010
1229
|
} else {
|
|
@@ -1024,6 +1243,13 @@ function installFromLocalPath(source, agent = 'claude', dryRun = false) {
|
|
|
1024
1243
|
}
|
|
1025
1244
|
|
|
1026
1245
|
copyDir(skillPath, destPath);
|
|
1246
|
+
|
|
1247
|
+
// Write metadata for update tracking
|
|
1248
|
+
writeSkillMeta(destPath, {
|
|
1249
|
+
source: 'local',
|
|
1250
|
+
path: skillPath
|
|
1251
|
+
});
|
|
1252
|
+
|
|
1027
1253
|
log(` ${colors.green}✓${colors.reset} ${entry.name}`);
|
|
1028
1254
|
installed++;
|
|
1029
1255
|
}
|
|
@@ -1055,7 +1281,8 @@ ${colors.bold}Commands:${colors.reset}
|
|
|
1055
1281
|
${colors.green}list${colors.reset} List all available skills
|
|
1056
1282
|
${colors.green}list --installed${colors.reset} List installed skills for an agent
|
|
1057
1283
|
${colors.green}list --category <cat>${colors.reset} Filter by category
|
|
1058
|
-
${colors.green}install <name>${colors.reset} Install
|
|
1284
|
+
${colors.green}install <name>${colors.reset} Install to ALL agents (default)
|
|
1285
|
+
${colors.green}install <name> --agent cursor${colors.reset} Install to specific agent only
|
|
1059
1286
|
${colors.green}install <owner/repo>${colors.reset} Install from GitHub repository
|
|
1060
1287
|
${colors.green}install ./path${colors.reset} Install from local path
|
|
1061
1288
|
${colors.green}install <name> --dry-run${colors.reset} Preview installation without changes
|
|
@@ -1069,39 +1296,36 @@ ${colors.bold}Commands:${colors.reset}
|
|
|
1069
1296
|
${colors.green}help${colors.reset} Show this help
|
|
1070
1297
|
|
|
1071
1298
|
${colors.bold}Options:${colors.reset}
|
|
1072
|
-
${colors.cyan}--agent <name>${colors.reset} Target
|
|
1299
|
+
${colors.cyan}--agent <name>${colors.reset} Target specific agent (install defaults to ALL)
|
|
1073
1300
|
${colors.cyan}--agents <list>${colors.reset} Target multiple agents (comma-separated)
|
|
1074
|
-
${colors.cyan}--all-agents${colors.reset} Target ALL known agents at once
|
|
1075
1301
|
${colors.cyan}--installed${colors.reset} Show only installed skills (with list)
|
|
1076
1302
|
${colors.cyan}--dry-run, -n${colors.reset} Preview changes without applying
|
|
1077
1303
|
${colors.cyan}--category <c>${colors.reset} Filter by category
|
|
1078
1304
|
${colors.cyan}--all${colors.reset} Apply to all (with update)
|
|
1079
1305
|
${colors.cyan}--version, -v${colors.reset} Show version number
|
|
1080
1306
|
|
|
1081
|
-
${colors.bold}Agents:${colors.reset}
|
|
1082
|
-
${colors.cyan}claude${colors.reset}
|
|
1083
|
-
${colors.cyan}cursor${colors.reset} .cursor/skills/
|
|
1307
|
+
${colors.bold}Agents:${colors.reset} (install targets ALL by default)
|
|
1308
|
+
${colors.cyan}claude${colors.reset} ~/.claude/skills/
|
|
1309
|
+
${colors.cyan}cursor${colors.reset} .cursor/skills/ (project)
|
|
1310
|
+
${colors.cyan}codex${colors.reset} ~/.codex/skills/
|
|
1084
1311
|
${colors.cyan}amp${colors.reset} ~/.amp/skills/
|
|
1085
|
-
${colors.cyan}vscode${colors.reset} .github/skills/
|
|
1312
|
+
${colors.cyan}vscode${colors.reset} .github/skills/ (project)
|
|
1086
1313
|
${colors.cyan}copilot${colors.reset} .github/skills/ (alias for vscode)
|
|
1087
1314
|
${colors.cyan}goose${colors.reset} ~/.config/goose/skills/
|
|
1088
1315
|
${colors.cyan}opencode${colors.reset} ~/.opencode/skill/
|
|
1089
|
-
${colors.cyan}codex${colors.reset} ~/.codex/skills/
|
|
1090
1316
|
${colors.cyan}letta${colors.reset} ~/.letta/skills/
|
|
1091
|
-
${colors.cyan}project${colors.reset} .skills/
|
|
1317
|
+
${colors.cyan}project${colors.reset} .skills/ (portable)
|
|
1092
1318
|
|
|
1093
1319
|
${colors.bold}Categories:${colors.reset}
|
|
1094
1320
|
development, document, creative, business, productivity
|
|
1095
1321
|
|
|
1096
1322
|
${colors.bold}Examples:${colors.reset}
|
|
1097
1323
|
npx ai-agent-skills browse # Interactive browser
|
|
1098
|
-
npx ai-agent-skills install frontend-design # Install
|
|
1324
|
+
npx ai-agent-skills install frontend-design # Install to ALL agents
|
|
1325
|
+
npx ai-agent-skills install pdf --agent cursor # Install to Cursor only
|
|
1326
|
+
npx ai-agent-skills install pdf --agents claude,cursor # Install to specific agents
|
|
1099
1327
|
npx ai-agent-skills install anthropics/skills # Install from GitHub
|
|
1100
|
-
npx ai-agent-skills install anthropics/skills/pdf # Install specific skill from GitHub
|
|
1101
1328
|
npx ai-agent-skills install ./my-skill # Install from local path
|
|
1102
|
-
npx ai-agent-skills install pdf --agent cursor # Install for Cursor
|
|
1103
|
-
npx ai-agent-skills install pdf --agents claude,cursor # Install for multiple agents
|
|
1104
|
-
npx ai-agent-skills install pdf --all-agents # Install for ALL agents
|
|
1105
1329
|
npx ai-agent-skills install pdf --dry-run # Preview install
|
|
1106
1330
|
npx ai-agent-skills list --category development
|
|
1107
1331
|
npx ai-agent-skills search testing
|
|
@@ -1207,7 +1431,8 @@ function setConfig(key, value) {
|
|
|
1207
1431
|
// ============ MAIN CLI ============
|
|
1208
1432
|
|
|
1209
1433
|
const args = process.argv.slice(2);
|
|
1210
|
-
const { command, param, agents, installed, dryRun, category, tags, all } = parseArgs(args);
|
|
1434
|
+
const { command, param, agents, explicitAgent, installed, dryRun, category, tags, all } = parseArgs(args);
|
|
1435
|
+
const ALL_AGENTS = Object.keys(AGENT_PATHS);
|
|
1211
1436
|
|
|
1212
1437
|
// Handle config commands specially
|
|
1213
1438
|
if (command === 'config') {
|
|
@@ -1252,11 +1477,12 @@ switch (command || 'help') {
|
|
|
1252
1477
|
case 'add':
|
|
1253
1478
|
if (!param) {
|
|
1254
1479
|
error('Please specify a skill name, GitHub repo, or local path.');
|
|
1255
|
-
log('Usage: npx ai-agent-skills install <name> [--
|
|
1480
|
+
log('Usage: npx ai-agent-skills install <name> [--agent cursor]');
|
|
1256
1481
|
process.exit(1);
|
|
1257
1482
|
}
|
|
1258
|
-
//
|
|
1259
|
-
|
|
1483
|
+
// Default to ALL agents when no agent explicitly specified
|
|
1484
|
+
const installTargets = explicitAgent ? agents : ALL_AGENTS;
|
|
1485
|
+
for (const agent of installTargets) {
|
|
1260
1486
|
if (isLocalPath(param)) {
|
|
1261
1487
|
installFromLocalPath(param, agent, dryRun);
|
|
1262
1488
|
} else if (isGitHubUrl(param)) {
|
package/package.json
CHANGED