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.
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 — ironbee verify is exclusively the cloud verification job runner.Credentials
The command authenticates with your IronBee account — runironbee login once, or supply a credential from the environment (the way to do it in CI):
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 <url>— a publicly reachable deployment. The cloud agent drives it directly.--port <number>— a local application. The CLI holds a reverse tunnel open for the duration of the run, so the cloud agent reaches127.0.0.1:<port>on your machine without you exposing anything.
Target flags
--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:
::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
--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:
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 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-waitexpiry (default 60s) the command exits 1 with the last probe error.
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, itschecks / 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 <status>.
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:
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):
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
status accepts the same --json / --api-url / -C, --project-dir flags as run, plus --queue-wait <seconds> 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?
Verification
The in-editor verification gate — cycles, modes, and the verifier sub-agent.
Authentication
OAuth tokens for interactive use, API keys for CI.