Skip to main content
Agent Mode outputs structured NDJSON instead of the interactive terminal UI. It’s how AI coding agents (Claude Code, Codex CLI, Gemini CLI) consume Kane CLI results: parse events programmatically, extract the final result, and present it to the user.

Enable Agent Mode

Add --agent to any run command:
When --agent is active:
  • The interactive TUI is fully suppressed (no boot screen, no menus)
  • stdout carries only NDJSON, one JSON object per line, and the progress UI goes to stderr
  • When stdin is not a TTY, Kane CLI turns off ask_user, so the run never stops to wait for input (see below)
Kane CLI also switches to NDJSON on its own when stdin is not a TTY, for example in CI. Pass --agent anyway, so the output format does not depend on how the shell is set up.
Add --headless wherever there is no display, such as CI runners, containers, and SSH sessions, to avoid display server errors. On a desktop, a coding agent can leave the browser visible so you can watch the run.

NDJSON Output Format

With --agent, Kane CLI writes one JSON object per line (NDJSON) to stdout. Every line carries v, the stream contract version (currently 1), and ts, the time the line was written. Here is a shortened kane-cli run stream. ... marks lines and values left out, and the run_end line shows only some of its fields:
Rules for parsing the stream:
  • The first line is stream_start. Its surface is run, testmd, or testrun, and cli_version names the Kane CLI release that wrote the stream.
  • On a run stream, step lines have no type field. A step prints a running line when it starts and a done or failed line when it ends, and the stream has no run_start, step_start, step_event, or step_end events. A testmd run stream is different: every line is typed, and each test_md_step_start and test_md_step_end pair wraps typed run_start, step_start, step_event, step_end, and run_end events for that step.
  • Ignore fields and event types you do not recognize. New ones can appear in any release without a change to v. Skip any line that is not JSON.
  • For a run that started, the last line is run_end. A run refused before it starts can exit with code 2 and no run_end line, so check the exit code first.
Kane CLI also writes the same lines to events.ndjson in the session folder while the run is in progress.

NDJSON Event Schema

The tables below describe a kane-cli run stream. A testmd run stream is typed on every line and ends with test_md_done, and a testrun run stream uses its own testrun_* events. See Command-Specific Completion.

Step Progress Lines in a run Stream

Typed Events in a run Stream

Unresolved-Variable Warning

Kane CLI checks every {{name}} in the objective before the run starts. If a name has no value, Kane CLI prints a warning and the run continues. The name is typed literally as written, unless a step sets its value first. With --agent, the warning is a single typed event, sent before the first progress event:
reason is value_missing, not_declared, or not_a_dataset_column. The warning does not change the exit code. See Unresolved variables for what each reason means and which names are never checked.

The run_end Event

run_end is the last line of a kane-cli run that started, and it carries the complete result. A run refused before it starts, for example with no start URL, no sign-in, or no Chrome, can exit with code 2 and no run_end line. Check the exit code first, then read run_end.
run_end can carry more fields than this example, such as context and result_code. Ignore the fields you do not need.

run_end Fields


Exit Codes for kane-cli run

testmd run, testrun run, generate, and the assurance commands have their own exit codes. See CLI Reference: Exit Codes.

The Evidence Pack for Each Run

Every run seals an evidence pack: one .evidence file, a standard zip, that holds the test definition, a result summary, per-step screenshots (plus annotated copies that highlight the element the agent acted on), per-step browser console and network logs, run logs, and, when a step fails, a failure record for that step. The pack holds no video. run_end has no field for the pack’s path. After the run, Kane CLI prints a hint line on stderr, not on stdout:
kane-cli evidence serve serves sealed packs from your machine to the hosted viewer and uploads nothing. See Evidence Packs and How to Debug a Failed Kane CLI Run.

Parsing the run_end Result in a Script

Save stdout to a file, read the exit code, then pick the run_end line by its type. Selecting by type keeps the script working when a run never started and has no run_end line.
fromjson? skips any line that is not JSON. When the run started, run_end is also the last line, so tail -n 1 run.ndjson returns it too.

Command-Specific Completion

Reading the last run_end event works for one-shot run only. Other commands end with their own completion event:
  • testmd run: read test_md_done for overall_status, duration_s, session_id, and the optional share_url. The stream can also contain run_end events; these finish individual steps, not the file.
  • Local testrun run suites: end with testrun_done. Suites dispatched to the remote grid then also emit remote_done; keep its status, exit, and sessions_path fields.
  • generate: ends with generate_done.
  • Assurance commands: conversational agent streams end with done. The review and read commands have their own completion contracts.
Always check the process exit code too: an early refusal, an invalid plan, or a dry run can exit without the normal completion event. Progress events are meant for live display. When you count completions, count only done and failed. Step indices can repeat, so keep track of which child agent and execution each event belongs to. testrun run prints its NDJSON stream when stdin is not a TTY, or when you pass --agent. See Batch runs (testrun).

Handling ask_user Events

If an objective requires user input mid-run, Kane CLI fires ask_user:
ask_user is turned off automatically when stdin is not a TTY. In CI/CD and AI agent contexts, stdin is never a TTY, so ask_user never fires. Write objectives that don’t require interactive prompts.
If stdin IS a TTY, respond by writing JSON to stdin:
To cancel:

Agent Mode vs Interactive Mode


Next Steps