Awesome Go

skillreaper

CategoryArtificial Intelligence
SubcategoryArtificial Intelligence
Stars60

CLI that scans AI agent session transcripts to identify and safely quarantine unused skills, MCP servers, and agents across Claude Code, Codex CLI, Hermes, OpenCode, Cursor, and OpenClaw

About skillreaper

This large README is shown as a plain-text preview. Read the full README at the source

<!-- readme-numbers:start -->
```
S           K           I          L          L
######  #######   ###   ######  ####### ###### 
##   ## ##       ## ##  ##   ## ##      ##   ##
######  #####   ####### ######  #####   ###### 
##  ##  ##      ##   ## ##      ##      ##  ## 
##   ## ####### ##   ## ##      ####### ##   ##

a generated sample stack, not a real install - run reap for your own numbers

skillreaper · last 30d · 34 sessions
7/378 items fired · 1% utilization
371 never fired · 371 marked REAP · ~22720 dead tokens/session

TOKENS  CATEGORY  NAME                 VERDICT  REASON
185     skill     import-timesheet     REAP     unused
185     skill     render-playlist      REAP     unused
177     skill     review-sitemap       REAP     unused
163     skill     deploy-dataset       REAP     unused
159     skill     validate-manifest    REAP     unused
157     skill     parse-contract       REAP     unused
149     skill     extract-receipt      REAP     unused
145     skill     sync-changelog       REAP     unused
111     skill     summarise-timesheet  REAP     unused
110     skill     export-timesheet     REAP     unused
(361 more marked REAP not shown — use --json for all)

To prune: reap prune   (interactive, reversible via reap restore --all)

1 warning — some evidence was incomplete; those items were held back from a REAP verdict.

measured by skillreaper · github.com/thousandflowers/skillreaper
```
<!-- readme-numbers:end -->

<p align="center">
  <sub>Real <code>reap --agent</code> output, run against a generated sample stack
  (<a href="docs/gif-helpers/hero-fixture.sh">hero-fixture.sh</a>) - not anyone's
  install. The numbers further down are measured on mine.</sub>
</p>

<h1 align="center">
  Most of what your AI agent loads, it never uses.
</h1>
<p align="center">
  skillreaper finds the <b>unused skills, MCP servers, subagents, hooks and
  always-loaded prose</b> quietly filling your <b>context window</b> - proven
  from your own session transcripts - and prunes them reversibly.<br>
  Runs locally against transcripts you already have. Nothing is ever uploaded.
</p>



<p align="center">
  <a href="https://github.com/thousandflowers/skillreaper/actions/workflows/ci.yml"><img src="https://github.com/thousandflowers/skillreaper/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://github.com/thousandflowers/skillreaper/issues"><img src="https://badgen.net/github/open-issues/thousandflowers/skillreaper" alt="Issues"></a>
  <a href="https://github.com/thousandflowers/skillreaper/releases"><img src="https://img.shields.io/github/downloads/thousandflowers/skillreaper/total?cacheSeconds=6400&color=success" alt="Downloads"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT"></a>
  <a href="https://github.com/avelino/awesome-go#artificial-intelligence"><img src="https://awesome.re/mentioned-badge.svg" alt="Mentioned in Awesome Go"></a>
  <a href="https://github.com/VoltAgent/awesome-agent-skills#community-skills"><img src="https://awesome.re/mentioned-badge.svg" alt="Mentioned in Awesome Agent Skills"></a>
</p>

<br>

```bash
npx skillreaper
```

<!-- readme-mine-headline:start -->
On my own installation, measured 2026-08-23: **382 items loaded, 13 ever fired - 3% utilization.**
That's ~19,755 dead tokens re-sent in every single session, ~1087k a month of
pure token waste, paid for on every request before you type anything.
<!-- readme-mine-headline:end -->

<sub>Measured 2026-08-23 on my own installation; raw output in
<a href="docs/measurements/">docs/measurements/</a>. Every "on my own installation"
figure on this page comes from that one run.</sub>

