Local CLI: a skill package manager, install gate, and context accounting for SKILL.md-based agent skills.
Doesn't care where skills come from. Cares whether they land on your machine, how much context they eat, and which set each project enables.
Languages: English | 中文
| Command | Purpose |
|---|---|
skillctl ls [--all] [--json] [path] | List installed skills across runtimes: scope, tokens, flags, conflicts |
skillctl why <task> | Which skills would grab this task + conflict edges |
skillctl budget [--strict] [--json] | Description-token total vs budget; exit 1 on breach |
skillctl use <profile> | Apply a profile by writing each runtime's native enable/disable switch |
skillctl scan <git-url|path> | Wrap NVIDIA SkillSpector (--no-llm); report only |
skillctl add <git-url|path> | Gate, then copy-install; DO_NOT_INSTALL needs --force |
skillctl prune [--apply] | Broken links / duplicate inodes / empty dirs; dry-run by default |
Discovered runtimes: Claude Code, Codex (incl. .system, labeled scope=system), OpenCode, pi (recursive collections), omp. Plugin caches are never scanned.
Requires Python ≥ 3.11 and uv.
git clone <repo-url> skillctl
cd skillctl
# 1) Try without installing (creates .venv, resolves the only dep: pyyaml)
uv sync
uv run skillctl ls
# 2) Install as a `skillctl` command on PATH (editable — edits take effect immediately)
uv tool install --editable .
skillctl ls --all
# re-install over an existing link after big changes / remove it
uv tool install --editable . --force
uv tool uninstall skillctl
No tokenizer, no network calls: token estimate is chars / 4, TOML uses the stdlib.
~/.config/skillctl/config.toml:
default_runtime = "claude"
copy_not_symlink = true
skillspector_bin = "skillspector"
budget.max_skills = 20
budget.max_description_tokens = 2000
budget.max_body_words = 5000
Profiles at ~/.config/skillctl/profiles/<name>.toml:
enable = ["grilling", "using-superpowers"]
disable = ["follow-builders"]
# names not listed are left untouched
over_body flag. It warns; only budget --strict fails on it. Hard budget failures are max_skills / max_description_tokens.lstat + stat (dirent sizes lie); broken links are reported and become prune targets; same-inode copies dedupe to one record.use writes only runtime-native switches: Claude skillOverrides, Codex [[skills.config]] (absolute paths). It never edits SKILL.md or renames directories. OpenCode/pi/omp have no known native switch in v0 — those copies are reported on stderr and left untouched.0 success · 1 budget breach or gate refusal · 2 missing skillspector / scanner error / bad args or IO.uv sync # dev group (pytest) included by default
uv run pytest # isolated tmp HOME — never touches real configs
Design docs (PLAN.md, DESIGN.md) live in docs/ and are intentionally not committed.
1 commits
Python
100.0%
Local CLI: a skill package manager, install gate, and context accounting for SKILL.md-based agent skills.
Doesn't care where skills come from. Cares whether they land on your machine, how much context they eat, and which set each project enables.
Languages: English | 中文
| Command | Purpose |
|---|---|
skillctl ls [--all] [--json] [path] | List installed skills across runtimes: scope, tokens, flags, conflicts |
skillctl why <task> | Which skills would grab this task + conflict edges |
skillctl budget [--strict] [--json] | Description-token total vs budget; exit 1 on breach |
skillctl use <profile> | Apply a profile by writing each runtime's native enable/disable switch |
skillctl scan <git-url|path> | Wrap NVIDIA SkillSpector (--no-llm); report only |
skillctl add <git-url|path> | Gate, then copy-install; DO_NOT_INSTALL needs --force |
skillctl prune [--apply] | Broken links / duplicate inodes / empty dirs; dry-run by default |
Discovered runtimes: Claude Code, Codex (incl. .system, labeled scope=system), OpenCode, pi (recursive collections), omp. Plugin caches are never scanned.
Requires Python ≥ 3.11 and uv.
git clone <repo-url> skillctl
cd skillctl
# 1) Try without installing (creates .venv, resolves the only dep: pyyaml)
uv sync
uv run skillctl ls
# 2) Install as a `skillctl` command on PATH (editable — edits take effect immediately)
uv tool install --editable .
skillctl ls --all
# re-install over an existing link after big changes / remove it
uv tool install --editable . --force
uv tool uninstall skillctl
No tokenizer, no network calls: token estimate is chars / 4, TOML uses the stdlib.
~/.config/skillctl/config.toml:
default_runtime = "claude"
copy_not_symlink = true
skillspector_bin = "skillspector"
budget.max_skills = 20
budget.max_description_tokens = 2000
budget.max_body_words = 5000
Profiles at ~/.config/skillctl/profiles/<name>.toml:
enable = ["grilling", "using-superpowers"]
disable = ["follow-builders"]
# names not listed are left untouched
over_body flag. It warns; only budget --strict fails on it. Hard budget failures are max_skills / max_description_tokens.lstat + stat (dirent sizes lie); broken links are reported and become prune targets; same-inode copies dedupe to one record.use writes only runtime-native switches: Claude skillOverrides, Codex [[skills.config]] (absolute paths). It never edits SKILL.md or renames directories. OpenCode/pi/omp have no known native switch in v0 — those copies are reported on stderr and left untouched.0 success · 1 budget breach or gate refusal · 2 missing skillspector / scanner error / bad args or IO.uv sync # dev group (pytest) included by default
uv run pytest # isolated tmp HOME — never touches real configs
Design docs (PLAN.md, DESIGN.md) live in docs/ and are intentionally not committed.
1 commits
Python
100.0%