An open API service indexing awesome lists of open source software.

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.

Awesome Lists containing this project

README

          


claude-janitor


Your ~/.claude/skills/ folder is a graveyard. Janitor sweeps.


npm
test status
MIT
95 tests
node ≥18

```
npx claude-janitor
```


claude-janitor terminal demo

[▶ 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