**One command. Zero config.** It reads your real session transcripts, finds
every skill / MCP / agent your AI loads but never fires, and shows you exactly
what it costs you.

<br>

## What it does

skillreaper is a **measuring instrument** for your agent's context window.
Pruning is one of the things you do with the measurement, not the point of it.
The whole surface, in the order you use it:

| Stage | Command | What it answers |
|---|---|---|
| **Measure** | `reap` | What do I load, what actually fires, what does the dead part cost per session? |
| | `reap gap` | What share of each category is ever used, and which MCP tools fire but return noise? |
| | `reap by-project` | Which project is actually firing each skill? |
| **Decide** | `reap why <name>` | Why did *this* item get *this* verdict, on what evidence? |
| **Act** | `reap prune` | Quarantine the dead items, reversibly |
| | `reap mute <name>` | Strip a heavy rarely-used description, keep the skill callable |
| **Engineer** | `reap route` | Propose a lazy-load routing plan for a library too big to prune flat |
| | `reap apm` | Emit a proposed APM `apm.yml`, so a team reproduces one lean set |
| **Compare** | `reap snapshot` | Keep this run, so a later one has something to be measured against |
| | `reap diff` | What appeared, left, changed verdict, and did anything come back after a prune |

Everything above the **Act** row is read-only. You can run the entire
measurement side without changing a single file.

<br>

## What it reads, what it writes

| Read-only, changes nothing | Writes, always reversible |
|---|---|
| `reap` <sup>1</sup> | `reap prune` &nbsp;↔&nbsp; `reap restore --all` |
| `reap gap` | `reap mute <name>` &nbsp;↔&nbsp; `reap unmute <name>` |
| `reap by-project` | `reap keep <name>` &nbsp;↔&nbsp; `reap keep --remove <name>` |
| `reap why <name>` | `reap install-hook` &nbsp;↔&nbsp; `reap uninstall-hook` |
| `reap route` | |
| `reap apm` | |
| `reap manifest <name>` | |
| `reap share` | |
| `reap snapshot` <sup>1</sup> | |
| `reap diff` | |

**Nothing is ever deleted.** `reap prune` moves files into a `reaped/`
directory with a versioned manifest, `reap mute` keeps a backup of the
description it strips, and `reap uninstall-hook` removes only skillreaper's own
entry, leaving your other hooks alone. Every write is **atomic** (temp file +
rename) and **confined** to your Claude directory, so an interrupted prune,
mute, or hook edit leaves the original file intact, never a half-written mix.

<sub><sup>1</sup> The only files a read-only command writes are skillreaper's
own: <code>~/.claude/reaped/nudge-state.json</code>, which the default report
touches so a hint it already showed you does not repeat, and the snapshot
<code>reap snapshot</code> exists to write. Neither touches your stack. Pass
<code>--no-nudge</code> (or set <code>SKILLREAPER_NO_NUDGE=1</code>) and not
even that happens. No command in either column sends anything over the
network.</sub>

<br>

## First 60 seconds

Three commands, in this order. Only the third one writes anything, and it
prints its own undo line.

```bash
reap                       # 1. measure: what you load, what fires, what it costs
reap why <name>            # 2. decide: the evidence behind one verdict
reap prune                 # 3. act: quarantine the dead ones, interactive
```

**1. `reap`** prints the report at the top of this page. Every row carries a
verdict:

| Label | Meaning |
|---|---|
| **`REAP(broken)`** | Invoked but errored - broken, not just cold |
| **`REAP`** | Zero uses - safe to quarantine |
| **`MUTE`** | Used rarely + heavy - description stripped, skill stays available |
| **`KEEP`** | Used, tiny, or manually protected |
| **`REVIEW`** | Too new or not enough sessions |

Every verdict includes a reason suffix explaining *why*, and an item whose
evidence was incomplete stays `REVIEW` rather than being flagged.

**2. `reap why <name>`** is how you argue with a verdict before acting on it.
It shows the whole case for one item, so you are not trusting a label:

