<p align="center">
<img src="docs/assets/banner.svg" alt="haircut" width="760">
</p>
<p align="center">
<strong>Your coding agent pays for a full head of context before it reads your first word. Sit down.</strong>
</p>
<p align="center">
haircut finds every instruction file, MCP server, hook, skill and plugin your agents load,<br>
prices each one in tokens from your own transcripts, and parks what you decide to lose. Nothing is deleted.
</p>
<p align="center">
<a href="https://github.com/OthmanAdi/haircut/stargazers"><img src="https://img.shields.io/github/stars/OthmanAdi/haircut?style=flat&color=111111&label=stars" alt="Stars"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-111111?style=flat" alt="MIT license"></a>
<img src="https://img.shields.io/badge/works%20with-Claude%20Code%20%C2%B7%20Codex%20%C2%B7%208%20more-111111?style=flat" alt="Works with 10 agents">
<img src="https://img.shields.io/badge/node-18%2B-111111?style=flat" alt="Node 18 or newer">
</p>
<p align="center">
<a href="#before--after">See it</a> ·
<a href="#install">Install</a> ·
<a href="#what-it-does">What it does</a> ·
<a href="#what-you-get">Commands</a> ·
<a href="#verdicts">Verdicts</a> ·
<a href="#honest-numbers">Honest numbers</a> ·
<a href="#how-it-works">How it works</a> ·
<a href="#faq">FAQ</a>
</p>
---
You did not choose most of it. A plugin brought four hooks. A tutorial left an MCP server. Three skills have the same name and only one of them ever loads. Every session pays for all of it, in full, before you have typed anything.
haircut holds up the mirror so you can see what the back of your head costs.
## Before / after
<table>
<tr>
<th width="50%">Today</th>
<th width="50%">After a haircut</th>
</tr>
<tr>
<td valign="top">
```text
session start
before your first word 37,000 tokens
worst cold start 93,000 tokens
skill listing, every start 6,735 tokens
and again at every subagent start
MCP servers loading 25
never called in 45 days 9
skills, commands, agents 331
never invoked in 45 days 283
hooks, 45 days
fires 80,918
tokens re-injected 2.1M
waiting, critical path 17.6 h
one pre-tool-call hook
1,556 fires, 1.2M tokens re-sent
another one
2,774 fires, nothing injected, 3.8 s each
```
</td>
<td valign="top">
```text
haircut, 45-day window, 524 items
PARK 258 TRIM 7 ROTATE 7
ASK 14 FIX 1
KEEP 138 INERT 99
parking what actually loads
per session start 7,312 tokens
about a fifth of the cold start
receipt
bag ~/.haircut/bags/<run>/
manifest MANIFEST.jsonl, one line per move
undo haircut restore
nothing deleted, every move hashed
```
</td>
</tr>
</table>
Same machine, same window, real numbers from the sample run in [docs/HONEST-NUMBERS.md](docs/HONEST-NUMBERS.md). Nothing was deleted to get there. Every moved file sits in the bag with its hash, and one command puts it back.
## Install
Claude Code, two prompts:
```
/plugin marketplace add OthmanAdi/haircut
```
```
/plugin install haircut@haircut
```
Any terminal, no Claude Code needed:
```bash
npx github:OthmanAdi/haircut
```
Zero dependencies, Node 18 or newer, nothing to configure. It reads the config of every agent it finds, including the ones you installed years ago and forgot. The plugin and the CLI are the same program, so you can run it from a shell, from a cron line, or from inside a session.
## What it does
<p align="center">
<img src="docs/assets/pipeline.svg" alt="scan, measure, report, decide, trim, restore" width="900">
</p>
Five deterministic stages and one AI stage. The AI stage argues about judgement calls. It never does the arithmetic.
| stage | what happens | measured or estimated |
|---|---|---|
| **scan** | Walks every agent's config roots and lists what loads: MCP servers, hooks, skills, commands, agent definitions, plugins, instruction and memory files, settings, leftovers. Read only. | a census, no numbers claimed |
| **measure** | Reads your own transcripts and prices each item: tokens before the first word, per session, per fire, per call, plus latency, failure rate and last use. | fires, latency, calls and before-first-word are measured; injected text and file sizes are byte estimates |
| **report** | Writes `REPORT.md`, `report.json` and a self-contained local HTML page, plus a decisions file pre-filled from the verdicts. | carries the label through on every row |
| **decide** | The one AI stage. Your agent reads the report with you, overrules the verdicts it disagrees with, and edits the decisions file. | judgement |
| **trim** | Moves what you marked into a dated bag, writes one manifest line per operation, and backs up any config file before editing it. | nothing is deleted, ever |
| **restore** | Walks the manifest backwards and puts the bag back. Refuses to overwrite anything that returned on its own. | also deletes nothing |
## What you get
| command | what it does |
|---|---|
| `haircut` | Scan, measure, report, then print the summary. The whole job. |
| `haircut scan` | Inventory every agent's config. Read only. |
| `haircut measure` | Price it from your own transcripts. Read only. |
| `haircut report` | Re-render `REPORT.md` and the HTML page for the latest run. |
| `haircut probe` | Connect to every MCP server you configured and count its tool schemas. Kills only the servers it started. |
| `haircut trim <decisions>` | Park what you decided, with a receipt. Moves, never deletes. |
| `haircut restore [--bag ID]` | Put a bag back where it came from. |
| `haircut status` | What is parked, which runs exist. |
| `haircut inspect <file>` | Print one truncated example of every record shape in a transcript. |
Useful flags: `--days N` for the window (default 90), `--agents claude-code,codex` to narrow it, `--deep` to read every Codex rollout in the window instead of the newest 1500, `--probe`, `--dry-run`, `--json`, `--open`, `--quiet`.
Two skills ship with the plugin: `/haircut` runs the pipeline and walks the report with you, `/haircut:restore` finds the right bag and undoes a trim.
## Verdicts
Every item gets one. They are proposals on a page, not actions.
| verdict | meaning |
|---|---|
| `KEEP` | stays as it is |
| `TRIM` | stays, but cut down or reconfigured |
| `FIX` | wanted but broken |
| `PARK` | goes in the bag; nothing is deleted, restore puts it back |
| `ROTATE` | a credential sits in plain text; rotate it and move it to an environment variable |
| `ASK` | your call; the reason lists the options |
| `INERT` | listed for completeness, costs nothing where it sits |
**PARK never deletes.** It renames a file into a dated bag and writes down where it came from.
## Honest numbers
> [!IMPORTANT]
> **What is measured and what is guessed.** Tokens before the first word come from the API's own usage fields in your transcripts, so those are real. Hook fires, latency, failure rates, tool calls and last-use dates are counted from transcript records, also real. Everything else (injected hook text, skill listings, instruction files, MCP schemas) is bytes divided by a ratio per content type. That estimate was calibrated against an open tokenizer, and Anthropic's own tokenizer runs 5 to 15 percent higher, so treat those rows as a floor. Every table in the report says which is which.
Claude Code already ships `/context`, `/skill-doctor` and `/doctor`. On Claude Code alone, for the live session, with no undo, they cover a good slice of this. haircut adds the rest:
- every agent on the machine, not one (Codex, OpenCode, Cursor, Gemini, Copilot, Windsurf, Continue, Claude Desktop, VS Code)
- hooks priced in tokens per fire, with latency and failure rate
- duplicates and scope shadowing, the copies that load and the copies that never do
- a deterministic script that finishes in seconds and gives the same answer twice
- a report you keep, so next month's run has something to compare against
- a bag, a manifest and a restore command
The prize is smaller than the shock. Claude Code defers MCP tool schemas until something searches for them, so the recoverable part of a cold start is usually a modest share, not the headline number. In the sample run it came to about 7,300 tokens per session start against a 37,000-token average cold start, roughly a fifth. Codex has no deferred tools: every enabled server sends its full schemas with every model call, so there the same cleanup pays on every turn instead of once per session.
Method, ratios, window semantics and the full sample-run table: [docs/HONEST-NUMBERS.md](docs/HONEST-NUMBERS.md).
## How it works
1. It reads each agent's own config roots, the user scope and the project scopes, and resolves what actually loads when several copies share a name.
2. It reads your transcripts, which the agents already wrote to your disk. It parses them, it does not send them anywhere.
3. It prices each item in tokens, marks each number measured or estimated, and proposes a verdict with a reason you can read.
4. It writes the run folder: inventory, measurements, `REPORT.md`, an HTML page, and a decisions file where every PARK is pre-selected and everything else is set to later.
5. Nothing has changed yet. Scan, measure and report never write outside the run folder.
6. `haircut trim` acts only on what the decisions file says to park. Files move into a dated bag, config files get backed up verbatim first, and each MCP server or plugin is removed through the agent's own CLI where one exists.
7. Every operation appends one line to `MANIFEST.jsonl`: timestamp, item, source, destination, hash, and a note for anything it skipped.
8. `haircut restore` reads that manifest backwards. Symlinks are relinked, edits are pointed at their saved originals, and anything that came back on its own is left alone.
## Privacy
No network, no telemetry, no accounts, no phoning home. haircut reads files that are already on your disk and writes files next to them. Credentials are detected by shape, counted, and never printed, copied or stored; the report shows the file, never the value. The only outbound connections happen if you ask for `haircut probe`, and they go to the MCP servers you configured yourself, which it starts, questions, and shuts down again.
## FAQ
**Will it delete my stuff?**
No. `trim` renames things into a dated bag and writes a manifest. `restore` reads the manifest backwards. The one thing it ever unlinks is a symlink, and only after writing down what it pointed at, so restore can put the link back.
**Does it rewrite my CLAUDE.md?**
No. It measures it: bytes on disk, bytes that actually load, tokens per session, and whether the tail ever reaches the model. The prose is your job, and `/doctor` is good at helping with it.
**Why not just `/doctor`?**
Use both. `/doctor` inspects one agent, in a live session, with no receipt. haircut covers every agent on the machine, prices hooks per fire, catches duplicates and shadowed copies, and hands you a bag you can undo. Different tools, same barbershop.
**Does it work on Windows?**
Yes, first. It was written on Windows, junctions and all, then taught macOS and Linux. Restoring a symlink needs Developer Mode or an elevated shell; it says so rather than failing quietly.
**Why haircut?**
Because you already know how it goes. You sit down, someone who has seen worse looks at the situation, and you agree on how much comes off. Nothing grows back faster for being worried about.
## Star this repo
It costs nothing and takes less time than the haircut. Your context window is going to need one anyway.
## License
[MIT](LICENSE). Short back and sides.