khendzel/janitor-swipe
Tinder for your Claude Code skills. Reviews a sorted deck of every installed skill and lets you swipe keep / delete / skip on each one. Use when the user wants to bulk-clean their skill collection, triage unused skills, or do interactive skill cleanup. Trigger with '/janitor-swipe'.
npx skills add https://github.com/khendzel/skills-janitor --skill janitor-swipe
A bash TUI that puts every installed skill into a sorted deck and lets the user swipe keep / delete / skip on each card.
The deck is sorted "most likely waste first" — heavy, never-used skills appear at the top, so most users hit ← delete a few times and quit before reviewing the whole list. The swipe is scope-aware and honest about what it can delete: user-scope skills are actually removed (after confirmation), plugin skills are flagged for review instead.
scripts/swipe.sh and swipe-build-deck.sh)!Inside Claude Code, the Bash tool's stdin is non-interactive, so the keypress reader can't work. The user must invoke it via the ! prefix so the command runs in their actual shell:
!bash ~/.claude/skills/skills-janitor/scripts/swipe.sh
When the user asks for /janitor-swipe, tell them to run that command in their terminal. Do NOT try to run it yourself via the Bash tool — it will error with "needs an interactive terminal".
Each card shows:
[3 / 47])X always · Y on trigger (description tokens are permanent; body loads only when the skill fires)user, project, plugin · <plugin-name>, etc.)Controls:
← / h / d — stage for delete→ / l / k — keep↓ / j / s / space — skipu — undo (back up one card, clear its decision)i — inspect (show full SKILL.md description)q / Esc — quit (still shows summary for decisions made so far)| Scope | What happens on swipe left |
|---|---|
| user, project, codex-user, codex-project | Path is staged for rm -rf (or unlink if symlink) |
| plugin, plugin-source | NOT deleted — flagged under "Plugins to review" at the apply screen, with a hint to run /plugin uninstall <plugin> if enough skills from that plugin were swiped |
| mcp-user, mcp-project (v1.7) | Server entry is removed from its config file (~/.claude.json / .mcp.json) with a timestamped .bak backup — reversible |
| mcp-plugin | NOT edited — flagged for plugin review like plugin skills |
MCP server cards show real call counts from session transcripts instead of token guesses (schemas live server-side). An unused connected server ranks high — its tool schemas load into context for nothing.
After the last card (or q), an apply screen shows keep/skip/delete counts, the deletion list with paths, the "frees X always-loaded + Y on-trigger" token summary, the plugin review breakdown, and a prompt:
y — apply deletions immediately (logged to ~/.skills-janitor/log.jsonl with path and frontmatter snapshot)N — cancelsave — write decisions to ~/.skills-janitor/swipe-<timestamp>.json for later application via swipe.sh --apply <file>Solution: The command was run through the Bash tool. Have the user run it with the ! prefix in their own terminal.
Solution: The terminal window is too small — resize and retry.
Solution: Nothing is installed (exits 0 with a message) — suggest /janitor-discover to find skills.
Solution: Point them at /janitor-report or /janitor-value for the same data in list form.
Edge cases handled by the script: Ctrl-C mid-swipe restores the terminal; symlinks are unlinked, never followed; old saved decks without the v1.5 token-split fields still load.
Input: "/janitor-swipe" or "help me clean up my skills interactively"
Output: Explain the flow in two sentences, then give the exact command to run: !bash ~/.claude/skills/skills-janitor/scripts/swipe.sh — and offer to review the results afterwards.
Input: "I saved my swipe decisions yesterday — apply them."
Output: !bash ~/.claude/skills/skills-janitor/scripts/swipe.sh --apply ~/.skills-janitor/swipe-<timestamp>.json (list the files in ~/.skills-janitor/ to find the right one).
{baseDir}/../../scripts/swipe.sh; deck builder: {baseDir}/../../scripts/swipe-build-deck.sh~/.skills-janitor/log.jsonl/janitor-report — same data as a non-interactive list/janitor-value — the token + usage data underneath the swipe deck/janitor-fix --prune — automated broken-symlink cleanup, no interactive reviewTake khendzel/janitor-swipe from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.