Limitations
Known limitations and edge cases of the current Prune implementation.
Prune's analysis is purely static — it reads source files without executing them. This provides speed and safety, but also means there are scenarios where the tool cannot determine reachability with certainty, or may produce incorrect results.
Language Support
Prune currently supports only JavaScript and TypeScript projects (language: js-ts). The language mode handles .js, .jsx, .ts, and .tsx files. There is no support for other languages in the current implementation.
Dynamic Imports and require()
Prune detects dynamic constructs — eval, Function, require, and import() — as suspicious_dynamic_usage findings. When any of these are present in a file, the confidence of unused_function and unused_variable findings for that file is downgraded to review.
However, Prune does not resolve dynamic import arguments. If your code uses patterns like:
const module = await import(`./components/${name}`);or
const mod = require('./handlers/' + handlerName);Prune has no way to determine which files are actually loaded at runtime. Files referenced only through such expressions will appear as unused_file findings.
Ignored Import Patterns
Only relative imports (starting with ./ or ../) and configured aliases are resolved to files in the project. Non-relative imports are treated as external packages and skipped from the dependency graph.
import React from 'react'; // skipped — external package
import { bar } from './local-module'; // resolved — analyzedPath aliases (e.g., @/, ~/) are resolved when configured:
ts_config:
enabled: true
baseUrl: .
paths:
"@/*":
- src/*Aliases not configured in ts_config are treated as external and skipped.
Alias Resolution Edge Cases
// [!code highlight]
- Scoped patterns like
@scope/*are not supported — only exact prefix matches (@/*,~/*) - Multi-level wildcards like
@utils/*/helperresolve only the first match segment - Missing targets are marked
reviewrather thansafe(conservative)
Barrel Files and Re-exports
Prune tracks re-exports at the import spec level, but reachability from a barrel file is limited. If src/index.ts re-exports from src/components/Button.ts:
export { Button } from './components/Button';Prune registers ./components/Button as an import of src/index.ts, and Button is marked as potentially used from that file. However, if Button is imported by a consumer that only imports from the barrel (import { Button } from '../index'), the link from the barrel's re-export to the original file is tracked only if Prune successfully resolves the re-export source path.
For accurate re-export tracking, ensure that the files involved are all within the scan paths and that relative paths resolve correctly.
Circular Dependencies
Circular imports are handled without infinite loops — each file is processed once regardless of how many times it appears in the import graph. However, circular dependency structures may cause false negatives (missed findings) in some edge cases where a symbol is only referenced through a cycle.
Unresolved Files
Import resolution attempts to match paths with and without extensions, and with index.* variants. If a file is imported using a pattern Prune does not recognize — such as a non-standard extension, a virtual module, or a build-tool alias — the import will not be resolved, and the target file may appear as unreferenced.
False Positives in Exported Symbols
Prune operates on the files discovered by the scanner. If your project exports symbols consumed by code outside the scan paths (e.g., a library whose consumers live in a separate repository, or code excluded by the exclude patterns), those exports will appear as unused.
This is expected behavior — Prune analyzes only what it can see.
AST Parse Errors
If Tree-sitter fails to parse a file (for example, due to a syntax error), Prune falls back to regex-based extraction for that file. The fallback is less precise than AST parsing and may miss some declarations or produce incorrect symbol counts, resulting in false positives or negatives for that file.
Test Files
Prune does not automatically exclude test files. If you do not want test files included in the analysis, add exclusion patterns:
scan:
exclude:
- '**/*.test.ts'
- '**/*.spec.ts'
- '**/__tests__/**'Otherwise, symbols referenced only from tests will appear as unused in production code, and test-only files may not appear as unused_file if they are imported by other test files.