orphan-files
v1.0.0
Published
π¨ Find unused files in your JavaScript/TypeScript project by analysing the import graph
Maintainers
Readme
orphan-files
CLI tool for finding unused files in JavaScript/TypeScript projects.

Analyses the import graph (import, require, jest.mock, export * from, etc.) and reports files that are not reachable from any entry point β including whole islands of files that only import each other.
How it works
- Globs the project for source files (honouring
.gitignoreand yourexcludepatterns). - Parses each file with Babel and extracts every import specifier.
- Resolves each specifier (relative paths,
tsconfigpath aliases,baseUrl,import.meta.glob). - Determines entry points β
package.json(main/module/exports/bin/types), framework conventions (Next.js, Vite, Storybook, Remotionβ¦), tests, configs,index/mainbarrels, and your config. - Walks the graph from those entry points; anything it can't reach is unused.
This is a true reachability analysis: two dead files that import each other will not mask each other.
Installation
npm install -g orphan-filesCLI
# scan current directory
orphan-files
# scan a specific project
orphan-files /path/to/project
# preview what would be deleted, then actually delete
orphan-files --fix
orphan-files --fix --force
# explain why a file is kept (or unused)
orphan-files --why src/utils/helpers.ts
# CI: machine-readable output (exit code 1 when unused files are found)
orphan-files --format json
orphan-files --format sarif > orphan.sarif
# scaffold a config file
orphan-files --initOptions
| Option | Description |
| -------------------------- | --------------------------------------------------------- |
| -c, --config <path> | Config file (default: orphan-files.config.js) |
| -f, --format <type> | Output: cli, json, sarif, pdf (default: cli) |
| --sort <key> | Sort unused files: path, name, size |
| --group | Group unused files by directory |
| --why <file> | Explain why a file is kept or unused, then exit |
| --graph <type> | Print the dependency graph: mermaid, dot, html |
| --fix | Preview files that would be deleted (dry-run) |
| --force | With --fix, actually delete the files |
| --baseline <path> | Ignore unused files recorded in a baseline file |
| --update-baseline [path] | Write the current unused files as the baseline, then exit |
| --max-unused <n> | Exit 0 when the unused count is at most <n> |
| --no-gitignore | Do not honour .gitignore |
| --init | Write a starter config file, then exit |
| -v, --version | Print version |
| -h, --help | Show help |
Incremental adoption (baseline)
Record the current unused files and fail CI only on new ones:
npx orphan-files --update-baseline # writes .orphan-files-baseline.json
npx orphan-files --baseline .orphan-files-baseline.jsonVisualise the dependency graph
npx orphan-files --graph mermaid # paste into a Mermaid renderer
npx orphan-files --graph html > graph.htmlConfiguration
Create an orphan-files.config.js file in your project root:
export default {
include: ["**/*.{js,jsx,ts,tsx,mjs,cjs}"],
exclude: [
"**/node_modules/**",
"**/dist/**",
"**/.next/**",
"**/storybook-static/**",
],
// Entry points: kept, and everything they import is kept transitively.
entry: ["src/index.ts"],
// Also treated as entry points (kept and seed reachability).
exceptions: [
"index.{js,ts}",
"*.config.{js,ts,mjs,cjs}",
"**/*.test.{js,ts,tsx}",
"**/*.spec.{js,ts,tsx}",
"bin/**",
"scripts/**",
],
};Config files may be .js, .mjs, .cjs (default export) or .json. Monorepos
are supported: each workspace package's package.json entry points are honoured.
Framework auto-detection
The tool reads package.json and automatically adds exceptions for known frameworks:
| Framework | Detected exceptions |
| ------------- | ---------------------------------------------------------------------------------------------- |
| Next.js | app/**/page.tsx, app/**/route.ts, app/**/layout.tsx, sitemap.ts, middleware.ts, etc. |
| Storybook | **/*.stories.{ts,tsx} |
| Remotion | remotion.config.*, src/index.ts |
TypeScript path aliases
Reads tsconfig.json and resolves path aliases automatically (e.g. @/* β src/*).
Supported import expressions
import '...'/import x from '...'require('...')import('...')(dynamic import) β template literals likeimport(`./pages/${name}.js`)are matched as a globimport.meta.glob('./dir/*.js')(Vite)jest.mock('...')/vi.mock('...')export * from '...'/export { x } from '...'
Files using decorators (Angular, NestJS, TypeORM, MobX) and other modern TypeScript syntax are parsed correctly.
Continuous integration
Run it in CI and fail the build when unused files appear. Upload SARIF to get inline annotations in the GitHub "Code scanning" tab:
# .github/workflows/orphan-files.yml
name: orphan-files
on: [push, pull_request]
jobs:
unused:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npx orphan-files --format sarif > orphan.sarif
continue-on-error: true
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: orphan.sarifA reusable composite action is also provided:
- uses: piecioshka/orphan-files@v1
with:
directory: .
format: sarifAPI
import {
scanProject,
extractImports,
analyze,
findUnusedFiles,
explainFile,
} from "orphan-files";
const files = await scanProject("/path/to/project", "**/*.{js,ts}");
const fileImports = {};
for (const file of files) {
fileImports[file] = extractImports(file);
}
// High-level: graph + entry points + reachability + unused list
const result = analyze(files, fileImports, { projectDir: "/path/to/project" });
console.log(result.unused);
console.log(explainFile(files[0], result, "/path/to/project"));
// Or the simple helper (exceptionPatterns double as entry points):
const unused = findUnusedFiles(files, fileImports, [], "/path/to/project");
console.log(unused);Related packages
CLI / API
- knip β Detects unused files, exports, and dependencies in JS/TS projects; ~150 built-in framework plugins, supports monorepos.
- unimported β Scans a Node.js project and reports unimported files and modules. (archived March 2024 β author recommends knip)
- dead-files β Finds unused files in source code.
- deadfile β CLI for detecting unused (dead) code in JavaScript projects.
- dead-code-checker β Finds dead code in JavaScript and TypeScript projects.
- tsr β TypeScript Remove: removes unused code from TypeScript projects (tree-shaking for source files).
- ts-unused-exports β Finds exported TypeScript symbols (functions, classes, variables) not imported anywhere in the project.
- find-unused-exports β CLI and JS API for finding unused ECMAScript module exports.
- depcheck β Checks unused and missing dependencies in a Node.js project. (archived June 2025 β author recommends knip)
- orphan β Finds orphaned (unimported) files in a project.
- skott β Automatically builds and visualises the dependency graph, detects disconnected files.
- madge β Creates graphs from module dependencies; can identify files with no connections.
- rev-dep β Tracks imports, detects unused code, and cleans up dependencies via a fast CLI.
- next-unused β Finds unused files in Next.js projects.
- delete-react-zombies β Finds and removes unimported components in React projects.
Webpack plugins
- webpack-deadcode-plugin β Detects unused files and unused exports during a Webpack build.
- unused-files-webpack-plugin β Globs all files not compiled by Webpack in a given context.
- webpack-unused β Compares files in
src/against modules processed by the bundler. See also: overview on YouTube.
Vite / Rollup plugins
- vite-plugin-unused-code β Vite/Rollup plugin for detecting unused files and exports.
- rollup-plugin-unused β Rollup plugin for checking unused files.
- unplugin-slim β Detects unused dependencies and source files (unplugin).
ESLint plugins
- eslint-plugin-unused-imports β Reports and removes unused ES6 imports during linting.
License
The MIT License @ 2026
