Import Skill
Import skills from GitHub directory URLs or pasted content. Supports single-skill copy (preserves full directory structure) and multi-skill merge (intelligently combines into one).
Only public GitHub repositories are supported.
Speed Guidelines
This workflow involves multiple GitHub API calls and file writes. Minimize turns by following these rules:
- Batch independent API calls into single turns with parallel Bash calls
- Use
curlfor all GitHub content fetches — WebFetch summarizes HTML instead of returning raw content, making it unsuitable for fetching source files - Combine download + write with
curl -s URL > pathinstead of fetch-then-write-separately
Process
Step 1: Parse Source
Accept one of:
- One GitHub directory URL — single skill copy
- Multiple GitHub directory URLs — multi-skill merge
- Pasted content — user pastes SKILL.md content (and optionally other files) directly
Expected URL format: https://github.com/{owner}/{repo}/tree/{branch}/{path}
Parse to extract owner, repo, branch, and path. If the format doesn't match, ask for clarification.
For pasted content, skip to Step 4.
Step 2: Parallel Discovery
Launch ALL of these in a single turn using parallel tool calls:
# 1. Commit SHA
curl -s "https://api.github.com/repos/{owner}/{repo}/commits?sha={branch}&per_page=1" | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['sha'])"
# 2. Directory listing
curl -s "https://api.github.com/repos/{owner}/{repo}/contents/{path}?ref={branch}"
# 3. License check
curl -s "https://api.github.com/repos/{owner}/{repo}/license" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('license',{}).get('spdx_id','unknown'))"
# 4. Existing skills (Glob tool, parallel with the above)
Glob: plugins/*/skills/*/SKILL.md
If the directory listing contains subdirectories ("type": "dir"), list their contents too — add parallel curl calls for each subdirectory in the same turn or the next turn.
Error handling:
- 404 → invalid URL or directory doesn't exist, report and stop
- 403 / rate limit → inform the user, suggest waiting or retrying later
Step 3: Validate License & Confirm Name
License validation — this repo is MIT-licensed, so imported code must be under a compatible license:
Compatible: MIT, ISC, BSD-2-Clause, BSD-3-Clause, Apache-2.0, 0BSD, Unlicense, CC0-1.0, WTFPL, Zlib, BSL-1.0
| Result | Action |
|---|---|
| SPDX ID is in the compatible list | Proceed. Record the license. |
NOASSERTION or null / missing |
Stop. No detectable license means all rights reserved. Offer to skip this source. |
| Anything else (GPL, LGPL, AGPL, MPL, etc.) | Stop. Explain the license is incompatible with MIT. Offer to skip. |
If the user explicitly overrides (e.g., "I have permission from the author"), proceed but record "license_override": true and the user's reason in sources.json.
Name resolution — always ask the user for the skill name via AskUserQuestion. Offer the original name (extracted from the URL path) as the recommended option. Validate: lowercase kebab-case, no conflict with existing skills, not empty.
Step 4: Download & Write Files
Create the directory structure, then download ALL files directly to disk in a single turn using parallel Bash calls:
# First: create directories
mkdir -p plugins/{name}/skills/{name}/references plugins/{name}/.claude-plugin # include any subdirectories found in Step 2
# Then: parallel downloads (one Bash call per file)
curl -s "https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{full-path-to-file}" > plugins/{name}/skills/{name}/{relative-path}
Use download_url values from the directory listing (these point to raw.githubusercontent.com) for each file. Each curl download should be a separate parallel Bash tool call so they execute concurrently.
After writing: if the skill name differs from the original, update the name: field in SKILL.md frontmatter using the Edit tool.
For merge (multiple sources):
- Download all files from all sources first
- Read the fetched SKILL.md files
- Synthesize a merged SKILL.md combining capabilities — merged description, unified process steps, deduplicated where they overlap
- Copy all supporting files (
references/,scripts/,assets/) from all sources - On filename conflicts: suggest a descriptive alternative name, ask user to confirm
Step 5: Finalize
Each skill is its own installable plugin. Finalizing writes three things: sources.json (provenance), .claude-plugin/plugin.json (plugin manifest), and a new entry in the top-level .claude-plugin/marketplace.json.
Do ALL of these in a single turn using parallel tool calls:
- Write
plugins/{name}/skills/{name}/sources.json(Write tool):
{
"created_at": "YYYY-MM-DDTHH:mm:ss.000Z",
"type": "copy",
"sources": [
{
"url": "https://github.com/{owner}/{repo}/tree/{branch}/{path}",
"repository": "{owner}/{repo}",
"path": "{path}",
"branch": "{branch}",
"sha": "{full-commit-sha}",
"original_name": "{original-name}",
"fetched_at": "YYYY-MM-DDTHH:mm:ss.000Z"
}
],
"license": "{spdx-id}",
"copyright": "Copyright (c) {owner}",
"license_override": false,
"license_override_reason": null
}
type:"copy"for single source,"merge"for multiple,"paste"for pasted contentsha: full commit SHA at fetch time — used to check for upstream updates later
- Write
plugins/{name}/.claude-plugin/plugin.json(Write tool) using the per-skill manifest template:
{
"name": "{name}",
"description": "{one-line description taken from SKILL.md frontmatter}",
"version": "1.0.0",
"author": {
"name": "Leonid Svyatov",
"email": "leonid@svyatov.com",
"url": "https://www.svyatov.com"
},
"homepage": "https://github.com/svyatov/agent-toolkit",
"repository": "https://github.com/svyatov/agent-toolkit",
"license": "MIT"
}
- No
skillsfield — Claude Code auto-discoversplugins/{name}/skills/{name}/SKILL.mdvia default discovery. The invocation name comes from thename:inSKILL.mdfrontmatter. - New plugins start at
1.0.0. Version bumps happen per-skill in that skill's ownplugin.json.
- Append new plugin entry to
.claude-plugin/marketplace.json(Read tool, then Edit tool) — add an object to the top-levelpluginsarray:
{
"name": "{name}",
"source": "./plugins/{name}",
"description": "{one-line description — same as plugin.json}",
"category": "productivity",
"tags": ["{relevant}", "{tags}"]
}
Schema requires the ./ prefix on relative sources, so use the full path ./plugins/{name} (marketplace does not use pluginRoot). Pick 3–5 discovery tags that match the skill's domain; reuse productivity for most skills, writing for editing/copy skills.
- Verify JSON (Bash call, parallel with above):
python3 -c "import json; json.load(open('plugins/{name}/skills/{name}/sources.json')); json.load(open('plugins/{name}/.claude-plugin/plugin.json')); json.load(open('.claude-plugin/marketplace.json')); print('all JSON valid')"
Present a summary: skill name, source(s), files created, license, plugin manifest path, marketplace entry added.
Step 6: Post-Import Review
Review the imported skill and suggest improvements — simplifications, better structure, clearer instructions, content redundant with what Claude already does by default. If the skill-creator skill is installed, invoke it for this analysis; otherwise review the SKILL.md directly.
Important: Present all suggested changes to the user and wait for explicit confirmation before applying anything. Do not auto-apply improvements.
Edge Cases
- No SKILL.md in fetched directory — warn. Ask whether to treat all files as references and create a minimal SKILL.md, or abort.
- Large files (>1MB) — warn and ask whether to include.
- Binary files — detect by extension, warn, and ask whether to include.
- Nested subdirectories — recurse: list contents via API, then download all files in parallel.