Configuration¶
Rampart has two kinds of configuration:
- Runtime/client config — where Rampart should find its local service
- Policy config — what agents are allowed to do once Rampart evaluates a tool call
Most users only need one runtime setting:
Runtime Config (~/.rampart/config.yaml)¶
If you do not want to keep exporting environment variables, Rampart can load persistent local defaults from ~/.rampart/config.yaml.
url: http://127.0.0.1:9090
# serve_url: http://127.0.0.1:9090 # compatibility alias for url
# api: http://127.0.0.1:9091 # optional advanced override for daemon/split-topology API setups
| Setting | Use it for | Notes |
|---|---|---|
url | Primary Rampart base URL | Canonical setting for hook, watch, plugin, and service-backed flows |
serve_url | Backwards-compatible alias for url | Kept for compatibility; prefer url in new configs |
api | Optional API base URL override for approval/control commands | Advanced only; usually unnecessary unless you split the API away from the main serve endpoint |
Resolution order¶
Rampart resolves service addresses in this order:
flag → environment → config file → auto-discovered state → default
That means:
--apior--serve-urlwins when you pass it explicitly- environment variables such as
RAMPART_URL,RAMPART_SERVE_URL, andRAMPART_APIoverride file values ~/.rampart/config.yamlis the persistent local default- if nothing is configured, Rampart falls back to discovered local state and then localhost defaults
Which setting should I use?¶
Use url unless you have a specific reason not to.
urlis the normal setting for local Rampart service discoveryserve_urlexists for compatibility with older setupsapiis not the normalrampart servesetting — it is an advanced client-side override for approval/control flows
Two different meanings of --api
Client-side --api flags expect an API base URL such as http://127.0.0.1:9091.
Daemon/server --api flags refer to an API listen address such as 127.0.0.1:9091.
Policy File Location¶
Rampart policies are YAML files that define what your AI agent can and can't do. Policies are evaluated in microseconds and hot-reload when you edit them.
By default, Rampart looks for policies in ~/.rampart/policies/. You can specify a custom location:
Basic Structure¶
version: "1"
default_action: allow # allow | deny | ask | watch
policies:
- name: my-policy
match:
tool: ["exec"] # Which tool types this applies to
rules:
- action: deny # deny | allow | ask | watch | webhook
when:
command_matches: ["rm -rf *"]
message: "Destructive command blocked"
Actions¶
| Action | Effect |
|---|---|
deny | Block the tool call. Agent receives an error. |
allow | Permit the tool call. |
watch | Permit but log with elevated visibility. (Previously called log — log still works as an alias.) |
ask | Block until a human approves or denies. Also valid as default_action: ask to surface unmatched calls for review. |
webhook | Delegate the decision to an external HTTP endpoint. |
Deny always wins. If any matching policy says deny, the call is denied regardless of other policies.
Tool Types¶
Rampart recognizes four tool types:
| Tool | What It Matches |
|---|---|
exec | Shell commands (Bash, terminal) |
read | File read operations |
write | File write/edit operations |
fetch | HTTP requests, network operations |
For MCP tools, the tool name from the MCP tools/call is used directly (e.g., mcp__filesystem__read_file).
Matching Rules¶
Command Matching¶
rules:
- action: deny
when:
command_matches:
- "rm -rf *" # Glob pattern
- "mkfs.*" # Filesystem format
- "dd if=*" # Raw disk write
- ":(){ :|:& };:" # Fork bomb
Path Matching¶
rules:
- action: deny
when:
path_matches:
- "**/.ssh/id_*" # SSH private keys
- "**/.aws/credentials" # AWS credentials
- "**/.env" # Environment files
path_not_matches:
- "**/*.pub" # Exclude public keys
URL Matching¶
Match the full request URL for fetch tool calls. Useful when you need more precision than domain matching — for example, to allow a domain but restrict specific paths:
rules:
- action: deny
when:
url_matches:
- "https://api.example.com/admin/*" # Block admin endpoints
- "http://*/*" # Block non-HTTPS requests
- "https://*/v1/secrets*" # Block any host's secrets path
Use domain_matches when you only care about the hostname; use url_matches when path, scheme, or query matter.
Session Matching¶
Filter rules by session identity — the repo path, branch, or project label Rampart associates with the current run. Useful for per-project policies without separate YAML files:
rules:
- action: deny
when:
session_matches:
- "*/production" # Any repo on the production branch
- "infra-*" # Sessions labelled infra-*
- action: allow
when:
session_not_matches:
- "*/main" # Exclude main branch from this rule
Sessions are set by the agent integration (Claude Code sets them from the project path; MCP proxy uses the client-provided session ID).
Tool Parameter Matching¶
Match arbitrary MCP tool input parameters by name and glob pattern. Each key is a parameter name; any matching parameter triggers the rule (OR logic across params):
rules:
- action: deny
when:
tool_param_matches:
path: "**/.env*" # deny if the "path" param targets .env files
url: "*webhook.site*" # deny if the "url" param points to webhook.site
This is particularly useful for MCP tools where the tool name alone doesn't give enough context — for example, a generic file_read MCP tool where you want to restrict specific path arguments.
Domain Matching¶
rules:
- action: deny
when:
domain_matches:
- "*.ngrok-free.app"
- "*.requestbin.com"
- "webhook.site"
Response Matching¶
Scan tool output for sensitive patterns:
rules:
- action: deny
when:
response_matches:
- "AKIA[0-9A-Z]{16}" # AWS access key
- "-----BEGIN (RSA )?PRIVATE KEY-----" # Private keys
- "ghp_[a-zA-Z0-9]{36}" # GitHub PAT
Rate Limiting¶
Use call_count to trigger a rule when a tool is invoked more than N times in a sliding time window. Useful for capping runaway agents or limiting expensive operations:
rules:
- action: ask
when:
call_count:
gte: 50 # Threshold: 50 or more calls...
window: 10m # ...within the last 10 minutes
message: "High fetch volume — pausing for review"
- action: deny
when:
call_count:
tool: fetch # Optional: count only fetch calls (omit for all tools)
gte: 200
window: 1h
message: "Fetch rate limit exceeded"
window accepts standard duration strings: 1h, 30m, 10m, 5m, 1m. The counter increments on every PreToolUse event and resets as calls age out of the window.
Priority¶
Lower priority number = evaluated first. Use priority to ensure critical rules run before general ones:
policies:
- name: critical-blocks
priority: 1 # Evaluated first
match:
tool: ["exec"]
rules:
- action: deny
when:
command_matches: ["rm -rf /"]
- name: general-logging
priority: 10 # Evaluated later
match:
tool: ["exec"]
rules:
- action: log # Renamed to action: watch in v0.9.x.
when:
command_matches: ["curl *"]
Approval Flow¶
For commands that aren't dangerous enough to block outright, but risky enough for a human to decide:
policies:
- name: approve-deployments
match:
tool: ["exec"]
rules:
- action: ask
when:
command_matches:
- "kubectl apply *"
- "terraform apply *"
- "docker push *"
- "helm upgrade *"
message: "Deployment — approve or deny?"
- name: approve-installs
match:
tool: ["exec"]
rules:
- action: ask
when:
command_matches:
- "pip install *"
- "npm install *"
- "brew install *"
message: "Package install — approve or deny?"
How you'll see the approval prompt depends on your setup:
- Claude Code — native permission dialog (the same one Claude uses for
ask) - MCP clients — the proxy blocks until you approve via CLI or API
- OpenClaw — sends a chat message you can approve inline
- Webhooks — sends a notification with a signed approve/deny link
Manage pending approvals:
rampart pending # What's waiting
rampart approve abc123 # Let it through
rampart deny abc123 --reason "not now" # Block it
Webhook Notifications¶
Get alerts when commands are blocked or need approval:
version: "1"
default_action: allow
notify:
url: "https://discord.com/api/webhooks/your/webhook"
on: ["deny", "ask"] # Options: deny, log, ask
policies:
# ... your policies
Example: Standard Policy¶
A sensible default that blocks destructive commands and credential access:
version: "1"
default_action: allow
policies:
- name: block-destructive
match:
tool: ["exec"]
rules:
- action: deny
when:
command_matches:
- "rm -rf /"
- "rm -rf ~"
- "mkfs*"
- "dd if=*"
- "chmod -R 777 /"
message: "Destructive command blocked"
- name: block-credential-access
match:
tool: ["read"]
rules:
- action: deny
when:
path_matches:
- "**/.ssh/id_*"
- "**/.aws/credentials"
- "**/.env"
path_not_matches:
- "**/*.pub"
message: "Credential file access blocked"
- name: block-exfil
match:
tool: ["fetch"]
rules:
- action: deny
when:
domain_matches:
- "*.ngrok-free.app"
- "*.requestbin.com"
- "webhook.site"
message: "Exfiltration domain blocked"
Example: Anti-Exfiltration Policy¶
Detect encoding, obfuscation, and data staging:
version: "1"
default_action: allow
policies:
- name: encoding-sensitive-files
priority: 1
match:
tool: "exec"
rules:
- action: deny
when:
command_matches:
- "base64 ~/.ssh/*"
- "base64 ~/.aws/*"
- "*cat*.ssh*|*base64*"
- "*cat*.aws*|*base64*"
- "*xxd*.ssh*"
message: "Encoding of sensitive files blocked"
- name: encoded-data-exfil
priority: 1
match:
tool: "exec"
rules:
- action: deny
when:
command_matches:
- "*base64*|*curl*"
- "*base64*|*wget*"
- "*base64*|*nc *"
message: "Encoded data sent to network blocked"
- name: reverse-shell
priority: 1
match:
tool: "exec"
rules:
- action: deny
when:
command_matches:
- "*bash -i >& /dev/tcp*"
- "*python*socket*connect*"
- "*nc -e /bin/*"
message: "Reverse shell pattern blocked"
Hot Reload¶
Rampart watches policy files for changes via fsnotify. Edit a YAML file and the policy engine picks it up immediately — no restart needed.
Validation¶
Check your policy file for errors:
Trace how a specific command would be evaluated:
Next Steps¶
- Policy Engine → — Full evaluation logic
- Policy Schema → — Complete YAML reference
- Integration Guides → — Hook up your agent