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

# Scripting and CI

> JSON output, exit codes, and non-interactive behavior of the helix CLI, and what to use from CI

Reference

What scripts and CI jobs can rely on: output streams, each command's `--json` payload, exit codes,
and what an unattended job can reach in Helix Cloud.

```bash theme={"languages":{"custom":["languages/helixql.json"]}}
export HELIX_NO_UPDATE_CHECK=1
helix start dev --json
helix query dev --file examples/request.json --json > result.json
helix doctor dev --json > doctor.json
helix stop dev --json
```

## Output

* stdout carries only the result; stderr carries progress, warnings, hints, and errors.
* `--json` prints one compact JSON value and a newline on stdout, nothing else. It never prompts,
  skips the startup update checks, and conflicts with `--quiet` and `--verbose`.
* Without a terminal on stdin or stderr, or with `--json`, commands never prompt: they use a default
  (`dev`, or the only candidate) or fail and list the candidates.
* Destructive commands (`delete`, `prune --all`, `project delete`, `database delete`,
  `database key revoke`, `service-credential revoke`) that cannot prompt fail before acting unless
  you pass `-y`/`--yes`. `prune <instance>` never asks.
* Output that is not a terminal is never colored; `NO_COLOR=1` drops colors in a terminal.
* Set `HELIX_NO_UPDATE_CHECK=1` so the first command of the day does not wait up to 10 seconds on
  GitHub. See [Environment variables](https://docs.helix-db.com/cli/configuration.md#environment-variables).

## Exit codes

| Code | Meaning |
| - | - |
| `0` | Success, including `--help` and `--version`. |
| `1` | The command ran and failed. |
| `2` | Invalid arguments: an unknown command or flag, a missing value, or conflicting flags. |

The codes are the same with and without `--json`. Exceptions:

* `helix doctor` prints its whole report, then exits `1` if any check fails; warnings alone exit `0`.
* `helix shell` prints a failed request's error, keeps reading, and exits `0` at end of input. Use
  one `helix query` per request when each result must set the exit code.
* `helix stop` exits `0` when the instance was not running, and `helix prune <instance>` when there
  was nothing to remove.

With `--json`, an error is one JSON object on stderr; without it, the same error prints as text.
Only `message` is always present. `candidates` lists what you can pass when the CLI could not choose:

```json theme={"languages":{"custom":["languages/helixql.json"]}}
{"error":{"message":"no default query target","hint":"pass an instance name, or cluster:<id> / tenant:<id>","candidates":[{"id":"preview","name":"preview"},{"id":"production","name":"production"}]}}
```

The other fields are `context` and `caused_by`.

## JSON results

| Command | stdout with `--json` |
| - | - |
| `helix` | `{"version":"<cli version>"}` |
| `init` | `{"project":"<name>","config":"<path to helix.toml>"}` |
| `add local` | `{"instance":"<name>"}` |
| `add cloud` | `{"instance":"<name>","database":"tenant:<id>"}`, or `cluster:<id>` for a dedicated cluster |
| `delete` | `{"deleted":"<instance>"}` |
| `start` | `{"instance":"dev","url":"http://localhost:6969","container":"<container>"}` |
| `stop` | `instance`, `wasRunning`, `explorerStopped`, and `explorerError` when the Explorer could not be removed |
| `restart` | `{"instance":"<name>"}` |
| `status` | `project`, `root`, and `instances`; see [`helix status`](https://docs.helix-db.com/cli/command-reference/status) |
| `doctor` | `target`, `uptime_secs`, `checks`, and `summary`; see [`helix doctor`](https://docs.helix-db.com/cli/command-reference/doctor) |
| `query`, `cypher` | The server's response body. Nothing for an empty body. |
| `shell` | One response per line. |
| `logs` (Cloud) | An array of `{"timestamp","queryName","output"}` objects |
| `explorer` | See [`helix explorer`](https://docs.helix-db.com/cli/command-reference/explorer) |
| `prune` | `{"pruned":[{"instance":"dev","removed":true}]}` |
| `auth status` | `{"email":"<email>","workspaces":[{"id":"<id>","name":"<name>"}]}` |
| `auth logout` | `{"loggedOut":true}` |
| `workspace`, `project`, `cluster`, `database`, `service-credential` `list`; `cluster indexes`; `database indexes`; `database key list` | A JSON array of the Helix Cloud API's objects |
| `get` subcommands, `project create`, `service-credential update` | The Helix Cloud API's object |
| `project link` | `{"project":{...},"config":"<path to helix.toml>"}` |
| `database create`, `database key create`, `service-credential create` | The Helix Cloud API's create response, including the one-time `token` |
| `project delete`, `database delete` | `{"deleted":{"kind":"project","id":"<id>"}}`, with `kind` `tenant` for a database |
| `database key revoke`, `service-credential revoke` | `{"revoked":{"kind":"key","id":"<id>"}}`, with `kind` `service-credential` for a credential |
| `api` | The Helix Cloud API's response |
| `metrics full`, `basic`, `off` | `{"level":"<level>"}` |
| `metrics status` | `{"level":"basic","userId":null,"lastUpdated":<unix seconds>}` |
| `skills update` | `{"updated":true}` |
| `update` | `{"version":"<version>","updated":true}`, or `"updated":false` when already on that version |

Cloud results are the API's JSON field for field. Only `database list` and `database get` add
`"kind"` (`"dedicated"` or `"tenant"`); owners the human view resolves, such as a project's
workspace, are not added. Cloud lists follow pagination up to 50 pages of 200 items, then fail with
`more than 50 pages; narrow the request`.

These commands have no JSON result:

| Command | With `--json` |
| - | - |
| `auth login` | Fails: `logging in needs an interactive terminal`. |
| `chef` | Fails: it hands the terminal to a coding agent. |
| `start --foreground` | Fails: it streams container logs. |
| `logs` for a local instance | Fails: `local logs are plain text`. |
| `skills install`, `skills list` | Fail: they hand the terminal to the `skills` CLI. |
| `metrics full` | Reads the email from piped stdin; fails when stdin is a terminal. |
| `feedback` | Opens the browser and prints nothing on stdout. |

## Run in CI

### Local instances

Local commands need only Docker or Podman, no login, so they run in CI as on your machine. Give each
job its own CLI state with `HELIX_HOME="$(mktemp -d)"`. In-memory data does not survive a restart;
use `--disk` or S3 storage when it must.

### Helix Cloud

The CLI has no unattended login: `helix auth login` needs an interactive terminal, and neither a
service credential nor an application key can log the CLI in. Run Cloud commands such as
`helix query production`, `helix database`, and `helix api` on a developer machine, and do not copy
your session file into CI. From an unattended job, use:

| Need | Use |
| - | - |
| Read or write a database from your code or a job | An [application key](https://docs.helix-db.com/cli/command-reference/database.md) sent to the database's gateway: `POST /v2/query` with `Authorization: Bearer <key>`. A tenant on a shared gateway also needs `X-Helix-Database-Id: <tenant-id>`. See [HTTP API authentication](https://docs.helix-db.com/database/helix-db/query-guides/http-api.md#authentication). |
| Let an agent query or administer databases | A [service credential](https://docs.helix-db.com/cli/command-reference/service-credential.md) as the bearer token of the MCP endpoint `https://mcp.helix-db.com/mcp`. See [First query through MCP](https://docs.helix-db.com/database/helix-cloud/connect/mcp.md#first-query-through-mcp). |

```bash theme={"languages":{"custom":["languages/helixql.json"]}}
curl -sS "https://<gateway-host>/v2/query" \
  -H "Authorization: Bearer $HELIX_API_KEY" \
  -H "X-Helix-Database-Id: <tenant-id>" \
  -H "Content-Type: application/json" \
  --data @examples/request.json
```

`helix database get <database> --json` prints the gateway host as `connectionEndpoint`; the
dashboard's database page shows it too. Create the key once with
`helix database key create --access read-only` and store it as a CI secret.

A service credential:

* can use only the MCP query and administration tools its project grants allow;
* cannot list workspaces, projects, or databases, so give it a `tenant:<id>` or `cluster:<id>` target;
* cannot call the Helix Cloud API the CLI uses, so it cannot run `helix api`, a Cloud `helix query`,
  or other Cloud commands;
* cannot create, change, or revoke service credentials.

## Related

* [Targets and resolution](https://docs.helix-db.com/cli/command-reference.md#targets-and-resolution): how commands pick instances and Cloud resources.
* [CLI configuration](https://docs.helix-db.com/cli/configuration.md): `helix.toml`, state files, and environment variables.
* [CLI troubleshooting](https://docs.helix-db.com/cli/troubleshooting.md): the CLI's error messages and fixes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.