LSP server + VS Code extension
Vulkro ships a Language Server Protocol
server, exposed as the vulkro lsp subcommand of the main binary, and a
VS Code extension that consumes it. The same .vsix loads in Cursor and
Windsurf (both VS Code forks). The extension builds in two editions from one
codebase: the core edition (driven by vulkro) and a Salesforce edition
(driven by vulkro-sf).
The extension surfaces Vulkro findings inside your editor as diagnostics, with hover-to-explain, quick-fix code actions, report export, a CI-parity check, and optional AI assistance. AI assistance is advisory and local: it never changes a deterministic scan result, and the published benchmark is AI-free.
Install
Distribution status: the extension is built and distributed as a .vsix
today. A Visual Studio Marketplace listing is coming soon.
The extension spawns the vulkro binary you already have, so install the
scanner first (see the install guide). Build
the .vsix from integrations/editors/vscode:
cd integrations/editors/vscode
npm install
npm run package:editions
That emits vulkro-<version>.vsix (core) and vulkro-sf-<version>.vsix
(Salesforce edition). Install one through your editor: Extensions view,
... menu, Install from VSIX.
If the binary cannot be found when the extension starts, it offers an
Install action (also the Vulkro: Install or update the scanner binary
command) that downloads the right release for your platform, verifies its
.sha256, and installs it into ~/.vulkro/bin. That download runs only when
you trigger it, never on activation; it respects VULKRO_OFFLINE=1 and
honours the VULKRO_CDN host override.
What you get
- Diagnostics on open and save. Open any Python, JavaScript, TypeScript,
JSX/TSX, Go, or Java file inside a project with a root marker (
.git,package.json,pyproject.toml,Cargo.toml,go.mod,pom.xml,build.gradle,build.gradle.kts,composer.json,sfdx-project.json, orvulkro.toml). The server paints the open file first with a fast single-file scan, then reconciles with a full project scan moments later. Saving re-runs the engine; typing only republishes cached results (debounced), so keystrokes never trigger a re-scan. - Free scanning without an account. JavaScript, TypeScript, Python, and Go, plus IaC, containers, secrets, and dependency manifests, scan without signing in. Signing in unlocks the licensed languages (for example Java, and Salesforce Apex through the Salesforce server); the first sign-in on a device starts a 14-day trial of the full product. Licenses are issued directly by our team ([email protected]).
- Salesforce projects additionally start a second
vulkro-sf lspserver for Apex, Aura, LWC, Visualforce, Flow, and metadata. See the Salesforce extension page for the SFDX specifics. - Hover to explain. Hovering a diagnostic surfaces the rule id, severity, message, and remediation in a Markdown popup.
- Quick fixes on the lightbulb. Every Vulkro diagnostic offers
Suppress (insert a
// vulkro:disable next-line <rule>comment) and Explain (the rule's long-form explainer). A small set of clear-cut patterns (weak hash,yaml.load, cookie flags, debug flags, and similar) also gets a deterministic one-line fix; each template refuses to edit any line whose shape it does not fully recognise. Fix with AI (review) appears when local AI is set up (see below). - Sidebar views. The Vulkro activity-bar container shows Overview,
This File, Issues, and Account by default. Turning on
vulkro.showAdvancedViewsreveals Changes, History, Impact, Codemap, Trends, Dependencies, AI Hunt, Suppressions, and Ask Vulkro. A status bar item shows the live finding count. - Watch mode.
vulkro.watch(or Vulkro: Toggle watch mode) rescans the whole workspace as files change on disk, including files you have not opened and changes made bygit checkoutor codegen. Off by default. - Baseline. Set, clear, or toggle a baseline to hide known findings and surface only new ones.
- Severity display floor.
vulkro.severityThresholdhides findings below the chosen level from the gutter, the Problems panel, and the Vulkro views. It is a display floor, not a scan setting: the scanner still detects everything.
You stay in control of edits
The language server never writes to your files. Every edit it can produce (the suppression comment, a deterministic one-line fix, an AI fix candidate) is proposed through the editor and applied only when you accept it. AI fix candidates go one step further: a candidate is only offered after a fresh deterministic re-scan of the patched working copy confirms the finding no longer appears and the file still parses. That is what "verified" means here; it does not claim the build compiles or the tests pass.
Export a report
Vulkro: Export report (SARIF and other formats) (vulkro.exportReport)
runs the same whole-project vulkro scan that CI would, captures the output,
and saves it where you choose:
- SARIF 2.1.0 (the portable default): open it in a SARIF viewer or upload it to your code-scanning platform.
- JSON: the native Vulkro findings document, for scripts and
jq. - HTML is offered only when the installed engine's
scanaccepts--format html; the command probesscan -hso the picker never offers a format your binary would reject.
A scan that exits 0 (clean) or 1 (findings reported) both produce a
report; only exit 2 (error) is treated as a failure.
Editor / CI parity
Vulkro: Verify editor / CI parity (vulkro.verifyCiParity) runs the
CI-equivalent scan (vulkro scan <root> --format json), counts findings by
severity, and reports how your vulkro.severityThreshold display floor maps
onto a CI invocation. It then offers to copy the matching command, for
example:
vulkro scan . --min-severity low
--min-severity is the CLI twin of the editor's display floor: it drops
findings below the level from the output (composing with --fail-on, which
then evaluates the filtered set), so CI and the editor agree on what appears.
See CLI: scan.
AI assistance (local first)
All AI features are optional and advisory: they never change a deterministic
scan result, and the benchmark stays AI-free. The default transport is a
local model through Ollama, default model
qwen2.5-coder:7b, so nothing leaves your machine.
- Vulkro: Set up AI model lists recommended models (with their licenses), pulls your pick, and self-tests the connection. Test AI connection and Disable AI manage it afterwards.
- Fix issue with AI (review + apply) and Fix all issues with AI draft fixes for findings, validate each one with a deterministic re-scan (a fix is verified when the re-scan no longer reports the finding and the file still parses; the build compiling or tests passing is not claimed), show you the diff, and apply only what you accept.
- Explain impact with AI, Review my changes with AI, AI Hunt, and the Ask Vulkro chat view build on the same local model.
Using your editor's AI model instead
If you do not run Ollama, vulkro.ai.transport: "editor" (or Vulkro: Use
editor AI model) reuses the model your editor already provides (for
example GitHub Copilot) through a loopback shim on 127.0.0.1. This is
opt-in behind an explicit confirmation, because prompt content (which can
include your source code and findings) is sent to whatever provider backs
that model, usually a cloud service. It is refused outright when
VULKRO_OFFLINE=1 is set. Vulkro: Use local AI model switches back.
Your editor's AI agent can call Vulkro
On hosts new enough to expose the APIs (the extension targets VS Code 1.101+; older hosts degrade gracefully), the extension also plugs the scanner into the editor's own AI agent:
- Language-model tools.
vulkro_scan_filescans a single file and returns its findings;vulkro_explain_findingexplains a rule id. Agent mode can call both, and you can reference them in prompts (#vulkroScanFile,#vulkroExplainFinding). The Salesforce edition registersvulkro_sf_*twins, so both editions co-exist in one host. - MCP server. An MCP server-definition provider teaches the editor to
launch the engine's own stdio MCP server (
vulkro mcp serve) withVULKRO_OFFLINE=1set, so the agent's MCP scans never reach the network.
Settings
| Setting | Default | Purpose |
|---|---|---|
vulkro.path | vulkro | Path to the vulkro binary, or the bare name if it is on PATH. The extension spawns <path> lsp. |
vulkro.severityThreshold | low | Lowest severity shown (critical, high, medium, low, info). A display floor: match it to your CI --min-severity. |
vulkro.showAdvancedViews | false | Reveal the full set of sidebar views beyond Overview, This File, Issues, and Account. |
vulkro.watch | false | Rescan the whole workspace as files change on disk, including unopened files. |
vulkro.lsp.debounceMs | 300 | Debounce window (ms) for didChange republishes, clamped to [50, 5000]. Passed as VULKRO_LSP_DEBOUNCE_MS. |
vulkro.ai.model | (empty) | Override the local AI model; empty uses the engine default (qwen2.5-coder:7b). Passed as VULKRO_AI_MODEL. |
vulkro.ai.url | (empty) | Base URL of the local Ollama (OpenAI-compatible) endpoint; empty uses http://127.0.0.1:11434/v1. Passed as VULKRO_AI_URL. |
vulkro.ai.transport | local | local keeps AI fully on-machine; editor reuses the editor's model through the loopback shim (opt-in, see above). |
vulkro.trace.server | off | Trace LSP traffic in the Vulkro output channel. |
The Salesforce server has its own namespace (vulkro-sf.path,
vulkro-sf.severityThreshold, vulkro-sf.scanOnSave, vulkro-sf.watch,
vulkro-sf.targetOrg, vulkro-sf.trace.server); see
the Salesforce extension page.
Because the server maps Critical and High to the same editor severity
(Error), the critical and high thresholds behave identically in the
editor.
How the LSP talks to the scanner
vulkro lsp runs the scan in-process: no subprocess, no JSON-over-pipe. It
uses the same detection pipeline as vulkro scan (the full extractor set,
the auth model, taint analysis, and the same suppression pass), so a
// vulkro:disable directive silences the same finding in the editor and in
CI. Diagnostics are pushed by the server per file. vulkro lsp exits 0 on
a clean shutdown and 2 on an operational error; set VULKRO_LSP_LOG=1 for
a stderr message trace.
Performance
Opening the first file in a project (and every save) publishes the current file's findings from a fast single-file scan first, so squiggles land in a fraction of a second, then a full project scan reconciles the complete picture. Typing republishes cached results only; the engine re-runs on save (or on any disk change when watch mode is on).
For a scoped terminal loop alongside the editor, run something like
vulkro scan . --min-confidence high --scope src (see
CLI: scan).
Suppressing network egress from inside the editor
To suppress all network egress from the binary the editor spawns, set:
// settings.json
"terminal.integrated.env.osx": {
"VULKRO_OFFLINE": "1"
}
(Adapt osx to linux / windows as needed.)
VULKRO_OFFLINE=1 is the single switch and covers everything: scans, the
managed binary install, and the editor-AI transport (which is refused under
it). The MCP server the extension registers is always launched with
VULKRO_OFFLINE=1 regardless.
What this isn't (yet)
- No Marketplace listing yet. The
.vsixis the distribution channel today; the Marketplace listing is coming soon. - No standalone JetBrains plugin. The server works with any LSP-aware
editor in principle;
vulkro lsp --helpprints ready-made snippets for Neovim (nvim-lspconfig), Helix, and Emacs eglot. VS Code (and its forks) is the only editor with a packaged extension today. - No unreviewed rewrites. Every edit, deterministic or AI-drafted, is applied only when you accept it, and AI candidates must first pass the deterministic re-scan described above.
- No as-you-type engine runs. Diagnostics refresh from cache while you type; the engine re-runs on save (or on disk changes in watch mode).
Related
vulkro scan: the CLI front door that produces the same findings the LSP surfaces, plus the--min-severityparity flag.- Salesforce extension page: the
SFDX side, driven by the
vulkro-sfserver.