Use exit codes to branch: 0=success, 1=SQL/auth/parse error, 2=client init error. Capture stderr for error messages; stdout carries only result data when --format json is set.
delta-forge-cli [FLAGS] <SUBCMD> ... >stdout.log 2>stderr.log
## Overview DeltaForge CLI communicates outcomes through three channels: the process exit code, stdout, and stderr. Automation scripts key off the exit code for pass/fail, parse stdout when `--format json` is set, and retain stderr for diagnostics. The exit-code contract is narrow and stable: - `0` means the command completed and every statement succeeded. - `1` covers SQL execution failures, authentication failures, and parse errors originating from the engine or the client. - `2` covers client initialisation failures: invalid control-plane URL, HTTP client construction failure, and similar pre-flight problems. ## Recipe ```bash #!/usr/bin/env bash set -uo pipefail delta-forge-cli --profile prod --format json \ run migrations/${GIT_SHA}.sql \ >results.json 2>progress.log rc=$? case $rc in 0) jq '.' results.json ;; 1) echo 'migration failed (SQL/auth/parse)' >&2 tail -n 50 progress.log >&2 exit 1 ;; 2) echo 'client init failed; check DF_CONTROL_URL' >&2 cat progress.log >&2 exit 2 ;; *) echo "unexpected exit $rc" >&2 exit $rc ;; esac ``` ## Behavior - Progress lines (`[N/TOTAL] ...`), per-statement status, and error messages all go to stderr. Redirecting `2>` to a file or `2>&1` into a pipeline is the only way to capture them. - With `--format json`, stdout contains only the JSON document (one per executed statement for `run`, one for `query`). A trailing newline from `println!` is appended. Non-JSON formats mix result tables and progress on their respective streams the same way. - A partial `run` that fails mid-script still exits 1; statements that committed before the failure remain applied. There is no implicit rollback. - The CLI does not currently distinguish transport-level failures (network timeout, 5xx from the server) from SQL errors: both map to exit 1. Look at stderr to tell them apart.
# Branch on exit code, keep stderr for post-mortem:
if ! delta-forge-cli --format json run migration.sql 2>errors.log; then
echo 'migration failed' >&2
cat errors.log >&2
exit 1
fi
# Capture streams separately for downstream processing:
delta-forge-cli --format json query 'SELECT 1' >stdout.json 2>stderr.log
echo "exit=$?"
# Distinguish SQL errors (1) from client init errors (2):
delta-forge-cli --profile prod run etl.sql
case $? in
0) echo 'ok' ;;
1) echo 'sql/auth error' >&2; exit 1 ;;
2) echo 'client init failed (bad url, transport)' >&2; exit 2 ;;
esac