Local Setup Guide
vanzik v2.0updated view on github
Get Vanzik running on your machine in under 5 minutes.
Prerequisites#
| Tool | Version | Check |
|---|---|---|
Go (only to build from source or go install) |
1.26+ | go version |
| Git (only to build from source) | any | git --version |
| Python (optional, for the SDK) | 3.10+ | python --version |
| Node.js (optional, for the TS SDK) | 20+ | node --version |
| Docker (optional) | any | docker --version |
What you're setting up#
Vanzik is the wire-level checkpoint that sits between your agent and everything it touches. It runs as one or more of three enforcement layers, plus the Vanzik server that owns policy + audit + approvals.
| Layer | Binary | Use for | Code change |
|---|---|---|---|
| MCP traffic | vanzik-mcp-gateway |
Claude Desktop, Cursor, Cline, Continue, Zed | None |
| LLM API calls | vanzik-llm-proxy |
OpenAI / Anthropic SDK code | One env var |
| Direct calls | Python / TypeScript SDK + adapters | Custom code, framework integrations | Per-call guard.check(...) |
Layer-specific quickstarts: QUICKSTART_MCP.md · QUICKSTART_LLM_PROXY.md. The rest of this guide covers building the binaries, running the server, and using the SDK.
Quick Start#
1. Install#
The installers download the prebuilt binaries for your OS and CPU, check them against the release's checksums.txt, install all three binaries, and write a starter policy if you don't have one yet. Running the same command again updates to the latest release.
Upgrading from AgentGuard 1.x (this project's name before 2.0)? The same commands move your AgentGuard setup over (its folders, database, login service and coding-agent hooks) with vanzik migrate --from-agentguard; see MIGRATION.md.
# Linux / macOS — binaries in ~/.local/bin (or /usr/local/bin as root),
# starter policy in ~/.config/vanzik/default.yaml (or /etc/vanzik/ as root)
curl -fsSL https://github.com/lictorate/vanzik/releases/latest/download/install.sh | sh
# Windows — binaries in %LOCALAPPDATA%\Programs\Vanzik\bin (added to your user PATH),
# starter policy in %APPDATA%\vanzik\default.yaml
irm https://github.com/lictorate/vanzik/releases/latest/download/install.ps1 | iex
| Variable | Effect |
|---|---|
VANZIK_VERSION |
Install this version (e.g. 2.0.0) instead of the latest. Only 2.x versions can be installed: 1.x releases were AgentGuard, with agentguard_* archives |
VANZIK_INSTALL_DIR |
Install the binaries here |
VANZIK_DOWNLOAD_URL |
Download the release files from this base URL (a mirror, or an internal server for air-gapped hosts) |
VANZIK_NO_MODIFY_PATH=1 |
Windows only: leave the user PATH unchanged |
The installers never overwrite an existing starter policy. To check provenance as well as checksums, download an archive from the releases page and run gh attestation verify <archive> --repo lictorate/vanzik.
Next, run vanzik setup. From a menu, it starts Vanzik at login (no admin rights), protects it with an API key only you can read, and shows how to connect the SDKs and Claude Desktop; the same menu updates and uninstalls later (CLI.md).
If you'd rather run the server yourself, the commands below work without the leading ./, and you can leave out --policy configs/default.yaml: server, validate and check find the installer's starter policy on their own (CLI.md).
Update#
Run vanzik setup and choose Update: it downloads the new release, checks it against checksums.txt, swaps the binaries and restarts the server. Or run the same install command again. It replaces the three binaries, keeps your policy, and says what changed: Updated Vanzik <current> -> <latest>, Reinstalled Vanzik <version> (it was already on this version), or — when VANZIK_VERSION pins an older release — Downgraded Vanzik <current> -> <older> followed by a warning. The vanzik CLI prints a one-line notice with the right command when a newer release is out (server never checks; see CLI.md).
Uninstall#
Run vanzik setup and choose Uninstall…: it also removes the login service, works offline, and asks whether to keep your policy, key and data. Or use the installer:
# Linux / macOS (add --purge to delete the policy folder too)
curl -fsSL https://github.com/lictorate/vanzik/releases/latest/download/install.sh | sh -s -- --uninstall
# Windows (also set $env:VANZIK_PURGE=1 to delete the policy folder too)
$env:VANZIK_UNINSTALL=1; irm https://github.com/lictorate/vanzik/releases/latest/download/install.ps1 | iex
The uninstall removes the three binaries — on Windows also the folder's entry on your user PATH — and keeps your policy folder, printing where it is. Audit logs and the state database live wherever you ran vanzik server, so it cannot know their path and leaves them alone. Run it as the same user that installed (with sudo for a root install in /usr/local/bin); with VANZIK_INSTALL_DIR set, it removes from that folder. On Windows, stop any running Vanzik first: the uninstall refuses rather than removing half of it. VANZIK_UNINSTALL=1 works on Linux and macOS too; on Windows the variable is cleared once read, so a later install in the same window installs.
For the container image, stop and remove the container; docker volume rm vanzik-audit (or whatever volume you mounted at /var/lib/vanzik) deletes the audit trail.
Or build from source#
git clone https://github.com/lictorate/vanzik.git
cd vanzik
# Central server (always needed)
go build -o vanzik ./cmd/vanzik
# MCP Gateway (only if you're integrating MCP clients)
go build -o vanzik-mcp-gateway ./cmd/vanzik-mcp-gateway
# LLM API Proxy (only if you're proxying OpenAI / Anthropic SDK traffic)
go build -o vanzik-llm-proxy ./cmd/vanzik-llm-proxy
On Windows append .exe to each -o target. Or install everything from a remote tag:
go install lictorate.com/vanzik/v2/cmd/vanzik@latest
go install lictorate.com/vanzik/v2/cmd/vanzik-mcp-gateway@latest
go install lictorate.com/vanzik/v2/cmd/vanzik-llm-proxy@latest
2. Validate the Default Policy#
./vanzik validate --policy configs/default.yaml
# Output: VALID: default-sandbox — 61 rules across 5 scopes (numbers vary as the default ships more rules)
3. Start the Server#
# Basic
./vanzik server --policy configs/default.yaml
# With the dashboard, logging each policy reload (reloading is always on)
./vanzik server --policy configs/default.yaml --dashboard --watch
# Custom port
./vanzik server --policy configs/default.yaml --port 9090 --dashboard
4. Verify It's Running#
curl http://localhost:8080/health
# {"status":"ok","version":"2.0.0"}
Open http://localhost:8080/dashboard in your browser to see the live dashboard.
5. Test a Policy Check#
# This should be ALLOWED (ls is in the allow list)
curl -X POST http://localhost:8080/v1/check \
-H "Content-Type: application/json" \
-d '{"scope": "shell", "command": "ls -la", "agent_id": "test"}'
# This should be DENIED (fork bomb)
curl -X POST http://localhost:8080/v1/check \
-H "Content-Type: application/json" \
-d '{"scope": "shell", "command": ":(){ :|:& };:", "agent_id": "test"}'
# This should REQUIRE_APPROVAL (sudo)
curl -X POST http://localhost:8080/v1/check \
-H "Content-Type: application/json" \
-d '{"scope": "shell", "command": "sudo apt install vim", "agent_id": "test"}'
# Filesystem scope — DENIED by the system-directories write deny ("Writing to system directories is blocked")
curl -X POST http://localhost:8080/v1/check \
-H "Content-Type: application/json" \
-d '{"scope": "filesystem", "action": "write", "path": "/etc/passwd", "agent_id": "test"}'
# Network scope — ALLOWED (api.openai.com is whitelisted)
curl -X POST http://localhost:8080/v1/check \
-H "Content-Type: application/json" \
-d '{"scope": "network", "domain": "api.openai.com", "agent_id": "test"}'
Authentication#
By default (--api-key not set) the server binds to 127.0.0.1 only — safe
for local dev, but approve/deny/audit/status are unauthenticated. For
anything beyond local dev, set an API key:
./vanzik server \
--policy configs/default.yaml \
--api-key YOUR_SECRET \
--dashboard
# Or via environment (server + CLI both read this):
export VANZIK_API_KEY=YOUR_SECRET
./vanzik server --policy configs/default.yaml --dashboard
Which endpoints the key gates (and which stay open), the dashboard
login/CSRF flow, Bearer-vs-session curl recipes, and CORS
(--allowed-origin) are documented once in
DEPLOYMENT.md with the endpoint table in
API.md.
Using the Python SDK#
Install#
# From PyPI
pip install vanzik
# With framework adapters
pip install vanzik[langchain]
pip install vanzik[crewai]
pip install vanzik[browser-use]
pip install vanzik[all]
# Or from source (editable / development)
cd plugins/python
pip install -e ".[dev]"
Basic Usage#
from vanzik import Guard
# base_url / api_key fall back to VANZIK_URL / VANZIK_API_KEY.
guard = Guard("http://localhost:8080", agent_id="my-agent", api_key="YOUR_SECRET")
result = guard.check("shell", command="ls -la")
if result.allowed:
run_it()
That's the whole core loop. The rest of the SDK surface — the approval
flow (wait_for_approval), programmatic approve/deny, cost guardrails,
the @guarded decorator, failure modes, and testing recipes — is
documented once in SDK_PYTHON.md. The framework
adapters (LangChain, CrewAI, browser-use, MCP) with their scope-inference
rules and per-framework gotchas live in ADAPTERS.md.
Using the TypeScript SDK#
Install#
# From npm
npm install @lictorate/vanzik
# Or from source: build the package, then install it into your project
cd plugins/typescript
npm ci
npm run build
cd /path/to/your-project && npm install /path/to/vanzik/plugins/typescript
Usage#
import { Vanzik } from '@lictorate/vanzik';
const guard = new Vanzik({
baseUrl: 'http://localhost:8080',
agentId: 'my-bot',
apiKey: process.env.VANZIK_API_KEY,
// failMode: 'deny' (default) — server unreachable ⇒ check() returns DENY.
});
const result = await guard.check('shell', { command: 'ls -la' });
if (result.allowed) { /* proceed */ }
The TypeScript surface mirrors the Python one — waitForApproval,
approve/deny, cost checks, and the guarded higher-order wrapper.
See the package README in
plugins/typescript/ for the full API.
Using the CLI#
# Start the server
vanzik server --policy configs/default.yaml --dashboard --watch
# With authentication (also reads VANZIK_API_KEY from the environment)
vanzik server --policy configs/default.yaml --api-key YOUR_SECRET --dashboard
# Validate policy files (no server needed)
vanzik validate --policy configs/default.yaml
# Approve / deny — accept --api-key or VANZIK_API_KEY env var.
vanzik approve --api-key YOUR_SECRET ap_abc123def456
VANZIK_API_KEY=YOUR_SECRET vanzik deny ap_abc123def456
# Check server status and pending approvals (auth required if server is gated)
vanzik status --api-key YOUR_SECRET
# Query the audit log with filters
vanzik audit --agent my-bot --decision DENY --limit 20 --api-key YOUR_SECRET
# Print version
vanzik version
The full server flag table (persistence, audit rotation, buffered async
logger, session-cost TTL, base-url/CORS) lives in
CLI.md; vanzik server -h prints the same
list.
Wire-level enforcement points#
Two additional binaries enforce at the wire. Both reach vanzik server at --guard-url, which defaults to $VANZIK_URL, else http://127.0.0.1:8080, and both read VANZIK_API_KEY for authenticated server calls.
vanzik-mcp-gateway— sits between an MCP client and one or more MCP servers. Quickstart with copy-paste configs:QUICKSTART_MCP.md. Reference:MCP_GATEWAY.md.vanzik-llm-proxy— sits between OpenAI / Anthropic SDK code and the providers. Quickstart:QUICKSTART_LLM_PROXY.md. Reference:LLM_API_PROXY.md.
Using Docker#
docker build -t vanzik:latest .
# The API key is required: without it the server binds 127.0.0.1 inside
# the container and the published port is unreachable.
# Default policy is baked in; mount a named volume so the audit log
# survives container restarts.
export VANZIK_API_KEY="$(openssl rand -hex 32)"
docker run -d -p 8080:8080 --name vanzik \
-e VANZIK_API_KEY="$VANZIK_API_KEY" \
-v vanzik-audit:/var/lib/vanzik \
vanzik:latest
make docker-run does the same build and run, and stops early if
VANZIK_API_KEY isn't set.
Custom-policy mounts, the non-root uid-10001 volume-permission gotcha,
Compose, and Kubernetes manifests are in
DEPLOYMENT.md.
Configuration#
Policy Files#
Policies are YAML files in configs/. See the included examples:
| File | Use Case |
|---|---|
configs/default.yaml |
Safe sandbox defaults |
configs/examples/research-agent.yaml |
Permissive research agent |
configs/examples/trading-bot.yaml |
Strict financial trading agent |
Policy Hot-Reload#
Policy edits take effect without a restart: the server always watches the
--policy file (fsnotify, falling back to a 2 s modification-time poll
where fsnotify isn't available). --watch only adds a log line for each
reload:
vanzik server --policy configs/default.yaml --watch
# 2026/09/23 21:59:11 Policy reloaded: default-sandbox (61 rules)
Everything else in the policy file#
Per-agent overrides (agents:), notifications (Slack / webhook /
console), per-scope rate limits, cost guardrails, conditional rules, and
the tool_scope_map are all part of the policy YAML — the schema with
examples for each lives in
POLICY_REFERENCE.md; server-side tunables
(session TTL, body caps, audit query limits) in CONFIG.md.
Running Tests#
The fastest path is make test-all, which runs all four suites (Go, policy YAML validation, Python SDK, TypeScript SDK) in sequence and prints a PASS / FAIL / SKIP summary. An invalid policy or a failing configs/tests case fails the policy suite, and the Python suite installs the same extras as CI (.[dev,langchain,crewai,mcp,openai-agents]). Missing toolchains (no python, no npm) report SKIP cleanly so Go-only contributors aren't penalised. The script exits 0 if no suite failed and 1 if any did. See CONTRIBUTING.md.
make test-all # everything
# or, narrow:
./scripts/test-all.sh --skip-ts
./scripts/test-all.sh --no-race # drop the Go race detector for speed
Per-suite manual invocations:
# Go tests with race detection + coverage
go test -v -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
# Policy YAML validation (configs/default.yaml and every configs/examples/*.yaml; builds ./vanzik)
make validate
# Python SDK tests (adapter unit tests need framework extras)
cd plugins/python
pip install -e ".[dev,langchain,crewai,mcp,openai-agents]"
pytest -v --cov=vanzik
# TypeScript SDK tests
cd plugins/typescript && npm install && npm run build && npm test
Project Structure#
The main directories and files; the lists below are not exhaustive (pkg/ also holds depaudit, deprecation, internal, metrics, persist, report and store, and the Python adapters include openai_agents.py and the shared _common.py).
vanzik/
├── cmd/
│ ├── vanzik/ # Central server CLI (serve / validate / check / migrate / …)
│ │ ├── main.go
│ │ ├── check_cmd.go
│ │ └── update_check.go
│ ├── vanzik-mcp-gateway/ # MCP Gateway binary
│ │ └── main.go
│ └── vanzik-llm-proxy/ # LLM API Proxy binary
│ └── main.go
├── pkg/
│ ├── policy/ # Policy engine (YAML parsing, rule evaluation, providers)
│ ├── proxy/ # Central HTTP server + dashboard + approval queue
│ ├── audit/ # Audit logging (JSON lines + rotation + buffered async)
│ ├── notify/ # Webhook / Slack / console notifications
│ ├── ratelimit/ # Token-bucket rate limiter
│ ├── mcpgw/ # MCP Gateway core (upstream multiplexing, namespacing)
│ ├── llmproxy/ # LLM API Proxy core (OpenAI / Anthropic stream gating)
│ └── migrate/ # On-disk schema migrations (audit / checkpoint format)
├── plugins/
│ ├── python/ # Python SDK + framework adapters
│ │ ├── vanzik/
│ │ │ ├── __init__.py # Guard, @guarded, exception hierarchy
│ │ │ └── adapters/
│ │ │ ├── langchain.py # GuardedTool, GuardedToolkit (subclasses BaseTool)
│ │ │ ├── crewai.py # GuardedCrewTool (subclasses crewai BaseTool)
│ │ │ ├── browseruse.py # GuardedBrowser / Page / Frame
│ │ │ └── mcp.py # GuardedMCPServer + Python MCP gateway
│ │ ├── pyproject.toml
│ │ └── README.md
│ └── typescript/ # TypeScript SDK
│ ├── src/index.ts
│ └── package.json
├── configs/ # Policy files
│ ├── default.yaml
│ └── examples/
├── examples/ # MCP-client + SDK config snippets ready to copy
├── docs/ # Documentation
├── Dockerfile # Image shipping the `vanzik` server binary
├── Makefile # build / test / test-all / docker / …
└── README.md