Your dead code check says every file is used. It may be wrong.
I ran Graphify on a large React codebase. It builds a graph of files and imports, and you can ask an LLM questions about it.
I asked for files that nothing imports. It found them. But it also found something I didn’t ask for: dead islands.
A dead island
A dead island is a group of files that import each other, while nothing outside the group imports them. They are never used by the real app.
The smallest one is two files: a component and its test. The test imports the component, so the component looks used. Tools like Knip treat tests and stories as entry points, so they don’t report it.
useElementSize.ts is 52 lines. The only file that imports it is useElementSize.test.ts, 252 lines.
Smallest island
Test
useElementSize.
- imports useElementSize.ts
Code
useElementSize.ts
- useElementSize.test.ts imports useElementSize.ts
One example
6 files in 3 folders. A container, the button it renders, two test files and two test mocks. 467 lines, and only 168 of them are product code. Nothing in the app had used it for about a year.
Dead island
Test
Invoices/
InvoiceMenu.
- imports InvoiceMenu.tsx
Test
Invoices/
InvoiceMenu.
- imports InvoiceMenu.tsx
- imports csvFile.mock.ts
- imports zipFile.mock.ts
Code
Invoices/
InvoiceMenu.tsx
- imports MenuItem.tsx
Code
shared/
MenuItem.tsx
Test mock
mocks/
csvFile.
Test mock
mocks/
zipFile.
- Code
- Tests and mocks
6 files, 467 lines, unused for about a year.
Imports 28 files from the rest of the app
0 imports back
- InvoiceMenu.export.test.tsx imports InvoiceMenu.tsx
- InvoiceMenu.test.tsx imports InvoiceMenu.tsx
- InvoiceMenu.test.tsx imports csvFile.mock.ts
- InvoiceMenu.test.tsx imports zipFile.mock.ts
- InvoiceMenu.tsx imports MenuItem.tsx
InvoiceMenu.test.tsx and InvoiceMenu.export.test.tsx import InvoiceMenu.tsx, which renders MenuItem.tsx. The tests also import two mocks: csvFile.mock.ts and zipFile.mock.ts.
The island imports 28 files from the app. The app imports none back.
Why it matters
Software hygiene. Dead files are not free.
Every refactor, codemod, search and AI agent run reads them, and often changes them. You keep maintaining code nobody uses. Fewer files means less to read, for people and for agents.
Results
119
files
~5,700
lines
Dead code, in one repository.
Try it on your codebase
After building the import graph, ask:
- List dead files and dead islands.
- What insights do you have about the dead islands?
- Sort dead files by last change, oldest first. The oldest are most likely leftovers.
- Find the pull request that made this island dead. Gather the clues and share hypotheses about why.
- Which tests and mocks only cover code that nothing else imports?
Found with a file-import graph (Graphify). The idea is general, not tied to one tool.
Do you look for dead islands in your codebase?
