Documentation

Set up vexp, ship faster

Install vexp, connect your AI agent, and master the everyday workflow, commands, settings, and a troubleshooting playbook for both VS Code and the standalone CLI.

VS Code 1.85+36 languages · 17 agents
Overview

Introduction

vexp is a local-first reliability layer for AI coding agents. Its context engine builds a live dependency graph of your codebase and serves your agent only the code that matters for the task; when the agent declares the task done, vexp verifies the work mechanically against that same graph. Session memory persists across days, and an optional local AI layer compresses prompts and context further. Everything runs on your machine.

The VS Code extension is the primary distribution. A standalone CLI (npm install -g vexp-cli) is available for terminal-only workflows. Both bundle the same native engine and MCP server — no external dependencies, no account required. The VS Code extension needs no Node runtime; the npm CLI requires Node 20 or later.

How it works

01

Index

vexp parses your source files and builds a graph stored at .vexp/index.db (local, gitignored). A small manifest.json with per-file content hashes is committed to git, teammates rebuild incrementally from the manifest in seconds.

02

Traverse

Given a natural-language task, vexp identifies the pivot nodes that matter via semantic search + graph traversal. Session memories from previous work are surfaced too.

03

Capsule

Pivot files are returned in full; supporting files as compact skeletons (signatures only). The result fits the configured token budget, typically 8 000 tokens.

Getting Started

Installation

Pick a distribution. The VS Code extension is the fastest path; the CLI is for terminal-only setups (Claude Code, Codex, scripts, remote machines).

Install from the Extensions panel

Open Extensions (Ctrl+Shift+X / ⌘⇧X), search for vexp, and click Install.

The extension bundles the native engine for your platform. There is no Node runtime to install, no separate compilation, and nothing to download afterwards. Open a project folder and click the vexp: not indexed status-bar item (or run vexp: Start Indexing) to build the index; already-indexed projects start their daemon automatically.

NoteBundled binary won't run on your system? Set vexp.binaryPath in Settings to point at a locally-built vexp-core.

Platform support

PlatformMinimum OS
Linux x64Ubuntu 20.04+, Debian 11+, RHEL/Rocky 8+, WSL2
Linux arm64Same minimum as Linux x64
macOS IntelmacOS 11 (Big Sur) or later
macOS Apple SiliconmacOS 11 (Big Sur) or later
Windows x64Windows 10 or later
Windows ARM64Windows 11 on ARM; runs the x64 binary via built-in emulation
NoteThe platform table applies to both distributions, the same native engine is bundled in the VS Code extension and the npm CLI.
Getting Started

First Run

Pick your distribution below. Both paths end with the same result: a working index, a configured AI agent, and a daemon that auto-restarts when needed, usually within 30 seconds on a typical project.

  1. Index with one click. Open a project folder — the first time, the status bar shows vexp: not indexed; click it (or run vexp: Start Indexing) to build the index. On an already-indexed project the daemon starts automatically when the folder opens. The status bar shows vexp: indexing while it works, then vexp: 1.2k · 0/20 when ready (node count plus daily-call usage; numbers are abbreviated k/M).
  2. Agents are configured. vexp sets up the AI agents the project itself shows (Claude Code, Cursor, Copilot, Codex, and more) and writes the right config file for each. A tool found only on this machine is offered once per project (see Supported Agents). Run vexp: Project Setup or vexp: Setup Agents (multi-select) from the Command Palette to set up more.
  3. No login hook is installed. The daemon starts when you open the folder or when an agent calls a tool. Want it warm after every reboot? Run vexp autostart install from the CLI (optional, per-user, no admin needed).
  4. Your AI agent just works. If the daemon was ever killed, it auto-restarts the next time an agent calls a tool, no manual management. Use the sidebar panel to monitor or stop it.
  5. NotePersonal mode: enable vexp.personalMode in Settings to skip writing shared-repo files (.claude/CLAUDE.md, .cursor/rules/vexp.mdc, git hooks). Useful when you want vexp on someone else's repo without changing their files.
VS Code

VS Code Features

Beyond what your AI agent calls via MCP, vexp gives you visible feedback directly in VS Code (works the same in Cursor and Windsurf).

Sidebar panel

Click the vexp icon in the Activity Bar to open a sidebar with:

  • Status header (running / indexing / starting / connecting / stopped / error / workspace cap reached / not initialized) and live index stats (nodes, edges, files, uptime, agent sessions).
  • Activity (7 days): prompts analyzed, and the parts that add up to it: silences, orientations served and, when there are any, Held out (A/B) for the measurement holdback (disable with holdback_pct = 0 in .vexp/vexp.toml) and Past hook budget for orientations that finished after the agent stopped waiting.
  • Measured savings (tool calls) section — appears once at least one measured tool call exists — with a period selector (today, 7 / 14 / 30 / 60 / 90 days) and an Export Report button that writes a markdown report to .vexp/token-savings-report.md.
  • Local LLM section with Install / Start / Disable / Check-updates / Status buttons, plus a one-time notification that offers to enable it.
  • Contextual actions that follow daemon state: while running — Stop Indexing, Force Re-index, Generate Context Capsule, Add / Connect Repository, Setup Agents, Settings, View Daemon Logs; while stopped — Start Indexing, Setup Agents, Activate License, View Daemon Logs.
  • Repository cards (status dot with an 'indexing NN%' badge while indexing, repo alias and path, node / edge / file counts, last-indexed time). A toggle shows or hides empty repos.

The panel auto-refreshes every 10 seconds.

CodeLens

Functions, methods, classes, interfaces, enums, and other indexed symbols in TypeScript, JavaScript, Python, Go, Rust, Java, C#, C, C++, Ruby, and Bash get an inline annotation once the file is indexed: first vexp: analyze impact, then N dependents across M files (plus | K cross-repo when cross-repo dependents exist). Click it to open the impact graph for that symbol. Available on every paid plan (Pro, Team, and lifetime tiers); not on the free plan.

Hover

Hover an exported TypeScript/JavaScript declaration (a line containing the export keyword) to see its dependents count, cross-repo usage, and top 5 callers. Available on every paid plan.

Status bar

The left-side status bar shows the current state. Clicking it opens your license status — except in the vexp: not indexed state (click starts indexing) and the vexp: workspace cap state (click opens the logs).

StateMeaning
vexp: not indexedNever indexed yet; click to start indexing
vexp: indexing NN%Indexing in progress (progress percentage shown when known)
vexp: 1.2k nodesHealthy, plan with no node cap (Team, Lifetime Tier 4)
vexp: 1.8k/2.0kAt ≥ 50 % of the node cap (yellow); shown when no daily quota is displayed — with a daily quota the same state renders as vexp: 1.8k · 12/20
vexp: 1.8k · 12/20Plans with a node cap (Starter, Pro, Lifetime Tier 1–3): daily-call usage after node count; warning (yellow) at ≥75% of the daily cap
vexp: daily limit reachedDaily call limit reached (red): Starter pauses until midnight UTC; on a paid plan only the counted tools are refused until then
vexp: 2.0k/2.0kNode limit reached (red); the tooltip says how many source files were left out and the estimated size of the whole project
vexp: workspace capConcurrent-workspace limit for your plan reached (yellow); click opens logs
vexp: starting…Daemon booting
vexp: stoppedDaemon not running
vexp: disabledvexp.enabled is off in Settings
vexp: errorDaemon failed, check logs

Linked repos in VS Code

The active workspace's .vexp/workspace.json governs how repos are linked. See Multi-Repo Workspaces for the cross-repo features.

Reference

Commands

Everything you'll actually type, organized by where you type it.

Command Palette

Open the palette (Ctrl+Shift+P / ⌘⇧P), type vexp, and pick:

