cortex exec is the headless one: an autonomy ceiling, machine-readable output, turn and time limits, and a non-zero exit when anything goes wrong. cortex run is the one you type yourself: one prompt, one streamed answer, with sessions and sharing.
This page covers which of the two to reach for, how autonomy works when there is nobody to answer an approval prompt, the output formats and what the result document contains, the limits you should always set, and the exit-code contract that a script has to respect. For pipeline recipes, see the CI cookbook.
Both create a Cloud session unless
CORTEX_COMPUTER or CORTEX_SSH_HOST selects another host. See Cloud, This PC, and SSH.
cortex exec
Give it a prompt
Autonomy
There is nobody to ask in a headless run, so the run’s authority has to be decided before it starts.--auto is that decision:
read-only and raise the level only as far as the task genuinely needs. A review job never needs write access. In this build cortex exec accepts read-only and high only: --auto low and --auto medium stop the run before anything is submitted, with --auto low/medium (client risk thresholds) is not supported by the Code service contract. No turn was submitted.
You can narrow the run further, independently of the level, by naming the tools it may use:
--list-tools prints what a given run actually has. --enabled-tools and --disabled-tools are accepted only alongside --list-tools; on a run that submits a turn they stop it first, with --enabled-tools is not supported by the Code service contract. No turn was submitted. To narrow what a real run may do, set --auto and the [permission] table. See Tools the agent uses and Permission policy.
Hooks are not approvals
A hook cannot stand in for your consent. No hook can approve a tool call, and adding a hook does not make a run more permitted than its policy allows. A hook is not a way to stop one either: hooks belong to a plugin and do not fire around the tool calls a run makes. What a headless run may do is decided by--auto, the tool allow and deny lists, and the permission policy, before the first turn. See Hooks and Permission policy.
Output formats
-o / --output-format:
--input-format selects how the prompt is fed in. It takes text, the default; stream-jsonrpc for the JSON-RPC protocol; and stream-jsonl for one JSON object per line, one line per turn, with no envelope or ids and the connection held open between turns. --response-format is accepted only as text, which is what it already is, and --output-schema is refused outright. When you need a validated result document, use -o json with --json-schema.
Add context
Limits
Other flags
A further set of flags is declared on
cortex exec but refused before a turn is submitted, each with <flag> is not supported by the Code service contract. No turn was submitted.: --skip-permissions-unsafe, --output-schema, --max-tokens, --frequency-penalty, --presence-penalty, --stop, --logprobs, --n, --best-of, --user, --suffix, --spec-model, -i/--image, and --response-format or -r/--reasoning-effort with anything but their default. cortex exec --help lists what is declared; this page tells you which of it runs.
cortex run
cortex run streams a formatted answer into your terminal and understands sessions. It is the one to use when a person is reading the output.
cortex run also declares a set of flags it refuses before submitting a turn, each with <flag> is not supported by the Code service contract. No turn was submitted.: --share, --title, --port, --add-dir, --schema, --max-tokens, --retry, --no-cache, -t/--temperature, --top-p, --top-k, --seed, --frequency-penalty, --presence-penalty, --stop, --logprobs, --n and --best-of. --attach <URL> has its own message, --attach is not supported by this runtime. No local session was started. Sampling, retries and sharing are therefore not available from cortex run on this build.
Global options that matter in a script: --color, -L/--log-level, --debug, -c/--config KEY=VALUE (repeatable) and -p/--profile.
Read the result
cortex run --format json prints one document:
cortex exec -o json prints the same idea with its own field names, including subtype, is_error, duration_ms and num_turns, so read the document your command actually produced rather than assuming a shared shape.
Continuing a session across invocations is a matter of keeping the id:
Exit codes
A non-zero exit is the contract. Do not wrap a failing run in
|| true, or you have built a pipeline that cannot fail.
Headless runs also fail closed when the coding service cannot be reached: the run prints The coding service is temporarily unavailable, exits non-zero, and never falls back to running a model locally.
Practices worth keeping
- Start at
read-onlyand raise autonomy only when the task needs it. - Always set
--timeoutand--max-turnsin anything unattended. - Use a JSON format whenever something downstream parses the output.
- Keep the transcript.
-o stream-json ... | tee run.jsonlis your audit trail. - Pass credentials through the environment, never on the command line. See Sign in to the CLI.
Related
- CI cookbook, pipeline recipes and secret handling
- Modes and permissions, the controls
--automaps onto - Permission policy, rules that apply before a run starts
- Cloud, This PC, and SSH, where an unattended run executes
- Command reference, the supported command surface group by group