Skip to main content
Every command accepts the global --json flag. Successful data goes to stdout as one JSON object; progress, browser instructions, warnings, and errors go to stderr.
Loading indicators animate in an interactive terminal, fall back to static text when redirected, and are omitted entirely in JSON mode.

Envelopes

Collections use a named plural envelope and single resources use the singular form: Paginated collections add nextPageToken when more records remain. Context results add source. Destructive results add an explicit deleted, disconnected, left, removed, released, or revoked boolean. Declining a confirmation prints this and exits 0:
Only documented fields are selected into JSON, so a new upstream response field never silently becomes part of the CLI’s contract.

Errors

Errors are one JSON object on stderr in a stable shape:
retryable and replayable answer different questions and can legitimately disagree. A retryable transport error on a non-replayable mutation means “try the command again”; a non-retryable error on a replayable mutation means “use photon operation replay”.
A shorter example with HTTP diagnostics:

Exit codes

Exit code 2 is what you get when a script forgets --force on a command that confirms. It is an argument error, not implicit approval — nothing was changed.

Debug traces

Global --debug buffers sanitized HTTP exchanges and emits one ordered trace to stderr when the command finishes:
A successful --json command keeps its single result object on stdout and writes a separate {"debug":{"http":...}} object to stderr. A failed JSON command stays one error object, with the exchanges and sanitized cause chain under error.debug. Commands that make no HTTP requests emit no trace. Each exchange records the method, sanitized endpoint, query-parameter names, safe headers, JSON bodies when safe, status, request ID, and duration. Long traces keep the first three and latest 22 exchanges and report how many were dropped in between.
Review debug output before sharing it. Photon redacts authorization headers, cookies, API-key headers, query values, tokens, device and invitation codes, payment capabilities, presigned upload paths and form data, 10DLC profiles and campaign input, Call Registry profiles, tax identifiers, phone numbers, OTP and PIN values, registration feedback, and personal fields — but debug payloads are diagnostic and their shape may change between releases.

Color

Human output uses compact tables and labeled detail views. ANSI styling is enabled only for terminal streams, and text labels and symbols always carry the same meaning without color. Styling is disabled for JSON, for redirected output, for TERM=dumb, for a non-empty NO_COLOR or NO_COLORS, and for --no-color. FORCE_COLOR=1 enables it for a non-terminal stream unless --no-color or --json disables it.

Environment variables