Skip to main content
The CLI uses specific exit codes so you can branch on outcome in scripts and CI pipelines without parsing stdout.

Exit code reference

CodeNameWhen it’s used
0SuccessCommand completed successfully
1General errorUnexpected internal failure (uncaught exception, bug)
2Usage errorCommand-line parse failure from the CLI framework: unknown command, nonexistent flag, missing required argument or flag, invalid enum value
4ValidationLocal precondition failed: missing/invalid token, malformed YAML, request body that doesn’t match the schema
10Changes pendingplan / deploy --dry-run --detailed-exitcode detected pending changes
11API errorAPI returned a non-2xx response (4xx or 5xx). Carries status, code, and requestId in stderr
12TransportNetwork failure before getting a response: DNS, connection refused, TLS, timeout
13Partial failuredeploy finished but at least one resource operation failed; the remainder succeeded
The mapping is implemented in src/lib/errors.ts (EXIT_CODES). Sub-classes (e.g. DevhelmAuthError, DevhelmNotFoundError) inherit their root’s exit code. Exit 2 comes from the oclif framework before the command runs, so it is not part of EXIT_CODES.

Quick decision table

You want to…Check
Detect any failure$? -ne 0
Distinguish “config drift” from real errors in CI$? -eq 10 for drift, $? -eq 0 for clean, anything else for failure
Retry only on transient failuresRetry on 12; do not retry on 2, 4, or 11 (deterministic)
Surface auth problems to usersLook for 4 (no token / bad config) or 11 with code=UNAUTHORIZED / code=FORBIDDEN in stderr (rejected token)
Continue past partial deploy failureTreat 13 as “completed with errors” and inspect the deploy report

Usage in CI

Gate merges on config drift

Use --detailed-exitcode with deploy --dry-run to detect config changes in a PR check:
devhelm deploy -f devhelm.yml --dry-run --detailed-exitcode
Exit codeCI behavior
0Config is in sync — pass the check
10Config has changes — fail or flag for review
2 / 4 / 11 / 12Error — fail the check

Shell scripting

devhelm monitors list -o json > monitors.json
case $? in
  0) echo "OK" ;;
  4) echo "Config error — fix and retry"; exit 1 ;;
  11) echo "API error — see request id in stderr"; exit 1 ;;
  12) echo "Network error — will retry"; sleep 5; exec "$0" "$@" ;;
  *) echo "Failed"; exit 1 ;;
esac

GitHub Actions

- name: Check for drift
  run: devhelm deploy -f devhelm.yml --dry-run --detailed-exitcode
  continue-on-error: true
  id: drift

- name: Comment on PR
  if: steps.drift.outcome == 'failure'
  run: echo "Monitoring config has pending changes"

Next steps

Deploy commands

Full deploy, plan, and validate reference.

GitHub Actions

CI/CD integration with the setup-devhelm action.