# Inspecting Sessions
Source: https://docs.ironbee.ai/cli/advanced/inspecting-sessions
Check verdict status and validate verdicts from the terminal.
Most of the time you'll review sessions in the [Console](https://console.ironbee.ai). But two commands let you inspect sessions straight from the terminal, useful for quick checks and debugging a session that won't pass.
***
## ironbee status
Show the verdict status of the sessions in a project:
```bash theme={null}
ironbee status [project-dir]
```
For each session it prints the verdict (`pass` / `fail`), the number of checks recorded, the retry count, and, for failures, the list of unresolved issues. Sessions with no verdict yet show as `missing`, or as `monitoring-only` when verification is disabled. An [assist-mode](/cli/guides/verification#assist-mode-default) session that never ran a manual `/ironbee-verify` cycle also shows as `monitoring-only` (there was no gate); one that did will carry its verdict.
***
## ironbee verdict
Dry-run the verdict checks for a session **without changing anything**, a read-only version of the gate that runs when the agent stops:
```bash theme={null}
ironbee verdict [session-id]
```
If only one session is active, the session ID is auto-detected. Use this to understand exactly why a session would pass or fail before the agent retries. Add `-p, --project-dir
` to target a project other than the current directory.
This command used to be `ironbee verify [session-id]`. `ironbee verify` now runs a **cloud verification job** through the IronBee API — see [Verification Jobs](/cli/guides/verification-jobs). The local dry-run lives on unchanged as `ironbee verdict`.
***
## What's next?
Where verdicts, state, and session data are stored on disk.
Inspect and drain the background queue that ships session data.
# Job Queue
Source: https://docs.ironbee.ai/cli/advanced/job-queue
Inspect and manage the background queue that ships session data to the Collector.
IronBee buffers session events in a file-backed queue before sending them to the Collector. This happens automatically in the background and you rarely need to touch it. These commands are for diagnosing or recovering delivery when something stalls (e.g. you were offline and events piled up).
***
## Check queue status
Show queued job counts per session across the project:
```bash theme={null}
ironbee queue status
```
| Option | Description |
| --------------------- | ----------------------------------- |
| `--session ` | Limit to one session |
| `--project-dir ` | Target a specific project directory |
***
## Drain pending jobs
Process queued jobs synchronously, sending them to the Collector now instead of waiting for the background flush:
```bash theme={null}
ironbee queue drain
```
| Option | Description |
| --------------------- | ----------------------------------- |
| `--session ` | Drain just one session |
| `--project-dir ` | Target a specific project directory |
***
## Dead-letter queue
Jobs whose failures are **permanent** land in a **dead-letter** queue so they don't block healthy traffic. Transient failures (network errors, `429`, `5xx`) are retried on the next drain; anything else — an auth rejection (`401`/`403`, e.g. an expired credential) or any other `4xx` — is dead-lettered on the **first** attempt rather than retried pointlessly. Events dead-lettered under a bad credential won't auto-deliver later: fix the credential, then re-queue them with `dead-letter retry` (`dead-letter stats` shows the `auth:*` category). Inspect and recover them:
```bash theme={null}
ironbee queue dead-letter list # list failed entries
ironbee queue dead-letter stats # histogram of failure categories
ironbee queue dead-letter retry # re-queue one entry by its job id
ironbee queue dead-letter clear # empty the dead-letter file
```
| Command | Notable options |
| ---------------- | ------------------------------------------------------------- |
| `list` | `--session `, `--limit ` (default 50) |
| `stats` | `--session ` |
| `retry ` | `--session ` to force re-queue into a specific session |
| `clear` | `--all` to also remove rotated `dead-letter-*.jsonl` archives |
***
## Purge
Destructive cleanup of queue state. Use with care:
```bash theme={null}
ironbee queue purge --snapshots # delete all snapshot files, unprocessed
ironbee queue purge --sessions older-than=14d # remove queue dirs older than 14 days
```
| Option | Description |
| --------------------- | ----------------------------------------------------------------------------- |
| `--snapshots` | Delete all snapshot files across sessions **without** processing them |
| `--sessions ` | Remove old `queue/` subdirs — `older-than=` (e.g. `older-than=14d`) |
| `--project-dir ` | Target a specific project directory |
`purge` permanently drops queued data. `--snapshots` discards events that were never sent. Reach for `drain` first if you want to deliver pending events rather than throw them away.
All of these commands are available interactively in the [TUI](/cli/guides/interactive-mode) Queue area.
***
## What's next?
The `queue/` directory and everything else IronBee writes per session.
Check verdict status and validate sessions from the terminal.
# Privacy Mode
Source: https://docs.ironbee.ai/cli/advanced/privacy
Redact tool detail, screenshots, and recordings from the data the DevTools MCP servers ship to the Collector.
Privacy mode is a single cross-cutting switch that controls how much detail leaves your machine. When it's on, the [IronBee DevTools MCP servers](/cli/configuration/configuration#devtools-mcp-overrides) stop shipping potentially sensitive payloads tool, input/output detail, screenshots, and recordings to the [Collector](/cli/configuration/configuration#collector), across **every** verification cycle at once.
It's **opt-in and off by default**: a fresh install ships full detail so your Console sessions are as rich as possible. Turn it on when your code or browser sessions touch data you'd rather keep local.
***
## Enable or disable
```bash theme={null}
ironbee privacy enable # redact — stop shipping detail/artifacts
ironbee privacy disable # back to the default (full detail)
```
By default these write to the project config (committed, so the whole team inherits it). Use `-g`/`--global` to apply it across all your projects, or `--local` for a gitignored personal override that nobody else sees.
```bash theme={null}
ironbee privacy enable --global # redact everywhere on this machine
ironbee privacy enable --local # just you, not committed
```
Both commands re-render your installed client artifacts so the change lands in the DevTools MCP env. Narrow that re-render to one client with `--client ` (or `--client all`); by default it applies to the clients detected in the project.
Restart your editor or agent session after toggling privacy mode. The DevTools MCP servers read their config at session start, so the change takes effect on the **next** Claude Code / Cursor / Codex session — not the running one.
***
## What gets redacted
Enabling privacy mode injects two flags into every DevTools MCP server's environment:
| Flag | Effect when privacy is on |
| -------------------------------------------- | -------------------------------------------------------------------------------------- |
| `COLLECTOR_EVENTS_TOOL_DETAILS_ENABLE=false` | Drops tool **input/output detail** from the events the DevTools send to the Collector. |
| `COLLECTOR_ARTIFACTS_ENABLE=false` | Drops **screenshots and recordings** (browser and Android artifacts). |
You still get the structural signal which tools ran, verdicts, timing, and the session lifecycle all keep flowing but the heavy, potentially-sensitive payloads stay on your machine. Disabling privacy mode removes both flags, so the DevTools resume their default reporting.
This is a **DevTools-side** switch. The CLI's own event pipeline already whitelists tool input and strips tool responses before sending — shell commands, for example, are reduced to coarse binary/subcommand labels, and a command that can't be parsed confidently is dropped rather than guessed — so privacy mode is specifically about the extra detail and artifacts the DevTools MCP servers contribute.
***
## Tool-call reasons
IronBee asks its verifier and scenario sub-agents to annotate each DevTools call with a one-sentence **reason** — *why this call, what it expects to see* — which is recorded on the `tool_call` event and rendered on the Console timeline. It's a readability feature: it never changes what a tool does or whether a cycle passes.
Because it's model-authored free text, it's worth knowing exactly where it sits:
* **Privacy mode does not redact it.** The two flags above gate the DevTools' tool input/output detail and artifacts; the reason is a separate top-level field on the `tool_call` event that the CLI records itself.
* **There's no switch for it.** The channel that carries it (`TOOL_INPUT_EXTRAS_ENABLE`) is one of the IronBee invariants that always wins last when the DevTools MCP env is rendered, so an `ironbeeDevTools.env` override can't turn it off. If you need it gone, suspend the [Collector](/cli/configuration/configuration#collector) (`collector.enable: false`) — then nothing ships at all.
* **IronBee instructs the agent** to keep it to one sentence and to put no secrets, tokens, or personal data in it. The instruction lives in the sub-agent prompts, so it only reaches the modes that have one.
**Scope:** reasons come from the delegated sub-agents — Claude Code's verifier and scenario agents, and Codex in its default `sub-agent` mode. Where the main agent drives the tools itself (Cursor, and Codex in [`main-agent` mode](/cli/clients/codex#how-verification-is-delivered)) no annotation is requested, so no reason is recorded. On **Claude Code** there's one extra source: a `Bash` call the agent didn't annotate records the model's own `description` for the command (a field Claude Code already asks for) instead. Codex and Cursor shell tools carry no description.
***
## How it relates to telemetry and the collector
These three are independent knobs, privacy mode doesn't touch the other two:
| Control | Governs | Default |
| -------------------------------------------------------------------------------- | ------------------------------------------------------ | --------------------------- |
| **Privacy** (`privacy.enable`) | How much detail the DevTools send to *your* Collector | Off (full detail) |
| [**Telemetry**](/cli/advanced/telemetry) (`telemetry.enable`) | Anonymous PostHog product analytics for the CLI itself | On |
| [**Collector**](/cli/configuration/configuration#collector) (`collector.enable`) | Whether session data is sent to the Console at all | On when credentials are set |
To stop sending your session data entirely, suspend the Collector (`collector.enable: false`) rather than reaching for privacy mode, privacy mode trims *what* is sent, not *whether* anything is sent.
[VCS linkage](/cli/guides/issue-tracking#vcs-linkage-sessions-to-prs-and-issues) sends **repository and branch names** through the CLI's own pipeline, which privacy mode doesn't touch (it gates the DevTools payloads). If branch names in your repos can carry sensitive text, opt out of the linkage itself with `ironbee config set vcs.enable false`.
***
## Config equivalent
The command is a convenience wrapper around one [config key](/cli/configuration/configuration#privacy):
```bash theme={null}
ironbee config set privacy.enable true # same as: ironbee privacy enable
```
Both paths write the same `privacy.enable` value and re-render artifacts. The key is read from disk when the DevTools env is built, so the layer that wins (`local > project > global`) is the one that takes effect.
### Gate only one channel
Privacy mode flips both flags together. If you want, say, recordings off but tool detail on, set the [DevTools env override](/cli/configuration/configuration#devtools-mcp-overrides) your `ironbeeDevTools.env` values are applied *after* the privacy flags, so they win:
```json theme={null}
{
"privacy": { "enable": true },
"ironbeeDevTools": {
"env": { "COLLECTOR_EVENTS_TOOL_DETAILS_ENABLE": "true" }
}
}
```
Here screenshots and recordings stay redacted (privacy mode), but tool detail is allowed back through.
***
## What's next?
The other data toggle — anonymous CLI telemetry.
The `privacy.enable` key and the DevTools env overrides in full.
# Runtime Files
Source: https://docs.ironbee.ai/cli/advanced/runtime-files
What IronBee writes to disk which are global state, project config, and per-session runtime data.
IronBee stores its state in a few places: a global directory in your home folder, an `.ironbee/` directory inside each project, and a per-session runtime tree that by default lives **outside** the project. This page is a reference for what lives where, and what's safe to commit.
***
## Global (`~/.ironbee/`)
Machine-wide state, shared across all your projects:
| Path | What it holds |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `config.json` | Global config for your defaults across all projects. `ironbee login` writes your collector credentials here. |
| `projects.json` | The project inventory, the set of project paths IronBee is installed in. Powers `install --all` / `uninstall --all`. |
| `install-snapshots.json` | Transitional — backups of the statusline config older IronBee versions overwrote, so an upgrade or `uninstall` can restore your original. Written by nothing today and removed once every install has upgraded past the [statusline integration](/cli/clients/claude-code#removed-integrations). |
| `projects//` | **Per-session runtime data** for each project, in the default `external` [runtime location](#where-per-session-data-lives). `` is derived from the project's path, so each project gets its own folder. Holds the same `sessions//` tree described below. |
***
## Project (`/.ironbee/`)
Created by `ironbee install` in each project:
| Path | What it holds | Commit? |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| `config.json` | Project config, team settings, shared with the repo | ✅ Yes |
| `config.local.json` | Personal overrides, your machine only | ❌ Gitignored |
| `scenarios/` | Saved [verification scenarios](/cli/guides/scenarios) — one `.json` per scenario, plus a sibling `.cache.json` holding a step-ful scenario's captured `llm-action` replay scripts (both committed; never hand-edit the cache). A single flat store (older installs used per-cycle subfolders `bdt`/`ndt`/`pdt`/`bedt`/`adt`/`tdt`, still read for back-compat) | ✅ Yes |
| `VERIFICATION.md` | Area-specific [verification guidance](/cli/guides/verification-context), in any directory | ✅ Yes |
| `sessions//` | Per-session runtime data — **only when [`runtime.location`](#where-per-session-data-lives) is `in-project`** | ❌ Gitignored |
`ironbee install` adds five entries to your project's `.gitignore` automatically — `.ironbee/sessions/`, `.ironbee/config.local.json`, `.ironbee/codex-threads.json`, `.ironbee/vcs-cache.json`, and `.claude/settings.local.json`. Each is appended independently and only when it isn't already there, so an existing `.gitignore` is never rewritten. The last three are belt-and-suspenders: today the Codex thread map and the VCS cache live inside the `sessions/` folder (already covered by the first entry), and `.claude/settings.local.json` only exists on Claude Code — they're listed anyway so no machine-local state can slip into a commit on an older layout. The committed `config.json`, `scenarios/`, and any `VERIFICATION.md` files are what your teammates pick up when they run `ironbee install`.
***
## Where per-session data lives
The per-session runtime tree (`sessions//`) is controlled by [`runtime.location`](/cli/configuration/configuration#runtime):
| `runtime.location` | Per-session data lives at | Notes |
| ---------------------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `external` *(default)* | `~/.ironbee/projects//sessions//` | Kept **out of the project tree** so a project never accumulates a growing `sessions/` folder, even though it's gitignored. `` is a stable hash of the project's real path. |
| `in-project` | `/.ironbee/sessions//` | The legacy layout — runtime data sits beside your config, under the gitignored `sessions/` folder. |
Either way the contents of `sessions//` are identical — only the base directory differs. **Committed config (`config.json`, `config.local.json`, `scenarios/`, `VERIFICATION.md`) always stays in-project**, regardless of `runtime.location`. Switch layouts with `ironbee config set runtime.location in-project` or the [`IRONBEE_RUNTIME_LOCATION`](/cli/configuration/environment-variables#advanced) env var; it takes effect on the next session.
***
## Per-session (`sessions//`)
Each agent task gets its own directory, keeping concurrent sessions isolated (see [How verification works](/cli/concepts/how-it-works#session-isolation)):
| File | What it holds |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state.json` | The session's current state: phase, verification status, and the project dir it belongs to. |
| `agents//` | **Per-agent state** — see below. Each agent active in the session (the main conversation and every delegated sub-agent) gets its own partition. |
| `retries` | The current verification retry count. |
| `queue/` | Queue snapshots awaiting delivery, dead-letter entries, and the worker log. See [Job queue](/cli/advanced/job-queue). |
| `activity/` | One presence marker per participant in the open agent turn (the main agent and each delegated sub-agent). The turn closes only when the last participant leaves, so a backgrounded verifier can't split it. |
| `tool-results/` | Sidecar drop box for tool results the host truncated (a step-ful [scenario run](/cli/guides/scenarios) can exceed the host's tool-result limit). Normally empty — entries are consumed and deleted immediately. |
| `vcs-emitted.json` | Fingerprint of the last [`vcs_link`](/cli/guides/issue-tracking#vcs-linkage-sessions-to-prs-and-issues) emitted per turn, so an unchanged turn produces no repeat wire traffic. |
| `session.log` | Diagnostic log of the session's hook activity. |
### Per-agent state (`agents//`)
A session usually has more than one actor: the **main** agent, and the delegated sub-agents IronBee installs (`ironbee-verifier`, `ironbee-scenario`, `ironbee-issue-tracker`). Everything an individual agent writes is partitioned under its own `agents//` directory so concurrent writers — say a verifier running in the background while the main agent keeps working — never clobber each other's state. The `` is the host's opaque agent/thread id (only the main conversation is literally `main`); the human-readable agent name travels separately, as `cycle.json`'s `owner` and the `agent_name` on shipped events.
| File | What it holds |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `actions.jsonl` | That agent's event log: file edits, tool calls, and verification markers. The main conversation writes `agents/main/actions.jsonl`. |
| `cycle.json` | The agent's one open verification cycle (id, kind — gated or scenario — start time, trace id). |
| `verdict.json` | The agent's latest verdict (`status`, `checks`, `issues`, `fixes`). |
| `aux.json` | Auxiliary cycle flags (recording, conclusive checks, context injection, the [scenario](/cli/guides/scenarios) pause marker). |
| `steps.json` | The open [scenario step](/cli/guides/scenarios) stack. |
| `queue/jobs.jsonl` | The agent's live Collector queue producer file. |
| `fix.json` | *(main only)* The active fix cycle and the `/ironbee-verify fix` intent. |
Not every file is present in every session, and these persist after a session ends (they aren't auto-deleted). Sessions from older CLI versions kept `actions.jsonl` at the session root — that file is still merged in for a session in flight across the upgrade, but new writes all land under `agents/` (a pre-upgrade root `verdict.json` is no longer read; verdicts are looked up only under `agents//`). You rarely touch any of this directly: use [`ironbee status`](/cli/advanced/inspecting-sessions#ironbee-status) to read verdicts and [`ironbee queue`](/cli/advanced/job-queue) to inspect pending sends.
***
## What's next?
Every key you can set in the config files.
Overrides that take precedence over the config files.
# Telemetry
Source: https://docs.ironbee.ai/cli/advanced/telemetry
Manage the anonymous product telemetry the IronBee CLI and DevTools send.
IronBee collects anonymous usage telemetry (via PostHog) to improve the CLI. This is **separate** from the IronBee Collector pipeline that ships your session data — turning telemetry off doesn't change what your Console shows.
***
## Enable or disable
```bash theme={null}
ironbee telemetry disable # opt out
ironbee telemetry enable # opt back in (the default)
```
Disabling turns telemetry off in **both** the CLI and the IronBee DevTools MCP servers (it injects `TELEMETRY_ENABLE=false` into their environment), so one switch covers both sides.
By default these write to the project config. Use `-g`/`--global` for all your projects or `--local` for a gitignored personal override. The underlying key is [`telemetry.enable`](/cli/configuration/configuration#telemetry).
For a single shell or CI run, `IRONBEE_TELEMETRY=false` does the same thing without touching any config file — see [Environment variables](/cli/configuration/environment-variables#common).
Telemetry is about the CLI's own *anonymous* product analytics. To control how much of *your* session detail (tool input/output, screenshots, recordings) reaches the Collector, see [Privacy mode](/cli/advanced/privacy).
***
## How it relates to the other data switches
| Control | Governs | Default |
| -------------------------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------- |
| **Telemetry** (`telemetry.enable`) | Anonymous product analytics for the CLI and DevTools themselves | On |
| [**Privacy**](/cli/advanced/privacy) (`privacy.enable`) | How much detail the DevTools send to *your* Collector | Off (full detail) |
| [**Collector**](/cli/configuration/configuration#collector) (`collector.enable`) | Whether session data is sent to the Console at all | On when credentials are set |
***
## What's next?
The `telemetry.enable` key in full.
Redact tool detail, screenshots, and recordings from the data the DevTools MCP servers ship to the Collector.
# Claude Code
Source: https://docs.ironbee.ai/cli/clients/claude-code
How IronBee integrates with Claude Code - slash commands, rules, hooks, tools, the verifier sub-agent, and workspace trust.
When you run `ironbee install` in a project where [Claude Code](https://docs.anthropic.com/en/docs/claude-code) is detected, IronBee writes everything Claude needs to verify your agent's work. This page covers what gets installed and the agent-facing commands.
***
## What gets installed
| File | What it does |
| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `.claude/settings.json` | Registers IronBee's hooks and the permissions the agent needs |
| `.claude/skills/ironbee-verification.md` | The verification skill the agent follows (enforce mode) |
| `.claude/rules/ironbee-verification.md` | The always-on verification rule that enforces the gate (enforce mode) |
| `.claude/commands/ironbee-verify.md` | The `/ironbee-verify` slash command |
| `.claude/commands/ironbee-{manage,search,run,sync}-scenario.md` | The [saved-scenario](/cli/guides/scenarios) slash commands |
| `.claude/agents/ironbee-scenario.md` | The **scenario sub-agent** that authors, searches, and re-runs [saved scenarios](/cli/guides/scenarios) (like the verifier, it owns the scenario tools and can't edit your code) |
| `.claude/agents/ironbee-verifier.md` | The **verifier sub-agent** that actually runs the cycles. A single **`ironbee-devtools`** MCP server — it serves every enabled cycle's tools (`bdt_*` / `ndt_*` / `pdt_*` / `bedt_*` / `adt_*` / `tdt_*`), plus the shared `ibdt_*` family (batch execute, scenario run/CRUD, o11y trace helpers, issue-tracker tools), under one entry — is rendered **inline** into this file so it's scoped to the sub-agent. It also gets read-only `Read` / `Grep` / `Glob` (to understand the change) but **no edit tools** |
| `.claude/commands/ironbee-issue-track.md` | The `/ironbee-issue-track` command — written only when an [issue tracker](/cli/guides/issue-tracking) is connected |
| `.claude/agents/ironbee-issue-tracker.md` | The **issue-tracker sub-agent** `/ironbee-issue-track` delegates to (Jira/Linear tools scoped to it; GitHub driven via `gh`) — written only when an issue tracker is connected |
| `.claude/settings.local.json` | The [auto-mode allowlist carve-out](#auto-mode-and-the-verifier) for the verifier — written only when verification is active and `claude.autoModeAllowlist.enable` isn't `false`. Merged into any existing local settings |
These are merged into your existing Claude settings, not overwritten.
The `ironbee-devtools` MCP server lives inside the verifier sub-agent (above), not in a top-level `.mcp.json`. See [Verification runs in a sub-agent](#verification-runs-in-a-sub-agent) below.
Restart Claude Code after installing so it picks up the new hooks, commands, and MCP server.
***
## Slash commands
IronBee installs the `/ironbee-verify` slash command, which the agent (or you) can invoke directly in Claude Code:
### ironbee-verify
Run a verification cycle for the current changes. By default it exercises the areas affected by what changed. You can also pass a **custom scenario** describing exactly what to verify — either inline or as a path to a file:
```bash theme={null}
/ironbee-verify # default — exercise the changed pages/endpoints
/ironbee-verify log in as admin, open /billing, # inline scenario — verify exactly this flow
and confirm the invoice total updates
/ironbee-verify ./scenarios/checkout.md # a scenario file (any location, any format)
```
When a scenario is supplied it is **authoritative**: it replaces the default "exercise the changed pages" guidance, and the verifier drives precisely the flows, states, and endpoints it names. A scenario *file* is read at run time, so you can keep reusable test scripts in your repo. The completion gate is unchanged — every active cycle's required tools must still run for a `pass`.
An optional leading word picks what happens on a fail: the default is **verify-only** (report the verdict and stop), while a leading `fix` makes the agent fix the issues and re-verify until it passes — `/ironbee-verify fix`. See [Verify-only vs. fix mode](/cli/guides/verification#verify-only-vs-fix-mode).
`/ironbee-verify` **delegates to the `ironbee-verifier` sub-agent** rather than verifying in the main conversation — see [Verification runs in a sub-agent](#verification-runs-in-a-sub-agent).
### Scenario commands
IronBee also installs `/ironbee-manage-scenario`, `/ironbee-search-scenario`, `/ironbee-run-scenario`, and `/ironbee-sync-scenario` for authoring, finding, running, and repairing [saved verification scenarios](/cli/guides/scenarios). Like `/ironbee-verify`, they delegate to a dedicated sub-agent (`ironbee-scenario`). They're installed in enforce and assist modes, alongside the verifier.
### ironbee-issue-track
When an [issue tracker is connected](/cli/guides/issue-tracking) (Jira, Linear, or GitHub Issues), install adds `/ironbee-issue-track` — read a ticket, verify your changes against its acceptance criteria, and report the evidence-backed result to the tracker. It delegates to its own `ironbee-issue-tracker` sub-agent. See [Issue Tracking](/cli/guides/issue-tracking#using-it-ironbee-issue-track) for the modes.
### Assist mode: commands are user-only
In [assist mode](/cli/guides/verification#assist-mode-default) — which is manual-trigger-only by design — install marks every IronBee command (`/ironbee-verify`, the four scenario commands, and `/ironbee-issue-track` when present) with `disable-model-invocation: true`. You can still type them, but the model can't auto-invoke them and their descriptions stop costing context tokens (they show as *user-only* in Claude's `/skills` viewer). The sub-agents' descriptions likewise switch to a **non-proactive stance** in assist mode, so the model doesn't spawn the verifier or scenario agent on its own — a user-driven `/ironbee-verify` still spawns it explicitly. Enforce mode keeps auto-invocation on, since the verification mandate may route the model through the command.
***
## Verification runs in a sub-agent
On Claude Code, the main agent does **not** drive the devtools tools itself. They're scoped to a dedicated `ironbee-verifier` sub-agent: a single `ironbee-devtools` MCP server — serving every enabled cycle — is rendered inline into `.claude/agents/ironbee-verifier.md`. When verification is needed — automatically at the gate, or manually via `/ironbee-verify` — the main agent **spawns the verifier**, which runs every active cycle's tools and submits the verdict, then hands back a short summary.
This keeps the heavy devtools output (DOM snapshots, console logs, screenshots) in the sub-agent's context instead of flooding the main conversation. The sub-agent shares the parent session, so its verification events, tool calls, and verdict all land in the same session timeline — each tagged with its `agent_name` so the Console shows who did what.
By default the verifier runs on the **same model as the main conversation**. To pin it to a specific (e.g. cheaper or faster) model, set [`verification.model`](/cli/configuration/configuration#verification) — for example `ironbee verification model sonnet --client claude`. See [Verification → Picking the verifier's model](/cli/guides/verification#picking-the-verifier-model).
Codex delegates the same way (a per-project verifier agent). **Cursor** keeps the main agent driving the tools directly — its sub-agents can't share a session, so there's no verifier sub-agent there.
***
## How verification is enforced
IronBee installs a **Stop hook** that fires when the agent tries to finish a task. If code files changed, the hook runs verification automatically (spawning the verifier sub-agent, the equivalent of `/ironbee-verify`) and blocks completion until every active cycle passes. The verifier navigates pages, exercises the affected paths, and submits a verdict; on failure the main agent fixes the issues and re-verifies, up to your [`maxRetries`](/cli/configuration/configuration#core-options) limit.
When the agent fixes something after a failed verdict, it can record what it repaired with `ironbee hook record-fix` so the next passing verdict describes the fix. If it doesn't, IronBee fills in the `fixes` from the files that changed since the failure — so a delegated verifier that didn't author the edit never blocks on a missing fix description.
***
## Permissions
The permissions IronBee writes are scoped to what's actually active. When any cycle is enabled, it grants a single devtools permission, `mcp__ironbee-devtools__*` — the one compose server carries every enabled cycle's tools, matched against the verifier sub-agent's inline tools — plus `Bash(ironbee *)` for the agent's CLI calls. (Any stale per-cycle permissions from an older CLI, like `mcp__browser-devtools__*`, are stripped on every install.) Switching to [monitoring-only mode](/cli/guides/verification#verification-modes) removes all IronBee permissions (and the verifier sub-agent) entirely. [Assist mode](/cli/guides/verification#assist-mode-default) keeps the permissions, the verifier sub-agent, and its MCP server (so manual verification still works) but drops the always-on skill and rule.
***
## Auto mode and the verifier
Recent Claude Code releases (2.1.176+) ship an **auto mode** with a host-side "Content Integrity" classifier that inspects sub-agent hand-offs and prepends a security warning to ones it judges fabricated. It **false-positives** on IronBee's legitimate verdicts: the verifier's devtools calls happen earlier in the cycle and aren't re-shown in the hand-off summary the classifier reviews, so a real, evidence-backed verdict can look made-up to it.
To keep verification working under auto mode, IronBee writes **one narrow allowlist rule** into `.claude/settings.local.json`, keyed to the exact verdict-submission command. It relaxes **only** the Content Integrity check for that command — every other auto-mode protection (data exfiltration, production reads, self-modification, …) stays fully in force, and IronBee's own completion gate still independently confirms the required tools actually ran.
* Written **only** when verification is active (enforce or assist), and it's **inert** unless the host is actually in auto mode.
* Lives in `settings.local.json` (the local layer, gitignored), merges safely alongside anything else there, and is removed on uninstall or when you switch to monitoring-only.
* Opt out with `ironbee config set claude.autoModeAllowlist.enable false` (takes effect on your next `ironbee install`). See [`claude.autoModeAllowlist.enable`](/cli/configuration/configuration#claude-claude-code-only).
***
## Workspace trust
Claude Code 2.1.x **ignores a project's committed `permissions.allow`** — the `mcp__ironbee-devtools__*` and `Bash(ironbee *)` entries IronBee writes into `settings.json` — until the workspace is **trusted**. And once you've dismissed Claude's onboarding, the trust dialog no longer re-appears, so those entries would stay silently disabled and the agent would get prompted on every devtools or `ironbee` call.
To avoid that, `ironbee install` marks the project trusted in Claude Code's machine-global `~/.claude.json` (it flips `projects[""].hasTrustDialogAccepted` to `true`) when verification is active and the flag isn't already set.
* This is the **one machine-global file** IronBee writes — every other Claude artifact is a per-project `.claude/*` file.
* **Best-effort, idempotent, and non-clobbering:** it only ever flips a missing or `false` flag to `true`, preserves every other entry and key in the file, and never creates `~/.claude.json` if it's absent (Claude writes it on first run).
* It is **not** reverted on uninstall — un-trusting a workspace could surprise you if you rely on the trust elsewhere.
* Opt out with `ironbee config set claude.trustWorkspace.enable false`. See [`claude.trustWorkspace.enable`](/cli/configuration/configuration#claude-claude-code-only).
***
## Removed integrations
IronBee 0.42 removed the Claude-only *insights* integrations — the **statusline wrapper** (`session_status` events), the **local OTEL collector daemon** (`session_context` context-usage events), and the **OAuth-token read** (`ironbee claude oauth-access`) — along with the whole `ironbee claude` command group. Verification, session lifecycle, tool calls, file changes, verdicts, and [VCS linkage](/cli/guides/issue-tracking#vcs-linkage-sessions-to-prs-and-issues) are unaffected.
Upgrading cleans up after itself: the re-render restores whatever statusline you had before IronBee wrapped it (or strips ours so a lower settings layer re-emerges), removes the OTEL env block from `settings.json`, and deletes the transient `.ironbee/otel/` directory. The `statusLine.*`, `otel.*`, and `claude.oauthAccess.*` config keys are inert and can be dropped from your config files.
***
## What's next?
The same integration for Cursor.
The same integration for Codex.
# Codex
Source: https://docs.ironbee.ai/cli/clients/codex
How IronBee integrates with OpenAI Codex CLI - guidance files, hooks, the $ironbee-verify skill, MCP servers, and Codex-specific behavior.
When you run `ironbee install` in a project where [Codex CLI](https://github.com/openai/codex) is detected, IronBee wires up the hooks, guidance, and tools Codex needs to verify your agent's work. The integration mirrors [Claude Code](/cli/clients/claude-code) and [Cursor](/cli/clients/cursor), with a few Codex-specific details covered below.
IronBee supports the **interactive Codex CLI** (the TUI you get from running `codex`). The non-interactive `codex exec` mode is out of scope. Codex [doesn't fire hooks there](https://github.com/openai/codex/issues/24211), so there's nothing for IronBee to gate on.
***
## What gets installed
IronBee writes Codex's active config **per project** (under `/.codex/`) so each project gets its own hooks, MCP server, and verifier — no machine-global "last install wins". These files are committed alongside your `.claude/*` and `AGENTS.md`.
| File | What it does |
| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/.codex/hooks.json` | Registers IronBee's lifecycle hooks |
| `/.codex/config.toml` | Enables Codex's hook runtime (`[features] hooks = true`) and registers the verifier agent (`[agents.ironbee-verifier]`) |
| `/.codex/agents/ironbee-verifier.toml` | The **verifier sub-agent** that runs the cycles. A single `[mcp_servers.ironbee-devtools]` block (serving every enabled cycle's tools) lives here, scoped to the sub-agent |
| `/AGENTS.md` | The always-applied verification rule, written into an IronBee-delimited block (`` … ``) |
| `/.agents/skills/ironbee-verification/SKILL.md` | The verification skill the agent follows |
| `/.agents/skills/ironbee-verify/SKILL.md` | The `$ironbee-verify` skill you can invoke by hand |
| `/.codex/agents/ironbee-scenario.toml` | The **scenario sub-agent** for [saved scenarios](/cli/guides/scenarios) (registered like the verifier, with the same read-only sandbox) |
| `/.agents/skills/ironbee-{manage,search,run,sync}-scenario/SKILL.md` | The `$ironbee-{manage,search,run,sync}-scenario` skills |
| `/.codex/agents/ironbee-issue-tracker.toml` + `/.agents/skills/ironbee-issue-track/SKILL.md` | The **issue-tracker sub-agent** and its `$ironbee-issue-track` skill — written only when an [issue tracker](/cli/guides/issue-tracking) is connected (in `main-agent` mode there's no agent; the skill drives the tools inline) |
IronBee's entries are **merged** into your existing Codex config and `AGENTS.md`. Your own hooks, MCP servers, and guidance outside the IronBee block are never touched. On uninstall, only the IronBee block and skills are removed. Your user-level `~/.codex/config.toml` still applies — for example its top-level `model`.
The layout above is the default **`sub-agent`** delivery mode. In **`main-agent`** mode there's no `ironbee-verifier.toml` — the `ironbee-devtools` MCP server is registered at the session level in `config.toml` and the skill/rule/command are inlined instead of delegating. See [How verification is delivered](#how-verification-is-delivered).
Restart Codex after installing so it picks up the new hooks, guidance, and MCP servers. The first time, Codex shows a one-time **"hooks need review"** prompt (its safety gate for project-level hooks) — run `/hooks` to approve. IronBee writes `[features] hooks = true` for you; without it Codex parses hooks but never dispatches them.
***
## The \$ironbee-verify skill
Codex has no user-defined slash commands, so IronBee's manual verification trigger is exposed as a **skill you mention by name**. Type `$ironbee-verify` in the Codex prompt to run a verification cycle for the current changes. As with [`/ironbee-verify` in Claude Code](/cli/clients/claude-code#slash-commands), you can pass a **custom scenario** — inline text or a path to a scenario file — that defines exactly what to verify:
```bash theme={null}
$ironbee-verify # default — exercise the changed pages/endpoints
$ironbee-verify check that the cart total # inline scenario
recalculates after removing an item
$ironbee-verify ./scenarios/checkout.md # a scenario file
```
When a scenario is supplied it is authoritative and replaces the default "exercise the changed paths" flow; the completion gate is unchanged. As in Claude Code, an optional leading `fix` switches the default verify-only run into a fix-and-re-verify loop (`$ironbee-verify fix`) — see [Verify-only vs. fix mode](/cli/guides/verification#verify-only-vs-fix-mode). Only the invocation syntax differs from Claude Code.
The same mention syntax applies to the other commands — `$ironbee-{manage,search,run,sync}-scenario` for [saved scenarios](/cli/guides/scenarios) and, when an [issue tracker is connected](/cli/guides/issue-tracking), `$ironbee-issue-track`.
Using the **GitHub Issues** integration on Codex? Its `gh` calls run inside Codex's tool sandbox, which blocks outbound network by default — enable `[sandbox_workspace_write] network_access = true` if `gh issue view` can't reach `api.github.com`. Install prints a reminder; Jira and Linear are unaffected (their tools run outside the sandbox). See [Issue Tracking → GitHub Issues](/cli/guides/issue-tracking#github-issues).
***
## How verification is enforced
IronBee registers a **Stop hook** that fires when the agent tries to finish a task. If code files changed, the hook runs verification automatically and blocks completion until every active cycle passes. By default, like Claude Code, Codex **delegates verification to the `ironbee-verifier` sub-agent** — the devtools tools are scoped to that agent (in `/.codex/agents/ironbee-verifier.toml`), so the main conversation never carries the heavy devtools output. The verifier navigates the affected paths and submits a verdict; on failure the main agent fixes the issues and re-verifies, up to your [`maxRetries`](/cli/configuration/configuration#core-options) limit. You can pin the verifier's model with [`verification.model`](/cli/guides/verification#picking-the-verifier-model).
Enforcement only blocks task completion in [enforce mode](/cli/guides/verification#enforce-mode) (`ironbee verification auto enable`). In the default **assist** mode the verifier and `$ironbee-verify` are installed but nothing gates completion — see [Verification modes](/cli/guides/verification#verification-modes).
Codex's Stop hook returns a `decision: "block"` with a continuation reason, which pushes the agent back into the verification loop, the same enforcement semantics as Claude Code.
Codex exposes file edits through its single `apply_patch` tool, so IronBee gates edits on that instead of `Write`/`Edit`. File changes are recorded per patch, with the operation (create / update / delete) read from the patch body.
***
## How verification is delivered
By default Codex runs the cycle in the **`ironbee-verifier` sub-agent** (the `sub-agent` delivery mode), exactly like Claude Code — the devtools MCP server is scoped to that agent and the heavy output stays out of the main conversation. If Codex's sub-agent machinery regresses, you can fall back to driving the tools from the **main agent** instead:
```bash theme={null}
ironbee codex verifier mode main-agent # main agent drives the devtools tools directly
ironbee codex verifier mode sub-agent # back to the default delegated verifier
```
| Mode | What changes |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`sub-agent`** *(default)* | The `ironbee-verifier` custom agent owns the devtools tools (per-agent MCP in `ironbee-verifier.toml`); a slim delegation skill/rule/command tell the main agent to hand off. Heavy devtools output stays in the sub-agent. |
| **`main-agent`** | No verifier sub-agent. The `ironbee-devtools` MCP server is registered at the **session** level (`[mcp_servers.ironbee-devtools]` in `config.toml`) and the main agent drives its tools itself, with an inline (non-delegating) skill/rule/command — the same shape Cursor uses. |
Switching re-renders the Codex client. The choice maps to the [`codex.verifier.mode`](/cli/configuration/configuration#codex-codex-cli-only) config key; `verification.model` still applies in `sub-agent` mode and is a no-op in `main-agent` mode (there's no sub-agent to spawn).
***
## Codex-specific behavior
A few details differ from the other clients, all handled automatically:
* **No `SessionEnd` hook.** Codex doesn't expose one, so IronBee treats every Stop as a checkpoint and writes a session-end snapshot there (the Collector keeps the latest). Quitting Codex with `/quit` fires no hooks.
* **Interrupt recovery.** Pressing **Esc** to interrupt the agent doesn't fire a Stop hook in Codex ([#22858](https://github.com/openai/codex/issues/22858)). IronBee reconciles the interrupted activity on your next prompt, so the session timeline stays accurate.
* **Sandbox grant for external runtime.** With the default [`external` runtime location](/cli/advanced/runtime-files#where-per-session-data-lives), per-session data lives at `~/.ironbee/projects/` — outside the Codex workspace sandbox. So the agent's verdict writes (`ironbee hook submit-verdict` / `record-fix`) don't hit an approval prompt, IronBee adds a narrow `[sandbox_workspace_write].writable_roots` grant for `~/.ironbee/projects` to `config.toml` (the global `config.json` and collector credentials under `~/.ironbee` stay out of reach). It's reconciled away in `in-project` or monitoring mode and removed on uninstall.
* **Config is project-level.** Hooks, the MCP server, and the verifier are written per project (`/.codex/`), so each repo gets its own setup and there's no machine-global conflict. The devtools live inside the verifier agent (`/.codex/agents/ironbee-verifier.toml`) under a single `[mcp_servers.ironbee-devtools]` block whose `COMPOSE_PLATFORMS` lists the enabled cycles — browser on by default, node / python / backend / android / terminal added when you enable those cycles. A model must be resolvable for the verifier sub-agent: it inherits your `~/.codex/config.toml` `model` unless you pin [`verification.model`](/cli/guides/verification#picking-the-verifier-model); if neither supplies one, install warns you.
Session lifecycle, tool calls, file changes, verdicts, and [VCS linkage](/cli/guides/issue-tracking#vcs-linkage-sessions-to-prs-and-issues) flow to the Collector exactly as they do on the other clients.
***
## What's next?
The same integration for Claude Code.
The same integration for Cursor.
# Cursor
Source: https://docs.ironbee.ai/cli/clients/cursor
How IronBee integrates with Cursor - slash commands, rules, hooks, tools, and MCP activation.
When you run `ironbee install` in a project where [Cursor](https://cursor.com) is detected, IronBee writes the hooks, rules, and tools Cursor needs to verify your agent's work. The integration mirrors [Claude Code](/cli/clients/claude-code), with a few Cursor-specific details, including one manual step to activate the MCP server.
***
## What gets installed
| File | What it does |
| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `.cursor/hooks.json` | Registers IronBee's lifecycle hooks |
| `.cursor/skills/ironbee-verification.md` | The verification skill the agent follows |
| `.cursor/skills/ironbee-verify/SKILL.md` | The `/ironbee-verify` command |
| `.cursor/skills/ironbee-{manage,search,run,sync}-scenario/SKILL.md` | The [saved-scenario](/cli/guides/scenarios) commands (the main agent drives the scenario tools — Cursor has no sub-agent) |
| `.cursor/skills/ironbee-issue-track/SKILL.md` | The `/ironbee-issue-track` command — written only when an [issue tracker](/cli/guides/issue-tracking) is connected (the main agent drives the tracker tools) |
| `.cursor/rules/ironbee-verification.mdc` | An always-applied rule (`alwaysApply: true`) |
| `.cursor/mcp.json` | The devtools MCP server — a single **`ironbee-devtools`** entry that serves every enabled cycle's tools (`bdt_*` / `ndt_*` / `pdt_*` / `bedt_*` / `adt_*` / `tdt_*`), plus the shared `ibdt_*` family (batch execute, scenario run/CRUD, o11y trace helpers, issue-tracker tools) |
| `.cursor/permissions.json` | An allowlist so the agent isn't prompted on every devtools call or `ironbee` command (a single `ironbee-devtools:*` + `ironbee` in the terminal allowlist) |
These are merged into your existing Cursor config, not overwritten.
Unlike Claude Code and Codex, Cursor **doesn't use a verifier sub-agent** — the main agent drives the devtools tools directly. (Cursor's sub-agents run in a separate conversation that can't share the verification session, so there's nowhere to delegate to.) The [`verification.model`](/cli/configuration/configuration#verification) setting is therefore a no-op for Cursor.
***
## Activate the MCP server
Cursor sometimes doesn't pick up MCP servers added via `mcp.json` automatically. After installing, you usually need to activate it by hand.
After running `ironbee install`:
1. **Restart Cursor** so it loads the new hooks and MCP config.
2. Go to **Settings → Tools & MCP** and confirm the **`ironbee-devtools`** server is listed and on (it carries the tools for every cycle you enabled).
3. If the server shows as enabled but its tools aren't available, toggle it off and back on.
This is a known Cursor limitation: MCP servers added via config sometimes need a manual nudge.
***
## Slash commands
The `/ironbee-verify` command from Claude Code is available in Cursor too:
* **`/ironbee-verify`** run a verification cycle for the current changes. You can pass a **custom scenario** — inline text or a path to a scenario file — that defines exactly what to verify; when supplied it replaces the default "exercise the changed paths" flow. An optional leading `fix` switches it from the default verify-only behavior into a fix-and-re-verify loop — see [Verify-only vs. fix mode](/cli/guides/verification#verify-only-vs-fix-mode).
See [Claude Code → Slash commands](/cli/clients/claude-code#slash-commands) for the full breakdown; it behaves the same in Cursor, except Cursor's main agent runs the verification itself rather than delegating to a sub-agent. The same goes for `/ironbee-issue-track` when an [issue tracker is connected](/cli/guides/issue-tracking).
Cursor's CLI can try to hand an IronBee skill to a **sub-agent** via its `Task` tool — but a Cursor sub-agent runs in a separate conversation that can't share the verification session, so its evidence would silently never register. IronBee installs a hook that denies exactly those delegations (your own unrelated sub-agents pass through), keeping the verify, scenario, and issue-track skills on the main agent where their evidence counts.
***
## How verification is enforced
Cursor's stop hook can't hard-deny completion the way Claude's can, so IronBee uses Cursor's `followup_message` mechanism: when verification fails, it auto-submits a new prompt that pushes the agent back into the verification loop, mechanically preventing the task from finishing until it passes (up to Cursor's `loop_limit`, default 5).
Restart Cursor after installing, and remember the MCP activation step above; without it the agent won't have the devtools tools it needs to verify.
Cursor can also power IronBee's **LLM suggestions** — the `s` "suggest" key in the install platform picker and the [`ironbee checks suggest`](/cli/guides/verification#let-ironbee-suggest-your-checks) command — by running a one-shot headless prompt via `cursor-agent`. When Claude Code or Codex is also present, IronBee prefers those (`claude > codex > cursor`).
***
## What Cursor sessions ship
Cursor sessions ship the same events as Claude Code and Codex — session lifecycle, agent turns, tool calls, file changes, verification cycles, and verdicts — through the [Collector](/cli/configuration/configuration#collector).
IronBee also does one read-only lookup in Cursor's local SQLite store (`state.vscdb`): the signed-in user's cached email, so events can be attributed to you in the Console. Nothing is ever written there, and the read degrades silently when no SQLite driver is available. Point it elsewhere with [`IRONBEE_CURSOR_USER_DIR`](/cli/configuration/environment-variables#advanced) if your Cursor install isn't in the standard per-OS location.
IronBee 0.42 removed the Cursor usage-API integration (`ironbee cursor api-access`) that used to enrich sessions with per-request tokens and cost from `api2.cursor.sh`, together with the rest of the insights layer. The `cursor.apiAccess.*` config keys are inert and can be dropped from your config files.
***
## What's next?
The same integration for Claude Code.
The same integration for Codex.
# How Verification Works
Source: https://docs.ironbee.ai/cli/concepts/how-it-works
The completion gate, verification cycles, verdicts, and retries what happens when your agent finishes a task.
IronBee's core idea is simple: **code isn't done until it's verified.** This page explains the mechanism behind that: how IronBee intercepts task completion, what the agent has to do to pass, and what happens when it doesn't.
***
## The completion gate
When you run `ironbee install`, IronBee registers a **completion hook** with your AI client (the `Stop` hook in Claude Code and Codex, the `stop` hook in Cursor). It fires when the agent tries to finish a task.
If the agent changed code files, the hook runs verification before letting the task complete:
```mermaid theme={null}
flowchart TD
A[Agent edits code] --> B[Agent tries to finish]
B --> C{IronBee completion gate}
C -->|all active cycles pass| D([Task completes])
C -->|any cycle fails| E[Agent fixes the issues]
E --> B
```
If no code files changed (docs, config, etc.), the gate doesn't trigger.
***
## Verification cycles
A **cycle** is one pass of testing against a real surface. IronBee has six, and any combination can be active for a project:
| Cycle | Exercises the change through… |
| -------- | --------------------------------------------------------------------------------------------- |
| Browser | A real browser, navigation, screenshots, console, accessibility |
| Node | The Node.js V8 inspector, probes, runtime snapshots, and outbound HTTP capture |
| Python | A running Python process over debugpy/DAP, probes, thread dumps, and outbound HTTP capture |
| Backend | Real protocol calls HTTP, gRPC, GraphQL, WebSocket |
| Android | An emulator over ADB taps, swipes, screenshots, UI snapshots, Logcat, HTTP capture |
| Terminal | A pseudo-terminal (PTY) spawn the CLI / REPL / TUI, send input, capture output and exit codes |
When a task completes, **every active cycle whose patterns match the changed files must pass in the same verification attempt**. They run in parallel, not one task at a time. See [Verification](/cli/guides/verification) for choosing which cycles are active.
***
## The verdict
To pass a cycle, the agent exercises the affected paths with that cycle's tools and submits a **verdict**, its assessment of whether the change works:
```json theme={null}
{
"status": "pass",
"name": "checkout total updates",
"checks": [ ... ],
"issues": [ ... ],
"fixes": [ ... ]
}
```
IronBee doesn't take `status: "pass"` at face value. Each cycle defines the tools that must appear on the wire before a pass counts: required tools (all-of) and alternative evidence paths (any-of). If the agent claims success without actually using the tools, the gate overrides the verdict to **fail**. This is what stops an agent from declaring "it works" without testing.
`name` is an optional short label (3–6 words) for what the cycle actually verified. It isn't part of the verdict itself — IronBee lifts it off the payload and stamps it on the cycle as it closes. See [What a cycle records](#what-a-cycle-records) below.
***
## What a cycle records
Beyond the verdict, every verification cycle carries three pieces of metadata so the Console can describe a run at a glance:
| | Where it comes from | Trusted because |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Name** | The agent names the cycle when it opens (`ironbee hook verification-start --name`) and may rename it on the verdict's optional `name` field. The closing name wins — the agent knows more once it's done. A [saved-scenario](/cli/guides/scenarios) run is named after its scenario automatically. | Display only. It never gates anything, so a bad label costs nothing but clarity. |
| **Platforms** | Which cycles were *enabled* when the cycle opened, and which ones it *actually exercised* by the time it closed. | The exercised set is derived **mechanically** from the cycle's own recorded tool calls, never from what the agent claims. A cycle that drove no platform tools records none. |
| **Reason** | A one-sentence "why this call". IronBee's [delegated sub-agents](#who-drives-the-tools) attach one to every verification tool call; on Claude Code a `Bash` call without one falls back to the model's own command `description`. Where the main agent drives the tools directly (Cursor, Codex `main-agent`) none is requested. | Display only — it annotates the timeline, it never changes what a tool does or whether a cycle passes. |
The per-call **reason** is model-authored free text that ships to the Collector alongside the tool call. IronBee instructs the agent to keep it to one sentence and to put no secrets, tokens, or personal data in it — but it is not redacted by [privacy mode](/cli/advanced/privacy), which gates DevTools payloads rather than this field, and there's no separate switch for it. See [Privacy mode → Tool-call reasons](/cli/advanced/privacy#tool-call-reasons).
***
## Retries
A failed verdict sends the agent back to fix the issues and verify again. The [`maxRetries`](/cli/configuration/configuration#core-options) limit (default **3**) caps this loop: once it's hit, the agent is allowed to complete the task **but must report the unresolved issues** rather than silently pass. One counter covers all active cycles.
***
## Who drives the tools
On **Claude Code** and **Codex**, the main agent doesn't run the devtools tools itself — it **delegates to a dedicated `ironbee-verifier` sub-agent** that owns them. This keeps the heavy devtools output (DOM, console, screenshots) out of the main conversation while still recording everything to the same session. **Cursor** has no sub-agent surface, so its main agent verifies directly. See [Verification → How verification runs](/cli/guides/verification#how-verification-runs-the-verifier-sub-agent).
Every agent-bound event the session ships — tool calls, file changes, verification start/end, verdicts, check results — carries an **`agent_name`** (`main` for the top-level conversation, or the sub-agent's name like `ironbee-verifier`), so the Console can show exactly *who* did what within one session. Each agent's runtime state is likewise kept in its own partition on disk (see [Runtime files → Per-agent state](/cli/advanced/runtime-files#per-agent-state-agentsagentid)), so a delegated verifier and the main agent never race on the same files.
***
## Default vs custom scenarios
By default the gate verifies only the areas affected by what changed. You (or the agent) can instead pass a **custom scenario** to [`/ironbee-verify`](/cli/clients/claude-code#slash-commands) — inline text or a path to a scenario file — to specify exactly which flows, states, and endpoints to exercise. See [Custom verification scenarios](/cli/guides/verification#custom-verification-scenarios).
***
## Enforce, assist, and monitoring-only
The blocking gate described above is **enforce mode**. It's one of three [verification modes](/cli/guides/verification#verification-modes), and it's **opt-in** — a fresh install defaults to **assist**:
* **Assist** *(default)* (`ironbee verification auto disable`) - the `/ironbee-verify` command, the verifier sub-agent, and the devtools MCP server stay installed so the agent (or you) can verify on demand, but no gate ever blocks completion. Every manual cycle is still recorded to the Collector. Turn on full enforcement with `ironbee verification auto enable`.
* **Monitoring-only** (`ironbee verification disable`) - none of the machinery is installed. The agent works unblocked, but session lifecycle, tool calls, and timing still flow to the Collector. Useful for measuring baseline behavior before turning verification on.
***
## Area-specific guidance
Teams can steer *how* the agent verifies a given part of the codebase by committing [`.ironbee/VERIFICATION.md`](/cli/guides/verification-context) files. When a change touches that area, IronBee injects the matching guidance into the agent's context as it starts verifying: advisory instructions layered on top of the standard flow, resolved hierarchically from the changed paths.
***
## Session isolation
Every agent task runs as its own **session**, tracked independently in a per-session `sessions//` directory (by default under `~/.ironbee/projects//`, outside the project tree — see [Runtime files](/cli/advanced/runtime-files#where-per-session-data-lives)). Concurrent sessions, even in the same project, keep separate event logs, verdicts, and retry counters, so they never interfere. See [Runtime files](/cli/advanced/runtime-files) for what's stored per session.
***
## What's next?
Install, remove, track, and update IronBee across your projects.
Choose which cycles run and how enforcement behaves.
# Configuration
Source: https://docs.ironbee.ai/cli/configuration/configuration
Tune IronBee's verification behavior with layered global, project, and local config.
IronBee works out of the box, and most projects never need to touch config. When you do want to fine-tune *which* files get verified, change retry limits, or point at a self-hosted collector, this page is the reference.
You can edit settings two ways: the `ironbee config` command (recommended, since it validates and re-applies changes for you) or by editing the JSON files directly.
***
## Config layers
Settings are read from three files and **deep-merged**. Higher layers override lower ones:
| Layer | File | Use for |
| ------- | -------------------------------------- | ------------------------------------------------------------------- |
| Global | `~/.ironbee/config.json` | Defaults across all your projects (e.g. your collector credentials) |
| Project | `/.ironbee/config.json` | Team settings committed to the repo |
| Local | `/.ironbee/config.local.json` | Personal overrides, gitignored, never shared |
Precedence is **local > project > global**. A key set in the local layer wins over the same key in the project layer, which wins over global.
Secrets can also come from the environment: setting `IRONBEE_SERVICE_API_KEY` (or the legacy `IRONBEE_API_KEY`) supplies the account API key without committing it to any file.
***
## Editing config from the CLI
```bash theme={null}
ironbee config get # read the effective (merged) value
ironbee config set # write to the project config
ironbee config unset # remove a value (idempotent)
ironbee config list # print the merged effective config
ironbee config path # print the project config file path
```
**Targeting a layer:** `set`, `unset`, and the read commands accept `-g`/`--global` or `--local` to act on a specific layer (default is the project config). `list` and `get` also take `--project` to read one layer in isolation:
```bash theme={null}
ironbee config set collector.apiKey sk-... --global
ironbee config set maxRetries 5
ironbee config set browser.verifyPatterns '["*.ts", "*.tsx", "*.css"]'
ironbee config list --global
```
**Type coercion:** `set` parses values as JSON when it can (`true`, `42`, `[...]`, `{...}`) and falls back to a plain string otherwise. Pass `--json` to force strict JSON parsing.
**Automatic re-render:** when you change a key that affects installed client artifacts (anything under `verification`, `service`, `collector`, `browser`, `node`, `python`, `backend`, `android`, `terminal`, `telemetry`, `privacy`, `codex`, `runtime`, `integrations`, or the `*DevTools` overrides), the CLI automatically re-renders your hooks, MCP entries, skill, rule, and permissions. Pass `--no-rerender` to skip. After a global write on an artifact-affecting key, the CLI offers to propagate it to every registered project. `--apply-all` accepts without prompting, `--no-apply-all` declines.
Restart your editor or agent session after changing an artifact-affecting key; it takes effect on the next session.
***
## Core options
| Key | Type | Default | Description |
| ----------------------- | ---------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ignoredVerifyPatterns` | `string[]` | `[]` *(plus always-on test-file defaults)* | Glob patterns excluded from **all** cycles. Checked first a match here activates no cycle, whatever else matches. Your patterns are **unioned on top of** a built-in default set that always excludes test files (`**/*.spec.*`, `**/*.test.*`, `**/__tests__/**`, `**/__mocks__/**`), so a test-only edit never triggers a runtime-verification cycle even if you set nothing. |
| `maxRetries` | `number` | `3` | Failed verification attempts allowed before the agent may complete anyway (reporting unresolved issues). One global counter across all active cycles. |
| `params` | `object` | *(unset)* | User-defined string→string map consumed by [`${param:}` placeholders](#placeholders-param-env-built-ins) elsewhere in the config. Merged per key across layers (local wins). Not artifact-affecting (read live). |
```json theme={null}
{
"ignoredVerifyPatterns": ["**/generated/**", "**/*.gen.ts"],
"maxRetries": 5
}
```
Test files are already excluded out of the box — `ignoredVerifyPatterns` is only for *additional* paths you want to skip on top of that built-in default.
***
## Placeholders — `${param:}`, `${env:}`, built-ins
Config **string** values can interpolate placeholders that IronBee resolves at **read time**, so one committed config can carry per-developer or per-environment values without hand-editing. Three forms are supported:
| Form | Reads from | Example |
| ----------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `${param:}` | The [`params`](#core-options) block, overridable per key by the `IRONBEE_PARAM_` env var | `${param:api_url}` |
| `${env:}` | The `IRONBEE_ENV_` env var **only** | `${env:staging_url}` |
| Built-ins | Static values | `${projectDir}` `${projectName}` `${home}` `${configDir}` `${platform}` `${arch}` `${tmpdir}` |
Each `${param:}` / `${env:}` reference takes an optional bash-style default after `:-` (e.g. `${env:staging_url:-http://localhost:3000}`), and resolves in this order:
* **`${param:api_url}`** → `IRONBEE_PARAM_API_URL` env → the `params` block (local → project → global) → the `:-` default → the literal text (with a warning).
* **`${env:staging_url}`** → `IRONBEE_ENV_STAGING_URL` env → the `:-` default → the literal text.
```json theme={null}
{
"params": { "api_url": "http://localhost:3000" },
"verification": {
"checks": [
{ "name": "api-test", "command": "npm",
"args": ["run", "test:api", "--", "--base-url", "${param:api_url}"] }
],
"context": { "message": "Verify against ${env:staging_url:-http://localhost:3000}." }
}
}
```
The `env:` / `param:` prefix is **implied and never written** — `${env:staging_url}` can only read `IRONBEE_ENV_STAGING_URL`, so arbitrary environment variables (`AWS_SECRET_ACCESS_KEY`, tokens, …) are structurally unreachable from config text. Write a literal `${` as `$${`. Upper-case shell forms like `${HOME}` in check arguments are left untouched.
Placeholders resolve for **runtime consumers** (checks, context injection, the collector). Values baked into **committed client artifacts** are read raw and kept as literal references, so a resolved value never lands in a shared artifact — the supported keys are the runtime-read ones (`verification.checks[]` command/args/env/cwd and `verification.context.message`). `ironbee config get ` (merged) prints the **resolved** value with a provenance note on stderr; a layer-scoped read (`--project` / `--global` / `--local`) shows the raw on-disk text.
***
## Runtime
| Key | Type | Default | Description |
| ------------------ | -------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `runtime.location` | `string` | `"external"` | Where per-session runtime data (the `sessions/` folder — `actions.jsonl`, verdicts, queue) is stored. `"external"` *(default)* keeps it **out of the project tree** at `~/.ironbee/projects//sessions/`, so a project never accumulates a growing `sessions/` folder even when it's gitignored. `"in-project"` stores it under `/.ironbee/sessions/` (the legacy layout). Committed config, `scenarios/`, and `VERIFICATION.md` files always stay in-project regardless. The [`IRONBEE_RUNTIME_LOCATION`](/cli/configuration/environment-variables#advanced) env var overrides it per process. Takes effect on the next session. See [Runtime files](/cli/advanced/runtime-files#where-per-session-data-lives). |
Switching `runtime.location` doesn't move existing session data — it changes where *new* sessions are written. Old per-session folders under the previous location are left in place; you can delete them by hand if you don't need them.
***
## Verification
| Key | Type | Default | Description |
| --------------------- | -------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `verification.enable` | `boolean` | `true` | Master enforcement switch. `false` = monitoring-only (telemetry still flows, no verify gate). Equivalent to [`ironbee verification disable`](/cli/guides/verification#verification-modes). |
| `verification.auto` | `boolean` | `false` | Automatic-enforcement sub-toggle (only meaningful when `verification.enable` is `true`). Default `false` = [assist mode](/cli/guides/verification#assist-mode-default), the safer default: the `/ironbee-verify` command, the devtools MCP server, and permissions stay installed for manual verification, but nothing is enforced and no verify gate, non-blocking pre-edit hooks, and the skill/rule are omitted. Set `true` for full [enforce mode](/cli/guides/verification#enforce-mode) (blocking Stop gate + skill/rule installed). Equivalent to [`ironbee verification auto enable`/`disable`](/cli/guides/verification#enforce-mode). |
| `verification.model` | `string` \| `object` | *(unset — inherit the session model)* | Model the [delegated verifier sub-agent](/cli/guides/verification#picking-the-verifier-model) runs on (Claude Code and Codex). Unset means the verifier inherits the main conversation's model. Set a **string** (e.g. `"sonnet"`, `"gpt-5.5"`) to apply to every client, or a **per-client object** `{ "claude": "sonnet", "codex": "gpt-5.5" }` when a project uses both. Cursor has no verifier sub-agent, so it's a no-op there. Equivalent to [`ironbee verification model `](/cli/guides/verification#picking-the-verifier-model). |
| `verification.fix` | `boolean` | `true` | [Fix enforcement](/cli/guides/verification#fix-enforcement-block-on-a-fail-or-just-report-it). Default `true`: in enforce mode a **fail** verdict blocks completion until the agent fixes the issues and re-verifies (counts toward `maxRetries`). Set `false` for **report-only**: the agent still must verify and submit a verdict, but a fail is reported (and recorded) rather than looped on — the turn may end with the issues stated plainly. Only meaningful in enforce mode; read live by the gate. A manual `/ironbee-verify fix` run escalates that one run to fix-until-pass regardless. Equivalent to `ironbee verification fix `. |
| `verification.strict` | `boolean` | `false` | [Strict mode](/cli/guides/verification#strict-mode). When `true`, the verify gate **rejects all [N/A verdicts](/cli/guides/verification#when-a-change-has-nothing-to-verify-na-verdicts)** — the agent must produce real tool evidence for every active cycle. Default `false` accepts N/A (recorded and observable). Only meaningful in enforce mode (no gate runs in assist/monitoring). Read live by the gate. Equivalent to [`ironbee verification strict `](/cli/guides/verification#strict-mode). |
| `verification.checks` | `array` | `[]` | [Project checks](/cli/guides/verification#project-checks-run-first-lint-tests-types) — deterministic commands (lint, tests, typecheck, build, format) run as the **first step** of every verification cycle, before any devtools verification. Each entry is `{ "name", "command", "args"?, "env"?, "cwd"?, "timeoutMs"?, "required"?, "kind"?, "conclusive"? }` (`kind` is an advisory `typecheck`/`lint`/`test`/`build`/`format`/`other` label). The verifier runs them via `ironbee hook run-checks`; in enforce mode a `required` check that fails (or never ran) **blocks the gate** so the agent fixes and re-runs (it counts toward `maxRetries`). `conclusive: true` (implies `required`; hand-set only, never suggested) makes a check the **arbiter** of the cycle — all conclusive checks passing auto-submits the pass verdict and **skips** devtools verification; a conclusive check failing defers to a devtools **diagnosis** before a findings-rich fail. See [Conclusive checks](/cli/guides/verification#conclusive-checks-let-a-check-decide-the-cycle). Trust is the recorded exit code, never the agent's claim. Can be [LLM-suggested](/cli/guides/verification#let-ironbee-suggest-your-checks) at install or via `ironbee checks suggest`. Read live (not artifact-affecting); results stay local (not shipped to the Collector). |
***
## Verification cycles
The six cycles: `browser`, `node`, `python`, `backend`, `android`, and `terminal`, share the same set of keys (replace `` with `browser`, `node`, `python`, `backend`, `android`, or `terminal`):
| Key | Type | Description |
| ---------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `.enable` | `boolean` | Explicit on/off. Written `false` by `ironbee disable`, stripped by `ironbee enable`. Browser is the only cycle on by default; node, python, backend, android, and terminal are opt-in. |
| `.verifyPatterns` | `string[]` | Files that trigger the cycle. **Four states:** unset → built-in code defaults · `[]` → hard-disable · non-empty → custom patterns (replaces defaults). |
| `.additionalVerifyPatterns` | `string[]` | Extra patterns appended to `verifyPatterns` (or to the defaults when it's unset). Ignored when `verifyPatterns` is `[]`. |
| `.alwaysRequired` | `string[]` | Tools the agent must use before the cycle passes (all-of). Sensible per-cycle defaults apply. *Advanced.* |
| `.evidencePaths` | `json` | Alternative tool-satisfaction paths (any-of). *Advanced.* |
**Defaults differ per cycle:**
| Cycle | Default state | Default verify patterns |
| ---------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `browser` | On | 40+ code/markup extensions (`.ts`, `.tsx`, `.js`, `.css`, `.html`, `.vue`, …) |
| `node` | Opt-in | When enabled: server/api/routes code paths |
| `python` | Opt-in | When enabled: server/api/app `.py` paths, Django (`views.py`/`urls.py`/`models.py`/`tasks.py`), Flask/FastAPI (`app.py`/`main.py`), WSGI/ASGI entry points |
| `backend` | Opt-in | When enabled: 13 multi-language code defaults (ts/js/py/go/java/rb/cs/rs/kt/scala/ex/php/clj) |
| `android` | Opt-in | When enabled: standard Android project layouts (Gradle, Kotlin/Java source trees, resources) |
| `terminal` | Opt-in | When enabled: CLI / TUI / shell paths — `cli/`, `cmd/`, `commands/`, and `bin/` trees (at any depth), CLI entrypoints, and shell scripts |
The exact default patterns each cycle uses when `verifyPatterns` is unset:
Matches code and markup files by extension (project-wide):
```
*.ts *.tsx *.js *.jsx *.mjs *.cjs
*.vue *.svelte
*.html *.htm
*.css *.scss *.sass *.less *.styl
*.py *.rb *.erb *.go *.rs
*.java *.kt *.kts *.swift
*.c *.cpp *.h *.hpp *.cs *.php *.dart
*.ex *.exs *.erl *.lua *.r *.R
*.scala *.clj *.cljs *.zig *.nim
*.hbs *.ejs *.pug *.jade *.astro
```
Targets typical Node.js server entry points and API routes (applies once the cycle is enabled):
```
server/**/*.{ts,js,mjs,cjs}
src/server/**/*.{ts,js,mjs,cjs}
backend/**/*.{ts,js,mjs,cjs}
api/**/*.{ts,js,mjs,cjs}
src/api/**/*.{ts,js,mjs,cjs}
pages/api/**/*.{ts,js,mjs,cjs}
app/api/**/*.{ts,js,mjs,cjs}
routes/**/*.{ts,js,mjs,cjs}
**/server.{ts,js,mjs,cjs}
```
Targets typical Python server entry points, web-framework modules, and WSGI/ASGI apps (applies once the cycle is enabled):
```
server/**/*.py
src/server/**/*.py
backend/**/*.py
api/**/*.py
src/api/**/*.py
app/**/*.py
src/app/**/*.py
routes/**/*.py
services/**/*.py
**/views.py **/urls.py **/models.py **/tasks.py
**/app.py **/main.py **/server.py
**/wsgi.py **/asgi.py
```
Multi-language coverage of common server-side directories (applies once the cycle is enabled). The `{...}` extension set is `ts,js,mjs,cjs,py,go,java,rb,cs,rs,kt,scala,ex,exs,php,clj`:
```
server/**/*.{…}
src/server/**/*.{…}
backend/**/*.{…}
api/**/*.{…}
src/api/**/*.{…}
pages/api/**/*.{ts,js,mjs,cjs}
app/api/**/*.{ts,js,mjs,cjs}
routes/**/*.{…}
controllers/**/*.{…}
handlers/**/*.{…}
services/**/*.{…}
**/server.{…}
**/main.{go,py,java,rb,kt,scala}
```
Covers standard Android project layouts Gradle modules, Kotlin/Java source trees, and resources (applies once the cycle is enabled):
```
android/**/*.{kt,java}
app/src/**/*.{kt,java}
mobile/**/*.{kt,java}
src/main/kotlin/**/*.kt
src/main/java/**/*.java
**/*.{kt,java}
**/res/**/*.xml
**/AndroidManifest.xml
```
Covers CLI entrypoints, command trees, and shell scripts (applies once the cycle is enabled). Note these are **extension-scoped** — a `README.md` or a fixture inside `cli/` doesn't activate the cycle:
```
cli/**/*.{ts,js,mjs,cjs,py,go,rs,rb,java,kt}
**/cli/**/*.{ts,js,mjs,cjs,py,go,rs,rb,java,kt}
cmd/**/*.{go,ts,js,mjs,cjs,py,rs}
**/cmd/**/*.{go,ts,js,mjs,cjs,py,rs}
**/commands/**/*.{ts,js,mjs,cjs,py,go,rs,rb}
bin/**
**/bin/**/*.{ts,js,mjs,cjs,py,go,rs,rb,sh}
**/cli.{ts,js,mjs,cjs,py,go,rs,rb}
**/main.{go,rs}
**/*.{sh,bash,zsh,fish}
```
`bin/**` is the one deliberately unscoped entry — a top-level `bin/` holds executables that often carry no extension at all.
These defaults are defined in the CLI (not written into `config.json`) and may grow with new CLI versions. Setting `verifyPatterns` replaces the list for that cycle; `additionalVerifyPatterns` appends to it. The only built-in **skip** list is the always-on test-file exclusion baked into [`ignoredVerifyPatterns`](#core-options) (`**/*.spec.*`, `**/*.test.*`, `**/__tests__/**`, `**/__mocks__/**`); anything you add to `ignoredVerifyPatterns` is unioned on top. Non-code files simply don't match the patterns above.
Prefer the [`ironbee browser` / `node` / `python` / `backend` / `android` / `terminal` commands](/cli/guides/verification#enable-or-disable-a-platform) for turning cycles on and off; they write `.enable` and re-render artifacts for you. Reach for `verifyPatterns` only when you need to change *which files* a cycle covers.
```json theme={null}
{
"browser": {
"additionalVerifyPatterns": ["*.mdx"]
},
"backend": {
"verifyPatterns": ["api/**/*.go", "controllers/**/*.java"]
}
}
```
***
## Verification context
Controls the [path-scoped verification guidance](/cli/guides/verification-context) IronBee injects from `.ironbee/VERIFICATION.md` files. On by default; these keys are **read live** at verification time, so changes take effect on the next session without re-rendering artifacts.
| Key | Type | Default | Description |
| ---------------------------------- | --------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `verification.context.enable` | `boolean` | `true` | Master switch. When the first verification tool call of a cycle fires, the relevant `.ironbee/VERIFICATION.md` files for the changed paths are injected into the agent's context. Advisory only, never gates. Opt out with `false`. |
| `verification.context.source` | `string` | `"git"` | Where the changed-path set comes from. `"git"` = working tree (staged + unstaged + untracked) ∪ the last `commitDepth` commits, with an `actions.jsonl` fallback when the project isn't a git repo. `"actions"` = IronBee's own `file_change` events only (no git subprocess). |
| `verification.context.commitDepth` | `number` | `1` | How many recent commits join the working tree for the `git` source. `0` = uncommitted work only. Ignored when `source` is `"actions"`. |
| `verification.context.maxBytes` | `number` | `65536` | Aggregate cap (64 KB) on the injected text. Past the cap, the least-specific (root-side) guidance is dropped first, keeping area-specific docs. |
| `verification.context.message` | `string` | *(unset)* | A custom instruction injected into **every** verification cycle, independent of which files changed — so it reaches the verifier even on a manual no-change verify (where the path-scoped `VERIFICATION.md` injection is empty). Two forms: literal inline text, or a `file:` reference whose contents are read (path relative to the project dir; a leading `~` expands to your home dir). Rendered first and **never truncated** (it reserves its bytes off the `maxBytes` budget). Layered across global / project / local. |
```json theme={null}
{
"verification": {
"context": {
"commitDepth": 0,
"message": "Always confirm the health endpoint returns 200 before passing."
}
}
}
```
Earlier CLI versions used a top-level `verificationContext.*` namespace. These keys now live under `verification.context.*`; update any scripts or committed config that still reference the old names.
***
## Service identity
The `service` section is the CLI's **shared identity**: one credential and one stage selector that every IronBee service — the event-ingest collector, the read-side API (used by [`ironbee verify`](/cli/guides/verification-jobs) and the o11y trace tools), and the Console links — resolves from. [`ironbee login`](/cli/guides/authentication) writes it for you; you'd only set it by hand to self-host or to run in CI. See [Authentication](/cli/guides/authentication) for the difference between the two credentials.
| Key | Type | Default | Description |
| -------------------- | -------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `service.domain` | `string` | `ironbee.ai` | The single **stage selector**. Every service URL derives from it when not set explicitly: the collector at `collector.service.`, the API at `api.service.`, the Console at `console.`. `ironbee login` persists the domain you authenticated against when the hosts are standard-shaped (a non-standard, self-hosted deployment keeps explicit URLs instead). Env: `IRONBEE_SERVICE_DOMAIN`. |
| `service.oauthToken` | `string` | *(unset)* | Personal OAuth access token written by `ironbee login`. The CLI's default credential, shared by the collector and the API. Env: `IRONBEE_SERVICE_OAUTH_TOKEN`. |
| `service.apiKey` | `string` | *(unset)* | Account API key, used for CI and machine-to-machine. When both credentials are set, the OAuth token is used. Env: `IRONBEE_SERVICE_API_KEY`. |
| `api.url` | `string` | derived: `https://api.service.` | Explicit override for the read-side API base URL ([`ironbee verify`](/cli/guides/verification-jobs), trace lookups). Rarely set — `service.domain` covers the normal cases. |
Older configs kept the credential under `collector.oauthToken` / `collector.apiKey`. Those keys (and their `IRONBEE_OAUTH_TOKEN` / `IRONBEE_API_KEY` env vars) still work as **read fallbacks**, so nothing breaks — but new logins write `service.*`, and the `service.*` keys win when both are present.
***
## Collector
The collector is what ships your session data to the IronBee Console. Its endpoint and credential come from the [`service` section](#service-identity) above; the keys here tune delivery (and carry the legacy credential fallbacks).
| Key | Type | Default | Description |
| ---------------------- | --------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `collector.url` | `string` | derived: `https://collector.service.` | Explicit endpoint override. Normally unset — it derives from `service.domain`. |
| `collector.oauthToken` | `string` | *(unset)* | **Deprecated read fallback** for `service.oauthToken` (configs written before the `service` section). Can come from `IRONBEE_OAUTH_TOKEN` instead. |
| `collector.apiKey` | `string` | *(unset)* | **Deprecated read fallback** for `service.apiKey`. Can come from `IRONBEE_API_KEY` instead. |
| `collector.enable` | `boolean` | implicit `true` when a credential is set | Set `false` to suspend sending while keeping credentials around. The collector activates on the **presence of a credential** (`service.*` preferred, `collector.*` fallback) — the URL always resolves via `service.domain`. |
| `collector.batchSize` | `number` | `100` | Max events per POST. |
***
## Telemetry
| Key | Type | Default | Description |
| ------------------ | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `telemetry.enable` | `boolean` | `true` | [Anonymous PostHog product analytics](/cli/advanced/telemetry) for the CLI itself (separate from the collector pipeline). Opt out with `false`, also turns off telemetry in the devtools MCP servers. Equivalent to `ironbee telemetry disable`. |
***
## Privacy
| Key | Type | Default | Description |
| ---------------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `privacy.enable` | `boolean` | `false` | [Privacy mode](/cli/advanced/privacy) is a single cross-cutting switch (all cycles) that redacts sensitive payloads from what the devtools MCP servers ship to the collector. **Opt-in, default off.** When `true`, injects `COLLECTOR_EVENTS_TOOL_DETAILS_ENABLE=false` (tool input/output detail) and `COLLECTOR_ARTIFACTS_ENABLE=false` (screenshots, recordings) into the devtools MCP env. Devtools-side only and orthogonal to `telemetry` and `collector`. Equivalent to `ironbee privacy enable`. |
[DevTools env overrides](#devtools-mcp-overrides) are applied *after* the privacy flags, so set `ironbeeDevTools.env.COLLECTOR_ARTIFACTS_ENABLE` / `COLLECTOR_EVENTS_TOOL_DETAILS_ENABLE` back to `"true"` to let one channel through while privacy mode is on.
***
## Issue-tracker integrations
Connect Jira, Linear, or GitHub Issues — see the [Issue Tracking guide](/cli/guides/issue-tracking) for the setup flows (`ironbee integrations setup`) and what the integration does. A provider activates by **configuration presence** (a configured credential turns it on; GitHub is on whenever the `gh` CLI is authenticated); its `enable` key is an opt-out kill-switch.
**Secrets belong in the global config** (`~/.ironbee/config.json`) — `setup` writes them there for you. Installed artifacts carry only a `${file:…}` reference to the global config, so no token is ever baked into a committed file. In CI, supply them via the [credential env vars](/cli/configuration/environment-variables#issue-tracker-credentials) instead.
### Jira
| Key | Type | Default | Description |
| ---------------------------------- | ---------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `integrations.jira.baseUrl` | `string` | *(unset — integration off)* | Jira base URL (e.g. `https://acme.atlassian.net`). Not a secret — can be team-shared (project config) or per-user (global, where `setup` writes it). Required for the integration to be configured. |
| `integrations.jira.email` | `string` | *(unset)* | Jira **Cloud** identity, paired with `apiToken`. Per-user — keep it in the global config (Server/DC deployments leave it unset). |
| `integrations.jira.apiToken` | `string` | *(unset)* | Jira **Cloud** API token — **secret**, global config only. CI: `IRONBEE_JIRA_API_TOKEN`. |
| `integrations.jira.pat` | `string` | *(unset)* | Jira **Server/DC** personal access token — **secret**, global config only. CI: `IRONBEE_JIRA_PAT`. |
| `integrations.jira.deployment` | `string` | *(inferred)* | `cloud` or `server`. Inferred from the credential shape; set explicitly to pin. |
| `integrations.jira.defaultProject` | `string` | *(unset)* | Default Jira project key for creates and searches (e.g. `PROJ`). Committed. |
| `integrations.jira.projectKeys` | `string[]` | `[]` | Allow-list of issue-key prefixes accepted when [attributing issues](/cli/guides/issue-tracking#vcs-linkage-sessions-to-prs-and-issues) from branch/commit/PR text — kills `UTF-8` / `SHA-256`-style false positives. Read live. |
| `integrations.jira.writeEnabled` | `boolean` | `false` | Whether the [write tiers](/cli/guides/issue-tracking#read-only-by-default-write-gating) (comment, attach, transition, create/link, report) are enabled. Read-only integrations still read, search, and attribute. |
| `integrations.jira.enable` | `boolean` | `true` *(when configured)* | Opt-out kill-switch — `false` suspends the integration without deleting its config. Equivalent to `ironbee integrations jira disable`. |
### Linear
| Key | Type | Default | Description |
| ---------------------------------- | ---------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `integrations.linear.apiKey` | `string` | *(unset — integration off)* | Linear API key (`lin_api_…`) — **secret**, global config only. CI: `IRONBEE_LINEAR_API_KEY`. |
| `integrations.linear.oauth` | `boolean` | `false` | Set `true` when `apiKey` is an **OAuth access token** rather than a personal key (changes how it's sent). |
| `integrations.linear.defaultTeam` | `string` | *(unset)* | Default Linear team key for creates and searches (e.g. `ENG`). Committed. |
| `integrations.linear.teamKeys` | `string[]` | `[]` | Allow-list of issue-key prefixes for attribution — same role as Jira's `projectKeys` (also disambiguates the two when both are configured). Read live. |
| `integrations.linear.workspace` | `string` | *(unset)* | Workspace URL slug (the `acme` in `linear.app/acme`), used to build issue browse links in the attribution data. Unset → no browse URL (graceful). |
| `integrations.linear.baseUrl` | `string` | Linear's cloud GraphQL endpoint | Rare override for a proxy endpoint. |
| `integrations.linear.writeEnabled` | `boolean` | `false` | Same write gating as Jira. |
| `integrations.linear.enable` | `boolean` | `true` *(when configured)* | Opt-out kill-switch. Equivalent to `ironbee integrations linear disable`. |
### GitHub Issues
| Key | Type | Default | Description |
| ---------------------------------- | --------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `integrations.github.enable` | `boolean` | `true` *(when `gh` is authenticated)* | Opt-out kill-switch. GitHub is driven through the `gh` CLI and auto-activates when `gh` is installed and authenticated — no credential is stored. `false` suspends it regardless. |
| `integrations.github.writeEnabled` | `boolean` | `false` | Whether the write operations (`gh issue comment` / `close` / `edit`, the verification report) are allowed. Self-enforced by the agent (`gh` is always shell-reachable), unlike Jira/Linear's mechanical gate. Read live. |
***
## VCS linkage
Links each agent turn to the pull request it produced and the issues that PR closes — the join key that makes verification data attributable to an issue instead of an opaque session ID. It runs in every mode (enforce / assist / monitoring-only) and auto-enables whenever a collector is configured. See [Issue Tracking → VCS linkage](/cli/guides/issue-tracking#vcs-linkage-sessions-to-prs-and-issues).
| Key | Type | Default | Description |
| ----------------------- | --------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `vcs.enable` | `boolean` | implicit `true` when a collector is configured | Master switch for the linkage — the git-ref stamp, PR resolution, issue attribution, and the `vcs_link` events. **Note:** it sends repository and *branch names* to the Collector; branch names can carry sensitive text. Independent of [privacy mode](/cli/advanced/privacy). Read live. |
| `vcs.issueTtlSeconds` | `number` | `600` | Cache TTL for successful / not-found resolutions. Short — a PR can be opened or an issue transitioned at any moment. |
| `vcs.resolveTtlSeconds` | `number` | `3600` | Cache TTL for resolutions that can't improve on retry (no token, no remote, rejected credentials). |
| `vcs.stampDirty` | `boolean` | `false` | Probe the working tree for uncommitted changes during the git-ref stamp. Off by default — it's the most expensive part of the stamp and scales with repo size. |
| `vcs.timeoutMs` | `number` | `5000` | Per-request timeout for PR / issue resolution (always in a detached background worker, never a blocking hook). Clamped to `[1000, 60000]`. |
***
## Web console
| Key | Type | Default | Description |
| ------------- | -------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `console.url` | `string` | derived: `https://console.` | Explicit Console base URL override, used to build the `🔗 View in IronBee` timeline deep-links in [issue-tracker reports](/cli/guides/issue-tracking#using-it-ironbee-issue-track). Normally unset — it derives from [`service.domain`](#service-identity), which `ironbee login` persists, so self-hosted consoles link correctly. Read live. |
***
## File change capture
| Key | Type | Default | Description |
| ------------------------------ | --------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
| `fileChange.captureChangeset` | `boolean` | `false` | When `true`, each `file_change` event carries a hunks-only unified diff. Off by default (events stay metadata-only). |
| `fileChange.maxChangesetBytes` | `number` | `65536` | Hard cap (64 KB) on the diff string, larger diffs are truncated with a footer. |
***
## Claude (Claude Code only)
Two install-time behaviors that keep the verifier working with Claude Code's own host-side guardrails. See [Claude Code](/cli/clients/claude-code).
| Key | Type | Default | Description |
| --------------------------------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `claude.autoModeAllowlist.enable` | `boolean` | `true` | Whether IronBee writes the [auto-mode allowlist carve-out](/cli/clients/claude-code#auto-mode-and-the-verifier) for the verifier into `.claude/settings.local.json`. Claude Code's auto-mode "Content Integrity" classifier can false-positive on IronBee's legitimate verdict submissions; when enabled (default), install adds one narrow rule that exempts **only** that command from the block (every other auto-mode protection stays in force). Written only when verification is active (enforce/assist) and inert when the host isn't in auto mode. Opt out with `false` — takes effect on the next `ironbee install`. Claude-only. |
| `claude.trustWorkspace.enable` | `boolean` | `true` | Whether `ironbee install` marks the project [trusted](/cli/clients/claude-code#workspace-trust) in Claude Code's machine-global `~/.claude.json` when it isn't already. Claude Code 2.1.x ignores a project's committed `permissions.allow` (the devtools + `Bash(ironbee *)` entries IronBee writes) until the workspace is trusted, and the trust dialog doesn't re-appear once onboarding has been seen — so without this the entries stay silently disabled and the agent gets prompted on every devtools/`ironbee` call. Best-effort and idempotent: it only ever flips a missing/false flag to `true` and never clobbers other `~/.claude.json` content. Opt out with `false`. Claude-only. |
***
## Codex (Codex CLI only)
Controls how the Codex verification cycle is driven. Manage with `ironbee codex verifier mode `. See [Codex → How verification is delivered](/cli/clients/codex#how-verification-is-delivered).
| Key | Type | Default | Description |
| --------------------- | -------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `codex.verifier.mode` | `string` | `sub-agent` | How the Codex verification cycle runs. `"sub-agent"` (default) delegates to the [`ironbee-verifier`](/cli/clients/codex) custom agent (per-agent MCP, slim delegation skill/rule/command), keeping the heavy devtools output out of the main conversation. `"main-agent"` makes the **main** agent drive the devtools tools directly (session-level MCP server, no verifier sub-agent, inline skill/rule/command) — the Cursor-style fallback for when Codex's sub-agent machinery regresses. Re-renders the Codex client. Codex-only. |
***
## Devtools MCP overrides
All cycles are served by a single **`ironbee-devtools`** compose MCP server, customized via the `ironbeeDevTools` keys:
| Key | Description |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `ironbeeDevTools.env` | Extra env vars merged into the default MCP server entry. |
| `ironbeeDevTools.mcp` | Full replacement of the MCP server config, supply your own `command`+`args` (stdio) or `url` (HTTP), e.g. to point at a local devtools build. |
```json theme={null}
{
"ironbeeDevTools": {
"env": { "BROWSER_HEADLESS_ENABLE": "true" }
}
}
```
IronBee always sets its own invariants (`PLATFORM=compose`, `COMPOSE_PLATFORMS`, metadata flags) last; these can't be overridden.
The legacy per-cycle keys (`browserDevTools`, `nodeDevTools`, `pythonDevTools`, `backendDevTools`, `androidDevTools`, `terminalDevTools`) still exist for back-compat but **no longer feed the compose server** — use `ironbeeDevTools` to customize the one server that serves every cycle.
***
## Automatic pipeline keys
These sections auto-enable when a collector is configured and rarely need manual tuning. Browse them with `ironbee config list` or the [TUI](/cli/guides/interactive-mode) Configuration area:
* **`recording:`** session recording for the browser and Android cycles (`recording.enable`); the node, python, backend, and terminal cycles never trigger it.
* **`jobQueue:`** the file-backed background queue that feeds the collector (`jobQueue.enable`, flush thresholds).
***
## Common setups
### Ignore extra files
Test files (`**/*.spec.*`, `**/*.test.*`, `**/__tests__/**`, `**/__mocks__/**`) are **excluded by default** — you don't need to list them. Add `ignoredVerifyPatterns` only to skip *more* paths (e.g. generated code, fixtures); your entries are unioned with the built-in test-file defaults:
```json theme={null}
{
"ignoredVerifyPatterns": ["**/generated/**", "**/*.gen.ts", "fixtures/**"]
}
```
### Backend-only project (no browser cycle)
```json theme={null}
{
"browser": { "enable": false },
"backend": { "enable": true }
}
```
Or use the CLI: `ironbee browser disable && ironbee backend enable`.
### Monitoring only (no enforcement)
```json theme={null}
{
"verification": { "enable": false }
}
```
### Assist mode (verify on demand, never gated)
```json theme={null}
{
"verification": { "auto": false }
}
```
Or use the CLI: `ironbee verification auto disable`.
### Capture code diffs on file-change events
```json theme={null}
{
"fileChange": { "captureChangeset": true }
}
```
***
## What's next?
Overrides that take precedence over the config files.
Where these config files live and what else IronBee writes to disk.
# Environment Variables
Source: https://docs.ironbee.ai/cli/configuration/environment-variables
Environment variables IronBee reads for CI, secrets, debugging, and project resolution.
Most configuration lives in [config files](/cli/configuration/configuration), but a few settings can be supplied via environment variables, handy for CI runners, ephemeral shells, and secrets you don't want to commit.
***
## Common
| Variable | Effect |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IRONBEE_SERVICE_API_KEY` | Supplies [`service.apiKey`](/cli/configuration/configuration#service-identity) (the shared account API key) without committing it. **Takes precedence over every config layer.** The credential of choice for CI and the [GitHub Action](/github-action/get-started/getting-started). |
| `IRONBEE_SERVICE_OAUTH_TOKEN` | Supplies [`service.oauthToken`](/cli/configuration/configuration#service-identity) (the personal token from [`ironbee login`](/cli/guides/authentication)) without committing it. When both credentials are set, the OAuth token wins. |
| `IRONBEE_SERVICE_DOMAIN` | Supplies [`service.domain`](/cli/configuration/configuration#service-identity), the stage selector every service URL derives from. |
| `IRONBEE_API_KEY` | Legacy — supplies the deprecated `collector.apiKey` fallback, which is read **only when `service.apiKey` is unset** (a recent `ironbee login` writes `service.*`, which then wins). One exception: [`ironbee verify`](/cli/guides/verification-jobs#credentials) reads it as a deliberate top-priority override. |
| `IRONBEE_OAUTH_TOKEN` | Legacy — supplies the deprecated `collector.oauthToken` fallback; same caveat as above. |
| `IRONBEE_TELEMETRY` | Set to `false` to turn off [anonymous CLI telemetry](/cli/advanced/telemetry) for this shell/run, a per-session alternative to the `telemetry.enable` config key. |
| `IRONBEE_LOG_LEVEL` | Logging verbosity. Set to `debug` to see detailed output when troubleshooting. |
```bash theme={null}
# CI: provide the API key from a secret, no file commit
export IRONBEE_SERVICE_API_KEY=sk-...
ironbee install --mode enforce --yes
```
Because these override the files, a merged read (`ironbee config get service.apiKey`) returns the env value. A layer-scoped read (`--project` / `--global` / `--local`) bypasses env and shows only what's on disk.
***
## Verification jobs
[`ironbee verify`](/cli/guides/verification-jobs) — the cloud verification-job runner — reads two extra overrides of its own, plus the GitHub Actions context:
| Variable | Effect |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IRONBEE_ACCESS_TOKEN` | OAuth access token for the API, overriding `service.oauthToken`. |
| `IRONBEE_API_URL` | API base URL, overriding `api.url` (the `--api-url` flag wins over both). |
| `GITHUB_ACTIONS` | When exactly `"true"`, a created job is declared with the `github_actions` trigger (Console visibility only) and secret-header values are masked with `::add-mask::`. |
| `GITHUB_REPOSITORY` / `GITHUB_SHA` / `GITHUB_REF` | Fill the run's repository binding: the `owner/repo`, the authoritative commit, and the pull-request number on a PR run. |
***
## Issue-tracker credentials
The [issue-tracker integrations](/cli/guides/issue-tracking) normally keep their secrets in your global config (`~/.ironbee/config.json`, written by `ironbee integrations setup`). In CI — or anywhere you'd rather source them from a vault — supply them via env instead. Like the collector credentials, these **take precedence over every config layer**:
| Variable | Effect |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `IRONBEE_JIRA_API_TOKEN` | Supplies `integrations.jira.apiToken` (Jira **Cloud** API token). Combine with a file-set `integrations.jira.baseUrl` + `email` for a complete config. |
| `IRONBEE_JIRA_PAT` | Supplies `integrations.jira.pat` (Jira **Server/DC** personal access token). |
| `IRONBEE_LINEAR_API_KEY` | Supplies `integrations.linear.apiKey` (Linear personal API key or OAuth token). |
GitHub needs no credential variable — it rides the `gh` CLI's own auth (GitHub Actions ships a `GH_TOKEN`).
***
## Config placeholder bridges
[Config placeholders](/cli/configuration/configuration#placeholders-param-env-built-ins) let a committed config carry references that resolve from the environment — the way to override a team default per developer or per CI run without editing a file:
| Variable pattern | Feeds | Notes |
| ---------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IRONBEE_PARAM_` | `${param:}` references | Overrides the [`params`](/cli/configuration/configuration#core-options) block for that key. `` maps case-insensitively — `IRONBEE_PARAM_API_URL` fills `${param:api_url}`. |
| `IRONBEE_ENV_` | `${env:}` references | The **only** environment source a `${env:}` reference can read. `IRONBEE_ENV_STAGING_URL` fills `${env:staging_url}`. |
```bash theme={null}
# CI: override a committed ${param:api_url} for this run
export IRONBEE_PARAM_API_URL=https://api.staging.internal
```
The `IRONBEE_PARAM_*` / `IRONBEE_ENV_*` prefixes are **reserved for placeholder input** — the implied prefix means arbitrary environment variables (secrets, tokens) are structurally unreachable from config text. An empty value counts as unset (the reference falls through to its `:-` default). IronBee's own operational env vars never use these prefixes.
***
## Project directory resolution
When a hook or command needs to know which project it's acting on, IronBee resolves the directory in this order:
1. The client's own variable — `CLAUDE_PROJECT_DIR` (Claude Code), `CURSOR_PROJECT_DIR` (Cursor), or `CODEX_PROJECT_DIR` (Codex) — set automatically by the host
2. `IRONBEE_PROJECT_DIR`, an explicit override you can set
3. The current working directory
You normally don't set these yourself; the AI client provides them. `IRONBEE_PROJECT_DIR` is the escape hatch for scripted or non-standard setups.
***
## Advanced
Rarely needed, mostly for internal wiring and test harnesses:
| Variable | Effect |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IRONBEE_CLIENT` | Tells a hook runner which client it's acting as (the `--client` flag overrides it). Set by the installed hook config. |
| `IRONBEE_RUNTIME_LOCATION` | Overrides [`runtime.location`](/cli/configuration/configuration#runtime) for this process — `external` (default, per-session data under `~/.ironbee/projects//`) or `in-project` (`/.ironbee/sessions/`). Takes precedence over the config layers; mainly used by the test suite. |
| `IRONBEE_BIN` | Overrides the path to the `ironbee` binary used when spawning background workers. |
| `IRONBEE_COLLECTOR` | Set to `false` to disable Collector sends entirely (used by the test harness). |
| `IRONBEE_UPDATE_CHECK` | Set to `false` to skip the npm-registry version check (and its update banner) that runs after a command. Worth setting for scripts that spawn `ironbee` in a loop — each check keeps the event loop alive for up to a 3 s round trip. |
| `IRONBEE_DEVTOOLS_MCP` | Points the `ironbee-devtools` MCP server at your own entry without writing an [`ironbeeDevTools.mcp`](/cli/configuration/configuration#devtools-mcp-overrides) block. A full JSON object: `{"command": "...", "args": [...], "env": {...}}`. Read at install / re-render time, so the resolved command is baked into the artifact — export it when you run `ironbee install`. Wins over the config block; IronBee's invariant env is still layered on top. Mainly for editor extensions that bundle DevTools. |
| `IRONBEE_DEVTOOLS_ENTRY` | Simpler form of the above: a path, rendered as `node `. Used only when `IRONBEE_DEVTOOLS_MCP` is unset or malformed. |
| `IRONBEE_VCS_STAMP_BUDGET_MS` | Total budget (ms, default `3000`) for the git-ref stamp taken at the start of each agent turn. An ops escape hatch — raise it on a heavily loaded machine where the stamp would otherwise go partial and drop `repo`/`host` from the [VCS linkage](/cli/guides/issue-tracking#vcs-linkage-sessions-to-prs-and-issues). |
| `IRONBEE_CURSOR_USER_DIR` | Overrides where IronBee looks for Cursor's local user data (the read-only `state.vscdb` store it reads the signed-in user's email from, for event attribution). Defaults to Cursor's standard per-OS location; mainly for non-standard installs and tests. |
| `IRONBEE_NO_AUTO_RERENDER` | Disables the [auto re-render](/cli/guides/managing-projects#auto-re-rendering-after-an-upgrade) of registered projects after a structure-changing upgrade. A kill switch for CI and locked-down machines. |
| `IRONBEE_NO_PREFETCH` | Global kill-switch for the [devtools prefetch](/cli/guides/managing-projects#devtools-prefetch-warming-the-first-mcp-start) — any value other than empty/`0`/`false` skips the npx cache warm on `install`, upgrade re-renders, `ironbee browser enable`, and `ironbee devtools prefetch`. |
| `IRONBEE_GH_AUTHENTICATED` | Forces the [GitHub issue-tracker](/cli/guides/issue-tracking#github-issues) activation probe deterministically — `1`/`true` = active, `0`/`false` = inactive — bypassing the `gh auth status` check. For CI/test environments where a deterministic result is wanted. `integrations.github.enable: false` still suspends it regardless. |
| `CI` | When truthy (`true` / `1`), also short-circuits the upgrade auto re-render — belt-and-suspenders so a CI that allocates a pseudo-TTY can't hang on the confirmation prompt. |
***
## What's next?
The full config-key reference, the file-based equivalents of these overrides.
Where config and credentials are stored on disk.
# Getting Started
Source: https://docs.ironbee.ai/cli/get-started/getting-started
Sign up, install the IronBee CLI, and set it up in your first project.
The IronBee CLI connects your AI coding agent to IronBee. Once installed in a project, it wires up the hooks and tools your agent needs so that every code change gets verified before a task is marked complete.
This guide covers the basics: create an account, install the CLI, sign in, and set up your first project. That's all you need to get going; deeper configuration comes later.
## Prerequisites
* **Node.js 22 or later** - check with `node --version`
* An AI coding client: [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Cursor](https://cursor.com), or [Codex CLI](https://github.com/openai/codex)
***
## Overview
Sign up at [console.ironbee.ai](https://console.ironbee.ai).
`npm install -g @ironbee-ai/cli` installs the `ironbee` command globally.
`ironbee login` connects the CLI to your account. One time per machine.
`cd` into your project and run `ironbee install` to wire up your AI client.
***
## Step 1: Create your account
Go to [console.ironbee.ai](https://console.ironbee.ai) and sign up. If you already have an account, just sign in.
Your account gives you access to the dashboard and is what the CLI connects to in the next steps.
***
## Step 2: Install the CLI
Install the CLI globally with npm:
```bash theme={null}
npm install -g @ironbee-ai/cli
```
Verify the installation:
```bash theme={null}
ironbee --version
```
***
## Step 3: Sign in
From any directory, run:
```bash theme={null}
ironbee login
```
This opens [console.ironbee.ai](https://console.ironbee.ai) in your browser. Authorize the CLI, and it stores a personal OAuth access token locally. You only need to do this once per machine.
When it completes, the terminal prints a confirmation:
```
✓ Logged in successfully!
Console https://console.ironbee.ai
Collector https://collector.service.ironbee.ai
API https://api.service.ironbee.ai
Domain ironbee.ai
Token personal (my-laptop)
Config /Users/you/.ironbee/config.json
```
If the browser doesn't open automatically, the CLI prints a URL you can paste in manually. Running in CI with no browser? Use an account API key instead, see [Authentication](/cli/guides/authentication).
***
## Step 4: Set up your project
Navigate to the project you want to use IronBee with, then run the installer:
```bash theme={null}
cd your-project
ironbee install
```
IronBee detects your AI client (Claude Code, Cursor, or Codex) and sets it up automatically. If it can't detect one — or detects **more than one** — it asks which client(s) to install for: a checkbox multi-select where **space** toggles a client, **`a`** selects all, and **Enter** confirms (so you can set up several at once). When several were detected they come pre-checked; deselect any you don't want.
Then it walks you through two quick arrow-key pickers. First, **which verification mode** to run:
* **`assist`** *(default)* the verifier and `/ironbee-verify` are installed so the agent can verify on demand, but nothing blocks task completion.
* **`enforce`** changes must pass every active cycle before a task can complete.
* **`monitor`** tracking only — sessions, activity, and tool calls are recorded to the Collector; no verification machinery is installed.
Then, unless you chose `monitor`, **which platforms to verify**:
* **Browser** on by default covers most frontend work.
* **Node**, **Backend**, **Android**, and **Terminal** opt-in; enable any you want gated.
* Not sure which to pick? Press **`s`** to let IronBee analyze your project and suggest the set (Claude Code / Codex only).
You can change both anytime later (see [Verification](/cli/guides/verification)).
That's it. Your project is now connected to IronBee.
Restart your AI coding client after installing so it picks up the new setup.
***
## What's next?
Give your agent a task as you normally would. When it finishes editing code, IronBee steps in and has it verify the changes before the task can complete, and every session shows up in the [Console](https://console.ironbee.ai).
Understand the completion gate, cycles, and verdicts behind what you just set up.
Install, remove, update, and track IronBee across your projects.
# Authentication
Source: https://docs.ironbee.ai/cli/guides/authentication
How the CLI authenticates with IronBee with OAuth tokens for interactive use, API keys for CI and automation.
IronBee accepts two kinds of credentials, and the CLI picks the right one for you:
* **OAuth access token:** the default for interactive use. `ironbee login` mints a personal token tied to your user and account. Each token is individually named and revocable.
* **API key:** an account-scoped key for machine-to-machine (M2M) use, such as the [GitHub Action](/github-action/get-started/getting-started) or any CI pipeline where no browser is available.
Both are first-class and supported. The difference is who they identify: an OAuth token is *you*, an API key is *the account*.
***
## OAuth tokens (default)
Running [`ironbee login`](/cli/get-started/getting-started#step-3-sign-in) opens your browser, asks you to authorize the CLI, and writes a personal access token to `~/.ironbee/config.json` under [`service.oauthToken`](/cli/configuration/configuration#service-identity) (older CLI versions wrote `collector.oauthToken`, which is still read as a fallback). It also persists `service.domain` — the stage you authenticated against — so the collector, API, and Console URLs all derive from one place (and any hand-set explicit URLs are dropped so they re-derive; pin the Console with `--console-url` if you need to). For a self-hosted deployment on non-standard hosts, no domain is inferred and the explicit URLs are kept instead. From then on the CLI authenticates as you, everywhere: event delivery to the Collector **and** the read-side API behind [`ironbee verify`](/cli/guides/verification-jobs).
```bash theme={null}
ironbee login
```
The login flow waits up to five minutes for you to confirm in the browser; press `Ctrl+C` to cancel. By default the token is named after your machine's hostname so you can recognize it later in the Console and pass `--name` to set your own label:
```bash theme={null}
ironbee login --name "work-laptop"
```
Each token appears on the [API Tokens page](/console/access-tokens) in the Console, where you can see when it was created, when it expires, and revoke it. CLI-minted tokens default to a 90-day lifetime.
### Token limit
You can hold at most **10 OAuth access tokens** per account at a time. This count includes expired tokens that you have not yet removed.
If you are already at the limit, `ironbee login` cannot mint a new one and prints:
```
You already have the maximum of 10 access tokens, so a new one could not be issued for the CLI. Revoke one on the IronBee Console's API Tokens page, then run "ironbee login" again
```
To free a slot, open the [API Tokens page](/console/access-tokens), revoke a token you no longer use, then run `ironbee login` again.
***
## API keys (CI and automation)
For automation that runs without a browser; the GitHub Action, scheduled jobs, scripts, use an account API key instead. Supply it through the `IRONBEE_SERVICE_API_KEY` environment variable (the legacy `IRONBEE_API_KEY` still works) so it never lands in a committed file:
```bash theme={null}
export IRONBEE_SERVICE_API_KEY=
```
The CLI reads it into [`service.apiKey`](/cli/configuration/configuration#service-identity). You can also set it on disk with `ironbee config set service.apiKey --global`, but the environment variable is preferred for CI because it [overrides every config layer](/cli/configuration/environment-variables).
Find and manage the account API key on the [Account page](/console/account) in the Console. Owners and admins can view, copy, and rotate it.
### Rotation and the grace window
Rotating the API key on the [Account page](/console/account) generates a fresh key and keeps the **previous key valid for 24 hours** for a grace window so your CI and integrations keep working while you roll the new key out. Only one grace key exists at a time:
* Rotating again while a grace key is still active permanently disables the earlier grace key (the Console asks you to confirm first).
* Use **Deactivate now** on the Account page to end the grace window immediately.
***
## Which credential the CLI uses
If both are present, the OAuth token takes priority on the wire. In practice:
| Situation | Credential | How to set it |
| ---------------------------- | ----------- | --------------------------------------------- |
| You, working locally | OAuth token | `ironbee login` |
| GitHub Action / CI | API key | `IRONBEE_SERVICE_API_KEY` secret |
| Scripted or headless machine | API key | `IRONBEE_SERVICE_API_KEY` or `service.apiKey` |
Both `IRONBEE_SERVICE_OAUTH_TOKEN` and `IRONBEE_SERVICE_API_KEY` override whatever is on disk, so a CI runner can supply a credential without touching `~/.ironbee/config.json`. The legacy `IRONBEE_OAUTH_TOKEN` / `IRONBEE_API_KEY` forms fill only the deprecated `collector.*` fallback keys — they're used **only when the matching `service.*` key is unset** (except by [`ironbee verify`](/cli/guides/verification-jobs#credentials), which treats `IRONBEE_API_KEY` as a top-priority override), so on a machine that has run a recent `ironbee login` (which writes `service.oauthToken`) prefer the `IRONBEE_SERVICE_*` forms. See [Environment variables](/cli/configuration/environment-variables) for precedence details.
***
## What's next?
Create, name, and revoke your personal OAuth access tokens.
View and rotate the shared account key used for CI.
# Interactive Mode (TUI)
Source: https://docs.ironbee.ai/cli/guides/interactive-mode
Manage IronBee from a full-screen terminal UI instead of individual commands.
`ironbee tui` opens a full-screen interactive terminal UI, a single place to browse your projects, toggle platforms, edit config, and inspect sessions without remembering individual commands.
It mirrors the CLI: anything you do in the TUI runs the same underlying logic as the matching command.
***
## Launch
```bash theme={null}
ironbee tui
```
This opens the home menu. You can also jump straight into a specific area:
```bash theme={null}
ironbee tui platforms
ironbee tui projects -p /path/to/project
```
| Argument / flag | Description |
| --------------- | -------------------------------------------------------------------------------------------------- |
| `[area]` | Open directly into an area: `config`, `platforms`, `projects`, `sessions`, `scenarios`, or `queue` |
| `-p ` | Start with a specific project as the active one (default: current directory) |
The TUI needs an interactive terminal. In a non-interactive context (CI, piped output) it exits with a hint to use the equivalent `ironbee config` commands instead.
***
## Areas
| Area | What you can do |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Configuration** | Browse and edit config keys across the global, project, and local layers; see the effective merged value and where it comes from |
| **Platforms** | Toggle the browser, Node, Python, backend, Android, and terminal cycles per layer — or press **`s`** to have a detected client suggest the set and apply it |
| **Projects** | Install, uninstall, register, or unregister for the current directory or any project in your inventory; switch which project is active |
| **Sessions** | Browse sessions with their phase, verdict, and retry counts; run a read-only verdict check |
| **Scenarios** | Browse [saved verification scenarios](/cli/guides/scenarios) with their freshness (fresh / stale / unknown vs the current code, plus a `(N draft)` marker for never-replayed step caches). The detail pane lists each `llm-action` step cache — state, baseline commit, live-validated / draft, covered paths. Read-only — repair is the agent's `/ironbee-sync-scenario` |
| **Queue** | Inspect and drain the background job queue; manage dead-letter entries |
Installing from the **Projects** area runs the same flow as the CLI: a client picker when more than one is detected, then a **mode single-select** (`enforce` / `assist` / `monitor` — the equivalent of `ironbee install --mode`; picking `enforce` adds the same [strictness](/cli/guides/verification#strict-mode) and [fix-enforcement](/cli/guides/verification#fix-enforcement-block-on-a-fail-or-just-report-it) sub-pickers, with Esc stepping back) and, unless you pick `monitor`, a **platform multi-select** (pre-checked from the project's current config — the equivalent of `ironbee install --platforms`) to choose which cycles to enable, including the same **`s` suggest** key. One difference: a TUI install never runs the [devtools prefetch](/cli/guides/managing-projects#devtools-prefetch-warming-the-first-mcp-start) — it tips you to run `ironbee devtools prefetch` in a terminal instead.
***
## Navigating
| Key | Action |
| ------------------------ | --------------------- |
| `↑` / `↓` (or `j` / `k`) | Move within a list |
| `Enter` | Select / open |
| `Esc` | Back to the home menu |
| `q` / `Ctrl-C` | Quit |
The breadcrumb at the top always shows the **active project**. In the Projects area you can switch which project is active, and every project-scoped area (Configuration, Platforms, Sessions, Queue) retargets to it, so you can launch in one repo and inspect or edit another without changing directories.
***
## What's next?
The keys behind the Config area, in full.
The commands behind the Sessions area.
# Issue Tracking
Source: https://docs.ironbee.ai/cli/guides/issue-tracking
Connect Jira, Linear, or GitHub Issues — verify against tickets, report results back, and attribute each session to the issues it closed.
IronBee can connect your project to an **issue tracker** — [Jira](#set-up-jira), [Linear](#set-up-linear), or [GitHub Issues](#github-issues) — and use it in two directions:
* **In the agent session:** the `/ironbee-issue-track` command reads a ticket, verifies your changes against its acceptance criteria, and reports the result back to the tracker — with the verification's screenshots and a deep-link to the session timeline in the Console.
* **In the Console:** [VCS linkage](#vcs-linkage-sessions-to-prs-and-issues) ties each agent turn to the pull request it produced and the issues that PR closes, so verification data is attributable to *"the work behind PROJ-123"* instead of an opaque session ID.
Several trackers can be connected at once — one integration surface carries all of them.
The issue-tracker integration is a **cross-cutting integration** (like telemetry or privacy mode), not a verification cycle: its tools never gate completion and don't count as verification evidence.
***
## Set up Jira
```bash theme={null}
ironbee integrations jira setup
```
The interactive flow walks you through everything and **validates the credential live before saving** (a wrong token aborts without writing anything):
1. **Base URL** — e.g. `https://acme.atlassian.net`. The deployment flavor (Cloud vs Server/Data Center) is auto-detected.
2. **Credential** — masked entry, with the token-creation URL shown: your **email + API token** for Cloud, or a **personal access token (PAT)** for Server/DC.
3. **Auth check** — a live `GET /myself` confirms the credential works.
4. **Write access** — whether IronBee may write to Jira (comments, transitions, the verification report). Default is **read-only**.
5. **Project keys** *(optional)* — an allow-list of issue-key prefixes (e.g. `PROJ`) used when [attributing issues](#vcs-linkage-sessions-to-prs-and-issues) from branch names and commit messages, so `UTF-8` or `SHA-256` never get mistaken for ticket keys.
6. **Scope** — enable for this project only, or for all your projects (`-g`).
Credentials are written to your **per-user global config** (`~/.ironbee/config.json`) — a Jira token identifies *you*, so it's never committed. Installed artifacts carry only a `${file:…}` reference that resolves at runtime; no secret is ever baked into a committed file. In CI, supply the credential via the [`IRONBEE_JIRA_API_TOKEN` / `IRONBEE_JIRA_PAT`](/cli/configuration/environment-variables#issue-tracker-credentials) env vars instead.
In a non-interactive shell, `setup` prints the equivalent `ironbee config set` commands so you can script it.
***
## Set up Linear
```bash theme={null}
ironbee integrations linear setup
```
Linear is cloud-only, so there's no base-URL step: paste your **Personal API key** (`lin_api_…`, masked entry, settings URL shown), IronBee runs a live GraphQL auth check, then asks about write access, an optional **team keys** allow-list (e.g. `ENG`), and the enable scope. As with Jira, the key lands in the global config and CI can supply it via [`IRONBEE_LINEAR_API_KEY`](/cli/configuration/environment-variables#issue-tracker-credentials).
Using an **OAuth access token** instead of a personal key? Set it with `ironbee config set integrations.linear.apiKey -g` plus `integrations.linear.oauth: true` (it changes how the token is sent).
***
## GitHub Issues
GitHub needs **no setup and no stored credential** — it's driven through the [`gh` CLI](https://cli.github.com), which owns its own auth. The integration is **automatically active** whenever `gh` is installed *and* authenticated (`gh auth status`). Run `ironbee integrations github setup` only to check the connection, grant write access, or opt out:
```bash theme={null}
gh auth login # if gh isn't authenticated yet
ironbee integrations github setup # optional — probe + writeEnabled + scope
```
Two GitHub-specific details:
* **Reports are comments.** GitHub's issue API has no file-attach endpoint, so the verification report is posted as an issue comment referencing the artifact paths plus the Console timeline link (rather than attaching the screenshots as files, like Jira/Linear do).
* **Codex sandbox:** on Codex, `gh` runs inside the tool sandbox, which blocks outbound network by default — so `gh issue view` can't reach `api.github.com` unless you enable sandbox network access (`[sandbox_workspace_write] network_access = true` in your Codex config). IronBee doesn't flip that switch for you (it's a session-wide network grant); install prints a pointer to the exact knob. Jira and Linear are unaffected.
***
## Suspend or re-enable a tracker
The integration activates by **configuration presence** — a configured Jira/Linear credential (or an authenticated `gh`) turns it on. To suspend one without deleting its config:
```bash theme={null}
ironbee integrations jira disable # suspend (config kept; artifacts stripped)
ironbee integrations jira enable # drop the kill-switch
```
Same for `linear` and `github`. Both re-render the installed client artifacts and accept the usual `-g` / `--local` / `--client` target flags. `ironbee integrations --help` lists every available provider.
***
## Using it: /ironbee-issue-track
Once a tracker is connected (and verification is in enforce or assist mode), install renders the issue-tracking surface into your client: the `/ironbee-issue-track` command in Claude Code, `$ironbee-issue-track` in Codex, and the matching skill in Cursor. On Claude Code and Codex it delegates to a dedicated **`ironbee-issue-tracker` sub-agent** (like the verifier — the tracker tools stay out of the main conversation); on Cursor the main agent drives the tools.
One command, four modes:
```bash theme={null}
/ironbee-issue-track PROJ-123 # full loop — read the ticket, verify the changes
# against its acceptance criteria, report back
/ironbee-issue-track read:PROJ-123 # intake only — read and digest the ticket
/ironbee-issue-track report:PROJ-123 # report the LAST verification to the ticket
# (never re-verifies; errors if none ran)
/ironbee-issue-track triage my open bugs # ad-hoc — any free-form tracker instruction
```
`[` can be an exact issue key or free text — the integration searches the tracker, proceeding on a single match and asking you to choose when there are several. With more than one tracker connected, pick one with an optional leading provider word: `/ironbee-issue-track linear ENG-42`.
**The report is evidence-backed.** After a verification, the integration recovers that cycle's capture artifacts (screenshots, snapshots) from the session log and attaches them to the ticket, together with a `🔗 View in IronBee` deep-link to the exact session timeline in the Console. Reviewers jump from the ticket straight to the run.
The command is installed in enforce and assist modes (in assist it's [user-invocable only](/cli/clients/claude-code#assist-mode-commands-are-user-only), never auto-invoked by the model). It's never proactive — issue-tracker operations run only when you ask.
***
## Read-only by default: write gating
A freshly connected tracker is **read-only**: the agent can read and search issues, and issue attribution works, but nothing writes back. Writes — commenting, attaching evidence, transitioning/closing, creating or linking issues, and the verification report — are gated behind `writeEnabled`, which `setup` asks about and you can flip anytime:
```bash theme={null}
ironbee config set integrations.jira.writeEnabled true
```
For Jira and Linear the gate is mechanical (the write tools aren't even exposed to the agent until it's on). For GitHub it's self-enforced — the agent checks the flag before writing, since `gh` is always reachable through the shell.
***
## VCS linkage: sessions to PRs and issues
Independent of the agent-facing command, IronBee links every agent turn to your version control — this is what makes a session's verification record reportable per issue in the Console:
1. Each agent turn is stamped with its **git ref** (repo, branch, commit).
2. A background worker resolves the **pull request(s)** the commit belongs to (via GitHub), retroactively — a PR opened an hour after the work is picked up on a later pass.
3. The turn's **issues** are attributed from every available signal: the GitHub issues the PR closes, the tickets the agent read during the session, plus issue keys mined from the branch name, commit messages, and the PR title — validated against the tracker (a key that doesn't resolve is dropped).
The result ships as one `vcs_link` event per agent turn, so the Console can show verification outcomes **per issue and per PR**. Each event carries a deterministic ID and is re-emitted whenever the resolution improves (a PR opened later, an issue transitioned), so the record catches up on its own. Attribution runs in every mode — enforce, assist, even monitoring-only — and auto-enables whenever a collector is configured; opt out with [`vcs.enable`](/cli/configuration/configuration#vcs-linkage). The `projectKeys` / `teamKeys` allow-lists from setup keep false positives out (and disambiguate Jira from Linear, since both use the `ABC-123` shape).
VCS linkage sends **repository and branch names** to the Collector, and branch names can carry sensitive text (`fix/CVE-…`, `feat/acme-corp-…`). It's independent of [privacy mode](/cli/advanced/privacy) (which gates devtools payloads) — opt out of the linkage itself with `ironbee config set vcs.enable false`.
***
## Config reference
Everything above maps to config keys — the [`integrations.*`](/cli/configuration/configuration#issue-tracker-integrations) section (credentials, write gating, allow-lists, kill-switches) and the [`vcs.*`](/cli/configuration/configuration#vcs-linkage) section (linkage toggle, cache TTLs, timeouts).
***
## What's next?
The `integrations.*` and `vcs.*` keys in full.
The verification cycles the full issue-track loop runs against a ticket.
# Managing Projects
Source: https://docs.ironbee.ai/cli/guides/managing-projects
Install, remove, track, and update IronBee across your projects.
Once the CLI is installed and you're signed in (see [Getting Started](/cli/get-started/getting-started)), these commands set IronBee up in a project, remove it, keep track of where it's installed, and keep the CLI itself current.
***
## Install IronBee in a project
Run the installer from your project root:
```bash theme={null}
ironbee install
```
IronBee detects your AI client (Claude Code, Cursor, or Codex) and wires up everything it needs: the completion hook, the verification skill and rule, the devtools MCP server, and the matching permissions. If it can't detect a client, it asks which one you use.
To target a specific client explicitly:
```bash theme={null}
ironbee install --client claude # Claude Code
ironbee install --client cursor # Cursor
ironbee install --client codex # Codex CLI
ironbee install --client all # every detected client
```
When you don't pass `--client` (and IronBee can't uniquely detect one), install shows a **checkbox multi-select** so you can set up **any combination** of clients in one pass — **space** toggles a client, **`a`** selects all, **Enter** confirms. With **no** client detected, the first client is pre-checked; with **several** detected, install shows the same picker with the detected clients pre-checked so you confirm (or trim) the set rather than silently installing into all of them. Confirming with nothing selected aborts. In a non-interactive shell (`-y`, CI, piped stdin), multiple detected clients are all installed without a prompt — the historical behavior.
]
(`--client all` does the same non-interactively — it installs for every detected client.)
The interactive flow then asks three more questions in order — **mode**, **platforms**, then **checks** — because choosing `monitor` makes the platform picker (and the checks step) moot and skips them.
### Choosing the verification mode
After resolving the client, install asks **which verification mode** to run. In an interactive terminal it shows an arrow-key single-select, pre-selecting the project's current mode (so re-installing keeps your choice; a fresh project defaults to `assist`):
```
Which verification mode?
↑/↓ move · enter confirm
auto verify (enforce) block task completion until changes are verified — full enforcement
> assist tools installed but not enforced — the agent verifies manually via /ironbee-verify (default)
monitor only no enforcement — only track sessions / activity / tools to the collector
```
Skip the prompt with `--mode`:
```bash theme={null}
ironbee install --mode assist # tools installed, manual /ironbee-verify only (default)
ironbee install --mode enforce # full enforcement — block completion until verified
ironbee install --mode monitor # monitoring-only — no enforcement, no platform picker
```
Picking `enforce` opens two follow-up pickers: [strictness](/cli/guides/verification#strict-mode) (non-strict / strict) and then [fix enforcement](/cli/guides/verification#fix-enforcement-block-on-a-fail-or-just-report-it) (fix-enforce / report-only). Skip them with `--strict` (its absence keeps the existing or default non-strict choice) and `--fix` / `--no-fix` — all enforce-only; a non-interactive `--mode enforce` skips both pickers regardless.
The choice is written explicitly to the committed project config (`verification.enable` / `verification.auto`), so it's equivalent to the [`ironbee verification` toggles](/cli/guides/verification#verification-modes). For `assist` and `enforce`, install also records [`verification.strict`](/cli/guides/verification#strict-mode) and [`verification.fix`](/cli/guides/verification#fix-enforcement-block-on-a-fail-or-just-report-it) at their defaults (a choice you already made is kept). Any existing [`verification.model`](/cli/guides/verification#picking-the-verifier-model) is preserved. The picker default reads the project's **own** committed/local config (the machine-global config is ignored), so a fresh project defaults to `assist` even on a machine running monitoring-only globally. In a non-interactive shell with no `--mode` flag, the verification config is left untouched.
### Choosing which platforms to verify
Unless you picked `monitor`, install then asks **which verification platforms** (cycles) to enable. In an interactive terminal it shows an arrow-key multi-select, pre-checked from the project's current config (so re-installing keeps your choices; a fresh project defaults to browser-only):
```
Which platforms should require verification?
↑/↓ move · space toggle · a all · s suggest · enter confirm
[x] browser web UI · DOM · console · a11y · screenshots · recording
[ ] node Node.js runtime · tracepoints · logpoints · exceptions · variables · logs · HTTP capture
[ ] python Python runtime (debugpy) · tracepoints · logpoints · exceptions · thread dumps · logs · HTTP capture
[ ] backend HTTP · gRPC · GraphQL · WebSocket · DB · logs
[ ] android device/emulator · taps · swipes · screenshots · UI snapshots · Logcat · HTTP
[ ] terminal CLI / REPL / TUI driving over a PTY · send keys · capture output · exit codes
```
The picker also offers an **`s` "suggest"** key. Press it to have IronBee analyze your project with a headless prompt and **replace** the current selection with a recommended set of cycles; you can still adjust it before pressing Enter. All three clients can run the analysis — Claude Code, Codex, and Cursor — and when several are selected it uses the highest-priority one (`claude > codex > cursor`). It's opt-in (nothing runs until you press `s`), and if the analysis is cancelled (Esc), times out, or fails, your current selection is kept.
When the analysis finishes, IronBee **replaces** your checkboxes with its recommendation (here browser, node, and backend) — still editable before you press Enter:
Skip the prompt with `--platforms` (a comma-separated subset of `browser,node,python,backend,android,terminal`):
```bash theme={null}
ironbee install --platforms browser,node # enable just these two
ironbee install --platforms "" # disable all cycles (incl. the default-on browser)
```
The selection is written to the committed project config before the artifacts render, so it's equivalent to running the [`ironbee browser` / `node` / `python` / `backend` / `android` / `terminal`](/cli/guides/verification#enable-or-disable-a-platform) toggles. Install records the **full** platform state explicitly — an `enable` flag for every cycle (`browser`, `node`, `python`, `backend`, `android`, `terminal`) — so the committed `config.json` plainly shows what's on and what's off. In a non-interactive shell with no `--platforms` flag (or in monitoring-only mode, including a just-chosen `--mode monitor`), the platform config is left untouched.
### Choosing your project checks
Beta — the suggested commands are a starting point to review, not a finished config.
The last step (skipped in monitoring-only mode, or when no headless-capable client is available) offers to set up [project checks](/cli/guides/verification#project-checks-run-first-lint-tests-types) — deterministic lint / typecheck / test / build / format commands IronBee runs as the first step of every verification cycle. In an interactive terminal it asks a yes/no first (default **No**); if you accept, it analyzes your project with your AI client and proposes concrete commands for you to approve.
Control it non-interactively with a tri-state flag:
```bash theme={null}
ironbee install --checks # run the analysis and accept the suggested set (skip the yes/no gate)
ironbee install --no-checks # skip the checks step entirely
```
With no flag, checks are offered only on an interactive terminal and skipped otherwise. This is the same flow as the standalone [`ironbee checks suggest`](/cli/guides/verification#let-ironbee-suggest-your-checks) command, which you can re-run anytime; re-suggesting is additive, so it never clobbers checks you've hand-tuned.
### DevTools prefetch (warming the first MCP start)
The devtools MCP server is launched via `npx` against a [pinned version](#the-devtools-pin), so the very first start on a machine downloads the package **and** the Playwright browser binaries — cold enough to blow past some MCP hosts' startup timeout. To avoid that, `ironbee install` finishes by **prefetching** the pinned devtools into the npx cache (with live download progress), matched to the browsers your rendered setup actually needs. A prefetch failure never fails the install — the first MCP start just installs lazily instead.
It runs automatically on an interactive install (skipped under `--json`, in a non-interactive shell, or when installing from the [TUI](/cli/guides/interactive-mode), which tips you to run it standalone) and is controlled with a tri-state flag:
```bash theme={null}
ironbee install --prefetch # force the prefetch, even non-interactively
ironbee install --no-prefetch # skip it — the first MCP start installs lazily
```
Set the [`IRONBEE_NO_PREFETCH`](/cli/configuration/environment-variables#advanced) env var as a global kill-switch. On the install path, monitoring-only projects (no devtools artifacts) and custom `ironbeeDevTools.mcp` entries are skipped automatically. An interactive `ironbee browser enable` also prefetches (it's the moment a browser-less warm cache would need browser binaries). And you can warm the cache standalone, anytime:
```bash theme={null}
ironbee devtools prefetch # warm the pinned devtools for this project
ironbee devtools prefetch --browsers chromium # override the browser set (csv; also firefox, webkit, chromium-headless, none)
ironbee devtools prefetch -p --json # target another project; {ok, status, spec, browsers, detail}
```
Unlike the install step, the standalone command is deliberately permissive — a project with no rendered devtools entry (monitoring-only included) warms a default `chromium` plan anyway; pass `--browsers none` for a package-only warm. Exit codes: `0` completed (including already-warm), `1` failed, `2` skipped (npx unavailable or the kill-switch set). When a CLI upgrade triggers the [auto re-render](#auto-re-rendering-after-an-upgrade), that pass re-runs the prefetch across your registered projects too; a patch that changes nothing structural doesn't, so after a pin-only bump run `ironbee devtools prefetch` yourself.
### Unattended installs
For scripts and CI, `install` can run with zero prompts:
```bash theme={null}
ironbee install --client claude --mode enforce --platforms browser,node \
--no-checks --yes --json
```
| Flag | Description |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-y`, `--yes`, `--non-interactive` | Force zero prompts even under a TTY. Any choice you didn't pass a flag for falls back to the flag / existing config / defaults. |
| `--json` | Emit a machine-readable summary to stdout (`{ ok, project, clients, mode, strict, fix, platforms, checks, prefetch }`); decorative logs go to stderr. |
Restart your AI coding client after installing so it picks up the new hooks and tools.
### Install everywhere at once
IronBee keeps an inventory of every project you've installed it into (see [The project inventory](#the-project-inventory) below). To re-run install across all of them (handy after changing a global setting):
```bash theme={null}
ironbee install --all
```
With `--json`, the `--all` form emits a roll-up envelope instead of the single-project one: `{ ok, all: true, total, failures, prefetch }`.
***
## Remove IronBee from a project
```bash theme={null}
ironbee uninstall
```
This removes the hooks, skill, rule, MCP server entry, and permissions IronBee added, deletes the project's `.ironbee/` directory, and drops the project from the inventory.
| Option | Description |
| ----------------- | --------------------------------------------------------------------------------- |
| `--client ` | Only remove a specific client's setup (`claude`, `cursor`, `codex`, or `all`). |
| `--all` | Remove IronBee from **every** registered project. Prompts for confirmation first. |
| `-y`, `--yes` | Skip the confirmation prompt (required with `--all` in scripts/CI). |
```bash theme={null}
ironbee uninstall --all # asks before wiping every project
ironbee uninstall --all --yes # no prompt — for scripts
```
***
## The project inventory
IronBee tracks the projects it's installed in at `~/.ironbee/projects.json`. This inventory is what `install --all` and global config changes use to know which projects to update.
You normally don't manage it by hand; `ironbee install` adds a project automatically, and `ironbee uninstall` removes it. Two commands let you adjust the inventory **without touching any installed files**:
```bash theme={null}
ironbee register # add the current project to the inventory
ironbee unregister # remove the current project from the inventory
```
* **`register`** - retrofit a project that was set up manually (or before the inventory existed) so it shows up for `install --all` and global-config notices. No artifacts are written.
* **`unregister`** - drop an entry without uninstalling anything. Works even if the project directory has already been deleted.
Both accept `-p, --project ` to target a directory other than the current one.
***
## Update the CLI
Check for a newer release and update in place:
```bash theme={null}
ironbee update
```
The command compares your installed version against the npm registry, updates to the latest if one exists, and warns you if your shell would otherwise keep resolving an older copy on your `PATH`. You can always update manually instead:
```bash theme={null}
npm install -g @ironbee-ai/cli@latest
```
Restart your AI coding client after updating to use the new version.
### Auto re-rendering after an upgrade
Occasionally a new release changes the **structure** of the files install writes into a project — hook configs, the skill/rule/agent files, MCP entries, the verifier sub-agent. When that happens, IronBee re-renders every [registered project](#the-project-inventory) so they all pick up the new structure, without you running `install --all` by hand.
* It triggers right after the upgrade (the npm `postinstall`, including via `ironbee update`) and, as a fallback, on your next interactive `ironbee` command.
* It's **non-destructive**: re-rendering preserves your config — mode, platforms, the verifier model, and any custom verify patterns are kept.
* In an interactive terminal you get a one-key **"Press Enter to update them now…"** acknowledgement before it runs. In any non-interactive context (pipes, CI, agent-fired hooks) it **defers** rather than re-rendering silently, so the next interactive run picks it up.
* Routine patches that don't change the file structure re-render nothing.
To suppress the auto re-render entirely (CI, locked-down machines), set [`IRONBEE_NO_AUTO_RERENDER`](/cli/configuration/environment-variables#advanced) — or rely on `CI` being set, which also short-circuits it.
### The devtools pin
Each CLI release drives one **exact, pinned** version of the `@ironbee-ai/devtools` package — the pin is baked into every rendered MCP server entry (`npx -y @ironbee-ai/devtools@`), so a given CLI build always runs one immutable devtools build. The pin is a build-time constant, deliberately **not** a config key (point `ironbeeDevTools.mcp` at your own entry if you need a different build). Read it programmatically:
```bash theme={null}
ironbee devtools version # bare version on stdout, script-friendly: 0.37.0
ironbee devtools version --json # {"name":"@ironbee-ai/devtools","version":"0.37.0","spec":"@ironbee-ai/devtools@0.37.0"}
```
The output carries nothing else (no banner, no update notice), so `V=$(ironbee devtools version)` is safe in scripts — it's the contract for downstream tooling that bundles or pre-fetches devtools at its own build time.
***
## What's next?
Choose which platforms get verified and switch between enforcement and monitoring-only.
Manage projects, platforms, and sessions from a full-screen terminal UI.
# Scenarios
Source: https://docs.ironbee.ai/cli/guides/scenarios
Author, search, and re-run reusable verification scenarios so the agent verifies the right flows the same way every time.
A **scenario** is a reusable, saved verification script — "log in as admin, open billing, confirm the invoice total updates" — captured once and replayed on demand. Instead of re-describing what to verify (or letting the agent re-discover it) on every run, you build up a small library of scenarios the verifier can run directly. Scenarios are **committed to the repo**, so your whole team (and CI) shares them.
A scenario drives one or more [verification platforms](/cli/guides/verification#verification-platforms) — a browser scenario drives the browser, an Android scenario the device, a cross-platform one both — and is stored as a script (or a list of [typed steps](#steps-setup-and-teardown)) the `ironbee-devtools` server can execute.
Saved scenarios are installed in **enforce** and **assist** modes (the same gating as the verifier). In **monitoring-only** mode the scenario commands and sub-agent aren't installed.
***
## The commands
Four agent-invoked slash commands manage scenarios. On Claude Code and Cursor they're `/`-prefixed; on Codex use the `$` mention syntax (`$ironbee-manage-scenario`).
| Command | What it does |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `/ironbee-manage-scenario` | **Add, update, or delete** a scenario. By default it authors the script against your **running app**, then saves it. |
| `/ironbee-search-scenario` | **Find** saved scenarios by name, description, or metadata (e.g. a covered path). Read-only. |
| `/ironbee-run-scenario` | **Run** a saved scenario — see [Run a saved scenario](#run-a-saved-scenario). |
| `/ironbee-sync-scenario` | **Re-validate and repair** saved scenarios that have drifted as the code changed. |
Like the verifier, on Claude Code and Codex these **delegate to a dedicated `ironbee-scenario` sub-agent** that owns the scenario tools (and, like the verifier, can't edit your code — the scenario store is written server-side). On Cursor (and Codex in `main-agent` mode) the main agent drives the tools directly.
### Author a scenario
```bash theme={null}
/ironbee-manage-scenario log in as admin, open /billing, confirm the invoice total updates
/ironbee-manage-scenario ./scenarios/checkout.md # author from a file's contents
/ironbee-manage-scenario draft a smoke test of the home page # `draft` = author from source only
```
By default authoring is **live**: the agent drives your running app to understand it (navigate, log in, click, snapshot — the same way a verification run does), writes the script from what it actually observes, validates it by running once, and tears down anything it started. If the app can't be started it falls back to a **source-only draft**, and a leading `draft` token forces source-only authoring up front.
The sub-agent decides add-vs-update (it checks for an existing same-name scenario first), picks the right cycle, declares any [parameters](#parametric-scenarios) the script takes, and stamps metadata. A delete or a fuzzy-matched update asks you to confirm the matched scenario first.
### Search scenarios
```bash theme={null}
/ironbee-search-scenario checkout # fuzzy over name + description
/ironbee-search-scenario covers src/billing/invoice.ts # metadata match (e.g. a covered path)
```
It searches every enabled cycle's store and returns the matches (name, description, cycle, and a relevance score for fuzzy searches).
***
## Parametric scenarios
A scenario script reads its inputs from an `args` binding — `const { baseUrl } = args;` — so the same flow can run against different values. Each input is declared up front as a **typed parameter**, so the scenario carries its own input contract: defaults, types, and which values are required all travel with the script.
When the agent authors a parametric scenario it captures sensible **defaults from the live-authoring run**, so the scenario re-runs "as captured" with zero arguments — you only pass `args` to *override* a default. Each parameter declares:
| Field | Purpose |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | The `args` key the script reads (e.g. `baseUrl`). Required. |
| `description` | What the parameter is, for the agent and for humans. |
| `type` | `string`, `number`, `boolean`, `object`, or `array`. Omit for an untyped passthrough; `object` / `array` are shallow-checked at the top level only. |
| `default` | Applied when the caller omits the argument (captured from the authoring run). |
| `example` | A documentation-only shape, surfaced when there's no `default`. Never injected or validated. |
| `required` | Rejects the run when there's no value **and** no `default`. |
On every run the parameters are enforced: defaults fill in omitted arguments, `required` values must be present, and declared types are shallow-validated — a wrong-type or missing-required run **fails loudly** instead of silently passing `undefined` to the script. The declared parameters ride along in search and run output, so a scenario's contract is visible without opening the script.
Parameters are first-class — the agent manages them through `/ironbee-manage-scenario`, and they supersede the older `argsSchema` metadata convention. A scenario with no declared parameters keeps a fully-opaque `args` passthrough (its expected shape is documented in the scenario's description).
***
## Steps, setup, and teardown
A scenario can be a single `script`, or — with `formatVersion: 2` — a **step-ful** scenario: an ordered list of typed steps under `body.steps`, each reported (and cached, and repaired) individually:
| Step type | What it runs |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `script` | Sandbox JavaScript with `callTool(...)`, `args`, a shared mutable `ctx`, and `assert`. |
| `tool-call` | One devtools call as data: `tool` + `input` (values may reference `{{args.}}` / `{{ctx.}}`), optional `assignTo` to keep the output in `ctx`. |
| `command` | A host shell command; `{ stdout, stderr, exitCode }` lands in `ctx` via `assignTo`. Non-zero exit fails the step unless `allowNonZeroExit: true`. |
| `llm-action` | A natural-language `intent` the run can't execute deterministically — the run **pauses** and the agent realizes it. Must be named: the name is its [cache key](#steps-that-need-an-agent-llm-action). |
| `group` | A reporting-only container that nests other steps under one name. |
| `include` | Splices another saved scenario's steps in (with static `args`, and `as:` to give it a nested `ctx` root). |
Two optional **lifecycle sections**, `setup` and `teardown`, are peers of `body` with the same `steps` shape — but `script` and `command` steps **only** (no `tool-call`, `group`, `llm-action`, or `include`; a pausing step could strand the cleanup). Setup runs before the body and a setup failure skips it; **teardown always runs**, however the run ended, and its failures are reported separately without changing the run's verdict. A scenario that another scenario `include`s skips its own setup/teardown by default — opt in with `"whenReused": "run"`.
A scenario (step-ful or single-script) also declares `requiredPlatforms` (e.g. `["browser", "backend"]`) — the run refuses up front when a required cycle isn't enabled, instead of failing midway (an `include`d scenario's requirements are unioned in automatically). The remedy is `ironbee enable` plus a fresh agent session, since the devtools server reads its platform set at startup.
### Steps that need an agent (`llm-action`)
The first time a run reaches an `llm-action` step, it pauses; the agent drives the app to realize the intent, and the run captures what the agent did as a **replayable script** in the scenario's sibling cache file, `.cache.json` — committed alongside the scenario and reviewed in PRs like any other change (an `llm-action` inside an `include`d scenario caches into the *included* scenario's own file, so that cache is shared by every scenario that includes it). Every later run **replays the cache** instead of pausing, so a scenario that needed an agent once runs deterministically from then on. The cache re-materializes only when the runtime has marked it broken or stale — a failed warm replay pauses the run for a **self-heal**, showing the broken script for the agent to repair — or when you force it with `refresh:`. A `[static guess]` stale verdict from [`ironbee scenario status`](#ironbee-scenario-status) is detection only; it never changes what a run replays.
Cache scripts call tools by their **bare** devtools name (`bdt_navigation_go-to`), not the MCP wire name your client shows (`mcp__ironbee-devtools__bdt_navigation_go-to`). `ironbee scenario tool-name ` translates one to the other. The scenario tools themselves (`scenario-run`, search, CRUD) live under the compose server's shared `ibdt_*` prefix, alongside the per-cycle `bdt_*`/`ndt_*`/… families. Never edit a `.cache.json` by hand — the run itself is the only write channel.
***
## Run a saved scenario
Once a scenario exists, run it with `/ironbee-run-scenario` (`$ironbee-run-scenario` on Codex) — by exact name or a semantic description (the agent picks the best match and asks if it's ambiguous):
```bash theme={null}
/ironbee-run-scenario checkout flow # run by name or description
/ironbee-run-scenario checkout flow args:{"baseUrl":"http://localhost:8080"} # override a param for this run
/ironbee-run-scenario step checkout flow # pause after every step, for a guided walk-through
/ironbee-run-scenario refresh:all checkout flow # re-drive every cached step live instead of replaying
```
A leading `step` token pauses the run after **every** step; `refresh:` (or `refresh:all`) forces the named [cached steps](#steps-that-need-an-agent-llm-action) to re-run live instead of replaying their cache. To run a [parametric scenario](#parametric-scenarios) against different values, add a trailing `args:{...}` JSON object — it overrides the scenario's captured defaults for that run only (omitted params keep their defaults; the same typed-parameter validation still applies). Without it, a saved scenario re-runs exactly as captured.
Under the hood the devtools server executes the scenario's deterministic steps itself and **pauses** only when a step needs an agent — the agent acts (drives the app to realize the step's intent), then **resumes** the same run where it left off. On Claude Code and Codex (in the default `sub-agent` delivery) this loop runs inside the `ironbee-scenario` sub-agent; on Cursor — and Codex in `main-agent` mode — the main agent drives it inline. Follow it live from a second terminal with [`ironbee scenario progress --watch`](#watch-a-run-live).
Running a scenario is **not a verification cycle** — it opens no gate, submits no gated verdict, and doesn't satisfy the completion gate (use [`/ironbee-verify`](/cli/guides/verification#verify-only-vs-fix-mode) to verify code changes). The run is still fully recorded: it appears on the session timeline as a `scenario`-kind span with a **per-step timeline** — each step is its own start/end interval with the tool calls it drove nested under it — plus a visibility verdict listing each assertion that passed or failed, so the Console shows exactly what the run did and checked. Earlier CLI versions accepted a `scenario:[` reference on `/ironbee-verify` — that form is gone; `/ironbee-run-scenario` is how a saved scenario runs.
]
***
## Where scenarios are stored
Saved scenarios are committed under a single flat store, `.ironbee/scenarios/` — one `.json` per scenario, plus a sibling `.cache.json` for a [step-ful scenario's](#steps-that-need-an-agent-llm-action) captured `llm-action` scripts. The `ironbee-devtools` compose server registers the scenario tools once for the whole project rather than per cycle. A scenario can therefore be **cross-platform**: one script may drive several cycles' tools (for example a `bdt_*` browser step followed by a `bedt_*` backend check), authored as a single scenario rather than split per platform. The platform label `ironbee scenario status` and the [TUI](/cli/guides/interactive-mode) scenarios area display comes from the scenario's top-level [`requiredPlatforms`](#steps-setup-and-teardown) field (joined with `+` for cross-platform ones); the older `ironbee.platform` / `ironbee.platforms` metadata is still read as back-compat for scenarios that predate it.
Unlike the per-session `sessions/` data, the scenario store is **not gitignored** — scenarios are repo content meant to be reviewed in PRs and shared with the team, the same trust level as `.ironbee/VERIFICATION.md`. The store is committed and client-agnostic (it isn't per-client).
A scenario can also be saved with `scope: global` (say it when authoring via `/ironbee-manage-scenario`), which stores it at `~/.ironbee/scenarios/` — personal, cross-project, not committed. `ironbee scenario status` and `coverage` read only the **project** store, so global scenarios don't appear in freshness or coverage output.
Older installs wrote one folder per cycle (`.ironbee/scenarios/bdt/`, `ndt/`, `pdt/`, `bedt/`, `adt/`, `tdt/`). That layout is still read for back-compat — its scenarios are unioned with the flat store — so existing scenarios keep working without migration.
***
## Keep scenarios fresh
Saved scenarios rot as the code they cover evolves. Two **pure-code** commands (no LLM, no app run) tell you where things stand — useful both at the terminal and as CI gates. (These, like `scenario progress`, accept `-p, --project ` to target another project.)
### `ironbee scenario status`
Reports the freshness of every saved scenario against the current code by git-diffing each scenario's covered paths since the commit it was authored at:
```bash theme={null}
ironbee scenario status # fresh / stale / unknown per scenario
ironbee scenario status --stale # only stale ones; exits non-zero if any exist (CI gate)
ironbee scenario status --verbose # also list each llm-action step cache (baseline, draft, covered paths)
ironbee scenario status --json # machine-readable
```
* **fresh** — no covered file changed since the scenario was authored.
* **stale** — covered files changed since then (or it was saved as an unvalidated draft).
* **unknown** — can't tell: not a git repo, no covered-path / commit baseline, the baseline commit isn't in history (shallow or rewritten clone), or it isn't an ancestor of `HEAD` (divergent branch).
A [step-ful scenario](#steps-setup-and-teardown) is judged **per step**: each cached `llm-action` step is classified from its own baseline commit and covered paths, then rolled up — any stale step makes the scenario stale, any unassessable one makes it unknown. A declared step that has **no cache entry yet** (never run) reports `unknown`, not fresh. A stale verdict also says *what it rests on*, strongest first: `[replay failed]` (a warm replay actually broke), `[flagged]` (the run marked the cache stale), or `[static guess: covered files changed — may be behaviour-neutral]` (a git diff over the declared paths). A trailing `(N draft)` marker flags caches that were authored or healed but never successfully replayed — advisory only.
### `ironbee scenario coverage`
The inverse: changed code that **no** saved scenario covers — i.e. where you might want to author a new one. It resolves the current change set (working tree ∪ the last [`verification.context.commitDepth`](/cli/configuration/configuration#verification) commits), filters it to verification-relevant files (the same patterns the gate uses, so docs, lockfiles, and test files drop out), and lists the ones no scenario's covered paths match.
```bash theme={null}
ironbee scenario coverage # changed, verification-relevant files with no scenario
ironbee scenario coverage --commit-depth 0 # working tree only
ironbee scenario coverage --json
```
Coverage is **advisory** (covered paths are author-declared, so a gap can be a false positive) — most changes legitimately need no scenario, so it has no exit gate.
### Repair drift with `/ironbee-sync-scenario`
`scenario status` only *detects* staleness; repairing it is the agent-driven `/ironbee-sync-scenario`, which re-runs the target scenario against the live app and fixes drift:
```bash theme={null}
/ironbee-sync-scenario all # re-run + repair stale scenarios, stamp them current
/ironbee-sync-scenario check all # dry-run — report drift, change nothing
/ironbee-sync-scenario force all # re-validate every scenario, not just stale ones
/ironbee-sync-scenario checkout # a single scenario by name or description
```
Sync repairs **mechanical** drift only — the way the flow is driven (a renamed selector, a moved route) — and **never** changes *what* a scenario asserts (that would mask a regression). When it hits a real defect it stops and reports instead of editing the scenario; when an expectation genuinely changed it asks you. A leading `check` token makes it a dry-run; `force` re-validates everything rather than just the stale set. It's not a verification cycle — it submits no verdict and doesn't gate completion.
Browse freshness without running anything from the [TUI](/cli/guides/interactive-mode) **Scenarios** area — a read-only fresh/stale/unknown view of every saved scenario. Repair is still the agent's `/ironbee-sync-scenario`.
***
## Watch a run live
On Claude Code and Codex (sub-agent delivery) a scenario runs inside the `ironbee-scenario` sub-agent, so its step-by-step progress doesn't stream into your conversation. `ironbee scenario progress` shows the live state of the current (or last) run from a second terminal:
```bash theme={null}
ironbee scenario progress # one snapshot of the current/last run
ironbee scenario progress --watch # follow it live (q or Ctrl-C to stop)
ironbee scenario progress --json # machine-readable
```
`--watch` draws a full-screen pane (in the alternate screen buffer, like `less`) and redraws as the run advances. It shows the **whole scenario's step tree by name** — including steps the run hasn't reached yet — with per-step glyphs (`✓` passed, `✗` failed, `⊘` skipped, `.` not reached, `>` running), `[setup]` / `[teardown]` phase tags, whether each step ran from `(cache)` or `(live)`, the currently-pending step's intent (and self-heal reason, when a cache broke), and a footer with the verdict and assertion counts. The pane fits your terminal, follows the newest output, and is scrollable: `↑`/`↓` (or `k`/`j`) scroll, `PgUp`/`PgDn` page, `g`/`G` jump to top/bottom (`G` re-arms live-follow), `q` quits.
| Flag | Description |
| --------------------- | -------------------------------------------------------------- |
| `--watch` | Redraw as the run advances (Ctrl-C to stop). |
| `--session ` | Watch one session (default: the one that last ran a scenario). |
| `--interval-ms ` | Poll interval for `--watch` (default 400, min 100). |
| `-p, --project ` | Target a project other than the current directory. |
***
## What's next?
Choose which platforms get verified and switch between enforce, assist, and monitoring.
Give the agent area-specific instructions with `.ironbee/VERIFICATION.md` files.
# Verification
Source: https://docs.ironbee.ai/cli/guides/verification
Choose which platforms IronBee verifies, and switch between enforcement and monitoring-only.
When your agent finishes editing code, IronBee runs **verification cycles** to confirm the change actually works before the task can complete.
`ironbee install` walks you through three setup choices **in this order** — and each section below shows that install step first, then the command to change it later:
1. **[Mode](#verification-modes)** — enforce, assist, or monitoring-only (and, for enforce, how [strict](#strict-mode) to be and whether a failing verdict [blocks or just reports](#fix-enforcement-block-on-a-fail-or-just-report-it)).
2. **[Platforms](#verification-platforms)** — which runtime cycles gate a change (browser, node, python, backend, android, terminal).
3. **[Project checks](#project-checks-run-first-lint-tests-types)** — deterministic lint / test / typecheck commands to run first.
The rest of the page covers [how the verifier runs](#how-verification-runs-the-verifier-sub-agent), [verify-vs-fix](#verify-only-vs-fix-mode), [N/A verdicts](#when-a-change-has-nothing-to-verify-na-verdicts), and [custom scenarios](#custom-verification-scenarios).
***
## Verification modes
IronBee runs in one of **three modes**, set by two switches: the master toggle (`verification enable` / `disable`) and the automatic-enforcement sub-toggle (`verification auto enable` / `disable`). The default is **assist** — the verifier is installed but never blocks completion.
You normally pick the mode **while you [install](/cli/guides/managing-projects#choosing-the-verification-mode)** — the arrow-key pickers shown in this section are exactly what `ironbee install` presents (mode, then, for enforce, [strictness](#strict-mode)). Pass `--mode enforce|assist|monitor` to skip the prompt, or use the `verification` commands below to switch afterward.
### Assist mode (default)
The machinery is installed the [`/ironbee-verify`](#verify-only-vs-fix-mode) command, the verifier sub-agent, the devtools MCP server, and permissions so the agent (or you) can verify **manually**, but nothing is enforced: no verify gate blocks completion, the pre-edit hooks run non-blocking, and the always-on skill/rule are omitted. This is what a fresh install resolves to.
Assist keeps verification *available* but never *required* — the agent can verify on demand (and every manual cycle is recorded to the Collector) without a gate that blocks task completion. Assist is also **manual-trigger-only**: the installed commands are marked user-only (the model can't auto-invoke them, and their descriptions don't cost context tokens) and the verifier/scenario sub-agents carry a non-proactive stance, so nothing fires unless you ask — see [Claude Code → Assist mode: commands are user-only](/cli/clients/claude-code#assist-mode-commands-are-user-only). To switch to it later:
```bash theme={null}
ironbee verification auto disable # assist (default) — manual /ironbee-verify only, nothing enforced
```
### Enforce mode
The agent must pass every active cycle before it can mark a task complete. The blocking verify gate, the always-on skill and rule, the [`/ironbee-verify`](#verify-only-vs-fix-mode) command, the verifier sub-agent, and the devtools MCP server are all installed.
Enforce is opt-in — turn on the automatic-enforcement sub-toggle:
```bash theme={null}
ironbee verification auto enable # enforce — block task completion until every active cycle passes
ironbee verification auto disable # back to assist (the default)
```
`ironbee verification enable` only flips the master toggle; the mode it resolves to still depends on `auto` (assist unless you've also run `verification auto enable`).
### Strict mode
Enforce has two **follow-up choices** at install — how [strict](#strict-mode) the gate is about N/A verdicts, and whether a failing verdict [blocks or just reports](#fix-enforcement-block-on-a-fail-or-just-report-it) (assist and monitoring skip both — there's no gate to enforce).
The first is **how strict** the gate is about [N/A verdicts](#when-a-change-has-nothing-to-verify-na-verdicts) — the verifier's way of declaring a change has no runtime surface to exercise (a type-only refactor, a docs tweak). When you pick enforce, install shows its picker right away.
**Non-strict** *(default)* lets the agent skip changes with nothing to exercise — refactors, type-only edits, docs:
**Strict** always makes the agent actually exercise the change — no cycle can be skipped:
To set it later (rather than at install):
```bash theme={null}
ironbee verification strict enable # reject all N/A verdicts — every active cycle needs real evidence
ironbee verification strict disable # back to the default — N/A verdicts accepted (and recorded)
```
With strict on, a verdict that tries to mark a cycle not-applicable is **blocked**, and the agent has to produce the cycle's required tools. Strict only matters in **enforce mode** (in assist and monitoring-only there's no gate to enforce it). It's read live by the gate, so it takes effect on the next session without re-rendering artifacts. Strict maps to the [`verification.strict`](/cli/configuration/configuration#verification) config key and accepts the usual `-g`/`--global` and `--local` target flags. For how N/A verdicts work in the first place, see [N/A verdicts](#when-a-change-has-nothing-to-verify-na-verdicts) below.
### Fix enforcement (block on a fail, or just report it)
Enforce mode actually enforces **two** things: that the agent *verifies* at all (it can't edit code and finish without running the cycle), and that the *outcome* is a pass (a failing verdict blocks completion until the agent fixes the issues, up to [`maxRetries`](/cli/configuration/configuration#core-options)). The second follow-up choice — **fix enforcement** — decouples them. Install shows it as a picker right after strictness, with two options: **fix-enforce** *(default)* and **report-only**.
With fix enforcement **off** (report-only), the agent still must run every active cycle and submit a real verdict — but a **fail** verdict no longer loops it. The gate lets the turn end, records the verdict as *reported, not enforced*, and instructs the agent to state the unresolved issues plainly rather than claim the change works. Retries aren't consumed. Think of it as a third point between full enforce (auto-verify + fix until pass) and assist (nothing enforced): **verification is mandatory, fixing is your call**.
```bash theme={null}
ironbee verification fix disable # report-only — a failing verdict is reported, not looped on
ironbee verification fix enable # back to the default — a failing verdict blocks until fixed
```
It maps to the [`verification.fix`](/cli/configuration/configuration#verification) config key (default `true`), accepts the usual `-g`/`--global` and `--local` target flags, is read live by the gate, and only matters in enforce mode. At install, pass `--fix` / `--no-fix` with `--mode enforce` to skip the picker.
The manual [`/ironbee-verify fix`](#verify-only-vs-fix-mode) token **escalates a single run** to fix-until-pass regardless of this setting — the config is the sticky default, and the token only ever escalates (it never downgrades an enforced fix loop).
### Monitoring-only mode
The agent is never blocked and none of the verification machinery is installed no enforcement hook, skill, rule, command, verifier sub-agent, or MCP server but session lifecycle, tool calls, file changes, and timing still flow to the IronBee Collector. Use this when you want the session record without changing how the agent works.
Switch to it (or back) anytime:
```bash theme={null}
ironbee verification disable # monitoring-only — no machinery, tracking only
ironbee verification enable # re-enable verification (resolves to assist unless auto is on)
```
`auto` only matters while verification is enabled. If `verification.enable` is `false` (monitoring-only), the mode is monitoring regardless of `auto`, and `ironbee verification auto …` warns that it has no effect until you re-enable verification.
The master and `auto` toggles accept the same target flags as everything else (`-g`/`--global`, `--local`; default is the project config) and warn when a higher-priority layer is shadowing the layer you wrote to.
Restart your editor or agent session after toggling; the change takes effect on the next session.
***
## Verification platforms
Each platform is a separate cycle with its own tools. IronBee installs all six, but only some are active by default:
| Platform | Default | What it verifies | Tool prefix |
| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| **Browser** | On | Frontend changes navigates pages, takes screenshots, checks the console and accessibility | `bdt_*` |
| **Node** | Opt-in | Node.js backends attaches the V8 inspector, sets probes, reads runtime snapshots, and captures outbound HTTP | `ndt_*` |
| **Python** | Opt-in | Python backends attaches to a running process over debugpy/DAP, sets probes, dumps threads, and captures outbound HTTP | `pdt_*` |
| **Backend** | Opt-in | Any backend runtime drives real HTTP, gRPC, GraphQL, or WebSocket calls and checks the responses | `bedt_*` |
| **Android** | Opt-in | Android app changes drive an emulator over ADB, launch the app, tap and swipe, take screenshots and UI snapshots, read Logcat, and capture HTTP traffic | `adt_*` |
| **Terminal** | Opt-in | CLI / REPL / TUI changes spawns the program in a pseudo-terminal (PTY), sends input, and reads the output the same way `tmux` drives a pane | `tdt_*` |
Every enabled cycle's tools are served by a **single `ironbee-devtools` MCP server** (a "compose" server that multiplexes them under their fixed per-platform prefixes). The completion gate still routes each tool call to its cycle by that prefix — so `browser-devtools`, `node-devtools`, etc. remain the *logical* cycle names even though there's just one physical server. Enabling or disabling a cycle changes which prefixes that one server exposes.
The browser cycle covers most frontend work out of the box. The Node, Python, backend, Android, and terminal cycles stay off until you opt in, so those changes aren't gated until you ask for it.
### Choosing platforms at install
You pick which platforms to verify **while you [install](/cli/guides/managing-projects#choosing-which-platforms-to-verify)**, from an arrow-key multi-select — **space** toggles a cycle, **`a`** toggles all, **Enter** confirms. (You can also flip any cycle afterward with the [`enable` / `disable` commands](#enable-or-disable-a-platform) below.)
The picker also offers an **`s` "suggest"** key. Press it and IronBee analyzes your project with your client's model — Claude Code, Codex, and Cursor can all run it (when several are selected it uses the highest-priority one, `claude > codex > cursor`):
…then replaces your selection with the cycles it recommends — still editable before you press Enter:
Suggestion is opt-in — nothing runs until you press `s`. It runs a one-shot headless prompt through your client (`claude -p`, `codex exec`, or `cursor-agent -p`), so the client must be signed in. If the analysis is cancelled (Esc), times out, or fails, your current selection is kept.
Here's each platform, and what its row looks like in that picker.
**Browser** *(on by default)* — a real browser: navigate pages, take screenshots, and check the console and accessibility. It covers most frontend work with no setup, and is the only cycle enabled out of the box.
**Node** — Node.js runtime (tracepoints, logpoints, exceptions, variables, logs) plus outbound HTTP capture (axios, got, node-fetch, `fetch`/`undici`, http2, gRPC):
**Python** — a running Python process over **debugpy** (the Debug Adapter Protocol): tracepoints, logpoints, exceptions, watches, stdout/stderr logs, an all-thread **thread dump** (py-spy-style, for deadlock / GIL / hang diagnosis), plus outbound HTTP capture (`urllib`/`http.client`, `requests`, `httpx`, `aiohttp`). It attaches to an already-running process without blocking it — an already-listening debugpy at `host:port` (default `127.0.0.1:5678`), a PID (POSIX), a process name, or a docker container — and never modifies the target's source.
The Python cycle needs **`debugpy` installed in the target's Python environment** (`pip install debugpy`). Unlike Node's built-in inspector, debugpy is a third-party package, so IronBee can't attach without it.
**Backend** — HTTP, gRPC, GraphQL, WebSocket, DB, and logs:
**Android** — device/emulator drive, taps, swipes, screenshots, UI snapshots, Logcat, HTTP capture:
**Terminal** — CLI / REPL / TUI driving over a PTY: spawn a program, send keystrokes, capture output and exit codes. There are no screenshots here, so terminal is **not** a recording cycle.
### Enable or disable a platform
To change platforms **after** install (rather than re-running it), each has an `enable` / `disable` subcommand:
```bash theme={null}
ironbee node enable # turn on Node.js runtime verification
ironbee python enable # turn on Python runtime verification (needs debugpy in the target env)
ironbee backend enable # turn on backend protocol verification
ironbee android enable # turn on Android device/emulator verification
ironbee terminal enable # turn on terminal (CLI / REPL / TUI) verification
ironbee browser disable # turn off the browser cycle (e.g. backend-only projects)
```
Re-enabling is the inverse: `ironbee browser enable`, `ironbee node disable`, and so on. Changes are written to the project config and your client's hooks/tools are re-rendered automatically.
By default these write to the project config (`/.ironbee/config.json`). To target a different layer:
| Flag | Writes to |
| ---------------- | --------------------------------------------------------------- |
| *(none)* | Project config committed, shared with your team |
| `-g`, `--global` | `~/.ironbee/config.json` applies to all your projects |
| `--local` | `/.ironbee/config.local.json` gitignored, just for you |
Enabling a platform applies sensible built-in file patterns automatically; you don't have to list which files to verify. To fine-tune *which* files trigger each cycle (custom verify patterns, ignored paths, devtools settings), see [Configuration](/cli/configuration/configuration#verification-cycles).
***
## Project checks run first (lint, tests, types)
Before any devtools verification runs, IronBee can run your own **deterministic project checks** — linters, type-checkers, unit tests, a build — as the **first step** of every verification cycle. In **enforce mode**, a `required` check that fails (or never ran) **blocks completion**, so the agent has to fix it and re-run before it can finish.
There are two ways to set them up — **let IronBee suggest them** (at install, or on demand) or **write them by hand**. Both land in the same `verification.checks` config key.
### Let IronBee suggest your checks
Beta — the suggested commands are a starting point to review, not a finished config.
IronBee can analyze your project with your AI client and propose concrete checks, then let you approve a subset before it writes them. Like the mode and platform steps, this is offered **at install first** — the last step of [`ironbee install`](/cli/guides/managing-projects#choosing-your-project-checks), behind a yes/no gate (default No), after the mode and platform pickers.
Accept the gate and IronBee analyzes the project with the client's model (Esc cancels):
then hands you a per-check approval list, each check tagged **required** or **advisory** (from its `kind` — typecheck and test default to required). Per row, **`r`** flips required ⇄ advisory and **`c`** flips [conclusive](#conclusive-checks-let-a-check-decide-the-cycle) (which also forces required):
Optionally, IronBee then **validates** your picks by running each once (a `[y/N]` prompt at install, or the `--validate` flag on the command) — it shows pass/fail and re-presents the list so you can drop any that broke before it writes:
The model reads your `package.json` scripts, `Makefile`, `justfile`, `pyproject.toml`, `Cargo.toml`, `go.mod`, Gradle, turbo/nx, and the like, and returns the concrete command for each kind — **preferring your project's own existing scripts/targets** and never modifying any file. This is **"discovery LLM, deterministic runtime"** — the model runs only at install (or the command below), never during a verification cycle; the gate always just re-runs the committed commands.
**The same flow, standalone.** Run it anytime afterward — to add checks to a project you already set up, or re-suggest after big changes — with `ironbee checks suggest`:
```bash theme={null}
ironbee checks suggest # analyze the project and propose verification.checks
ironbee checks suggest --validate # run each proposal once and drop the ones that fail before writing
ironbee checks suggest --yes # accept the full suggested set (for scripts/CI)
```
| Flag | Description |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--client ` | Which client's model to analyze with. Claude Code, Codex, and Cursor all work; defaults to the highest-priority detected one (`claude > codex > cursor`). |
| `--validate` | Run each suggested check once and drop the ones that fail before writing. |
| `-y`, `--yes` | Accept the full suggested set without the approval prompt. |
| `-g`, `--global` / `--local` | Which config layer to write to (default is the committed project config). |
Re-running is **additive and non-destructive** — a fresh suggestion is *unioned* with your existing checks (your hand-tuned entries win on a name clash), so you can re-suggest anytime (or re-run install) without losing customizations.
Resolving the suggestion runs a one-shot headless prompt through your client — **Claude Code**, **Codex**, or **Cursor** (`cursor-agent`) — so the client must be installed and signed in. With more than one available it uses the highest priority (`claude > codex > cursor`). If none can run headless, write `verification.checks` by hand instead.
### Write the checks by hand
Or set `verification.checks` directly — a JSON array where each entry is one command:
```json theme={null}
{
"verification": {
"checks": [
{ "name": "lint", "command": "npm", "args": ["run", "lint"], "kind": "lint" },
{ "name": "typecheck", "command": "npm", "args": ["run", "typecheck"], "kind": "typecheck", "required": true },
{ "name": "test", "command": "npm", "args": ["test"], "timeoutMs": 120000, "kind": "test", "required": true }
]
}
}
```
Each entry takes:
| Field | Required | Meaning |
| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | yes | Label shown in the verdict and any block message. |
| `command` | yes | Executable to run. |
| `args` | no | Argument list. |
| `env` | no | Extra environment variables. |
| `cwd` | no | Working directory (defaults to the project dir). |
| `timeoutMs` | no | Per-check timeout in milliseconds. |
| `required` | no | Whether a failure blocks completion (see below). |
| `conclusive` | no | Makes the check the **arbiter** of the whole cycle — see [Conclusive checks](#conclusive-checks-let-a-check-decide-the-cycle). Implies `required`. Hand-set only (never suggested). |
| `kind` | no | Advisory label — `typecheck` / `lint` / `test` / `build` / `format` / `other`. Cosmetic to the gate; it drives the [suggester's](#let-ironbee-suggest-your-checks) required-by-default choice (`typecheck` and `test` default to required). |
### How a check gates completion
The verifier runs the checks via `ironbee hook run-checks` at the **start** of the cycle, and IronBee trusts the **recorded exit codes**, not the agent's word for it. In **enforce mode**, a `required` check that exits non-zero or times out **blocks completion** — the agent has to fix it and re-run — and a `required` check that *never ran* blocks too, so the agent can't quietly skip it. Non-required checks are recorded but don't gate. A failed check counts toward [`maxRetries`](/cli/configuration/configuration#core-options) like any other block.
Check results stay **local** to your machine (recorded under `.ironbee/`, not sent to the Collector), and `verification.checks` is read live — editing it takes effect on the next session without re-rendering artifacts. In assist and monitoring-only mode there's no gate, so the checks run during a manual `/ironbee-verify` but never block.
### Conclusive checks (let a check decide the cycle)
By default a check is a *gate* — it can block completion, but the agent still has to run the devtools verification (screenshots, probes, HTTP calls) to actually pass. A check marked **`conclusive: true`** is stronger: it becomes the **arbiter** of the cycle, so its exit code alone can conclude verification — no devtools step needed. Use it when a deterministic command (a full end-to-end suite, an integration test) is a trustworthy stand-in for driving the app by hand.
`conclusive` implies `required`, and there are two outcomes:
* **All conclusive checks pass** → `ironbee hook run-checks` **auto-submits the pass verdict** and closes the cycle. The devtools verification is **skipped** entirely — the recorded exit codes are the evidence, so this is strict-compatible (a machine result, not an agent claim). The agent just reports and stops.
* **A conclusive check fails** → a **deferred fail**: instead of stopping at the red command, the verifier turns to the devtools tools to **diagnose** the named failure, then submits a findings-rich fail verdict. IronBee auto-prepends a `conclusive check "" failed (exit N)` issue and refuses a pass or N/A for that cycle until a fresh cycle re-runs the checks green.
Because it can *replace* the devtools cycle, `conclusive` is **hand-set only** — the [suggester](#let-ironbee-suggest-your-checks) never marks a check conclusive. Set it in the config by hand, or flip it in the approval pickers (at install, `ironbee checks suggest`, or the [TUI](/cli/guides/interactive-mode)) with the per-row **`c`** key (`c` toggles conclusive — and forces required; **`r`** toggles required/advisory). Give a long conclusive suite an explicit `timeoutMs` (checks default to 120s).
```json theme={null}
{
"verification": {
"checks": [
{ "name": "e2e", "command": "npm", "args": ["run", "test:e2e"],
"timeoutMs": 600000, "kind": "test", "conclusive": true }
]
}
}
```
Conclusive checks only conclude the cycle in **enforce mode** (assist and monitoring-only never gate). A deferred fail counts toward [`maxRetries`](/cli/configuration/configuration#core-options) and releases at the cap with the failure reported, like any other block.
***
## How verification runs (the verifier sub-agent)
On **Claude Code** and **Codex**, IronBee doesn't let the main agent drive the devtools tools directly. Instead it installs a dedicated **`ironbee-verifier` sub-agent** that owns those tools (plus read-only `Read` / `Grep` / `Glob` so it can understand the change it's verifying — but **no edit tools**), and the main agent **delegates** the verification cycle to it — automatically at the completion gate, or manually via `/ironbee-verify`. The verifier runs every active cycle, submits the verdict, and hands back a short summary.
The point is to keep the heavy devtools output (DOM snapshots, console logs, screenshots) inside the sub-agent's context instead of the main conversation. The sub-agent shares the session, so its events still flow to the Collector — each tagged with its `agent_name` so the Console can tell the verifier's work from the main agent's.
**Cursor** has no verifier sub-agent — its main agent runs the verification itself, because Cursor's sub-agents can't share the verification session.
### Picking the verifier model
By default the verifier runs on the **same model as the main conversation**. Pin it to a specific model — for example to verify on something cheaper or faster than your main coding model — with `ironbee verification model`:
```bash theme={null}
ironbee verification model sonnet --client claude # pin Claude's verifier
ironbee verification model gpt-5.5 --client codex # pin Codex's verifier
ironbee verification model sonnet # apply to every client (bare string)
```
`--client` is **optional when exactly one verifier-capable client is installed** and **required when there are two** (Claude + Codex), since one model name rarely works for both. To go back to inheriting the session model:
```bash theme={null}
ironbee config unset verification.model
```
The setting accepts the usual `-g`/`--global` and `--local` target flags and re-renders the verifier artifact when it changes. It maps to the [`verification.model`](/cli/configuration/configuration#verification) config key. Cursor is a no-op.
On **Codex** the verifier needs *some* resolvable model. It inherits your `~/.codex/config.toml` `model`; if you haven't set one there, pin `verification.model` so the sub-agent can spawn.
***
## Verify-only vs. fix mode
When you trigger `/ironbee-verify` by hand (or `$ironbee-verify` on Codex), an optional leading word picks what happens on a **fail** verdict:
```bash theme={null}
/ironbee-verify # verify-only (default) — report the verdict and stop
/ironbee-verify fix # fix-and-re-verify — on a fail, fix the issues and loop until it passes
/ironbee-verify fix log in as admin, open /billing # fix mode + a custom scenario
```
| Mode | Leading word | On a fail verdict |
| --------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Verify-only** *(default)* | *(none)* or `report` | Runs the cycle, submits the verdict, reports it, and **stops**. It never edits your code, even when the verdict is a fail — use it to check the current state. |
| **Fix** | `fix` | On a fail, the agent fixes the reported issues and re-verifies, looping until it passes (or hits [`maxRetries`](/cli/configuration/configuration#core-options)). |
In **enforce mode** the choice is enforced mechanically, not just suggested: a `fix` run won't let the agent stop on a fail without addressing it, while a verify-only run is allowed to report a fail and end the turn. A custom scenario can follow the mode word. The `fix` token escalates just that one run — the sticky default for what a failing verdict does at the gate is the [fix enforcement](#fix-enforcement-block-on-a-fail-or-just-report-it) setting.
This only changes the **manual** command's behavior. The automatic completion gate is unaffected — when the agent edits code and tries to finish, it must still pass every active cycle. In [assist mode](#assist-mode-default) nothing blocks the agent, so `fix` there is advisory; in monitoring-only mode the command isn't installed.
***
## When a change has nothing to verify (N/A verdicts)
Some edits match a cycle's file patterns but have **no runtime surface** to exercise — a type-only change, a behavior-neutral refactor, a config or docs tweak. Rather than fake screenshots or HTTP calls to satisfy the gate, the verifier can submit a **not-applicable (N/A) verdict**, declaring there's nothing to verify and explaining why:
* **Global N/A** — no active cycle applies to the change. The verifier reports `status: not_applicable` with a short reason, and the gate lets the task complete without any tool evidence.
* **Per-platform N/A** — some cycles apply and some don't. The verifier verifies the ones that do (a normal `pass`/`fail`) and exempts the rest by name, with a reason for each exemption.
N/A verdicts are **recorded and observable** — they show up in the session's verdict like any pass or fail, with the exempted cycles and reasons attached, so you can see *why* a change wasn't exercised. To guard against abuse, the gate **refuses an N/A after a previous fail** on the same change (an agent can't downgrade a real failure to "not applicable" to escape the gate).
To refuse N/A entirely — demanding real tool evidence for every active cycle — turn on **[strict mode](#strict-mode)** (the enforce follow-up choice covered under [Verification modes](#verification-modes)). It's picked at install right after enforce, or toggled later with `ironbee verification strict enable`.
N/A is **off-limits after a fail and under strict mode** — it's an escape hatch for changes that genuinely have no runtime behavior, not a way around a real verification.
***
## Custom verification scenarios
By default the agent verifies the areas affected by what changed. To tell it **exactly** what to exercise, pass a custom scenario to `/ironbee-verify` (or `$ironbee-verify` on Codex) — either inline or as a path to a file:
```bash theme={null}
/ironbee-verify log in as admin, open /billing, confirm the invoice total updates
/ironbee-verify ./scenarios/checkout.md
```
When a scenario is supplied it's **authoritative**: it replaces the default "exercise the changed pages" guidance, and the verifier drives precisely the flows, states, and endpoints it names. A scenario *file* is read at run time (any location, any format), so you can keep reusable test scripts in your repo and point at them. The completion gate is unchanged — every active cycle's required tools still have to run for a pass.
To capture a flow once and replay it by name instead of re-typing it every time, save it as a [scenario](/cli/guides/scenarios) and run it with [`/ironbee-run-scenario`](/cli/guides/scenarios#run-a-saved-scenario). The old `scenario:` reference is **not** accepted by `/ironbee-verify` anymore — the command will point you at `/ironbee-run-scenario` instead.
***
## What's next?
Capture reusable verification flows and replay them by name.
Give the agent area-specific instructions with `.ironbee/VERIFICATION.md` files.
Fine-tune which files trigger each cycle, retry limits, and more.
Check a session's verdict and debug why it passes or fails.
# Verification Context
Source: https://docs.ironbee.ai/cli/guides/verification-context
Give your agent area-specific verification instructions by dropping .ironbee/VERIFICATION.md files in your repo.
Different parts of a codebase need different things checked. A payments module wants the 3DS challenge exercised; an auth module wants session-fixation verified; the frontend wants an accessibility pass. **Verification context** lets your team author that guidance once, in the repo, and have IronBee surface *only the parts relevant to what changed*, injecting them straight into the agent's context the moment it starts verifying.
It's advisory: the guidance reaches the agent as a first-class reminder alongside the standard verification flow, but it never blocks completion on its own.
***
## Author guidance in `.ironbee/VERIFICATION.md`
Drop a Markdown file at `.ironbee/VERIFICATION.md` inside any directory whose changes need special attention:
```
my-app/
├── .ironbee/
│ └── VERIFICATION.md # repo-wide defaults
├── payment/
│ ├── .ironbee/
│ │ └── VERIFICATION.md # payment-area guidance
│ └── stripe/
│ └── charge.ts
└── frontend/
└── .ironbee/
└── VERIFICATION.md # frontend-area guidance
```
The file is plain prose. Write whatever you'd tell a teammate before they verify a change in that area:
```markdown theme={null}
# Payment verification
- Exercise the 3DS challenge flow end-to-end, not just the happy path.
- Confirm a declined card surfaces the retry UI, not a 500.
- Check that the idempotency key prevents a double charge on retry.
```
The file name is the fixed convention `.ironbee/VERIFICATION.md`; it isn't configurable. The `.ironbee/` folder is the same namespace that holds the project's `config.json` at the repo root, so area guidance lives alongside it consistently. These files are meant to be **committed** and reviewed in PRs; only `sessions/` and `config.local.json` are gitignored.
***
## How guidance is matched to a change
When a verification cycle begins, IronBee looks at **what changed this cycle**, then for each changed file walks *up* from its directory to the project root, collecting every `.ironbee/VERIFICATION.md` it finds along the way:
```
Changed: payment/stripe/charge.ts
Collects: payment/stripe/.ironbee/VERIFICATION.md (if present)
payment/.ironbee/VERIFICATION.md (if present)
.ironbee/VERIFICATION.md (repo-wide default, if present)
```
* **Nearest-parent hierarchy:** a change picks up its own area's guidance plus everything above it. Directories without a file are simply skipped.
* **Merged general → specific:** the repo-wide default reads first, area-specific guidance after it.
* **Deduplicated:** if ten files under `payment/` changed, `payment/.ironbee/VERIFICATION.md` is included once.
* **Always includes the changed-path list:** even when *no* `.ironbee/VERIFICATION.md` matches, IronBee still injects the list of paths that changed this cycle (capped at 100, with a `+N more` for the rest). This gives the delegated verifier a head start on *what* to exercise instead of discovering it from scratch. Authored guidance, when present, is appended on top.
***
## An always-on instruction (`verification.context.message`)
The `.ironbee/VERIFICATION.md` files are *path-scoped* — they only reach the verifier when a change touches their directory. For a standing instruction that should accompany **every** verification cycle regardless of what changed, set `verification.context.message`:
```bash theme={null}
ironbee config set verification.context.message "Confirm the health endpoint returns 200 before passing."
```
This is injected into every cycle **unconditionally** — even a manual `/ironbee-verify` with no code changes, where the changed-path list and path-scoped docs would otherwise be empty. It's rendered first, ahead of any matched `VERIFICATION.md` guidance, and is **never truncated** (it reserves its own bytes so the `maxBytes` cap still bounds the path-scoped docs).
Two value forms:
* **Inline text** the message itself.
* **A file reference** `file:`, read at verification time. The path is relative to the project dir; a leading `~` expands to your home directory; a missing or unreadable file is silently skipped.
```bash theme={null}
ironbee config set verification.context.message "file:.ironbee/verify-checklist.md"
```
Like the rest of the context keys, it's layered across global / project / local (the highest layer that sets it wins) and read live, so a change takes effect on the next session.
***
## What counts as "changed"
By default the changed set comes from **git**: your uncommitted work (working tree: staged, unstaged, and untracked files) plus the last commit. In a non-git project, IronBee falls back to its own `file_change` events for the current cycle.
* [`ignoredVerifyPatterns`](/cli/configuration/configuration#core-options) filter the set — test files are excluded by default, and anything you add filters out build/docs churn too, so it doesn't pull in guidance.
* IronBee's own `.ironbee/` tree is always excluded.
* `commitDepth` controls how many recent commits join the working tree: `1` (default) covers in-flight work plus the latest commit, `0` is uncommitted-only, and you can raise it for teams that commit per logical step.
***
## When it's injected
The guidance is injected on the **first verification tool call of each cycle** (exactly when the agent starts verifying) and once per cycle (re-verifying after a fix gets a fresh read of what changed). It arrives through each client's native context channel, so the agent treats it as a binding reminder, not incidental output.
| Mode | Injects? |
| ---------------------- | --------------------------------------------------------- |
| **Assist** *(default)* | Yes, manual `/ironbee-verify` cycles get the guidance too |
| **Enforce** | Yes |
| **Monitoring-only** | No, monitoring installs no verification hooks |
It is **advisory in this release**: the agent must follow the guidance as part of its verification, but the content itself never gates completion. (Machine-checkable per-area rules are planned separately.)
***
## Configuration
The feature is on by default. Tune it under the `verification.context` key. See [Configuration → Verification context](/cli/configuration/configuration#verification-context) for the full table. The common knobs:
```bash theme={null}
ironbee config set verification.context.enable false # turn it off entirely
ironbee config set verification.context.commitDepth 0 # uncommitted work only
ironbee config set verification.context.source actions # skip git, use IronBee's own file_change events
```
These keys are read live at verification time, so a change takes effect on the next session without re-rendering client artifacts.
`.ironbee/VERIFICATION.md` is repo content at the same trust level as `CLAUDE.md` or `AGENTS.md`; the agent follows whatever it says. Review changes to these files in PRs as you would any other instruction your agent reads.
***
## What's next?
Choose which platforms get verified and switch between enforce, assist, and monitoring.
The full `verification.context` key reference.
# Verification Jobs
Source: https://docs.ironbee.ai/cli/guides/verification-jobs
Run a real verification job in the IronBee cloud with `ironbee verify` — against a deployed URL or a local port through a reverse tunnel.
`ironbee verify` starts a **verification job through the IronBee API**: a cloud agent exercises your application — a deployed URL, or a local app reached through a reverse tunnel — and returns a verdict. Nothing runs in your editor: no AI client, no local devtools server, no completion gate. It's the same kind of verification your agent performs locally, packaged as a command you can run from any shell or CI pipeline.
```bash theme={null}
ironbee verify run web --url https://preview.example.com # verify a deployment
ironbee verify run web --port 3000 # verify a local app via tunnel
ironbee verify status # read a job back
ironbee verify cancel "superseded by a newer build" # ask a job to stop
```
Earlier CLI versions used `ironbee verify [session-id]` for a **local dry-run** of a session's verdict checks. That command is now [`ironbee verdict`](/cli/advanced/inspecting-sessions#ironbee-verdict) — `ironbee verify` is exclusively the cloud verification job runner.
***
## Credentials
The command authenticates with your IronBee account — run [`ironbee login`](/cli/guides/authentication) once, or supply a credential from the environment (the way to do it in CI):
| Source | Credential |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `ironbee login` | Personal OAuth access token, stored under [`service.oauthToken`](/cli/configuration/configuration#service-identity) |
| `IRONBEE_SERVICE_OAUTH_TOKEN` / `IRONBEE_SERVICE_API_KEY` | The standard [config env overrides](/cli/configuration/environment-variables) — they work here too |
| `IRONBEE_ACCESS_TOKEN` | OAuth access token, a verify-specific override that beats everything above |
| `IRONBEE_API_KEY` | Account API key (the legacy CI form) — likewise beats the config |
When both an OAuth token and an API key are available the OAuth token wins. With no credential at all the command fails with `no IronBee credential — run ironbee login, or set IRONBEE_ACCESS_TOKEN / IRONBEE_API_KEY`. The credential is **never a CLI argument**, so it can't leak through the process table.
***
## `ironbee verify run web`
Starts a job and follows it to a verdict. The target is exactly one of:
* **`--url `** — a publicly reachable deployment. The cloud agent drives it directly.
* **`--port `** — a local application. The CLI holds a **reverse tunnel** open for the duration of the run, so the cloud agent reaches `127.0.0.1:` on your machine without you exposing anything.
```bash theme={null}
ironbee verify run web --url https://preview.example.com \
--prompt "log in as admin, open /billing, confirm the invoice total updates"
ironbee verify run web --port 3000 --name "checkout smoke"
```
### Target flags
| Flag | Description |
| ------------------------------ | -------------------------------------------------------------------------------------------------- |
| `--url ` | Publicly reachable URL of the deployment to verify. |
| `--port ` | Local port the application listens on; reached through a reverse tunnel. |
| `--header ` | Request header for the URL target (repeatable). |
| `--secret-header ` | Request header whose value is **secret** — encrypted by the service, never read back (repeatable). |
| `--app-wait ` | Give up if the local port is not accepting within this (default `60`). |
`--header` / `--secret-header` apply to `--url` only — a tunnel target's traffic passes no layer that could apply them.
### Secret headers for protected deployments
A preview deployment behind **deployment protection** (e.g. a Vercel protection-bypass header) needs a header the agent must send to reach it. Pass it with `--secret-header` so the value is treated as a secret end to end:
```bash theme={null}
ironbee verify run web --url https://preview.example.com \
--secret-header 'X-Vercel-Protection-Bypass: '
```
The value is masked from all CLI output the instant it's parsed (and registered with `::add-mask::` on GitHub Actions runners), sent in a dedicated `secretHeaders` field the service **encrypts and never reads back**. Plain `--header` values get none of that treatment — use it only for non-sensitive headers.
### Common flags
| Flag | Description |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `--prompt ` | What to verify on the target. |
| `--prompt-file ` | Read the prompt from a file, or from stdin with `-`. |
| `--project ` | Project the results attach to (default: derived from the git remote). |
| `-C, --project-dir ` | Directory the project and repository are derived from (default `.`). |
| `--name ` | Job name, as it appears in the console. |
| `--timeout ` | Run timeout (default: the API's own). |
| `--queue-wait ` | Give up if the job has not started within this (default `900`) — the run then **cancels the job** and exits `2`. |
| `--api-url ` | API base URL (default: the configured service domain). |
| `--json` | Print the finished job as JSON on stdout and nothing else. |
| `--no-wait` | Create the job, print its id, and exit without following it. |
`--prompt` and `--prompt-file` are alternatives. `--no-wait` can't be combined with `--port`: the run reaches the application only while the command is holding the tunnel open.
### Binding the run to your repository
By default the run is bound to your repository and current commit, so the verdict lands next to the right code in the Console. Fine-tune or opt out:
| Flag | Description |
| ---------------- | ------------------------------------------------------------------------------------------ |
| `--commit ` | Bind to this full 40-character commit SHA (default: derived from the repo / `GITHUB_SHA`). |
| `--base [` | Measure the changeset from this ref or SHA. |
| `--pr ` | Bind to this pull request instead of a commit (default: from `GITHUB_REF` on a PR run). |
| `--no-diff` | Bind the commit but declare no changeset. |
| `--no-repo` | Don't bind the run to a repository at all. |
The binding attaches only when it would actually work: the remote must be **GitHub**, and a commit derived from local HEAD must be **reachable from a remote-tracking branch** — an unpushed HEAD produces a warning and the run proceeds **unbound** rather than pointing at code the service can't read (an explicit `--commit`, or `GITHUB_SHA` in CI, is taken at face value). A dirty working tree only warns: the run stays bound to the committed SHA, so what the agent reads and what's on your disk may differ. In GitHub Actions the binding is automatic — `GITHUB_REPOSITORY`, `GITHUB_SHA`, and `GITHUB_REF` fill in the repo, commit, and PR, and the job is declared with a `github_actions` trigger so the Console can filter CI-triggered runs (purely informational — it carries no authority). If the job errors with a repo-checkout failure, grant the [IronBee GitHub App](/integrations/github) access to the repository, or re-run with `--no-repo`.
### How a tunnel run starts
For a `--port` target the CLI first probes the local port — **before** creating the job, so a doomed run is never started:
* It keeps waiting while nothing is listening, and while the port **accepts and immediately hangs up** (Docker publishes a container's port before the app inside is ready).
* A server that accepts but stays silent is treated as ready (just slow), not as a failure.
* A **TLS** listener fails immediately: the tunnel carries plain HTTP, so serve the app over HTTP locally.
* On `--app-wait` expiry (default 60s) the command exits 1 with the last probe error.
Once the job is created, the CLI prints every status change (`queued` → `starting` → `running` → a terminal status) while holding the tunnel. When the run finishes, the service closes the tunnel with a dedicated "run ended" signal and the command stops without reconnecting; if that signal is ever lost (a killed environment, a dropped connection), the command falls back to the job's own status polling — the verdict is the same either way. `Ctrl-C` requests a cancel and waits for the service to confirm; a second `Ctrl-C` exits immediately.
***
## Output and exit codes
A finished run prints the job's summary, its `checks` / `issues` / `fixes` / `reason` lists, a warning when the run **refused** or narrowed part of the request, and a final banner — `PASS`, `FAIL`, `NOT APPLICABLE — the run verified nothing`, or `no verdict — the job `.
| Exit code | Meaning |
| --------- | ---------------------------------------------------------------------- |
| `0` | The job succeeded **and** the verdict is `pass`. |
| `1` | Failing verdict, not-applicable, no verdict, job failed, or any error. |
| `2` | Cancelled (including `Ctrl-C`). |
| `3` | `verify status` only: the job isn't terminal yet. |
That makes it CI-gate-ready: `ironbee verify run web --url … && deploy.sh`.
### `--json`
With `--json`, stdout carries exactly one JSON document (all decoration goes to stderr). A run that produced a job prints the **job body**:
```json theme={null}
{
"id": "…", "name": "…", "status": "succeeded",
"result": {
"status": "pass",
"checks": ["…"], "issues": [], "fixes": [], "reason": [],
"summary": "…"
}
}
```
`status` is one of `queued` / `starting` / `running` / `succeeded` / `failed` / `cancelled`; `result.status` is `pass` / `fail` / `not_applicable`. The result may also carry `refused: true` with a `reasonCode` when the run declined or narrowed part of the request — a refused run can still be `succeeded`, so a caller should check it — and the job may carry an `error: { type, message }`. A failure that produced **no job** prints a machine-readable error envelope instead (discriminate on the presence of `id`):
```json theme={null}
{ "error": { "status": 409, "code": "NO_GITHUB_INSTALLATION", "message": "…",
"details": [ { "field": "…", "message": "…" } ] } }
```
`error.code` is the API's own error code — the field to branch on. `status` and `details` appear only when the failure came from the API; a purely local failure (flag validation, missing credential) carries only `message`.
On a **GitHub Actions** runner the CLI also writes `::add-mask::` workflow-command lines to stdout (masking the credential and any `--secret-header` values with the runner). A `--json` consumer there should parse the last JSON document rather than assume the stream is pure JSON.
***
## `ironbee verify status` and `cancel`
```bash theme={null}
ironbee verify status # one read: status + verdict (exit 3 if not terminal)
ironbee verify status --watch # poll until the job is terminal
ironbee verify cancel [reason] # ask the job to stop, with an optional reason for the record
```
`status` accepts the same `--json` / `--api-url` / `-C, --project-dir` flags as `run`, plus `--queue-wait ` with `--watch`. As an observer it never cancels — if the queue wait elapses it just warns that the job is still queued.
***
## What's next?
The in-editor verification gate — cycles, modes, and the verifier sub-agent.
OAuth tokens for interactive use, API keys for CI.
# API Tokens
Source: https://docs.ironbee.ai/console/access-tokens
Create, name, and revoke the personal OAuth access tokens the CLI uses to send data on your behalf.
The **API Tokens** page lists your personal access tokens, the OAuth credentials [`ironbee login`](/cli/get-started/getting-started#step-3-sign-in) creates so the CLI can send session data as you. Each token is tied to your user and account, and you manage them independently of the shared [account API key](/console/account).
## What you see
Each token in the list shows:
* **Name**: the label set at creation (the CLI defaults this to your machine's hostname)
* **Prefix**: the first characters of the token, followed by `…`; the full value is never shown again after creation
* **Created**: when the token was issued
* **Expires**: the expiry date, or "Never expires" for non-expiring tokens
## Create a token
Click **Create token**, give it a name, and choose an expiry (30, 60, 90, 180, or 365 days, or no expiration). The full token is shown **once** on the next screen, copy it somewhere safe, because it cannot be retrieved later.
Most people never create tokens here by hand; `ironbee login` mints one for you. Create one manually when you need a token for a specific tool or a custom expiry.
## Revoke a token
Click **Revoke** next to any token to disable it immediately. Anything still using that token can no longer authenticate.
You can hold at most **10 access tokens** at a time, including expired ones you have not removed. If you hit the limit, revoke one here before creating or minting another. This is also what frees up `ironbee login` when it reports the limit.
## Tokens vs the account API key
| | API token | Account API key |
| ---------- | ---------------------------- | ----------------------------------------------------------------------------------------------- |
| Identifies | You | The account |
| Created by | `ironbee login` or this page | Generated with the account |
| Used for | Interactive CLI use | CI and machine-to-machine, like the [GitHub Action](/github-action/get-started/getting-started) |
| Managed on | This page | The [Account page](/console/account) |
See [Authentication](/cli/guides/authentication) for how the CLI chooses between them.
# Account
Source: https://docs.ironbee.ai/console/account
Account name, API key, and your role within the account.
The Account page shows your IronBee account details and credentials. Access it from the bottom of the sidebar.
]
## Account name
Displays the current account name. Account owners can click **Change Name** to edit it (letters, numbers, and spaces, max 50 characters).
## Owner
The email address of the account owner. Read-only.
## Your role
Your role within this account: Owner, Admin, Member, or Billing Admin.
## API key
Your account API key, used for machine-to-machine authentication with the IronBee Collector for the [GitHub Action](/github-action/get-started/getting-started), CI pipelines, and scripts. For interactive CLI use, `ironbee login` issues a personal [OAuth token](/console/access-tokens) instead; see [Authentication](/cli/guides/authentication) for when to use each.
* The key is masked by default (first 8 + last 4 characters visible)
* Click the **eye icon** to reveal the full key
* Click **Copy** to copy it to the clipboard
To use this key in CI, set it as an environment variable (it takes precedence over config):
```bash theme={null}
export IRONBEE_API_KEY=
```
### Rotate the key
Owners and admins can click **Rotate** to generate a new key. The previous key stays valid for a **24-hour grace window** so existing integrations keep working while you roll out the new one.
* Only one grace key exists at a time. Rotating again while a grace key is still active permanently disables the earlier one, the Console asks you to confirm first.
* Click **Deactivate now** to end the grace window immediately, before the 24 hours are up.
# Activities
Source: https://docs.ironbee.ai/console/activities
The individual actions an AI agent takes within a session.
An **activity** is a discrete working period within a session. Activities form the chronological record of everything the agent did, and each one contains a mix of verifications, fixes, and other tool calls.
Activities are accessible through the [Session Timeline](/console/session-timeline). Click any activity bar to select it, or expand it to see the child intervals (verifications, fixes, and other events) nested inside.
***
## Activity types
| Type | Description |
| -------------- | ------------------------------------------------------------------------------------------------------------- |
| `activity` | The parent working period contains verifications, fixes, and other events |
| `verification` | A verification cycle run by the agent |
| `fix` | A fix attempt made after a failed verification |
| `other` | Tool calls and events that don't belong to a verification or fix which are idle time, setup, general tool use |
***
## Detail panels
Clicking an interval in the timeline opens a detail panel on the right. Each interval type has its own panel:
### Activity panel
Shows when you click an activity bar directly (without selecting a child):
| Field | Description |
| ------------ | -------------------------------------------------------------- |
| Label | Activity 1, Activity 2, etc. |
| Duration | Total elapsed time for this activity |
| % of session | How much of the session this activity represents |
| Start / End | Absolute timestamps (End shows "in progress" if still running) |
### Verification panel
Shows when you click a verification interval:
* **Status badge:** passed, failed, or abandoned
* **Video playback:** browser session recording if available (space/K to play, arrows to seek, J/L for ±10s)
* **Event timeline:** every tool call and assertion in order, with timestamps, input/output sizes, and expandable JSON details
* **Image artifacts:** screenshots shown inline with lightbox
### Fix panel
Shows when you click a fix interval:
| Field | Description |
| -------- | ------------------------ |
| Duration | Total fix time |
| Files | Unique files changed |
| Changes | Total file change events |
| Started | Absolute timestamp |
Below the stats, a chronological event list shows each step of the fix:
* **fix\_start:** user and session that initiated the fix
* **file\_change:** file path, operation (create / update / delete), lines added/removed, tool that made the change, and a **View code** button that opens a diff dialog showing the full changeset
* **fix\_end:** total duration and reason the fix concluded
### Other panel
Shows when you click an "other" interval, for events that occurred outside a named verification or fix:
| Field | Description |
| -------- | ------------------------------------- |
| Duration | Time span |
| Events | Count of events in this period |
| Activity | Which parent activity this belongs to |
| Started | Absolute timestamp |
Each event in the list shows the tool name (with MCP server if applicable), relative and absolute timestamp, input size, response size, duration, and any error message. Click the input button to inspect the full tool input JSON.
***
## Reading an activity
A healthy activity typically looks like:
1. **Verification** (passed) → task completes
An activity with issues might look like:
1. **Verification** (failed) → issues found
2. **Fix** → agent corrects the code
3. **Verification** (passed) → task completes
Multiple failed verifications and fixes within one activity signal that the agent struggled with a particular change, a useful signal when reviewing [Quality Analysis](/console/analysis-quality).
# Analysis
Source: https://docs.ironbee.ai/console/analysis
AI-powered analysis of your sessions which are quality, cost, and behavioral patterns.
After sessions complete, IronBee automatically runs **analysis** an LLM-powered pass over session data that turns raw telemetry into actionable insights.
## Analysis types
IronBee produces five analysis types across two scopes:
| Type | Scope | What it covers |
| ---------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------ |
| [Project Quality Analysis](/console/analysis-quality) | Project | Verification thoroughness, fix effectiveness, retry patterns, hot files |
| [Project Cost Analysis](/console/analysis-project-cost) | Project | Token spend, cache efficiency, cost per session, top billed sessions |
| [Project Session Insights](/console/analysis-project-session-insights) | Project | Session patterns, tool usage, context pressure, languages, activity categories |
| [Account Cost Analysis](/console/analysis-account-cost) | Account | Account-wide spend across all projects and users |
| [Account Session Insights](/console/analysis-account-session-insights) | Account | Account-wide behavioral patterns across all projects |
## The analyses list
The Analyses page shows a card grid of recent analysis runs. Use the **Account / Project** scope tabs to switch between account-wide and project-scoped analyses. When viewing Project scope, use the project picker to select a project.
Each card shows:
* Analysis type and timestamp
* A hero metric with a mini trend chart
* Five secondary metrics at a glance
Click a card to open the full analysis detail view.
Account Analysis:
Project Analysis:
## How analysis works
1. A session completes (verdict submitted or retry limit reached)
2. IronBee aggregates session metrics into a structured data packet
3. An LLM analyst processes the packet and produces findings and recommendations
4. The analysis appears in the Analyses page and the Findings and Recommendations pages update
Analysis typically completes within a minute of session end.
## Related pages
Specific observations surfaced by the analyzer.
Directives injected into the agent's context on future sessions.
# Cost Analysis
Source: https://docs.ironbee.ai/console/analysis-account-cost
Account-wide API spend across all projects and users.
The **Account Cost** analysis aggregates API spend across every project and user on the account. It has the same structure as [Project Cost Analysis](/console/analysis-project-cost) with additional breakdowns for cross-project and cross-user comparisons.
## Shadow / Billed cost
Hero card with five metrics (sparklines + week-over-week deltas):
| Metric | Description |
| ------------------ | ----------------------------------------------------- |
| Real spend | Total USD billed across the account |
| Subscription value | Total USD equivalent served from subscription credits |
| API calls | Total requests across all projects |
| Successful calls | Requests that returned a response |
| Failed calls | Requests that errored or timed out |
The total cost line also shows the number of active projects contributing to the figure.
## Daily activity honeycombs
Three 30-day honeycomb grids with weekends toggle:
* **Requests:** daily request count
* **Input / Output tokens:** toggle between input and output
* **Cache-read / Cache-creation tokens:** toggle between read and creation; footer shows cache hit %
## Cost summary
API calls, average real spend per session, average subscription value per session, and active projects count.
## Daily cost chart
Two-way bar chart: billed up, shadow down, per day across the account.
## Cost over time
Stacked area chart of daily billed + shadow cost.
## Cost per session
Grouped bar chart: avg, p50, p90, p99, billed vs shadow.
## By model
Stacked bar chart by model with metric toggle: Cost, Tokens, Cache, Requests, Cache hit %.
## By plan
Stacked bar chart by subscription plan with the same metric toggle. Shows cost distribution across Claude plans used across the account.
## By project
Table of all projects: request count, input tokens, output tokens, cache read, cache create, cache %, billed cost, shadow value, total cost. Sortable by any column.
## Top cost by user
Table of all users: request count, input/output/cache tokens, billed cost, shadow value, total cost. Sortable by any column.
## Top billed sessions / Top shadow sessions
Two ranked lists of up to 10 sessions each: the highest-cost sessions across the entire account, with project attribution.
## Tool metrics
Table of tools with call count, error rate, and speed, aggregated across all projects.
# Session Insights
Source: https://docs.ironbee.ai/console/analysis-account-session-insights
Account-wide behavioral patterns and activity trends across all projects.
The **Account Session Insights** analysis aggregates behavioral data across every project on the account. It has the same structure as [Project Session Insights](/console/analysis-project-session-insights) with an additional By Project table for cross-project comparisons.
## Session overview
Hero card with five metrics (sparklines + week-over-week deltas):
| Metric | Description |
| ------------------ | --------------------------------------- |
| Sessions | Total session count across the account |
| Active time | Hours of active agent work account-wide |
| User messages | Total user turns |
| User interruptions | Times users interrupted the agent |
| Tool errors | Total tool call failures |
## Activity heartbeat
* **Messages per day:** 30-day honeycomb grid with weekends toggle
* **Hour-of-day usage:** polar bar chart (UTC)
* **Standout sessions:** longest, highest context peak, most files, widest tool usage, most efficient, with project attribution
## Time & code activity
Wall-clock vs active vs idle split, concurrency events (overlapping sessions), and code change breakdown (lines added/removed).
## By project
Table of all projects: session count, total duration, files changed, tool errors. Sortable by any column, default sorted by sessions descending.
## Response time
Bar histogram across buckets: `<1s`, 1–2s, 2–10s, 10–30s, 30s–1m, 1–2m, 2–5m, 5–15m, `>15m`.
## Context pressure
Line chart of average peak context by turn bucket with summary stats (avg peak, max, avg at session end, high-pressure session count).
## Models
Donut chart of session distribution across Claude models, account-wide.
## Languages
Radar chart of lines changed across the top 8 programming languages, account-wide.
## Adoption signals
Feature adoption indicators across the account: MCP servers, sub-agents, skills, web search, web fetch.
## Hot files
Top files by edit frequency across all projects, with list or treemap view.
## Session types
Sankey diagram from session type to activity category.
## Activity categories
Horizontal bar chart of turns by activity category.
## Tool error categories
Horizontal bar chart of errors by category.
## Tool leaderboards
* **Top tools:** calls, errors, error %, sessions
* **MCP servers / Shell binaries:** toggled view
* **Skills:** custom command usage
* **Sub-agents:** background agent usage
## Shell command flow
Sankey diagram of shell binary → subcommand invocations.
## Tool metrics
Table of all tools with call count, error rate, and speed.
# Cost Analysis
Source: https://docs.ironbee.ai/console/analysis-project-cost
Token spend, cache efficiency, cost per session, and top billed sessions for a single project.
The **Project Cost** analysis breaks down API spend for a single project: real (billed) cost vs subscription-served (shadow) value, token usage patterns, and which sessions drove the most cost.
## Shadow / Billed cost
The hero card shows five metrics with sparklines and week-over-week deltas:
| Metric | Description |
| ------------------ | ----------------------------------------------- |
| Real spend | USD billed by the API for this project |
| Subscription value | USD equivalent served from subscription credits |
| API calls | Total requests made |
| Successful calls | Requests that returned a response |
| Failed calls | Requests that errored or timed out |
## Daily activity honeycombs
Three 30-day honeycomb grids (cell intensity = value). Each has a weekends toggle:
* **Requests:** daily request count
* **Input / Output tokens:** toggle between input and output token counts
* **Cache-read / Cache-creation tokens:** toggle between read and creation; footer shows cache hit %
## Cost summary
Four aggregate stats: API calls, average real spend per session, average subscription value per session, and cache-read token total.
## Daily cost chart
Two-way bar chart showing billed cost (up) vs shadow value (down) per day. Makes it easy to see the ratio of API spend to subscription benefit over time.
## Cost over time
Stacked area chart of daily billed + shadow cost across the analysis window.
## Cost per session
Grouped bar chart showing average, p50, p90, and p99 cost per session, both billed and shadow. Useful for spotting outlier sessions that are pulling the average up.
## By model
Stacked bar chart broken down by model. Metric toggle: Cost, Tokens, Cache, Requests, Cache hit %.
## Top billed sessions / Top shadow sessions
Two ranked lists of up to 10 sessions each: the sessions with the highest real spend and the highest shadow value respectively.
## Tool metrics
Table of tools with call count, error count, error rate, and speed metrics. Useful for identifying expensive or slow tool patterns driving cost.
# Session Insights
Source: https://docs.ironbee.ai/console/analysis-project-session-insights
Session patterns, tool usage, context pressure, and behavioral trends for a single project.
The **Project Session Insights** analysis gives a behavioral view of how the agent works in a single project: activity patterns, tool usage, context pressure, and code change trends.
## Session overview
Hero card with five metrics (sparklines + week-over-week deltas):
| Metric | Description |
| ------------------ | --------------------------------------------- |
| Sessions | Total session count (with billed/shadow note) |
| Active time | Hours of active agent work |
| User messages | Total user turns |
| User interruptions | Times the user interrupted the agent mid-task |
| Tool errors | Total tool call failures |
## Activity heartbeat
Three cards showing temporal patterns:
* **Messages per day:** 30-day honeycomb grid with weekends toggle
* **Hour-of-day usage:** polar bar chart of message count by hour (UTC)
* **Standout sessions:** highlights the longest session, biggest context peak, most files changed, widest tool usage, and most efficient session
## Time & code activity
* **Time split:** total wall-clock, active time (with share %), idle time (with share %)
* **Code changes:** net line change visualization with added/removed breakdown and percentages
## Response time
Bar histogram of response time distribution across buckets: `<1s`, 1–2s, 2–10s, 10–30s, 30s–1m, 1–2m, 2–5m, 5–15m, `>15m`.
## Context pressure
Line chart of average peak context tokens by conversation length (turn buckets: 1–3, 4–10, 11–25, 26–50, 51–100, 100+). Summary stats: avg peak, max, avg at session end, high-pressure session count.
## Models
Donut chart showing session distribution across Claude models used in the project.
## Languages
Radar chart of lines changed across the top 8 programming languages.
## Adoption signals
Indicators showing whether the project's sessions are using advanced features: MCP servers, sub-agents, skills, web search, web fetch.
## Hot files
Top files by edit frequency. Toggle between list view and treemap (hierarchical codebase map sized by change count). Up to 10 files.
## Session types
Sankey diagram from session type to activity category. Shows what kinds of sessions the agent runs and what activities those sessions spend time on.
## Activity categories
Horizontal bar chart of assistant turns by activity category (coding, debugging, refactoring, testing, documentation, analysis).
## Tool error categories
Horizontal bar chart of tool errors by category (command failed, edit failed, file not found, file too large, user rejected, other).
## Tool leaderboards
* **Top tools:** name, call count, error count, error %, session count
* **MCP servers / Shell binaries:** toggled view of MCP server vs shell binary usage (same columns)
* **Skills:** custom slash commands invoked, with call counts
* **Sub-agents:** background agents spawned, with call counts
## Shell command flow
Sankey diagram of shell binary → subcommand invocations with total invocation count.
## Tool metrics
Table of all tools with call count, error rate, and speed metrics.
# Quality Analysis
Source: https://docs.ironbee.ai/console/analysis-quality
Verification thoroughness, fix effectiveness, retry patterns, and hot files in project scope.
The **Quality** analysis gives a structured view of how well the agent verifies its changes in a project. It covers first-pass success rates, where the agent gets stuck, how effective its fixes are, and which files cause the most trouble.
## Quality overview
The hero card shows six metrics, each with an 8-week sparkline and a week-over-week delta:
| Metric | Description |
| ----------------------- | --------------------------------------------------- |
| First-pass success | % of verifications that passed on the first attempt |
| Re-fail rate | % of fix cycles that failed again after a fix |
| Verifications / session | Average number of verification cycles per session |
| Issues caught on fail | Average issues reported per failed verdict |
| Fixes / session | Average number of fix attempts per session |
| Failed sessions | Count of sessions that hit the retry limit |
## Session outcomes
Three cards break down how sessions ended:
* **Session outcomes:** donut chart of Pass, Fail, Abandoned, and Completed sessions
* **Client distribution:** donut chart showing which AI client (Claude Code, Cursor) ran each session
* **First-pass share:** efficiency % (time NOT spent on fixes) vs rework %
## Where time goes
Time distribution across Coding, Verification, and Fix phases, shown as a pie chart alongside four averages: session duration, activity duration, verification duration, fix duration.
## Issues before vs after fix
Average issue count before a fix attempt vs after, with a delta indicator. Shows whether fixes are actually resolving the problems the agent finds.
## Verification depth
Grouped bar chart comparing how thoroughly the agent checked before passing vs before failing:
* Checks per verdict
* Screenshots per verification
* Aria snapshots per verification
* Issues per failed verdict
## Fix outcomes
Donut chart categorizing fix cycles as:
* **Helpful:** the fix reduced or resolved the issues
* **No-effect:** issues unchanged after the fix
* **Backfiring:** the fix introduced new issues
## Top blockers
The most frequent reasons the agent was blocked, the recurring patterns across failed verifications. Up to 10 entries.
## Hot files
Files under the most verification pressure, highest frequency of triggering a cycle or appearing in failed verdicts. Up to 10 files.
## Weekly trend
Line chart of the selected metric over the last 30 days by ISO week. Toggle between: Pass rate, Efficiency, Cycles, Checks.
## Outcomes by session size
Heatmap of session outcomes plotted by duration (rows) vs activity count (columns) shows whether longer or more complex sessions tend to fail more.
## Recent corpus
Three text lists drawn from recent session verdicts:
* **Recent issues:** text the agent flagged during failed verifications
* **Recent fixes:** what the agent said it did to resolve problems
* **Recent verification checks:** assertions the agent verified against
These are useful for spotting recurring language patterns in failures.
# Findings
Source: https://docs.ironbee.ai/console/findings
Observations and problems identified during analysis, per project and across your account.
**Findings** are observations that IronBee's analysis identified, a file with a high fix-cycle rate, a pattern of retries, excessive token spend, or a behavioral habit worth changing. Each finding is grounded in actual session data.
## Finding areas
| Area | What it covers |
| -------------- | ---------------------------------------------------------------- |
| **Quality** | Verification thoroughness, fix effectiveness, recurring failures |
| **Efficiency** | Time and compute waste, rework rate, slow sessions |
| **Patterns** | Files and issues that recur across sessions |
| **Behavior** | Agent working habits and interaction style |
| **Cost** | Token spend, cache efficiency, expensive sessions |
## Severity levels
| Severity | Meaning |
| ---------------------- | ---------------------------------------------------------- |
| `notice` (Information) | Descriptive observation, informational, no action required |
| `concern` | Worth watching, may have a linked recommendation |
| `critical` | Serious degradation, should have a linked recommendation |
Only `concern` and `critical` findings can have recommendations attached.
## Scopes
Findings across all projects on the account.
Findings scoped to a single project.
# Account Findings
Source: https://docs.ironbee.ai/console/findings-account
Findings across all projects on the account.
**Findings** are observations that IronBee's analysis identified patterns and problems grounded in actual session data. Account-level findings span the entire account and are produced by the Account Cost and Account Session Insights analysis runs.
## Finding areas
| Area | What it covers |
| -------------- | ---------------------------------------------------------------- |
| **Quality** | Verification thoroughness, fix effectiveness, recurring failures |
| **Efficiency** | Time and compute waste, rework rate, slow sessions |
| **Patterns** | Files and issues that recur across sessions |
| **Behavior** | Agent working habits and interaction style |
| **Cost** | Token spend, cache efficiency, expensive sessions |
## Severity levels
| Severity | Meaning |
| ---------------------- | ---------------------------------------------------------- |
| `notice` (Information) | Descriptive observation, informational, no action required |
| `concern` | Worth watching, may have a linked recommendation |
| `critical` | Serious degradation, should have a linked recommendation |
Only `concern` and `critical` findings can have recommendations attached.
***
## KPI strip
Four tiles at the top of the page show the current finding counts:
| Tile | Description |
| -------------- | -------------------------- |
| Critical | Count of critical findings |
| Concern | Count of concern findings |
| Information | Count of notice findings |
| Total findings | Sum of all active findings |
***
## Briefing panel
Shown above the KPI strip on each visit. Reports what changed since your last visit:
* **First visit:** starts tracking from this point; come back to see deltas
* **No changes:** nothing new since your last visit (shows timestamp)
* **Changes detected:** "New **X** critical findings. Resolved **Y** concerns." in severity-colored text
Dismiss with the × button. Can be toggled in [Settings](/console/settings).
***
## Filters
| Filter | Options |
| ------------ | ------------------------------------------------------------- |
| Severity | All severities · Critical · Concern · Information |
| Area | All areas · Quality · Efficiency · Patterns · Behavior · Cost |
| Title search | Free text (min 3 characters) |
Active filters appear as chips. **Clear filters** removes severity, area, and title pinned filters (Finding ID, Analysis ID) are cleared individually.
***
## Findings table
Five columns, all sortable:
| Column | Description |
| -------- | ----------------------------------------------------------------------------- |
| Severity | Badge with icon, Critical (flame), Concern (test tube), Information (sparkle) |
| Project | Project the finding belongs to, or "Account" for account-scoped findings |
| Title | Brief description of the observation |
| Area | Quality · Efficiency · Patterns · Behavior · Cost |
| Created | How long ago the finding was generated |
Default sort: Created, newest first. Page sizes: 20, 50, or 100 rows.
***
## Finding detail drawer
Click any row to open the detail drawer:
* **Severity badge:** and area, project, and created date in the header
* **Title:** the finding headline
* **Body:** full markdown description with supporting evidence, metrics, and inline visualizations where applicable
* **View linked recommendation** button shown for `critical` and `concern` findings; navigates to the Recommendations page filtered to this finding
# Project Findings
Source: https://docs.ironbee.ai/console/findings-project
Findings scoped to a single project.
**Findings** are observations that IronBee's analysis identified patterns and problems grounded in actual session data. Project-level findings are produced by the Project Quality, Project Cost, and Project Session Insights analysis runs and reflect what's happening in a specific codebase.
Select a project from the project picker to view its findings.
## Finding areas
| Area | What it covers |
| -------------- | ---------------------------------------------------------------- |
| **Quality** | Verification thoroughness, fix effectiveness, recurring failures |
| **Efficiency** | Time and compute waste, rework rate, slow sessions |
| **Patterns** | Files and issues that recur across sessions |
| **Behavior** | Agent working habits and interaction style |
| **Cost** | Token spend, cache efficiency, expensive sessions |
## Severity levels
| Severity | Meaning |
| ---------------------- | ---------------------------------------------------------- |
| `notice` (Information) | Descriptive observation, informational, no action required |
| `concern` | Worth watching, may have a linked recommendation |
| `critical` | Serious degradation, should have a linked recommendation |
Only `concern` and `critical` findings can have recommendations attached.
***
## KPI strip
Four tiles show counts pulled directly from the project's stats:
| Tile | Description |
| -------------- | ------------------------------------------- |
| Critical | Count of critical findings for this project |
| Concern | Count of concern findings |
| Information | Count of notice findings |
| Total findings | Sum of all active findings |
***
## Briefing panel
Reports changes since your last visit to this project's findings:
* **First visit:** starts tracking from this point
* **No changes:** nothing new since your last visit (shows timestamp)
* **Changes detected:** new and resolved findings summarized in severity-colored text
Dismiss with the × button. Can be toggled in [Settings](/console/settings).
***
## Filters
| Filter | Options |
| ------------ | ------------------------------------------------------------- |
| Severity | All severities · Critical · Concern · Information |
| Area | All areas · Quality · Efficiency · Patterns · Behavior · Cost |
| Title search | Free text (min 3 characters) |
Active filters appear as chips. **Clear filters** removes severity, area, and title — pinned filters (Finding ID, Analysis ID) are cleared individually.
***
## Findings table
Four columns, all sortable (no Project column, scope is already fixed to the selected project):
| Column | Description |
| -------- | ----------------------------------------------------------------------------- |
| Severity | Badge with icon, Critical (flame), Concern (test tube), Information (sparkle) |
| Title | Brief description of the observation |
| Area | Quality · Efficiency · Patterns · Behavior · Cost |
| Created | How long ago the finding was generated |
Default sort: Created, newest first. Page sizes: 20, 50, or 100 rows.
***
## Finding detail drawer
Click any row to open the detail drawer:
* **Severity badge** and area, project, and created date in the header
* **Title:** the finding headline
* **Body:** full markdown description with supporting evidence, metrics, and inline visualizations where applicable
* **View linked recommendation** button shown for `critical` and `concern` findings; navigates to the Recommendations page filtered to this finding
# Fix Detail
Source: https://docs.ironbee.ai/console/fix-detail
The event timeline and code diffs for a single fix cycle.
The fix detail panel opens when you click a fix interval in the [Session Timeline](/console/session-timeline). It shows a chronological timeline of everything that happened during the fix which files changed, what the operations were, and the exact code diffs.
***
## Header
The panel header shows the fix ID. If the fix is still running, an **In progress** badge appears alongside it.
***
## Stats
Four metrics shown as chips below the header:
| Field | Description |
| -------- | ------------------------------------- |
| Duration | Total elapsed time for this fix |
| Files | Number of unique files modified |
| Changes | Total number of file change events |
| Started | Absolute timestamp when the fix began |
***
## Event timeline
A vertical chronological list of every event recorded during the fix:
### Fix started
* User email that initiated the fix
* Session ID
### File change
Each file edit appears as its own event:
* **File path:** directory (muted) and filename (bold), full path on hover
* **Operation chip:** `create`, `update`, or `delete`
* **Diff stats:** lines added (green) and lines removed (red)
* **View code:** button opens the [Diff Dialog](#diff-dialog) (only shown when changeset data is available)
* **Tool chip:** the tool that made the change
### Fix ended
* Total fix duration
* Reason the fix concluded (if provided)
***
## Diff Dialog
Clicking **View code** on a file change event opens a modal showing the full unified diff for that file:
* **File path** and diff stats (lines added / removed) in the header
* **Copy** button copies the entire changeset to the clipboard
* **Diff table** has columns: old line number, new line number, sign (`+` / `−`), content
* Added lines: green background
* Removed lines: red background
* Hunk headers (`@@ -start,count +start,count @@`): blue background
* Meta lines (e.g., `\ No newline at end of file`): italic, muted
The diff is displayed in unified format only.
# Fixes
Source: https://docs.ironbee.ai/console/fixes
Code changes the agent makes to resolve failed verifications.
A **fix** is a set of code changes the agent makes in response to a failed verification. After a fix, the agent re-verifies, if it passes, the session continues; if it fails again, another fix cycle begins.
Fixes are accessed through the [Session Timeline](/console/session-timeline), they appear as labeled intervals (Fix 1, Fix 2, …) nested inside activity bars. Click a fix interval to open the [Fix Detail](/console/fix-detail) panel.
***
## Fix lifecycle
1. A verification fails, the agent reports issues
2. The agent edits one or more files to address the issues
3. A new verification cycle runs
4. If it passes, the session continues to completion; if it fails, the cycle repeats up to `maxRetries`
All fix cycles are recorded in the timeline so you can trace exactly what the agent changed and whether each change helped.
***
## Interpreting fixes
The number of fix cycles in a session is a signal of difficulty:
| Fix count | Interpretation |
| --------- | ------------------------------------------------------------------------------------------- |
| 0 | The agent verified successfully on the first attempt |
| 1–2 | Normal for moderately complex changes |
| 3+ | The agent struggled, worth reviewing [Quality Analysis](/console/analysis-quality) findings |
Fixes clustered on the same files across many sessions suggest those files are error-prone and may benefit from clearer code or better test coverage.
***
## Relationship to verification quality
Fix count, fix effectiveness (did the fix actually resolve the issue?), and backfiring fixes (fixes that introduced new problems) are all surfaced as metrics in [Quality Analysis](/console/analysis-quality).
# Other Activity
Source: https://docs.ironbee.ai/console/other
Tool calls and agentic interactions outside of verification and fix cycles.
Not everything an agent does falls inside a verification or fix cycle. **Other** intervals capture the tool calls and agentic interactions that happen between named cycles: setup work, general exploration, file reads, web searches, shell commands, sub-agent spawns, and anything else the agent does before or after verifying.
These intervals appear in the [Session Timeline](/console/session-timeline) as **Other** bars nested inside activity rows. Click one to open the Other detail panel.
***
## Stats
Four metrics shown at the top of the panel:
| Field | Description |
| -------- | ----------------------------------------------------------------- |
| Duration | Total elapsed time for this interval |
| Events | Number of tool call events recorded |
| Activity | Which parent activity this interval belongs to (e.g., Activity 1) |
| Started | Absolute timestamp when the interval began |
***
## Event timeline
A chronological list of every tool call and agentic event in the interval. Each row shows:
* **Tool name:** the tool invoked, with any prefix stripped for readability
* **MCP server:** if the tool belongs to an MCP server, the server name is shown as a chip
* **Tool type:** `mcp`, `skill`, or `sub_agent` where applicable
* **Time offset:** relative to the start of the interval (e.g., `+4s 210ms`)
* **Absolute timestamp**
* **Duration:** how long the tool call took
* **Input size:** bytes of input passed to the tool
* **Response size:** bytes returned by the tool
* **Error:** error message if the call failed
* **View input:** button opens the full tool input as JSON
Tool icons are color-coded by domain:
| Color | Domain |
| ------ | ----------------------------------- |
| Blue | File operations (read, write, edit) |
| Purple | Search |
| Orange | Shell / exec (Bash, terminal) |
| Green | Web (fetch, browser) |
| Pink | UI interactions |
| Gray | Diagnostic / flow control |
***
## What you'll typically see here
Other intervals contain the bulk of an agent's day-to-day work, the parts that aren't about proving a change is correct:
* **Reading and exploring:** file reads, directory listings, grep searches
* **Planning and reasoning:** turns where the agent thinks without calling tools, or uses TodoWrite / task tracking
* **Web activity:** WebFetch, WebSearch, or MCP-based HTTP calls made during research
* **Shell commands:** Bash invocations for building, running tests, installing dependencies
* **Sub-agent interactions:** spawning and waiting on background agents
* **MCP tool calls:** any tool from a connected MCP server not tied to a verification cycle
Long Other intervals between verifications can indicate the agent spent significant time exploring or debugging before it felt confident enough to verify a useful signal alongside the [Session Shape](/console/session-analytics#session-shape) card in Analytics.
# Profile
Source: https://docs.ironbee.ai/console/profile
Your identity, authentication provider, and avatar preferences.
The Profile page shows your personal account details. Access it from the bottom of the sidebar.
## Identity
* **Name** is your display name, or email if no name is set
* **Status** shows as Active with a green indicator when you are logged in
## Email
Your account email address with a verification badge showing which provider confirmed it.
## Authentication
The provider you used to sign in: Google, GitHub, or Email & Password.
## Profile picture
If your account has a profile picture (from OAuth), a toggle lets you show or hide it in the sidebar and other UI surfaces. When hidden, IronBee displays your initials instead.
# Projects
Source: https://docs.ironbee.ai/console/projects
Organize your codebases and track verification health at a glance.
A **project** in IronBee maps to a codebase. When you run `ironbee install` in a directory, that directory is associated with a project and all session data flows there automatically.
## The projects page
The projects page is the home screen of the IronBee Console. It shows every project your account has access to. Use the **date filter** in the page header to scope all metrics to a specific time range.
## Quick Search
Use the search bar at the top of the console to jump directly to any project, session, or finding by ID or keyword. Quick Search returns results across all projects your account has access to.
## View modes
Toggle between **Card view** and **List view** using the toolbar controls. Your preference is saved automatically.
### Card view
* **Project name**
* **Last active date**
* **Pass rate donut chart**, center label shows the percentage of verifications that passed; hover for a passed/failed count breakdown
* **KPI stack**, Sessions, Verifications, Fixes counts
* **Time breakdown**: Total activity time split into Coding, Verification, and Fix phases with percentages
* **Findings tiles**, Critical, Concern, and Notice finding counts (click to go directly to the filtered Findings page)
* **Recommendations button**, shows count of active recommendations (click to open the Recommendations page)
### List view
The table has the following columns (all sortable by clicking the header):
| Column | Description |
| ------------- | --------------------------------------------------------------- |
| Project | Project name |
| Sessions | Total session count |
| Verifications | Total verification cycle count |
| Success Rate | Percentage of verifications that passed, with a bar chart |
| Fixes | Total fix attempts |
| Total Time | Combined coding + verification + fix time (hover for breakdown) |
| Verif. Time | Time spent in verification cycles |
| Fix Time | Time spent on fixes |
| Analyze | Critical / Concern / Notice finding counts (clickable) |
| Recs | Active recommendations count (clickable) |
| Activity | Last and first activity dates |
## Sorting
In card view, use the **Sort dropdown** in the toolbar to sort by: Project Name, Sessions, Verifications, Success Rate, Fixes, Total Time, Verif. Time, Fix Time, or Last Activity. In list view, click any column header to sort.
## Creating a project
Projects are created automatically the first time a session is started in a directory that has IronBee installed. No manual setup is required in the console.
## Next steps
Browse and filter all sessions for a project.
View AI-powered insights across your project.
# Recommendations
Source: https://docs.ironbee.ai/console/recommendations
Concrete directives generated from findings, injected into the AI agent's context automatically.
**Recommendations** are actionable directives generated from findings. Every recommendation is tied to a specific finding (`concern` or `critical` severity) and grounded in observed session data.
## What makes recommendations different
Recommendations are not generic advice, they are imperative instructions written specifically for the AI coding agent. They are automatically injected into the agent's system prompt on the next session, so the agent adjusts its behavior without you needing to manually relay the feedback.
Example recommendations:
* *"Always check contrast ratio, form validation, and error states before writing a verdict."* (quality finding)
* *"After a fix, re-run all checks, not just the failing one."* (efficiency finding)
* *"Button.tsx has a 70% fail rate, take extra care when modifying this file."* (patterns finding)
* *"Prefer prompts with stable cached prefixes when working in src/auth/ and current cache hit rate is below 30%."* (cost finding)
## Recommendation scope
| Scope | Injected when |
| -------------- | ------------------------------------------- |
| Project-scoped | Agent works in any session for that project |
| Account-scoped | Agent works in any project for that account |
Project-scoped recommendations come from Quality, Cost, and Session Insights analysis. Account-scoped recommendations come from Account Cost and Account Session Insights analysis.
## Recommendations list
The Recommendations tab shows all active recommendations, linked to their source findings. Each recommendation includes:
* **Action:** what the agent should do, written as a clear directive
* **Source finding:** the observation that generated it (title, area, severity)
* **Status:** active or dismissed
## Dismissing recommendations
You can dismiss a recommendation if it is not relevant to your current work. Dismissed recommendations are not injected into the agent and are preserved separately from active recommendations.
When a new analysis run supersedes the current one, previously-dismissed recommendations are preserved, they are not re-activated.
## Feedback
You can mark a recommendation as helpful or not helpful. This feedback helps improve analysis quality over time for your project.
# Account Recommendations
Source: https://docs.ironbee.ai/console/recommendations-account
Recommendations across all projects on the account.
**Recommendations** are directives generated from findings, specific actions IronBee suggests to improve agent behavior, reduce cost, or increase verification effectiveness. Account-level recommendations are produced by the Account Cost and Account Session Insights analysis runs and span the entire account.
Recommendations are automatically injected into the agent's context at the start of future sessions. There is no UI indicator when this happens, injection is handled server-side.
## Recommendation statuses
| Status | Meaning |
| ------------ | --------------------------------------------- |
| `active` | Visible and being injected into agent context |
| `dismissed` | Hidden from the list (no UI toggle to view) |
| `superseded` | Replaced by a newer recommendation hidden |
Only `active` recommendations appear in the list. Dismissed and superseded recommendations are not shown.
***
## Briefing panel
Shown above the recommendations list on each visit. Reports changes in active recommendation count since your last visit:
* **First visit:** starts tracking from this point; come back to see deltas
* **No changes:** nothing new since your last visit (shows timestamp)
* **Changes detected:** new and resolved recommendations summarized
Dismiss with the × button. Can be toggled in [Settings](/console/settings).
***
## Filters
| Filter | Options |
| ------------- | ---------------------------- |
| Action search | Free text (min 3 characters) |
Active filters appear as chips. Pinned filters (Finding ID, Analysis ID) are cleared individually.
There are no severity or area filters on the recommendations page.
***
## Recommendations table
Three columns, all sortable:
| Column | Description |
| ------- | -------------------------------------------------------------------------------------- |
| Project | Project the recommendation applies to, or "Account" for account-scoped recommendations |
| Action | The recommended directive |
| Created | How long ago the recommendation was generated |
Default sort: Created, newest first. Page sizes: 20, 50, or 100 rows.
***
## Recommendation detail drawer
Click any row to open the detail drawer:
* **Status badge:** `active` or `dismissed`, shown in the header
* **Metadata line:** scope (account or project name), created date, dismissed time (if applicable)
* **Action:** full markdown description of the recommended directive
* **Causal chain strip:** three-step provenance trail:
1. **Recommendation:** this recommendation
2. **Source Finding:** the finding that triggered it, with severity badge
3. **Source Analysis:** the analysis run that produced the finding
### Dismiss button
A **Dismiss** button is present in the drawer but is currently disabled ("Dismiss (coming soon)"). Dismissal support is not yet available.
# Project Recommendations
Source: https://docs.ironbee.ai/console/recommendations-project
Recommendations scoped to a single project.
**Recommendations** are directives generated from findings, specific actions IronBee suggests to improve agent behavior, reduce cost, or increase verification effectiveness. Project-level recommendations are produced by the Project Quality, Project Cost, and Project Session Insights analysis runs and reflect what's needed in a specific codebase.
Select a project from the project picker to view its recommendations.
Recommendations are automatically injected into the agent's context at the start of future sessions. There is no UI indicator when this happens, injection is handled server-side.
## Recommendation statuses
| Status | Meaning |
| ------------ | --------------------------------------------- |
| `active` | Visible and being injected into agent context |
| `dismissed` | Hidden from the list (no UI toggle to view) |
| `superseded` | Replaced by a newer recommendation hidden |
Only `active` recommendations appear in the list. Dismissed and superseded recommendations are not shown.
***
## Briefing panel
Shown above the recommendations list on each visit. Reports changes in active recommendation count since your last visit:
* **First visit:** starts tracking from this point; come back to see deltas
* **No changes:** nothing new since your last visit (shows timestamp)
* **Changes detected:** new and resolved recommendations summarized
Dismiss with the × button. Can be toggled in [Settings](/console/settings).
***
## Filters
| Filter | Options |
| ------------- | ---------------------------- |
| Action search | Free text (min 3 characters) |
Active filters appear as chips. Pinned filters (Finding ID, Analysis ID) are cleared individually.
There are no severity or area filters on the recommendations page.
***
## Recommendations table
Two columns, both sortable (no Project column, scope is already fixed to the selected project):
| Column | Description |
| ------- | --------------------------------------------- |
| Action | The recommended directive |
| Created | How long ago the recommendation was generated |
Default sort: Created, newest first. Page sizes: 20, 50, or 100 rows.
***
## Recommendation detail drawer
Click any row to open the detail drawer:
* **Status badge:** `active` or `dismissed`, shown in the header
* **Metadata line:** scope (project name), created date, dismissed time (if applicable)
* **Action:** full markdown description of the recommended directive
* **Causal chain strip:** three-step provenance trail:
1. **Recommendation:** this recommendation
2. **Source Finding:** the finding that triggered it, with severity badge
3. **Source Analysis:** the analysis run that produced the finding
### Dismiss button
A **Dismiss** button is present in the drawer but is currently disabled ("Dismiss (coming soon)"). Dismissal support is not yet available.
# Session Analytics
Source: https://docs.ironbee.ai/console/session-analytics
Context window, cost, token usage, session shape, and tool metrics for a single session.
The Analytics tab is a scrollable dashboard of metric cards. Cards with no data for the session are hidden automatically.
***
## Session overview
Headline numbers for the session at a glance.
* **Hero stats:** Duration, Cost (USD), User turns, Files modified, Peak context, Tool errors
* **Session type:** A characterization of the session: Quick question, Exploration, Iterative refinement, Multi-task, Focused single task, or Mixed
* **Capabilities used:** Chips for MCP, Skills, Sub-agents, WebSearch, WebFetch — filled if used at least once in the session
* **Session window:** Start and end timestamps with total duration in minutes
***
## Time / Turns
Active vs idle duration split, plus user and assistant turn counts with a one-shot vs. with-retry breakdown.
***
## Code changes
Lines added, lines removed, files modified, and net line change for the session.
***
## Cache & misc
User prompt count, prompt size in bytes, approximate prompt tokens, and user interruption count.
***
## Context Window
Context occupancy over time. Two views:
* **Total** area chart of total context tokens vs the model's maximum context window
* **Breakdown** stacked chart of context by message type (Cache Read, Cache Write, Input, Output)
Summary stats: Peak tokens, Latest tokens, Peak %. Click **Open breakdown** to open the [Context Breakdown Drawer](#context-breakdown-drawer).
***
## Cost / Tokens
Total cost in USD, input tokens, output tokens, cache create tokens, and cache read tokens.
***
## Models
Donut chart showing cost distribution across the models used in the session.
***
## Per-model tokens
Table with one row per model: message count, input tokens, output tokens, cache write, cache read, and cost. Sortable by any column, default sorted by cost descending.
***
## Context Pressure
Peak context tokens vs the model's threshold, latest context tokens, a per-category breakdown (system prompt, user messages, tool results, etc.), and a progress bar relative to the full context window size.
***
## Session Shape
A horizontal stacked bar showing how the agent's turns were distributed across activity categories: coding, debugging, refactoring, testing, documentation, and analysis.
***
## Tool usage
Four related tables:
| Card | Contents |
| -------------------------------- | ------------------------------------------------------------------------------------------- |
| **Top tools** | All tools sorted by invocation count with error count, error %, input tokens, output tokens |
| **MCP servers / Shell binaries** | Toggled view: MCP server usage or shell binary (Bash) usage same columns |
| **Skills** | Custom slash commands invoked during the session |
| **Sub-agents** | Background agents spawned during the session |
***
## Other cards
Visible when the session has the relevant data:
| Card | What it shows |
| ---------------------- | -------------------------------------------------------------------------------------- |
| **Messages per day** | 30-day honeycomb grid with a weekends toggle |
| **Hour of day** | Polar bar chart of message count by hour (0–23) |
| **Response time** | Horizontal bar chart by time bucket (2–10s, 10–30s, 30s–1m, 1–2m, 2–5m, 5–15m, `>15m`) |
| **Shell command flow** | Sankey diagram of shell binary → subcommand invocations |
| **Languages** | Radar chart of lines of code per programming language |
| **Hot files** | Top 5 most-edited files, toggle between list and treemap view |
| **Tool errors** | Error count by category (command failed, edit failed, file not found, etc.) |
| **By weekday** | Horizontal bar chart of message count by day of week |
***
## Context Breakdown Drawer
Opens from the **Context Window** card. A full-height side panel with four sections:
### Overview
Snapshot of the latest query: query number, model, query source, input tokens, input size in bytes, tool count.
### Context growth
Area chart showing token count by category across the full query sequence, traces how context filled up turn by turn. Visible when the session has more than one query.
### Breakdown
What occupies the context window in the latest query:
* **Composition** tab has a treemap of 11 categories: system prompt, built-in tools, MCP tools, rules, memory, skills, system messages, user messages, assistant messages, tool results, others
* **Detail** tab has a drill-down tables showing token counts per MCP server, per rules file, per skill, and per tool result
### Counts
* **Tools:** donut chart of built-in vs MCP tool count
* **Messages:** pie chart of user, assistant, tool result, and system message counts
# Session Details
Source: https://docs.ironbee.ai/console/session-details
Overview of the session detail view, timeline and analytics.
Clicking a session row opens the session detail page. The page header shows the session ID and a breadcrumb trail (Projects → Project Name → Session ID). Two tabs organize the content:
| Tab | What it shows |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| [Timeline](/console/session-timeline) | The full activity sequence as an interactive horizontal chart, code changes, verifications, fixes, and idle time |
| [Analytics](/console/session-analytics) | A metrics dashboard with context window usage, cost, token breakdown, tool usage, session shape, and more |
## Meta row
Both tabs share a summary strip at the top of the page:
| Field | Description |
| ------------- | ---------------------------------------- |
| Duration | Total elapsed session time |
| Status | `in-progress`, `completed`, or `stopped` |
| Activities | Total activity count |
| Verifications | Total verification cycle count |
| Fixes | Total fix count |
| Started | Absolute start timestamp |
Interactive timeline of every activity, verification, and fix.
Context window, cost, token usage, session shape, and more.
# Session Timeline
Source: https://docs.ironbee.ai/console/session-timeline
An interactive horizontal chart of every activity, verification, and fix in a session.
The Timeline tab renders the session as a horizontal time-series chart. Use the **Zoom slider** to control how much time each pixel represents, zoom in to inspect a short verification cycle, zoom out to see the full session arc.
## Chart layout
The chart is split into two synchronized columns:
**Left Labels column**
Lists each activity as a row: Activity 1, Activity 2, and so on. Click a row to expand it and reveal its nested child rows: verifications, fixes, and other intervals that belong to that activity. The expanded state is indicated by a chevron icon.
**Right Chart area**
Scrollable horizontally. Each row in the labels column has a corresponding colored interval bar in the chart area. Nested child bars appear below their parent when the activity is expanded. Tick marks and an axis row at the top show the time scale.
## Interactions
* **Click an interval bar** selects it and opens a detail panel on the right side
* **Drag horizontally** pans the chart
* **Zoom slider** adjusts the time scale
## Detail panels
Clicking an interval opens one of four panels depending on what was clicked:
### Verification panel
Opens when a verification interval is clicked. Shows:
* Verdict (pass or fail)
* Checks the agent confirmed
* Issues reported (on fail)
* Fixes applied (on a passing retry)
* Trace data for the cycle
### Fix panel
Opens when a fix interval is clicked. Shows the fix details and the code diff.
### Activity panel
Opens when an activity interval bar is clicked directly (without selecting a child). Shows metadata for that activity.
### Other panel
Opens when an unaccounted interval is clicked. Shows context about time within an activity that was neither a verification nor a fix which is idle time, thinking, or tool calls not captured in a named cycle.
Click anywhere outside a panel to close it.
## Related pages
Verification cycles with evidence and verdicts.
Code changes the agent made to resolve failures.
# Sessions
Source: https://docs.ironbee.ai/console/sessions
Browse, filter, and understand every coding session in your project.
A **session** represents a single continuous working period for an AI agent — from when it starts editing to when it completes or is interrupted. Every time your agent works on a task, a new session is created.
## The sessions list
The sessions page shows all sessions for a project. Use the **date filter** in the page header to scope the list to a specific time window.
Each row displays:
| Column | Description |
| ------------- | ----------------------------------------------------------------- |
| Session ID | Truncated ID with copy button — hover for the full value |
| Email | The user account that ran the session |
| Start Time | When the session began (sortable, default newest first) |
| Duration | Total elapsed time |
| Client | AI client used: Claude Code, Codex or Cursor |
| Status | `in-progress`, `completed`, or `stopped` |
| Activities | Number of discrete actions recorded |
| Verifications | Number of verification cycles run |
| Fixes | Number of fix attempts after failed verifications |
| Issues | Number of issues reported across all verdicts |
| Files | Number of files changed during the session |
| Efficiency | Score reflecting how directly the agent reached a passing verdict |
All columns are sortable by clicking the header. In-progress sessions are not clickable.
## Session status
| Status | Meaning |
| ------------- | --------------------------------------------------------------------------------- |
| `in-progress` | The agent is still active in this session |
| `completed` | The session finished, agent submitted a verdict |
| `stopped` | The session ended before a verdict was submitted (agent interrupted or timed out) |
## Filtering sessions
Click the **Filter** button to stack multiple filters. Available filter fields:
| Field | Type | Operators |
| ------------- | -------------- | -------------------- |
| Status | Dropdown | equals |
| Client | Text | contains |
| Efficiency % | Slider (0–100) | gt, gte, lt, lte, eq |
| Verifications | Number | gt, gte, lt, lte, eq |
| Fixes | Number | gt, gte, lt, lte, eq |
| Issues | Number | gt, gte, lt, lte, eq |
| Files Changed | Number | gt, gte, lt, lte, eq |
| Duration (ms) | Number | gt, gte, lt, lte, eq |
Active filters appear as chips below the filter button. Click a chip to edit it or remove it.
## Pagination
Use the **Show Items** dropdown to display 10, 25, 50, or 100 rows per page. The page info strip shows total results and current page.
## Next steps
Explore the timeline, analytics, verifications, and fixes for a single session.
# Settings
Source: https://docs.ironbee.ai/console/settings
Customize the IronBee Console appearance and default behavior.
The Settings page controls how the console looks and behaves for your account. Access it from the bottom of the sidebar.
## Appearance
### Theme
Switch between **Light** and **Dark** mode. The transition is animated. Your selection is saved per-browser.
### Sidebar position
Move the navigation sidebar to the **left** or **right** side of the screen. A live preview shows the effect before you confirm.
### Default projects view
Choose whether the Projects page opens in **Card view** or **List view** by default. Can be overridden per-session from the Projects toolbar.
### Briefing panel
Toggle the **briefing panel** on or off. The briefing panel appears on the Findings and Recommendations pages and shows an AI-generated summary of current results. Hiding it gives more space to the data table.
# Team
Source: https://docs.ironbee.ai/console/team
Manage team members and pending invitations.
The Team page is accessible to Owners and Admins. It shows all current members and pending invitations for the account.
## Members
A searchable, sortable table of everyone on the account:
| Column | Description |
| ----------- | -------------------------------------- |
| User | Avatar, name, and email |
| Role | Owner, Admin, Member, or Billing Admin |
| Invited by | Who sent the invitation |
| Invited at | When the invitation was sent |
| Accepted at | When the member joined |
| Last login | Most recent login timestamp |
| Actions | Remove member (if you have permission) |
Click any column header to sort. Members with no data for a field sort to the bottom.
**Permission rules:**
* Owners can manage anyone
* Admins can manage Members and Billing Admins only
* You cannot remove yourself
## Invitations
A table of pending and past invitations:
| Column | Description |
| ------- | ------------------------------------- |
| Email | The invited address |
| Role | The role they will receive on joining |
| Status | `pending`, `accepted`, or `expired` |
| Expires | Expiry date of the invitation link |
| Actions | Revoke (pending) or Resend (expired) |
## Inviting a new member
Click **Invite** to open the invite dialog. Enter the email address and select a role. The invitee receives an email with a link to accept and create their account.
# Traces
Source: https://docs.ironbee.ai/console/traces
OpenTelemetry span waterfall for a verification cycle, see exactly what the agent tested and how long each tool call took.
IronBee records a **trace** for each verification cycle, an OpenTelemetry-compatible log of every tool call the agent made, organized as a hierarchy of **spans**. The trace is visualized as an interactive waterfall chart inside the verification detail panel.
## How to access traces
Traces are embedded in the [Verification Detail](/console/verification-detail) panel, they are not a standalone page.
1. Open a session and go to the **Timeline** tab
2. Click a verification event in the timeline to open the Verification panel
3. Click the **Traces** button in the verification header
The panel opens to the right. The URL updates with `tracesOpen=true` so you can link directly to it.
***
## Traces panel
The panel header shows a **count badge**, for example `5 / 12` means 5 spans match the current filters out of 12 total.
### View toggle
| Mode | Behavior |
| -------- | ---------------------------------------------------------------------------------------------------------------- |
| **Fit** | Compresses chart to fit the panel width, no horizontal scroll |
| **Wide** | Adaptive density: the longest span fills \~25% of visible width; allows horizontal scrolling for long recordings |
***
## Waterfall chart
The chart has two columns:
**Left label panel (frozen)**
* Span name
* Service name (color-coded)
* OpenTelemetry span kind icon
* Collapse / expand chevron for parent spans
**Right chart area**
* Horizontal bars representing span duration
* Time axis (in seconds) pinned to the bottom
* Bars colored by status
### Span status colors
| Color | Status |
| ----- | ------ |
| Green | OK |
| Red | ERROR |
| Gray | Unset |
Each unique service name also gets a stable color from a 24-color palette.
### Span kind icons
Kinds follow OpenTelemetry conventions: `INTERNAL`, `CLIENT`, `SERVER`, `PRODUCER`, `CONSUMER`.
***
## Filters
| Filter | Description |
| ----------- | ------------------------------------------------------ |
| Text search | Filter by span name or service name |
| Kind | All · Internal · Client · Server · Producer · Consumer |
| Status | All · OK · Error · Unset |
Active filter chips appear below the toolbar. The count badge updates as you filter.
***
## Interacting with the chart
**Navigate:**
* **Vertical scroll** browse rows
* **Horizontal drag** pan left/right within the chart area (click and drag on the background)
**Explore spans:**
* **Hover** a bar tooltip shows span name, service, kind, duration, status
* **Click** a bar opens the span JSON modal
* **Click** a label scrolls the chart horizontally to bring that span's bar into view
* **Chevron** collapse or expand a span's children
**Playback mode** (when the verification video is playing):
* A vertical **playhead** line tracks the current video position
* The active span is highlighted in gold
* Parent and sibling spans in the call chain are also highlighted
* The chart auto-scrolls to keep the active span visible
* **Seek button** on each bar click to jump the video to that span's start time
***
## Span JSON modal
Click any span bar to open its detail modal:
* **Header:** service name · span name, Copy JSON button
* **Metadata row:** `span_id`, `trace_id`, `parent_span_id`, `kind`, `status`, `duration`
* **Data section:** full key-value view of the span payload, including any custom data fields
The Copy button copies the complete span as formatted JSON.
# Verification Detail
Source: https://docs.ironbee.ai/console/verification-detail
Event timeline, video playback, verdict, and traces for a single verification cycle.
The verification detail panel opens when you click a verification interval in the [Session Timeline](/console/session-timeline). It shows everything that happened during the cycle: the event sequence, video recording, verdict, and traces.
## Header
The panel header shows the verification ID and a status chip: **Pass**, **Fail**, **In progress**, or **Unknown**. Two buttons sit alongside it:
* **Traces** toggles the [trace panel](#trace-panel)
* **Play** arms video playback (visible when a recording exists)
***
## Video playback
When a browser session recording is available, the playback section shows a video player with:
* Play / pause button
* Scrub track with drag support
* Current time and total duration
* Speed toggle — 1× and 2×
* Picture-in-Picture button
* Fullscreen button
**Keyboard shortcuts:**
| Key | Action |
| ------------- | ---------------- |
| `Space` / `k` | Play / pause |
| `←` / `→` | Seek ±1 second |
| `j` / `l` | Seek ±10 seconds |
While playing, the event timeline below highlights the event corresponding to the current video time.
***
## Event timeline
A chronological list of every event recorded during the verification cycle. Each row is clickable to expand its details.
### Event types
| Event | What it shows |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Verification started** | User email and session ID |
| **Tool call** | Tool name, MCP server (if applicable), type badge (mcp / skill / sub-agent), duration, input size, response size, any error, inline images or videos captured |
| **Verification ended** | Status, duration, and reason |
| **Verdict** | Final pass or fail, with the full **Checks**, **Issues**, and **Fixes** lists |
### Per-event details
Each row shows:
* A color-coded icon by tool domain (file, search, exec, web, UI, diagnostic, flow)
* Time offset from the start of the cycle (e.g., `+1m 23s`)
* Absolute timestamp
* Status chips. error indicator, duration, MCP server name, tool type badge
* **View JSON** button tool events split into Input / Output with byte sizes; other events show a full view
Images captured by tool calls appear inline within the event row. Click an image to open it in a lightbox.
***
## Verdict
The verdict section at the bottom of the event timeline shows the final assessment:
* **Status:** `pass` or `fail`
* **Checks:** evidence items the agent confirmed (green)
* **Issues:** what went wrong, if the verdict is `fail` (red)
* **Fixes:** what was changed to resolve issues on a passing retry (orange)
***
## Trace panel
Click **Traces** in the header to open the trace panel alongside the event timeline. The panel shows a span waterfall chart for the cycle with:
* **Filters:** by span kind (Internal / Client / Server / Producer / Consumer) and status (OK / Error / Unset)
* **Text search:** filter spans by name or service name
* **View toggle;** Fit (panel-width) or Wide (horizontal scroll for dense traces)
Click any span bar to open a JSON modal with the raw span data.
# Verifications
Source: https://docs.ironbee.ai/console/verifications
Browser, Node, and backend verification cycles how the agent tests its changes before completing.
A **verification** is a complete testing cycle the agent runs to prove that its code changes work. Before any task can complete, every affected code path must be exercised with real tools.
Verifications are accessed through the [Session Timeline](/console/session-timeline) and they appear as labeled intervals (Verification 1, Verification 2, …) nested inside activity bars. Click a verification interval to open the [Verification Detail](/console/verification-detail) panel.
***
## Verification types
IronBee supports three cycle types that can run in parallel:
### Browser cycle
The agent uses browser devtools to verify frontend and full-stack changes:
* Navigates to affected pages
* Takes screenshots at key states
* Checks the browser console for errors
* Tests user interactions (clicks, forms, navigation)
* Records a browser session video
* Submits a verdict with evidence
The browser cycle is active by default for most code file types. Disable it with `ironbee browser disable`.
### Node cycle
The agent connects to a running Node.js process to verify backend changes via V8 inspector:
* Connects to the Node inspector
* Sets tracepoints or logpoints at changed code paths
* Exercises those paths via API calls or UI interactions
* Reads back execution snapshots or runtime logs
* Submits verdict with backend evidence
The Node cycle is opt-in and enable it with [`ironbee node enable`](/cli/guides/verification#enable-or-disable-a-platform).
### Backend cycle
The agent drives real HTTP, gRPC, GraphQL, or WebSocket requests against a running backend service and verifies the responses. Works for any backend runtime (Node, Java, Python, Go, Rust, and more). Evidence is collected across three domains:
| Domain | Tools | What is captured |
| ------------------ | ----------------------------------------------------------- | -------------------------------------------------------- |
| Protocol calls | `bedt_http_*`, `bedt_grpc_*`, `bedt_graphql_*`, `bedt_ws_*` | Request/response pairs, status codes, payloads |
| Observability logs | `bedt_log_*` | Runtime log lines emitted by the service during the call |
| Database queries | `bedt_db_*` | SQL or NoSQL queries executed as a side effect |
The backend cycle is opt-in and enable it with [`ironbee backend enable`](/cli/guides/verification#enable-or-disable-a-platform).
***
## Verification status
| Status | Meaning |
| ------------- | ---------------------------------------------- |
| `in-progress` | The agent is actively running this cycle |
| `pass` | All evidence checks passed |
| `fail` | One or more checks failed |
| `abandoned` | The cycle ended before a verdict was submitted |
***
## Retry behavior
If a verification fails, the agent must fix the issues and re-verify. By default, it gets 3 attempts (`maxRetries`). After the limit is reached, the session can complete but must report unresolved issues.
Each retry creates a new verification cycle, you can see the full history in the timeline.
# What is IronBee?
Source: https://docs.ironbee.ai/getting-started/introduction
The verification and intelligence layer for agentic development.
IronBee ensures that AI coding agents **verify their changes before completing a task**. When an agent edits code, it cannot finish until it exercises the affected paths through real tools navigating pages in a browser for frontend changes, or connecting to a running Node process for backend changes and submits a passing verdict.
No more "it should work" every change is tested.
## The problem
AI coding agents are fast, but they lack accountability. An agent can write hundreds of lines of code, declare success, and move on without ever checking if the browser renders correctly, if the API responds as expected, or if anything broke.
Teams using agentic development today face:
* Silent regressions that only surface in code review or production
* No evidence that a change was actually tested
* No insight into how the agent spent its time, what it struggled with, or where it kept failing
## What IronBee does
The agent must exercise affected code paths with real tools before it can mark a task complete. Browser navigation, screenshots, console checks, and network monitoring are required not optional.
Every coding session is recorded time spent coding vs. fixing, pass/fail rates per file, retry counts, and tool usage. The console turns raw session data into actionable insights.
After each session, IronBee runs an LLM analysis pass to surface findings and recommendations what went wrong, what patterns keep appearing, and what to do next.
Findings are turned into directives that are automatically injected into the agent's context on future sessions, it learns from past mistakes without manual intervention.
The IronBee GitHub Action brings the same verification loop into your pull request workflow automatically verifying changes, fixing issues, and posting evidence on every PR.
Every tool call, verification cycle, fix attempt, and verdict is captured and available in the Console with traces, timelines, and cost breakdowns.
Never collects prompt content, file content, tool output, credentials (API keys and authentication tokens), or any PII beyond your org-configured email. Your code and secrets stay on your machine.
## How it works
```mermaid theme={null}
stateDiagram-v2
[*] --> AgentEditsCode
AgentEditsCode: Agent edits code
AgentEditsCode --> AgentTriesToFinish
AgentTriesToFinish: Agent tries to finish
AgentTriesToFinish --> CompletionGate
CompletionGate: IronBee completion gate
CompletionGate --> AgentFixesIssues: Any verification cycle fails
AgentFixesIssues: Agent fixes the issues
AgentFixesIssues --> AgentTriesToFinish
CompletionGate --> TaskCompletes: All active verification cycles pass
TaskCompletes: Task completes
TaskCompletes --> [*]
```
All session data, including tool calls, verifications, verdicts, and timing, is captured and made available in the [Console](/console/projects).
***
## Supported AI clients
| Client | Status |
| ------------------------------------------------------------- | --------- |
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | Supported |
| [Cursor](https://cursor.com) | Supported |
| [Codex](https://github.com/openai/codex) | Supported |
| OpenCode | Planned |
## Next steps
Install the CLI and run your first verification in five minutes.
Learn the terminology: sessions, verifications, cycles, verdicts, and more.
# Key Concepts
Source: https://docs.ironbee.ai/getting-started/key-concepts
Core terminology you will encounter throughout IronBee.
## Project
A **project** maps to a codebase, in practice usually a single git repository. When you run `ironbee install` in a directory, that directory is associated with a project in the console. All sessions, verifications, and analysis for that codebase are grouped under its project.
***
## Session
A **session** is a single continuous working period for an AI agent from when it starts editing to when it completes (or is interrupted). Every agent task creates a session.
Sessions record:
* All activities performed by the agent
* Every verification cycle attempted
* Total coding time, fix time, and idle time
* Pass/fail outcomes and retry counts
***
## Activity
An **activity** is a discrete action within a session. Activities include:
* Code edits the agent makes to files
* Verification cycles the agent runs to test its changes
* Fixes the agent applies after a failed verification
* Individual tool calls (browser navigation, screenshots, API requests, console checks, etc.)
***
## Verification cycle
A **verification cycle** (or just "cycle") is one complete pass of testing. IronBee supports three cycle types that can run in parallel:
### Browser cycle
The agent uses browser devtools to:
1. Navigate to affected pages
2. Take screenshots
3. Check browser console for errors
4. Test functionality (clicks, forms, navigation)
5. Submit a verdict
The browser cycle is **on by default** for code changes matching `browser.verifyPatterns` (most code file types). Disable it with `ironbee browser disable`.
### Node cycle
The agent connects to a running Node.js process and:
1. Sets V8 tracepoints or logpoints at changed code paths
2. Exercises those paths
3. Reads back execution snapshots or runtime logs
4. Submits verdict with backend evidence
The Node cycle is **opt-in** enable it with `ironbee node enable`. Only applies to Node.js backends.
### Backend cycle
The agent drives real HTTP, gRPC, GraphQL, or WebSocket calls against a running backend service and verifies the responses. Works with any backend runtime (Node, Java, Python, Go, Rust, and more).
The backend cycle is **opt-in** enable it with `ironbee backend enable`.
A single task can require **multiple cycles in parallel** the agent must provide evidence for each active cycle before completing.
***
## Verdict
A **verdict** is the agent's signed assessment of whether its changes work. It includes:
* `status`: `pass` or `fail`
* `checks`: evidence items the agent confirmed (e.g. "form submits successfully", "API returns 200")
* `issues` (on fail): what went wrong
* `fixes` (on a passing retry after a previous failure): what was changed to resolve the issues
IronBee validates the verdict against the evidence. If the evidence does not support a `pass`, the gate overrides to `fail` and the agent must retry.
***
## Fix
A **fix** is a code change made by the agent in response to a failed verification. After a fix, the agent re-verifies. All fixes are tracked separately so you can see exactly what the agent changed to resolve an issue.
***
## Trace & span
IronBee records **traces** for each verification cycle, a structured log of every tool call, with timing. Within a trace, each individual tool invocation is a **span**.
The **waterfall chart** in the console visualizes these as a timeline, making it easy to see what the agent tested, in what order, and how long each step took.
***
## Analysis
After a session completes, IronBee runs **analysis** an LLM-powered pass over the session data. Analysis produces:
* **Findings** — specific problems identified (errors, failures, inconsistencies)
* **Recommendations** — concrete suggestions for improving code quality or the verification setup
Analysis runs at two scopes: **project level** (focused on a single codebase) and **account level** (aggregated across all your projects, surfacing broader patterns).
***
## Operation modes
IronBee supports three operation modes:
### Assist mode (default)
Verification is enabled the devtools, the verifier, the `/ironbee-verify` command, and MCP servers are all installed but the completion gate does **not** automatically block the agent. The agent (or you) can run verifications on demand and the results are recorded, but a pass isn't required before completing. This is the default after `ironbee install` — the tooling is available without strict enforcement.
### Enforce mode
Verification is fully enforced. When the agent tries to complete a task, the completion gate triggers automatically and the agent cannot finish until all active verification cycles pass. Opt in with `ironbee verification auto enable` (or pick `enforce` at install time).
### Monitoring-only mode
When **verification is disabled** (`ironbee verification disable`), IronBee runs in monitoring-only mode. The enforcement hook, verification skill, and MCP servers are not installed. Sessions still record tool calls and timing data and you get full observability without slowing the agent down.
This is useful for measuring baseline agent behavior before enabling enforcement.
***
## Projects inventory
`ironbee install` records every project it touches in `~/.ironbee/projects.json`. This inventory powers batch operations like `ironbee install --all` (re-install across every registered project) and `ironbee uninstall --all` (wipe IronBee from every project). Use `ironbee register` / `ironbee unregister` for manual inventory management.
***
## Config files
IronBee reads config from three locations, deep-merged (project-local wins over project wins over global):
| File | Scope | Committed? |
| -------------------------------------- | ----------------------------------------- | --------------- |
| `~/.ironbee/config.json` | Global, applies to all projects | N/A |
| `/.ironbee/config.json` | Project-level, shared with team | Yes |
| `/.ironbee/config.local.json` | Project-local, machine-specific overrides | No (gitignored) |
The `IRONBEE_API_KEY` environment variable overrides `collector.apiKey` from any config file.
See [Configuration](/cli/configuration/configuration) for all available options.
# Quick Start
Source: https://docs.ironbee.ai/getting-started/quickstart
Sign up, install the CLI, connect to your account, and run your first verification.
## Prerequisites
* **Node.js 22 or later** check with `node --version`
* An AI coding client: [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Cursor](https://cursor.com), or [Codex CLI](https://github.com/openai/codex)
***
## Step 1 - Create your account
Go to [console.ironbee.ai](https://console.ironbee.ai) and sign up. Your account gives you access to the dashboard and generates the API key the CLI needs to ship session data.
***
## Step 2 - Install the CLI
```bash theme={null}
npm install -g @ironbee-ai/cli
```
Verify the installation:
```bash theme={null}
ironbee --version
```
***
## Step 3 - Connect the CLI to your account
Run `ironbee login` from any directory. It opens your browser at `console.ironbee.ai`, asks you to authorize the CLI, and writes a personal OAuth access token and collector URL to `~/.ironbee/config.json` automatically.
```bash theme={null}
ironbee login
```
The browser opens, you confirm, and the terminal prints:
```
✓ Logged in successfully!
Console https://console.ironbee.ai
Collector https://collector.service.ironbee.ai
Token personal (my-laptop)
Config ~/.ironbee/config.json
```
The token is named after your machine by default and shows up on the [API Tokens page](/console/access-tokens) in the Console, where you can revoke it anytime.
For automation that has no browser, the [GitHub Action](/github-action/get-started/getting-started) or any CI pipeline and use an account API key instead of `ironbee login`. Supply it through the environment:
```bash theme={null}
export IRONBEE_API_KEY=
```
Find the account API key on the [Account page](/console/account) in the Console. See [Authentication](/cli/guides/authentication) for when to use each credential.
***
## Step 4 - Set up your project
Navigate to your project directory and run:
```bash theme={null}
cd your-project
ironbee install
```
IronBee auto-detects your AI client and writes:
* **Hook configuration** — the client calls IronBee automatically when the agent finishes
* **Verification skill/rules** — the agent knows the verification workflow
* **An MCP server entry** — a single `ironbee-devtools` server carrying the tools for every cycle you enabled
* **Permissions** — grants the agent access to devtools tools
If you are using **Cursor**, you need one extra step after install: go to **Settings → Tools & MCP** and confirm the `ironbee-devtools` server is listed and on. See [Cursor setup](/cli/clients/cursor#activate-the-mcp-server) for details.
***
## Step 5 - Let the agent work
Open Claude Code, Cursor, or Codex and give the agent a task:
When the agent finishes editing code, IronBee intercepts the completion and requires verification:
1. The agent navigates to the affected pages in a real browser
2. It takes screenshots, checks the console, and tests functionality
3. It submits a verdict, pass or fail
4. If it fails, the agent fixes the issues and re-verifies
***
## Step 6 - View your results
Open the [IronBee Console](https://console.ironbee.ai) and navigate to your project. You will find:
* The session with all activity recorded
* Screenshots and browser interactions from each verification cycle
* Pass/fail verdict with evidence
* Timing breakdowns how long the agent spent coding, verifying, and fixing
***
## What's next?
Customize verify patterns, retry limits, and devtools settings.
Add Node.js or backend protocol verification for backend code changes.
Verify changes automatically on every pull request.
Understand sessions, verifications, findings, and recommendations.
# Custom Configuration
Source: https://docs.ironbee.ai/github-action/advanced/custom-configuration
Override any IronBee CLI setting the action doesn't expose as a dedicated input.
Most behavior is controlled by the action's [dedicated inputs](/github-action/configuration/configuration). For anything not exposed as an input, `ironbee_extra_config` is a raw JSON escape hatch: it's deep-merged into the generated `.ironbee/config.json`, and your keys win over the defaults.
***
## How it works
Pass a JSON object as a string. It's merged on top of the config the action generates, so you only specify the keys you want to change:
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
ironbee_extra_config: |
{
"verification": { "enable": true },
"browserDevTools": { "env": { "LOG_FILE": "/tmp/browser-devtools.log" } }
}
```
This accepts any key from the IronBee CLI config, see the [CLI configuration reference](/cli/configuration/configuration) for the full set.
***
## Tuning a verification platform
Each [verification platform](/github-action/guides/verification-platforms)'s MCP server is customized under `browserDevTools`, `backendDevTools`, or `nodeDevTools`. Set extra environment variables or replace the server entirely:
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
ironbee_extra_config: |
{
"browserDevTools": { "env": { "BROWSER_HEADLESS_ENABLE": "true" } }
}
```
See the CLI's [DevTools MCP overrides](/cli/configuration/configuration#devtools-mcp-overrides) for the full set of keys each platform accepts.
IronBee always sets its own invariants (tool-name prefix, metadata flags, platform) last, these can't be overridden via `ironbee_extra_config`.
***
## What's next?
The browser, backend, and Node.js platforms you're tuning.
Every input and output, with defaults.
# Diagnostics
Source: https://docs.ironbee.ai/github-action/advanced/diagnostics
Troubleshoot a run with verbose logging and the per-session event logs.
When a run doesn't behave as expected a surprising verdict, an early exit, or missing coverage, these tools help you see what happened.
***
## Verbose logging
Set `verbose: 'true'` to expand CI logs with the full verification prompt, tool responses, the collected artifact list, and verdict details:
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
verbose: 'true'
```
***
## Session logs and early exits
The [evidence bundle](/github-action/advanced/evidence#evidence-artifacts) includes per-session logs you can use to debug a run. Under `sessions//`, `verdict.json` holds the final verdict and `actions.jsonl` is the full event log.
If a session ends abnormally, for example, hitting `max_turns`, the [PR report](/github-action/guides/running-in-ci#the-pr-report) shows an early-exit banner with a collapsible diagnostics block (turns, cost, errors, and any blocked tool calls). Raising `max_turns` or narrowing the work with `prompt` usually resolves early exits.
***
## What's next?
Console links and the downloadable artifact bundle.
Every input and output, with defaults.
# Evidence
Source: https://docs.ironbee.ai/github-action/advanced/evidence
Console links and the downloadable artifact bundle each run produces.
Beyond the [PR report](/github-action/guides/running-in-ci#the-pr-report), each run records evidence to the IronBee Console and uploads a downloadable bundle. This page covers both.
***
## Console links
The report links each session and verification cycle to the IronBee Console so you can replay the recording and inspect the timeline. By default these point at `console.ironbee.ai`; override the host if you self-host:
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
ironbee_console_url: 'console.example.com'
```
***
## Evidence artifacts
Screenshots and recordings are organized by verification cycle and uploaded as a GitHub Actions artifact with 30-day retention:
```
.ironbee/artifacts/
cycle-1/
screenshots/homepage-before-fix.png
recordings/verification.webm
cycle-2/
screenshots/homepage-after-fix.png
recordings/verification.webm
sessions// # verdict.json, actions.jsonl
```
The download URL is also exposed as the [`artifacts_url` output](/github-action/configuration/configuration#outputs) for use in later workflow steps.
***
## What's next?
Triggers, fix behavior, and the PR report.
Troubleshoot a run with verbose logs and session data.
# How It Works
Source: https://docs.ironbee.ai/github-action/concepts/how-it-works
The verification loop the action runs in CI from diff to verdict to fix.
The IronBee Action runs the same verification loop as the [CLI](/cli/concepts/how-it-works), but unattended in CI. Instead of gating a developer's task, it reviews what changed on a push or pull request, drives Claude Code through verification, and turns the result into a PR comment or a fix PR. This page explains what happens on each run.
***
## The run, step by step
Every run is a single composite job that sets up the toolchain, verifies, and reports:
```mermaid theme={null}
flowchart TD
A[Install CLI + Claude Code + DevTools + Chromium] --> B[Configure .ironbee + ironbee install]
B --> C[Build a trigger-aware prompt]
C --> D[Run Claude Code with /ironbee-verify]
D --> E[Extract verdict + collect artifacts]
E --> F{Trigger?}
F -->|pull_request| G[Post / update PR comment]
F -->|push / manual / schedule| H[Open a fix PR if anything changed]
```
Pins and installs `@ironbee-ai/cli`, `@anthropic-ai/claude-code`, `@ironbee-ai/devtools`, and Playwright Chromium (cached across runs).
Writes `.ironbee/config.json` with the collector URL and per-mode DevTools flags, then runs `ironbee install --client claude` to wire up hooks, skills, rules, and MCP config. Your API key is passed as an env var, never written to disk.
Builds a verification prompt tailored to the trigger diff-based for pushes and PRs, full-application for manual and scheduled runs.
Runs Claude Code with `/ironbee-verify`, which exercises the change through each enabled DevTools mode and submits a verdict.
Extracts the final verdict, uploads evidence, and posts a PR comment or opens a fix PR depending on the trigger.
***
## The completion gate
Verification is enforced by the same **completion gate** the CLI installs, see [How Verification Works](/cli/concepts/how-it-works) for the full mechanism. In CI, the action instructs the agent to run `/ironbee-verify`, fix any issues it finds, and re-verify. The gate is what makes that meaningful: each cycle defines the tools that must appear on the wire before a pass counts, so the agent can't declare success without actually exercising the change.
***
## The verdict
To pass, the agent exercises the affected paths and submits a **verdict**: `pass`, `fail`, or `unknown` with the checks it ran, issues it found, and fixes it applied. The action surfaces the final verdict two ways:
* As the [`verdict` output](/github-action/configuration/configuration#outputs) you can branch on in later workflow steps.
* As a badge at the top of the [PR report](/github-action/guides/running-in-ci#the-pr-report).
A run can go through several cycles, a failing verdict sends the agent back to fix and re-verify before the final result is recorded.
***
## Verification scope
The prompt the action builds depends on what triggered it:
| Scope | When | What the agent verifies |
| ------- | ------------------------------- | ---------------------------------------- |
| Focused | `pull_request`, `push` | Only the areas affected by the diff |
| Full | `workflow_dispatch`, `schedule` | The entire application, no diff required |
See [Running in CI](/github-action/guides/running-in-ci) for the full breakdown.
***
## Fix behavior
When verification produces fixes, where they land depends on the trigger:
* **Pull request** fixes are committed directly to the PR branch and the agent re-verifies.
* **Push, manual, scheduled** fixes are moved to a new branch and opened as a fix PR; the original ref is left untouched.
***
## Sessions and recording
Each run is recorded as a **session** to the IronBee collector and shows up in the [Console](https://console.ironbee.ai), with the full timeline, recordings, and per-cycle verdicts. Locally, the same data is written under `.ironbee/sessions//` and collected into the uploaded evidence artifact. The [PR report](/github-action/guides/running-in-ci#the-pr-report) links straight to the session and to each verification cycle in the Console.
***
## What's next?
How scope, fix behavior, and the PR report change per event.
What the action records and uploads after a run.
# Configuration
Source: https://docs.ironbee.ai/github-action/configuration/configuration
All inputs and outputs for the IronBee Action, with defaults.
The complete input and output reference. For task-oriented walkthroughs, see the guides: [Running in CI](/github-action/guides/running-in-ci), [Verifying your application](/github-action/guides/verifying-your-app), [Verification platforms](/github-action/guides/verification-platforms), [Evidence](/github-action/advanced/evidence), [Diagnostics](/github-action/advanced/diagnostics), and [Custom configuration](/github-action/advanced/custom-configuration).
The only required input is `ironbee_api_key`, plus one form of Claude authentication (`anthropic_api_key` or `claude_code_oauth_token`).
***
## Inputs
### IronBee - Auth & Reporting
| Input | Required | Default | Description |
| ----------------------- | -------- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ironbee_api_key` | Yes | | Your account API key (from the Console [Account page](/console/account)) used to authenticate the collector. Passed as an env var, never written to disk. |
| `ironbee_collector_url` | No | `https://collector.service.ironbee.ai` | IronBee collector endpoint URL. |
| `ironbee_console_url` | No | `console.ironbee.ai` | IronBee Console hostname (no scheme) used to build session links in the PR report. |
### IronBee - DevTools Modes
| Input | Required | Default | Description |
| -------------------------- | -------- | ------- | --------------------------------------------------- |
| `ironbee_browser_devtools` | No | `true` | Enable browser DevTools verification (browser MCP). |
| `ironbee_backend_devtools` | No | `false` | Enable backend DevTools verification (backend MCP). |
| `ironbee_node_devtools` | No | `false` | Enable Node.js DevTools verification (node MCP). |
### IronBee - Install & Config
| Input | Required | Default | Description |
| ----------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------- |
| `ironbee_cli_version` | No | `latest` | IronBee CLI version to install (e.g. `0.4.1`). |
| `ironbee_exclude_files` | No | `false` | Set `true` to keep IronBee config files (`.ironbee/`, `.claude/`, `.mcp.json`) out of commits. |
| `ironbee_extra_config` | No | | Raw IronBee config as a JSON string, deep-merged into the generated `.ironbee/config.json` (your keys win). |
### Claude Code
| Input | Required | Default | Description |
| ------------------------- | -------- | -------- | ---------------------------------------------------------- |
| `anthropic_api_key` | Yes\* | | Anthropic API key for Claude Code. |
| `claude_code_oauth_token` | No\* | | Claude Code OAuth token (alternative to the API key). |
| `claude_code_cli_version` | No | `latest` | Claude Code CLI version to install. |
| `model` | No | | Claude model override (e.g. `claude-sonnet-4-5-20250514`). |
| `max_turns` | No | `100` | Maximum conversation turns for Claude Code. |
| `prompt` | No | | Additional instructions for the verification agent. |
| `claude_args` | No | | Additional Claude Code CLI arguments. |
### Application Under Test
| Input | Required | Default | Description |
| --------------------- | -------- | ------- | ------------------------------------------------------------------------ |
| `app_install_command` | No | | Command to install dependencies (e.g. `npm ci`). |
| `app_build_command` | No | | Command to build the application (e.g. `npm run build`). |
| `app_start_command` | No | | Command to start the application (e.g. `npm run dev`). |
| `app_url` | No | | Application URL for browser verification (e.g. `http://localhost:3000`). |
### GitHub & General
| Input | Required | Default | Description |
| ------------------- | -------- | --------------------- | ----------------------------------------------------------------------------------- |
| `github_token` | No | `${{ github.token }}` | GitHub token for PR operations. |
| `working_directory` | No | `.` | Working directory for verification. |
| `verbose` | No | `false` | Enable verbose CI logging (tool responses, prompt, artifact list, verdict details). |
\*One of `anthropic_api_key` or `claude_code_oauth_token` is required. `ironbee_api_key` is always required.
***
## Outputs
| Output | Description |
| --------------- | ----------------------------------------------------------------- |
| `verdict` | Final verification result: `pass`, `fail`, or `unknown`. |
| `artifacts_url` | Download URL for verification evidence (screenshots, recordings). |
***
## Caching
Playwright Chromium binaries (\~200 MB) are cached using `actions/cache` to speed up subsequent runs. The cache key is based on the runner OS. Browser downloads during `npm install` are skipped (`PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=true`) and installed separately with system dependencies.
# Getting Started
Source: https://docs.ironbee.ai/github-action/get-started/getting-started
Add IronBee verification to your GitHub Actions workflow.
The IronBee GitHub Action brings IronBee's verification loop into CI. On every push or pull request, it has Claude Code review your changes, verify them through IronBee DevTools, a real browser by default, plus optional backend and Node.js modes, fix any issues found, and post a report on the PR.
This guide gets the action running in your workflow in a couple of minutes. For the mechanics behind it, see [How it works](/github-action/concepts/how-it-works).
***
## Prerequisites
* An [IronBee account](https://console.ironbee.ai) and your **account API key**, found in the Console on the [Account page](/console/account). The action runs without a browser, so it authenticates with the account API key rather than an interactive [OAuth login](/cli/guides/authentication).
* An Anthropic API key (get one at [console.anthropic.com](https://console.anthropic.com)) or a Claude Code OAuth token
***
## Minimal setup
Create a file at `.github/workflows/ironbee.yml`:
```yaml theme={null}
name: IronBee Verification
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
verify:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
```
Then add both keys to your repository secrets:
1. Go to **Settings → Secrets and variables → Actions**
2. Click **New repository secret**
3. Add `IRONBEE_API_KEY` (your IronBee API key) and `ANTHROPIC_API_KEY` (your Anthropic key)
That's it. The next push or pull request will trigger a verification run.
***
## With application build and start
Verification needs your app running. Tell the action how to bring it up:
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
app_install_command: 'npm ci'
app_build_command: 'npm run build'
app_start_command: 'npm run start'
app_url: 'http://localhost:3000'
```
These inputs are optional but recommended. Without them the agent infers how to install, build, start, and reach your app from the repository which works, but is slower and less reliable than spelling it out. See [Verifying your application](/github-action/guides/verifying-your-app) for details.
***
## Required permissions
The action needs these GitHub token permissions to operate:
| Permission | Purpose |
| ---------------------- | ------------------------------------------------- |
| `contents: write` | Commit fixes to PR branches, create fix branches |
| `pull-requests: write` | Post verification report comments, create fix PRs |
| `issues: write` | Update PR comments via the GitHub API |
***
## Authentication
The action needs two credentials:
**IronBee API key (always required)** authenticates the collector so sessions are recorded and reportable. Passed as an env var, never written to disk.
```yaml theme={null}
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
```
**Claude authentication (one of the two)** either an Anthropic API key:
```yaml theme={null}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
```
…or a Claude Code OAuth token:
```yaml theme={null}
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
```
***
## Next steps
How the action behaves on different events and what it reports.
Build commands, app URL, verification platforms, and more.
# Running in CI
Source: https://docs.ironbee.ai/github-action/guides/running-in-ci
How the action behaves on each trigger - verification scope, fix strategy, and what it reports back.
The IronBee Action adapts to what triggered the workflow: the verification scope and fix strategy change per event, and so does how results are reported back. This guide covers each trigger and the report the action produces.
***
## Pull request
```yaml theme={null}
on:
pull_request:
types: [opened, synchronize]
```
**Verification scope:** Diff-based reviews changed files and verifies affected pages only.
**Fix behavior:** Fixes are committed directly to the PR branch. The agent re-verifies after each fix.
**Report:** A verification report is posted as a PR comment. If the comment already exists (re-run), it is updated in place.
This is the most common trigger and the recommended starting point for most projects.
***
## Push to main
```yaml theme={null}
on:
push:
branches: [main]
```
**Verification scope:** Diff-based reviews the commit diff and verifies affected pages.
**Fix behavior:** If issues are found, the action creates a new branch with fixes and opens a pull request targeting `main`.
Use this alongside the PR trigger to catch anything that merged without issues but broke in context.
***
## Scheduled smoke test
```yaml theme={null}
on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 09:00 UTC
```
**Verification scope:** Full tests the entire application, not just changed files.
**Fix behavior:** Creates a fix PR if issues are found.
Use this for regular regression checks or to catch drift between releases. The full scope means no change is required, the agent tests every meaningful page and flow it can find.
***
## Manual verification
```yaml theme={null}
on:
workflow_dispatch:
```
**Verification scope:** Full tests the entire application.
**Fix behavior:** Creates a fix PR if issues are found.
Trigger from the **Actions** tab in GitHub. Useful for on-demand checks before a release or after a deployment.
***
## Combining triggers
You can combine multiple triggers in one workflow:
```yaml theme={null}
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize]
schedule:
- cron: '0 9 * * 1'
workflow_dispatch:
```
Each trigger type uses the appropriate verification scope automatically, no additional configuration required.
***
## Trigger summary
| Trigger | Scope | Fixes committed to | Fix PR created |
| ------------------- | ----- | -------------------- | -------------- |
| `pull_request` | Diff | PR branch (directly) | No |
| `push` | Diff | New fix branch | Yes |
| `schedule` | Full | New fix branch | Yes |
| `workflow_dispatch` | Full | New fix branch | Yes |
***
## The PR report
On `pull_request` runs, the action posts a verification report as a PR comment. If a report comment already exists (a re-run on the same PR), it's updated in place rather than duplicated.
The report contains:
* **Verdict badge:** the final `pass` / `fail` / `unknown` result, with a cycle count when there was more than one.
* **Session link:** a link to the full session in the IronBee Console.
* **Per-cycle breakdown:** each verification cycle with its checks, issues, and fixes, plus a link straight to that verification in the Console.
* **Early-exit banner:** if the session ended abnormally (for example, hitting `max_turns`), a banner and a collapsible diagnostics block explain why.
* **Artifact download:** a link to the uploaded evidence bundle.
For the self-host Console host override and the structure of the evidence bundle, see [Evidence](/github-action/advanced/evidence).
***
## Fix PRs
On non-PR triggers (`push`, `workflow_dispatch`, `schedule`), there's no PR to comment on, so the same report becomes the **body of the fix PR** the action opens when verification produces changes, see the [trigger summary](#trigger-summary) above for when that happens.
***
## What's next?
Configure build, start, and app URL for verification.
Verify through the browser, backend, and Node.js.
# Verification Platforms
Source: https://docs.ironbee.ai/github-action/guides/verification-platforms
Verify through the browser, backend, Node.js, and Android and tune each platform.
The action verifies through IronBee DevTools modes: the browser, backend, Node.js, and Android platforms, the same cycles the [CLI uses](/cli/concepts/how-it-works#verification-cycles). Each enabled platform registers its MCP server so the agent can exercise the change through that surface.
***
## The four platforms
| Platform | Input | Default | Verifies through… |
| -------- | -------------------------- | ------- | ------------------------------------------------------------------------------------ |
| Browser | `ironbee_browser_devtools` | `true` | A real Chromium browser navigation, screenshots, console, accessibility |
| Backend | `ironbee_backend_devtools` | `false` | Real protocol calls HTTP, gRPC, GraphQL, WebSocket |
| Node.js | `ironbee_node_devtools` | `false` | The Node.js V8 inspector probes and runtime snapshots |
| Android | `ironbee_android_devtools` | `false` | A real emulator over ADB app launch, taps, swipes, screenshots, UI snapshots, Logcat |
Only the browser runs by default. Opt into backend, Node.js, or Android verification by setting the corresponding input to `true`.
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
ironbee_browser_devtools: 'true'
ironbee_backend_devtools: 'true'
ironbee_node_devtools: 'false'
ironbee_android_devtools: 'false'
```
Each enabled platform is registered as an MCP server during `ironbee install`, and its log is written under `.ironbee/artifacts/` so it ships with the [evidence artifact](/github-action/advanced/evidence#evidence-artifacts).
***
## Browser on CI runners
GitHub-hosted Linux runners reject user-namespace sandboxing, which would otherwise kill Chromium on first navigation. The action handles this for you by launching Chromium with `--no-sandbox` (`BROWSER_CHROMIUM_SANDBOX=false`), no configuration needed.
***
## Tuning a platform
Each platform's MCP server can be customized beyond the enable toggles, set extra environment variables or replace the server entirely via `ironbee_extra_config`. See [Custom configuration](/github-action/advanced/custom-configuration).
***
## What's next?
Install, build, start, and reach your app.
The verification loop behind these platforms.
# Verifying Your Application
Source: https://docs.ironbee.ai/github-action/guides/verifying-your-app
Tell the action how to install, build, start, and reach your app.
Verification needs your application running, that's true for every [verification platform](/github-action/guides/verification-platforms), not just the browser. This guide covers how to point the action at your app's lifecycle commands, work in a monorepo, and focus the agent on what matters.
***
## App lifecycle commands
Four inputs describe how to bring your app up. The first three (`install`, `build`, `start`) run in order before verification; `app_url` tells the browser where to reach it:
| Input | Purpose | Example |
| --------------------- | -------------------------------- | ----------------------- |
| `app_install_command` | Install dependencies | `npm ci` |
| `app_build_command` | Build the app | `npm run build` |
| `app_start_command` | Start the server | `npm run start` |
| `app_url` | Where to reach it (browser mode) | `http://localhost:3000` |
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
app_install_command: 'npm ci'
app_build_command: 'npm run build'
app_start_command: 'npm run start'
app_url: 'http://localhost:3000'
```
**All four are optional, but providing them is recommended.** If you leave them out, the agent still verifies, it just has to resolve how to install, build, start, and reach your app from the repository first. Spelling the commands out skips that guesswork, so runs are faster and more reliable. Omit only the steps that don't apply (e.g. `app_build_command` when there's no build).
***
## Monorepos
Point the action at a subdirectory with `working_directory`. All commands, config, and verification run relative to it:
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
working_directory: 'packages/web-app'
app_install_command: 'npm ci'
app_start_command: 'npm run dev'
app_url: 'http://localhost:3000'
```
***
## Focusing the agent
By default the agent decides what to verify from the diff. Steer it when you want specific coverage:
| Input | Effect |
| ----------- | ------------------------------------------------------ |
| `prompt` | Extra instructions appended to the verification prompt |
| `max_turns` | Cap on Claude Code conversation turns (default `100`) |
| `model` | Override the Claude model |
```yaml theme={null}
- uses: ironbee-ai/ironbee-action@v1
with:
ironbee_api_key: ${{ secrets.IRONBEE_API_KEY }}
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: 'Focus on the checkout flow and payment form validation'
max_turns: '30'
```
Give the job enough headroom — verification, fixes, and re-verification can take a while. Set a generous `timeout-minutes` on the job (the examples use `45`).
***
## What's next?
Verify through the browser, backend, and Node.js.
Every input and output, with defaults.
# Compliance
Source: https://docs.ironbee.ai/help/compliance
Security and compliance posture of the IronBee platform.
IronBee is built with security and privacy as first-class concerns.
* **Encryption:** all data is encrypted at rest and in transit.
For compliance documentation or to request a security questionnaire, contact [support@ironbee.ai](mailto:support@ironbee.ai).
# Contact us
Source: https://docs.ironbee.ai/help/contact-us
Get in touch with the IronBee team.
Reach out to the IronBee team for support, partnerships, or general questions.
* Email: [support@ironbee.ai](mailto:support@ironbee.ai)
* Discord: [IronBee Community](https://discord.gg/xqBJy53dyJ)
* Slack: [IronBee Community](https://ironbeeai-community.slack.com/)
* X: [@ironbee\_ai](https://x.com/ironbee_ai)
* LinkedIn: [ironbee-ai](https://www.linkedin.com/company/ironbee-ai)
# Legal
Source: https://docs.ironbee.ai/help/legal
Terms of service, privacy policy, and other legal documents.
* [Terms of Service](https://ironbee.ai/terms)
* [Privacy Policy](https://ironbee.ai/privacy)
# Support
Source: https://docs.ironbee.ai/help/support
How to get help with IronBee.
Need help with IronBee? Here is how to reach support.
* Email: [support@ironbee.ai](mailto:support@ironbee.ai)
* Discord: [IronBee Community](https://discord.gg/xqBJy53dyJ)
* Slack: [IronBee Community](https://ironbeeai-community.slack.com/)
When you reach out, please include your account email, project name, and the session ID (if applicable) so we can investigate quickly.
# GitHub App
Source: https://docs.ironbee.ai/integrations/github
Install the IronBee GitHub App so verification runs can read your code, resolve the pull request behind a commit, and report back on it.
The IronBee GitHub App is what connects a verification run to the code it is verifying. It lets the cloud agent check out your repository during a run, resolve the pull request behind a deployed commit so there is a real changeset to work from, and report the verdict back on the commit and the pull request.
It pairs with the [Vercel integration](/integrations/vercel) and the [Netlify extension](/integrations/netlify), and it is also what binds an [`ironbee verify`](/cli/guides/verification-jobs) run to your repository.
***
## Install the App
Open the Console at **Settings → Integrations** and select **Install the GitHub App** under the GitHub card, or install it directly from [github.com/apps/ironbee-ai](https://github.com/apps/ironbee-ai).
1. On GitHub, choose the **organization or user account** to install into.
2. Choose the repositories: **all repositories**, or a selected set. Only repositories in that scope are ever read.
3. GitHub sends you back to IronBee, where you pick the **IronBee account** the installation belongs to, and select **Connect**.
Binding an installation to an account requires the **owner** or **admin** role on it. If you install into an organization you don't administer on GitHub, an org admin has to approve the request before the installation exists.
***
## What the App uses its access for
| Access | Why |
| ------------------------------ | -------------------------------------------------------------------------------------------------- |
| Repository contents (read) | The agent checks out the commit under verification during a run. |
| Pull requests (read and write) | Resolving the pull request behind a commit for the changeset, and posting the result as a comment. |
| Checks (read and write) | Opening the live **IronBee Verification** check on the commit and completing it with the verdict. |
Access is read-only where it can be: IronBee never pushes to your repository, and never opens or merges a pull request.
***
## What appears on the pull request
**The check.** When a run is queued, IronBee opens a check run named **IronBee Verification** on the deployed commit, so the pull request shows a live in-progress state while the agent works. When the run finishes, that same check is completed with the verdict:
| IronBee verdict | Check conclusion | Check title |
| -------------------------- | ---------------- | --------------------------------------- |
| `pass` | Success | Verification passed |
| `fail` | Failure | Verification failed |
| `not_applicable` | Neutral | Verification not applicable |
| Verification could not run | Neutral | IronBee could not run this verification |
| Cancelled | Cancelled | Verification canceled |
The check's **Details** link opens the session in the Console, where the timeline, the replay, the network payloads, and the files behind each finding live.
**The comment.** On top of the check, and only for a real verdict, IronBee posts a single comment on the open pull request for that commit - what was verified, what was found, and which files the findings came from. It is one comment, edited in place on every re-run, rather than a new comment per run. A cancelled run or an internal error gets the quiet neutral check and no comment.
***
## Managing the installation
**Settings → Integrations** lists every connected GitHub installation with its organization, the repositories it covers, its status (**Active** or **Suspended**), and the date it was connected. The external-link icon opens the installation's settings on GitHub.
Changes on GitHub's side flow back automatically:
* Adding or removing repositories refreshes the covered repository list.
* Suspending the installation on GitHub shows it as **Suspended**; unsuspending restores it.
* Uninstalling the App marks the installation as uninstalled in IronBee, and runs stop being reported to GitHub.
If you change the repository selection from GitHub's own settings page, IronBee refreshes the list and confirms it with a **GitHub installation updated** notice when you return to the Console.
***
## Beyond deployments
The same installation is what lets [`ironbee verify`](/cli/guides/verification-jobs) bind a run to your repository and commit, so a verdict lands next to the right code. If a `verify` run fails with a repository-checkout error or the `NO_GITHUB_INSTALLATION` error code, the App is either not installed for that repository or the repository is outside its scope - grant it access, or re-run with `--no-repo`.
***
## Troubleshooting
| Symptom | Likely cause |
| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| The run happens, but nothing appears on the pull request | The App isn't installed for that repository, or the repository is outside the installation's scope. |
| The check appears, but there is no comment | Comments are posted only for a real verdict, and only when an open pull request heads the commit. A push straight to a branch gets the check alone. |
| The verification works from a thin changeset | No pull request heads the commit, so the run falls back to the commit's own parent. |
| `NO_GITHUB_INSTALLATION` from `ironbee verify` | No active installation covers the repository the run tried to bind to. |
***
## What's next?
Verify every preview deployment as a Vercel deployment check.
Verify every deploy preview, with the verdict on the deploy summary.
Start the same cloud verification from your shell or CI with `ironbee verify`.
# Netlify
Source: https://docs.ironbee.ai/integrations/netlify
Install the IronBee Netlify extension so every deploy preview is verified automatically, with the verdict reported right on the deploy summary.
The Netlify extension puts IronBee on your deploys. When a deploy preview or branch deploy succeeds, a cloud agent opens it in a real browser, reads what the pull request changed, walks the affected flows, and reports what it found back to the deploy - with the full evidence behind it in the Console.
There is no workflow file to add and no test suite to maintain. Nothing waits on IronBee: the deploy completes as before, and the verification reports on it.
***
## Prerequisites
* A Netlify team with sites that build **deploy previews** from a Git repository.
* An IronBee account, and the **owner** or **admin** role on it - connecting a team to an account requires one of those roles.
* The [IronBee GitHub App](/integrations/github), so the agent can check out your code and resolve the pull request behind the deploy. Without it a run still happens, but with no changeset to work from.
***
## Step 1 - Install the Netlify extension
Open the Console at **Settings → Integrations**, pick **Netlify**, and select **Install the Netlify extension**. You can also reach the same flow from onboarding by choosing **Connect Netlify**.
The connect flow is three short steps on Netlify, and IronBee finishes the rest for you:
1. **Install the IronBee extension on Netlify.** The button opens app.netlify.com in a new tab; pick the team the extension should live on.
2. **Turn on verification for your sites.** Enable IronBee on the sites you deploy - only enabled sites are verified.
3. **Come back.** IronBee detects the installation and moves you forward automatically. Already installed? It can take a few seconds to show up.
***
## Step 2 - Connect the team to your IronBee account
Installing the extension puts IronBee on the Netlify team; connecting is what tells IronBee where the results should go. When the connect flow detects the installation, it moves you to the connection step:
1. Confirm the Netlify team shown.
2. Pick the **IronBee account** the team reports to. Verification results for the team's sites land in that account.
3. Select **Connect**.
Only accounts where you hold the **owner** or **admin** role appear in the picker. If none do, ask an account owner to open the same link, or to grant you the admin role and reload the page.
Once connected, the extension's **Configuration** section on Netlify shows the connection and which IronBee account the team reports to, with **Open IronBee settings** jumping straight to the Console.
***
## What the extension uses its access for
| Access | Why |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Deploy events (read) | Knowing when a deploy preview or branch deploy of an enabled site succeeds, and the URL and Git metadata behind it. |
| Deploy notifications (write) | Posting the **IronBee verification** card onto the deploy summary. |
| Sites (read) | Listing the team's sites, so verification can be enabled per site. |
The extension never changes your sites, builds, or deploy settings: it watches deploys and reports on them. Disconnecting removes the deploy notifications IronBee created on the next delivery.
***
## Step 3 - Install the GitHub App
The Netlify extension knows the deploy; the GitHub App knows the code behind it. Installing both is what gives the agent a diff to verify against, a live check on the pull request, and the result posted as a PR comment.
Install it from **Settings → Integrations → Install the GitHub App**, then follow [GitHub App](/integrations/github) for the setup and permissions.
***
## How it runs
Netlify builds exactly as before. When a deploy preview or branch deploy of an enabled site succeeds, the extension hands it to IronBee.
IronBee queues a verification job carrying the deploy URL and its Git metadata. With the GitHub App installed it resolves the **pull request** behind the deployed commit, so the agent works from the full diff. The agent then writes a scenario for what changed and exercises it in a real browser against your real backend.
While the run is going, the session in the Console streams live: every action as it executes, the browser view, and the network requests behind it. Nothing is lost when it ends - the recording replays the exact same workspace, action by action.
The verdict lands as an **IronBee verification** card on the Netlify deploy summary, and the full report with the evidence behind it lives in the Console.
***
## What you see on the deploy
The deploy summary on Netlify gets an **IronBee** row alongside Netlify's own build notes. Expanding it shows the verification card: the verdict, the issues that were found, how many checks passed, and a link that opens the full report in IronBee.
The full report is the same evidence workspace every verification gets: the action timeline, the recording synced to it, the network payloads, traces and logs, and each issue with where it happened, the proof behind it, and its impact - plus suggested fixes.
***
## Scope and limits
* **Deploy previews and branch deploys.** Production deploys are not verified.
* **Non-blocking.** The verification never holds up a deploy; it reports on a deploy that already succeeded.
* **Per-site.** Only sites where IronBee is enabled are verified.
* **Scoped to the team.** The extension covers the Netlify team it is installed on, and results report to the IronBee account that team is connected to.
***
## Managing the installation
On Netlify, the extension lives under your team's **Extensions → IronBee** page:
* **Configuration** shows the connection and which IronBee account the team reports to. **Open IronBee settings** jumps to the Console.
* **Disconnect** stops verification for every project on the team. Deploy notifications IronBee created are removed on the next delivery.
* **Uninstall**, under the danger zone, removes the extension from the team. Verification history already reported stays in the IronBee Console.
In the Console, **Settings → Integrations → Netlify** shows the connected team, or the install button when no team is connected yet.
***
## Troubleshooting
| Symptom | Likely cause |
| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| No IronBee card on the deploy summary | The deploy is a production build, IronBee isn't enabled for that site, or the extension isn't installed on the team. |
| The run verifies broad behaviour instead of what the commit changed | The GitHub App isn't installed for that repository, so there was no diff to work from. See [GitHub App](/integrations/github). |
| The Console says no Netlify team is connected | The extension is installed but the team was never connected to an IronBee account. Run the connect flow again from **Settings → Integrations**. |
| The connect flow doesn't detect the installation | Detection can take a few seconds after installing on Netlify. Keep the connect page open; it moves forward automatically. |
| No account appears in the picker when connecting | Connecting requires the **owner** or **admin** role on the IronBee account. Ask an account owner to run the connect flow, or to grant you the admin role. |
***
## What's next?
Repository access, the check on the commit, and the pull request comment.
The same cloud verification, started from your shell or CI with `ironbee verify`.
# Vercel
Source: https://docs.ironbee.ai/integrations/vercel
Install the IronBee Vercel integration so every preview deployment is verified automatically, as a Vercel deployment check.
The Vercel integration puts IronBee on your deployments. Every preview deployment gets a check named **IronBee Verification**: a cloud agent reads what the commit changed, drives the preview in a real browser against your real backend, and reports the verdict back on the deployment - with the evidence behind it in the Console.
There is no workflow file to add and no test suite to maintain. Nothing waits on IronBee: the deployment completes as before, and the check reports on it.
***
## Prerequisites
* A Vercel project that builds **preview** deployments from a Git repository.
* An IronBee account, and the **owner** or **admin** role on it - binding an installation to an account requires one of those roles.
* The [IronBee GitHub App](/integrations/github), so the agent can check out your code and resolve the pull request behind the deployment. Without it a run still happens, but with no changeset to work from.
***
## Step 1: Install the Vercel integration
Open the Console at **Settings → Integrations** and select **Install the Vercel integration** under the Vercel card. You can also install it from the [Vercel Marketplace](https://vercel.com/marketplace) listing.
On Vercel, choose the **team** and the **projects** the integration covers - all projects on the team, or a selected set. Only the projects in that scope are ever verified.
Vercel then sends you back to IronBee, to the **Connect Vercel to IronBee** page:
1. Confirm the Vercel team and the project list shown.
2. Pick the **IronBee account** the installation belongs to. Verification results for this team land in that account.
3. Select **Connect**.
Only accounts where you hold the **owner** or **admin** role appear in the picker. If none do, ask an account owner to open the same link, or to grant you the admin role and reload the page.
If the connect page reports that the installation is no longer pending, it expired or was already completed. Run the installation again from Vercel: open your Vercel team, go to the IronBee integration, and reinstall it.
***
## Step 2: Install the GitHub App
The Vercel integration knows the deployment; the GitHub App knows the code behind it. Installing both is what gives the agent a diff to verify against, a live check on the pull request, and the result posted as a PR comment.
Install it from **Settings → Integrations → Install the GitHub App**, then follow [GitHub App](/integrations/github) for the setup and permissions.
***
## Step 3: Give IronBee preview access
Preview deployments are usually behind Vercel deployment protection, which means IronBee cannot open the deployment it is meant to verify. Pick any **one** of the three options below - each is enough on its own. If your previews are already public, skip this step.
Open **Settings → Integrations** in the Console and select the info icon next to **Preview access** to see the same three options with screenshots.
The recommended option: previews stay protected, and IronBee sends the secret when it opens them.
1. In the Vercel project, open **Settings → Deployment Protection → Protection Bypass for Automation** and select **Add Secret**.
2. The secret must be exactly **32 characters**. The one Vercel generates already is, so generating it is the easiest path.
3. Copy the secret, paste it into the **Preview access** field on the Console's Integrations page, and select **Save**.
The secret can be set per project, or once for every project in the installation. Saved secrets are masked - only the first characters are shown back - and are never readable after they're stored.
1. In the Vercel project, open **Settings → Deployment Protection**.
2. Turn off **Require Log In** under **Vercel Authentication** and save.
Previews become publicly reachable: anyone with the link can open them.
Nothing is pasted into IronBee and no secret is shared - Vercel verifies an OIDC token IronBee signs.
1. In the Vercel project, open **Settings → Deployment Protection → Trusted Sources** and select **Add trusted source**.
2. Choose **External Service**, then **Custom provider**.
3. Fill the form with the values below and apply it to the **preview** environment.
| Field | Value |
| ---------- | --------------------------------------------------------- |
| Issuer URL | `https://integrations.ironbee.ai/oidc` |
| `aud` | The Vercel project ID (as shown on the Integrations page) |
| `sub` | `ironbee` |
***
## How it runs
Vercel builds exactly as before. IronBee registers a project-level check definition named **IronBee Verification** - scoped to **preview** targets, non-blocking, and re-requestable - the first time it sees a deployment for that project.
Once the deployment is ready, **IronBee Verification** shows up under **Deployment Checks** on the deployment page, with its own status and duration.
When Vercel starts the check, IronBee queues a verification job carrying the deployment URL and its Git metadata. With the GitHub App installed it also resolves the **pull request** behind the deployed commit, so the agent works from the full diff; on a push straight to a branch it falls back to the commit's own parent, a narrower changeset. The agent then writes a scenario for what changed and exercises it in a real browser against your real backend.
The verdict is written back onto the check, with the summary and any issues, and a link out to the session in the Console. When the GitHub App is installed, the same run also lands on the pull request.
***
## What you see on the deployment
The check moves through three states on the Vercel deployment page:
| State | What it means |
| --------- | -------------------------------------------------------------------------------------------- |
| Queued | The build is done and the preview has a URL. The check is waiting for its turn. |
| Running | IronBee is driving the preview. The duration counts up, and the link opens the live session. |
| Concluded | The verdict, with the evidence behind it in the Console. |
The conclusion Vercel shows maps to the verdict like this:
| IronBee verdict | Vercel conclusion |
| -------------------------- | ----------------- |
| `pass` | Succeeded |
| `fail` | Failed |
| `not_applicable` | Neutral |
| Verification could not run | Neutral |
| Cancelled | Canceled |
The check's link opens the session in the Console. While the run is going, the session streams **live**: every action as it executes, the browser view, and the network requests behind it. Once it concludes, the recording replays the exact same workspace - the action timeline, the network payloads, the traces and logs, and the files a finding came from - synced to the replay. In the Console's verification list these runs carry the **Vercel** trigger, so you can filter for them.
***
## Scope and limits
* **Preview deployments only.** Production deployments are ignored.
* **Non-blocking.** The check never holds up a deployment or a promotion; it reports on a deployment that already finished.
* **Re-requestable.** You can re-request **IronBee Verification** from the Vercel deployment page, which starts a fresh run.
* **Scoped to the installation.** Deployments of projects outside the installation's project scope are ignored.
***
## Managing the installation
**Settings → Integrations** in the Console lists every connected Vercel installation with its team, the projects it covers, its status (**Active** or **Suspended**), and the date it was connected. The external-link icon takes you to the installation on Vercel.
Changes on Vercel's side flow back automatically:
* Adding or removing projects updates the covered project list.
* Uninstalling the integration on Vercel marks the installation as uninstalled in IronBee; no further deployments are verified.
***
## Troubleshooting
| Symptom | Likely cause |
| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| No **IronBee Verification** entry on the deployment | The deployment is a production build, or the project is outside the installation's project scope. Check the project list under **Settings → Integrations**. |
| The check concludes quickly, and the session shows the agent could not open the app | Preview access is missing. Complete [Step 3](#step-3-give-ironbee-preview-access) with any one of the three options. |
| The run verifies broad behaviour instead of what the commit changed | The GitHub App isn't installed for that repository, so there was no diff to work from. See [GitHub App](/integrations/github). |
| Neutral conclusion, "IronBee could not run this verification" | An infrastructure or agent error on our side. Re-request the check from the Vercel deployment page. |
| The connect page says the installation is no longer pending | It expired or was already completed. Reinstall the integration from your Vercel team. |
***
## What's next?
Repository access, the check on the commit, and the pull request comment.
The same verification on Netlify deploy previews, via the Netlify extension.
The same cloud verification, started from your shell or CI with `ironbee verify`.