---
title: CLI JSON Output & Exit Codes
url: https://arcana.otnelhq.com/docs/cli-json
---

New in v0.4.0 

Every CLI command now supports `--json` output and deterministic exit codes.

# CLI JSON Output & Exit Codes

Every Arcana CLI command supports `--json` for machine-readable output and returns deterministic exit codes. This makes Arcana safe to use in CI pipelines, automation scripts, and programmatic workflows.

## JSON Output

Add `--json` to any command to get structured JSON output instead of human-readable text:

```bash
# Session list as JSON
arcana session list --json

# Doctor check as JSON
arcana doctor --json

# Model list as JSON
arcana models --json

# Trust status as JSON
arcana trust --json
```

### JSON Structure

All JSON responses follow a consistent envelope:

```json
{
  "ok": true,
  "command": "session list",
  "data": {
    "sessions": [...]
  },
  "meta": {
    "version": "0.4.0",
    "timestamp": "2026-08-19T12:00:00Z"
  }
}
```

On error:

```json
{
  "ok": false,
  "command": "run",
  "error": {
    "code": "ARC_AUTH_INVALID",
    "message": "Provider API key is invalid or missing",
    "hint": "Set OPENAI_API_KEY or run arcana providers"
  }
}
```

## Exit Codes

Exit codes are deterministic and stable across versions. Use them in CI to distinguish failure modes:

| Code | Name | Meaning |
| --- | --- | --- |
| `0` | `OK` | Command succeeded |
| `1` | `GENERAL_ERROR` | Unspecified failure |
| `2` | `MISUSE` | Invalid arguments or usage |
| `10` | `AUTH_REQUIRED` | Authentication needed (run `arcana console login`) |
| `11` | `AUTH_INVALID` | API key invalid or expired |
| `12` | `AUTH_FORBIDDEN` | Authenticated but not authorized |
| `20` | `PROVIDER_ERROR` | LLM provider returned an error |
| `21` | `RATE_LIMITED` | Rate limit hit (retry later) |
| `22` | `QUOTA_EXHAUSTED` | Credits or quota exhausted |
| `30` | `SESSION_TIMEOUT` | Session exceeded `--timeout` |
| `31` | `SESSION_CANCELLED` | Session was cancelled by user |
| `40` | `TOOL_DENIED` | Tool execution denied by policy |
| `41` | `APPROVAL_REQUIRED` | Action needs human approval |
| `50` | `CONFIG_ERROR` | Configuration file invalid or missing |
| `51` | `TRUST_REQUIRED` | Workspace not trusted (run `arcana trust`) |

## CI Usage

### GitHub Actions

```yaml
- name: Run code review
  run: |
    result=$(arcana run --json --timeout 120 "review this PR for bugs")
    echo "$result" | jq .
    exit_code=$?
    if [ $exit_code -ne 0 ]; then
      echo "::error::Arcana failed with exit code $exit_code"
      exit $exit_code
    fi
```

### Bash Script

```bash
#!/bin/bash
set -euo pipefail

# Run with JSON output
output=$(arcana run --json "explain this codebase")

# Check exit code
case $? in
  0)  echo "Success" ;;
  10) echo "Need to login: arcana console login"; exit 1 ;;
  21) echo "Rate limited, retrying in 60s..."; sleep 60 ;;
  *)  echo "Failed: $output"; exit 1 ;;
esac

# Parse JSON
echo "$output" | jq -r '.data.response'
```

### Pipeline Gate

```bash
# Use exit codes to gate deployments
arcana run --json "run test suite" || {
  code=$?
  if [ $code -eq 41 ]; then
    echo "Approval required — check the TUI"
  elif [ $code -eq 22 ]; then
    echo "Quota exhausted — add credits"
  fi
  exit $code
}
```

## Error Codes

Error codes are stable strings that appear in JSON output and can be used for programmatic handling:

| Code | Description | Recovery |
| --- | --- | --- |
| `ARC_AUTH_INVALID` | API key missing or invalid | Set provider key or run `arcana providers` |
| `ARC_CREDITS_EXHAUSTED` | No credits remaining | Add credits at [arcana.otnelhq.com/credits](/credits) |
| `ARC_RATE_LIMITED` | Too many requests | Wait and retry |
| `ARC_SESSION_TIMEOUT` | Session exceeded timeout | Increase `--timeout` or simplify prompt |
| `ARC_TOOL_DENIED` | Tool blocked by permission policy | Check `arcana.json` permissions |
| `ARC_TRUST_REQUIRED` | Workspace not trusted | Run `arcana trust` |
| `ARC_CONFIG_INVALID` | Config file has errors | Validate `arcana.json` against schema |

## NDJSON Streaming

For long-running commands, use `--ndjson` to get newline-delimited JSON events as they happen:

```bash
arcana run --ndjson "review this codebase" | while read -r line; do
  event=$(echo "$line" | jq -r '.type')
  case $event in
    "token")   echo -n "$(echo "$line" | jq -r '.data.text')" ;;
    "tool")    echo "[tool: $(echo "$line" | jq -r '.data.name')]" ;;
    "done")    echo ""; echo "Complete. Cost: $(echo "$line" | jq -r '.data.cost')" ;;
  esac
done
```

## Related

- [CLI Commands](/docs/cli) — Full command reference
- [Configuration](/docs/configuration) — Config file and environment variables
- [Examples](/docs/examples) — Real-world automation workflows