vexp: Project SetupSet up the agents this project shows (and those chosen for it before), write config files, ask about each tool found only on this machine, and ask once about git hooks.
vexp: Setup AgentsMulti-select picker of all supported agents (Space to toggle, Enter to confirm). Tools found only on this machine are marked; what you pick is remembered for this project.
vexp: Setup Multi-Repo WorkspacePick additional repos; vexp creates .vexp/workspace.json and enables cross-repo queries.
vexp: Generate Context Capsule for Current TaskType a task description; vexp opens a panel with the pivot files and supporting skeletons.
vexp: Show Impact Graph for Symbol at CursorOpen a panel showing what depends on the symbol you have selected.
vexp: Show File SkeletonPick a detail level and see the file's structure without bodies.
vexp: Show Index StatusOpen a panel with node / edge / file counts and uptime.
vexp: Start IndexingStart the daemon if it's not running.
vexp: Stop IndexingGracefully stop the daemon.
vexp: Force Re-indexConfirm, then fully restart the daemon and re-index the project.
vexp: Activate License KeyPaste a Pro / Team license key.
vexp: Show License StatusSee plan, expiry, and links to manage your subscription.
vexp: Show Token SavingsFocus the vexp sidebar panel, where the token-savings figures live.
vexp: Verify Completion (parse errors, broken imports, impacted tests)Run the same mechanical completion check as vexp verify and write the report to the 'vexp verify' output channel; the summary is shown as a notification.
vexp: Restart Daemon (after updates or config changes)Restart the daemon in place from the palette — the remedy for version-skew warnings from Doctor.
vexp: Doctor (diagnose daemon, license, hooks)One-page health report: binary vs daemon version, index status, license, hooks wiring. The first thing to run when something feels off.
vexp: Shield Scan (PII and secrets any AI agent can read)Scan comments and string literals for PII and secrets any AI agent could read. Masked previews only, everything stays local.
vexp: SettingsOpen VS Code Settings filtered to vexp options.
Reference

MCP Tools

Your AI agent uses these tools through MCP. You won't call them directly, your agent does, but it helps to know what each one does.

ToolPurposeWhen to use
run_pipelinePrimary tool. Context search + impact analysis + memory recall in one call. Auto-detects intent.Every task
verify_doneHorizon: mechanical completion check on the session’s changes: parse errors, broken imports, untouched dependents, impacted tests (the exact test files to RUN, with shared helpers flagged for UPDATE), docs drift. File:line evidence, free on every plan. Repeat calls on an unchanged tree return the cached verdict instantly.Before declaring a multi-file task complete
get_context_capsuleLightweight context search with relevant memories.Quick lookups
get_impact_graphWhat breaks if a symbol changes. Cross-repo supported.Before refactoring
search_logic_flowExecution paths between two symbols.Debugging
get_skeletonToken-efficient file structure (minimal / standard / detailed).Exploring unfamiliar code
get_session_contextObservations from current and previous sessions.Recalling earlier work
search_memoryCross-session search with a "why this surfaced" rationale.Finding past decisions
save_observationPersist an insight; optionally linked to a symbol for staleness tracking.Recording context
expand_vexp_refRetrieves the original code behind a [V-REF:xxxx] marker (12 hex chars) found in compressed vexp output. Free on every plan.When compressed output references a V-REF
index_statusIndexing health, stats, available repo aliases; when the plan’s node cap left files out, how many and the estimated size of the whole project.Checking health
workspace_setupGenerates agent configuration files.First-time setup
index_incrementalLive incremental or full re-index of a repo without restarting the daemon; built for push/PR-webhook pipelines. Pro/Team, native MCP server only.CI / webhook reindex
pr_impactChanged symbols of a base..head git diff with their downstream dependents, most-impactful first. Pro/Team, native MCP server only.PR-review automation
NoteBy default your agent's tool list advertises only a slim core set (run_pipeline, get_skeleton, expand_vexp_ref, verify_done; three via the Node MCP wrapper). Listing is not availability: every tool on this page stays callable even when unlisted. Set VEXP_ALL_TOOLS=1 on the MCP server to advertise the full plan-gated list.

run_pipeline at a glance

run_pipeline replaces the older multi-step workflow with a single call that picks the right strategy for your task.

javascript
run_pipeline({
task: "fix login bug", // describe the task in your own words
preset: "auto", // auto | explore | debug | modify | refactor
max_tokens: 10000, // token budget
include_tests: false, // include test files (auto-on for debug)
observation: "uses cookies" // optional: save an insight in the same call
})

For multi-repo workspaces, scope a query with repos: ["backend", "shared"].

NoteOnly run_pipeline, get_context_capsule, and get_skeleton count against the Starter daily quota (20 / day, resets midnight UTC). Memory and status tools never count against it, on any plan. Impact, flow, and workspace_setup are Pro/Team features: on Starter they are not available as tools, and run_pipeline skips the impact and flow steps. Once the daily quota is spent, the daemon stops until the quota resets at midnight UTC, so no tool answers until then.
Core Feature

Session Memory

vexp remembers what your agent explored, decided, and learned, automatically, across sessions and days. Memories are linked to the code graph, so when the underlying code changes, related memories are flagged stale (your agent sees that the past decision may no longer apply).

How it works

  • Auto-capture. Every vexp tool call your agent makes becomes a compact observation in the local database.
  • Auto-surface. run_pipeline and get_context_capsule include relevant memories in the result, no extra tool calls needed.
  • Each result explains itself. A short rationale tells the agent why this memory surfaced (matching the task, recent activity, related code, etc.).
  • Staleness tracking. When code linked to a memory changes, the memory is marked stale and demoted in ranking, but still shown with a warning so the agent can re-evaluate.

The three memory tools

All three are included on every plan, Starter included, and none of them count against the daily quota. Note that on Starter they still stop answering once that quota is spent, because the daemon shuts down until it resets at midnight UTC:

  • get_session_context, observations from the current and previous sessions.
  • search_memory, cross-session search across everything vexp has captured.
  • save_observation, manually record an insight. Optionally link it to a symbol so it gets flagged when that symbol changes. Manually saved observations persist permanently. Auto-captured observations are ephemeral: when a session is compressed they are rolled into a session summary and pruned.
Integrations

Supported Agents

