https://github.com/doramirdor/janitor
Sweep your ~/.claude/skills graveyard. Scans installed skills, MCP servers, and sub-agents, cross-references session logs, and shows what's actually used.
https://github.com/doramirdor/janitor
anthropic claude-code cleanup cli mcp skills
Last synced: 16 days ago
JSON representation
Sweep your ~/.claude/skills graveyard. Scans installed skills, MCP servers, and sub-agents, cross-references session logs, and shows what's actually used.
- Host: GitHub
- URL: https://github.com/doramirdor/janitor
- Owner: doramirdor
- License: mit
- Created: 2026-05-12T18:14:20.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-12T20:59:30.000Z (about 1 month ago)
- Last Synced: 2026-05-12T22:29:12.338Z (about 1 month ago)
- Topics: anthropic, claude-code, cleanup, cli, mcp, skills
- Language: JavaScript
- Size: 41 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Your ~/.claude/skills/ folder is a graveyard. Janitor sweeps.
```
npx claude-janitor
```
[▶ watch the full MP4](https://github.com/doramirdor/janitor/releases/download/v0.1.0/demo.mp4) · [static screenshot](docs/demo.svg)
- **Evidence-based.** Reads your session logs (`~/.claude/projects/`) for invocation counts and last-used dates — so you see what you actually use, not what you installed.
- **Covers skills, sub-agents, and MCP servers.** One scan across everything in `~/.claude/` — and it flags MCP configs that carry a plaintext credential.
- **Reversible by default.** `sweep` moves dust to an archive with a manifest; `restore` puts it back. `purge` is opt-in and requires `--yes`.
- **Plugin-aware.** Skills and sub-agents owned by a plugin are off-limits — Janitor won't desync your plugin manager, and points you at `/plugin uninstall ` instead.
> **Local-only.** Reads files in `~/.claude`. The only thing it writes is `~/.claude/janitor/archive/` (when you sweep). No network calls. No telemetry. Zero runtime dependencies.
## Commands
```
janitor scan and print report (default, read-only)
janitor sweep archive dust skills + sub-agents, remove dust MCP entries
janitor restore [id] restore the most recent (or named) archive
janitor archives list past sweeps
janitor purge [id] delete archive(s) — requires --yes
janitor --json machine-readable scan output
```
Add `--yes` to skip confirmation prompts (useful in scripts).
## Why
Skills install in seconds. Plugins install in bulk. Six months in, your `~/.claude/skills/` is a museum of things you tried once. Janitor reads your session logs to tell you what you actually use — and gives you one command to clean up the rest, reversibly.
On the author's own install: **97 skills installed, 3 used in the last 30 days.** Yours is probably similar.
## How it classifies
Applies to skills and sub-agents alike:
- **USED** — invoked in the last 30 days
- **DUST — user-installed, sweepable** — never invoked, older than the 14-day grace period, lives in `~/.claude/skills/` or `~/.claude/agents/`. Safe to sweep.
- **PLUGIN DUST** — never invoked, but owned by a plugin. Janitor will not touch these (the plugin manager would re-install them); it shows the `/plugin uninstall ` command instead.
- **NEW** — installed less than 14 days ago. Grace period.
For symlinked skills, install age is computed from the symlink's own birthtime, not the target file — so re-linking doesn't reset the grace period.
## FAQ
**Will it delete my stuff?**
No. `janitor sweep` moves dust skills to `~/.claude/janitor/archive//` and removes dust MCP entries from config (stashing the original key + a `.bak` of the full config in that same archive). `janitor restore` puts everything back. `janitor purge` is opt-in and requires `--yes`.
**Why won't it sweep plugin skills?**
Plugin skills live in the plugin cache, owned by Claude Code's plugin manager. Sweeping them would desync `installed_plugins.json` and they'd come back on the next plugin update. Use `/plugin uninstall ` for those. Same applies to plugin-bundled sub-agents.
**What about sub-agents?**
Janitor scans sub-agents from `~/.claude/agents/*.md` and plugin-bundled `agents/` directories, cross-references them against `Agent` tool invocations in your session logs, and classifies them USED/DUST/NEW exactly like skills. `janitor sweep` archives dust user-installed sub-agents (the `.md` file moves into the archive; `restore` puts it back). Plugin-bundled agents are reported but not swept.
**What about MCP servers?**
The report shows which MCP servers are installed, invoked, or orphaned. It reads MCP config from every source: `~/.claude.json` (user-level + project-scoped), `~/.claude/settings.json`, project-root `.mcp.json` files, skill-bundled `mcp.json`, and plugin-bundled `plugin.json` declarations. UUID-named connectors (Supabase, Gmail, Calendar, Vercel, Stripe, Drive) are fingerprinted by their method calls and labeled. Runtime-registered servers (`Claude_Preview`, `Claude_in_Chrome`, the session MCP) are detected and listed separately — they're not user-configurable, so they're not cleanup candidates. Servers that failed auth (per `mcp-needs-auth-cache.json`) are flagged `⚠ needs-auth`, and configs carrying an inline credential — a token in `env`, an `Authorization` header, a URL with embedded auth — are flagged `🔑 plaintext secret` with the offending location. `janitor sweep` removes dust MCP entries from `~/.claude.json` and `~/.claude/settings.json` — the entry's JSON is stashed in the archive manifest with a `.bak` of the full pre-edit config, and `janitor restore` re-inserts the key. Project-scoped and skill-bundled MCPs are intentionally left untouched by sweep (different lifecycles).
**Does it work with Claude.ai or Claude Desktop?**
No — Janitor reads Claude Code's local files (`~/.claude/`) and session logs (`~/.claude/projects/`). Claude.ai and the desktop apps don't expose equivalent local state.
**`--json` mode?**
`janitor --json` emits the full scan as JSON for dashboards, CI checks, or downstream tooling. Each `usage.mcpServers[]` entry carries `runtime` and `connector` fields (the same resolution the human report does) so consumers can tell a runtime-registered server or a known connector apart from a genuine unknown.
## Install
```
npx claude-janitor # one-shot
npm install -g claude-janitor # persistent
```
Requires Node 18+. Works on macOS and Linux. Not yet tested on Windows.
## Contributing
Issues and PRs welcome. The code is ~2,000 lines of zero-dependency Node split into single-purpose modules under [`src/`](src/) — `scan-skills`, `scan-agents`, `scan-mcp`, `parse-logs`, `resolve-mcp`, `report`, `sweep`. Tests live in [`test/`](test/) and run with `node --test test/*.test.js`.
## License
[MIT](LICENSE) © Dor Amir