Skip to main content

Headless runs

PreviewAvailable on: WindowsmacOSLinuxShips in the preview channel only. Not a stable release.

harmony run: one Harmony Agent turn from a script or CI, its options, its output schema, and its exit codes.

harmony run runs one Harmony Agent model turn without a UI and exits when the turn is over. It is the command to reach for in scripts, CI and scheduled jobs. The turn goes through the same pipeline as the TUI: it registers a session for the working directory, sends the prompt once, reads the turn's events back, and closes the session when it is done.

harmony run "fix the failing tests"
echo "refactor utils" | harmony run --output jsonl
harmony run "summarize the diff" --output json --timeout 120
harmony run "audit the config" --cwd ./service --non-interactive-approval fail

Before the first run, set up a model once: run harmony tui, then /login and /model. Without that, harmony run stops before any turn starts and exits 3 with that instruction.

Options

The prompt is the first argument. When there is none, harmony run reads it from stdin. These are the only options it accepts; anything else is a usage error (exit 2).

OptionDefaultMeaning
--cwd <dir>current directoryThe directory the agent's workspace is bound to
--timeout <seconds>600Turn deadline, up to 86400. When it passes, the turn is cancelled and the run exits 7
--output text|json|jsonltextOutput format, described below
--output-file <path>noneWrite the output to a file inside the current directory instead of stdout
--non-interactive-approval deny|faildenyWhat happens when the agent asks for a permission: deny refuses it and lets the turn continue; fail ends the turn
--no-coloroffSuppress the launch banner in text output
--detachRefused (exit 2). The runtime acknowledges a turn only once it has finished, so there is no "accepted, still running" receipt to hand back, and no command can read a detached turn's result later

Nothing is ever approved. There is no approval policy that grants a permission on your behalf; a headless run cannot give consent you did not give. There is also no hidden fallback: no other API key, subscription or model is tried when the configured one is unavailable.

The provider, model and profile come from the setup you made in the TUI. The run does not take them as flags.

Ctrl+C cancels the turn. The run reports cancelled only when the runtime confirms the cancel; if it cannot confirm, the run says the turn may still be running rather than claiming it stopped.

Output

The output schema is version 2. Every event and the final result carry "schemaVersion": 2.

  • text: the assistant's reply, then a short summary: classification, exit code, session, turn, model, event count and duration.
  • json: one object, { "result": …, "events": [ … ] }, printed when the turn is over.
  • jsonl: one line per event as it arrives, then a final line with "type": "final" holding the result.

The final result names what ran:

FieldMeaning
ok, exitCodeThe verdict; exitCode matches the process exit status
classificationsuccess, failed, cancelled, timeout, setup-required or refused
stageThe step that produced the classification, such as runtime start or model turn
sessionId, launchIntentId, workspaceId, taskIdThe runtime session this run registered and the records it is bound to
turnThe turn's ids, from the runtime's prompt receipt
textThe assistant's reply
eventCount, streamSettlementHow many events were read, and whether the event stream itself carried the turn's end
deniedPermissionRequestsPermission requests this run refused
cancelWhether a cancel was requested, and whether the runtime confirmed it
runtimeClosedWhether the session was closed at the end
errorThe NALA_* code, the message, and a remediation when there is one concrete next step

Provider-specific data is kept under provider, and any payload key that looks like a secret is replaced with [REDACTED].

With the global --json flag, the result comes back inside the standard JSON envelope instead.

Exit codes

harmony run classifies its own outcome, so a script can branch on the code.

CodeMeaning
0The turn finished
2Usage: no prompt, an unknown option, or --detach
3No model is set up, or the provider or daemon is unavailable
4Refused: a permission was denied under --non-interactive-approval fail, or the billing route lock refused the turn
5The turn failed
6Cancelled, confirmed by the runtime
7Timed out; the turn was cancelled at the --timeout deadline
8Version or capability mismatch between the CLI and the daemon
9Conflict: the write raced another writer
10Anything else the run could not classify

These codes are specific to harmony run and harmony "<prompt>". Other commands follow the shared table.

harmony "<prompt>"

A prompt with no command runs the same single turn and prints a plain transcript as the events arrive. It is not the TUI: for a conversation, run harmony or harmony tui. It takes one option, --cwd, and has no deadline; Ctrl+C cancels the turn the same way.

harmony ask and harmony plan refuse

Both commands refuse today and exit 8 with NALA_CAPABILITY_UNSUPPORTED. Nothing is submitted. ask promises a read-only turn and plan a planning-only one, and the Harmony Agent runtime cannot enforce either yet. Rather than run a turn that could change files, they do nothing. Use harmony run for a supervised turn in the meantime.