Skip to main content Skip to navigation Skip to footer

JSON Output Reference

Complete reference for rdc CLI JSON output format, envelope schema, error handling, and agent discovery commands.

All rdc commands output structured JSON. Pipe it to a script or feed it directly to an agent.

Enabling JSON Output

Explicit Flag

rdc machine status prod-1 --output json
rdc machine status prod-1 -o json

Auto-Detection

When rdc runs in a non-TTY environment (piped, subshell, or spawned by an AI agent), output automatically switches to JSON. No flag needed.

# Produces JSON automatically
result=$(rdc machine status prod-1)

JSON Envelope

Every JSON response uses a consistent envelope:

{
  "success": true,
  "command": "machine query",
  "data": {
    "name": "prod-1",
    "status": "running",
    "repositories": []
  },
  "errors": null,
  "warnings": [],
  "metrics": {
    "duration_ms": 142
  }
}
FieldTypeDescription
successbooleanWhether the command completed successfully
commandstringThe full command path (e.g., "machine query", "repo up")
dataobject | array | nullCommand-specific payload on success, null on error
errorsarray | nullError objects on failure, null on success
warningsstring[]Non-fatal warnings collected during execution
metricsobjectExecution metadata

Error Responses

Failed commands return structured errors with recovery hints:

{
  "success": false,
  "command": "machine query",
  "data": null,
  "errors": [
    {
      "code": "NOT_FOUND",
      "message": "Machine \"prod-2\" not found",
      "retryable": false,
      "guidance": "Verify the resource name with \"rdc machine status\" or \"rdc repo list\""
    }
  ],
  "warnings": [],
  "metrics": {
    "duration_ms": 12
  }
}

Error Fields

FieldTypeDescription
codestringMachine-readable error code (see ERROR_CODES constants for the canonical list)
messagestringHuman-readable description
retryablebooleanWhether retrying the same command may succeed
guidancestringFree-text hint (legacy. Prefer next for structured action data)
nextobject?Structured next-action hint (when present). See below

Structured next action hints

For high-value error codes like PRECONDITION_MISMATCH, the error includes a next field with the exact commands to offer the user. Not every error code carries this field. Only those with a defined recovery path. Agents should relay next.options[].run verbatim to the human rather than synthesizing their own command. This cuts the failure mode where the agent invents a command that doesn’t exist. It happens more than you’d think.

{
  "errors": [{
    "code": "PRECONDITION_MISMATCH",
    "message": "--current digest mismatch (expected 3264f8ee…, got 611dfd8a…)",
    "next": {
      "summary": "Provide the current value or acknowledge rotation.",
      "options": [
        {
          "description": "Re-read current digest, then retry with --current",
          "run": "rdc repo secret get mail --key STRIPE_KEY"
        },
        {
          "description": "Skip the precondition (rotation, audited)",
          "run": "rdc repo secret set mail --key STRIPE_KEY --value <new> --mode file --rotate-secret"
        }
      ]
    }
  }]
}

Schema:

FieldTypeDescription
next.summarystringOne-line description of what the user needs to decide
next.options[]arrayConcrete actions; each is an alternative the user can pick
next.options[].descriptionstringHuman-readable explanation of this option
next.options[].runstringExact CLI command. Relay verbatim to the user

Retryable Errors

These error types are marked retryable: true:

  • NETWORK_ERROR, SSH connection or network failure
  • RATE_LIMITED, Too many requests, wait and retry
  • API_ERROR, Transient backend failure

Non-retryable errors (authentication, not found, invalid arguments) need a fix before you try again.

Filtering Output

Use --fields to limit output to specific keys and cut token usage:

rdc machine status prod-1 --containers -o json --fields name,status,repository

Dry-Run Output

Destructive commands support --dry-run to preview what would happen:

rdc repo delete mail@prod-1 --dry-run -o json
{
  "success": true,
  "command": "repo delete",
  "data": {
    "dryRun": true,
    "repository": "mail",
    "machine": "prod-1",
    "guid": "a1b2c3d4-..."
  },
  "errors": null,
  "warnings": [],
  "metrics": {
    "duration_ms": 8
  }
}

Commands with --dry-run support: repo up, repo down, repo delete, snapshot delete, sync upload, sync download.

Parsing Examples

Shell (jq)

status=$(rdc machine status prod-1 -o json | jq -r '.data.status')

Python

import subprocess, json

result = subprocess.run(
    ["rdc", "machine", "query", "--name", "prod-1", "-o", "json"],
    capture_output=True, text=True
)
envelope = json.loads(result.stdout)

if envelope["success"]:
    print(envelope["data"]["status"])
else:
    error = envelope["errors"][0]
    if error["retryable"]:
        # retry logic
        pass
    else:
        print(f"Error: {error['message']}")
        print(f"Fix: {error['guidance']}")

Node.js

import { execFileSync } from 'child_process';

const raw = execFileSync('rdc', ['machine', 'query', '--name', 'prod-1', '-o', 'json'], { encoding: 'utf-8' });
const { success, data, errors } = JSON.parse(raw);

if (!success) {
  const { message, retryable, guidance } = errors[0];
  throw new Error(`${message} (retryable: ${retryable}, fix: ${guidance})`);
}