vexp detects and configures 17 AI coding agents. Running vexp setup writes the correct configuration file for each agent it sets up, including tool-usage instructions tailored to that agent. For Windsurf and Kiro, setup also pre-approves the vexp tools in the MCP entry (alwaysAllow / autoApprove), so those agents never prompt per call. Every vexp tool also declares what it does in MCP terms (read-only, or writing only vexp's own local data), so Codex no longer asks permission before each vexp call and codex exec with approvals set to never no longer refuses them.

Which agents get set up. An agent the project itself shows is set up without asking: its own folder or file in the project (.claude, .cursor, opencode.json, …; for Codex a project .codex/config.toml, never AGENTS.md or anything else vexp writes), or an agent you chose for this project before. A tool found only on this machine (Codex's login, sessions or history under ~/.codex or CODEX_HOME, the ~/.claude folder, Antigravity's ~/.gemini/antigravity, Cline's VS Code storage) is not set up on its own. VS Code asks once per project, one question per tool: Set up / Not here / Never. vexp setup lists such a tool unselected, and without a terminal skips it and prints the command that adds it.

The answers live in ~/.vexp/agent-consent.json (per project, plus a list of tools you never want), shared by the extension and the CLI. Set up, or picking the tool in vexp setup, vexp setup-agents or vexp use, records yes. Not here records no for this project and removes what vexp wrote there for that tool (its AGENTS.md block when no other tool set up here reads it, its .codex hooks), keeping your own text and files. Never says no for every project on this machine, does the same cleanup, and removes vexp's machine-wide entry for that tool (Codex, Antigravity, Cline) when it names no project or this one; ~/.claude.json is never touched. Closing the question answers nothing: it comes back at the next start.

NoteVerification channels: on Claude Code, vexp setup --interventions installs an opt-in Stop hook that runs the Horizon completion check once per session (default setup does not install it); on opencode and Kilo Code the check runs at session idle through the default-on vexp plugin; every agent can call verify_done directly or run vexp verify headless.
AgentFiles writtenTransport
Claude Code.claude/CLAUDE.md + ~/.claude.json + .claude/hooks/ (vexp-hint.sh, vexp-search.sh, vexp-restore.sh; registered in .claude/settings.json). The Grep/Glob deny hook vexp-guard.sh is written only with vexp setup --guard-strictstdio
Cursor.cursor/rules/vexp.mdc + .cursor/mcp.json + .cursor/hooks/vexp-edit-hint.sh (via .cursor/hooks.json)stdio
Windsurf / Devin Desktop.windsurf/rules/vexp.md + ~/.codeium/windsurf/mcp_config.json (Cascade, user scope) + .devin/mcp_config.json (Devin Local); with Devin Desktop Next installed, also ~/.codeium/windsurf-next/mcp_config.json; earlier releases wrote .windsurf/mcp.json, which Cascade does not readstdio
GitHub Copilot.github/copilot-instructions.md + .vscode/mcp.jsonstdio
Zed.zed/rules.md + .zed/settings.jsonstdio
Continue.dev.continue/config.jsonstdio
Cline.clinerules + machine-global cline_mcp_settings.json (per installed VS Code variant)stdio
CodexAGENTS.md + ~/.codex/config.toml + .codex/hooks.json + .codex/vexp-hint.sh (.codex/vexp-hint.cmd on Windows)stdio, direct (default); opt-in HTTP via VEXP_CODEX_TRANSPORT=http (CLI) or the vexp.codexMcpTransport VS Code setting, on 127.0.0.1:7821 by default (per-workspace override in .vexp/mcp.port); the HTTP entry always routes to one project
OpencodeAGENTS.md + mcp key in opencode.json(c) + .opencode/plugin/ (vexp-hint.js, vexp-compress.js)stdio
Kilo Code.kilocode/rules/vexp.md + mcp key in kilo.jsonc (.kilo/kilo.jsonc or root kilo.jsonc) + .kilo/plugin/ (vexp-hint.js, vexp-compress.js)stdio
Kiro.kiro/steering/vexp.md + .kiro/settings/mcp.jsonstdio
Augment.augment/guidelines.mdinstructions only (no MCP file)
Trae.trae/rules/project_rules.md + .trae/mcp.jsonstdio
Firebase Studio.idx/airules.md + .idx/mcp.jsonstdio
AntigravityAGENTS.md + ~/.gemini/antigravity/mcp_config.jsonstdio (machine-global MCP config)
ZCodeAGENTS.md + mcp.servers key in .zcode/config.json (or .agents/mcp.json when the project already keeps its servers there, since ZCode stops reading that file once a .zcode config exists) + the orientation hook in ~/.zcode/cli/config.json (user scope: ZCode runs no project-level hooks)stdio (binary, no node)
Friday Codefriday.md at the project root (the same mandate as AGENTS.md, appended to your own rules and refreshed on every vexp update)instructions only (Friday Code connects to vexp on its side)

Claude Desktop is two surfaces, not one. The desktop app hosts a Claude Code pane, and that pane is Claude Code: it reads ~/.claude.json and the project's .claude/ hooks, so the Claude Code row above already covers it and vexp setup needs nothing extra. Because those hooks inject context into the prompt rather than showing up as tool calls, vexp can be working there without ever appearing in the transcript. The app's plain chat is the other surface: it speaks MCP through claude_desktop_config.json and is not written by vexp setup. A chat with no repository open has nothing to index, so most people never need that entry, add it only if you want vexp in the plain chat pinned to one workspace.

Antigravity note. Antigravity reads the cross-tool AGENTS.md (v1.20.3+) together with GEMINI.md and .agent/rules/, and keeps its MCP servers in a machine-global file: ~/.gemini/antigravity/mcp_config.json. vexp registers its server there once and resolves the workspace per-session, so one configuration serves every project you open.

Codex note. vexp's entry in ~/.codex/config.toml names no project: Codex starts vexp in each session's own folder, so every project gets its own index. An entry an earlier release pinned to one project is rewritten this way the next time vexp sets Codex up. In a folder that is not a vexp project, vexp answers with no tools and says why, instead of failing Codex's start. To make every Codex session use one project's index, whatever folder it starts in, run vexp use <path> --pin; vexp use --unpin undoes it.

Codex runs a project hook only after you trust it. When vexp writes or changes its orientation hook, VS Code shows this step once and vexp setup prints it: in the Codex extension for VS Code, open the Codex panel > Settings > Hooks and trust vexp-hint; in a terminal, run codex in the project, type /hooks and approve vexp-hint (trust the folder first if Codex asks). On Windows the hook is registered as cmd /d /c call "<project>\.codex\vexp-hint.cmd", which runs whether Codex starts it through PowerShell or cmd, and the terminal and the VS Code extension keep separate approvals, so approve it in each one you use. After updating from 3.2.5 on Windows, approve it once more: its command changed. vexp doctor shows which approvals are in place.

VS Code forks & Open VSX. The vexp extension also runs in the AI-IDE forks of VS Code, Antigravity, Cursor, Windsurf, Kiro, VSCodium, whose Extensions views are backed by the Open VSX registry (the Microsoft Marketplace is licensed to Microsoft products only). Search for “vexp” there, or use “Install from VSIX” with the same .vsix we ship for VS Code, no fork-specific build needed. Trae ships its own extension store and accepts the VSIX directly.

Platform

Windows + WSL2

Inside WSL2, vexp is simply Linux: install the linux-x64 CLI or extension in the WSL side and everything, daemon, index, MCP server, runs there. The one thing to keep straight is that your agents live on both sides of the boundary, and each side reads its own configuration. vexp setup runs inside WSL, so it can only write WSL-side files.

Agent runsReads its config fromWhat to do
In the WSL remote of your editor (Cursor, VS Code + Copilot, Trae, Kiro, …)Project-level files inside the repo (.cursor/mcp.json, .vscode/mcp.json, …)Nothing extra, vexp setup inside WSL covers them
In the WSL shell (Claude Code, Codex CLI, opencode)The WSL home (~/.claude.json, ~/.codex/config.toml, AGENTS.md)Nothing extra, vexp setup inside WSL covers them
As a Windows desktop app (Codex app, Claude Desktop) — and Windsurf / Devin Desktop: even with a WSL folder open, Cascade starts MCP servers on the Windows sideThe Windows profile (C:\Users\<you>\…), never the WSL homeAdd the entry by hand on the Windows side, bridged through wsl.exe (below)
The same folder opened both in a Dev Container (or WSL / SSH remote) and on the Windows hostHook scripts and MCP entries in the repo bake the binary path of the environment that ran setup (/root/.vscode-server/…/vexp-core vs C:\Users\…\vexp-core.exe)Each side needs its own paths: the extension re-pins them when it activates in the other environment; if a file still points across, run vexp: Setup Agents there

Concretely: the Codex desktop app reads C:\Users\<you>\.codex\config.toml, not the WSL ~/.codex/config.toml that vexp setup writes. Claude Desktop reads %APPDATA%\Claude\claude_desktop_config.json, and the Microsoft Store build relocates it to %LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\claude_desktop_config.json.

Bridging a Windows app to vexp in WSL

The entry goes in the Windows-side config and crosses into WSL with wsl.exe. Two rules: environment variables set in the MCP entry do not propagate through wsl.exe (that would need WSLENV), so set them on the command line inside WSL instead; and launch via bash -lc so a version-managed Node (nvm) is on PATH. To find the server path, run npm root -g inside WSL and append /vexp-cli/mcp/mcp-server.cjs.

C:\Users\<you>\.codex\config.toml, Codex desktop app
[mcp_servers.vexp]
command = "wsl.exe"
args = ["--", "bash", "-lc",
"VEXP_WORKSPACE=/home/<you>/project exec node /usr/lib/node_modules/vexp-cli/mcp/mcp-server.cjs"]
claude_desktop_config.json, Claude Desktop
{
"mcpServers": {
"vexp": {
"command": "wsl.exe",
"args": ["--", "bash", "-lc",
"VEXP_WORKSPACE=/home/<you>/project exec node /usr/lib/node_modules/vexp-cli/mcp/mcp-server.cjs"]
}
}
}
%USERPROFILE%\.codeium\windsurf\mcp_config.json, Windsurf / Devin Desktop (Cascade)
{
"mcpServers": {
"vexp": {
"command": "wsl.exe",
"args": ["-d", "Ubuntu", "--", "bash", "-lc",
"VEXP_WORKSPACE=/home/<you>/project exec node /usr/lib/node_modules/vexp-cli/mcp/mcp-server.cjs"],
"alwaysAllow": ["run_pipeline", "get_skeleton", "verify_done", "expand_vexp_ref"]
}
}
}

Cascade reads that one file and no project-level one; quit and reopen Windsurf after editing it. Devin Desktop Next (the beta build) is a separate install with its own copy at %USERPROFILE%\.codeium\windsurf-next\mcp_config.json; the same entry goes there. vexp setup run inside WSL prints this entry filled in with your real paths, ready to paste. Devin Local (the agent in Devin Desktop) reads .devin/mcp_config.json from the project, which setup writes; if it too runs on the Windows side, the same entry goes in %APPDATA%\devin\mcp_config.json.

With more than one distro installed, pin it: args = ["-d", "Ubuntu", "--", …]. These bridged entries pin one workspace by design, a Windows-side config cannot follow whichever WSL project you happen to open, so point VEXP_WORKSPACE at the repo that app should use.

Notevexp doctor runs inside WSL and cannot see Windows-side configs: if an agent ignores vexp even though setup reported success, first check which side of the boundary that agent reads its config from. In a WSL remote, editor extensions install into the WSL extension host, let the editor pick the package (it selects linux-x64) rather than hand-downloading a VSIX.
Advanced

Multi-Repo Workspaces

vexp can index multiple repositories as a unified workspace and detect relationships between them, entirely on your machine. Useful for monorepos split across repos, frontend + backend pairs, and microservices.

Setup

Create .vexp/workspace.json in your primary repo, or click Add / Connect Repository in the sidebar, or run vexp in a terminal and pick Repos & Workspace to list connected repos or add one from the CLI (the plan's repo limit is enforced; a running daemon indexes the new repo automatically).

workspace.json
{
"name": "my-project",
"repos": [
{ "alias": "my-project", "path": "." },
{ "alias": "frontend", "path": "../frontend" },
{ "alias": "shared", "path": "../shared-lib" }
]
}

Paths are relative to the folder that contains the .vexp/ directory: use "." for that root itself, and a subfolder (packages/api) or a sibling (../shared-lib) for every other repo. Listing the root with "." is optional — the primary is always served, and always under its folder name as its alias (an alias you write on the "." entry is ignored). The workspace_id key is also accepted in place of name.

Index the workspace

A workspace is indexed as a whole, not one repo at a time. After creating workspace.json, index every repo in the list in one step, then point your agent's MCP server at the workspace root.

Open the workspace root (the folder holding .vexp/workspace.json), or click Add / Connect Repository. vexp loads every repo in the list and indexes any that aren't up to date.

Notevexp index run inside any single repo of a workspace indexes the entire workspace, not just that folder. Your plan's repo limit still applies, repos beyond it are skipped with a note in the output. If the daemon is already running you don't need to restart it — it watches workspace.json and picks up a newly added repo automatically within a few seconds.

Cross-repo edge detection

vexp automatically detects five kinds of relationship across repos:

TypeHow vexp detects itExample
API contractOpenAPI / Swagger spec files (openapi.yaml/.yml/.json, swagger.json/.yaml, api.yaml/.yml — at the repo root or under src/, api/, docs/, spec/); each declared endpoint is linked to the workspace's other repos as potential consumersBackend exposes /api/users; frontend fetches it
Shared typespackage.json dependency matching between reposBoth repos import @company/shared-types
Env contract.env.example keys matched to process.env / os.environ usageBackend defines DATABASE_URL; worker reads it
Manifest referenceJSON manifest entries that name another workspace repo by alias or by a relative path into itcatalog.json points at ../shared-lib/schema
Doc authority linkLinks in README.md, AUTHORITY.md, INDEX.md, MANIFEST.md, CATALOG.md, REFERENCES.md or ARCHITECTURE.md that point at a sibling repo (GitHub URL or relative path); links inside code fences are ignoredREADME says "the contract lives in ../api-spec/"

Querying across repos

  • run_pipeline and get_context_capsule query all indexed repos by default.
  • Scope with repos: ["backend"].
  • Use cross_repo: true on get_impact_graph and search_logic_flow to trace across repo boundaries.
  • Use repo: "alias" on get_skeleton to target a specific repo — the alias is the one run_pipeline prints next to each file. The alias is optional: an absolute path pins its repo, and a repo-relative path is looked up in the primary first, then in every connected repo.
  • Call index_status to see available repo aliases.
  • From the CLI: vexp capsule --repos backend,shared, vexp impact <fqn> --cross-repo, vexp flow <start> <end> --cross-repo.

Git worktrees and parallel agents

Agent harnesses create a linked git worktree per parallel task (Claude Code under .claude/worktrees/, Cursor's background agents, or your own git worktree add). A worktree is a full copy of the checkout, and it is the same project, and vexp treats it that way everywhere. The generated git hooks detect a linked worktree from .git's own gitdir line — no path convention, so every agent is covered — and skip per-worktree indexing (set VEXP_WORKTREE_INDEX=1 to opt back in); the login supervisor (vexp serve) never resurrects worktree daemons after a reboot and staggers the daemons it does bring back. A new worktree needs no setup of its own: it takes the answer you gave for its repository, so the first agent session in a worktree of a repository set up with vexp indexes it in the background (a worktree of a repository that never had vexp is left alone); until it is complete, answers say they cover only the files indexed so far. On Windows, agents connected through vexp's Node MCP server still need vexp index in a new worktree. That index is kept out of git, so git worktree remove works without --force and takes it along once the session has ended. A daemon started in a worktree shares one license slot with its repository, is not revived at boot, and stops about a minute after the worktree is removed. On Windows a file in use cannot be deleted, so removing a worktree while a vexp daemon runs in it leaves the folder behind; the daemon then stops and the folder can be deleted. To have the index ready before the first prompt, run vexp index from the script your tool runs when it creates a worktree (a Codex local environment's setup script, for example), or set VEXP_WORKTREE_INDEX=1. Submodules are separate projects and are untouched by all of this.

Codex across several workspaces

Nothing to switch: Codex's vexp entry names no project, so each Codex session uses the index of the folder it starts in. To make every Codex session use one workspace instead, run vexp use <workspacePath> --pin; vexp use --unpin undoes it.

NoteOpening a secondary repo on its own still loads the whole workspace, thanks to a small backlink vexp writes into the secondary repo's .vexp/ during setup.
Optional

Local LLM (optional)

vexp ships an optional on-device AI layer that improves prompt preprocessing and compresses the context further. Everything runs on your machine, no cloud, no account, no code leaving your laptop.

Multi-language prose compression: language detection covers 15 languages: English, Italian, French, German, Spanish, Portuguese, Russian, Chinese, Japanese, Korean, Arabic, Hindi, Turkish, Dutch, Polish.

Install & manage

One-time download (~3.5 GB). Files stay on disk after a disable, so re-enabling is instant. Requires at least 6 GB of RAM; below that the installer declines and vexp stays on the built-in rule-based compressor. On NVIDIA Linux/Windows machines, a one-time CUDA plugin (~62 MB) and CUDA 12 runtime (~550 MB) are also downloaded automatically.

The sidebar's Local LLM section shows the model status and these buttons:

  • Install LLM (primary, blue), when not yet installed. A one-time first-run notification (Enable now / Learn more / Not now) also offers this.
  • Start LLM (primary, blue), when installed but disabled.
  • Check LLM updates (secondary), shown only while the LLM is active; compares your model with upstream without downloading.
  • Disable LLM (red, destructive), when active. Files stay on disk.
  • LLM Status, writes the full diagnostic (hardware, files, backends registered) to the 'vexp: LLM' output channel.

Extension users need none of these commands: the sidebar's Install LLM / Start LLM / Disable LLM buttons drive the bundled binary directly. One thing to know either way: the daemon builds its compressor when it starts, so enabling the model changes nothing until the daemon is restarted — vexp: Restart Daemon from the Command Palette, or vexp daemon-cmd restart. When the sidebar shows "LLM is configured but this daemon is running the rule compressor", that is the case it describes; the banner carries a Restart daemon button and the Start/Install actions offer the restart themselves.

GPU acceleration

Works the same in both distributions. On Apple Silicon, Metal is detected and used automatically; Intel Macs run the model on CPU by design. On Linux or Windows with an NVIDIA GPU, CUDA is detected and used automatically, no flag or environment variable is needed. If no usable GPU is found, inference silently falls back to CPU. GPU preference is a config setting: prefer_gpu = false under [llm] in ~/.vexp/config.toml forces CPU inference. flash_attention = "auto" | "on" | "off" (same [llm] table; env default VEXP_FLASH_ATTENTION) — set "off" if your GPU crashes while running the model.

NVIDIA GPUs are supported on Linux and Windows; a one-time CUDA plugin download is fetched automatically. The first GPU inference may take a few seconds to warm up.

GPU offload requires an NVIDIA driver at least as new as CUDA 12.8 (570.xx or newer); on older drivers inference falls back to CPU until the driver is updated. If a GPU attempt ever crashes the daemon, vexp writes ~/.vexp/gpu-unusable and runs the model on CPU from then on. Delete that file after a driver update to retry the GPU (upgrading vexp retries once automatically). If the file says the crash happened while running the model, delete it and set flash_attention = "off" under [llm] to keep the GPU.

Use your own server (optional)

Instead of the ~3.5 GB download, point vexp at any OpenAI-compatible server via endpoint / endpoint_model / endpoint_api_key under [llm] in ~/.vexp/config.toml (llama.cpp llama-server, LM Studio, vLLM, Ollama /v1, AMD Lemonade, FastFlowLM on Ryzen AI NPUs). The endpoint is tried first at daemon start, with automatic fallback to the local model, then the rule-based compressor.

Share one model across environments

The model is a single ~3.5 GB GGUF file, identical on every platform, stored under the OS data directory: ~/.local/share/vexp/models/vexp-devmind-v1/ on Linux (/root/.local/share/… in a container running as root), ~/Library/Application Support/vexp/models/… on macOS, %APPDATA%\vexp\models\… on Windows. Every Dev Container, WSL distro or machine that installs it downloads its own copy unless you share one. Three ways, best first:

One shared volume. Mount a named Docker volume at the default models directory in every container; install once, and in every other container vexp setup-llm --install (or the sidebar's Install LLM) finds the file already there, verifies its size and skips the download — the step only writes that container's config.

.devcontainer/devcontainer.json
"mounts": [
"source=vexp-models,target=/root/.local/share/vexp/models,type=volume"
]

Reuse the host's copy. The same mount as a bind mount of the host folder (source=${localEnv:APPDATA}/vexp/models on Windows) needs no second copy at all. The model is memory-mapped, and reading it through Docker Desktop's file sharing is slow: the first calls after a start can exceed timeout_ms, which falls back to the rule compressor for that call. Fine when disk space matters more than warm-up time.

One server, many clients. Serve the GGUF once on the host (llama.cpp llama-server, LM Studio, Ollama) and point every environment at it with endpoint as above — http://host.docker.internal:8080/v1 from a container. No model files anywhere else, and inference runs on the host's GPU, which containers only get with the NVIDIA container toolkit. Any other location works too: model_path under [llm] in ~/.vexp/config.toml names the file directly. The CUDA plugin is per-platform and is not shared.

NoteThe local LLM is entirely optional. Everything else in vexp works without it.
Reference

Configuration

vexp works out of the box. Tune it via VS Code settings, .vexp/vexp.toml, environment variables, or ignore files.

VS Code settings

All under the vexp. prefix in Settings or your settings.json:

SettingTypeDefaultDescription
vexp.enabledbooleantrueMaster toggle for the extension
vexp.guardStrictbooleanfalseInstall the Grep/Glob deny hooks when configuring agents (opt-in). When off, agent setup removes any previously installed vexp guard hooks.
vexp.maxContextTokensnumber8000Maximum tokens per context capsule
vexp.skeletonDetailenum"standard"minimal / standard / detailed
vexp.gitHooksInstallbooleantrueOff: vexp removes its git hooks from this clone and does not reinstall them, like answering Skip; back on, they return (or the hooks question is asked). The index still refreshes through the file watcher
vexp.multiRepo.enabledbooleantrueMulti-repo workspace support
vexp.multiRepo.workspaceConfigstring".vexp/workspace.json"Path to the workspace config
vexp.telemetry.enabledbooleanfalseAnonymous usage telemetry (opt-in; never code content)
vexp.mcpPortnumber7821MCP HTTP port, used only when vexp.codexMcpTransport is set to http
vexp.codexMcpTransportenum"direct"How vexp configures the Codex IDE MCP server (direct stdio vs VS Code-managed HTTP); a config you wrote by hand is left untouched
vexp.binaryPathstring""Override the vexp-core binary path (escape hatch)
vexp.logLevelenum"warn"error / warn / info / debug
vexp.personalModebooleanfalseSkip agent configs + git hooks for this workspace
vexp.hideInternalFilesbooleantrueHide .vexp internal files from the explorer

.vexp/vexp.toml

Optional file at .vexp/vexp.toml inside the repo (all keys top-level — no [index] table). Useful for ranking hints and indexing limits:

.vexp/vexp.toml
max_file_size_kb = 512 # skip files larger than this; 0 disables the cap
max_context_tokens = 8000 # default context capsule budget
log_level = "warn"
priority_paths = ["src/core", "src/api"] # rank these higher
depriority_paths = ["generated", "vendor"] # rank these lower
filter_secrets = true # default; set false to disable secret filtering
tests_gate = "instruct" # stop-gate mode for impacted tests:
# "instruct" (default) blocks once naming the exact
# tests to run; "run" executes them and blocks only
# on red; "off" disables. Env override: VEXP_TESTS_GATE
exclude_patterns = ["generated/**", "vendor/**"] # repo-root-relative globs; a bare pattern also matches at any depth
delivery_ignore = ".distignore" # delivery boundary: pivots outside the package are tagged "(not shipped)";
# unset = auto-detect .distignore, then .npmignore
stage_manifest = false # pre-commit hook stages .vexp/manifest.json into the commit when true
output_mode = "v2" # compact output; "legacy" = plain-text output
scope_gate = "advisory" # "off" / "advisory" (report only) / "strict"
holdback_pct = 10 # 0-50; 0 disables the measurement holdback
ambient_seed = true # false = bare hint instead of the orientation seed
ambient_decay_after = 3 # hints served per session before going quiet; 0 disables (env: VEXP_AMBIENT_DECAY)
query_stemming = true # typed questions (25 words or fewer) also try a stem of each plain word (validated -> validat*); pasted issues stay literal; false = never (env: VEXP_QUERY_STEMMING=0)
# plan limits (max_nodes / max_repos) cannot be set here — they come from your license

In a multi-repo workspace, the primary workspace's .vexp/vexp.toml is the default for every connected repository. A connected repo needs its own file only where it wants to differ, and any key it sets there wins for that repo; keys it leaves out come from the workspace. So raising max_file_size_kb once on the primary applies to all of them.

The file may be UTF-8, with or without a byte-order mark, or UTF-16 as Windows PowerShell and Notepad save it. A file that cannot be read or parsed, or that has a setting of the wrong type, gets one warning in the log naming the file (and the setting); the whole file is then ignored and the defaults apply (in a connected repo, the workspace's settings). vexp still starts.

Delivery boundary

vexp indexes the working tree — shipped code, tests, docs, anything .gitignore does not cover. A project delivered as a package (a WordPress plugin ZIP, an npm tarball) ships a subset, and the file that says which is not .gitignore: it is .distignore (wp dist-archive) or .npmignore. When the repo root has one of those — or delivery_ignore names your own gitignore-syntax file — run_pipeline adds a header line > delivery boundary: .distignore — 2 of 5 pivots are outside the package and tags each such pivot (not shipped), so a file:line citation says whether the code is delivered. Ranking is unchanged; without such a file the output is exactly as before. It is an annotation, not a check of the package contents.

A source file over max_file_size_kb is not indexed at all: its symbols and the calls it makes are invisible to impact,search and run_pipeline. Every such skip is recorded in .vexp/coverage.json, flagged by vexp doctor and the index_status tool, printed after vexp index, and disclosed in the header of every pipeline answer. Files matching exclude_patterns are out by choice: they are not counted as oversized and never appear in the coverage warning — after adding a pattern, run vexp index once to refresh coverage.json.

Environment variables

VariableWhen to set it
VEXP_CORE_PATHBundled binary won't run, point at a locally-built vexp-core
VEXP_HOMEOverride the home directory used for ~/.vexp/ state (license, config, daemon registry). Set this when running inside a sandboxed environment (e.g. Codex, containers, CI) where the OS-resolved home directory differs from the real user profile. Must be an absolute path.
VEXP_NO_AUTOSTART_INSTALL=1Don't install login autostart on first vexp setup
VEXP_PORT=<port>MCP HTTP port (default 7821), set if 7821 is taken
VEXP_TRACE=1Verbose trace mode, same as -i/--trace (IPs / tokens / home paths redacted)
VEXP_NO_AUTOSTART=1Disable the lazy daemon/MCP bootstrap the CLI performs before most commands
VEXP_OFFLINE=1Stay fully offline: disables all license network calls (14-day grace applies)
VEXP_SKIP_UPDATE_CHECK=1Skip the advisory npm update check (same as --skip-update-check)
VEXP_WORKSPACE=<path>Pin workspace resolution (honored before CLAUDE_PROJECT_DIR); vexp doctor warns when a global pin points at the wrong repo
VEXP_OUTPUT_MODE=<v2|legacy>Default for the output_mode config key
VEXP_TESTS_GATE=<off|instruct|run>Per-session override of tests_gate
VEXP_AMBIENT_DECAY=<n>Override ambient_decay_after

Manifest & git

.vexp/index.db is local-only (gitignored by default). .vexp/manifest.json contains a small list of content hashes and is committed to git, clones rebuild incrementally from it (typically < 5 s on a 5 000-file repo). The pre-commit hook refreshes the manifest but does not stage it into your commit automatically; opt in with stage_manifest = true in .vexp/vexp.toml. A merge driver auto-resolves manifest conflicts. Git hooks (pre-commit, post-checkout, post-merge) keep the index in sync. Existing hooks coexist via marker-delimited blocks.

VS Code asks once per project whether to install them. Skip is remembered for this clone in .vexp/git-hooks.declined (never committed, so a teammate does not inherit it): vexp removes the hooks it had installed and the daemon no longer puts them back. vexp hooks remove, personal mode and the vexp.gitHooksInstall setting turned off record the same answer (the last two withdraw it once you undo them); vexp hooks install reinstalls them and withdraws it. Without the hooks the index still refreshes: the daemon watches the tree while it runs and reconciles it periodically.

Notevexp hooks can never fail a commit, merge or checkout (they are fail-open) and are repaired on every daemon start unless declined for this clone. If your repo uses a custom core.hooksPath (e.g. husky), hooks installed in .git/hooks never run — vexp detects and reports this.

Ignore files

vexp honours .gitignore, .ignore, .vexpignore and .vexp_ignore at every level of the tree, plus .git/info/exclude and git's global excludes file, all in gitignore syntax: negations, rules starting with a slash (/chatlogs/) and bare folder names work as in git. The live watcher applies exactly the rules of a full scan, together with exclude_patterns, the size and minified limits and the secret filter, so a file saved while vexp runs is indexed only if a full index would include it. A change to an ignore file in the project or to .git/info/exclude applies within seconds, without a restart, and a file it excludes is removed from the index with its change notes. Common directories are excluded by default: node_modules, .git, .vexp, target, dist, .next, __pycache__, build, vendor, Pods, DerivedData, .expo, venv, .venv, site-packages, .tox, .gradle, .m2, bin/Debug, bin/Release, obj, coverage, .nyc_output, test-results, playwright-report. Nested git checkouts (worktrees, submodules) are pruned as whole subtrees, and minified assets (*.min.js, *.min.css, *.bundle.js, ...) are skipped by filename.

Notes kept in the repository. A Markdown file that records the questions you ask vexp is, by construction, the strongest text match for those same questions. Since 3.2.0 a documentation section that records a question (a Q1: label, an expected/got note, a list of questions) is demoted the way CHANGELOG files already are, and files under notes/, journal/, diary/ or scratch/ are treated as records, as are the reports an agent writes when it is done (MISSION_ACCOMPLISHED.md, fixes_summary_final.md); a FAQ that states the question it answers is not touched. Agent instruction files and folders (.claude/, CLAUDE.md, AGENTS.md) rank as repository furniture. The pivot's why line names the rule (quotes the question, diary path). To take a folder out of the index entirely, add it to .vexpignore (/notes/ for a root-anchored rule); an exclude_patterns entry also matches the same name at any depth, so prefer .vexpignore for one specific folder.

Reference

Supported Languages

vexp parses 36 languages plus Markdown, CSS/SCSS/LESS stylesheets included. 32 have a dedicated tree-sitter grammar with language-specific extraction. For Vue, Svelte and Astro the <script> block (and Astro's --- frontmatter) is parsed as TypeScript; for Razor/Blazor the @code/@functions blocks are parsed as C#. Symbols keep their real file line numbers, and every component file gets a component node searchable by name. Templates/markup are not parsed. SQL indexes DDL, tables, views, functions, indexes, triggers from migrations and schema files. In Ruby, the methods ActiveRecord generates from has_many, has_and_belongs_to_many, has_one, belongs_to and scope (posts, post_ids, build_author, ...) are indexed as methods of their model since 3.3.1, and so is what delegate defines since 3.3.2. Ruby calls written without parentheses (author.posts, post.author.full_name) are linked through the class the receiver names, its superclasses and the modules it includes; a public_send with a computed name is reported by vexp impact as a dynamic call. Markdown is indexed via a structural heading scan (no tree-sitter). The doc comment directly above a declaration is indexed as the symbol's docstring - JSDoc, Python, Go and Rust since the beginning; Dart ///, C# /// <summary> (XML stripped), Javadoc and Doxygen blocks, Kotlin, Scala, Swift, C, C++, Objective-C, PHP, Ruby, Bash, PowerShell, Lua and OCaml since 3.2.0 - so a plain-English question can match the words of your comments, not only the words inside identifiers. Licence headers, trailing remarks and pragma lines are not docstrings, and secret-shaped values in a comment are masked before they are stored.

LanguageExtensions
TypeScript.ts, .tsx
JavaScript.js, .jsx, .mjs, .cjs
Python.py
Go.go
Rust.rs
Java.java
C#.cs
C.c, .h
C++.cpp, .cc, .cxx, .hpp, .hh, .hxx
Ruby.rb
Bash.sh, .bash
Kotlin.kt, .kts
Scala.scala, .sc
Swift.swift
Dart.dart
PHP.php, .module, .install, .inc, .theme, .profile, .engine (Drupal)
Elixir.ex, .exs
Haskell.hs
OCaml.ml, .mli
Lua.lua
R.r, .R
Zig.zig
HCL / Terraform.tf, .hcl
Objective-C.m, .mm
Clojure.clj, .cljs, .cljc
F#.fs, .fsx, .fsi
DockerfileDockerfile, Dockerfile.* (matched by filename, not extension)
Vue.vue
Svelte.svelte
Astro.astro
Razor / Blazor.razor, .cshtml
SQL.sql, .ddl, .dml
PowerShell.ps1, .psm1, .psd1
Groovy / Gradle.groovy, .gvy, .gradle
Julia.jl
CSS / SCSS / LESS.css, .scss, .less
NoteJSON is not indexed as a language, with one exception: manifest-shaped files — manifest.json, refs.json, index.json, catalog.json, examples.json, samples.json, registry.json, openapi.json, swagger.json, and *.manifest.json / *-manifest.json / *_manifest.json variants (same for catalog/examples/samples/registry) — are structurally indexed (top-level entries become searchable nodes, up to 500 per file). package.json, lockfiles, tsconfig*.json and other tool configs are never indexed, and nothing under .vexp/ is.

Markdown indexing

Markdown files (.md, .mdx, .markdown) are first-class index nodes. Each file becomes a Document node (named after the file stem); each ATX heading (# through ######) becomes a nested Section node; each http:// or https:// URL becomes a Link node (URLs inside fenced code blocks are skipped).

Planning documents, spec.md, plan.md, tasks.md, README.md, ADRs under docs/adr/, RFCs under docs/rfcs/, get a ranking boost when an agent searches for design or architecture context. Surfaced through run_pipeline and get_skeleton like code files.

Documentation-only repositories

A folder with no source code at all is a valid workspace: a knowledge base, a handbook, a tree of ADRs and specs. Run vexp setup in it from the CLI. The VS Code extension activates on a folder that holds source files or an existing .vexp/manifest.json, so in a Markdown-only folder run vexp setup once, or vexp: Setup Agents from the Command Palette, and it picks the index up from there.

What is matched. vexp matches the words of the task against document names, headings and section text, then ranks by structure. There are no embeddings: a question that shares no word with a section does not reach it on its own, which is why it works best through an agent, which turns a loose question into the terms your documents use. Sections come from ATX headings (#); a file with no headings is a single Document node, so the only thing vexp can return for it is the whole file.

What ranks lower. Ranking was tuned on code repositories, where a record of a change is never the answer. Three path rules matter in a knowledge base. A dated file name (2026-09-14-retro.md) and the folders notes/, journal/, diary/, scratch/, blog/, posts/ and releases/ mark a record, which ranks well below a reference document. A folder named exactly like a locale code (fr/, de/, it/, pt-br/) is read as a translation and left out of the answer. If meeting minutes or an it/ department folder are what you need to retrieve, name them otherwise (minutes/vendor-sync-september.md, it-department/).

To see what happened to a document you expected, name it: vexp capsule "who approves a refund?" --explain refunds.md runs the same retrieval and says where that file left it and which rule applied.

NoteEvery document, heading and link is one node, so a large knowledge base counts against the node limit of your plan faster than its file count suggests. See Plans & Quotas.
Support

Troubleshooting

Pick your distribution for the distro-specific issues, then check the cross-distro table below for the rest.

SymptomDiagnoseFix
Extension does nothingRun 'vexp: Doctor (diagnose daemon, license, hooks)' from the Command Palette — the health report lands in the 'vexp doctor' Output channelOpen a folder with a supported source file (or .vexp/manifest.json)
Index never updatesvexp: Show Index Statusvexp: Force Re-index
Bundled binary won't runSee the binary error in the Output panelSet vexp.binaryPath in Settings
macOS "unidentified developer"Only affects binaries copied or downloaded by hand (quarantined files)Install via npm or the marketplace (never quarantined). For a hand-copied binary: xattr -d com.apple.quarantine <path>
Sidebar empty / no reposCheck status header in the sidebarUse vexp: Start Indexing or reload the window
Copilot Chat shows no vexp tools / no vexp MCP serverRun vexp doctor (it checks .vscode/mcp.json); in VS Code: Command Palette → MCP: List Servers → vexp → Show OutputMCP tools exist only in Chat Agent mode (tools picker → "MCP Server: vexp"); the folder open in VS Code must be the one you set up; on spawn node ENOENT re-run vexp setup (it pins the absolute node path); on Copilot Business/Enterprise an admin must enable the "MCP servers in Copilot" policy
Hand-downloaded VSIX won't install / wrong platformCheck the file name ends in your platform (e.g. linux-x64)Install from the marketplace so the editor picks the platform; for manual installs use the platform-specific .vsix from Open VSX

Cross-distro issues

These apply whether you use the VS Code extension or the CLI.

SymptomDiagnoseFix
Agent can't reach vexpvexp daemon-cmd statusRe-run vexp setup, or run vexp doctor to diagnose daemon/MCP state
Port 7821 in usevexp daemon-cmd statusSet vexp.mcpPort (VS Code) or VEXP_PORT (CLI) and re-run vexp setup
Daily limit reached (Starter)Status bar shows "daily limit reached"Wait until midnight UTC, or upgrade to Pro
MCP entry runs the editor itself (Cursor.exe …mcp-server.cjs) — connection dies with MCP error -32000Open the agent's mcp.json: the command is the editor executable instead of nodeRe-run vexp setup — it writes a real node and repairs the broken entry instead of adopting it
vexp resolved the workspace to the home directory (agents that spawn MCP servers from ~, e.g. Antigravity)vexp doctor shows resolves to: /home/<you>Fixed (the ~/.vexp state dir no longer counts as a workspace); to pin a project for such an agent, set VEXP_WORKSPACE in a project-scoped MCP config
Codex never gets vexp’s per-prompt orientationvexp doctor (Codex section: project trust and hook approval, per place on Windows)Approve the hook once: Codex panel > Settings > Hooks > trust vexp-hint, or run codex in the project and type /hooks. On Windows approve it in each place you use Codex, and once more after updating from 3.2.5
Daemon refuses to start / status bar shows vexp: workspace capvexp daemonsFree a slot with vexp stop <workspace>, then start the daemon again — concurrent-workspace ceilings are per plan (Starter 1, Pro 4, Team 8)
LLM "no backends are loaded"vexp setup-llm --statusRun vexp setup-llm --status — its runtime library check names what is missing and prints the fix; if plugin files are missing, re-run vexp setup-llm --install (on NVIDIA machines it downloads the CUDA plugin and runtime)
LLM out of diskdu -sh ~/.local/share/vexp/modelsvexp setup-llm --disable, then delete the models folder
GPU crash / LLM silently on CPU after a crashvexp setup-llm --status (shows a 'GPU in use' verdict and the reason)vexp writes ~/.vexp/gpu-unusable after a GPU crash and runs the model on CPU. Update the NVIDIA driver to ≥ 570.xx, then delete ~/.vexp/gpu-unusable to retry the GPU (upgrading vexp also retries automatically). If the crash happened while running the model, set flash_attention = "off" under [llm] in ~/.vexp/config.toml to keep the GPU.
LLM “Backends registered: 0” on minimal Linux images (Replit, distroless, trimmed containers)vexp setup-llm --statusFixed (libgomp.so.1 is bundled app-local); on older releases run apt-get install libgomp1
Pro license shows as FREE / 2000 nodes in sandboxed env (Codex, containers)Run vexp doctor (it reports license state under the resolved home, no daemon needed), or check .vexp/daemon.log for home_dir= — the daemon logs it at startup. (vexp index shows it only with VEXP_LOG_LEVEL=info.)Set VEXP_HOME to the real user home in your MCP/agent config (e.g. VEXP_HOME=C:\Users\yourname)
Session cost explodes on long-context models (1M-token context windows)Check the agent transcript: the context keeps growing past ~200k tokens with no compactionOn 1M-context sessions every turn re-bills the entire context as cache reads, so any loop that inflates turns multiplies cost. Use the vexp defaults (no strict deny guard), keep run_pipeline to one orientation call per task, and compact or restart the session when the context passes a few hundred thousand tokens
Not sure what's wrong / agent can't reach vexpvexp doctorRead-only check of workspace drift, stale daemons, Codex transport, and license (works without a running daemon).
Want logsvexp daemon-cmd logs --followOr open .vexp/daemon.log directly
Want to send us a bug reportvexp doctor --reportAttach .vexp/vexp-report.md to your message (see below): doctor output, tool-call ledger, log warnings, config — secrets masked, paths visible
NoteIf none of the above match, the daemon log .vexp/daemon.log and the index log .vexp/vexp.log are the next stop. .vexp/vexp.log is auto-truncated to its last 500 lines when it exceeds 2 MB; .vexp/daemon.log is rotated on every daemon start — the previous boot's log is kept as .vexp/daemon.log.1.

Sending a bug report

vexp doctor --report writes .vexp/vexp-report.md: the doctor output as printed, the tool-call ledger of the last 30 days (per tool: calls, median, p95, max, how many ran past 30 s, how many ended with no result, and the ten slowest calls), the warnings and errors from the daemon log with repeats collapsed, and your vexp.toml. It never contains prompt text or file contents — parameters are reported by length only — and secret-shaped values are masked throughout. File paths are visible, so read it once, then send it to staff@vexp.dev or attach it to your issue. The ledger is read straight from the index database, so the report works with the daemon down. --report <file> picks another path.

The report is deliberately mechanical: numbers and log lines, nothing anyone has to second-guess. If you want your agent's observations next to it, paste this prompt into the same session and send the file it produces:

Run `npx vexp-cli doctor --report` in this workspace. Then read `.vexp/vexp-report.md` and, using only what happened in this session, write a short "Notes" section at the end: what I asked vexp for, what it returned, where it helped, where it did not, and anything in the report that surprises you. Do not change the sections above your notes. Tell me the path of the file when you are done.
NoteThe notes are the agent's opinion and the sections above them are measurements; keeping the two apart is what makes the file useful. Add your own line under the notes if there is something the agent could not see.
Support

Uninstall

A complete removal has two parts: remove the distribution you installed, then (optionally) clean up what vexp wrote on disk. Nothing vexp writes is hidden or system-level, everything lives in your home directory and your project folders.

  1. Stop the daemon. Command Palette → vexp: Stop Indexing, or use the stop button in the vexp sidebar panel.
  2. Uninstall the extension. Extensions panel → gear icon on vexp → Uninstall, or from a terminal:
    bash
    $ code --uninstall-extension Vexp.vexp-vscode
    The native engine is bundled inside the extension, so it is removed with it.
  3. Clean up leftovers. See the table below. If you also installed the npm CLI, follow the CLI tab as well.

Leftover data (optional cleanup)

These are safe to delete once vexp is removed. All of them are plain files and directories, no registry entries, no system services.

WhatWhereNotes
Per-project index.vexp/In each project root: index database, logs, workspace.json. Delete the folder.
Global state~/.vexp/License files, device id, autostart marker and log, and your answers about which agents to set up (agent-consent.json). Deleting removes your local license copy - keep your key to re-activate later.
Local LLM models (~3.5 GB)~/.local/share/vexp/models (Linux) · ~/Library/Application Support/vexp/models (macOS) · %APPDATA%\vexp\models (Windows)Only present if you installed the optional local LLM.
Agent config entries.claude/CLAUDE.md, .cursor/rules/vexp.mdc, AGENTS.md, …vexp sections are marker-delimited - delete the block between the vexp markers. Also remove the "vexp" server entry from MCP configs (~/.claude.json, .cursor/mcp.json, .vscode/mcp.json) and the vexp-guard PreToolUse hook from .claude/settings.json.

If you skipped autostart uninstall

Removed the CLI before running vexp autostart uninstall? The login hook is a single per-user file, delete whichever exists:

PlatformFile
Linux (systemd)~/.config/systemd/user/vexp.service
Linux (XDG)~/.config/autostart/vexp.desktop
Linux (shell profile)Block between # vexp-autostart-begin and # vexp-autostart-end in ~/.bashrc / ~/.zshrc / ~/.profile
macOS~/Library/LaunchAgents/io.vexp.serve.plist
Windowsvexp-serve.vbs in the Start Menu Startup folder (%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup)
Trust

Privacy & Security

vexp is designed for codebases you can't send to the cloud. Everything runs on your machine.

  • Local-only by default. Zero network calls for parsing, indexing, or querying. Outbound calls are limited to: (1) a once-a-day license check-in that sends only your license token, an anonymous device id and the vexp version — opt out with VEXP_OFFLINE=1, which disables all license network calls (vexp keeps a 14-day grace period); (2) an advisory CLI update-availability check against the npm registry — cached 4 hours, never blocks a command, and skippable with VEXP_SKIP_UPDATE_CHECK=1 or --skip-update-check; (3) the explicit, opt-in local-LLM model download when you run vexp setup-llm. Nothing else ever leaves your machine.
  • No code execution during indexing. vexp parses your code with tree-sitter; indexing and querying never execute it. The one exception is opt-in and explicit: vexp verify --run-tests (or tests_gate = "run") runs your repo's own test suite, bounded, at your request.
  • Telemetry is opt-in. Telemetry is opt-in and off by default. The vexp.telemetry.enabled setting exists for future use; today vexp transmits nothing.
  • Distribution integrity. Binaries ship exclusively through npm (with registry integrity checksums) and the VS Code / OpenVSX marketplaces; there is no browser-download channel. macOS binaries carry the Apple toolchain's standard ad-hoc signature and are not Developer-ID notarised today: npm and marketplace installs are never quarantined, so Gatekeeper does not evaluate them. If your security policy requires notarised or countersigned artifacts, contact us about the enterprise distribution line.
  • Secret filtering (default on). Files named like credentials are dropped at index time: .env, .env.production, .env.local, id_rsa, *.pem, *.key, secrets.yaml, secret.md, password.json, credentials.toml, and similar filename-boundary matches.
  • Template files allowlisted. .env.example, .env.sample, .env.template, .env.test, secrets.example.*, and secrets.sample.* are not excluded, they document contracts, not secrets.
  • Filename boundary matching. Legitimate source files that just contain the word secret, password, or credential in their name, e.g. src/secret-manager.ts, are not excluded.
  • Custom exclusions. Add patterns to .vexpignore (gitignore syntax; the older .vexp_ignore name is also honored), or set exclude_patterns = ["generated/**", "vendor/**"] at the top level of .vexp/vexp.toml — repo-root-relative globs; a bare pattern like dist/** also matches at any depth. To disable the secret filter entirely, set filter_secrets = false at the top level of .vexp/vexp.toml.
NoteThe license system itself doesn't need the network: signature verification is offline, and the 14-day grace period covers planes, ferries, and locked-down build machines.
Reference

Plans & Quotas

Quotas at a glance. For prices and the upgrade button, see the full pricing on the homepage.

PlanNodesReposDaily calls
Starter (Free)2,000120 / day (resets midnight UTC)
Pro50,00031,000 / day
Teamunlimitedunlimited1,500 / day per workspace
Lifetime Tier 110,0001500 / day
Lifetime Tier 250,00031,000 / day
Lifetime Tier 3100,000unlimited1,200 / day
Lifetime Tier 4unlimitedunlimited1,500 / day
NoteDaily calls count only against run_pipeline, get_context_capsule, and get_skeleton. Memory tools and index status never count, on any plan. Impact graphs and flow analysis are paid-plan features, not part of Starter. Ambient hints and the orientation seed are infrastructure and never count against the budget.
NotePaid-plan ceilings are a fleet fence, not a meter: they sit far above any interactive day (the heaviest measured usage stays under half the Pro ceiling), and exist so that automated, headless or service use lands on the SDK line. Hitting one refuses the call with a clear message; the daemon stays up and everything else keeps working. Every plan carries a concurrent-workspace ceiling — 1 live daemon on Starter, 4 on Pro, 8 on Team — with the same philosophy.

What happens at the limits

  • At 80 % of the node cap, the VS Code extension shows a warning (once per session, on any node-capped plan). CLI-only setups get no 80 % warning.
  • At 100 % of the node cap, new nodes stop being added. Your existing index keeps working, no data loss. The VS Code notice and status-bar tooltip, the index_status tool and vexp index say how many source files were left out and the estimated size of the whole project, the two numbers you need to size exclude_patterns or pick a plan. The tooltip and index_status drop it once the index fits under the cap again.
  • At 20 daily calls, the next call to a quota-affected tool returns a limit-reached error and the daemon shuts down. This stops every vexp tool, not just the quota-affected ones, until the quota resets at midnight UTC. Nothing is lost: your index and session memories are kept on disk and are there when it comes back (or upgrade to Pro/Team, whose ceilings interactive use never reaches).

License activation

Run vexp: Activate License Key from the Command Palette and paste your key, or click the magic link in the activation email, vexp activates without any further input.

Daily check-in

Once a day, vexp checks in with vexp.dev from every setup: VS Code, the CLI, or an AI agent running vexp on its own. The check-in sends your license token, an anonymous device id (a random string stored in ~/.vexp/device.id) and the vexp version, nothing else. It registers the machine against your plan's device limit and keeps your license current. Set VEXP_OFFLINE=1 to turn it off; nothing then renews your license key either, so a paid plan lasts until the key's own expiry (30 days after its last renewal) and returns at the next check-in.

Offline use

vexp refreshes your license quietly in the background whenever you're online. If you stay offline, you keep working at your current plan for at least 14 days; after that vexp falls back to your license key itself, which keeps the paid plan until its own expiry date. Only when that also lapses does vexp drop to Starter — no data loss, and your plan returns automatically the next time you're online.

Account portal

Manage your subscription, devices, and team at vexp.dev/account (magic-link login). Team owners can add or remove members; each member logs in independently.

Device limit

Each license covers a limited number of devices: Pro 4, Team 4 per seat, Lifetime Tier 1 and Tier 2 one, Tier 3 five, Tier 4 ten. A machine counts from its first check-in, right away when you activate your key and otherwise within a day. Each environment with its own home folder counts as a device of its own: WSL next to Windows, or a dev container. On a lifetime license, a machine over the cap runs at Starter limits until you free a slot at vexp.dev/account/devices — your key stays valid, and the plan returns automatically on that machine once a slot is free. A slot is freed only when you remove a device there.