Skip to content

doramirdor/janitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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 · static screenshot

  • 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 <name> 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 <name> 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/<timestamp>/ 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 <name> 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/scan-skills, scan-agents, scan-mcp, parse-logs, resolve-mcp, report, sweep. Tests live in test/ and run with node --test test/*.test.js.

License

MIT © Dor Amir

About

Sweep your ~/.claude/skills graveyard. Scans installed skills, MCP servers, and sub-agents, cross-references session logs, and shows what's actually used.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors