Skip to main content
datumctl prints human-friendly tables by default, but it is built to be scripted. Every read command can emit JSON or YAML, errors can be serialized into a structured envelope, and exit codes are predictable. This page shows you how to drive datumctl from shell scripts, CI pipelines, and AI agents.
datumctl writes command results to stdout and errors to stderr. These are two independent channels controlled by two independent flags: -o/--output shapes the data on stdout, and --error-format shapes errors on stderr. You can set them independently.

Choosing an output format

Read and inspection commands accept the -o (or --output) flag. When you omit it, datumctl prints a formatted table designed for humans. Pass a machine format to get output you can parse. The -o flag is per-command — it is not a global flag. It is available on commands that render resources, including datumctl get, datumctl edit, datumctl create, datumctl apply, datumctl version, and datumctl api-resources. For datumctl get, the supported values are:
ValueDescription
(none)Formatted table (the default), for reading in a terminal.
wideThe default table plus extra columns.
jsonA single JSON document. Best for piping into jq.
yamlA YAML document.
nameJust the resource identifiers, one per line — ideal for shell loops.
jsonpath, jsonpath-as-json, jsonpath-fileExtract specific fields with a JSONPath expression.
custom-columns, custom-columns-fileBuild your own column layout.
go-template, go-template-file, template, templatefileRender output through a Go template.
A few commands take -o but with their own value set. datumctl explain accepts -o plaintext or -o plaintext-openapiv2 to choose a schema-rendering style, and datumctl diff always emits YAML (it has no -o flag). When in doubt, run datumctl <command> --help.
# Default table — human reading
datumctl get projects --organization <org-id>

# Full resource as JSON
datumctl get project my-project-id --organization <org-id> -o json

# Full resource as YAML
datumctl get project my-project-id --organization <org-id> -o yaml

# Just the names, one per line
datumctl get projects --organization <org-id> -o name

Piping and jq patterns

Because -o json produces standard JSON, you can pipe it straight into jq or any JSON tooling.
# Pull a single field out of one resource
datumctl get project my-project-id --organization <org-id> -o json \
  | jq -r '.metadata.name'

# List returns a JSON object with an "items" array — iterate it
datumctl get projects --organization <org-id> -o json \
  | jq -r '.items[].metadata.name'

# Filter by a status condition
datumctl get projects --organization <org-id> -o json \
  | jq -r '.items[] | select(.status.conditions[]?.type == "Ready") | .metadata.name'
The name format is the simplest way to feed identifiers into a loop:
# Describe every project in an organization
datumctl get projects --organization <org-id> -o name \
  | while read -r ref; do
      datumctl describe "$ref" --organization <org-id>
    done
For extracting one or two fields you often do not need jq at all — a jsonpath expression keeps the whole thing in one process:
datumctl get projects --organization <org-id> \
  -o jsonpath='{.items[*].metadata.name}'

Structured errors

By default datumctl prints errors as plain text on stderr, prefixed with error:. For automation you can switch to a structured envelope with the global --error-format flag. --error-format is a persistent (global) flag — it works on every command. It accepts one of three values:
ValueBehavior
humanThe default. Human-readable error: <message> text on stderr.
jsonA single-line JSON error envelope.
yamlThe same envelope rendered as YAML.
Passing any other value fails fast before the command runs:
$ datumctl get organizations --error-format foo
error: invalid value "foo" for --error-format
Allowed values: human, json, yaml.
In json or yaml mode, a failed command emits an envelope under a top-level error key:
datumctl get projects --organization does-not-exist --error-format json
{
  "error": {
    "message": "the organization \"does-not-exist\" was not found",
    "hint": "Run 'datumctl get organizations' to see organizations you can access.",
    "retryable": false
  }
}
The code, hint, and details fields are omitted when they are empty, so the exact set of keys varies by error. The envelope fields are:
FieldMeaning
messageThe user-facing error message. Always present.
codeAn optional machine-readable identifier (for example AUTH_EXPIRED) that agents can branch on. Omitted when empty.
hintActionable guidance for resolving the error, when available. Omitted when empty.
retryabletrue when the operation can be safely retried without further action. Always present.
detailsThe underlying technical error, when one is attached. Omitted when empty.
--error-format only changes how errors are serialized on stderr. It does not affect successful command output on stdout — that is controlled entirely by -o. A script can safely combine, for example, -o json for results and --error-format json for failures.

