VS Code extension
See unused code, duplication, complexity hotspots, and boundary violations in VS Code while you edit, and fix them in one click. Includes inline warnings and Code Lens reference counts.
The VS Code extension shows fallow findings in your editor while you write code, so you can fix them before you commit. The fallow LSP server gives real-time diagnostics for unused code, duplication, complexity, and boundary violations.
Sidebar views and status-bar items cover more of fallow:
- project health
- security candidates
- runtime coverage
- the audit verdict for changed files
- monorepo workspace scope
- license management
Code Lens shows a reference count above each export. Click it to peek all usages. You can see at once which exports have zero references.
Features
- Real-time diagnostics for dead-code issue types. The LSP server updates them, with no separate CLI process
- Code Lens with reference counts above each export (click to peek references)
- Hover information with export usage counts, unused status, and duplicate block locations
- Quick-fix code actions to remove unused exports or delete unused files, or to copy the finding id of a dead-code or security diagnostic
- Refactor actions to extract duplicates into shared functions
- Tree views in the sidebar with an icon for each category, an issue count badge, and a welcome view
- Status bar with color-coded severity, a tooltip with a breakdown, and command links
- Diagnostic documentation links: click a diagnostic code to open its docs page
- Related information: circular dependencies, duplicate exports, and code duplication diagnostics link to all related files
- Fix preview with a searchable Quick Pick to review fixes and go to them
- JSON schema for
.fallowrc.jsonwith autocomplete and validation - Auto-download of the LSP binary
- Getting Started walkthrough on first install
Codebase intelligence surfaces
The extension also shows the rest of the fallow analysis. Each one is a sidebar view or a status-bar item. Most are on by default. The Security Candidates view is opt-in, and the Runtime Coverage view stays empty until you load a capture:
- Health view (sidebar): the project health score and grade, the top complexity findings, and hotspot and refactoring candidates. A separate run computes it when you need it. To turn it off, use
fallow.health.enabled. - Security Candidates view (sidebar): local security candidates (
client-server-leak, the tainted-sink CWE catalogue). These are unverified candidates to verify, never confirmed vulnerabilities. To turn it on, usefallow.security.enabled. - Runtime Coverage view (sidebar): hot paths and cleanup candidates (safe-to-delete or review-required) from a loaded coverage capture.
- Audit verdict (status bar): pass, warn, or fail for your current change set, the same as
fallow audit. - License management: activate, view the status of, refresh, and deactivate the fallow license for continuous or multi-capture runtime coverage in the editor.
- Monorepo workspace scope (status bar): a picker that limits sidebar analysis to one package. The limit also applies to the Health, Security, and Audit views. The extension passes the package as
--workspace.
Installation
Install the extension
Search for "fallow" in the VS Code extensions marketplace. You can also install from the command line:
code --install-extension fallow-rs.fallow-vscodeBinary resolution
The extension finds the binary for you. It checks these places in order:
- the
fallow.lspPathsetting node_modules/.bin/for a local devDependency (pnpm add -D fallow)- the system PATH
If it finds no binary, it downloads one from GitHub releases. Before it installs the download, the extension verifies the Ed25519 signature of the binary. When a release has no signature file, it compares the SHA-256 digest from the GitHub release. If the check fails, the extension does not install the binary.
The extension downloads the binary from the GitHub release of its own version. After an extension update, that release can take some minutes to appear. In that time, the extension keeps the verified binary that you already have and tells you once per session. When
fallow.autoDownloadis on, it retries in the background and offers a restart when the new binary is in place. When no binary is installed, the download prompt names the release that is not published yet.- the
Getting Started walkthrough
After the first install, a walkthrough opens with four steps: Run your first analysis, Explore the results, Fix an issue, and Configure rules. Each step links to its command. To open it again, use the Command Palette.
Start coding
Open a TypeScript or JavaScript project. The extension starts and runs the analysis. Diagnostics show inline, and Code Lens annotations show above exports.
Status bar
The status bar shows the current issue count and duplication percentage. When the LSP server completes an analysis, it sends a custom fallow/analysisComplete notification, and the status bar updates. No separate CLI process runs.
- Color-coded background: red when there are unresolved imports (errors), yellow when there are other issues (warnings), and the default color when the project is clean
- Rich tooltip: hover to see all issues by category, such as unused files, exports, dependencies, circular dependencies, and clone groups
- Command links in tooltip: Run Analysis, Auto-Fix, and Show Output
You can turn each of these status-bar items on or off:
- Health score segment with the project grade (toggle with
fallow.health.statusBar) - Audit verdict for the current change set: pass, warn, or fail, color-coded, with a gating-candidate count (toggle with
fallow.audit.statusBar.enabled) - License indicator showing the active license state (toggle with
fallow.license.showStatusBar) - Workspace scope picker that shows the package the analysis is limited to in a monorepo (hidden in single-package projects)
Diagnostics
Each diagnostic has a clickable diagnostic code, such as unused-export or unresolved-import. The code opens its documentation page at docs.fallow.tools.
Related information
Some diagnostics link to the other files in the issue. To go to a related location, click it in the Problems panel.
- Circular dependencies: each file in the cycle is a related location, so you can follow the full cycle
- Duplicate exports: links to the other files that export the same name
- Code duplication: links to all other instances of the duplicated block
- Prop drilling: links to each component that passes the prop and to the component that uses it
- Duplicate prop shapes: links to the other components with the same prop shape
Finding ids
Each dead-code diagnostic has a quick fix, Copy Fallow finding id. It copies the stable finding_id of the finding to the clipboard, for example dc1:unused-export:81a349a3b9ea3b15. The id is the same as the finding_id field in fallow dead-code --format json, so you can find the same finding in a CLI or CI report. The id does not change when code above the finding moves.
A security candidate diagnostic has the same quick fix. It copies the security finding_id, which is the same id as in fallow security --format json and the MCP security_candidates tool.
The language server puts the id in the data.findingId key of each dead-code diagnostic, next to changedSince and the circular-dependency cycleId. A security candidate diagnostic has data.findingId next to its security object. Other LSP clients can read the id there.
Severity levels
| Issue type | Severity | Appearance |
|---|---|---|
| Unresolved imports | Error (red) | Red underline |
| Unused files, dependencies, circular deps, duplicate exports | Warning (yellow) | Yellow underline |
| Unused exports, types, enum/class members | Hint | Faded text (unnecessary tag) |
| Code duplication | Information (blue) | Blue underline |
| Security candidates (opt-in) | Information (blue) | Blue underline |
| Prop drilling, thin wrappers, duplicate prop shapes (opt-in) | Hint | Dots under the start of the component line |
| Config patterns that match nothing | Information (blue) | Faded entry in the config file |
Security candidate diagnostics are off by default. They are separate from the Security Candidates sidebar view. They show in the editor gutter only when you raise the security-sink or security-client-server-leak rule to warn or error in your fallow config. Each one is an unverified candidate to verify, shown as information and never as a red error. The hover shows the confidence signals first and points to fallow security --file for the full trace. A quick-fix dismisses the candidate.
The component health signals are off by default too. When you set prop-drilling, thin-wrapper, or duplicate-prop-shape to warn or error under rules, each finding shows as a hint on the component and in the sidebar tree. The hints do not add to the issue count. To hide one type in the editor, set it to false in fallow.issueTypes.
An ignoreDependencies glob or an ignoreFindings pattern that matches nothing has no effect. The editor marks the entry in .fallowrc.json, .fallowrc.jsonc, fallow.toml, or .fallow.toml. For an extends chain, the diagnostic goes on the file that declares the list. See Unmatched config patterns.
Tree views
The sidebar groups issues by type and duplicates by clone family. Each category has its own icon:
| Category | Icon |
|---|---|
| Unused files | File |
| Unused exports | Method |
| Unused types | Interface |
| Unused dependencies | Package |
| Unused enum members | Enum member |
| Unresolved imports | Error |
| Circular dependencies | Sync |
| Duplicate exports | Files |
A badge on the sidebar icon shows the total issue count. Before the first analysis, a welcome view shows a "Run Analysis" button.
Click an item in the tree to open the file at its line and column.
Fix preview
Fallow: Preview Fixes (Dry Run) opens a searchable Quick Pick with each available fix, its type, and its file location. Select an item to go to it in the editor. To apply all fixes at once, choose Apply all fixes at the bottom.
After it applies fixes, the extension saves the changed files, restarts the LSP server, and runs the analysis again. The diagnostics then update.
Config autocomplete
The extension gives .fallowrc.json files autocomplete and validation from the published JSON schema. You do not need to set this up.
Commands
| Command | Description |
|---|---|
| Fallow: Run Analysis | Run full analysis |
| Fallow: Reload Analysis | Run the analysis again |
| Fallow: Inspect Active File | Collect the fallow evidence for the file in the active editor |
| Fallow: Inspect Symbol at Cursor | Collect the fallow evidence for the symbol at the cursor |
| Fallow: Set Baseline at HEAD | Create or use the local fallow-baseline tag at HEAD, set fallow.changedSince, and refresh analysis |
| Fallow: Auto-Fix (unexport unused, remove unused deps) | Apply auto-fixes |
| Fallow: Preview Fixes (Dry Run) | Preview fixes in a searchable Quick Pick |
| Fallow: Restart Language Server | Restart the language server |
| Fallow: Show Output Channel | Open the LSP output channel |
| Fallow: Toggle Hide Code-Duplication Findings | Hide or show the code duplication diagnostics |
| Fallow: Toggle Hide All Findings | Hide or show all fallow diagnostics in the editor |
| Fallow: Hide Diagnostic Category | Hide one diagnostic category in the editor |
| Fallow: Manage Hidden Findings... | Choose the diagnostic categories to hide |
| Fallow: Show All Findings | Show all diagnostic categories again |
| Fallow: Reload Health | Re-run the Health view analysis |
| Fallow: Scan for Security Candidates | Populate the Security Candidates view |
| Fallow: Select Workspace Scope... | Scope analysis to one monorepo package |
| Fallow: Clear Workspace Scope (Analyze All) | Remove the workspace scope |
| Fallow: Load Runtime Coverage | Point the Runtime Coverage view at a capture |
| Fallow: Reload Runtime Coverage | Re-read the current coverage capture |
| Fallow: Clear Runtime Coverage | Clear the loaded coverage |
| Fallow: Audit Changed Files | Compute the pass/warn/fail audit verdict for the current changes |
| Fallow: Activate License | Activate a license (paste a token, load a file, or start a trial) |
| Fallow: Show License Status | Show the current license state |
| Fallow: Refresh License | Refresh the license from the server |
| Fallow: Deactivate License | Deactivate the license on this machine |
Extension settings
| Setting | Default | Description |
|---|---|---|
fallow.lspPath | - | Path to the fallow-lsp binary. Highest priority: overrides local node_modules/.bin, PATH, and auto-download |
fallow.configPath | "" | Path to a fallow config file, the same as --config. Relative paths resolve from the workspace root. Empty means auto-discovery of .fallowrc.json, .fallowrc.jsonc, fallow.toml, or .fallow.toml. |
fallow.allowRemoteExtends | false | Let the language server load trusted https:// config inheritance |
fallow.autoDownload | true | Download the LSP binary when it is not found locally or in PATH |
fallow.typeAware.enabled | false | Add exact TypeScript symbol evidence to the project-wide fallow analysis. Does not show compiler diagnostics or generic typed lint rules. Requires fallow 3.9.2 or newer. |
fallow.typeAware.projects | [] | Optional tsconfig paths for type-aware analysis. Relative paths resolve from the workspace root. |
fallow.typeAware.require | "best-effort" | With the default, incomplete semantic evidence does not fail the run. With "complete", the run fails after it reports the conservative result. |
fallow.typeAware.timeoutSeconds | 0 | Time limit in seconds for one semantic request, passed to the CLI as FALLOW_TYPE_AWARE_TIMEOUT_SECS. 0 keeps the CLI default of 120 seconds, or the value that the environment already sets. |
fallow.issueTypes | all | Which issue types to report |
fallow.duplication.threshold | 0 | Maximum duplication percentage before the analysis fails (0 = no limit) |
fallow.duplication.minTokens | 50 | Minimum token count for a reported clone |
fallow.duplication.minLines | 5 | Minimum line count for a reported clone |
fallow.duplication.minOccurrences | 2 | Minimum occurrences for a reported clone group. Set 3 or higher to skip clones that occur only twice |
fallow.duplication.mode | mild | Duplication detection mode |
fallow.duplication.near | false | Also report function-scoped near-miss clones with small structural edits, next to exact clones. Requires fallow 3.15.0 or newer. |
fallow.duplication.skipLocal | false | Only report duplicate code that appears across different directories |
fallow.duplication.crossLanguage | false | Compare TypeScript and JavaScript files after stripping TypeScript type annotations |
fallow.duplication.ignoreImports | true | Ignore module wiring in duplicate-code detection: ES imports, re-export declarations, and top-level static require() binding declarations. On by default. Set to false to count module wiring as clone candidates. |
fallow.duplication.ignoreSymlinks | false | Omit clone instances whose path is a symlink or lies under a symlinked directory. When you do not set it, the project config duplicates.ignoreSymlinks decides. Set to false to report symlinked instances when the project config ignores them. Requires fallow 3.32.0 or newer. |
fallow.production | "auto" | Production mode for the sidebar tree and the editor diagnostics (the two stay in sync). "auto" uses the project config. "on" turns production mode on. "off" turns it off, also when the project config turns it on. Editor only: CLI and CI always report every finding. |
fallow.packageBaselines | true | Apply the per-package refs of workspaces.changedSince. Set it to false to show every workspace package in full scope (same as --no-package-baselines). fallow.changedSince takes precedence when set. |
fallow.changedSince | "" | Git ref. Diagnostics and the sidebar show only files changed since that ref (same as --changed-since). To block new issues and ignore old findings, tag a baseline commit (for example fallow-baseline) and set this to the tag. |
fallow.diagnostics.statusBar | true | Show the Fallow status-bar button that hides or shows all fallow squiggles in the editor. The Fallow: Toggle Hide All Findings command works also when you turn the button off. Editor only: CLI and CI output do not change. |
fallow.diagnostics.severity | "warning" | Show fallow editor diagnostics as warning, information, or hint. With hint, findings stay available without squiggles. Editor only: CLI and CI output do not change. |
fallow.diagnostics.mutedCategories | [] | Fallow diagnostic category codes to hide in the editor, such as code-duplication or stale-suppression. Commit it in .vscode/settings.json to share it with your team. Local mutes can still hide more categories or show a category that this list hides. Editor only: CLI and CI output do not change. |
fallow.workspace | "" | Name of one monorepo package. Sidebar analysis and the Health, Security, and Audit views cover only that package. Empty means the whole project. Passed as --workspace. |
fallow.health.enabled | true | Show the Health view (score and grade, complexity findings, hotspot and refactoring candidates) |
fallow.health.hotspots | true | Show git churn hotspots in the Health view. This reads git history. Turn it off to skip that cost |
fallow.health.topFindings | 20 | Maximum number of complexity findings shown in the Health view |
fallow.health.statusBar | true | Show the project health score and grade in the status bar |
fallow.health.inlineComplexity | true | Show a compact complexity lens (N cyc, N cog) above functions over the fallow health thresholds. Click the lens to show or hide the per-line +N breakdown for that function |
fallow.complexity.breakdownEnabled | true | Turns the complexity breakdown in the editor on or off: lens, per-line markers, and hovers. The breakdown shows after the Health view runs |
fallow.complexity.afterText | false | Show the dim per-line +N token for every complex function. By default, it shows only for the function you expand with its lens or select in the Health view. The hover always shows the breakdown |
fallow.complexity.decorationCap | 200 | Number of top complexity findings fetched for editor decorations, independent of fallow.health.topFindings |
fallow.security.enabled | false | Show local security candidates (client-server-leak, tainted-sink CWE catalogue) in the Security Candidates view. These are unverified candidates to verify, not confirmed vulnerabilities. |
fallow.audit.gate | new-only | Which findings change the audit verdict in the editor (same as fallow audit --gate) |
fallow.audit.statusBar.enabled | true | Show the audit verdict (pass/warn/fail) for the current change set in the status bar |
fallow.audit.runOnSave | false | Run the audit again when you save a JS or TS file (off by default) |
fallow.coverage.capturePath | "" | Path to a local runtime-coverage capture (file or directory) for the Runtime Coverage view |
fallow.coverage.top | 0 | Show only the top N hot paths and findings in the Runtime Coverage view (0 = all) |
fallow.license.showStatusBar | true | Show a Fallow license indicator in the status bar |
fallow.license.refreshOnStartup | false | Check the license status once when the extension starts. Off by default, so there is no network call on startup |
fallow.trace.server | off | LSP trace level for debugging |
Adopting fallow on a legacy codebase
To hide existing issues and still flag new ones, run Fallow: Set Baseline at HEAD from the Command Palette. The command does three things:
- It creates the local lightweight
fallow-baselinetag at the current commit. - It writes
fallow.changedSinceto the workspace settings. - It runs the analysis again.
The command asks before it replaces another active baseline setting. It does not work in multi-root workspaces. It never moves an existing tag or pushes to a remote.
To share the baseline with your team, push the tag and commit the change to .vscode/settings.json:
git push origin refs/tags/fallow-baseline
git add .vscode/settings.json
git commit -m "chore: set fallow baseline"
To apply the same rule to pull requests, use the same tag in CI with fallow dead-code --changed-since fallow-baseline.
Shallow clones hide the baseline. actions/checkout@v4 defaults to fetch-depth: 1, and GitLab CI defaults to GIT_DEPTH: 50. If your baseline tag is older than the fetched history, --changed-since and fallow.changedSince fall back to the full scope with no error. The LSP logs a warning to the Fallow output channel. When you use a long-lived baseline tag, set fetch-depth: 0 on actions/checkout (or GIT_DEPTH: 0 in GitLab CI).