Version: v0.2.0 ▾
Quickstart
Install the binary, wire it into your agent, start in ride-along, then turn the dial up.
brig init writes the hook config for your harness and a starter .brig.json in your repo. Out of the box Brig runs in ride-along — every call allowed and recorded, nothing blocked — so you can watch before you enforce. When you're ready, change one line to "mode": "guardrails" and it starts denying the clearly dangerous; "containment" is deny-by-default.
Concepts
The handful of ideas the rest of the docs build on.
Modes — the friction dial
Ride-along allows every call and records it (zero friction). Guardrails allows by default but blocks the clearly dangerous — a write escaping the workspace, egress to a non-allow-listed host, an unmistakably destructive shell command. Containment is deny-by-default: only what your capabilities grant gets through. Every mode records every decision.
Capabilities — what a tool may do
Every tool call requires a capability, and nothing is granted unless you grant it (deny-by-default). The vocabulary is small and fixed:
| Capability | Gates the tool | Allows |
|---|---|---|
| fs.read | read_file | Read files inside the workspace |
| fs.write | write_file | Write or modify files inside the workspace |
| sandbox.run | run_code | Run code in the memory-safe sandbox |
| net.outbound | http_fetch | Reach allow-listed hosts over HTTPS |
| proc.exec | run_command | Run a shell command — always human-approved |
Profiles — least-privilege presets
A profile is a named bundle of capabilities; pick the smallest that fits the job. The default is the most conservative, reviewer.
| Profile | Grants | For |
|---|---|---|
| reviewer (default) | fs.read · sandbox.run | Read-only review + sandboxed compute |
| builder | + fs.write | Editing code in the repo |
| ops | + net.outbound · proc.exec | Network + shell (egress allow-listed, shell human-approved) |
The gates
On top of capabilities, each allowed call still passes the relevant gates: workspace containment (paths can't escape the workspace root, symlink-safe), the egress allow-list (HTTPS to named hosts only), human-in-the-loop on the shell, and budgets and rate limits to cap a runaway agent. You set each in Configuration.
Audit
Every decision and outcome is written to a tamper-evident, hash-chained log. Key it to an operator secret (BRIG_AUDIT_KEY) and a file-write attacker can't silently re-forge it; brig verify recomputes the chain and fails on any edit.
Configuration
Two places to configure Brig: a .brig.json file in your repo (checked in, shared with your team) and environment variables (for secrets and per-machine settings). Most knobs are available in either.
The .brig.json file
Drop it at the root of your repo — brig init writes a starter. Every field is optional; capabilities overrides profile when both are set.
Environment variables
Use these for secrets (the audit key) and per-machine settings — the common ones here, the full list in the Reference:
| Variable | Sets | Example / default |
|---|---|---|
| BRIG_WORKSPACE | Workspace root for file tools | current dir |
| BRIG_PROFILE | Capability profile | reviewer (default) |
| BRIG_EGRESS_ALLOW | Allowed hosts for http_fetch | api.github.com |
| BRIG_HITL | Shell approval | tty = prompt you |
| BRIG_PREAPPROVED | Shell commands allowed without a prompt | npm test |
| BRIG_AUDIT_KEY | Keyed, unforgeable audit chain | hex secret ≥ 16 bytes |
Recipes
Common cases, as the config you'd actually write.
Read-only code review
The agent may read and reason — never write, reach the network, or run a shell.
Builder allowed to reach one API
Read/write the repo and run code, reach exactly one host — and nothing else (no shell).
Pre-approve your build commands
A couple of exact shell commands run without a prompt; everything else still asks you.
Locked-down CI with a provable log
Deny-by-default, key the audit chain, and fail the job if the log was touched.
Harness setup
One command does it — brig init <harness> writes the config for you, no JSON to hand-edit. Add --dry-run to print exactly what it would write (changing nothing), or --global for a user-level install. You can wire it by hand too; here's what each harness needs. The decision contract is identical everywhere — allow (exit 0) or block (exit 2), fail-closed.
Claude Code
brig init claude-code merges a PreToolUse hook into .claude/settings.json (without touching your other settings):
OpenCode
A TypeScript plugin that routes tool.execute.before through brig hook --harness opencode (and throws when Brig blocks), plus a tool.execute.after report for cross-call tracking.
Pi
A TypeScript extension that gates the tool_call event through brig hook --harness pi (returning a block decision when Brig denies), plus a tool_result report.
Hermes
A Python plugin that gates the pre_tool_call hook through brig hook --harness hermes (returning a block decision when Brig denies). It's opt-in — after install, enable it in ~/.hermes/config.yaml. Needs a model with ≥64K context (Hermes v0.17+).
How it works — the security depth
Brig's strongest claim is that containment holds by construction, at the layer below the prompt, where a model's intent can't reach. The first thing to understand is that there are two data-flow layers, and they protect different things.
Governs the agent you already use — Claude Code, OpenCode, Pi. Provenance is tracked across the harness's tool calls, so data read from your workspace can't leave through a later call. This is the lethal-trifecta defense for your live session.
For tasks run through Brig's own runtime (run-task) — not the external hook path — a dual-LLM split with capability-typed data-flow means a secret can't reach a forbidden sink, even an allow-listed one. Provenance decides, not byte-matching.
The four pillars
A dual-LLM design separates the planner from the data it reads, and types every value with where it came from. A prompt-injected instruction can't grant a capability it doesn't have, and a tainted value can't reach an egress sink — by construction, not by a rule that could be misconfigured.
The brig hookd daemon carries taint across a whole session, so a value read early can't be relayed out by a call made much later — including base64 / paraphrase attempts that a single-call literal check would miss.
Untrusted code runs in a clean-room, memory-safe interpreter — no unsafe, no JIT, no filesystem, network, or process access, and hard CPU and memory ceilings. It deliberately runs a minimal, audited language — just enough to transform data, and no more. A sandbox's security is what it can't do — so a smaller language means less to attack and less to audit, by design.
A conformance battery proves containment holds identically across models — including ones people distrust and a built-in hostile model that dumps the secret and still can't launder it out. "Verified to contain these models" is the trust signal — the same discipline our engines live by.
Reference
CLI
| Command | Does |
|---|---|
| brig init <harness> | Wire Brig into a harness + write a starter .brig.json. Flags: --mode · --global · --force · --dry-run |
| brig doctor [harness] [--live] | Check the install + each harness's installed version against what Brig verified. --live drives a real tool call to prove the gate still fires on your version |
| brig hook --mode <m> | The pre-tool decision (stdin event → allow exit 0 / block exit 2). Called by the harness, not by hand |
| brig hookd | Stateful daemon: cross-call budgets + exfiltration tracking |
| brig verify | Recompute the audit chain; non-zero exit on tampering |
| brig audit [--json] | Print the audit log (human or JSON Lines) |
| brig report [path] | Write a self-contained, verifiable HTML audit report |
| brig export [path] | Write the log as JSON Lines for a SIEM |
| brig anchor · anchor-keygen | Commit / sign the audit head to an external anchor (truncation-proof) |
| brig profiles | Print the profile × tool matrix |
| brig demo | The scripted governance demo (what See it shows) |
Profiles × capabilities
| Capability | reviewer | builder | ops |
|---|---|---|---|
| fs.read | ✓ | ✓ | ✓ |
| sandbox.run | ✓ | ✓ | ✓ |
| fs.write | — | ✓ | ✓ |
| net.outbound | — | — | ✓ |
| proc.exec | — | — | ✓ |
Environment variables
The configuration knobs (defaults shown). Network, operator auth, and the CaMeL runtime are opt-in build features beyond this single-developer reference.
| Variable | Default | Sets |
|---|---|---|
| BRIG_WORKSPACE | current dir | Workspace root (file tools confined here) |
| BRIG_PROFILE | reviewer | Capability profile |
| BRIG_MAX_PROFILE | — | Ceiling: caps every caller at this profile |
| BRIG_EGRESS_ALLOW | none (denied) | Comma-separated allowed hosts |
| BRIG_EGRESS_SCHEMES | https | Allowed URL schemes |
| BRIG_HITL | deny | tty to approve shell at the terminal |
| BRIG_PREAPPROVED | none | Exact shell commands allowed without a prompt |
| BRIG_MAX_CALLS · _PER_TOOL · BRIG_RATE_PER_MIN | unlimited | Budgets + 60-second rate limit |
| BRIG_AUDIT_DB | brig-audit.db | Audit log path |
| BRIG_AUDIT_KEY · _KEY_FILE | — | HMAC key for the keyed audit chain |
| BRIG_POLICY_FILE | — | Custom roles → capabilities (multi-user / auth) |
FAQ — honest answers to the hard questions
The questions a skeptic should ask. If one isn't answered here, write to us.
How is this different from a container or a VM?
A container or VM isolates a whole machine, but leaves the agent's powers intact inside it — shared-kernel CVEs, egress open by default, and a log you can't prove wasn't edited. Brig governs the agent's individual actions — each file, network, and shell call — at the layer below the prompt, deny-by-default, with a tamper-evident record.
They compose: use a VM for blast radius, Brig for what the agent may actually do. Brig also runs without the weight of a VM.
Does my code leave my machine?
Brig is self-hosted — the gateway, your files, and egress all stay on your infrastructure. With a local model, nothing reaches any model vendor at all. With a vendor API, only what you send the model leaves, under your egress controls and full audit. Brig itself phones nothing home — no telemetry.
Which models can I use?
Any — Brig is model-agnostic (local via Ollama and the like, or a vendor API). The gating is model-independent, so it holds identically whichever model drives the agent. The conformance battery proves that across models, including ones people distrust.
What about the subagent coverage gap?
A hook governs the calls the harness routes through it. On some harnesses, a subagent's calls can be opaque to the hook — we name that gap rather than paper over it. The airtight answer (interception below the harness) is a platform direction, not yet scheduled. If you need a hard ceiling today, run containment mode inside a VM.
Is the audit really un-forgeable?
It's tamper-evident. Every record is hash-chained and HMAC-keyed to an operator secret, so a file-write attacker without the key can't silently re-forge it. brig verify recomputes the chain and fails on any edit; brig anchor commits the head to an external sink (Ed25519-signable — an auditor verifies with only the public key), which also catches deletion and truncation.
What's the license?
Open-core. The gateway — gating, audit, egress, and the injection-defense logic — is open to review under agreement by teams deploying it (not published for the crowd, and never a license to resell). Our proprietary execution engines stay private; a neutral third party holds a sealed source copy for continuity if the vendor ever fails. Provided as is — see the Terms.
What's the performance overhead?
The hook is a fast local decision per tool call — no network round-trip, no per-token interception of the model. The sandbox and CaMeL paths only run for tasks Brig executes itself.
Does CaMeL protect my Claude Code session?
Two layers. Your Claude Code session is governed by the hook's cross-call taint tracking — that's what stops exfiltration there. CaMeL's by-construction defense applies to tasks you run through Brig's own runtime, not the external hook path. Same goal, different mechanism per surface — see Security depth.
Changelog
There's no public code repo — this page and the feed are the release channel. No account, no tracker.
- brig run — OS-enforced boundary: the agent's writes are confined to the workspace by the OS (Seatbelt · Landlock · restricted token), proven on macOS, Linux, and Windows.
- Egress sole-exit (macOS): with an allowlist, an out-of-sandbox proxy becomes the agent's only route to the network.
- brig run --contained (preview): selects the privilege-separation tier (the agent as a separate, unprivileged user it can't become); fails closed until provisioned — full enforcement is in progress.
- Hermes cross-call exfil tracking: Hermes's post_tool_call is now wired in — a secret it reads in one step can't be slipped out in a later one. Verified end-to-end.
- Drop-in install: brig init for Claude Code, OpenCode, Pi, and Hermes.
- Three modes: ride-along · guardrails · containment.
- Tamper-evident audit: keyed hash chain + Ed25519-signable external anchors.
- Injection defense: the CaMeL by-construction runtime (opt-in).
Each tagged release will list its changes here and link the verified binaries on the install page.