@vibedrift/cli
v0.21.3
Published
Ship agentic. Stay coherent. Self-checking code integrity for AI coding agents, in the loop via MCP.
Downloads
1,955
Maintainers
Readme
vibedrift
Your AI drives. VibeDrift navigates.
Open source · Analysis runs on your machine · JS/TS, plus Python, Go and Rust
npx @vibedrift/cliOn Claude Code: install the plugin instead — one install wires in the MCP server, the drift-check skill, and /vibedrift:setup.
Contents
- Claude Code: 30-second setup
- What drift is
- The three channels
- The CLI: you run it
- The MCP server: your agent asks
- Drift Sessions
- What it detects
- Scanning and reports
- Configuration
- Deep scan
- CI integration
- Privacy
- Command reference
- Pricing
- Developer Handbook
- Contributing
- License
- Links
Claude Code: 30-second setup
1. Install the plugin.
/plugin marketplace add VibeDrift/VibeDrift
/plugin install vibedrift@vibedriftThe plugin bundles the MCP server — wired in for you, no claude mcp add needed — plus the in-loop drift-check skill, the /vibedrift:setup command below, and the Drift Sessions hooks. The hooks capture nothing until you activate a repo (/vibedrift:setup or vibedrift enable; only the one-time activation nudge speaks before that), and with the plugin installed, activation is the whole step: no repo-local hook install is written. A repo that already has vibedrift watch-session installed is captured once, by that install. The community-marketplace listing is pending, so that's the install path today; once it lands, a plain claude plugins install vibedrift will also work, but it does not yet.
Already have claude mcp add vibedrift set up from before? Run claude mcp remove vibedrift after installing the plugin, so you are not left with two copies of the server wired in.
Not on Claude Code, or want to wire the server in yourself? Skip the plugin and use claude mcp add or the generic mcpServers JSON in the MCP server section below, same server, same tools, any MCP client.
2. Run /vibedrift:setup, once per repo. It:
- detects whether this repo has been set up before, and picks up from there
- configures what to exclude, through the MCP server's
inittool - runs a baseline scan and injects a context block into
CLAUDE.md - offers Drift Sessions, through a native consent prompt
3. Done. VibeDrift rides along from then on: the MCP tools answer as the agent writes, and, if you opted in, Drift Sessions flags drift live in the session.
What drift is
Every fresh agent session starts with no memory of the conventions your codebase already settled on. So it makes reasonable choices that are not your choices.
One handler throws a typed error, the next returns a plain object. Eight services go through a repository layer, the ninth reaches for raw SQL. Everything compiles, everything passes review, and the codebase slowly stops agreeing with itself.
That gap is drift. Linters miss it by design: a linter checks one file against a rulebook. VibeDrift checks your codebase against itself. It learns the patterns your code already agrees on, flags the files that deviate, and points at the exact line.
The three channels
VibeDrift reaches your code three ways. One local engine, three different moments.
| Channel | Who starts it | What you get | Tier |
| --- | --- | --- | --- |
| CLIvibedrift | You, after the code exists | Scans, HTML reports, a CI gate, continuous watch, a git pre-push gate | Free (watch, the pre-push gate and deep scan are Pro) |
| MCP servervibedrift mcp | Your agent, before it writes | Eight tools it can call: the repo's dominant pattern, near duplicates, whether a file drifts | Free (an opt-in deep flag on two tools is metered) |
| Drift Sessionsvibedrift watch-session | VibeDrift, while the edit happens (Claude Code only today) | A one line advisory in the agent's context whether it asked or not, on a live tape | Pro, one time 5 session trial |
The last two are different plumbing. MCP is pull: a long lived process your agent connects to over stdio, so it only helps when the agent chooses to ask. Drift Sessions is push: it rides Claude Code's own hooks, so VibeDrift gets a word in whether the agent asks or not. Run both and they join up: while a Drift Session is active, the MCP server's verdicts tee into that same session ledger, so the agent's questions and VibeDrift's flags read as one dialogue. Without an active session the MCP tools simply answer and write nothing.
One word, two meanings.
vibedrift hookis the git pre-push gate, part of the CLI channel. The agent hooks behind Drift Sessions are a Claude Code feature and have nothing to do with git. Different command, different mechanism.
The CLI: you run it
npx @vibedrift/cliNo install, no signup. Scans the current directory and opens an interactive HTML report.
Install globally if you scan often:
npm i -g @vibedrift/cli
vibedrift # scan ./
vibedrift ./path/to/project # scan a specific path
vibedrift --format terminal # print to stdout insteadRequires Node.js 20 or newer.
The MCP server: your agent asks
Your agent pulls. The MCP server lets it interrogate your codebase before it writes a line, so new code matches the first time.
claude mcp add vibedrift -- npx -y @vibedrift/cli mcpOn Claude Code, the plugin does this step for you, skip the command above and install it instead.
Any other MCP client uses the same stdio command:
{
"mcpServers": {
"vibedrift": { "command": "npx", "args": ["-y", "@vibedrift/cli", "mcp"] }
}
}Eight tools ship with the server:
| Tool | What the agent gets |
| --- | --- |
| get_intent_hints | The conventions your CLAUDE.md, AGENTS.md, or .cursorrules already declare |
| get_dominant_pattern | The repo's majority pattern for a dimension, with example files to copy |
| check_file_drift | Whether a file diverges from those patterns, and how |
| find_similar_function | An existing near duplicate, so the agent reuses instead of rewriting |
| validate_change | Whether a proposed function would introduce drift or duplicate something |
| init | One time repo setup, so every tool skips non product code |
| enable | The Drift Sessions activation answer: records your consent (or your decline) and installs the Claude Code hooks when present |
| respond_to_flag | The agent's call on a live Drift Sessions flag: accept, park, or decline |
These run on your machine and need no login. The baseline builds itself on the first tool call in a repo, once, then caches. A no_baseline reply means there was no code to analyze or the build failed, not that you skipped a setup step.
Two of them, validate_change and find_similar_function, also take an opt-in deep flag that checks your function against the cloud checker. It needs an account, it is metered, and it is the only part of this channel that leaves your machine: the first deep call in a repo sends your functions to be embedded, and later calls send the function being written plus the handful of existing functions it might duplicate. It stays off unless the agent asks for it.
No MCP client? The five query tools above, everything except init, enable, and respond_to_flag which are MCP only, are also plain functions: import { validateChange, findSimilarFunction } from "@vibedrift/cli/tools" (docs/tools-api.md), or a self contained Agent Skill.
Drift Sessions (preview)
VibeDrift pushes. A scan finds drift after the code exists, and MCP only helps when the agent thinks to ask. Drift Sessions flags a drifting edit while your agent is still typing, asked or not.
Turn it on, once
Point --dir at the folder you keep your work in. It shows you the resolved path and asks you to confirm by typing, and it refuses your home directory and filesystem roots.
vibedrift enable --dir ~/work # every repo under it, including new onesThat is the whole setup, for every repo in that folder and every repo you clone into it later. There is nothing to initialize and no scan to run: a repo VibeDrift has not seen yet records its edits and marks them as not checked, learns its own patterns in the background when the turn ends, and is checked from the next session on.
One repo at a time works the same way, and typing the command is the consent:
cd ~/your/project
vibedrift enable
vibedrift watch-session --status # is this repo set up?
vibedrift decline # turn it off; reversible with enableDrift Sessions ride inside a Claude Code session through the agent's own hooks, which Claude Code runs at session start, on each prompt, after each edit, after each Bash command, and when the session stops. When an edit diverges from the patterns your repo already follows, VibeDrift writes a one line advisory straight into the agent's context, so the agent can correct itself on the spot instead of waiting for a review it will never see.
One session, many repos
An agent session that moves across several repos is one sitting, and each repo in it is tracked on its own. An edit belongs to the repo that owns the edited file, so it lands in that repo's ledger and is judged against that repo's patterns, never against whichever folder your agent happened to start in. Files that belong to no repo stay with the working folder, which gets a scope of its own.
Consent stays per repo. A repo covered by your folder grant records, a repo where you typed vibedrift decline records nothing even inside that folder, and a repo nobody has answered for records nothing at all. Each repo you touch also gets its own patterns learned in the background, one repo at a time, so the setup work does not come back as the workspace grows.
Watch it happen (optional)
vibedrift enable is all you need. If you also want to see the session as it runs, watch-session opens a live event tape and follows along until you stop it. It is a viewer, not a second setup step, though it will install the hooks itself if the repo does not have them yet.
vibedrift watch-sessionThe two commands differ in one way worth knowing. enable will let the Claude Code plugin provide the hooks when the installed plugin ships them, so nothing is written into your repo. watch-session always writes the hooks into .claude/settings.local.json for that repo, and that copy then owns the capture.
You watch the whole thing happen on a live event tape. Prompts show as USER, the agent's edits as AGENT, and VibeDrift's own flags and outcomes as VIBEDRIFT, all on one stream with a running count and a smoothed drift gauge in the footer. If the MCP server is also connected, its verdict calls (validate_change, check_file_drift, find_similar_function) join the same tape as ASKS and REPLIES rows, so the agent asking VibeDrift and VibeDrift flagging the agent read as a single dialogue.
Outcomes are real, not guessed. A finding is marked resolved only when the same finding re-runs over the re-edited file and passes, so the summary's open and resolved counts mean something.
What it records, and where
Everything lands in an append-only JSONL ledger, one per session per repo:
~/.vibedrift/sessions/<projectHash>/<sessionId>.jsonlA session that touched three repos therefore writes three ledgers, one under each repo's own id, and all three ship at the end of every turn.
| Recorded | Never recorded | | --- | --- | | Your prompts, with secrets masked | Your source code | | Edit metadata: repo relative path and a diffstat | The diff body | | Drift flags, MCP calls, and their outcomes | The agent's transcript file |
The capture hook is fully offline and fails open: a hook error, a timeout, or an input shape it does not recognize exits cleanly and never interrupts your agent. Installation writes marker tagged entries into the project's .claude/settings.local.json behind an explicit consent prompt, and --uninstall removes exactly what it added. Recorded ledgers always remain yours.
vibedrift watch-session --status # is it installed for this repo?
vibedrift watch-session --no-watch # install without following the tape
vibedrift watch-session --uninstall # remove the agent hooks
vibedrift watch-session --sync on # opt in to the hosted dashboard
vibedrift recheck-session # clear open findings whose flagged code is gone (recorded apart from in-loop fixes)Sync is off by default. Turning it on uploads a derived projection only, meaning findings, outcomes, and metadata, to vibedrift.ai/dashboard/sessions. Never your code or your prompts, and file paths travel as per-repo hashes rather than real paths.
Drift Sessions is a Pro feature with a one time 5 session free trial, and a free account is all it takes to start. After the trial, capture stops: no more in-context advisories, and the tape locks behind a summary of what the trial caught. See pricing.
What it detects
- Architectural inconsistency. Half your handlers use a repository, the rest hit raw SQL.
- Hidden duplicates. Two functions doing the same job under different names.
- Convention drift across naming, imports, exports, error handling, async style, logging, comments, and test structure.
- Security consistency. Routes that skip the auth the rest of your code applies, plus hardcoded secrets and injection risks.
- Phantom scaffolding. Placeholder and half finished implementations that look done.
- Hygiene. Dead code, complexity hotspots, and TODO density.
Findings roll into two independent numbers:
- Vibe Drift Score (0 to 100) across Architectural Consistency, Redundancy, Security Consistency, and Intent Clarity. How consistent your code is with its own dominant patterns.
- Hygiene Score (0 to 100). Generic quality checks, kept separate so they never contaminate the drift number.
Coverage is not uniform across languages. Scoring, duplicate detection, and Security Consistency run on all five; several convention detectors, including exports, error handling, and test structure, are JS/TS only today.
Drift is always measured against your repo's own behavior, never an external style guide. A minority directory that is internally consistent is not drift. The Developer Handbook explains the dominance vote and the Code DNA fingerprinting that finds near duplicates.
Scanning and reports
vibedrift --format terminal # print to stdout instead of opening HTML
vibedrift --json > report.json # machine readable
vibedrift --diff main # only what differs from a branch| Flag | Effect |
| --- | --- |
| --format <type> | html (default), terminal, json, csv, docx |
| --output <path> | Write the report to a file |
| --fail-on-score <n> | Exit 1 when the score falls below n |
| --diff [ref] | Scope to files changed in git, uncommitted vs HEAD by default |
| --include / --exclude <glob> | Filter the files scanned, repeatable |
| --deep | AI deep analysis, requires vibedrift login |
| --write-context | Write committable .vibedrift/ context files, requires a free account |
| --inject-context | Inject the context summary into CLAUDE.md in a managed block |
| --local-only | Skip every network call |
| --since <scanId> | Diff against a specific saved scan |
Scans compare themselves against your previous run automatically when history exists. Run vibedrift --help for the full list.
Configuration
vibedrift initinit detects fixtures and generated code, then asks which paths to skip, your CI score floor, and your default report format. It writes two committable files:
| File | Holds |
| --- | --- |
| .vibedriftignore | Which paths to skip, gitignore syntax |
| .vibedrift/config.json | Default report format and CI score threshold |
Commit both so your whole team scans the same way. .vibedriftignore is honored by the CLI and the MCP server, so excluded paths stop counting toward your score in either. Use it for test fixtures, generated code, and vendored files that are not really yours.
Skip the wizard with vibedrift ignore "**/fixtures/**" to append a glob, or vibedrift init --yes to accept the detected defaults non interactively.
Deep scan
--deep adds cloud analysis that local static checks cannot do: semantic duplicate detection, name versus behavior intent checks, and a synthesized coherence report graded against your own patterns (Pro).
vibedrift login
vibedrift --deep # full repo
vibedrift --deep --diff # only what you changed, a fast pre-PR checkDeep scan sends function-level snippets and their repo-relative paths, never whole files. Free accounts include a monthly deep scan allowance; see pricing.
CI integration
Any runner works, since --fail-on-score sets the exit code:
# .github/workflows/vibedrift.yml
name: VibeDrift
on: [pull_request]
jobs:
drift-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npx @vibedrift/cli --local-only --format terminal --fail-on-score 70A GitHub Action is also available if you want a score delta comment posted on the pull request.
To gate locally instead, vibedrift hook install writes a git pre-push hook that blocks a push below your threshold (Pro). That is the git hook, not the agent hooks behind Drift Sessions. Bypass once with git push --no-verify.
Privacy
- Analysis runs on your machine. Parsing, pattern detection, and scoring are all local. Nothing about how VibeDrift reaches a verdict depends on a server.
--local-onlyskips every network call, even when you are signed in. Reach for it when you want a scan with zero egress.- Signed out, only the anonymous beacon leaves. After each scan VibeDrift posts language, file count, lines of code, scan time, CLI version, finding count, score, whether the scan was deep, whether the directory is a git repo, whether intent hints were found, and whether you were signed in. No code, no paths, no identifiers. Opt out with
vibedrift telemetry disable,VIBEDRIFT_TELEMETRY_DISABLED=1, or--local-only. - Signed in, each scan syncs its result to your dashboard, which is how your history and score trend appear on vibedrift.ai. That payload carries repo-relative paths and code snippets from findings, so use
--local-onlyon anything you would rather keep entirely local. The HTML report also pings once when you open it in a browser, carrying the scan id and a timestamp and nothing else. Reports produced signed out or under--local-onlyhave no such ping. --deepis opt in per run. It sends function-level snippets and their repo-relative paths, never whole files.- Update check. Once a day the CLI asks npm whether a newer version exists. Cached, silent on failure, skipped under
--local-onlyand when telemetry is off. - Auth state lives at
~/.vibedrift/config.json(mode0600) and scan history at~/.vibedrift/scans/, never inside your project tree.
| Variable | Purpose |
| --- | --- |
| VIBEDRIFT_TOKEN | Bearer token for CI and non interactive use |
| VIBEDRIFT_API_URL | Override the API base URL |
| VIBEDRIFT_TELEMETRY_DISABLED | Set to 1 to turn off the beacon and the update check |
| VIBEDRIFT_NO_BROWSER | Set to 1 to never auto open a browser |
Command reference
| Command | Does |
| --- | --- |
| vibedrift [path] | Scan a project. The default command. |
| vibedrift init [path] | Guided setup: .vibedriftignore and .vibedrift/config.json |
| vibedrift ignore <globs...> | Append path globs to .vibedriftignore |
| vibedrift watch [path] | Re-scan and refresh .vibedrift/ on file changes (Pro) |
| vibedrift watch-session [path] | Drift Sessions, the live agent tape (preview) |
| vibedrift enable [path] | Drift Sessions: activate this repo — typing this is the consent; records prompts (secrets masked) + edit metadata to a local ledger |
| vibedrift enable --dir <dir> | Activate every repo under a folder, including ones added later — asks you to confirm the resolved path; refuses $HOME and filesystem roots |
| vibedrift decline [path] | Drift Sessions: decline for this repo — never asked again, capture stays off (reverse anytime with vibedrift enable) |
| vibedrift recheck-session [path] | Re-check open Drift Session findings against the tree; clears are recorded apart from in-loop fixes (--dry-run, --session, --json) |
| vibedrift mcp | Run the MCP server over stdio |
| vibedrift hook <action> | Manage the git pre-push drift gate, not the agent hooks (install is Pro) |
| vibedrift login / logout | Account auth |
| vibedrift status | Current account, plan, and token |
| vibedrift usage | This billing period's scan usage |
| vibedrift upgrade | Open the pricing page |
| vibedrift billing | Open the Stripe customer portal |
| vibedrift telemetry <action> | Enable or disable the anonymous beacon |
| vibedrift doctor | Diagnose install, auth, and API connectivity |
| vibedrift update | Update to the latest version |
| vibedrift feedback [message] | Send feedback straight to the maintainer |
Pricing
The CLI is MIT licensed and the local engine is free forever, including the local MCP tools.
| Tier | Includes |
| --- | --- |
| Free | Unlimited local scans, the MCP server's local tools, a monthly deep scan allowance, a 5 session Drift Sessions trial |
| Pro | Drift Sessions, watch, the git pre-push gate, and more deep scans |
| Enterprise | Custom terms, contact sales |
Current numbers live at vibedrift.ai/pricing.
Developer Handbook
Fifteen chapters covering the whole engine: the scan pipeline, every static analyzer, cross-file drift detection, Security Consistency across all five languages, Code DNA fingerprinting, the scoring engine, the MCP server, Drift Sessions, and how to add your own detector or language.
- Web: vibedrift.ai/handbook
- GitHub:
docs/handbook/ - Offline:
docs/handbook/DEVELOPER_HANDBOOK_OSS.html, one self contained file
Build it yourself with npm run handbook.
Contributing
Contributions are welcome. Start with CONTRIBUTING.md for setup and how to add an analyzer, AGENTS.md for codebase conventions, and SECURITY.md for reporting vulnerabilities. Read the Developer Handbook before changing the engine.
License
MIT. See LICENSE. The CLI runs entirely on your machine. The optional cloud deep-scan service it can talk to is a separate hosted product.
Links
Website · Docs and scoring guide · Handbook · Blog · Releases · FAQ · Issues · Discord
