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

# CLI

> Drive Hyze Cloud from the terminal. Deploy, follow the build, read the logs and configure access.

The official Hyze Cloud CLI is called `hyze`. It covers the deploy loop end to end: log in, list apps, deploy, follow the build, read the logs and check what is live, without leaving the terminal.

<CardGroup cols={2}>
  <Card title="Install" icon="download" href="#install">
    Node 18+ or Bun, one command.
  </Card>

  <Card title="Quickstart" icon="rocket" href="#quickstart">
    From login to a live app.
  </Card>
</CardGroup>

## Install

```bash theme={"system"}
npm install -g @hyze-cloud/cli
# or
bun add -g @hyze-cloud/cli

hyze --version
```

Runs on **Node 18+** and **Bun**.

## Quickstart

<Steps>
  <Step title="Store your API key">
    Create a key in the [dashboard](http://hyzecloud.com/dashboard) under **Settings → Developer**, then store it with `hyze login`. The CLI checks the key against the API before saving it.

    ```bash theme={"system"}
    hyze login
    ```
  </Step>

  <Step title="See what the workspace holds">
    ```bash theme={"system"}
    hyze projects
    ```
  </Step>

  <Step title="Deploy">
    ```bash theme={"system"}
    hyze deploy . --name my-api --runtime bun --port 3000 --subdomain my-api.hyzecloud.app
    ```

    Inside a project folder, `hyze deploy .` uses the app already bound to that folder (see [`.hyzerc.json`](#configuration-files)).
  </Step>

  <Step title="Check what is live">
    ```bash theme={"system"}
    hyze status my-api
    hyze logs my-api --follow
    ```
  </Step>
</Steps>

## Commands

| Command                                   | What it does                                         |
| ----------------------------------------- | ---------------------------------------------------- |
| `hyze login`                              | stores an API key, after checking it against the API |
| `hyze logout`                             | removes the stored key of the active profile         |
| `hyze projects`                           | lists the workspace's apps                           |
| `hyze deploy [path]`                      | zips, uploads and follows the build                  |
| `hyze deployments [appId] [deploymentId]` | build history, or one build with its stage timeline  |
| `hyze logs [appId] [deploymentId]`        | the app's output, or the build log of that attempt   |
| `hyze status [appId]`                     | the app's current state                              |

`appId` is optional wherever an app is the subject: the [`.hyzerc.json`](#configuration-files) binds an app to the folder, so inside a project `hyze status`, `hyze logs` and `hyze deploy .` need no arguments.

## Interactive screen

Running `hyze` with no arguments opens a screen in the terminal instead of printing help (`hyze --help` still prints help). It reads the same API through the same commands:

```
Projects                                                       4 projects

> ● Running    shop-api                shop-api.hyzecloud.app
  ○ Stopped    docs                    docs.hyzecloud.app
  ◐ Deploying  worker                  worker.hyzecloud.app
  ✕ Error      billing                 billing.hyzecloud.app

↑↓ Navigate · Enter Open · / Search · ? Help · q Quit
```

`Enter` opens the highlighted app, with its state, its URL, the hostnames it answers on and the variables it runs with:

```
Projects › shop-api

● Running

URL           https://shop-api.hyzecloud.app
Last deploy   Success · 3h ago

Domains
  shop.example.com  Active · certificate active
CNAME         apps.hyzecloud.app

Environment
  API_KEY       hyze_abcd…wxyz
  DATABASE_URL  postgre…hop

d Deploy · r Restart · s Stop · b Builds · o Open in the browser · l Logs
e Set a variable · a Add a domain · v Show the values · Esc Back · ? Help · q Quit
```

Variables are masked, recognisable but not usable. `v` shows the values in full and hides them again. `e` sets a variable spelled `KEY=value`, the same spelling `-e` uses everywhere else, and asks before writing because the app restarts to apply it.

`s` is the verb that changes something: `Stop` while the app is up, `Start` when it is not. Stopping takes the app off the air, so it asks first and nothing goes out until you answer. `r` restarts, `o` opens it in the browser, `l` shows the logs and `a` adds a hostname, telling you where to point DNS.

## Authentication and configuration

`hyze login` verifies the key against the API before storing it. In a terminal the input is masked per keystroke, so a paste is visible without exposing the secret. Piped stdin and `--key <hyze_...>` skip the prompt entirely, which is how CI feeds it:

```bash theme={"system"}
printf '%s' "$HYZE_API_KEY" | hyze login --no-verify
```

### Configuration files

| Location                          | Purpose                                                       |
| --------------------------------- | ------------------------------------------------------------- |
| `~/.config/hyze/config.json`      | profiles, active profile and default output (mode `0600`)     |
| `.hyzerc.json` (nearest ancestor) | per-app defaults: `appId`, `apiUrl`, `workspaceId`, `profile` |

```json theme={"system"}
// .hyzerc.json
{ "appId": "app_abc123", "workspaceId": "org_abc", "apiUrl": "https://api.hyzecloud.com/api" }
```

Precedence, highest first: **flag → environment variable → `.hyzerc.json` → active profile → default**. An empty variable counts as absent, so `HYZE_API_KEY=""` does not shadow the profile.

### Environment variables

| Variable                              | Effect                                     |
| ------------------------------------- | ------------------------------------------ |
| `HYZE_API_KEY`                        | API key                                    |
| `HYZE_API_URL` or `HYZE_API_BASE_URL` | API base. A bare host gets `/api` appended |
| `HYZE_WORKSPACE_ID`                   | workspace to scope requests to             |
| `HYZE_PROFILE`                        | profile name                               |
| `HYZE_OUTPUT`                         | `table`, `json`, `ndjson` or `text`        |
| `HYZE_CONFIG` or `HYZE_CONFIG_DIR`    | config file or config directory            |
| `NO_COLOR`                            | disable colors                             |

## Global options

```
--profile <name>      config profile to use
--api-key <key>       API key (overrides env and the stored profile)
--api-url <url>       API base URL
--workspace <id>      workspace to scope requests to
--config <path>       config file path
--timeout <seconds>   per-request timeout (default 60)
-o, --output <format> table | json | ndjson | text
--json                shorthand for -o json (the API response, untouched)
--no-color            disable colors
-q, --quiet           suppress informational output
--verbose             log every HTTP request and extra detail
```

## Use it in scripts

`table` is the default when stdout is a terminal, `json` otherwise. Piping always yields JSON without asking.

<Callout>
  Payloads go to **stdout**; progress and messages go to **stderr**. That is why `hyze deployments app_1 --json | jq '.deployments[0].status'` is safe.
</Callout>

`--json` prints the API response untouched, so there is no re-shaped "CLI format" to keep in sync:

| Command                    | Payload                                                                   |
| -------------------------- | ------------------------------------------------------------------------- |
| `projects`                 | `{ success, apps, meta }`                                                 |
| `deployments <appId>`      | `{ success, deployments, currentDeploymentId, activeDeploymentId, meta }` |
| `deployments <appId> <id>` | `{ success, deployment, timeline }`                                       |
| `logs <appId>`             | `{ success, logs }`                                                       |
| `deploy`                   | the settled build. With `--no-wait`, the upload response                  |
| `status <appId>`           | the state the CLI resolved, always the same shape                         |

`status` is the one command that resolves instead of forwarding. The API cannot always see the container, and a made-up `stopped` would read as "the app is down".

## Deploy

The flags you reach for most: `--name`, `--app <appId>` to redeploy, `--runtime node|bun|python`, `--memory <mb>`, `--port` and `--subdomain` (together), `--env KEY=VALUE` (repeatable), `--env-file`, `--start-command`, `--install-command`, `--build-command`, `--machine`, `--exclude` and `--include`, `--no-wait`, and `--repo <owner/name> [--branch] [--auto-deploy]` for GitHub.

Without `--runtime`, the CLI asks the API to inspect the upload and uses the detected runtime.

While it waits, the CLI draws the progress in place, from facts the API sent: the build's own clock, every stage with the duration the platform stamped and the phase the worker wrote for that build. A fact the API did not send is a line that is not drawn. **There is no percentage**, because the contract has none.

```
shop-api · building · 14s
  ✔ queue    4s
  ✔ install  5s
  ● build    4s
  worker · building · updated 2s ago
```

<Callout>
  The wait belongs to a terminal: in a pipe it writes nothing, no `\r`, no ANSI, no spinner. `--json` and `-o json` keep the exact payload.
</Callout>

### What gets uploaded

In this order: `--include` and `--exclude` patterns, then `.hyzeignore` (gitignore style: `*`, `**`, `dir/`, `!keep`), then `git ls-files --cached --others --exclude-standard` inside a work tree and, outside one, a walk with built-in ignores. `.git` and `node_modules` are never uploaded.

<Tip>
  The upload limit is not a constant baked into the CLI: before zipping, it reads the platform's own limit and refuses an oversized archive by naming that number.
</Tip>

## Logs

`hyze logs <appId>` prints the app's output (`--tail 1-1000`, `--timestamps`). `hyze logs <appId> <deploymentId>` prints the install and build log the API persisted for that attempt.

With `--follow`, the CLI prints only what is new. For a build it stops when the build settles; for a container it runs until you interrupt it.

```bash theme={"system"}
hyze logs my-api --follow -o text
```

## Errors and exit codes

Every failure is one line plus the fix, on stderr, with no stack trace. Add `--verbose` when you want the stack trace.

```
$ hyze projects
✖ UNAUTHORIZED · Unauthorized
  The key is missing, expired or revoked. Run `hyze login` to store a new one (Settings → Developer).
```

| Code | Meaning                                              |
| ---- | ---------------------------------------------------- |
| 0    | success                                              |
| 1    | operation failed, including a failed deployment      |
| 2    | usage error: bad flags, missing key, no app selected |
| 3    | unauthenticated or forbidden, including plan limits  |
| 4    | not found                                            |
| 5    | rate limited, including the workspace build slot     |
| 6    | validation error                                     |
| 7    | server error                                         |
| 8    | network error or timeout                             |
| 130  | interrupted with Ctrl-C                              |

### The `unknown` state

`hyze status` prints what the platform reports: `running`, `stopped`, `paused`, `restarting`, `deploying`, `error`, `exited` or `created`. When the platform cannot see the app at all, it prints `unknown`.

<Callout>
  `unknown` exits `0`: the question was answered, and the answer is that the platform does not know. A read that fails, on auth, server or network, keeps its mapped exit code instead.
</Callout>

## Next steps

<CardGroup cols={2}>
  <Card title="Deploy an app" icon="rocket" href="/en/guides/deploy-an-app">
    The same deploy through the API, for comparison.
  </Card>

  <Card title="API keys" icon="key" href="/en/guides/api-keys">
    How keys work and how to protect them.
  </Card>

  <Card title="View logs" icon="file-lines" href="/en/guides/view-logs">
    Where to find your app's output.
  </Card>

  <Card title="Official SDKs" icon="code" href="/en/sdks/overview">
    TypeScript and Python, to call the API from your code.
  </Card>
</CardGroup>
