Introduction
Vigils is a local-first control plane for AI agents:
- Action firewall (
Firewall::evaluate) — fail-closed effect gating - Audit ledger (SHA-256 hash chain) — tamper-evident decision history
- Privacy filter — hard-fingerprint rules (always on) + optional ONNX PII/injection model (opt-in via
--engine ml|auto; not in default release builds — see Privacy Filter) - MCP hub (Model Context Protocol server registry + descriptor pinning)
- Approval queue (human-in-the-loop for risky effects)
- Sandbox runner (Wasm + native, Linux Landlock LSM)
Vigils sits between AI agents and the effectful tools / APIs they touch, gating each action through redaction + policy + audit + approval — and everything stays on your machine.
Two ways in
- Desktop app — a few clicks. Open the Aegis command deck and click Deploy Guardian: Vigils detects every installed agent, backs up its config, wires hook + MCP-gateway protection into all of them and shows per-agent status. Missing engine? One click downloads it (signed manifest + SHA-pin, fail-closed). Close the window — it keeps guarding from the tray. See the Desktop Quickstart.
- CLI — one command.
vigil-hub setup --alldoes the same from a terminal, andvigil-hub demoshows the whole protection story in 30 seconds with zero setup. See Agent Integration.
What it protects against — and what it doesn’t
Vigils is defense in depth, not an airtight barrier. Being honest about the boundary lets you rely on it correctly.
Reliably catches
- Plaintext credential leaks — 13 hard-fingerprint classes (AWS keys, GitHub / GitLab tokens, Google API keys, Slack webhooks, Stripe keys, private-key PEM blocks, credential-bearing DB URLs, …) appearing verbatim in tool calls, browser pastes, or tool results.
- Reversible redaction round-trip — the model / logs / audit see only
secret://<alias>placeholders; the real value is injected only at the local execution boundary. - Tamper-evident audit (SHA-256 chain, falsifiable via
vigil-hub verify), approval gating, and sandbox isolation.
Does not stop (deliberate evasion)
Input-side fingerprint detection is fundamentally evadable by a model that is trying to exfiltrate: it can encode / transform a secret (base64, hex, String.fromCharCode, chunking) or route it through a channel Vigils doesn’t mediate (e.g. a Playwright-driven browser typing character-by-character). Vigils raises the bar and leaves an audit trail, but is not a guarantee against an adversarial agent. Don’t treat “Vigils is installed” as license to let an untrusted agent handle real credentials.
The complete fix (roadmap)
An egress proxy that mediates all outbound data is the full answer — it catches encoded / chunked exfiltration before the value leaves the machine. That’s future work; until then, treat Vigils as audit + accidental-leak prevention + reversible redaction, not a sealed exfiltration barrier.
Project status
| Dimension | State |
|---|---|
| Releases | 3-platform signed installers + auto-update (OTA) — latest release |
| Rust SDK | vigil-sdk published to crates.io |
| Security | Comprehensive audit (OWASP + STRIDE + supply chain) — 9.9 / 10, 0 critical / high |
| Maturity | Core safety claims proven-safe with code + test evidence; all sandbox / SDK / audit changes reviewed |
Distribution
- Desktop installers — Linux deb / rpm / AppImage + macOS dmg + Windows nsis / msi (Ed25519-signed, auto-update).
- Rust SDK —
cargo add vigil-sdk(crates.io / docs.rs). - Browser extension — Chrome MV3 (redacts before paste / submit on AI sites).
- CLI agent gateway —
vigil-hub serve --stdio; turnkeysetup --allcovers Claude Code / Codex / Gemini CLI / Cursor hooks and MCP wrapping for Claude Code / Codex / Cursor / Windsurf / Kimi CLI / ZCode / pi.
License
Apache-2.0 © Vigils Project Contributors
Quick links
- Installation
- Quickstart — Desktop App
- Agent Integration & Test
- Quickstart — Embedding the SDK
- Architecture Overview
Watch the demo (20 seconds)
One command — vigil-hub demo — shows the whole idea: your AI agent tries to leak a
secret, and Vigils stops it. Everything below runs locally: the firewall, the
redaction, and the tamper-evident audit are the real runtime code paths; only the
external model/tool is simulated, and no LLM is contacted.
Player not loading? Download the recording and play it with
asciinema play vigil-demo.cast, or just run it yourself after installing:vigil-hub demo.
What you just watched
- Default-deny. The agent puts a raw GitHub token into a tool call. The firewall
refuses to forward a raw secret —
DENY. - The Vigils way. The agent instead passes a placeholder (
secret://github_pat). The remote model only ever sees the placeholder; the real value is detokenized only at the local tool boundary; and when the tool’s result leaks a credential back, Vigils re-redacts it before the model sees anything. - Tamper-evident audit. Every step lands in a SHA-256 hash-chained ledger — with no
plaintext secrets stored. (
vigil-hub demo --tamperalters one row and the chain verification fails, on purpose.)
The agent did useful work with a real secret — while the model, the logs, and the audit never received the real value. That is the whole product, in one command.
Next: install it and protect your own agents with
vigil-hub setup --all.
Install Vigils
简体中文:安装 Vigils
1. Which download do I want?
| I want to… | Download | Where |
|---|---|---|
| Use the app — see activity, approve actions (a window/GUI) | the desktop installer for my OS | §2 |
| Guard my AI coding agent — Claude Code / Codex / Cursor / Zed | the CLI (vigils-cli-…) | §3 |
| Guard pasting into AI websites — ChatGPT / Claude / Gemini | the browser extension | §4 |
Most people want the desktop app. Developers wiring up an agent want the CLI.
All files live on the Releases page
(replace <version> below with the one you grabbed, e.g. 0.3.0).
2. Desktop app
Pick your OS, download, run. First launch shows a one-time “unknown developer” prompt (we’re not OS-code-signed yet) — the steps to allow it are below.
Windows
- Download
Vigils_<version>_x64-setup.exe→ double-click. - If a blue “Windows protected your PC” box appears → More info → Run anyway.
- Done. (The warning fades on its own as more people install.)
macOS
- Download the dmg for your chip — Apple Silicon:
Vigils_<version>_aarch64.dmg; Intel:Vigils_<version>_x64.dmg(not sure? Apple menu → About This Mac — “Apple M…” means Apple Silicon) → open it → drag Vigils to Applications. - First launch is blocked (“Apple could not verify…”). To allow it once: ** System Settings → Privacy & Security → scroll down → “Open Anyway” → confirm with Touch ID / password.**
- Done — it won’t ask again.
Terminal alternative (power users):
xattr -dr com.apple.quarantine /Applications/Vigils.appThis is the standard one-time step for any not-yet-notarized app; signing is planned.
Linux (Ubuntu 22.04+ / Debian 12+)
sudo dpkg -i Vigils_<version>_amd64.deb # Debian / Ubuntu
sudo rpm -i Vigils-<version>-1.x86_64.rpm # Fedora / RHEL
chmod +x Vigils_<version>_amd64.AppImage && ./Vigils_<version>_amd64.AppImage # portable, any distro
On an older distro (the desktop GUI needs glibc ≥ 2.35)? Use the CLI instead — it runs on practically any Linux (glibc ≥ 2.17).
3. CLI — guard your coding agent (30 seconds)
Install it with one line:
curl -fsSL https://vigils.ai/install.sh | sh # macOS / Linux
irm https://vigils.ai/install.ps1 | iex # Windows (PowerShell)
(Or download vigils-cli-<os> from Releases and unpack it — it contains vigil-hub.)
Then turn on protection:
vigil-hub setup # auto-detects Claude Code / Codex / Cursor and wires the guard
Restart your agent — that’s it. Raw secrets are now blocked from its tool calls, and every
block is recorded in a tamper-evident local ledger. Kick the tires with vigil-hub demo
(zero setup). Per-agent details: Agent Integration
(中文).
ML variant (optional, semantic PII + prompt-injection detection): download
vigils-cli-ml-<os>instead and runvigil-hub serve --engine ml. Floors: Linux glibc ≥ 2.28, macOS ≥ 14, Apple Silicon only (upstream onnxruntime dropped x86_64 macOS; Intel macs use the default hard-fingerprint engine). See Privacy Filter.
4. Browser extension (Chrome)
Redacts secrets / PII before you paste or submit on AI sites. Install
Vigils Browser Guard
from the Chrome Web Store — consumer mode works out of the box, no desktop app required.
Optional deep redaction: install the Vigils CLI, register the native messaging host
(vigil-native-host install --extension-id <ID>, ID shown in the extension’s Options),
then pick “Local Vigils engine” under enterprise mode in Options — checks route to the
local engine (hard fingerprints + ML PII when the daemon runs); raw text never leaves
the device. Dev builds:
chrome://extensions → Developer mode → Load unpacked → pick extensions/chrome-mv3/.
Worried it’s authentic? Every download has a SHA-256 checksum and a cryptographic build attestation — Verifying your download (中文). Building Vigils into your own Rust app? SDK Quickstart.
Verifying your download
🌐 中文版:验证你的下载
Vigils sits in front of your secrets, so you shouldn’t have to take our word that a download is genuine. Every release artifact is independently verifiable. This page shows how — and is honest about what each check does and doesn’t prove.
TL;DR
# The strongest check: proves the file was built by THIS repo's CI from THIS repo's
# source. Works for every artifact — CLI archives, desktop installers, extension zip.
gh attestation verify <downloaded-file> --repo duncatzat/vigils
A ✓ with a matching source repository and workflow means the binary is authentic; nothing else is strictly required. The sections below add complementary checks and explain the current absence of OS code-signing.
1. Build provenance — recommended, covers everything
Every downloadable artifact ships with a SLSA build-provenance attestation, signed through GitHub’s Sigstore-backed infrastructure (no key for you to manage, nothing to trust besides GitHub and the public source):
- CLI archives —
vigils-cli-linux-x64.tar.gz,vigils-cli-macos-arm64.tar.gz,vigils-cli-macos-x64.tar.gz,vigils-cli-windows-x64.zip - Desktop installers —
.exe,.msi,.dmg,.deb,.rpm,.AppImage - Browser extension —
vigils-chrome-extension.zip
Verify with the GitHub CLI:
gh attestation verify Vigils_0.1.7_amd64.deb --repo duncatzat/vigils
A pass proves the file was produced by this repository’s release workflow from a specific commit — i.e. it wasn’t swapped out, rebuilt by someone else, or altered after the build. This is a stronger statement about origin than a code-signing certificate alone, because it binds the binary to the exact public source commit and CI run you can go read.
Air-gapped? Download the artifact’s attestation bundle from the release and verify offline with
gh attestation verify <file> --bundle <bundle.jsonl> --repo duncatzat/vigils.
2. Checksums — CLI archives
Each CLI archive is published next to a .sha256 file. The one-line installer
checks it for you; to verify by hand:
# macOS / Linux — the .sha256 holds "<hash> <filename>"
shasum -a 256 -c vigils-cli-linux-x64.tar.gz.sha256
# Windows — compare against the published hash in vigils-cli-windows-x64.zip.sha256
(Get-FileHash -Algorithm SHA256 vigils-cli-windows-x64.zip).Hash
A checksum only proves the bytes you got match the bytes the release published (it
catches truncation / transport corruption). It is not a signature — use provenance
(§1) for authenticity. Desktop installers rely on provenance rather than a separate
.sha256.
3. The install script
The one-liner is a plain, readable shell/PowerShell script — read it before running. Note it verifies the archive checksum for you:
curl -fsSL https://vigils.ai/install.sh # read it first
curl -fsSL https://vigils.ai/install.sh | sh # then run
irm https://vigils.ai/install.ps1 # read it first
irm https://vigils.ai/install.ps1 | iex # then run
4. About the “unsigned app” warning
Vigils installers are not yet OS-code-signed or notarized — that requires a paid, identity-verified certificate from Apple and a Windows CA, which isn’t in place yet. So on first run your OS will warn you:
- macOS — Gatekeeper blocks the app. Verify provenance (§1) first, then clear the
quarantine flag:
xattr -d com.apple.quarantine /Applications/Vigils.app. - Windows — SmartScreen warns. Verify provenance (§1) first, then More info → Run anyway.
Until code-signing lands, build provenance is the verification path — and for proving a binary really came from this open source, it’s the stronger guarantee anyway.
5. Auto-updates are signed
Once installed, the desktop app’s auto-updater only accepts updates carrying a valid
signature from the project’s minisign key (the .sig files in each release), so the
update channel is authenticated end-to-end with no action from you. See
Auto-Update.
SDK Quickstart
[dependencies]
vigil-sdk = "0.1"
Hello, redaction
Hard-fingerprint PII detection — zero model dependencies:
use vigil_sdk::prelude::*;
fn main() {
let result: RedactionResult = scan_text(
"API: ghp_0123456789abcdefghijklmnopqrstuvwxyz12"
).unwrap();
for f in &result.findings {
println!("{:?} @ {:?}", f.kind, f.span);
}
// Output: github_token @ (5, 45)
}
Firewall + approval
#![allow(unused)]
fn main() {
use vigil_sdk::prelude::*;
let firewall = Firewall::new(FirewallConfig::default());
match firewall.evaluate(&invocation, &decision) {
Ok(FirewallOutcome::Allow) => proceed(),
Ok(FirewallOutcome::ApprovalRequired(req)) => queue(req),
Err(e) => return Err(e), // FAIL CLOSED
}
}
Invariants
- Fail-closed — errors → DENY.
- No-plaintext audit.
DecisionRecordmandatory.- API stability — 0.x minor evolution allowed; v1.0 freezes the surface.
See Invariants.
Feature flags
| Feature | Default | Description |
|---|---|---|
ort | off | ONNX-Runtime PII scanner (3-engine ensemble) |
Desktop Quickstart
First launch
The window opens on the Protection Overview — the Aegis command deck: a shield hero surrounded by an eight-emblem defense ring (firewall, approval, policy, sandbox, lease, redaction, gateway, audit). On a fresh machine it honestly reports no protection yet and offers the two one-click paths:
- Deploy Guardian — wires protection into every detected agent (per-agent status shown).
- Download engine — if the
vigil-hubengine isn’t on this machine yet, fetches it securely (HTTPS + SHA-pin against the signed engine manifest + run-verify, fail-closed).
Closing the window hides Vigils to the system tray — it keeps guarding in the background. Reopen or quit from the tray menu; launching the app again focuses the existing instance instead of starting a second one.
Connect an AI agent
The fastest path is the CLI turnkey (the desktop app’s Deploy Guardian button drives the same engine):
vigil-hub setup --all
This registers native-tool hooks (Claude Code / Codex / Gemini / Cursor) and rewrites each detected agent’s stdio MCP servers through Vigils (Claude Code / Codex / Cursor / Windsurf / Kimi CLI / ZCode / pi). Full matrix: Agent Integration.
Manual MCP stdio entry (any MCP-capable agent):
{ "mcpServers": { "vigil": { "command": "vigil-hub", "args": ["serve", "--stdio"] } } }
Browser extension
Chrome MV3 extension → native host → the same local engine and ledger the desktop app shows.
Pages at a glance
| Page | What it shows |
|---|---|
| Protection Overview | Shield hero + defense ring, per-agent guardian status, browser-guard card, one-click deploy |
| Approval Queue | Risky effects awaiting a decision — approve / reject, scoped grants |
| Activity Feed | Live audit stream, SQLite FTS5 search, hash-chain verification |
| Privacy Findings | What redaction caught — classes, counts, trends (no plaintext) |
| Server Registry | Active / Pending / Removed servers, descriptor drift |
| Session Replay | The full decision timeline for a chosen session_id |
| Settings | Engine mode (hardfp / ml / auto), posture, resident daemon, ML model install, audit checkpoint anchor |
See Architecture.
Agent Integration & Test Guide
🌐 中文版:Agent 接入与测试指南
Put Vigils in front of your AI agent’s tools, so every tool call your agent makes is firewalled (default-deny), audited (tamper-evident hash chain), redacted (secrets / PII), and — when risky — sent to approval. Everything runs locally; nothing leaves your machine.
Works with any MCP-capable agent: Claude Code, Codex, Cursor, Zed, Kimi CLI, ZCode, pi, OpenCode, Continue, and more.
How it works
Vigils runs as an MCP gateway: your agent connects to vigil-hub over stdio, and vigil-hub
proxies your real MCP tool servers (“upstreams”), gating every call.
┌──────────────────┐ stdio JSON-RPC ┌────────────────────┐ ┌──────────────────┐
│ Your agent │◄──────────────────►│ vigil-hub serve │─────►│ Upstream MCP │
│ Claude Code / │ │ --stdio │ │ servers │
│ Codex / Cursor /│ │ ┌──────────────┐ │ │ (filesystem, │
│ Zed / ... │ │ │ Firewall │ │ │ github, db, ...) │
└──────────────────┘ │ │ Audit ledger │ │ └──────────────────┘
│ │ Redaction │ │
│ │ Approval │ │
│ └──────────────┘ │
└────────────────────┘
Each upstream’s tools are namespaced with a __ (double-underscore) separator — <server>__<tool>,
e.g. fs__read_file, github__create_issue — and aggregated into the tools/list your agent sees. When the agent calls one, Vigils evaluates it against the
firewall before forwarding, records a decision in the audit ledger, and either allows it,
denies it, or queues it for your approval.
Prerequisites
Install the CLI gateway, vigil-hub:
- Prebuilt: download
vigils-cli-<target>.tar.gz(.zipon Windows) from the latest release — it containsvigil-hubandvigil-native-host. Putvigil-hubon yourPATH. - From source:
cargo install --path apps/vigil-hub-cli
Verify: vigil-hub --help
Fastest path — Claude Code, one command (setup --all)
If you use Claude Code, you don’t need to hand-write configs at all. One command detects your setup and protects everything — your existing config is backed up and only Vigils’ own entries are added (fully reversible):
vigil-hub setup --all
setup --all wires up both layers:
- Native-tool input guard — a
PreToolUsehook so every tool call (Bash, Edit, Write, Read, MCP tools, …) is checked before it runs; a real credential heading into a tool is blocked fail-closed and audited. - MCP gateway — rewrites each of your stdio MCP servers to run through Vigils, so secrets in
tool results are scrubbed before the model sees them and every call is audited. Defaults to
monitor posture (your servers stay usable; raw-secret block, result redaction, and audit
stay on). Add
--enforcefor default-deny gating.
vigil-hub setup --mcp --doctor # pre-flight: will each wrapped MCP server actually start? (read-only PATH check)
vigil-hub verify # after using your agent: confirm the tamper-evident audit chain is intact (the desktop app shows what was caught)
vigil-hub setup --all --uninstall # remove everything (config restored byte-for-byte)
Restart Claude Code and you’re protected.
What setup auto-detects (2026-07):
| Agent | Hook (native-tool gate) | MCP wrap (server gateway) | Config touched |
|---|---|---|---|
| Claude Code | ✅ | ✅ (user + local scope) | ~/.claude/settings.json + ~/.claude.json |
| Codex CLI | ✅ | ✅ (honors $CODEX_HOME) | $CODEX_HOME/hooks.json + config.toml |
| Gemini CLI | ✅ | — (MCP lives inside the shared settings.json; later increment) | ~/.gemini/settings.json |
| Cursor | ✅ | ✅ | ~/.cursor/hooks.json + mcp.json |
| Windsurf | — | ✅ | ~/.codeium/windsurf/mcp_config.json |
| Kimi CLI | — (hooks are Beta and officially fail-open; deferred until GA) | ✅ | ~/.kimi/mcp.json |
| ZCode | — (plugin-only hook surface) | ✅ (close ZCode before --apply) | mcp.servers inside ~/.zcode/cli/config.json |
| pi | — (no hook mechanism) | ✅ (via the pi-mcp-adapter convention file — pi ships no built-in MCP) | $PI_AGENT_DIR/mcp.json (default ~/.pi/agent/) |
ZCode notes: the workspace-level
<project>/.zcode/config.jsonis an in-repo file (may be committed) and is deliberately left alone; the shared~/.agents/mcp.jsonfallback is not rewritten either (multi-host file, identity ownership unsettled). Users who configure MCP in ZCode’s settings panel (which always writes back to the user-level.zcodeconfig) get full protection. For pi, a missingmcp.jsonsimply means “nothing to protect” — the file is never created for you.
The rest of this guide is the manual path — use it
for non-Claude agents (Codex / Cursor / Zed / …) or when you want explicit control over the
serve gateway and its upstreams.json.
Step 1 — Smoke-test vigil-hub (30s, no agent needed)
Confirm the gateway speaks MCP before wiring any agent. Pipe an initialize + tools/list into
it (MCP stdio is newline-delimited JSON-RPC):
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| vigil-hub serve --stdio --ledger ./vigil.db
Expected stdout (two JSON-RPC responses):
{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"tools":{"listChanged":false}},"protocolVersion":"2025-06-18","serverInfo":{"name":"vigil-hub","version":"0.1.7"}}}
{"id":2,"jsonrpc":"2.0","result":{"tools":[]}}
tools/list is empty because no upstreams are configured yet (next step). Startup banners go to
stderr (stdout is reserved for the protocol).
Step 2 — Declare your tool servers (upstreams.json)
List the MCP servers you want Vigils to proxy. Bare commands resolve via PATH.
{
"upstreams": [
{ "name": "fs", "argv": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/data"] },
{ "name": "github", "argv": ["npx", "-y", "@modelcontextprotocol/server-github"] }
]
}
Pass it to serve:
vigil-hub serve --stdio --ledger ./vigil.db --upstream-config ./upstreams.json
For each entry Vigils registers the server, pins its launch command, and runs a
gate-before-spawn check (argv + resolved-program drift) before starting the child process —
then namespaces its tools (fs__…, github__…) into tools/list.
HTTP / remote MCP servers use OAuth onboarding instead:
vigil-hub add-remote-mcp --url https://mcp.example.com/ --client-id <id> --scopes mcp:tools.read
Step 3 — Point your agent at vigil-hub
Use a shared ledger path so the desktop app and CLI see the same audit trail. The desktop app
reads data_local_dir()/Vigil/ledger.sqlite3:
- Windows:
%LOCALAPPDATA%\Vigil\ledger.sqlite3 - Linux:
~/.local/share/Vigil/ledger.sqlite3 - macOS:
~/Library/Application Support/Vigil/ledger.sqlite3
The filename must be exactly ledger.sqlite3 (with the 3) and the directory must be
data_local_dir() — a path mismatch means the desktop reads a different file and the
Activity Feed stays empty. Easiest path: run vigil-hub setup --mcp / setup --all, which
auto-targets this shared ledger. Do not omit --ledger on a manual serve --stdio — that
uses an in-memory ledger the desktop can’t see. serve/wrap print the resolved ledger path
on startup, so you can compare it with the desktop’s.
In the snippets below, replace the --ledger / --upstream-config paths and the vigil-hub path
(use the absolute .exe path on Windows, e.g. C:\\Vigil\\vigil-hub.exe).
Claude Code
Project .mcp.json (or user-level ~/.claude.json → mcpServers):
{
"mcpServers": {
"vigil": {
"command": "vigil-hub",
"args": ["serve", "--stdio", "--ledger", "~/.local/share/Vigil/ledger.sqlite3", "--upstream-config", "./upstreams.json"]
}
}
}
Run /mcp in Claude Code — vigil should show connected, with your upstream tools under it.
Codex (OpenAI Codex CLI)
~/.codex/config.toml (or project .codex/config.toml):
[mcp_servers.vigil]
command = "vigil-hub"
args = ["serve", "--stdio", "--ledger", "~/.local/share/Vigil/ledger.sqlite3", "--upstream-config", "./upstreams.json"]
Cursor
~/.cursor/mcp.json (or project .cursor/mcp.json):
{ "mcpServers": { "vigil": { "command": "vigil-hub", "args": ["serve", "--stdio", "--upstream-config", "./upstreams.json"] } } }
Zed
~/.config/zed/settings.json:
{ "context_servers": { "vigil": { "command": { "path": "vigil-hub", "args": ["serve", "--stdio", "--upstream-config", "./upstreams.json"] } } } }
OpenCode
Project opencode.json:
{ "mcp": { "vigil": { "type": "local", "command": ["vigil-hub", "serve", "--stdio", "--upstream-config", "./upstreams.json"], "enabled": true } } }
Continue (VS Code / JetBrains)
~/.continue/config.yaml:
mcpServers:
- name: vigil
command: vigil-hub
args: ["serve", "--stdio", "--upstream-config", "./upstreams.json"]
Step 4 — Verify it’s actually gating
After your agent runs a tool call (or trigger one yourself), inspect the local ledger. inspect
prints single-line JSON — pipe to jq:
vigil-hub inspect --db-path ./vigil.db protection # at-a-glance: secrets blocked, leaks redacted, chain intact
vigil-hub inspect --db-path ./vigil.db activity --limit 20 # recent events / decisions
vigil-hub inspect --db-path ./vigil.db search "read_file" # full-text search the trail
vigil-hub inspect --db-path ./vigil.db approvals list # risky calls awaiting you
vigil-hub inspect --db-path ./vigil.db verify-chain # tamper-evident chain check
# → {"kind":"ChainVerification","data":{"ok":true,"broken_at_event_id":null,"message":null}}
Or open the Vigils desktop app for a live view: Activity Feed, Approval Queue (approve / deny), Server Registry, Session Replay, and Privacy Findings.
What “gating” looks like: with the default firewall (deny-by-default), a risky tool call is
either denied outright or surfaced in the Approval Queue — your agent’s call blocks until you
approve. The decision is recorded in activity.
Optional — turn on the ML privacy filter
By default Vigils uses fast hard-fingerprint rules (no ML). To add the ONNX PII scanner, build the
CLI with the ort feature and pass --enable-privacy-filter:
cargo install --path apps/vigil-hub-cli --features ort
vigil-hub serve --stdio --upstream-config ./upstreams.json --enable-privacy-filter
If the flag is set but the binary wasn’t built with --features ort, startup fails closed (it
never silently runs without the filter you asked for).
Troubleshooting
command not found/ agent can’t start vigil-hub — use the absolute path tovigil-hub(vigil-hub.exeon Windows) in the config; verify withvigil-hub --version.- Agent connects but no tools — you haven’t passed
--upstream-config, or the file lists no upstreams. Add yourupstreams.json. - An upstream fails to start — make sure its
argvruns standalone and thatnpx/node(or whatever it needs) is onPATH. - Desktop app doesn’t show events — point
--ledgerat the same path the desktop app uses (Step 3), writable by the agent’s child process. - Garbled bytes in the agent log — nothing but JSON-RPC may go to stdout;
vigil-hubkeeps all banners on stderr.
References
- Architecture · MCP Hub · Action Firewall
apps/vigil-hub-cli/src/serve.rs— theserveimplementation
Architecture Overview
Vigils is a 5-layer control plane (T0 → T4):
T4 — Desktop UI / Browser Extension / CLI
T3 — MCP Hub (server registry, descriptor pinning)
T2 — Action Firewall + Approval Queue + Policy + Audit Ledger
T1 — Privacy Filter + Sandbox Runner (Wasm + native)
T0 — Types + Schemas (vigil-types)
Crate layout
SDK boundary (publishable, 10 crates)
| Layer | Crate |
|---|---|
| T0 | vigil-types |
| T0 | vigil-redaction (hard rules + optional ORT) |
| T0 | vigil-runner-types |
| T2 | vigil-policy / vigil-audit / vigil-lease / vigil-firewall |
| T3 | vigil-ui-protocol / vigil-mcp |
| — | vigil-sdk (facade) |
Internal (not published)
vigil-runnerconcrete (wasmtime + sandbox-linux + vigil-redaction deps)vigil-sandbox-linux(Linux-only, target-gated)vigil-daemon-ipc(daemon wire protocol + thin client, shared by hook / native-host)vigil-http-auth/vigil-http-transport/vigil-browserapps/desktop/apps/native-host/apps/vigil-hub-cli
Key invariants
- Fail-closed errors → DENY
- No-plaintext audit
DecisionRecordmandatoryinherit_env=false(native) + fuel/epoch dual limit (Wasm) + Landlock (Linux)- preopen allowlist only / per-run independent engine
See the ADR Index for the design rationale behind each layer.
Data flow (typical action)
1. AI agent → MCP request → vigil-hub stdio
2. vigil-hub::descriptor_lookup → drift check
3. vigil-firewall::evaluate → policy + scope + PII
4. (if approval needed) → ApprovalBroker → Desktop UI
5. (on approve) vigil-runner::spawn_native/wasm → sandbox
6. vigil-audit::append → SQLite ledger
7. result → AI agent
Every step is fail-closed: any error → DENY plus a ledger event.
Action Firewall
vigil-firewall::Firewall::evaluate(invocation, decision) → FirewallOutcome
A fail-closed effect-gating API with three outcomes:
- Allow — policy, privacy, and scope checks all pass.
- ApprovalRequired — a risky effect is queued for a human.
- Deny — policy block, PII detected, or scope outside the allowlist.
Policy DSL
OAuth scope allowlists are enforced at the firewall layer (see ADR 0011): a request whose granted scopes fall outside the configured allowlist is denied by default.
PII scanner integration
Two layers of defense — hard fingerprint rules plus an optional ONNX ensemble. See Privacy Filter and ADR 0013.
Audit Ledger
vigil-audit — an append-only ledger protected by a SHA-256 hash chain:
event_n.hash = sha256(event_{n-1}.hash || serde_jcs(event_n) || timestamp_n)
serde_jcs (RFC 8785 canonical JSON) keeps the hash consistent across implementations.
Since the 2026-06 security audit the chain digest is versioned (v2) and additionally binds
session_id,event_type, andredacted_text, so a local actor with database write access can no longer rewrite those columns undetected. Historical v1 events stay verifiable, andverify_chainenforces version monotonicity (a v2→v1 downgrade is rejected). See the ADR Index and the security advisory.
Storage
SQLite (WAL) + FTS5. Schema: vigil-audit/migrations/.
Invariants
- Append-only (no
UPDATE/DELETE). - No-plaintext (raw secrets are never stored).
- SHA-256 chain (tamper-evident).
- FTS5 search by
event_type/session_id.
See ADR 0001 and ADR 0005.
Privacy Filter
vigil-redaction provides two layers of defense in depth.
Layer 1 — Hard fingerprints
Fixed-prefix and structured-credential rules with 100% precision, zero ML dependency, and instant startup:
| Kind | Pattern |
|---|---|
| github_token | ghp_ / gho_ / ghu_ / ghs_ / ghr_ + 36 |
| slack_webhook | hooks.slack.com/services/T... |
| stripe_secret | sk_live_ / sk_test_ |
| google_api_key | AIza + 35 |
| gitlab_pat | glpat- + 20 |
| aws_access_key | AKIA + 16 uppercase |
| database_url | <scheme>://user:password@host/db |
| private_key | PEM block |
| … | 13 kinds total |
Layer 2 — ONNX model (opt-in: the ML release build, or --features ort)
⚠️ Honest boundary: the default
vigils-cli-<plat>build runs Layer 1 (hard fingerprints) only. Layer 2 (the ML model) needs (1) an ort-enabled binary — either the prebuiltvigils-cli-ml-<plat>release build or your owncargo build --features ort, (2)vigil-hub serve --engine ml(orauto) at runtime, and (3) the model files (fetched on first use; ~0.8–1.5 GB, Hugging Face + vigils.ai mirror, SHA-256 verified). If any is missing, behavior falls back to Layer 1 — see the table below and ADR 0022. The ML release build bundles the ONNX Runtime 1.24 dylib and floors at Linux glibc ≥ 2.28 / macOS ≥ 14.
OpenAI Privacy Filter (PII NER) + a DeBERTa prompt-injection classifier (soft signal); ort
builds additionally carry a multilingual ensemble (xlmr / yonigo). Typical latency: cold
~7–11 s, warm p95 ~420 ms — inference runs synchronously in the gateway preflight, which is
exactly why --engine lets latency-sensitive deployments stay Layer-1-only.
A per-(language, label) threshold profile calibrates recall vs. false positives — for example
tightening zh.account_number cut a noisy false-positive cluster while improving F1.
Engine selection — --engine (ADR 0022)
vigil-hub serve --engine <hardfp|ml|auto>, default hardfp:
--engine | Layer 2 ML | When the model / dylib is missing |
|---|---|---|
hardfp (default) | off | — (hard fingerprints only) |
ml | on (strict) | refuses to start — if you ask for ML it must be available, no silent fallback |
auto | on (if already cached) | degrades to hard fingerprints + warns — never triggers a download |
Coexistence is structural: hard-fingerprint hits are always kept; the ML layer only adds non-overlapping findings (ADR 0013 merge) — so credentials covered by Layer 1 are never missed, ML on or off.
MCP Hub
vigil-mcp — a Model Context Protocol hub that sits in front of your tool servers.
- Server registry — stdio servers and HTTP servers (OAuth / JWT; see ADR 0011).
- Descriptor pinning — a SHA-256 of each server’s tool list + schemas, used for drift detection. A changed descriptor is treated as first-seen (approval-required), never auto-trusted.
- Outbox — an append-only outbox table for reliable delivery.
- Approval-queue integration — the embedded Hub shares cross-process SQLite persistence with the Approval Queue (see ADR 0014).
See ADR 0004, 0005, 0011, and 0014.
Approval Queue
Human-in-the-loop gating for risky effects (driven by FirewallOutcome::ApprovalRequired):
firewall::evaluate → ApprovalRequired(req)
→ ApprovalBroker (SQLite, persistent)
→ Desktop UI "Approval Queue" page
→ user: Approve / Reject / Delegate / Defer
→ ledger event
→ vigil-runner spawn (only if approved)
ApprovalScope
Each request carries a scope (see ADR 0014):
server_id+tool_nameeffect_kind(read / write / network / …)resource_pathduration(once / session / forever)
Delegate hands the decision to a super-user or batch-approval flow.
See ADR 0003 and ADR 0014.
vigil-sdk Reference
A stable public facade that re-exports the vigil-types, vigil-firewall,
vigil-redaction, and vigil-mcp surfaces.
Public surface
#![allow(unused)]
fn main() {
use vigil_sdk::prelude::*;
// vigil-types
pub use vigil_types::{DecisionRecord, AuditEvent, EffectVector,
ApprovalRequest, ApprovalResolution, ApprovalScope, ApprovalStatus,
ToolInvocation, EffectKind, DecisionKind};
// vigil-firewall
pub use vigil_firewall::{Firewall, FirewallConfig, FirewallError, FirewallOutcome,
EngineStatusReport, PiiScanner, OAuthScopeContext};
// vigil-redaction
pub use vigil_redaction::{scan_text, RedactionResult, Finding, FindingKind, FindingSource};
// vigil-mcp
pub use vigil_mcp::descriptor_hash;
}
Out of scope (not exported)
- Server runtime (Hub / oracle internals).
- Backend implementations (
NoopEngine/MockEngine/OrtEngine). - Ops infrastructure (bootstrap / model distribution).
- The concrete
vigil-runner(WasmRunner/spawn_native).
See Invariants and docs.rs/vigil-sdk.
SDK Invariants
The SDK boundary is defined by ADR 0015. Consumers can rely on these guarantees.
1. Fail-closed
#![allow(unused)]
fn main() {
match firewall.evaluate(..) {
Ok(FirewallOutcome::Allow) => proceed(),
Ok(_) => other_handling(),
Err(e) => return Err(e), // NEVER default to allow
}
}
2. No-plaintext audit
Raw text passed to the SDK is never persisted. Audit records go through DecisionRecord /
AuditEvent (a hash plus a redacted body).
3. DecisionRecord mandatory
Every effect must first produce a DecisionRecord. No SDK API lets a consumer skip it.
4. API stability
- 0.x: additive improvements are allowed (each behind review + an ADR).
- After v1.0: additive only — no removals, no signature changes.
- Adding a variant/field to a
#[non_exhaustive]enum/struct is not a breaking change.
5. Reviewed surface changes
Every change to the SDK’s public surface is reviewed before release.
SDK Feature Flags
ort (default: off)
vigil-sdk = { version = "0.1", features = ["ort"] }
Enabled:
- The
ortcrate + ONNX Runtime 1.24.4 (dynamic library). - A 3-engine ensemble (OpenAI Privacy Filter +
xlmr-pii-v1+yonigo-pii-v1). - An 8-class
PrivacyLabel.
Disabled (default):
- 13 hard fingerprint rules.
- A
NoopEngineplaceholder. - No ONNX dependency; sub-second startup.
Choosing
| Scenario | Feature |
|---|---|
| CLI tool wrapper | default — hard rules cover the vast majority of leaks, instant |
| Long-running agent | ort — higher recall (~11 s cold + ~419 ms warm) |
| Browser extension | default — size- and cold-start-sensitive |
Runtime environment (with ort)
export ORT_DYLIB_PATH=/path/to/onnxruntime-<platform>-1.24.4/lib/libonnxruntime.so.1.24.4
export VIGIL_PRIVACY_FILTER_MODEL_DIR=/path/to/models/openai-pf/v1
See ADR 0012, 0016, and 0017.
Auto-Update
Installed desktop apps update over the Tauri auto-updater, using Ed25519 (minisign) signatures.
Flow
client startup
→ Tauri updater plugin polls
https://vigils.ai/desktop-updates/<target>-<arch>/<current_version>.json
→ server returns { version, url, signature, ... }
→ client compares server.version > local.version
→ downloads the bundle and verifies its .sig against the embedded public key
→ restarts on the new version
The update endpoint and signing key are operated by the project; release bundles are signed
in CI. macOS is served as two independent lines — darwin-aarch64 (Apple Silicon) and
darwin-x86_64 (Intel) — each with its own manifest and arch-suffixed updater archive, so an
update can never deliver the wrong architecture.
Building a signed bundle
export TAURI_SIGNING_PRIVATE_KEY="$(cat <your-updater-key>)"
cargo tauri build --features gui --config '{"bundle":{"createUpdaterArtifacts":true}}'
# produces the platform bundle plus a matching .sig
For the full pipeline (CI signing → manifest generation → endpoint sync), see
docs/ota-pipeline.md.
Multi-Platform Build
Three platforms, four architectures (Windows x64 · Linux x64 · macOS Apple Silicon · macOS Intel).
Linux
sudo apt install libwebkit2gtk-4.1-dev libsoup-3.0-dev libgtk-3-dev
cd apps/desktop
cargo tauri build --features gui --bundles deb,rpm,appimage
macOS
export CI=true # skips the AppleScript Finder styling that needs a GUI session
cd apps/desktop
cargo tauri build --features gui --bundles app,dmg
# app target = updater artifact (.app.tar.gz + .sig)
# dmg target = user-facing installer
# Intel (x86_64) — cross-compile from the arm64 runner; the Apple SDK is dual-arch:
rustup target add x86_64-apple-darwin
cargo tauri build --features gui --target x86_64-apple-darwin --bundles app,dmg
# bundles land under target/x86_64-apple-darwin/release/bundle
In CI the two mac updater archives are renamed per-arch (Vigils-darwin-<arch>.app.tar.gz)
so they can coexist as release assets; each latest-darwin-<arch>.json points at its own.
Windows
cd apps/desktop
cargo tauri build --features gui --bundles msi,nsis
Binary layout
apps/desktop/Cargo.toml declares a single binary —
[[bin]] name = "vigils" path = "src/bin/vigils.rs" — aligned with the Tauri v2 bundle
default (the bin name matches the path basename and mainBinaryName). The installed
executable is vigils / vigils.exe (since v0.1.5; earlier builds shipped gui).
Architecture Decision Records
Every significant design decision is recorded as an ADR under
docs/adr/. Each ADR and its
implementation were reviewed before merge.
| # | Title |
|---|---|
| 0001 | Action control plane |
| 0002 | Audit ledger + hash chain (revised: v2) |
| 0003 | Firewall + approval queue |
| 0004 | MCP hub + outbox |
| 0005 | Descriptor pinning + drift |
| 0006 | Secret lease broker |
| 0007 | Sandbox runner (Wasm + native + Landlock) |
| 0008 | Desktop UI protocol |
| 0009 | Browser extension + native host |
| 0010 | HTTP MCP auth |
| 0011 | HTTP transport + JWKS |
| 0012 | Model distribution |
| 0013 | Hard × model merge |
| 0014 | Tauri-embedded Hub |
| 0015 | SDK boundary |
| 0016 | Performance gate |
| 0017 | Model descriptor design |
| 0018 | vigil-runner-types split |
| 0019 | Audit advisories policy |
Changelog & Releases
Vigils ships from a single public version line (0.1.x).
- Binaries & signed installers — the GitHub Releases page.
- Full changelog —
CHANGELOG.md(简体中文).
Recent highlights
| Version | Theme |
|---|---|
| v0.1.7 | Security hardening — ports the first comprehensive audit’s fixes (hash-chain v2, descriptor-hash guard, …) |
| v0.1.6 | In-app branding consistency |
| v0.1.5 | Desktop binary renamed gui → vigils |
The v0.1.7 audit summary is published as a security advisory.
安装 Vigils
English: Install Vigils
1. 我该下载哪个?
| 我想… | 下载 | 跳转 |
|---|---|---|
| 用这个 App —— 看活动、批准操作(图形界面) | 对应系统的桌面安装包 | §2 |
| 守护我的 AI 编码助手 —— Claude Code / Codex / Cursor / Zed | CLI(vigils-cli-…) | §3 |
| 守护往 AI 网站粘贴 —— ChatGPT / Claude / Gemini | 浏览器扩展 | §4 |
大多数人要的是桌面 App;给 agent 接网关的开发者要的是 CLI。
所有文件都在 Releases 页
(把下文的 <version> 换成你下载的版本,例如 0.3.0)。
2. 桌面 App
选你的系统,下载,运行。首次启动会有一次性的“未知开发者“提示(我们暂未做 OS 代码签名)——放行步骤见下。
Windows
- 下载
Vigils_<version>_x64-setup.exe→ 双击。 - 若弹出蓝色 “Windows 已保护你的电脑” → 更多信息 → 仍要运行。
- 完成。(随着安装量增加,该警告会自行消退。)
macOS
- 按芯片下载 dmg —— Apple Silicon:
Vigils_<version>_aarch64.dmg;Intel:Vigils_<version>_x64.dmg(不确定?苹果菜单 → 关于本机 —— 显示“Apple M…“即 Apple Silicon)→ 打开 → 把 Vigils 拖进 应用程序。 - 首次启动会被拦(“Apple 无法验证…”)。一次性放行: ** 系统设置 → 隐私与安全性 → 下拉到底 → 点“仍要打开“ → 用 Touch ID / 密码确认。**
- 完成 —— 之后不再询问。
终端替代方案(进阶用户):
xattr -dr com.apple.quarantine /Applications/Vigils.app这是任何“尚未公证“App 的标准一次性步骤;签名已在计划中。
Linux(Ubuntu 22.04+ / Debian 12+)
sudo dpkg -i Vigils_<version>_amd64.deb # Debian / Ubuntu
sudo rpm -i Vigils-<version>-1.x86_64.rpm # Fedora / RHEL
chmod +x Vigils_<version>_amd64.AppImage && ./Vigils_<version>_amd64.AppImage # 便携版,任意发行版
发行版较老(桌面 GUI 需要 glibc ≥ 2.35)?改用 CLI —— 它几乎能在任何 Linux 上跑(glibc ≥ 2.17)。
3. CLI —— 守护你的编码助手(30 秒)
一行装好:
curl -fsSL https://vigils.ai/install.sh | sh # macOS / Linux
irm https://vigils.ai/install.ps1 | iex # Windows(PowerShell)
(或从 Releases 下载 vigils-cli-<os> 解压 —— 里面有 vigil-hub。)
然后开启防护:
vigil-hub setup # 自动探测 Claude Code / Codex / Cursor 并接好守护
重启你的 agent —— 就这样。明文密钥从此被挡在它的工具调用之外,每次拦截都记进防篡改的本地账本。
想先试试就跑 vigil-hub demo(零设置)。各 agent 细节见 Agent 集成。
ML 变体(可选,语义 PII + 提示注入检测):改下载
vigils-cli-ml-<os>,跑vigil-hub serve --engine ml。 底线:Linux glibc ≥ 2.28、macOS ≥ 14(仅 Apple Silicon —— 上游 onnxruntime 已停发 x86_64 macOS 构建,Intel mac 使用默认硬指纹引擎)。见 隐私过滤器。
4. 浏览器扩展(Chrome)
在 AI 网站上粘贴/提交前先脱敏密钥与 PII。从 Chrome 应用商店一键安装
Vigils Browser Guard ——
普通模式开箱即用,无需桌面 App。可选深度脱敏:安装 Vigils CLI,用扩展 ID 注册 native host
(vigil-native-host install --extension-id <ID>,ID 在扩展「选项 → 高级设置」里可复制),
再到选项页企业模式下选择「本机 Vigils 引擎」——检查将路由到本机引擎(硬指纹 + daemon
运行时的 ML PII 识别),原文不出设备。
开发版:chrome://extensions → 开 开发者模式 → 加载已解压的扩展程序 → 选 extensions/chrome-mv3/。
担心来源真伪? 每个下载都带 SHA-256 校验和 + 密码学构建证明 —— 见 验证你的下载。 想把 Vigils 嵌进自己的 Rust 应用?见 SDK 快速上手。
验证你的下载
🌐 English: Verifying your download
Vigils 守在你的密钥前面,所以你不该仅凭我们一句话就相信某个下载是正版。每一个发布产物 都是可独立验证的。本页说明怎么验证——并诚实交代每种方法能证明什么、不能证明什么。
速览
# 最强校验:证明该文件由「本仓库」的 CI 从「本仓库」的源码构建。
# 适用于全部产物——CLI 压缩包、桌面安装包、扩展 zip。
gh attestation verify <下载的文件> --repo duncatzat/vigils
输出 ✓ 且源仓库 / workflow 匹配,即说明二进制是正版;严格来说无需更多步骤。下面各节是 互补校验,并解释当前为何还没有操作系统级代码签名。
1. 构建溯源(Build provenance)——推荐,覆盖全部产物
每个可下载产物都附带一份 SLSA 构建溯源证明,由 GitHub 背后的 Sigstore 基础设施签发(你无需自管密钥,除 GitHub 与公开源码外无需信任其他方):
- CLI 压缩包——
vigils-cli-linux-x64.tar.gz、vigils-cli-macos-arm64.tar.gz、vigils-cli-macos-x64.tar.gz、vigils-cli-windows-x64.zip - 桌面安装包——
.exe、.msi、.dmg、.deb、.rpm、.AppImage - 浏览器扩展——
vigils-chrome-extension.zip
用 GitHub CLI 验证:
gh attestation verify Vigils_0.1.7_amd64.deb --repo duncatzat/vigils
通过即证明该文件由「本仓库」的发布流水线、从某个具体 commit 构建——也就是说它没有被 掉包、没有被第三方重新构建、构建后也没有被篡改。这对「来源」的证明强于单纯的代码签名 证书,因为它把二进制绑定到了你可以亲自去读的那个公开源码 commit 和 CI 运行。
离线 / 隔离网环境?从 release 下载该产物的 attestation bundle,离线验证:
gh attestation verify <文件> --bundle <bundle.jsonl> --repo duncatzat/vigils。
2. 校验和(Checksum)——CLI 压缩包
每个 CLI 压缩包旁边都发布了 .sha256 文件。一行安装器会自动校验;
手动验证:
# macOS / Linux —— .sha256 内容格式为 "<hash> <文件名>"
shasum -a 256 -c vigils-cli-linux-x64.tar.gz.sha256
# Windows —— 与 vigils-cli-windows-x64.zip.sha256 中发布的 hash 比对
(Get-FileHash -Algorithm SHA256 vigils-cli-windows-x64.zip).Hash
校验和只能证明你下到的字节和 release 发布的字节一致(用于发现截断 / 传输损坏),它
不是签名——认证真伪请用溯源(§1)。桌面安装包依赖溯源,不另发 .sha256。
3. 安装脚本
一行安装命令是一个朴素、可读的 shell / PowerShell 脚本——运行前先读它。注意它会替你 校验压缩包的校验和:
curl -fsSL https://vigils.ai/install.sh # 先读
curl -fsSL https://vigils.ai/install.sh | sh # 再运行
irm https://vigils.ai/install.ps1 # 先读
irm https://vigils.ai/install.ps1 | iex # 再运行
4. 关于「未签名应用」警告
Vigils 安装包尚未做操作系统级代码签名 / 公证——那需要 Apple 与 Windows CA 颁发的、 付费且经身份核验的证书,目前还没有到位。因此首次运行时系统会警告:
- macOS——Gatekeeper 会拦截。先验证溯源(§1),再清除隔离标记:
xattr -d com.apple.quarantine /Applications/Vigils.app。 - Windows——SmartScreen 会提示。先验证溯源(§1),再点 More info → Run anyway。
在代码签名落地之前,构建溯源就是验证路径——而对「证明二进制确实来自这份开源代码」 而言,它本就是更强的保证。
5. 自动更新是签名的
安装后,桌面应用的自动更新器只接受携带项目 minisign 密钥有效签名的更新(每个 release
里的 .sig 文件),因此更新通道无需你任何操作即端到端可信。见
自动更新。
Agent 接入与测试指南
🌐 English: Agent Integration & Test Guide
把 Vigils 插在你的 AI agent 与它调用的工具之间,让 agent 的每一次工具调用都经过 防火墙(默认拒绝)、审计(防篡改哈希链)、脱敏(密钥 / PII),高危调用还会进入 人工审批。全部本地运行,数据不外传。
支持任何兼容 MCP 的 agent:Claude Code、Codex、Cursor、Zed、Kimi CLI、 ZCode、pi、OpenCode、Continue 等。
工作原理
Vigils 作为 MCP 网关运行:你的 agent 通过 stdio 连接 vigil-hub,由 vigil-hub 代理你真正的
MCP 工具服务器(“upstream”),对每次调用进行管控。
┌──────────────────┐ stdio JSON-RPC ┌────────────────────┐ ┌──────────────────┐
│ 你的 agent │◄──────────────────►│ vigil-hub serve │─────►│ 上游 MCP server │
│ Claude Code / │ │ --stdio │ │ (filesystem、 │
│ Codex / Cursor /│ │ ┌──────────────┐ │ │ github、db…) │
│ Zed / ... │ │ │ 防火墙 │ │ └──────────────────┘
└──────────────────┘ │ │ 审计账本 │ │
│ │ 脱敏 │ │
│ │ 审批 │ │
│ └──────────────┘ │
└────────────────────┘
每个 upstream 的工具会用 __(双下划线)分隔符做命名空间化 —— <server>__<tool>,例如
fs__read_file、github__create_issue —— 聚合进 agent 看到的 tools/list。agent 调用某个工具时,Vigils 会在转发之前用防火墙评估它、在审计账本记一条决策,
然后放行、拒绝、或排进审批队列等你确认。
前置条件
安装 CLI 网关 vigil-hub:
- 预编译:从最新 release 下载
vigils-cli-<target>.tar.gz(Windows 为.zip),内含vigil-hub与vigil-native-host。把vigil-hub放进PATH。 - 从源码:
cargo install --path apps/vigil-hub-cli
验证:vigil-hub --help
最快路径 —— Claude Code,一条命令(setup --all)
如果你用 Claude Code,完全不必手写配置。一条命令检测你的环境并全面保护 —— 既有配置会被备份,只新增 Vigils 自己的条目(完全可逆):
vigil-hub setup --all
setup --all 同时接入两层:
- 原生工具输入侧守门 ——
PreToolUsehook,于是每次工具调用(Bash、Edit、Write、Read、MCP 工具……)执行前都先被检查:真实凭据流入工具会被 fail-closed 拦截并审计。 - MCP 网关 —— 把你每个 stdio MCP server 改写为经 Vigils 路由,工具结果里的 secret 在模型看到
之前被脱敏,每次调用都被审计。默认 monitor 姿态(你的 server 保持可用;裸 secret 拦截、结果脱敏、
审计照常)。加
--enforce升级 default-deny 硬拦。
vigil-hub setup --mcp --doctor # 接入前预检:每个被包裹的 MCP server 真能启动吗?(只读 PATH 检查)
vigil-hub verify # 用过 agent 后:确认防篡改审计链完整(桌面应用可看拦了什么)
vigil-hub setup --all --uninstall # 移除全部(配置逐字节还原)
重启 Claude Code 即受保护。
setup 自动探测覆盖面(2026-07):
| Agent | Hook(原生工具守门) | MCP wrap(server 网关) | 涉及配置 |
|---|---|---|---|
| Claude Code | ✅ | ✅(user + local scope) | ~/.claude/settings.json + ~/.claude.json |
| Codex CLI | ✅ | ✅(尊重 $CODEX_HOME) | $CODEX_HOME/hooks.json + config.toml |
| Gemini CLI | ✅ | —(MCP 嵌在共享 settings.json,留后续增量) | ~/.gemini/settings.json |
| Cursor | ✅ | ✅ | ~/.cursor/hooks.json + mcp.json |
| Windsurf | — | ✅ | ~/.codeium/windsurf/mcp_config.json |
| Kimi CLI | —(hooks 为 Beta 且官方 fail-open,等 GA 再评) | ✅ | ~/.kimi/mcp.json |
| ZCode | —(仅 plugin 形态 hook) | ✅(--apply 前请先关闭 ZCode) | ~/.zcode/cli/config.json 的 mcp.servers |
| pi | —(无 hook 机制) | ✅(经 pi-mcp-adapter 约定文件 —— pi 本体无内置 MCP) | $PI_AGENT_DIR/mcp.json(默认 ~/.pi/agent/) |
ZCode 说明:工作区级
<项目>/.zcode/config.json是项目内文件(可能被提交),刻意不碰;共享~/.agents/mcp.jsonfallback 亦不改写(多宿主文件,身份归属未定)。用 ZCode 设置面板配置 MCP(默认写回用户级.zcode配置)的用户获得完整保护。pi 的mcp.json不存在即“无可保护 项“——绝不会替你创建。
本指南余下部分是手动路径 —— 用于非 Claude agent(Codex / Cursor /
Zed / …)或你想显式控制 serve 网关及其 upstreams.json 时。
第 1 步 —— 冒烟测试 vigil-hub(30 秒,不用 agent)
接任何 agent 之前,先确认网关能说 MCP。给它喂一个 initialize + tools/list(MCP stdio 是逐行
JSON-RPC):
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| vigil-hub serve --stdio --ledger ./vigil.db
预期 stdout(两条 JSON-RPC 响应):
{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"tools":{"listChanged":false}},"protocolVersion":"2025-06-18","serverInfo":{"name":"vigil-hub","version":"0.1.7"}}}
{"id":2,"jsonrpc":"2.0","result":{"tools":[]}}
tools/list 为空是因为还没配 upstream(下一步配)。启动提示走 stderr(stdout 留给协议)。
第 2 步 —— 声明你的工具服务器(upstreams.json)
列出你要 Vigils 代理的 MCP server。裸命令会自动经 PATH 解析。
{
"upstreams": [
{ "name": "fs", "argv": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/data"] },
{ "name": "github", "argv": ["npx", "-y", "@modelcontextprotocol/server-github"] }
]
}
传给 serve:
vigil-hub serve --stdio --ledger ./vigil.db --upstream-config ./upstreams.json
对每个条目,Vigils 会注册该 server、固定其启动命令,并在启动子进程之前做一次
gate-before-spawn 校验(argv + resolved-program 双 drift),然后把它的工具命名空间化
(fs__…、github__…)聚合进 tools/list。
HTTP / 远程 MCP server 改走 OAuth onboarding:
vigil-hub add-remote-mcp --url https://mcp.example.com/ --client-id <id> --scopes mcp:tools.read
第 3 步 —— 把 agent 指向 vigil-hub
用同一个 ledger 路径,让桌面应用和 CLI 看到同一份审计。桌面应用读
data_local_dir()/Vigil/ledger.sqlite3:
- Windows:
%LOCALAPPDATA%\Vigil\ledger.sqlite3 - Linux:
~/.local/share/Vigil/ledger.sqlite3 - macOS:
~/Library/Application Support/Vigil/ledger.sqlite3
文件名必须恰好是 ledger.sqlite3(带 3)、目录是 data_local_dir() —— 路径不一致桌面就读到
另一个文件,Activity Feed 一直空。最省心:跑 vigil-hub setup --mcp / setup --all,自动指向这个
共享账本。手动 serve --stdio 切勿省略 --ledger —— 省略 = 内存账本,桌面看不到。serve/wrap
启动时会打印解析后的账本路径,可与桌面读的路径比对。
下面的片段里,替换 --ledger / --upstream-config 路径和 vigil-hub 路径(Windows 用绝对
.exe 路径,如 C:\\Vigil\\vigil-hub.exe)。
Claude Code
项目根 .mcp.json(或用户级 ~/.claude.json 的 mcpServers):
{
"mcpServers": {
"vigil": {
"command": "vigil-hub",
"args": ["serve", "--stdio", "--ledger", "~/.local/share/Vigil/ledger.sqlite3", "--upstream-config", "./upstreams.json"]
}
}
}
在 Claude Code 里运行 /mcp —— vigil 应显示已连接,其下挂着你的 upstream 工具。
Codex(OpenAI Codex CLI)
~/.codex/config.toml(或项目级 .codex/config.toml):
[mcp_servers.vigil]
command = "vigil-hub"
args = ["serve", "--stdio", "--ledger", "~/.local/share/Vigil/ledger.sqlite3", "--upstream-config", "./upstreams.json"]
Cursor
~/.cursor/mcp.json(或项目级 .cursor/mcp.json):
{ "mcpServers": { "vigil": { "command": "vigil-hub", "args": ["serve", "--stdio", "--upstream-config", "./upstreams.json"] } } }
Zed
~/.config/zed/settings.json:
{ "context_servers": { "vigil": { "command": { "path": "vigil-hub", "args": ["serve", "--stdio", "--upstream-config", "./upstreams.json"] } } } }
OpenCode
项目根 opencode.json:
{ "mcp": { "vigil": { "type": "local", "command": ["vigil-hub", "serve", "--stdio", "--upstream-config", "./upstreams.json"], "enabled": true } } }
Continue(VS Code / JetBrains)
~/.continue/config.yaml:
mcpServers:
- name: vigil
command: vigil-hub
args: ["serve", "--stdio", "--upstream-config", "./upstreams.json"]
第 4 步 —— 验证它真的在管控
等 agent 跑一次工具调用(或你自己触发一次)后,查本地账本。inspect 输出单行 JSON,可接 jq:
vigil-hub inspect --db-path ./vigil.db protection # 一眼看清:裸 secret 拦截、泄漏脱敏、链完整
vigil-hub inspect --db-path ./vigil.db activity --limit 20 # 最近事件 / 决策
vigil-hub inspect --db-path ./vigil.db search "read_file" # 全文搜索审计链
vigil-hub inspect --db-path ./vigil.db approvals list # 待你处理的高危调用
vigil-hub inspect --db-path ./vigil.db verify-chain # 防篡改链校验
# → {"kind":"ChainVerification","data":{"ok":true,"broken_at_event_id":null,"message":null}}
或打开 Vigils 桌面应用实时看:Activity Feed、Approval Queue(批准 / 拒绝)、 Server Registry、Session Replay、Privacy Findings。
“管控“长什么样:默认防火墙是 deny-by-default,一次高危工具调用要么被直接拒绝,要么进 Approval
Queue —— 在你批准之前,agent 的这次调用一直阻塞。决策会记进 activity。
可选 —— 开启 ML 隐私过滤
Vigils 默认用快速硬指纹规则(无 ML)。要加 ONNX PII 扫描器,用 ort feature 编译 CLI 并传
--enable-privacy-filter:
cargo install --path apps/vigil-hub-cli --features ort
vigil-hub serve --stdio --upstream-config ./upstreams.json --enable-privacy-filter
如果传了 flag 但二进制没用 --features ort 编译,启动会 fail-closed(绝不静默地在你以为开了过滤
的情况下不开就跑)。
故障排查
command not found/ agent 起不了 vigil-hub —— 配置里用vigil-hub的绝对路径(Windows 为vigil-hub.exe);vigil-hub --version验证可执行。- 连上了但没工具 —— 你没传
--upstream-config,或文件里没列 upstream。补上upstreams.json。 - 某个 upstream 起不来 —— 确认它的
argv能独立跑,且npx/node(或它需要的东西)在PATH。 - 桌面应用不显示事件 —— 把
--ledger指向桌面应用用的同一路径(第 3 步),且 agent 子进程可写。 - agent 日志里有乱字节 —— stdout 只能有 JSON-RPC;
vigil-hub所有 banner 都走 stderr。
参考
- 架构 · MCP Hub · Action Firewall
apps/vigil-hub-cli/src/serve.rs——serve实现