You've been there. You rename a component, move a file, or quietly migrate from one styling approach to another โ and the old CSS stays behind. Nobody complains, the build doesn't break, and the dead selectors quietly accumulate.
css-ghost is a small Node.js CLI tool I built to solve that problem. Point it at a folder and it tells you every CSS class defined in your style files that isn't referenced anywhere in your components.
What it does
css-ghost scans your style files (.css, .module.css, .scss, .sass, .less, MUI makeStyles, vanilla-extract), extracts every class selector, then cross-references them against every component file it can find (.js, .jsx, .ts, .tsx, .vue, .svelte).
Anything defined but never actually used gets reported as an orphan โ with its line number and the full CSS rule printed inline, so you can see what it does before deciding to delete it.
It also catches orphaned CSS custom properties (--my-token: value defined but never consumed via var(--my-token) anywhere in the codebase), reported in a separate ๐ฎ section.
Run it now
No install required:
npx css-ghost ./src
Or install globally for repeated use:
npm install -g css-ghost
css-ghost ./src
Interactive folder picker
Run css-ghost with no arguments and an interactive directory picker opens. Navigate with โโ (or j/k), press Enter or โ to go into a folder, โ to go back up, [a] to add the current directory to the scan, then [d] when done:
css-ghost
Useful when you're not sure which subfolder to target, or want to scan multiple directories in one pass.
Dynamic class detection
If a component accesses classes dynamically โ styles[variable], styles[\${variant}] โ css-ghost can't resolve the class name statically. Rather than silently skip those files or report false positives, it flags them with a โ ๏ธ warning per file:
โ
src/components/Alert/Alert.module.css
โ ๏ธ Dynamic class references detected โ results may be incomplete.
Dynamic references in: src/components/Alert.jsx
๐ป .hidden (line 30)
.hidden { display: none; }
All statically resolvable patterns are still analysed: string literals, ternaries, cx({ active: isOn }) object keys, array literals, and both branches of ternaries.
Deleting orphans
Once you're happy with the report, pass --delete to remove every flagged selector from its source file:
css-ghost ./src --delete
css-ghost prints the full report first, lists what it's about to delete, then asks for confirmation. Pass --yes to skip the prompt in CI:
css-ghost ./src --delete --yes
Tip: commit or stash first. There's no undo.
Other useful flags
| Flag | What it does |
|---|---|
--ghost-trail |
Show the last git commit that touched each orphan |
--strict |
Exit with code 1 when orphans exist (CI / pre-commit) |
--install-hook ./src |
Write a pre-commit hook that blocks commits with orphans |
--output <path> |
Custom path for the markdown report |
--ai |
Append a plain-English AI summary (needs free OpenRouter key) |
Ghost trail
Pass --ghost-trail to fetch the last git commit that changed each orphan's occurrence count:
css-ghost ./src --ghost-trail
๐ป .iconRight (line 28)
๐ต๏ธ b5c6efb ยท Roland Levy ยท 3 weeks ago โ "Refactor Button component"
.iconRight {
margin-left: 6px;
}
Handy for tracking down when and why a class went dead.
Pre-commit hook
css-ghost --install-hook ./src
Writes .git/hooks/pre-commit (executable, chmod 755) that blocks commits whenever orphaned selectors exist. Remove it with rm .git/hooks/pre-commit.
How is it different from PurgeCSS?
PurgeCSS is a build-time bundler โ it hooks into webpack or PostCSS to strip unused CSS from your production output. It's designed for frameworks like Tailwind or Bootstrap where you use a fraction of the utility classes.
css-ghost is a source code auditor โ it finds dead selectors in your actual codebase, with no build step and no config file.
| PurgeCSS | css-ghost | |
|---|---|---|
| Works on source files | โ Build output only | โ |
| Zero config, no build step | โ | โ |
| CSS custom property orphans | โ | โ |
| Git history per orphan | โ | โ |
| Pre-commit hook | โ | โ |
| Deletes dead code for you | โ | โ |
| Safe with dynamic classes | โ Silently removes them | โ Flags with โ ๏ธ |
The two tools are complementary โ PurgeCSS for trimming framework output at build time, css-ghost for auditing your own hand-written CSS throughout development.
The source is on GitHub and the package is on npm. PRs and issues welcome.













