All rdc commands support structured JSON output for programmatic consumption by AI agents and scripts.
Enabling JSON Output
Explicit Flag
rdc machine query --name prod-1 --output json
rdc machine query --name 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.
# These all produce JSON automatically
result=$(rdc machine query --name prod-1)
echo '{}' | rdc agent exec "machine query"
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
}
}
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the command completed successfully |
command | string | The full command path (e.g., "machine query", "repo up") |
data | object | array | null | Command-specific payload on success, null on error |
errors | array | null | Error objects on failure, null on success |
warnings | string[] | Non-fatal warnings collected during execution |
metrics | object | Execution 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 query\" or \"rdc config repository list\""
}
],
"warnings": [],
"metrics": {
"duration_ms": 12
}
}
Error Fields
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code (see ERROR_CODES constants for the canonical list) |
message | string | Human-readable description |
retryable | boolean | Whether retrying the same command may succeed |
guidance | string | Free-text hint (legacy. Prefer next for structured action data) |
next | object? | Structured next-action hint (when present). See below |
Structured next action hints
For high-value error codes (e.g. PRECONDITION_MISMATCH), errors carry a structured next field telling the agent exactly what command to suggest the user run. Agents should relay next.options[].run verbatim to the human rather than synthesizing their own command. This avoids the “agent invents a command that doesn’t exist” failure mode.
{
"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 --name mail --key STRIPE_KEY"
},
{
"description": "Skip the precondition (rotation, audited)",
"run": "rdc repo secret set --name mail --key STRIPE_KEY --value <new> --mode file --rotate-secret"
}
]
}
}]
}
Schema:
| Field | Type | Description |
|---|---|---|
next.summary | string | One-line description of what the user needs to decide |
next.options[] | array | Concrete actions; each is an alternative the user can pick |
next.options[].description | string | Human-readable explanation of this option |
next.options[].run | string | Exact 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) require corrective action before retrying.
Filtering Output
Use --fields to limit output to specific keys. This reduces token usage when only specific data is needed:
rdc machine containers --name prod-1 -o json --fields name,status,repository
Dry-Run Output
Destructive commands support --dry-run to preview what would happen:
rdc repo delete --name mail -m 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.
Agent Discovery Commands
The rdc agent subcommand provides structured introspection for AI agents to discover available operations at runtime.
List All Commands
rdc agent capabilities
Returns the full command tree with arguments, options, and descriptions:
{
"success": true,
"command": "agent capabilities",
"data": {
"version": "1.0.0",
"commands": [
{
"name": "machine query",
"description": "Show machine status",
"arguments": [
{ "name": "machine", "description": "Machine name", "required": true }
],
"options": [
{ "flags": "-o, --output <format>", "description": "Output format" }
]
}
]
}
}
Get Command Schema
rdc agent schema --command "machine query"
Returns detailed schema for a single command, including all arguments and options with their types and defaults.
Execute via JSON
echo '{"machine": "prod-1"}' | rdc agent exec "machine query"
Accepts JSON on stdin, maps keys to command arguments and options, and executes with JSON output forced. Useful for structured agent-to-CLI communication without constructing shell command strings.
Parsing Examples
Shell (jq)
status=$(rdc machine query --name 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})`);
}