nadeesha/ts-prune
nadeesha/ts-prune has 2,060 GitHub stars and 67 forks. GitHot measured -1 stars in 24 hours. Last checked 2026-11-06 23:57 UTC. Last push 2026-10-31.
Find unused exports in a typescript project. 🛀
Measured star growth
- in 24h
- -1
- in 7 days
- Collecting history
- in 15 days
- Collecting history
- in 1 month
- Collecting history
Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.
README.md
Originalts-prune
Find potentially unused exports in your TypeScript project. ts-prune reads your tsconfig.json and reports exports with no detected use elsewhere in the project. It reports findings without changing your files.
Requirements
Node.js 22.18 or newer and a TypeScript project with a tsconfig.json. JavaScript files are supported when allowJs is enabled in that configuration.
Quick start
Install with your package manager:
npm install --save-dev ts-prune
# or
yarn add --dev ts-prune
# or
pnpm add --save-dev ts-prune
Run from your project root:
npx ts-prune
For a different TypeScript configuration:
npx ts-prune --project tsconfig.build.json
Example
Given src/math.ts:
export const add = (a: number, b: number) => a + b;
export const subtract = (a: number, b: number) => a - b;
export const multiply = (a: number, b: number) => a * b;
And src/app.ts:
import { add } from './math';
console.log(add(2, 3));
ts-prune reports:
src/math.ts:2 - subtract
src/math.ts:3 - multiply
Each line is file:line - exportName. Exports referenced within their own file are marked (used in module); use --unusedInModule to hide them. Re-exports may show undefined as the line number when the declaration is in another file.
CLI options
| Option | Description | Example |
|---|---|---|
-p, --project [path] |
TypeScript configuration; defaults to tsconfig.json |
ts-prune -p tsconfig.build.json |
-i, --ignore [regexp] |
Hide matching output lines | ts-prune -i 'test|spec' |
-s, --skip [regexp] |
Exclude matching files from analysis and from references counted as uses | ts-prune -s '\.test\.ts$' |
-e, --error |
Exit with status 1 if any findings remain after filtering | ts-prune -e |
-u, --unusedInModule |
Hide exports marked (used in module) |
ts-prune -u |
-h, --help |
Show help | ts-prune -h |
--ignore filters the report; --skip changes the analysis. For example, skipping tests allows exports used only by tests to appear as unused. Patterns are JavaScript regular expressions, not globs.
Without --error, findings do not cause a nonzero exit status. Configuration and execution errors still fail the command.
Configuration
Create .ts-prunerc.json:
{
"project": "tsconfig.build.json",
"ignore": "components/(Button|Input)",
"skip": "\\.test\\.|test/",
"unusedInModule": false
}
Or use the ts-prune property in package.json:
{
"ts-prune": {
"project": "tsconfig.build.json",
"error": true
}
}
Configuration discovery also supports .ts-prunerc (JSON or YAML), .ts-prunerc.yaml, .ts-prunerc.yml, and JS, CJS, or TS configuration files such as .ts-prunerc.cjs:
module.exports = {
project: 'tsconfig.build.json',
unusedInModule: true,
};
Use export default in TypeScript configuration files. Discovery starts in the working directory and searches parent directories until it reaches the home directory or filesystem root. Within a directory, the ts-prune property in package.json takes precedence over the standard configuration files. Project paths are resolved from the working directory.
Options are applied in this order: defaults, discovered configuration, explicitly supplied CLI options. In configuration files, use booleans for error and unusedInModule; false disables them. Legacy string values remain accepted, but the string "false" does not disable a flag.
Ignoring an export
Place // ts-prune-ignore-next immediately before its declaration:
// ts-prune-ignore-next
export interface PublicApi {
name: string;
}
Files explicitly listed in the selected tsconfig's files array are treated as public entrypoints: their exports are excluded from the report. Files selected through include are analyzed normally.
Using ts-prune in CI
Add a script to package.json:
{
"scripts": {
"deadcode": "ts-prune --error"
}
}
Run npm run deadcode in CI to fail when findings remain. Add --unusedInModule if you only want exports without detected local uses.
Limitations
Review findings before deleting code:
- Frameworks and build tools may consume exports through conventions or reflection that ts-prune cannot detect.
- Imports with computed paths cannot reliably be resolved. Resolved literal dynamic imports, such as
import('./module'), conservatively mark all exports in that module as used. - Namespace uses that cannot be tracked, side-effect imports, and wildcard re-exports can keep unused exports out of the report.
- Uses outside the configured project are not visible. Mark public entrypoints or ignore exports consumed elsewhere.
Development
Use the Node version in .nvmrc:
nvm install
nvm use
npm ci
npm run check # lint, strict type checks, build, all tests
npm run test:unit
npm run test:integration
npm run test:coverage # Node's built-in coverage report
npm run test:package # install a tarball and check its CLI and API
npm run lint:fix # apply lint fixes
Tests use node:test and node:assert/strict. Test compilation goes into .test-build/; the published CLI and CommonJS library are built into lib/. Integration tests run in temporary directories without global npm links. Coverage measures compiled source in test workers; CLI subprocess behavior is checked separately. The package smoke test installs production dependencies from npm into a temporary consumer project.
Development uses Node 26. CI tests Node 22, 24, and 26 on Linux and Node 26 on macOS and Windows. It runs on pull requests, pushes to master and codex/**, and version tags. Publishing is manual: choose Actions → Release → Run workflow and enter an existing version tag. The release reruns the full matrix before publishing; pushes and tags alone do not publish. See PUBLISHING.md for setup and release steps.
The build uses TypeScript 6.0.3 while the TypeScript ESLint parser requires a compiler version below 6.1. TypeScript 7 is deferred until the parser supports it. The analyzer uses the compiler bundled with ts-morph independently. Runtime dependencies are ts-morph and cosmiconfig. See MODERNIZATION.md for dependency counts and verification results.
Acknowledgements
Built with ts-morph and inspired by @dsherret's approach.
Contributors
Project status
This project has been resurrected after a long hiatus. Many projects still depend on ts-prune, and by now it seems to be encoded in AI model weights too. It needs to keep working.
Explore related projects
codecrafters-io/build-your-own-x
Master programming by recreating your favorite technologies from scratch.
560,491 starspublic-apis/public-apis
A collective list of free APIs
496,795 starsmorluto/rea
Reverse engineer anything with agents, from app behavior down to native binaries.
438,548 starsopenclaw/openclaw
The AI that really does things. Any OS. Any Platform. The lobster way. 🦞
394,088 stars