Skip to main content

skillpod — pod-style dependency manager for AI coding agent skills

CI PyPI Python License: MIT

Manage the skills your AI coding agents use — per project, or globally.

A project says which skills it recommends. You decide what you actually run. skillpod installs them once and wires them into every agent you use — Claude Code, Codex, Gemini, Cursor, OpenCode, Antigravity.

Pre-1.0: the manifest and profile schema may still change in breaking ways.


Install

uv tool install skillpod     # or: pipx install skillpod
skillpod --version

Needs Python 3.11+ and git on your PATH.


60-second start

cd my-project
skillpod init                                   # writes skillfile.yml, gitignores .skillpod/
skillpod add anthropics/skills --skill pdf -y   # fetch a skill and wire it up
skillpod status                                 # confirm it landed
recommends: 1 skill(s)
  satisfied: 1   (1 project)

pdf is now materialised in .skillpod/skills/ and linked into .claude/skills/, so your agent can use it. Commit skillfile.yml; .skillpod/ stays out of git.

Not sure what a repo offers? List before you commit to anything:

skillpod add anthropics/skills --list

I want to…

…recommend a set of skills for this project

skillfile.yml is the recommendation. Commit it, and a teammate who wants the same setup runs one command.

version: 1
agents: [claude]

sources:
  - name: skills
    type: git
    url: https://github.com/anthropics/skills
    ref: main
    subpath: skills

skills:
  - name: pdf
    source: skills
  - name: docx
    source: skills
skillpod install

Nothing here is enforced. A teammate who ignores it, or already has these skills globally, is not doing anything wrong — see the next entry.

…not install a skill I already have globally

This is the default. If a skill is already in ~/.skillpod/skills/, the recommendation is already met, so no project copy is made:

$ skillpod install
Already present: 2 skill(s)
Satisfied by your global install: xlsx

It applies only where every agent you declare is known to read its personal and project skill directories together. Only Claude Code is verified today; the rest get a project copy rather than risk a skill being silently unavailable.

To force a project-local copy anyway:

install:
  prefer_global: false

Be aware Claude Code documents that a personal skill outranks a project one of the same name — so with prefer_global: false, skillpod install will warn you that your project copy is not the one in use.

…see what I actually have right now

$ skillpod status
project:    my-project
manifest:   /path/to/skillfile.yml

recommends: 4 skill(s)
  satisfied: 2   (1 global, 1 project)
  missing:   1   → skillpod install
  broken:    1   → skillpod doctor

Every count names the command that fixes it. For the per-skill breakdown:

$ skillpod list
NAME      SOURCE    LAYER     INSTALLED
pdf       skills    project   fa0fa64bdc96
docx      skills    project   fa0fa64bdc96

LAYER says which copy is actually serving each skill: project, global, user, missing, or broken.

…install a skill for every project, not just this one

skillpod add anthropics/skills --skill xlsx -g -y

This puts the skill in ~/.skillpod/skills/ without wiring it into any agent — that is a deliberate second step, so a global install never silently changes what your agents see:

skillpod global link xlsx --agent claude    # or omit --agent for all of them
skillpod global list
NAME  LINKED     SIZE  MTIME
xlsx  cl      1102893  2026-07-21

…turn a skill off without deleting it

skillpod unlink audit             # this project
skillpod unlink xlsx -g           # globally

The materialised copy stays put, so skillpod link audit brings it back with no download. Only skillpod-created links are removed — anything you placed by hand is reported and left alone.

This is deliberately not remove: that deletes the content and edits skillfile.yml, which is much more than "stop showing me this".

…use a skill I already have, in a project that doesn't declare it

$ skillpod link xlsx
Copied 'xlsx' from ~/.skillpod/skills/ — nothing downloaded.
Linked to: claude

link never fetches. If the skill is already on your machine — in this project or globally — it wires it up; if it is nowhere, it tells you to run skillpod add.

…update my global skills

$ skillpod global update --dry-run
Would update 18 skill(s):
  algorithmic-art              5128e1865d67 → fa0fa64bdc96
  brand-guidelines             5128e1865d67 → fa0fa64bdc96

  local        33 skill(s) — no upstream to pull from
  no source    37 skill(s) — origin unknown, reinstall from a source to make them updatable