```
skill:import-timesheet

verdict      REAP(unused)
reason       zero uses in the evidence window
token weight ~185 tok  (description: 684 chars)
sessions     34 total in window
uses         0
last seen    never
installed    unknown
keep-list    no
claude-md    not referenced
→ safe to prune. run: reap prune
```

**3. `reap prune`** asks before it moves anything, quarantines what you confirm
into `reaped/`, and ends by printing `reap restore --all`. If a verdict looks
wrong, `reap keep <name>` protects the item permanently instead.

<p align="center"><sub>The <code>why</code> output above is real, produced
against the same generated sample stack as the report at the top of this page
(<a href="docs/gif-helpers/hero-fixture.sh">hero-fixture.sh</a>) - so the item
names are the fixture's, not anyone's install.</sub></p>

<br>

## Why this exists

### Why I built this

I was running out of context budget on every session. I had accumulated skills,
MCP servers, and agents over months most of them experiments I'd forgotten
about or be too busy to change it. Every new session loaded all of them, burning tokens before I'd typed a
single message.

I needed to know which ones were actually firing and which were just dead
weight. Nothing existing told me that from transcript evidence. So I built it.

It now supports every platform in the table below, and ships on Homebrew, npm,
and as a static binary for every major OS.

<br>

### Two costs of context bloat

**Wrong-tool picks.** Buried in a wall of irrelevant options, your agent
wastes turns reaching for the wrong tool. More turns = slower, costlier,
sloppier runs. This isn't about pennies - it's about work quality.

**Wasted tokens.** Dead instructions eat context every session and hurt
prompt-cache hit rate. A typical setup:

<!-- readme-mine-costs:start -->
- 382 items loaded
- 369 never fired (96 %), of which 367 marked REAP
- 19 755 tok/session dead
- ~1 087 000 tok/month burned on irrelevant instructions
- ~$3.26/month, ~$39/year - the same waste priced instead of counted

<p align="center"><sub>The money line is one measurement of one stack, n=1, and the
weakest number here: <code>19 755 × 55 × $3.00 ÷ 1e6</code> - input tokens only, at
<code>claude-sonnet-4-6</code>'s $3.00/MTok default, with tokens estimated as
<code>ceil(chars / 3.7)</code> and the monthly session count extrapolated from a
30-day window. Change the model, the price, or how much you work and it moves;
the item and token counts do not. See <a href="#limitations-transparency">Limitations</a>.</sub></p>

<p align="center"><em>Measured on my own setup - 55 sessions over 30 days, 2026-08-23. Run <code>reap</code> to see yours.</em></p>
<!-- readme-mine-costs:end -->

skillreaper measures both, from evidence - no guessing.

> `reap` points at the waste. You decide what goes.

<br>

### Privacy

**100 % local.** Zero telemetry, zero network, zero uploads. Reads config
files and session transcripts on disk - your data never leaves your machine.

<br>

### Before → After: what removing token waste buys

<!-- readme-mine-table:start -->
| Before skillreaper | After skillreaper |
|---|---|
| 382 items loaded every session | 15 kept · 13 actually fire |
| 19 755 tok/session dead | Full context budget for real work |
| ≈ 73 000 dead chars ≈ 29 pages every session (at 500 words/pg) | Zero |
| Lower cache hit rate = higher latency | Smaller prompt fits in cache |

<sub>My own installation, measured 2026-08-23.</sub>
<!-- readme-mine-table:end -->

<br>

<p align="center">If this looks useful → <a href="https://github.com/thousandflowers/skillreaper">⭐ star the repo</a></p>

## Getting started

### Install

**Inside Claude Code** - adds `/skillreaper:reap` and `/skillreaper:gap`, so the
report renders in the conversation instead of a scrollback you have to re-read:

```
/plugin marketplace add thousandflowers/skillreaper
/plugin install skillreaper@skillreaper
```

The plugin is a thin wrapper: it drives the same binary, so install that too
with any line below. The skills fall back to `npx skillreaper` and tell you how
to install permanently if they can't find it.

