> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devhelm.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Exit Codes

> DevHelm CLI exit codes — success, error categories, and CI-friendly drift detection

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

## Exit code reference

| Code | Name            | When it's used                                                                                                                              |
| ---- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `0`  | Success         | Command completed successfully                                                                                                              |
| `1`  | General error   | Unexpected internal failure (uncaught exception, bug)                                                                                       |
| `2`  | Usage error     | Command-line parse failure from the CLI framework: unknown command, nonexistent flag, missing required argument or flag, invalid enum value |
| `4`  | Validation      | Local precondition failed: missing/invalid token, malformed YAML, request body that doesn't match the schema                                |
| `10` | Changes pending | `plan` / `deploy --dry-run --detailed-exitcode` detected pending changes                                                                    |
| `11` | API error       | API returned a non-2xx response (4xx or 5xx). Carries `status`, `code`, and `requestId` in stderr                                           |
| `12` | Transport       | Network failure before getting a response: DNS, connection refused, TLS, timeout                                                            |
| `13` | Partial failure | `deploy` finished but at least one resource operation failed; the remainder succeeded                                                       |

The mapping is implemented in [`src/lib/errors.ts`](https://github.com/devhelmhq/cli/blob/main/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 failures                  | Retry on `12`; do **not** retry on `2`, `4`, or `11` (deterministic)                                                |
| Surface auth problems to users                    | Look for `4` (no token / bad config) or `11` with `code=UNAUTHORIZED` / `code=FORBIDDEN` in stderr (rejected token) |
| Continue past partial deploy failure              | Treat `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:

```bash theme={null}
devhelm deploy -f devhelm.yml --dry-run --detailed-exitcode
```

| Exit code               | CI behavior                                  |
| ----------------------- | -------------------------------------------- |
| `0`                     | Config is in sync — pass the check           |
| `10`                    | Config has changes — fail or flag for review |
| `2` / `4` / `11` / `12` | Error — fail the check                       |

### Shell scripting

```bash theme={null}
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

```yaml theme={null}
- 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

<CardGroup cols={2}>
  <Card title="Deploy commands" icon="rocket" href="/cli/commands/deploy">
    Full deploy, plan, and validate reference.
  </Card>

  <Card title="GitHub Actions" icon="github" href="/integrations/github-actions">
    CI/CD integration with the setup-devhelm action.
  </Card>
</CardGroup>
