π Detect and eliminate unused code in TypeScript/JavaScript projects safely and efficiently.
Detect and optionally remove unused code across TypeScript/JavaScript projects. Includes detectors for Cypress custom commands and Playwright fixtures. Safe defaults, CI-friendly reports, and an ignore file for precise scoping.
npm install -g universal-dead-code-analyzer-eliminationOr run without installing globally:
npx universal-dead-code-analyzer-elimination src/Analyze your project without making changes:
universal-dead-code-analyzer-elimination src/This will scan all .ts, .tsx, .js, and .jsx files in the src/ folder and report unused items.
Generate a report instead of modifying files:
universal-dead-code-analyzer-elimination src/ --reportChoose a report format:
universal-dead-code-analyzer-elimination src/ --report --report-format json
universal-dead-code-analyzer-elimination src/ --report --report-format md- JSON β machine-readable, great for CI/CD.
- Markdown β human-readable, ideal for PR comments.
--report first.
universal-dead-code-analyzer-elimination src/ --deleteThis removes unused members directly from your source files.
-
Dead/Unused Code Detection
- Functions, classes, variables, constants, enums, types, interfaces.
- Named & default exports.
- Cypress commands: Detects
Cypress.Commands.add("foo")not used ascy.foo(...). - Playwright fixtures: Declared but never injected.
- React components: Unused PascalCase components.
- Tree-shaken export graph: Finds unused exports.
-
File Exclusions
-
Always ignores
node_modules/. -
Supports
.analyzerignore(works like.gitignore). -
Generate a template:
universal-dead-code-analyzer-elimination --init-ignore
-
-
Reports
- JSON, Markdown, and CLI summary.
- Example summary:
Found 12 unused members across 5 files.
-
Safety First
- Default mode is non-destructive.
.analyzerignorelets you control scope.- Clear, colorized logs for confidence.
-
Initialize ignore rules:
universal-dead-code-analyzer-elimination --init-ignore
-
Run safe report:
universal-dead-code-analyzer-elimination src/ --report --report-format md
-
Review the report, update
.analyzerignoreif needed. -
When confident, clean up:
universal-dead-code-analyzer-elimination src/ --delete
targets...Files or globs to analyze (defaults tosrc/**/*.{ts,tsx,js,jsx}andtests/**/*.{ts,tsx,js,jsx})-r, --reportReport only (default true)-f, --report-format <json|md>Output format (defaultmd)-d, --deleteDelete unused members (destructive)--cwd <dir>Working directory--init-ignoreCreate a default.analyzerignorein project root--out <file>Write report to a file
- Unused functions, classes, methods, variables, enums, types, interfaces, and certain default exports (heuristic)
- Unused exported symbols that are never referenced/imported elsewhere (simple tree-shake heuristic)
- Unused React components (PascalCase) not found in any JSX
- Unused Cypress custom commands declared via
Cypress.Commands.add('name', ...)not referenced ascy.name(...) - Unused Playwright fixtures declared through
test.extend<{ name: ... }>()but never injected in test callbacks like `({ name })
β Framework entry files (Next.js
pages/**orapp/**) are treated as entrypoints and never flagged.
Works like .gitignore. Example:
node_modules/
dist/
coverage/
**/*.spec.ts
**/*.test.ts
**/__tests__/**
# Ignore legacy folder
# src/legacy/**Create it with:
analyzer --init-ignore- Start with
--report. Review the output. - Commit your code before running
--delete. - Consider running in CI with JSON report and failing on findings to control adoption.
name: unused-code
on: [push, pull_request]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- run: node ./dist/cli.js --report --report-format json --out analyzer-report.json
- run: |
node -e "const r=require('fs').readFileSync('analyzer-report.json','utf8'); const j=JSON.parse(r); if(j.summary.totalUnused>0){console.error('Unused code found');process.exit(1)}"unused_code:
image: node:20
script:
- npm ci
- npm run build
- node ./dist/cli.js --report --report-format json --out analyzer-report.json
- node -e "const r=require('fs').readFileSync('analyzer-report.json','utf8'); const j=JSON.parse(r); if(j.summary.totalUnused>0){console.error('Unused code found');process.exit(1)}"
artifacts:
paths: [analyzer-report.json]Create a new file in src/lib/detectors/yourDetector.ts that implements a scan(globs): Promise<ScanResult>. Merge its results in src/lib/UniversalUnusedCodeAnalyzer.ts..
The package integrates with GitHub Checks API to annotate unused code inline in pull requests.
- Always start with
--reportbefore--delete. - Review
.analyzerignorecarefully to avoid accidental removal. - Commit before running
--deletefor easy rollback.
For convenience, add scripts to your package.json:
{
"scripts": {
"analyze": "universal-dead-code-analyzer-elimination src/ --report",
"analyze:delete": "universal-dead-code-analyzer-elimination src/ --delete"
}
}See CONTRIBUTING.md.
MIT @ Mohamed Said Ibrahim
See CHANGELOG.md.
- Built with TypeScript and
ts-morph. - Default behavior is non-destructive.
- Deletion is best-effort and may not handle every edge case. Review diffs.