Skip to content
This repository was archived by the owner on Feb 1, 2026. It is now read-only.

Commit be5ff2d

Browse files
committed
Add Claude Code support to skillpack build and install scripts
- Add 'claude' target for project-level installation (.claude/skills/) - Add 'claude-global' target for user-level installation (~/.claude/skills/) - Add --global flag as shorthand for --targets=claude-global - Add --skills flag for selective skill installation - Add --list flag to show available skills - Add --dry-run flag to preview installation - Update README with Claude Code installation instructions
1 parent 2ad2599 commit be5ff2d

File tree

3 files changed

+227
-46
lines changed

3 files changed

+227
-46
lines changed

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,25 @@ Agent Skills solve this by giving AI assistants **expert-level WordPress knowled
3636

3737
## Quick Start
3838

39+
### Install globally for Claude Code
40+
41+
```bash
42+
# Clone agent-skills
43+
git clone https://github.com/Automattic/agent-skills.git
44+
cd agent-skills
45+
46+
# Build the distribution
47+
node shared/scripts/skillpack-build.mjs --clean
48+
49+
# Install all skills globally (available across all projects)
50+
node shared/scripts/skillpack-install.mjs --global
51+
52+
# Or install specific skills only
53+
node shared/scripts/skillpack-install.mjs --global --skills=wp-playground,wp-block-development
54+
```
55+
56+
This installs skills to `~/.claude/skills/` where Claude Code will automatically discover them.
57+
3958
### Install into your repo
4059

4160
```bash
@@ -47,12 +66,26 @@ cd agent-skills
4766
node shared/scripts/skillpack-build.mjs --clean
4867

4968
# Install into your WordPress project
50-
node shared/scripts/skillpack-install.mjs --dest=../your-wp-project --targets=codex,vscode
69+
node shared/scripts/skillpack-install.mjs --dest=../your-wp-project --targets=codex,vscode,claude
5170
```
5271

5372
This copies skills into:
5473
- `.codex/skills/` for OpenAI Codex
5574
- `.github/skills/` for VS Code / GitHub Copilot
75+
- `.claude/skills/` for Claude Code (project-level)
76+
77+
### Available options
78+
79+
```bash
80+
# List available skills
81+
node shared/scripts/skillpack-install.mjs --list
82+
83+
# Dry run (preview without installing)
84+
node shared/scripts/skillpack-install.mjs --global --dry-run
85+
86+
# Install specific skills to a project
87+
node shared/scripts/skillpack-install.mjs --dest=../my-repo --targets=claude --skills=wp-wpcli-and-ops
88+
```
5689

5790
### Manual installation
5891

shared/scripts/skillpack-build.mjs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ function usage() {
55
process.stderr.write(
66
[
77
"Usage:",
8-
" node shared/scripts/skillpack-build.mjs [--out=dist] [--targets=codex,vscode] [--clean]",
8+
" node shared/scripts/skillpack-build.mjs [--out=dist] [--targets=codex,vscode,claude] [--skills=skill1,skill2] [--clean]",
99
"",
1010
"Outputs:",
1111
" - <out>/codex/.codex/skills/<skill>/SKILL.md",
1212
" - <out>/vscode/.github/skills/<skill>/SKILL.md",
13+
" - <out>/claude/.claude/skills/<skill>/SKILL.md",
14+
"",
15+
"Options:",
16+
" --targets Comma-separated list of targets (codex, vscode, claude). Default: codex,vscode,claude",
17+
" --skills Comma-separated list of skill names to build. Default: all skills",
18+
" --clean Remove target directories before building",
1319
"",
1420
"Notes:",
1521
"- Avoids symlinks (Codex ignores symlinked directories).",
@@ -19,12 +25,13 @@ function usage() {
1925
}
2026

2127
function parseArgs(argv) {
22-
const args = { out: "dist", targets: ["codex", "vscode"], clean: false };
28+
const args = { out: "dist", targets: ["codex", "vscode", "claude"], skills: [], clean: false };
2329
for (const a of argv) {
2430
if (a === "--help" || a === "-h") args.help = true;
2531
else if (a === "--clean") args.clean = true;
2632
else if (a.startsWith("--out=")) args.out = a.slice("--out=".length);
2733
else if (a.startsWith("--targets=")) args.targets = a.slice("--targets=".length).split(",").filter(Boolean);
34+
else if (a.startsWith("--skills=")) args.skills = a.slice("--skills=".length).split(",").filter(Boolean);
2835
else {
2936
process.stderr.write(`Unknown arg: ${a}\n`);
3037
args.help = true;
@@ -91,6 +98,7 @@ function buildTarget({ repoRoot, outDir, target, skillDirs }) {
9198
const rootByTarget = {
9299
codex: path.join(outDir, "codex", ".codex", "skills"),
93100
vscode: path.join(outDir, "vscode", ".github", "skills"),
101+
claude: path.join(outDir, "claude", ".claude", "skills"),
94102
};
95103
const destSkillsRoot = rootByTarget[target];
96104
assert(destSkillsRoot, `Unknown target: ${target}`);
@@ -107,6 +115,8 @@ function buildTarget({ repoRoot, outDir, target, skillDirs }) {
107115
process.stdout.write(`OK: built ${target} skillpack at ${rel}\n`);
108116
}
109117

118+
const VALID_TARGETS = ["codex", "vscode", "claude"];
119+
110120
function main() {
111121
const args = parseArgs(process.argv.slice(2));
112122
if (args.help) {
@@ -118,23 +128,31 @@ function main() {
118128
const skillsRoot = path.join(repoRoot, "skills");
119129
const outDir = path.isAbsolute(args.out) ? args.out : path.join(repoRoot, args.out);
120130

121-
const skillDirs = listSkillDirs(skillsRoot);
131+
let skillDirs = listSkillDirs(skillsRoot);
122132
assert(skillDirs.length > 0, "No skills found under ./skills");
123133

134+
// Filter skills if --skills was specified
135+
if (args.skills.length > 0) {
136+
const requestedSkills = new Set(args.skills);
137+
const availableSkills = skillDirs.map((d) => path.basename(d));
138+
139+
// Validate requested skills exist
140+
for (const s of requestedSkills) {
141+
assert(availableSkills.includes(s), `Unknown skill: ${s}. Available: ${availableSkills.join(", ")}`);
142+
}
143+
144+
skillDirs = skillDirs.filter((d) => requestedSkills.has(path.basename(d)));
145+
}
146+
124147
const targets = [...new Set(args.targets)];
125148
for (const t of targets) {
126-
assert(t === "codex" || t === "vscode", `Invalid target: ${t}`);
149+
assert(VALID_TARGETS.includes(t), `Invalid target: ${t}. Valid targets: ${VALID_TARGETS.join(", ")}`);
127150
}
128151

129152
if (args.clean) {
130153
for (const t of targets) {
131-
const p =
132-
t === "codex"
133-
? path.join(outDir, "codex")
134-
: t === "vscode"
135-
? path.join(outDir, "vscode")
136-
: null;
137-
if (p) fs.rmSync(p, { recursive: true, force: true });
154+
const targetDir = path.join(outDir, t);
155+
fs.rmSync(targetDir, { recursive: true, force: true });
138156
}
139157
}
140158

0 commit comments

Comments
 (0)