Skip to main content
difyctl is built to be scripted: data goes to stdout while everything else goes to stderr, the -o global flag selects the output format, and failures exit with a predictable code.

Output Formats

-o <format> selects how a command renders its result on stdout. Each command supports a subset of the five formats, listed in its --help and the Flags table on its reference page.
FormatWhat stdout gets
jsonThe result as pretty-printed JSON (2-space indent). Unicode characters appear as-is, and null fields are an explicit null, never omitted.
yamlThe same data as YAML.
nameBare resource IDs, one per line. Built for shell loops; no parsing needed.
wideThe default table plus extra columns. For example, get app -o wide adds a WORKSPACE column.
textHuman-readable text. The default for single-resource commands such as describe app and run app.
Without -o, list commands such as get app print an aligned text table and other commands print text. The JSON shapes are stable: list commands such as get app print a JSON object with the rows in an array, and two runs of the same command return the same top-level structure. For a command’s exact JSON shape, see its reference page.

Output Channels

ChannelWhat lands there
stdoutData: tables, JSON and YAML documents, IDs, run output, exported DSL
stderrEverything else: errors, hints, progress spinners, status lines such as ✓ form submitted, and reasoning streamed by --think
The rules worth scripting against:
  • On failure, stdout stays empty. You never have to filter error text out of captured data.
  • On success, get and describe commands leave stderr empty; run app and resume app may print hints there.
  • Progress spinners appear only in a terminal, on stderr, and are suppressed under -o json, -o yaml, and -o name.
  • Piped output carries no ANSI color codes.
  • If the consumer of a pipe exits early (difyctl get app -o name | head -2), difyctl exits 0 rather than failing on the broken pipe.

Errors

Errors go to stderr. In the default human format, an error is a code: message line plus optional detail lines:
not_logged_in: not logged in
hint: run 'difyctl auth login'
When an HTTP request was involved, request: <METHOD> <url> and http_status: <n> lines follow. When the server’s reply carries Dify’s standard error body, the header line shows the server’s more specific code (not_found, invalid_param) instead of the CLI’s transport-level code. Per-field validation details follow as indented lines, and the server’s hint appears when difyctl has none of its own. Under -o json, the same error becomes a single-line JSON object on stderr:
{"error":{"code":"not_logged_in","message":"not logged in","hint":"run 'difyctl auth login'"}}
Only -o json switches error rendering: -o yaml failures print the human format.
FieldPresentMeaning
codealwaysStable machine-readable error code. Branch on this, never on message text.
messagealwaysHuman-readable description.
hintwhen knownThe fastest fix, often a copy-pasteable command.
http_statuson HTTP failuresStatus code of the failed request.
method, urlon HTTP failuresThe request that failed.
raw_responseonly with -vThe raw server response body, bearer tokens redacted.
serveron HTTP failures, when the reply is Dify’s standard error bodyThe server’s own error: code, message, status, plus optional hint and details.

The top-level code stays the CLI’s stable transport-level code; server.code carries the server’s finer-grained reason.
For what each code means and how to fix it, see Troubleshooting.

Exit Codes

CodeMeaningExamples
0SuccessAlso --help, version, and a workflow run that paused for human input.
1Generic failureNetwork and server errors (network_connection, server_5xx, server_4xx_other), unknown commands, unknown flags, an unreachable OS keychain (keyring_unavailable).
2Usage errorAn invalid flag value (-o table, --limit 0), a missing argument, a non-UUID app or workspace ID, --inputs that isn’t a JSON object.
4Authentication errornot_logged_in, auth_expired, token_expired, access_denied.
6Version or compatibility errorunsupported_endpoint, or an unreadable config file (config_schema_unsupported).
7Rate limitedAn HTTP 429 (rate_limited), kept distinct from 1 so a script can back off and retry.
64Compatibility gate failedOnly version --check-compat: the server was not confirmed compatible.
One nuance for strict scripts: parser-level mistakes (an unknown command, an unknown flag, a flag missing its value) exit 1 with a plain-text message, while an invalid value for a known flag exits 2.

A Paused Workflow Run Exits 0

A Workflow app can pause mid-run to collect human input. The pause is a successful outcome, not a failure: run app and resume app exit 0 and print a paused payload to stdout. To detect a pause in a script or an agent, run with -o json and check stdout for "status": "paused"; don’t branch on the exit code. For the payload shape and the resume protocol, see When a Workflow Pauses on the Apps reference.
Last modified on June 25, 2026