Structured output
The --output json and --json shapes, which commands support each, and where neither exists.
Structured output
Most commands can print structured JSON instead of a Rich table or a confirmation message, for scripts and agents. Verified by running one command from every group against a live organization.
Two different flags, not one
The CLI's own design decision (docs/v2/cli/decisions/0005-output-json-convention.md)
says every command takes --output json, with up0 tail as the one
documented exception (--json, because it streams). As shipped, four more
commands also use a bare --json boolean flag instead of --output:
up0 deploy, up0 monitors, up0 metrics, and up0 import. The table
below documents what each command actually accepts today — check it
rather than assuming --output json works everywhere.
--output json (default: table)
These commands take --output, defaulting to a human table, and print the
same data as JSON when you pass json:
| Command | Shape |
|---|---|
up0 whoami --output json | one object |
up0 tokens create/list/revoke --output json | one object, or an array for list |
up0 ingest test --output json | one object |
up0 service-accounts create/list/rotate/revoke --output json | one object, or an array for list |
up0 schema explain --output json | a flat array, one entry per spec field |
up0 stats --output json | one object with a series array |
up0 whoami --output json{"logged_in": true, "identity": "you@example.com", "profile": "default", "org_id": "1f1317e4-...", "org_name": "your org", "org_slug": "your-org", "api_url": "https://api.up0.io", "issuer": "https://auth.up0.io", "expires_at": "2026-09-16T21:31:50.953934+00:00", "expired": false, "secret_store": "keyring", "env_overrides": []}up0 stats --output json is the same object up0 stats renders as two or
three tables — series holds one entry per signal/dimension pair, each
with a total, unit, is_estimate flag, and (when a range was given) a
bucketed points array. A dimension or bucket with nothing measured yet
renders null in JSON (no data/- in the table), never a computed 0 —
an actual 0 is a real reading and is shown as one.
--json (default: off)
These commands take a bare boolean --json flag instead — pass it to get
JSON, omit it for the human view:
| Command | Shape |
|---|---|
up0 deploy create/finish/list --json | one object, or {"items": [...]} for list |
up0 monitors list/bind/unbind --json | an array for list, one object for bind/unbind |
up0 metrics ls/query --json | one object |
up0 import --json | {"written": [...], "excluded_kinds": {...}} |
up0 monitors list --json[{"id": "924dfcbe-...", "name": "payments-health", "type": "http", "url": "https://example.com/health", "status": "down", "interval_seconds": 300, "last_check_at": "2026-09-16T20:32:02.710096Z", "last_response_time_ms": null, "created_at": "2026-09-16T13:29:31.037547Z", "uptime_24h": 0.0, "service_id": null, "service_name": null}]up0 tail --json — newline-delimited, not a single object
tail streams, so --json prints one JSON object per matching record, one
per line (JSON Lines), not a wrapped array — the shape a pipeline like
up0 tail --json | jq expects:
up0 tail --type logs --since 1h --no-follow --json{"timestamp": "2026-09-16T13:26:25.548778Z", "trace_id": "f8020ef0...", "span_id": "6cf3ac58...", "service_name": "checkout-api", "severity_text": "info", "severity_number": 9, "body": "downstream http call complete (target=https://example.com, status=200)", "row_id": "01a0aa65-..."}
{"timestamp": "2026-09-16T13:26:25.646493Z", "trace_id": "b27563ee...", "span_id": "a4bd5eef...", "service_name": "checkout-api", "severity_text": "error", "severity_number": 17, "body": "boom: deliberate example failure occurred", "row_id": "01a0aa65-..."}If a poll matched more records than the render cap (--limit/-n, default
20), one extra line reports how many were left out of that poll rather than
printing them all or silently dropping them:
{"summary": "... 78 more matching records this interval, showing latest 2 — narrow with --status/--service or increase your terminal's scrollback", "more": 78}--json also suppresses the "no results in this window" note that the
human view prints — stdout stays byte-clean JSON Lines, nothing else mixed
in.
No structured output at all
up0 auth login, up0 auth logout, and up0 health print plain text and
take no --output/--json flag — there's nothing to script against beyond
the process exit code (non-zero on failure).