setup-project-skills
Installs skills into the current project from a manifest the user maintains. Distinct from claude-automation-recommender (which advises across hooks/MCP/subagents/skills/plugins and does not install) and from find-skills (which discovers public skills). This skill is opinionated: it installs only what's on the user's whitelist.
When to invoke
- "Set up skills for this project."
- "Bootstrap this repo with my skills."
- "What skills should I install here?" — the project-detection pass answers that from the manifest.
- "Link/install/add
<name>here." - Fresh
git clonefollowed by a session in the new directory.
When NOT to invoke
- User is actually doing terraform/k8s/docker/etc. work — the underlying skills handle that.
- User wants a recommendation across the full Claude Code surface (hooks, subagents, MCP, plugins) — that's
claude-automation-recommender. - User wants to discover what skills exist on the public registry — that's
find-skills. - User wants to author a new skill — that's
skill-creator.
Cross-cutting rules
- The manifest is the source of truth. Always read
~/.claude/skill-manifest.json(or$SKILL_MANIFESTif set). Never invent skills not listed there. If a skill the user names isn't in the manifest, offer to add it rather than installing ad-hoc. - Project-scoped install only. Always link or install into
./.claude/skills/<name>of the current working directory. Never into~/.claude/skills/from this skill — that's the user's global decision. - Idempotent. If
./.claude/skills/<name>already exists, check whether it matches the desired target. Skip if identical; refuse and surface the conflict if not. - Restart required. Skills installed mid-session don't activate until the next Claude Code session starts in this project. Always say so after a successful install.
- No slash commands. Claude can't invoke
/plugin install. Forclaude-pluginsources, print the exact command for the user to run themselves.
Manifest schema
{
"version": 1,
"skills": [
{
"name": "<short-id>",
"source": "local-symlink | npx-skills | claude-plugin",
"path": "<absolute or ~ path>", // for local-symlink
"repo": "<owner/repo[/subpath]>", // for npx-skills
"plugin": "<plugin@marketplace>", // for claude-plugin
"tags": ["..."],
"detect": ["glob", "glob:substring", "..."],
"note": "<optional user-facing hint>"
}
]
}
detect entries are glob patterns. A trailing :<substring> requires that substring to appear inside any matching file (cheap grep). Examples:
**/*.tf— any Terraform file**/*.tf:google_— Terraform file containing the substringgoogle_package.json:"react"— package.json that mentions"react"
Procedure
Step 1 — Locate and validate the manifest
MANIFEST="${SKILL_MANIFEST:-$HOME/.claude/skill-manifest.json}"
test -f "$MANIFEST" || { echo "Manifest not found at $MANIFEST"; exit 1; }
python3 -c "import json,sys; json.load(open('$MANIFEST'))" || { echo "Manifest is not valid JSON"; exit 1; }
If missing or invalid, offer to create a minimal one and stop.
Step 2 — Detect matches against the current project
For each skill, evaluate its detect patterns against the current working directory. Use find for plain globs and grep -l for glob:substring form. Mark every skill that matches at least one pattern as recommended.
If the project is empty (no entries in ls -A), skip detection — present the full catalog and ask which to install.
Step 3 — Present and confirm
Show the user a table grouped by status:
RECOMMENDED (detected in this project)
[x] cloudflare-cf-cli — wrangler.jsonc found
[x] docker-workflows — Dockerfile found
[x] github-actions-pipelines — .github/workflows/deploy.yml found
OPTIONAL (in your manifest, not detected)
[ ] terraform-workflows
[ ] kubernetes-operations
...
Pre-check the recommended ones. Ask the user to confirm or amend the selection before installing anything. Honor an explicit user request that contradicts detection (e.g. "actually also install terraform-workflows").
Step 4 — Install each selected skill by source
Always create the target directory first: mkdir -p .claude/skills.
local-symlink — symlink the path into .claude/skills/<name>:
TARGET="$(python3 -c 'import os,sys; print(os.path.expanduser(sys.argv[1]))' "<path-from-manifest>")"
LINK=".claude/skills/<name>"
test -d "$TARGET" || { echo "Source missing: $TARGET"; exit 1; }
if [ -L "$LINK" ]; then
current=$(readlink "$LINK")
[ "$current" = "$TARGET" ] && { echo "$<name> already linked — skip"; }
[ "$current" != "$TARGET" ] && { echo "$LINK points elsewhere — resolve manually"; exit 1; }
elif [ -e "$LINK" ]; then
echo "$LINK exists and is not a symlink — refusing"; exit 1
else
ln -s "$TARGET" "$LINK" && echo "Linked $<name>"
fi
npx-skills — fetch into the project's skills directory (NOT global):
# `npx skills add` defaults to project scope (./.claude/skills/) when run without -g
npx skills add "<repo-from-manifest>"
npx skills add copies files; updates require npx skills update later. Mention this when installing.
claude-plugin — Claude can't trigger slash commands. Tell the user to run it themselves:
Run this command yourself (Claude can't invoke slash commands):
/plugin install <plugin>
Include any note field from the manifest.
Step 5 — Post-install
After each successful install:
- Print a one-line confirmation.
- After all installs, remind the user to restart the session.
- If a
.gitignoreexists and doesn't already cover.claude/skills/, ask whether to add it. Symlinks to absolute user-machine paths shouldn't be committed; copies fromnpx skills addmay or may not be wanted in the repo — let the user decide.
Adding new skills to the manifest
When the user says "I found a new skill on skills.sh, add it to my manifest" or similar:
- Confirm
sourcetype (most oftennpx-skillsfor skills.sh entries, orclaude-pluginfor Claude Code marketplace plugins). - Confirm the repo/plugin identifier.
- Ask for
tagsanddetectpatterns — the user's project-detection signals. - Append to
~/.claude/skill-manifest.json(preserve formatting and trailing newline). - Validate JSON before writing back.
This is the only modification this skill makes outside the project directory.
Anti-patterns
- ❌ Installing a skill not in the manifest without first offering to add it.
- ❌ Linking into
~/.claude/skills/from this skill — global is the user's explicit choice. - ❌ Running
npx skills add -ghere — that's global, not project-scoped. - ❌ Attempting
/plugin installvia Bash — Claude can't invoke slash commands; print the instruction. - ❌ Overwriting an existing symlink or directory without confirming.
- ❌ Forgetting to remind the user to restart the session.
- ❌ Recommending skills based on Claude's general knowledge instead of the manifest — that's
claude-automation-recommender's job. - ❌ Copying skill content into the project instead of symlinking when source is
local-symlink— defeats the live-edit benefit.
Cross-skill notes
claude-automation-recommender(claude-code-setup plugin): broader codebase-aware advisor across hooks, subagents, MCP, plugins, and skills. Read-only. Useful BEFORE this skill — surfaces new ideas; you then add the good ones to the manifest.find-skills: discovers skills on the public registry. Use to find candidates worth adding to the manifest.skill-creator: for authoring new skills (which then get added to the manifest aslocal-symlink).devops-skill-link: deprecated — this skill subsumes its job. Safe to delete.