# Output and exit codes

> Read Nodaro CLI output as tables or JSON, follow runs to the end with --watch, and branch on the exit codes for failed, cancelled and held runs in scripts.

Source: https://nodaro.ai/docs/developers/cli/output

The **output** of the Nodaro CLI is readable in a terminal by default and machine-readable with `--json`. With `--watch`, a run command waits until the run ends and reports the outcome in its exit code, so a shell script or a CI job can branch on it.

## Tables and JSON

Without `--json`, a `list` command prints a small ASCII table and a `get` command prints a formatted JSON block. Every read command accepts `--json` and then prints the full payload, ready for `jq`:

```bash
nodaro projects list --json | jq '.[].id'
nodaro workflows run wf_abc --json
```

## Follow a run with --watch

A run command returns as soon as Nodaro accepts the run. Add `--watch` to keep polling until the run ends:

```bash
nodaro workflows run wf_abc --watch
nodaro nodes run generate-image --param prompt="a snow leopard" --watch --poll-interval 1000
```

`--watch` works on the run commands, such as `workflows run`, `apps run` and `nodes run`, on `executions get`, and on the generation commands of the [asset](https://nodaro.ai/docs/developers/cli/asset-commands) and [media](https://nodaro.ai/docs/developers/cli/media-commands) groups. `--poll-interval` sets the time between two polls, in milliseconds.

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success. |
| `1` | Not authorized, not found, an argument error or a network error. |
| `2` | `--watch` ended and the execution failed. |
| `3` | `--watch` stopped because the job is held for review (`pending_review`). A person is deciding; it is not a failure. |
| `130` | `--watch` ended and the execution was cancelled. |

With `--json`, the CLI prints the payload and returns without setting the codes `2`, `3` and `130`. In that mode, branch on the `status` field of the output:

```bash
status=$(nodaro workflows run wf_abc --watch --json | jq -r '.status')
```

When the token is missing, expired or invalid, the CLI says so, suggests `nodaro auth login` and exits with code `1`. For other API errors, it prints the message and the error code. The codes are listed in [Errors](https://nodaro.ai/docs/developers/api/errors).

## When a job is held for review

Some deployments review generations before they release them. On such a deployment, a job can enter the `pending_review` status. The work is done, the credits stay reserved, and a person decides whether to release the result.

The status does not change on its own, so `--watch` stops polling. It prints `awaiting review (a human decision is pending; not a failure)` and exits with code `3`.

- **Do not run the request again.** A duplicate would be held too.
- **Check back later** with `nodaro jobs get <id>`. The job ends in one of three states:

| Status | Meaning |
| --- | --- |
| `completed` | The result was approved and released. |
| `failed` | The result was rejected. `error_hint.kind` is `policy-block`, and `error_hint.reason` is the text to show your user. |
| `cancelled` | The job was cancelled. |

```bash
nodaro nodes run generate-image --param prompt="..." --watch
case $? in
  0) echo "released" ;;
  3) echo "awaiting review, check back later" ;;
  *) echo "failed" ;;
esac
```

## Frequently asked questions

### How do I get machine-readable output from the Nodaro CLI?

Add --json to a read command. Without it, list commands print a small table and get commands print a formatted JSON block.

### What does exit code 3 mean in the Nodaro CLI?

The job is held for review. The work is done and the credits stay reserved while a person decides whether to release the result. It is not a failure, so do not run the request again. Check back later with nodaro jobs get.

### Why does my script not see exit code 2 when a run fails?

With --json, the CLI prints the result and returns without setting the exit codes 2, 3 or 130. Read the status field of the JSON output instead.

### How do I make a CI job wait for a Nodaro run?

Add --watch to the run command. The CLI polls until the run ends and exits with 0 on success, 2 on failure and 130 on cancellation, so the next step can depend on it.
