Repository navigation
Agent Integrations
IronVise can stand in front of an existing agent in several ways. Some enforce (they answer before the action runs, and a "no" stops it); some only record. This page says which is which. The authoritative matrix is docs/guides/integrations.md.
All of these need a running Observer: ironvise serve or the desktop app.
ironvise hook install # .claude/settings.local.json in this project
ironvise hook install --shared # .claude/settings.json, checked in for the team
ironvise hook install --user # ~/.claude/settings.json, every project
export ECTOLEDGER_URL=http://127.0.0.1:3000 # default
export ECTOLEDGER_TOKEN=<an agent or admin token>hook install merges into the existing settings file, replaces an older IronVise hook instead of adding a second one, and checks that the Observer answers and the token is accepted. --project DIR and --command CMD change where it writes and what it runs. The token needs the agent or admin role.
What it checks.
| Claude Code tool | IronVise action | Checked on |
|---|---|---|
Bash |
run_command |
the command, split at &&, ||, ;, | and & and checked command by command |
Read |
read_file |
the path |
WebFetch |
http_get |
the URL |
Write, Edit, MultiEdit, NotebookEdit
|
write_file |
where the write lands |
Glob, Grep
|
read_file |
the directory the search can reach |
mcp__<server>__<tool> |
mcp:<server>/<tool> |
policy and allowed_mcp_tools
|
Anything else returns ask, which escalates to you. Writes to .claude/settings*.json, .git/hooks/ and anything under .ssh/ are refused even inside the workspace.
Allow means "no objection". By default an allow is sent to Claude Code as no decision, so Claude Code's own prompts still apply. Set ECTOLEDGER_HOOK_MODE=approve if the policy should replace those prompts.
Fail-closed. Any error (missing token, unreachable server, malformed input, timeout) exits 2, the only exit code that makes Claude Code block the tool.
Data receipts. After each call the hook hashes what the tool returned and records only the hashes. Check a file later:
ironvise data-receipts <session_id> --file config.iniironvise hook install --codex # .codex/hooks.json in this project
ironvise hook install --codex --user # ~/.codex/hooks.json, every projectCodex runs a project's hooks only after you trust them (/hooks in Codex). Bash calls are checked as commands and apply_patch as a write to every file it touches. Because Codex cannot ask a person, an escalation is sent as a deny that says a person must approve. Hosted tools such as Codex's web search never reach a hook.
ironvise hook install --antigravity # .agents/hooks.json in this workspace
ironvise hook install --antigravity --user # ~/.gemini/config/hooks.jsonShell, file, search and URL tools are checked. Antigravity's hook contract gives no tool result and no tool-use id, so there are no data receipts and no replay check for this agent.
ECTOLEDGER_TOKEN=<agent token> ironvise mcp-proxy --name files -- \
npx -y @modelcontextprotocol/server-filesystem ~/workPut the proxy where your MCP client would start the server. Every tools/call is judged as mcp:<name>/<tool> before it reaches the server; a refused call returns to the client as a tool error and never happens. It fails closed. Restrict tools with allowed_mcp_tools in the tripwire configuration, or name one tool in a policy:
[[forbidden_actions]]
action = "mcp:files/write_file"Arguments called command, cmd or script get the shell check. Other arguments are not interpreted. make demo-mcp runs this end to end.
Ask before acting; nothing is executed or recorded by asking.
verdict = await client.verify_intent(sid, "run_command", {"command": cmd}, justification="...")
verdict.raise_if_denied()The SDK runs inside your process, so nothing stops your code from ignoring a deny. If you want the decision in the ledger, append it yourself or use a hook. See SDKs.
ironvise import-openshell ocsf.log --out openshell-receipts
verify-cert --strict openshell-receipts/<receipt>.elcTurns OpenShell's OCSF decision log into one sealed, signed session and .elc receipt per sandbox. Audit-mode allows are recorded as audit, not hidden. It cannot prove OpenShell logged every decision; it makes what was logged tamper-evident from the moment of import.
ironvise proxy --bind 127.0.0.1:3100 --upstream https://api.openai.com
# in the agent:
export OPENAI_BASE_URL=http://127.0.0.1:3100An OpenAI-compatible proxy that writes every prompt and completion to the hash chain. It works with any agent that has a configurable endpoint. It sees text, not actions, so it cannot stop anything; flagged prompts are recorded with enforced: false. It has no authentication, so a non-loopback --bind is refused unless you pass --allow-remote.
The CLI takes --policy. For everything that goes through the Observer, set the server-wide policy before starting it:
export ECTO_POLICY_PATH=/path/to/audit_policy.toml
ironvise serveA set but unloadable policy stops the server instead of running without it. Every verdict carries a coverage object naming the layers that ran, the ones that were skipped, and the policy hash.
IronVise, by EctoSpace. Repository | Website | Releases | Report a vulnerability. The server is licensed under BUSL-1.1; the SDKs under Apache-2.0. Compliance mappings are aids, not legal advice or certification.
Get going
Understand
Use
Operate
Project