Concepts
This page explains the core ideas behind warrant-shell: what the pieces are, how they fit together, and why they're designed the way they are.
Manifests
A manifest is a declarative capability map for a CLI tool. It's a TOML file that describes what a tool's commands can do — factually, without opinions about what should be allowed or denied.
Key properties of manifests:
- Anyone can write one. Manifests don't require cooperation from the tool author. You can write a manifest for git, curl, or any CLI tool without modifying the tool itself.
- They map commands to capabilities. Each entry says "when the user runs
git push, that exercises thegit.pushcapability." - They define scopes. Manifests can extract context from command arguments — which remote, which branch, which host — using a transform pipeline.
- They're read-only once installed. Manifests are reference material, not configuration. Your decisions about what to allow or deny live in draft policies.
wsh fetches manifests for git, cargo, npm, curl, docker, ssh, and pip from the registry. See Manifest Specification for the full schema.
Draft policies
When you run wsh add git, wsh reads the git manifest and generates a draft policy. The draft lists every capability from the manifest with an initial value of review.
You then edit the draft (wsh edit git) to set each capability to allow or deny. Drafts live in your user config directory and have no security significance until they're signed and locked.
Think of manifests as the menu and drafts as your order.
Lock compilation
sudo wsh lock is the critical step that turns drafts into an enforceable policy. The lock process:
- Reads all draft policies
- Validates each draft against its manifest (no unknown capabilities)
- Rejects any draft that still contains
reviewdecisions - Compiles all drafts into a single policy document
- Signs the policy with an Ed25519 private key stored in a root-owned path
- Increments the monotonic version number
- Installs the signed policy to the system path (
/etc/warrant-shell/)
Lock requires sudo because the signing keys and installed policy are owned by root. This is the privilege separation boundary — an AI agent running as a normal user cannot modify the signed policy.
Enforcement
When your agent runs git push origin main in an environment wired through wsh, the enforcement engine:
- Loads the signed policy from the system path
- Verifies the Ed25519 signature against the public key
- Checks the version number against the monotonic version store (no rollback)
- Parses the command arguments and resolves the binary
- Loads the manifest for the tool
- Matches the command and flags against manifest declarations to identify capabilities
- Extracts scopes (remote names, hostnames, paths) via the transform pipeline
- Checks each required capability against the policy
- Allows the command if all capabilities are granted, or denies it otherwise
Enforcement is deny-by-default. If a command doesn't match any manifest entry, or if the matched capability isn't granted in the policy, the command is blocked.
Audit
Every enforcement decision — allow or deny — is written to a structured audit log as JSON Lines. Each entry records the timestamp, the command, the matched capability, the decision, the policy version, and the session ID.
This gives you a complete record of what your agents did and why each action was allowed or blocked. Unlike raw syscall logs, wsh audit entries are application-aware — they tell you "git.push was allowed" rather than "execve() was called."
Elevation
Sometimes a human needs to temporarily bypass the policy. wsh elevate prompts for the system password and creates a time-limited session token (stored in a root-owned path). While elevated, warrant enforcement is bypassed for that user.
wsh elevate --duration 30 # elevated for 30 minutes An agent cannot elevate because it doesn't know the system password. The session token is stored in a root-owned path, so an agent can't forge or extend it. Brute-force protection (exponential backoff and lockout after 5 failures) prevents password guessing.
To end elevation early:
wsh de-elevate To check whether you're currently elevated:
wsh is-elevated Two-tier scope: system vs project
wsh supports two levels of policy scope:
- System scope — applies everywhere, stored in
~/.config/warrant-shell/drafts/and compiled into the system-wide signed policy. This is the default. - Project scope — applies only within a specific project directory. Useful for per-repo policies where you might want tighter restrictions for untrusted projects.
Project-scoped policies are additive restrictions — they can deny capabilities that the system policy allows, but they can't grant capabilities that the system policy denies. The system policy is the ceiling.
Three-tier architecture
The warrant ecosystem is built in three layers:
warrant-core
The Rust library that implements Ed25519 signing, TOML parsing, canonical JSON serialization, and version enforcement. This is the embeddable component that any CLI tool can integrate directly.
wsh (warrant-shell)
The CLI control plane. Manages manifests, drafts, lock compilation, runtime enforcement, audit logging, elevation, and profiles. This is what you install and interact with.
warrant-box (coming soon)
A containerized sandbox with wsh as the shell. Provides kernel-level isolation (default-deny network and filesystem) on top of wsh's application-level policy enforcement. For users who want hard containment in addition to capability policies.