Drop --dry-run to apply, or name specific skills:

skillpod global update pdf docx

Skills with no recoverable origin, skills from local directories, and remotes that cannot be reached are reported and skipped — never fatal. One dead remote does not stop the rest.

…run only some of this project's skills right now

$ skillpod switch minimal
active profile set to 'minimal' (scope: project)
  hidden: polish (still installed — switching back is instant)

Declare the subsets in skillfile.yml:

profiles:
  minimal:
    skills: [audit]

Hidden skills stay in .skillpod/skills/, so switching back is offline and immediate. install and sync respect the active profile too — neither will put a hidden skill back.

…switch my whole global setup at once

Save what you have now, then move between named sets:

skillpod profile save writing            # snapshot the current global skills
skillpod switch reviewing --scope global # download what's missing, unlink the rest
skillpod switch --back                   # undo

Add --dry-run to preview the reconcile first, or dev+reviewer to union two profiles.

…use a skill that only exists on my machine

Drop it in .skillpod/user_skills/<name>/ and run skillpod install. It needs no source and no manifest entry, and it takes precedence over a declared skill of the same name.


Commands

Command What it does
skillpod init Write a starter skillfile.yml and gitignore .skillpod/
skillpod add <source> Fetch a skill from a repo or directory and install it
skillpod install Install what the manifest recommends and is not already present
skillpod update [skill] Re-resolve and pull newer upstream content
skillpod remove <skill> Drop a skill from the manifest and uninstall it
skillpod link <skill> Make a skill visible to your agents (-g for global)
skillpod unlink <skill> Hide it again, keeping the copy (-g for global)
skillpod status The one-screen answer to "is this project ready"
skillpod list Per-skill breakdown: source, layer, installed commit
skillpod doctor Report faults with paths and codes
skillpod sync Rebuild fan-out from the install record, offline
skillpod outdated Compare installed commits against upstream
skillpod search <query> Search the skills.sh registry
skillpod global … list, link, unlink, update, archive, doctor
skillpod profile … create, list, show, save, diff, export, import
skillpod switch <name> Set the active profile for a scope
skillpod shell <name> Sub-shell with a profile pre-activated
skillpod resolve Show the effective skill set, with --explain
skillpod adapter list Inspect the active adapter registry
skillpod schema Emit the JSON Schema for editor integration

--help on any subcommand shows the full options. Most commands accept --json for scripting.


skillfile.yml reference

Only version is required. Everything below shows its default.

version: 1

# Agents that receive fan-out. Empty means skills land in .skillpod/skills/
# only. Supported: claude, codex, gemini, cursor, opencode, antigravity.
agents: [claude]

install:
  mode: symlink          # symlink | copy | hardlink
  fallback: [copy]       # tried when `mode` fails (e.g. symlinks denied)
  on_missing: error      # error | skip
  prefer_global: true    # a skill already in ~/.skillpod/skills/ counts as satisfied

sources:
  - name: skills
    type: git            # git | local
    url: https://github.com/anthropics/skills
    ref: main            # branch, tag, or commit
    subpath: skills      # git only — where the skills live inside the repo
    priority: 50         # higher wins when several sources could provide a skill

skills:
  - audit                          # shorthand: resolve against sources, then the registry
  - name: pdf
    source: skills                 # pin to one source, skipping the registry
    version: <40-char commit sha>  # optional: pin to an exact commit

groups:                  # named bundles, activated by `use:`
  frontend: [pdf, docx]
use: [frontend]

registry:
  default: skills.sh
  skills_sh:
    allow_unverified: false
    min_installs: 0
    min_stars: 0

profiles:                # named subsets, see `skillpod switch`
  minimal:
    skills: [pdf]

activation:
  mode: manual           # manual | strict | merge | fallback
  inherit_global: true
  default_profile: null

Run skillpod schema --output schemas/skillfile.schema.json for editor autocomplete, or skillpod schema --profile for the global profile schema.


How it works

skillfile.yml  →  resolve  →  cache  →  .skillpod/skills/  →  .<agent>/skills/
  1. Resolve. A skill declared with source: is looked up there. A bare name probes declared sources by priority, then falls back to the skills.sh registry.
  2. Cache. Git sources clone into ~/.cache/skillpod/<host>/<owner>/<repo>@<commit>/, written by atomic rename so a partial clone is never visible.
  3. Materialise. .skillpod/skills/<name>/ is a real directory copy, never a symlink — clearing the cache cannot break an installed project.
  4. Fan out. Each declared agent gets .<agent>/skills/<name> pointing at that copy, using install.mode.

