Script the CLI with JSON¶
Drive alis from a script or a coding agent: get one machine-readable result per command, keep progress separate, and branch on exit codes.
Prerequisites¶
- A signed-in CLI with an active account.
- A shell, or an agent tool that runs a command and captures stdout, stderr and the exit code separately.
Steps¶
-
Add
--jsonto every call, and run one standalone command at a time. Pass the working directory with your tool's workdir setting or--cwd; do not wrap the command in a shell chain, pipe or redirect. -
Parse stdout as one JSON document. It is the result, the final operation, or an error envelope. For long-running commands it is the final operation even when the operation failed, so parse stdout before looking anywhere else:
-
Treat stderr as progress only. Under
--jsonit carries one small NDJSON event per line and never a result:There is no final stderr event; stdout arriving is the completion signal.
-
Branch on the exit code:
Code Do 0 Parse the result. 1 Read the structured failure on stdout ( erroron the operation, or an envelope), then stderr.3 Stop. Show the human the envelope's retrycommand and run it only after they approve. Never add--approveor--confirm-productionyourself.4 Have the human run alis login, then retry.5 No change ( reply_timeoutonalis specialist wait). Not a failure. -
When stdout is an error envelope, follow its fields:
{"error": {"code": "ENVIRONMENT_SELECTION_REQUIRED", "message": "…", "retry": "alis deploy --json -e <env-id>", "retryArgv": ["…"], "retryCwd": "…", "agent": "…", "details": {}}}retryis the recovery command,retryArgvandretryCwdits exact arguments and directory,agentthe instruction for an automated caller,detailsstructured extras such as the deployment environments to pick from. -
Read stdout whole. A streamed result is pruned to what is actionable and a success is under 1 KB, so never pass it through
head,tail,grepor2>/dev/null: you would drop the fields you need. Absent fields mean zero or empty. Add--verbosewhen you want every field and full progress snapshots. -
Verify creations by exit code 0 and the identifiers in the result. If a repeat returns an
AlreadyExistsenvelope, follow itsagentfield instead of repeating the mutation.
Headless budgets¶
A headless invocation (--json, or stdin and stdout not a terminal) has a time budget. If a command overruns it, usually because it hit a prompt nobody could answer, it exits 1 with a TIMEOUT envelope whose details.phase names the step. Run its retry once; if it repeats, alis doctor --json carries the command log. ALIS_COMMAND_TIMEOUT=<duration> changes the budget.
Example: build, then act on the result¶
#!/usr/bin/env bash
set -u
out=$(alis build --json --branch main 2>progress.ndjson)
code=$?
case $code in
0) version=$(printf '%s' "$out" | jq -r .version); echo "built $version" ;;
3) echo "approval needed:"; printf '%s' "$out" | jq -r .error.retry; exit 3 ;;
4) echo "run: alis login"; exit 4 ;;
*) printf '%s' "$out" | jq .error; exit "$code" ;;
esac
The script captures stdout into a variable and stderr into a file, then parses the whole result. It does not pipe alis itself.
Related: Output contract, Exit codes, Run long operations asynchronously.