skill-graveyard
CLAUDE.md10 starsChanged 6 months agoMITView on GitHub
A CLI that audits which Claude Code skills the user actually invokes. It parses local session JSONL logs and cross-references the skill installs on disk to surface two signals from one parser: The four user-facing buckets (active / dead / missing / hallucinated) and their definitions are documented in README.md and are a stable contract. No secrets, no proprietary client names, no real session data ever lands in docs/ or README.md. Sample CLI output on the live site uses anonymized…
- Installs packages
- Commits and pushes
In this repositoryOne other file it gives its agents.
- AGENTS.mdAGENTS.md
The file
We split this CLAUDE.md into the rules it gives an agent
12 rules. About 0 are common, 9 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈9
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 59
No telemetry. No network calls anywhere in the runtime.
- Distinctive: line 86
Use only if release-please is blocked and a release is urgent:
- Distinctive: line 105
Don't push automatically after committing.
- Distinctive: line 106
Don't run destructive git operations (force-push, hard reset, branch delete) without confirmation.
- Very specific: line 126
Use bd for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
- Very specific: line 127
Run bd prime for detailed command reference and session close protocol
- Very specific: line 128
Use bd remember for persistent knowledge — do NOT use MEMORY.md files
- Distinctive: line 138
File issues for remaining work: - Create issues for anything that needs follow-up
- Distinctive: line 148
Verify: - All changes committed AND pushed
- Distinctive: line 153
NEVER stop before pushing - that leaves work stranded locally
- Distinctive: line 154
NEVER say "ready to push when you are" - YOU must push
- Distinctive: line 155
If push fails, resolve and retry until it succeeds <!-- END BEADS INTEGRATION -->
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
A CLI that audits which Claude Code skills the user actually invokes. It parses local session JSONL logs and cross-references the skill installs on disk to surface two signals from one parser:
- Dead installs — skills present on disk, never invoked → safe to remove.
- Hallucinated invocations — skills invoked that aren't installed → external-framework registrations, model tool/skill confusion, or typos.
The four user-facing buckets (active / dead / missing / hallucinated) and their definitions are documented in README.md and are a stable contract.
This repo is public
No secrets, no proprietary client names, no real session data ever lands in docs/ or README.md. Sample CLI output on the live site uses anonymized project names (e.g. client-analytics, clientco/web-platform) — keep that pattern when refreshing screenshots. If you spot a real-looking name slipping in, mask it before pushing.
Layout
This is an npm workspaces monorepo:
packages/core/—@skill-graveyard/core(published). Shared parser, discovery, paths, tokenizer, known_tools. GenericparseToolCalls<T>lets sister CLIs reuse the JSONL stream.packages/skill-graveyard/— published asskill-graveyard. CLI, all subcommand implementations (audit,prune,suggest,projects,cost,outdated),format.ts.packages/mcp-graveyard/— published asmcp-graveyard. CLI for auditing MCP server tool usage. Mirrors skill-graveyard's bucket model (active/dead/missing/hallucinated) but for MCP servers.packages/memory-graveyard/— published asmemory-graveyard. CLI auditing per-projectMEMORY.mdindex +memory/*.mdentries. v1 surface:audit,lint,prune,projects. Same monorepo conventions; no plugin distribution.skills/skill-graveyard/SKILL.md,skills/mcp-graveyard/SKILL.md,skills/memory-graveyard/SKILL.md— Agent Skill manifests for skills.sh. Discovered when users runnpx skills add sfrangulov/skill-graveyard. NOT shipped in any npm tarball — read directly from the GitHub repo.release-please-config.json,.release-please-manifest.json— release-please configuration (per-package settings, current version baseline). See the Release section below..github/workflows/release-please.yml— automated release workflow (open Release PR on push to main, publish + tag + GH release on PR merge).docs/— Pages site (docs/index.html) and design specs (docs/specs/).
Inside each package:
src/cli.ts(skill-graveyard only) — argument routing; no business logic.src/{audit,prune,suggest,projects,cost,outdated}.ts— one subcommand per file (skill-graveyard).src/{parser,discovery,paths,tokenizer,known_tools}.ts— primitives (core).src/format.ts(skill-graveyard) — every terminal rendering helper (sparkbars, tables, colors). Subcommands return data; this file prints.src/*.test.ts— colocated; flat under each package'ssrc/.
Development
npm install
npm run build --workspace=@skill-graveyard/core # build core first; skill-graveyard depends on its dist
npm run dev --workspace=skill-graveyard -- <subcommand> # tsx, no build step
npm run typecheck # both workspaces (delegates via --workspaces --if-present)
npm test # both workspaces
npm run build # both workspacesNode ≥18. Runtime deps: gpt-tokenizer (in @skill-graveyard/core). skill-graveyard itself only depends on @skill-graveyard/core at runtime.
Tests
Each package runs the same node --import tsx --test src/*.test.ts pattern. Single *, unquoted, shell-expanded — do not change to 'src/**/*.test.ts': bash on Ubuntu CI doesn't expand ** without globstar, and node --test on Node 20 won't expand a literal glob either. Both failure modes have happened. If tests ever need subdirectories within a package, switch the test runner — don't paper over the glob.
Tests use real fs against os.tmpdir() fixtures. No fs mocking. The whole purpose of this tool is correctly walking real Claude Code install layouts; mocked filesystem tests would defeat the point.
Intentional non-features
These look like missing features. Verify with the user before "fixing":
prunenever executes/plugin remove. It prints the command for the user to run inside Claude Code. Invoking CC slash commands from outside the runtime is fragile and is explicitly out of scope.pruneignores project-scoped skills (<project>/.claude/skills/). Per-project artifacts are intentional.- No telemetry. No network calls anywhere in the runtime.
README.mdpromises "all analysis is local" — keep it true. - The
costsubcommand usescl100k_baseBPE as a proxy for Claude's tokenizer (Anthropic doesn't publish one for Claude 3+). User-facing output must keep the 5–15% drift disclaimer. - No Claude Code plugin / slash commands. We tried, then removed in skill-graveyard@0.10.0 / mcp-graveyard@0.3.0. The plugin layout repeatedly collided with skills.sh-bundled SKILLs in the
/<plugin>:namespace and the autocomplete UX never landed cleanly. If reintroducing, the SKILL files inskills/MUST stay outside the plugin's auto-scanned paths (Claude Code's plugin loader picks up<plugin-root>/skills/automatically), or the namespace collision will reappear. prune --applysemantics differ across the three CLIs by design.mcp-graveyard prune --applyandmemory-graveyard prune --applyboth execute (with backups), because they operate on files we own.skill-graveyard pruneonly prints removal commands — disabling installed skills/plugins requires invoking Claude Code's runtime (claude /plugin remove), which is fragile from outside CC. Don't "fix" this divergence to match — the asymmetry is the right answer.
Release
Automated via release-please
Do not run npm publish, git tag, or gh release create manually. All three packages release through release-please, configured in release-please-config.json + .release-please-manifest.json and driven by .github/workflows/release-please.yml. Manual workflows compete with the bot and create version drift.
How it works:
- Author commits with conventional-commit prefixes when the change should ship as a release:
fix:(patch),feat:(minor),feat!:orBREAKING CHANGE:in body (major).chore:/docs:/refactor:/test:/ci:show in CHANGELOG history but don't bump versions. Bare imperative subjects without a prefix are fine for non-release changes. - On push to
main, the release-please action either opens or updates a "Release PR" listing the queued bumps for any package with releasable commits. GitHub setting required: Settings → Actions → General → "Allow GitHub Actions to create and approve pull requests" must be ON, otherwise the bot fails with "GitHub Actions is not permitted to create or approve pull requests." - Merging the Release PR triggers the publish job: tags (
<component>@vX.Y.Z), GitHub releases, and conditionalnpm publishper package. UsesNPM_TOKENautomation token, no OTP. Core publishes first if its release was created.
Things to know:
binpath in each package must bedist/cli.js— no./prefix. With./, npm strips the entirebinentry from the published tarball with only a warning.npm pkg fixnormalizes this.- For
skill-graveyard, the prepack/postpack scripts copyREADME.md,LICENSEfrom repo root into the package dir at pack time (so the npm package displays the canonical README). Ifnpm packerrors mid-way during local debugging,postpackdoes NOT run — manually clean withrm -f packages/skill-graveyard/{README.md,LICENSE}ifgit statusis dirty. mcp-graveyardships its own README from inside the package, no prepack hack.@skill-graveyard/corehas no GitHub release per release-please config — internal-facing only.- Marketplace-merged Release PRs need the autorelease label. If you ever have to open a release PR manually (because the bot was blocked when it tried), copy the
autorelease: pendinglabel that release-please normally adds — without it, release-please won't recognize the merge as a release commit and won't create tags / GH releases / npm publishes.
Manual fallback (emergency only)
Use only if release-please is blocked and a release is urgent:
- Bump
versioninpackages/<name>/package.jsonand.release-please-manifest.jsonlockstep. Add a## [X.Y.Z]section topackages/<name>/CHANGELOG.md. npm publish --workspace=<name>with an interactive OTP — ask the user to run! npm publish --workspace=<name> --otp=NNNNNNso the result lands in the conversation.git tag -a <component>@vX.Y.Zand push.gh release create <component>@vX.Y.Zwith notes from the CHANGELOG entry.- release-please will resync its state on the next push.
Docs site
The Pages site (https://sfrangulov.github.io/skill-graveyard/) deploys automatically from main branch, path /docs. Any push touching docs/ triggers pages-build-deployment. Live URL is referenced from README.md, the homepage field in package.json, and homepage in .claude-plugin/plugin.json — change all three together if the URL ever moves.
CI
.github/workflows/ci.yml runs typecheck, test, build per workspace via an 8-cell matrix: {@skill-graveyard/core, skill-graveyard, mcp-graveyard, memory-graveyard} × {Node 20, Node 22}. fail-fast: false — one cell's failure does not cancel the others. Before any CLI's typecheck/test/build runs, a conditional step builds @skill-graveyard/core first (the CLIs import types from packages/core/dist/).
Conventions
- Commit subjects are short, lowercase, imperative ("fix ci test glob", not "Fixed the CI test glob"). Conventional-commits prefixes (
fix:,feat:,chore:,docs:, etc.) are permitted but not required — use them when they help release tooling infer bump types, otherwise a bare imperative subject is fine. NoCo-Authored-Byline unless the user asks for one. - Don't push automatically after committing. Wait for explicit confirmation.
- Don't run destructive git operations (force-push, hard reset, branch delete) without confirmation.
.claude/at the repo root is local Claude Code state. It's untracked and intentionally not in.gitignore— leave it alone.
<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:7510c1e2 -->Beads Issue Tracker
This project uses bd (beads) for issue tracking. Run bd prime to see full workflow context and commands.
Quick Reference
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --claim # Claim work
bd close <id> # Complete workRules
- Use
bdfor ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists - Run
bd primefor detailed command reference and session close protocol - Use
bd rememberfor persistent knowledge — do NOT use MEMORY.md files
Architecture in one line: issues live in a local Dolt DB; sync uses refs/dolt/data on your git remote; .beads/issues.jsonl is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns.
Session Completion
When ending a work session, you MUST complete ALL steps below. Work is NOT complete until git push succeeds.
MANDATORY WORKFLOW:
- File issues for remaining work - Create issues for anything that needs follow-up
- Run quality gates (if code changed) - Tests, linters, builds
- Update issue status - Close finished work, update in-progress items
- PUSH TO REMOTE - This is MANDATORY:
git pull --rebase git push git status # MUST show "up to date with origin" - Clean up - Clear stashes, prune remote branches
- Verify - All changes committed AND pushed
- Hand off - Provide context for next session
CRITICAL RULES:
- Work is NOT complete until
git pushsucceeds - NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds
<!-- END BEADS INTEGRATION -->Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

