Skip to content

Docs

RepoLens reads a project and gives you a map of how its files connect, plus a short, prioritised list of things worth a look.

Using the app

  1. Open a project. Choose a folder, pick a ZIP, or drop either anywhere on the page. Dropped folders skip node_modules, .git and build output automatically.
  2. Turn the map. Drag to rotate, scroll to zoom, shift-drag to pan, double-click a file to centre it. Files are grouped by folder into labelled constellations; colour them by language, folder, risk or kind.
  3. Select a file to see its neighbours: what it imports (teal) and what imports it (gold). Use What depends on it to light up its full blast radius, or Trace path to… to show the exact chain of imports between two files.
  4. Work the list. “Fix first” in the left rail is the shortest useful to-do list. Findings, Hotspots, Architecture and Packages give the full picture.
  5. Share. Export a JSON report (reopenable here), a Markdown summary, or a PNG of the map. Press Ctrl K for the command palette.

Command line

npx repolens [path] [options]

--json <file>      write the full report (open it later in the app)
--md <file>        write a Markdown summary
--impact <file>    list every file affected by changing <file>
--fail-on <level>  exit 1 on: secret | error | warning | cycle
--min-score <n>    exit 1 when the health score is below n
--max-files <n>    analyse up to n files (default 5000)
--no-gitignore     do not apply the project's .gitignore

The folder’s .gitignore is respected by default, symbolic links are never followed, and the tool makes no network connections.

In CI

# .github/workflows/repolens.yml
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
  with: { node-version: 22 }
- run: npx repolens . --fail-on secret --min-score 70 --md repolens.md

Supported languages

LanguageHow imports are found
JavaScript, TypeScript, JSX, TSXParsed with the TypeScript compiler. import, export … from, require, literal import(), type-only edges, tsconfig/jsconfig paths and baseUrl.
Vue, Svelte, AstroScript blocks (and Astro frontmatter) are parsed as TypeScript.
Pythonimport / from … import, absolute and relative, packages, namespace packages.
Java, Kotlin, ScalaImports matched to each file’s package declaration, including static and wildcard imports.
GoImport blocks resolved through go.mod module paths to package directories.
Rustmod, use (including braced lists), crate::, self::, super::.
C, C++#include "…" resolved relative to the file, common include directories and unique path suffixes.
C#using matched to namespace declarations.
Ruby, PHP, Dart, Swiftrequire / require_relative, require / include / use, import / export / part, import.

Other languages’ files are not analysed in depth. Only JavaScript/TypeScript is parsed by a real compiler; the rest use comment-aware pattern matching, which is dependable for imports but not a full parser.

What each finding means

Every finding is labelled confirmed (a fact about the graph) or review (a judgement call that needs a human). Findings are ordered by a priority that multiplies severity and certainty by how much of the project depends on the files involved.

FindingCertaintyMeaning
Credentialconfirmed / reviewA value shaped like an API key, token, private key or password appears in source. The value is never stored. Rotate it if real.
CycleconfirmedFiles import each other in a loop (type-only imports are excluded). The shortest loop is shown.
Directory cycleconfirmedDirectories depend on each other sideways or downward. A child importing from its own parent folder is not counted.
Broken importreviewA relative or aliased import that resolves to no included file.
Syntax errorconfirmedJavaScript/TypeScript the compiler cannot parse, or an invalid package.json.
Risky coderevieweval, raw HTML injection, shell execution, unsafe deserialization, disabled TLS checks, weak hashes and similar. Sometimes legitimate.
Complexityconfirmed (JS/TS) / reviewA function with cyclomatic complexity of 15 or more (each branch, loop, case and boolean operator counts one).
UntestedreviewA widely-used file that no test file reaches through imports. Shown only when the project has tests.
Undeclared packagereviewAn imported package that no covering package.json lists.
Unused packagereviewA production dependency with no traced import.
Unused exportreviewA named export that nothing in the project imports. Library entry points may use it legitimately.
UnreachablereviewNo import path connects the file to a recognised entry point. Dynamic loading and framework conventions can cause false positives.
DuplicateconfirmedSource files with identical text.
LayeringreviewA stable directory depending on a volatile one.

How scores are calculated

Health score

Start at 100 and subtract capped penalties for: exposed credentials (up to 30), syntax errors (15), circular dependencies (18), broken imports (8), risky constructs (8), complex functions (8), untested or untested-project (8), duplicates (6) and unused code (6). Except for credentials and syntax errors, penalties are divided by a size factor (the square root of the number of code files over 20, between 1 and 4), so a large project is not punished for simply being large. Every deduction is listed in the app under “How it is scored”. Grades: A ≥ 90, B ≥ 80, C ≥ 70, D ≥ 55, otherwise E.

Change risk (per file)

38% blast radius (how many files are affected, on a log scale) + 27% complexity of the most complex function + 15% not reached by any test + 10% size + 10% being part of a cycle. It is a prompt for where to look first, not a prediction.

Blast radius and centrality

Blast radius counts every file that depends on a file directly or through any chain of imports, each counted once. Centrality is PageRank over the import graph: high when important files lean on it.

Report format

Reports are JSON with schemaVersion: 2: nodes (files with metrics and 3D positions), edges, findings, folders, folderEdges, externals, health and fixFirst. They contain paths and findings only, never source text or secret values. When you open one, it is validated against strict bounds before use.

Limits