What gets recorded. .skillpod/installed.yml (and ~/.skillpod/installed.yml for global installs) records what is on this machine: source, ref, commit, content digest. Both live under .skillpod/, which is gitignored — they describe your machine, they do not constrain a teammate's.

install versus update. install brings in what is missing and leaves alone what is already there, so re-running it is offline and instant. Pulling newer upstream content is skillpod update — always an explicit act, never a side effect.


Security model — what you're trusting

Adding a skill pulls external text into your agent's context. A SKILL.md is read as instructions, so review a repo before adding it, the same way you would review a package before installing it.

The registry trust policy gates skills.sh only. registry.skills_sh (allow_unverified, min_installs, min_stars) applies when you search or resolve a bare name through the registry. Passing a git URL, an owner/repo shorthand, or a local path to skillpod add trusts that source directly — no threshold is checked.

Content is digested, not policed. Each install records a sha256 of what it materialised, so skillpod doctor can tell you the disk no longer matches the record. That detects drift and corruption; it does not vet the content.


Roadmap

Milestone Status Highlights
0.1.0 – 0.5.x shipped manifest, installer, registry, adapters, global CLI
0.6.x shipped workspace profiles, activation policy, session shell, composition
0.9.0 shipped recommendation modelskillfile.lock retired, prefer_global, global update, status dashboard, unified link/unlink, project profiles that reconcile fan-out
1.0.0 planned schema freeze

Full history: CHANGELOG.md.


Troubleshooting

Agent directory is empty after install agents: defaults to [], which disables fan-out. Declare the agents you use.

A skill is installed but my agent ignores it If the same name exists in ~/.skillpod/skills/, Claude Code prefers the personal copy. skillpod status shows which layer is serving it.

Symlink creation fails (Windows, some CI) Set install.mode: copy, or rely on the default fallback: [copy].

skillpod add <owner/repo> fails with a git error Check git is on $PATH. For private repos, verify your SSH or HTTPS credentials.

global archive '*' expands to filenames Quote the asterisk — the shell expands it otherwise.


Contributing

uv sync
uv run pytest -q
uv run ruff check src tests
uv run mypy src/skillpod

See CONTRIBUTING.md for the module map and conventions.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

skillpod-0.9.0.tar.gz (177.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

skillpod-0.9.0-py3-none-any.whl (155.4 kB view details)

Uploaded Python 3

File details

Details for the file skillpod-0.9.0.tar.gz.

File metadata

  • Download URL: skillpod-0.9.0.tar.gz
  • Upload date:
  • Size: 177.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for skillpod-0.9.0.tar.gz
Algorithm Hash digest
SHA256 fb76307ad2edda71db05592ee19879f5a41aba598aa960e5b7c5e54701a0306f
MD5 d5b214dfc909e8deed4bee883ed6f46c
BLAKE2b-256 2d9a46af79bfc60b6b150c6606d2e0117e5121e06e2a2aeca52c0c0684f8cc90

See more details on using hashes here.

Provenance

The following attestation bundles were made for skillpod-0.9.0.tar.gz:

Publisher: release.yml on g761007/skillpod-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file skillpod-0.9.0-py3-none-any.whl.

File metadata

  • Download URL: skillpod-0.9.0-py3-none-any.whl
  • Upload date:
  • Size: 155.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for skillpod-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0b176f8762cf24b4618e7091a3a0c9532e96c47bdfe26f769b67cb481a9b12c6
MD5 86031fcb8687e7a8b87ad64662915ed4
BLAKE2b-256 e162c9029a5a2fa667c8fda03320f5ebff9a08b0df97551c9fa7ec4d597c9e3d

See more details on using hashes here.

Provenance

The following attestation bundles were made for skillpod-0.9.0-py3-none-any.whl:

Publisher: release.yml on g761007/skillpod-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.9.1

2 files

This release

0.9.0 This release

2 files

0.6.5

2 files

0.6.4

2 files

0.5.7

2 files

0.5.6

2 files

0.5.5

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page