Configuration
Environment variables, commands, ports, paths.
Everything Iris reads from the environment, everything the CLI does, and where files land.
Commands
| Command | What it does |
|---|---|
iris [--port N] | Start proxy + UI (start and run are aliases) |
iris init [--port N] | Configure this project. Without --port it discovers a running instance for this directory. Needed once — after that the server keeps the port in sync |
iris hook | The Pre/PostToolUse hook body. Claude Code invokes this, not you |
iris version | Print version |
iris help | Usage |
What init writes
All of it idempotent — re-running never wipes entries you added yourself.
| File | Change |
|---|---|
.claude/settings.json | env.ANTHROPIC_BASE_URL, env.IRIS_HOME, env.IRIS_ENVELOPE_PATH, and hooks.PreToolUse + hooks.PostToolUse entries running node "<pkg>/bin/iris.mjs" hook |
.claude/iris-project.json | Project id and metadata |
~/.iris/projects/<id>/sessions/authority.json | A first envelope draft, if none exists |
.gitignore | Four capture paths: .claude/proxy-logs/, .claude/history-index.json, .claude/action-log.json, .claude/proxy-run.log |
Environment variables
| Variable | Default | What it does |
|---|---|---|
PROXY_PORT | 8787 | Bind on 127.0.0.1. Set explicitly, it is never auto-moved on a conflict |
ANTHROPIC_PROXY_TARGET | https://api.anthropic.com | Upstream |
IRIS_HOME | ~/.iris | Per-project store |
IRIS_ENVELOPE_PATH | ~/.iris/projects/<id>/sessions/authority.json | Guard envelope. Hook, UI and server all read this one path |
IRIS_UI_TOKEN | unset | Require X-Iris-Token on mutating UI routes |
IRIS_ADAPTER | claude-code | Host adapter |
IRIS_AUTOWIRE | on | Keep ANTHROPIC_BASE_URL pointed at the bound port (=0 to manage it yourself) |
PROXY_REDACT | on | Scrub secrets in logs (=0 off) |
PROXY_REDACT_EMAILS | on | Scrub emails (=0 keep) |
PROXY_REDACT_WIRE | off | Redact on the wire and rehydrate the response (=1 on) |
Path overrides used mainly by the test suite: PROXY_LOG_DIR,
PROXY_HISTORY_PATH, PROXY_ACTIONS_PATH, PROXY_SETTINGS_PATH,
PROXY_IRIS_PATH, IRIS_DECISIONS_PATH, IRIS_LEDGER_PATH.
The UI token
If IRIS_UI_TOKEN is set, open /__monitor?iris_token=… once. A query
?token= on POST URLs is not accepted. The gate covers POST on
/__config, /__authority, /__correlate,
/__guard/evaluate, /__export and /__reset.
More than one project
One Iris instance serves one project — it resolves the project from the directory you start it in. For a second project, start a second instance there. There is nothing else to do:
$ npx @zero-drift/iris
Port 8787 is in use by another Iris instance (project "checkout-api") — starting on 8788 instead.
Iris for Claude Code
Project covenant-layer
Proxy http://127.0.0.1:8788
Settings re-pointed 8787 -> 8788 in .claude/settings.json
restart Claude Code to pick it up
Iris finds a free port, then re-points this project's settings at the port it actually
bound. You do not pass --port and you do not re-run init; you restart Claude
Code, which reads settings at session start.
| Situation | What Iris does |
|---|---|
| Default port busy, occupant is Iris on this project | Prints "already running" with the URLs, exits 0 |
| Default port busy, occupant is anything else | Moves to the next free port and re-points this project's settings |
--port / PROXY_PORT given and busy | Refuses — an explicit port is never silently moved |
| Settings point elsewhere, project is initialised | Re-points them to the bound port |
| Settings point elsewhere, project has no Iris hook | Warns with the init command — it will not wire a project you never opted in |
ANTHROPIC_BASE_URL is not a loopback URL | Reported and left exactly as you set it |
A project pointed at another project's port does not fail visibly. Its traffic is recorded under
the wrong project, and Guard evaluates its tool calls against the wrong envelope and the wrong
project root. That is a correctness problem, not a cosmetic one. Set IRIS_AUTOWIRE=0 if
you manage settings by hand.
Where data lands
| Path | Contents |
|---|---|
.claude/proxy-logs/ | Captured request / response payloads |
.claude/history-index.json | Call index behind Spend and Traffic |
.claude/action-log.json | Tool action ledger |
~/.iris/projects/<id>/sessions/ | authority.json, decisions.json |
~/.iris/projects/<id>/exports/ | JSON / CSV exports |
The views
| Key | View | Use it to |
|---|---|---|
1 | Overview | Session cost, context shipped, unused-schema tax, Guard tallies, flagged anomalies |
2 | Spend | Daily cost, cache savings, models used, cache expiries |
3 | Traffic | Every /v1/messages call: tokens, latency, cache hit, cost |
4 | Context | The newest turn, plus diffs and attribution |
5 | Optimize | Tool inventory with call counts; stage and publish trims |
6 | Guard | The envelope, the decision ledger, trajectory signals |
7 | Flight Recorder | What actually ran, in order, with decisions |
⌘K / Ctrl-K opens the command palette. /__classic is a
lighter UI over the same data; /__health and /__meta report status.