Skip to main content

skillprune

Every agent skill you install puts its name and description into the system prompt on every turn, forever. Installing is one click; nothing tells you what to remove.

The OSS ecosystem has solved discovery and install several times over — SkillDock (519★), skillfish (315★), skilld (308★). The other half of the loop is empty: every audit/eval/conflict tool on GitHub sits at 1–14 stars.

skillprune is that other half. It reads your real transcript history and tells you what to turn off.

uvx skillprune                   # run it, install nothing
pipx install skillprune          # or keep it around
skillprune                       # report
skillprune --prune               # act on it, reversibly
skillprune --json                # + skillprune.json
skillprune --selfcheck           # the guards below, as assertions
skillprune --help                # all of the above

No install needed either way — it is one stdlib-only file, so python3 skillprune.py works straight from a clone.

Example, on a real 291-skill install:

  171 loaded    35 fired    123 dead    13 too new to judge
  125 more sit on disk, not loaded by any plugin — those cost nothing

  ████████████████████░░░░░░░░  72% of your skill surface has never fired

  ~15,673 tokens in every system prompt, for skills that have never fired
  71% of the ~22,169 tokens your skills cost you per turn

Removing what it finds

skillprune --prune prints a plan, asks once, and applies it. Two levers, because they are two different things:

  • Plugins where not one skill has ever fired → claude plugin disable. Reversible with enable. A plugin with even one live skill is never offered.
  • Personal skills in ~/.claude/skills/ → moved, never deleted, to ~/.claude/.skillprune-trash/<timestamp>/, next to a generated restore.sh that puts every one of them back.

There is no per-skill disable for plugin skills — the plugin is the unit the tool manages, so that is the unit offered.

It follows symlinks, so the agent-neutral layout — one shared ~/.agents/skills tree linked into each tool's config — is counted rather than silently skipped, and skills a plugin ships under .claude/skills/ or .openclaw/skills/ are found too. A project's own ./.claude/skills is included when you run it there. A shared tree that is not linked into a config dir is deliberately ignored: nothing loads it, so it costs nothing.

Set CLAUDE_CONFIG_DIR if your Claude Code config lives somewhere other than ~/.claude. With nothing to audit it says so, rather than reporting 0%.

How it decides

Source Used for
~/.claude/projects/**/*.jsonl what actually fired, and when
SKILL.md frontmatter what exists on disk
plugins/installed_plugins.json which of those are actually loaded
claude plugin details real always-on token cost (not re-derived)

Nothing leaves the machine. No dependencies beyond the standard library.

Where it deliberately errs

A tool that says delete this has one unacceptable failure: naming something you actually use. Five guards, each pinned by an assertion in --selfcheck:

  • Slash commands count. A skill invoked only as /foo never produces a Skill tool call. Counting just the tool call marks it dead.
  • Hooks count. A plugin shipping a SessionStart hook runs every session with an invocation count of zero. Those are held back, never auto-disabled.
  • Bare-name matching. Transcripts log <plugin>:<skill>, and that prefix often disagrees with the marketplace directory the skill was found in. Two plugins sharing a skill name will cross-credit — that errs toward in use, the only safe direction here.
  • On disk is not loaded. A marketplace you added and a plugin you later uninstalled both leave complete SKILL.md trees behind, and neither costs a single prompt token. Only what installed_plugins.json actually points at is counted. Skipping this inflated the count on the author's own machine from a true 171 to 291.
  • 14-day grace. Something installed yesterday hasn't had its chance. Tune GRACE_DAYS; skills under it are reported separately, never as dead.

Collision detection is Jaccard overlap on description word-sets (COLLIDE, default 0.35) — crude next to embeddings, but it needs no model and no network.

MIT.

Release files for skillprune 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for skillprune 0.3.0
File Size Uploaded
skillprune-0.3.0.tar.gz 14.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for skillprune 0.3.0
File Interpreter ABI Platform
skillprune-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 29.8 kB

Release files / skillprune-0.3.0.tar.gz

Download URL skillprune-0.3.0.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
7a15efdf3c6dc8fcd4022f42e60a7ba98309878b60065888ead0cd7093f9b0b1
BLAKE2b-256 checksum
How to use checksums
6ec6262a120d3476bd7c7b4787b7c550b6be6c4c4d9a35d9a3f1722ca20cba6b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / skillprune-0.3.0-py3-none-any.whl

Download URL skillprune-0.3.0-py3-none-any.whl
Size 15.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c8f86b605ba36fe32d0fbda3f9667dd1c9550f9da387a1e2f8800aa54736ebc0
BLAKE2b-256 checksum
How to use checksums
ad2c5fae347af8e389db608720830f9dd7e8b244ffa6e564572d943dd16d9c5f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page