The whole-project static analyzer that tracks what is truly live, what has gone rogue, and where JavaScript turns into fog.
rogue-lint moves through a codebase like a careful rogue moving through a forest: it starts from entrypoints and public surface, follows only the paths it can actually prove, and keeps track of what is really consumed. It traces same-project reachability, imports, exports, locals, object paths, array slots, returned structures, helper-carried values, callback correlation, retained bindings, discarded results, and selected safety failures. That lets it report the code and values that have gone rogue from real use. When the proof holds, it emits a real finding. When the path disappears into dynamic JavaScript, it emits an explicit conservative boundary instead of pretending it still knows the way.
→ starts from entrypoints and public surface
→ follows proven usage across files, structures, returns, callbacks, and helpers
→ reports dead code, dead structure, dead values, and selected safety failures
→ preserves intentional API surface and explicit keep rules
→ marks dynamic fog with explicit skipped boundaries
→ stays truthful to JavaScript semantics
Quick Start • See It In Action • Docs • Development
Most code analysis tools fail in one of two ways:
- they stay shallow and only see file-local syntax
- they overreach in dynamic JavaScript and turn uncertainty into false positives
rogue-lint is built to avoid both.
Use it when you want:
- whole-project reachability instead of isolated lint warnings
- symbol-liveness analysis across imports, exports, locals, and members
- export and type-surface analysis that understands application mode versus library mode
- exact object and array path cleanup in the supported subset
- explicit
findings,skipped, anddiagnosticsby default, withkeptavailable when you ask for it - output that humans can read and agents can automate against
Requires Node.js 20 or newer.
Install in a project:
npm install -D rogue-lintRun it:
npx rogue-lint .
npx rogue-lint . --json
npx rogue-lint . --kept
npx rogue-lint . --mode library
npx rogue-lint . --kinds unused-export,unused-file,use-before-init
npx rogue-lint . --config rogue-lint.config.jsonIf you prefer a global install:
npm install -g rogue-lint
rogue-lint .Default exit codes:
0: no findings1: findings were produced2: execution failed
Both non-zero exit codes are configurable.
A fixture-backed text report looks like this:
rogue-lint
Mode: application
Files analyzed: 4
Reachable files: 3
Findings: 9
Skipped: 2
Findings:
unused-export
src/lib.ts
unused-export src/lib.ts:2:14 unusedExport - exported declaration has no non-declaration references outside its declaring file
unused-file
src/unused.ts
unused-file src/unused.ts:1:1 unused.ts - file is unreachable from configured entrypoints
Skipped:
object-key
src/index.ts
object-key src/index.ts:24:3 maybe - computed property access prevents exact path analysis
Pass --kept when you want preserved public-surface and suppression audits in either text or CLI JSON output.
That structure is the trust model in practice:
findings: stale code or suspicious flows the analyzer can justifyskipped: explicit conservative boundaries where exact reasoning stoppedkept: otherwise-dead entities intentionally preserved by public-surface rules, suppressions, or keep rules, available via--keptor the library API
rogue-lint currently covers:
- whole-project reachability and API surface:
unused-file,unused-export,unused-type,unused-enum-member - symbol-liveness across imports, local declarations, and members:
unused-import,unused-local,unused-class-member,unused-interface-member - exact structural cleanup:
unused-array-element,unused-object-key,unused-nested-path - value-flow and safety signals:
dead-store,unused-value,write-only-state,use-before-init,invalidated-read,stale-read-after-mutation - same-project namespace or member helpers, callback correlation, awaited returns, and structured-return propagation in the supported exact subset
- retained bindings through supported
Map.setandMap.get, local object-backed static slots, module bindings, and staticglobalThisflows - JS-truthful value-fate modeling for supported
push,unshift,slice,concat,structuredClone, and bounded single-item consume paths, plus explicit boundaries when those flows stop being exact
For the detailed coverage map and fixture-backed examples, see CAPABILITIES.md.
- Load the project through TypeScript and the current
tsconfigorjsconfigwhen present. - Build the same-project module graph.
- Discover roots from configured entrypoints, package metadata, or conventional defaults.
- Compute reachable files.
- Layer exactness-gated object, array, helper, return, and value-flow analysis on top of semantic data.
- Emit
findings,kept,skipped, anddiagnostics.
In application mode, entrypoints define runtime roots. In library mode, the analyzer preserves the public package surface inferred from configured entrypoints or from package.json main and exports, while still treating bin entrypoints as reachable roots.
- CAPABILITIES.md: tested coverage map, examples, and conservative boundaries
- docs/ARCHITECTURE.md: module ownership map and maintenance rules for the refactored engine
- docs/CONFIGURATION.md: modes, entrypoint discovery, filters, keep rules, suppressions, and config precedence
- docs/OUTPUT.md: text and JSON reports,
findingsversuskeptversusskipped,collection-boundary, and skip-category reference - CONTRIBUTING.md: repo workflow, fixture-first changes, and validation expectations
For local development in this repository:
npm install
npm run lint
npm run build
npm testHelpful repo-local commands:
npm run self
npm run self:json
npm run check
npm run pack:check
npm run prepnpm run self and npm run self:json build the package and run rogue-lint against this repository in library mode.
The repository regression suite also keeps a normalized self-host baseline for that library-mode output, enforcing zero findings, zero skips, and zero diagnostics.
Before publishing:
npm run prepThat gate runs the build, lint, tests, self-analysis, and dry-run pack checks that currently define the package release flow.
This project is source-available under the PolyForm Noncommercial License 1.0.0.
The public license allows noncommercial use, study, modification, and redistribution. Commercial use is not permitted without separate permission from the licensor.
In practical terms, uses that require separate permission include incorporating rogue-lint into paid products, internal company tooling, hosted services, or commercial AI and LLM products or capability bundles.
Because the public license restricts commercial use, this project is not open source under the OSI Open Source Definition.