**Install permanently** - Homebrew and npm install both names, `reap` and
`skillreaper`, so either one works. `go install` gives you `reap`:

```bash
# macOS — Homebrew
brew install thousandflowers/tap/skillreaper

# Any platform — npm (downloads the matching prebuilt, checksum-verified)
npm install -g skillreaper

# Any platform — Go (Go ≥ 1.24)
go install github.com/thousandflowers/skillreaper/cmd/reap@latest
```

> Already installed it with Homebrew? You don't need the npm package -
> both put `reap` and `skillreaper` in the same prefix, so `npm install -g`
> stops at an EEXIST link error rather than overwriting brew's copy.
> Pick one route: to switch to npm, run `brew uninstall skillreaper` first.
> Neither affects `npx skillreaper`, which runs from a cache and never
> links a global command.

**Binary downloads** - macOS (Intel + Apple Silicon), Linux (amd64 + arm64),
Windows (amd64 + arm64) - all on the
[releases page](https://github.com/thousandflowers/skillreaper/releases).
Single static binary, no dependencies.

Upgrading, uninstalling, and platform-specific tips →
[INSTALL.md](INSTALL.md).

<br>

### Usage
💬 **Curious what `reap` finds in other setups?** [Share your output →](https://github.com/thousandflowers/skillreaper/discussions)

```bash
reap                          # scan + report (read-only)
reap gap                      # loaded-vs-fired utilization + MCP payload quality
reap prune                    # quarantine REAP items (reversible)
reap mute <name>              # strip description, keep skill available
reap unmute <name>            # restore description from backup
reap unmute --all             # restore all muted skills
reap keep <name>              # protect an item from pruning
reap restore --all            # undo every prune
reap why <name>               # explain in detail why an item got its verdict
reap by-project               # skills bucketed by the project that fired them
reap route                    # propose a usage-informed lazy-load routing plan (opt-in)
reap apm                      # emit a proposed APM apm.yml from this repo's firing
reap apm --diff apm.yml       # reconcile: what to add (fired, undeclared) / drop (declared, cold)
reap share                    # print a ready-to-paste line about what you reclaimed
reap snapshot                 # save this run's --json payload for later comparison
reap diff                     # compare the newest two snapshots
reap diff <a> <b>             # compare two named snapshots
reap manifest <name>          # emit a release manifest for one skill
reap install-hook             # install weekly nudge (SessionStart hook)
reap install-hook --dry-run   # preview without writing
reap uninstall-hook           # remove hook, other hooks untouched
reap --json                   # structured JSON output
reap --md                     # markdown report
reap --days 7                 # shorter evidence window
reap --mute-threshold 0.20    # firing rate below which MUTE triggers (default 20%)
reap version                  # print version
```

<br>

### Demo

<p align="center">
  <img src="docs/reap-demo.gif" alt="reap in action" width="800"><br>
  <sub>Recorded against a small sample fixture
  (<a href="docs/gif-helpers/demo-fixture.sh">demo-fixture.sh</a>), so the
  numbers are the fixture's, not a real stack's.</sub>
</p>

<br>

### share - the number, ready to paste

`reap share` prints one line about what you reclaimed, with the install command
under it. Read-only: it measures and prints, nothing else. `--json` and `--md`
are there for anything that wants to post it automatically.

```
Just cut ~22.8k tokens/session of dead context from my AI agent with skillreaper.
One read-only command, 100% local:

  brew install thousandflowers/tap/skillreaper
  github.com/thousandflowers/skillreaper
```

<p align="center"><sub>Same generated sample stack as the report at the top of
this page - the figure is the fixture's, not mine.</sub></p>

<br>

## Reading the report

### Loaded vs fired: measuring context-window utilization

Beyond the prune verdicts, `reap gap` shows your **utilization rate** -
how much of what you load you actually use.

<!-- readme-gap:start -->
```
  ── loaded vs fired · last 30 days · 34 sessions ──────────────────────────────

  CATEGORY  LOADED  FIRED  UTIL              TOK LOADED  TOK USED
  skills       298      6    2%  ▏▱▱▱▱▱▱▱▱▱     ~21,693       278
  mcp           12      1    8%  ▏▱▱▱▱▱▱▱▱▱           ?         ?
  agents        68      0    0%  ▱▱▱▱▱▱▱▱▱▱      ~1,305         0
  ───────────────────────────────────────────────────────────────
  total        378      7    1%  ▏▱▱▱▱▱▱▱▱▱     ~22,998       278

  ~  MUTE — 2 heavy low-use skills, ~102 tok/session recoverable with reap mute
```
<!-- readme-gap:end -->

<p align="center"><sub>Same generated sample stack as the report at the top of this
page, so the two agree. The numbers further up the page are measured on mine.</sub></p>

Each row breaks down by category (skill, MCP, agent) with item count, token
weight, and a 10-segment utilization bar. The token column reads
*loaded → actually used*: the left number loads every session, the right is all
that is ever touched - the gap between them is dead weight that reloads each
time. Low utilization (<10 %) is red, medium (<50 %) yellow,
high (≥50 %) green.

The default `reap` report also includes a compact utilization summary line:

<!-- readme-utilization:start -->
```
  utilization 1%  7/378 items fired · ~278/22998 tok touched (30d)
```
<!-- readme-utilization:end -->

<p align="center"><sub>Same generated sample stack, not my install - as with the two
blocks above it.</sub></p>

This is the **real** gap between what your agent carries and what it fires -
complementary to the shock box (which only counts items that are safe to prune
right now).

<pre>reap gap          # text breakdown
reap gap --json   # JSON output
reap gap --md     # markdown table</pre>

The gap view also scores **payload quality** for MCP tools: when a tool fires,
is the result signal or noise? A fetch/screenshot tool can fire 80× and return
mostly base64 or boilerplate every call - green under load utilization, but
context burned on each call. Tools that fire often *and* return mostly noise are
flagged `⚑ noisy`. This is the second utilization axis (load is the first), and
mute does not catch it.

<br>

### by-project - which project actually fires each skill

A skill that looks cold across the whole window is often a skill that is alive
in exactly one repo. `reap by-project` buckets each fired skill by the project
that fired it, one row per skill-and-project pair, and marks a skill that fired
in exactly one project as `repo-local` - the case this view exists for, since a
per-repo tool should not be read as global dead weight.

```
  ── skills by project · last 30 days · 34 sessions ────────────────────────────

  SKILL            PROJECT        FIRINGS  NOTE
  audit-backlog    acme-platform       17  repo-local
  audit-catalog    acme-platform       11  repo-local
  audit-changelog  acme-platform        8  repo-local
  audit-contract   acme-platform        6  repo-local
  audit-dataset    acme-platform        5  repo-local
  audit-invoice    acme-platform        4  repo-local
```

<p align="center"><sub>Same generated sample stack as the blocks above. This
capture is one of the files <code>make renders-check</code> verifies, so it
cannot drift from what the binary prints.</sub></p>

<pre>reap by-project          # text table
reap by-project --json   # JSON output</pre>

<br>

## Beyond pruning

### route - context engineering for large tool libraries

After pruning, a library of hundreds of legit skills still grows resident
context linearly. `reap route` proposes a category-router organization driven by
**real firing evidence**, not text similarity: frequently-fired skills stay
exposed; the rare long tail is pushed behind leaf routers (grouped by namespace,
else dominant firing project) loaded on demand. It is strictly opt-in and

Frequently Asked Questions

What is skillreaper?

skillreaper is a Artificial Intelligence library for the Go programming language. CLI that scans AI agent session transcripts to identify and safely quarantine unused skills, MCP servers, and agents across Claude Code, Codex CLI, Hermes, OpenCode, Cursor, and OpenClaw

How do I install skillreaper?

Install skillreaper with the Go module system using `go get thousandflowers/skillreaper`. Check the repository for the current installation instructions.

What category does skillreaper belong to?

skillreaper is listed under Artificial Intelligence, specifically Artificial Intelligence.

← Back to Artificial Intelligence