Install agent skills from GitHub repositories
Project description
shskills
Install agent skills from GitHub repositories.
shskills is a CLI tool and Python library that fetches skill definitions from a remote Git repository and installs them into the correct directory for your AI agent (Claude, Codex, Gemini, OpenCode, or a custom target).
Quickstart
pip install shskills
# Install all skills for Claude
shskills install --url https://github.com/org/repo --agent claude
# Install a specific group
shskills install --url https://github.com/org/repo --agent claude --subpath aws
# Install a single skill
shskills install --url https://github.com/org/repo --agent claude --subpath aws/scale_up_service
Installation
Requires Python >= 3.11 and Git >= 2.28.
pip install shskills
# or
uv add shskills
# or
pipx install shskills
CLI reference
install
Fetch and install skills from a remote repository.
shskills install [OPTIONS]
Options:
--url -u TEXT Git repository URL [required]
--agent -a TEXT Target agent: claude, codex, gemini, opencode, custom
--subpath -s TEXT Path relative to SKILLS/ to install
--ref -r TEXT Branch, tag, or commit SHA [default: main]
--dest -d PATH Override the default destination directory
--dry-run Plan without writing any files
--force -f Overwrite skills whose content has changed
--clean Remove orphaned skills no longer in the source
--strict Abort on any conflict
--verbose -v Show detailed per-skill progress
Examples:
# Install all skills, Claude adapter
shskills install --url https://github.com/org/skills-repo --agent claude
# Preview changes without writing anything
shskills install --url https://github.com/org/skills-repo --agent claude --dry-run
# Force-update all skills even if locally modified
shskills install --url https://github.com/org/skills-repo --agent claude --force
# Pin to a tag
shskills install --url https://github.com/org/skills-repo --agent claude --ref v2.1.0
# Pin to a commit SHA
shskills install \
--url https://github.com/org/skills-repo \
--agent claude \
--ref a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
# Install into a custom directory
shskills install --url https://github.com/org/skills-repo --agent custom --dest ./my-skills
# Install and remove skills that no longer exist in the source
shskills install --url https://github.com/org/skills-repo --agent claude --clean
list
List available skills in a remote repository without installing.
shskills list --url https://github.com/org/repo [--subpath aws] [--ref main] [--verbose]
installed
Show skills currently installed for an agent.
shskills installed --agent claude
shskills installed --agent claude --dest ./custom-dest
doctor
Check the health of installed skills: verifies files are present and SHA-256 digests match the manifest.
shskills doctor --agent claude
Exit code 0 = healthy. Exit code 1 = one or more errors found.
Repository skill format
Skills live in a SKILLS/ directory tree inside the repository:
SKILLS/
<group>/
<skill_name>/
SKILL.md <- required; marks this as a skill directory
helper.py <- optional supporting files
...
A skill directory is any directory containing a SKILL.md file.
Nesting depth is unrestricted.
SKILL.md front-matter
SKILL.md may begin with an optional --- delimited front-matter block:
---
name: scale_up_service
description: Scales up an ECS service to the desired count
version: "1.2.0"
---
# Scale Up Service
...skill body here...
| Field | Required | Default |
|---|---|---|
name |
No | directory name |
description |
No | "" |
version |
No | "1.0.0" |
Destination mapping
--agent |
Default destination |
|---|---|
claude |
.claude/skills/ |
codex |
.codex/skills/ |
gemini |
.gemini/skills/ |
opencode |
.opencode/skills/ |
custom |
must supply --dest |
The destination path is always relative to the current working directory (your project root).
Installed path structure
Skills are installed preserving their path relative to the --subpath root:
| Invocation | Source path | Installed at |
|---|---|---|
| (no subpath) | SKILLS/aws/scale_up |
<dest>/aws/scale_up/ |
--subpath aws |
SKILLS/aws/scale_up |
<dest>/scale_up/ |
--subpath aws/scale_up |
SKILLS/aws/scale_up |
<dest>/scale_up/ |
Adapter system
Each agent has an adapter (shskills.adapters.*) that controls how skill files are written to disk.
The base adapter copies all skill files verbatim. Agent-specific adapters can override
preprocess(skill, dest_dir) to rename, reformat, or generate additional files for that
agent's expected format.
from shskills.adapters.base import AgentAdapter
from shskills.models import SkillInfo
from pathlib import Path
class MyAdapter(AgentAdapter):
@property
def agent_name(self) -> str:
return "myagent"
def preprocess(self, skill: SkillInfo, dest_dir: Path) -> list[str]:
# Custom transformation: expose only a single prompt.md
dest_dir.mkdir(parents=True, exist_ok=True)
out = dest_dir / "prompt.md"
out.write_text((skill.local_path / "SKILL.md").read_text())
return ["prompt.md"]
Manifest
After installation, shskills writes a manifest at <dest>/.shskills-manifest.json:
{
"version": "1",
"agent": "claude",
"dest": ".claude/skills",
"updated_at": "2026-02-28T12:00:00+00:00",
"source": {
"url": "https://github.com/org/repo",
"ref": "main",
"subpath": null
},
"skills": {
"aws/scale_up": {
"name": "scale_up",
"source_path": "aws/scale_up",
"dest_path": ".claude/skills/aws/scale_up",
"content_sha256": "e3b0c44298fc1c149a...",
"installed_at": "2026-02-28T12:00:00+00:00",
"files": ["SKILL.md"]
}
}
}
The manifest is used to detect up-to-date skills (idempotency via SHA-256), identify
orphans for --clean, and power the installed and doctor commands.
Written atomically (temp file then rename) so a crash cannot corrupt it.
Python API
from shskills import install, list_skills, installed_skills, doctor
from pathlib import Path
# Install
result = install(
url="https://github.com/org/repo",
agent="claude",
subpath="aws",
ref="main",
dest=Path(".claude/skills"),
dry_run=False,
force=False,
clean=False,
)
print(result.installed) # ["aws/scale_up"]
print(result.skipped) # ["aws/other_skill"]
# List remote skills without installing
skills = list_skills(url="https://github.com/org/repo", subpath="aws")
for s in skills:
print(s.name, s.frontmatter.description)
# List installed skills
for s in installed_skills(agent="claude"):
print(s.name, s.content_sha256[:8])
# Health check
report = doctor(agent="claude")
print(report.healthy)
for issue in report.issues:
print(issue.severity, issue.message)
Conflict policy
| Situation | Default | --force |
--clean |
|---|---|---|---|
| Already installed, same content | Skip (no-op) | Skip | — |
| Already installed, content changed | Warn + skip | Overwrite | — |
| File exists but not in manifest | Warn + skip | Overwrite | — |
| Skill in manifest but not in current source | Keep | Keep | Delete |
--strict mode |
Any conflict = fatal | — | — |
Security notes
- No code execution. No fetched file is ever executed or evaluated.
- Path sanitisation. All source paths are validated against
..traversal and absolute paths; any violation raises an error before any file is touched. - Symlinks rejected. Symlinks inside skill directories are refused.
- File size cap. Files larger than 512 KB are rejected (configurable via
MAX_FILE_BYTES). - Untrusted input. The remote repository is treated as untrusted. SKILL.md front-matter is parsed with a plain regex — no YAML or TOML evaluator is invoked.
- Atomic manifest. The manifest is written via temp-file-then-rename; a crash cannot leave a partial or corrupt manifest file.
Local development
git clone https://github.com/your-org/shskills
cd shskills
# Install in editable mode with dev dependencies
pip install -e ".[dev]"
# Run the CLI
shskills --version
# Lint
ruff check src/ tests/
# Type-check
mypy src/shskills
# Run all tests (unit + integration)
pytest
# Unit tests only (fast, no git required)
pytest tests/ --ignore=tests/integration
# Integration tests only (requires git >= 2.28)
pytest tests/integration/
Publishing to PyPI
One-time setup (OIDC trusted publishing — no token needed)
- Go to https://pypi.org/manage/account/publishing/
- Add a trusted publisher:
- Package name:
shskills - Repository:
your-org/shskills - Workflow filename:
release.yml
- Package name:
Release
# 1. Bump version in src/shskills/_version.py and pyproject.toml
# 2. Commit
git commit -am "chore: bump to v0.2.0"
# 3. Tag and push — the release workflow fires automatically
git tag v0.2.0
git push origin main --tags
install from test pypi
python -m pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple shskills
Manual publish (fallback)
uv build
uv publish --token "$PYPI_TOKEN"
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file shskills-0.1.4.tar.gz.
File metadata
- Download URL: shskills-0.1.4.tar.gz
- Upload date:
- Size: 82.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6fa79ed544f05db348ebf5e08f90a337a5457eb3510b1c9e7374920de06aec4f
|
|
| MD5 |
a8505b27171b142cb4025d0afb9b680e
|
|
| BLAKE2b-256 |
b715c4bc97e185cf266e8fc75d7adb81b0fe58202b10b2133e4edf8386495b2d
|
Provenance
The following attestation bundles were made for shskills-0.1.4.tar.gz:
Publisher:
release.yml on trelatomasz/shareable-skills
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shskills-0.1.4.tar.gz -
Subject digest:
6fa79ed544f05db348ebf5e08f90a337a5457eb3510b1c9e7374920de06aec4f - Sigstore transparency entry: 1008656240
- Sigstore integration time:
-
Permalink:
trelatomasz/shareable-skills@34a2791a6e3a6f430aece550592b2a8d8a536319 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/trelatomasz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@34a2791a6e3a6f430aece550592b2a8d8a536319 -
Trigger Event:
push
-
Statement type:
File details
Details for the file shskills-0.1.4-py3-none-any.whl.
File metadata
- Download URL: shskills-0.1.4-py3-none-any.whl
- Upload date:
- Size: 26.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80e72156203dbe28703761ec8b22b884d864118476df9fcec7acd74ca484c067
|
|
| MD5 |
49b734acbff7912b01fcc8189b1de5a0
|
|
| BLAKE2b-256 |
a3708ddc631d0201bafb1733248cb814223a1c37efb0934f8b3dccf1e3ef19f4
|
Provenance
The following attestation bundles were made for shskills-0.1.4-py3-none-any.whl:
Publisher:
release.yml on trelatomasz/shareable-skills
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
shskills-0.1.4-py3-none-any.whl -
Subject digest:
80e72156203dbe28703761ec8b22b884d864118476df9fcec7acd74ca484c067 - Sigstore transparency entry: 1008656294
- Sigstore integration time:
-
Permalink:
trelatomasz/shareable-skills@34a2791a6e3a6f430aece550592b2a8d8a536319 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/trelatomasz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@34a2791a6e3a6f430aece550592b2a8d8a536319 -
Trigger Event:
push
-
Statement type: