npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tsx-prune

v1.2.0

Published

Analyze and remove unused components, files, imports, and exports in TypeScript/React codebases

Readme

tsx-prune

Analyze and safely remove unused components, files, imports, and exports in TypeScript/React codebases.

npm version License: MIT


Features

  • Unused file detection — find files unreachable from your entry points
  • Unused export detection — find exports never imported anywhere
  • Unused import detection — find and remove imports not used in the file body
  • React component detection — detect JSX components never referenced anywhere
  • Safe deletion — never deletes test files, stories, or spec files
  • Config file supporttsx-prune.config.ts / tsx-prune.config.json
  • tsconfig path aliases — respects baseUrl and paths from your tsconfig.json
  • JSON output — machine-readable output for CI pipelines
  • Fast — uses ts-morph AST cache and fast-glob for 10k+ file projects

Installation

# Global install
bun add -g tsx-prune
npm install -g tsx-prune

# Or use without installing
bunx tsx-prune
npx tsx-prune

Usage

# Dry run (default) — shows what would be removed
tsx-prune

# Delete unused files
tsx-prune --delete

# Remove unused imports
tsx-prune --fix-imports

# Remove export modifier from unused exports
tsx-prune --fix-exports

# All fixes together
tsx-prune --delete --fix-imports --fix-exports

# Custom entry points
tsx-prune --entry src/main.tsx src/server.ts

# Ignore patterns
tsx-prune --ignore "src/legacy/**" "src/vendor/**"

# JSON output (for CI)
tsx-prune --json

# Silent mode
tsx-prune --silent

# Custom tsconfig
tsx-prune --tsconfig tsconfig.app.json

# Use a config file
tsx-prune --config tsx-prune.config.ts

Example Output

  Scanning 342 files...
  Entry points: 3 found

  Unused Files:
    ✗ src/components/OldCard.tsx
    ✗ src/utils/legacyHelpers.ts
    2 unused files found

  Unused Exports:
    src/components/Button.tsx
      ✗ <ButtonGroup>
      ✗ ButtonSize

    1 file with unused exports

  Unused React Components:
    <ButtonGroup>, <CardVariant>
    2 unused components found

  ─────────────────────────────────────────
  Summary: 342 files scanned
    ✗ 2 unused files
    ✗ 2 unused exports
    ✗ 2 unused React components

  Dry run complete. Use --delete to remove files.

Configuration File

Create tsx-prune.config.ts (or .json) at your project root:

// tsx-prune.config.ts
export default {
  entry: ["src/main.tsx", "src/server.ts"],
  ignore: [
    "src/legacy/**",
    "src/vendor/**",
    "**/*.generated.ts",
  ],
};
// tsx-prune.config.json
{
  "entry": ["src/main.tsx"],
  "ignore": ["src/legacy/**"]
}

Options

| Flag | Description | Default | |------|-------------|---------| | --delete | Delete unused files | false (dry run) | | --dry-run | Show what would be deleted | true | | --fix-imports | Remove unused import statements | false | | --fix-exports | Remove export from unused exports | false | | --entry <paths...> | Entry point files or globs | src/main.tsx, src/index.tsx, etc. | | --ignore <patterns...> | Additional glob patterns to ignore | — | | --root <dir> | Root directory to scan | process.cwd() | | --tsconfig <path> | Path to tsconfig.json | ./tsconfig.json | | --json | Output results as JSON | false | | --silent | Suppress all output | false | | --config <path> | Path to config file | auto-detected |


Default Entry Points

When no --entry is specified, tsx-prune looks for:

  • src/main.tsx / src/main.ts
  • src/index.tsx / src/index.ts
  • src/app.tsx / src/App.tsx
  • src/pages/** (Next.js pages router)
  • src/app/** (Next.js app router)
  • pages/**
  • app/**

Safety Rules

tsx-prune never deletes:

  • *.test.ts / *.test.tsx
  • *.spec.ts / *.spec.tsx
  • *.stories.tsx / *.stories.ts
  • Files inside __tests__/ or tests/
  • Files inside .storybook/
  • Files with dynamic imports pointing to them

Comparison

| Feature | tsx-prune | ts-prune | knip | |---------|-----------|----------|------| | Unused files | ✓ | — | ✓ | | Unused exports | ✓ | ✓ | ✓ | | Unused imports | ✓ | — | ✓ | | React component detection | ✓ | — | — | | Safe deletion CLI | ✓ | — | — | | JSX-aware analysis | ✓ | — | — | | tsconfig paths | ✓ | — | ✓ | | Config file | ✓ | — | ✓ | | JSON output | ✓ | — | ✓ | | React-optimized | ✓ | — | — |


Programmatic API

import {
  scanFiles,
  Parser,
  buildGraphFromFileInfos,
  analyze,
  reportAnalysis,
} from "tsx-prune";

const files = await scanFiles({
  root: "./src",
  extensions: [".ts", ".tsx"],
  ignore: [],
  entry: [],
});

const parser = new Parser({
  tsconfig: "./tsconfig.json",
  root: "./src",
  extensions: [".ts", ".tsx"],
});

parser.addFiles(files);
const fileInfos = new Map(files.map((f) => [f, parser.parseFile(f)]));

const graph = buildGraphFromFileInfos(fileInfos);
const result = analyze(graph, fileInfos, {
  entryPoints: ["./src/main.tsx"],
  ignorePatterns: [],
});

reportAnalysis(result, { json: false, silent: false, cwd: process.cwd() });

Development

# Install dependencies
bun install

# Build
bun run build

# Run directly (no build step needed with Bun)
bun run src/cli.ts

# Type-check
bun run lint

# Test
bun test

License

MIT