Treating warnings as errors

--warnings-as-errors is a global boolean flag (hidden from --help output) that causes server-side warnings returned by resource commands to be treated as failures, producing a non-zero exit. Use it in pipelines when you want deprecation notices or other API warnings to break the build rather than pass silently.
datumctl apply -f ./project.yaml --organization <org-id> --warnings-as-errors

Exit codes

datumctl follows conventional exit-code semantics, so scripts can branch on $?:
Exit codeMeaning
0Success.
1A general error — for example an unknown command, an invalid flag value, an authentication failure, or an API request that failed.
>1A lower-level fatal error surfaced by the underlying request machinery.
datumctl diff is a special case, mirroring the diff convention:
Exit codeMeaning
0No differences were found.
1Differences were found.
>1An error occurred.
This makes diff useful as a gate before writing:
datumctl diff -f ./project.yaml --organization <org-id> \
  && datumctl apply -f ./project.yaml --organization <org-id>

Wrapping datumctl in scripts and agents

1

Authenticate non-interactively

Interactive browser login is the default. For CI and headless environments, pass --no-browser to datumctl login, or use a service account. Never rely on a prompt that a pipeline cannot answer. See Service accounts for non-interactive credentials, or Automating datumctl in CI/CD for the full pipeline setup.
2

Always pass a machine format

Add -o json (or -o yaml) to read commands and --error-format json globally. Do not parse the human table — its columns are meant to change over time.
3

Pin the context explicitly

Pass --organization and --project on every invocation instead of relying on the active context. Scripts and agents should be self-describing and not depend on ambient state that another process might change. See Contexts & scoping for how scope is resolved and which flags and environment variables win.
4

Branch on exit codes and the error envelope

Check $? first. When it is non-zero and you asked for --error-format json, parse the error envelope: read retryable to decide whether to back off and retry, and code/hint to decide what to do next.
5

Prefer safe, idempotent operations

Use datumctl apply for declarative create-or-update, validate with --dry-run=server, and preview writes with datumctl diff -f. Remember that datumctl delete proceeds without a confirmation prompt.
datumctl delete has no confirmation prompt. In automation, gate destructive operations behind an explicit review step or a --dry-run=client preview before running the real delete.
A minimal, robust wrapper looks like this:
#!/usr/bin/env bash
set -euo pipefail

ORG="my-org-id"

if ! output=$(datumctl get projects --organization "$ORG" -o json --error-format json 2>err.json); then
  code=$(jq -r '.error.code // empty' err.json)
  retryable=$(jq -r '.error.retryable' err.json)
  echo "datumctl failed (code=${code:-none}, retryable=$retryable)" >&2
  exit 1
fi

echo "$output" | jq -r '.items[].metadata.name'
  • Logging in — how to log in interactively, including --no-browser for headless flows.
  • Automating datumctl in CI/CD — headless service-account login, credential helpers, and cleanup for any pipeline.
  • Contexts & scoping — how the active organization and project are resolved, and how to set them explicitly.
  • Reading resources — the get and describe commands these output controls apply to.
  • Changing resources — the apply, diff, and delete commands you gate on exit codes in scripts.
  • Discovering resources & schemas — the api-resources, api-versions, and explain commands that also honor -o for machine-readable output.
  • Audit logs & events — apply these JSON/JSONPath and pagination patterns to export audit records and stream them into a SIEM.
Last modified on July 2, 2026