New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

pruny

Package Overview
Dependencies
Maintainers
1
Versions
93
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pruny

Find and remove unused Next.js API routes & Nest.js Controllers

latest
Source
npmnpm
Version
1.43.5
Version published
Maintainers
1
Created
Source

pruny

Find and remove unused code in Next.js and NestJS projects.

Pruny scans your codebase using regex-based static analysis to detect unused API routes, page links, exports, files, public assets, and NestJS service methods. Works with monorepos out of the box.

Install

npm install -g pruny
# or
npx pruny

What It Detects

ScannerWhat it finds
API RoutesUnused Next.js route.ts handlers and NestJS controller methods
Broken Links<Link>, router.push(), redirect(), href: "/path" in arrays/objects pointing to pages that don't exist
Unused ExportsNamed exports and class methods not imported anywhere
Unused FilesSource files not reachable from any entry point
Unused ServicesNestJS service methods never called by controllers or other services
Public AssetsImages/files in public/ not referenced in code
Source AssetsMedia files in src/ not referenced in code
Missing AssetsReferences to files in public/ that don't exist

CLI Commands

CommandDescription
prunyInteractive scan (auto-detects monorepo apps)
pruny --allCI mode: scan all apps, exit 1 if issues found
pruny --fixInteractively delete unused items
pruny --dry-runSimulate fix mode and output a JSON report
pruny --app <name>Scan a specific app in a monorepo
pruny --folder <path>Scan a specific folder for routes/controllers
pruny --cleanup <items>Quick cleanup: routes, exports, public, files
pruny --filter <pattern>Filter results by path or app name
pruny --ignore-apps <list>Skip specific apps (comma-separated)
pruny --no-publicSkip public asset scanning
pruny --jsonOutput results as JSON
pruny -v, --verboseVerbose debug logging
pruny --dir <path>Set target directory (default: ./)
pruny -c, --config <path>Path to config file
pruny initGenerate a pruny.config.json with defaults

Configuration

Create pruny.config.json in your project root (or run pruny init):

{
  "ignore": {
    "routes": ["/api/webhooks/**", "/api/cron/**"],
    "folders": ["node_modules", ".next", "dist"],
    "files": ["*.test.ts", "*.spec.ts"],
    "links": ["/custom-path", "/legacy/*"]
  },
  "extensions": [".ts", ".tsx", ".js", ".jsx"]
}

Ignore Options

KeyWhat it doesExample
ignore.routesSkip API routes matching these patterns["/api/webhooks/**"]
ignore.foldersExclude directories from scanning["node_modules", "dist"]
ignore.filesExclude specific files from scanning["*.test.ts"]
ignore.linksSuppress broken link warnings for these paths["/view_seat", "/admin/*"]

All patterns support glob syntax (* matches any characters, ** matches nested paths).

Pruny also reads .gitignore and automatically excludes those folders.

Additional Config Options

KeyWhat it does
nestGlobalPrefixNestJS global route prefix (e.g., "api/v1")
extraRoutePatternsAdditional glob patterns to detect route files
excludePublicSet true to skip public asset scanning

Config File Locations

Pruny searches for config files recursively across your project:

  • pruny.config.json
  • .prunyrc.json
  • .prunyrc

In monorepos, configs from multiple apps are merged together. CLI --config takes precedence.

Multi-Tenant / Subdomain Routing

Pruny automatically handles multi-tenant architectures where routes live under dynamic segments like [domain].

For example, if your file structure is:

app/(code)/tenant_sites/[domain]/view_seat/page.tsx

And your components reference /view_seat (resolved at runtime via subdomain), Pruny recognizes this as a valid route and will not report it as a broken link. The matched tail must contain at least one literal segment (e.g., view_seat) — fully-dynamic tails like [token] alone won't match arbitrary paths.

If auto-detection doesn't cover your case, use ignore.links in config:

{
  "ignore": {
    "links": ["/view_seat", "/review", "/custom-path"]
  }
}

Monorepo Support

Pruny auto-detects monorepos by looking for an apps/ directory. It scans each app independently but checks references across the entire monorepo root.

# Scan all apps (CI-friendly, exits 1 on issues)
pruny --all

# Scan a specific app
pruny --app web

# Skip certain apps
pruny --ignore-apps admin,docs

CI Integration

Add to your CI pipeline to catch unused code before merging:

npx pruny --all

This scans all monorepo apps and exits with code 1 if any issues are found. Combine with --json for machine-readable output.

How It Works

  • Route Detection: Finds all app/api/**/route.ts (Next.js) and *.controller.ts (NestJS) files
  • Link Detection: Finds <Link>, router.push(), redirect(), href: "/path" in arrays/config objects, <a> tags, revalidatePath(), and pathname === comparisons — validates all against known page routes. The summary table always shows an "Internal Links" row when links are scanned, so you can see the feature is active
  • Reference Scanning: Searches the entire codebase for string references to routes, exports, and assets
  • Dynamic Route Matching: Understands [id], [...slug], [[...slug]] dynamic segments
  • Fix Mode: Removes unused methods, exports, and files with a cascading second pass to catch newly dead code

Vercel Cron Detection

Routes listed in vercel.json cron jobs are automatically marked as used:

{ "crons": [{ "path": "/api/cron/cleanup", "schedule": "0 0 * * *" }] }

Debug Mode

DEBUG_PRUNY=1 pruny

Enables verbose logging across all scanners.

License

MIT

Keywords

unused

FAQs

Package last updated on 04 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts