---
name: livehq-deploy
description: Deploy, configure, scale, inspect, and operate local applications with the signed LiveHQ CLI. Use for LiveHQ app deployment, environment variables, resources, domains, managed databases, logs, lifecycle, rollback, or deletion. Not for operating LiveHQ’s own control-plane backend or publishing Mac releases.
metadata:
  version: "0.1.0-beta.3"
  minimum_cli_build: "272"
  xpc_protocol: "12"
---

# LiveHQ CLI

Run this skill through a local coding agent with shell access on the same
Apple Silicon Mac and macOS user account as LiveHQ. A cloud/Linux agent or
browser-only chat cannot reach the signed local runtime. Do not build a proxy
or copy device credentials to work around that boundary.

Use `livehq` as a desired-state application controller. Commands return JSON
by default and wait until the requested state is settled. Use an exact app or
database name when it is unique; otherwise use the stable ID returned by
`livehq list` or `livehq database list`.

Do not call Docker directly, edit LiveHQ databases, manipulate Keychain, or
invent URLs. Return the URL reported by LiveHQ.

Before the first mutation in a session, run:

```bash
livehq version
livehq doctor
livehq capabilities
```

This skill targets CLI build 272 or newer, exact XPC protocol 12, and manifest
version 2. Require doctor to exit 0 with runtime and deployment `ready`, and
use the commands actually advertised by `capabilities`. A skill cannot install
the signed runtime or grant CLI access. If the CLI build differs from the running app, stop and
tell the user to choose **LiveHQ → Settings → Developer Tools → Install CLI**.

The CLI needs the local runtime's Mach service. Some coding-agent sandboxes
block that connection even while LiveHQ is ready. If version works but runtime
access is denied, use the agent's normal approved local-execution mechanism
once before diagnosing a broken installation. Do not disable macOS security,
change runtime permissions, or expose a localhost control endpoint.

Before using billing selection, confirm `livehq capabilities` advertises
`billing status` and `billing selection`. An older installed build may remain
valid for deployment while lacking the newer billing commands.

This file is the complete skill. No reference files, ZIP, extra scripts, or
plugin are required. If `livehq` is not on PATH, use
`"$HOME/.local/bin/livehq"` for the same commands. If that executable is missing,
ask the user to install/enable the CLI in LiveHQ; do not create a replacement
symlink or change shell startup files.

## Deploy

For an ordinary detected project, no `livehq.yaml` is required:

```bash
livehq deploy ./folder
```

Configure the common deployment properties in the same command:

```bash
OPENAI_API_KEY="$OPENAI_API_KEY" livehq deploy ./folder \
  --name my-app \
  --port 3000 \
  --cpu 1 \
  --ram 1024 \
  --env OPENAI_API_KEY \
  --privacy private
```

Rules:

- `--env NAME` is repeatable and reads `NAME` from the command's process
  environment. Never put a secret value in argv.
- LiveHQ never reads `.env` automatically. Never edit or print a `.env` file.
- `--privacy` accepts `private`, `public`, or `password`.
- Public deploys additionally require `--confirm-public`.
- Automated password deploys require `--password-fd N`, an already-open
  writable descriptor numbered 3 or higher going to a user-approved secure
  destination. It is password output, not password input. Never send it to
  stdout/stderr, JSON, chat, or a world-readable file.
- `--database postgres|sqlite` ensures one managed database attachment. It
  creates it on the first deploy and reuses the exact active database and
  attachment on ordinary redeploys of that bound project.
- `--new` deliberately gives a previously bound folder a new app identity; do
  not use it for an ordinary retry or redeploy.
- `--cpu` accepts 0.1–16 cores. `--ram` accepts 128–65536 MiB. Explicit
  `--port` accepts 1024–65535 and overrides image detection, including an
  explicit 3000. Automatic custom-image detection may select internal port 80.
- Command name/port/resources/privacy/database flags override `livehq.yaml`;
  the manifest overrides detected defaults. A `--env` name must not duplicate
  a variable or secret already declared in the manifest. When a manifest is
  present, inspect that non-secret declaration before composing `--env` flags.

Use optional `livehq.yaml` only when the project genuinely needs a custom
start command, custom health check, release/migration command, build-scoped
secret, or unusual database mapping. Do not create it for a normally detected
stateless app.

A successful deploy has `status: succeeded` or `status: no_change` and a
stable app ID at `data.id` plus the canonical URL at `data.url`. Use that ID
for later commands; do not reconstruct a hostname or correlate by guessing.

## Optional advanced configuration

### Choose the production image before deploying

LiveHQ's managed Vite React/Vue image serves static `dist` output. Its final
`/app` contains that output and LiveHQ's static server, not the project's
`package.json`, dependencies, API server, or migrations. Adding an
`app.start.command` or `release.command` does not copy those files into it.

For a combined Vite frontend + Node API + PostgreSQL app, provide an explicit
production `Dockerfile` or `Containerfile` before the first deploy. LiveHQ
selects that image definition instead of managed framework detection. Keep
managed detection for a static Vite app or a supported server framework whose
production image meets the app's needs; not every React app needs a Dockerfile.
PostgreSQL access belongs in the server API, never in browser code or a
`VITE_*` variable. `--database postgres` provisions and attaches a database;
it does not supply an API server, package migration files, or create tables.

Before deploying, inspect the source and final image definition:

- Trace both start and release commands from the final `WORKDIR`. `npm run
  migrate` requires `package.json`, its `migrate` script, the referenced files,
  and their dependencies in that final image. Having them in the source or
  build stage is insufficient. Executable preflight alone cannot prove this.
- Include the built frontend, API server, migrations and required schema
  assets in the final stage. Keep migration dependencies available after
  production pruning; a CLI installed only as a dev dependency will be absent.
- Check `.dockerignore` does not exclude required source or migration files;
  exclude local `node_modules`, credentials, and `.env` files from the context.
- Match the server's listen port, manifest health route, and production start
  command. The server must listen on `0.0.0.0` and serve the built frontend.

These are source checks, not a requirement to run local tests or previews.
Respect a user's instruction to skip those; LiveHQ performs the deployment
build. Do not invoke Docker directly for this check.

### Manifest settings

Use a V2 manifest for settings not supplied by the ordinary deploy flags.
Include only the sections the project needs. The following example assumes
the final image contains `package.json` with working `start` and `migrate`
scripts and all their runtime files and dependencies:

```yaml
version: 2
app:
  name: my-app
  port: 3000
  start:
    command: ["npm", "run", "start"]
  health:
    path: /healthz
    initial_delay: 5s
    interval: 2s
    timeout: 2s
    failure_threshold: 30
    success_status: "200-399"
  privacy:
    mode: private
secrets:
  API_KEY:
    from: env
    scope: runtime
release:
  strategy: command
  command: ["npm", "run", "migrate"]
  timeout: 10m
```

Remove the release section if no schema command is required. A database
manifest must explicitly choose `release.strategy: none` or a bounded command
and a dedicated non-root health route. For a custom PostgreSQL mapping:

```yaml
database:
  name: app-data
  engine: postgres
  version: "17"
  variable: DATABASE_URL
  access: owner
```

SQLite uses `engine: sqlite`, omits `version`, and normally maps `DATABASE_PATH`.
Database type and schema work come from explicit user intent/configuration;
never select a migration merely because ORM dependencies or migration files
exist. Release work must be present in the production image, noninteractive,
idempotent, and safe for at-most-once execution. Its timeout is 1 second through
1 hour, default 10 minutes. Health timeout cannot exceed its interval.

Keep database access out of builds, imports executed during builds, and
prerendering. A health endpoint must not require tables before release work
creates them. Runtime secrets stay out of image layers and build metadata.
Manifest secrets accept `from: env` or `stdin`; scope defaults to `runtime` and
can be `build` or `both` only when required. At most one manifest secret can
read stdin in a deploy. Build-scoped values require at least eight bytes.

For managed Node/Python/Rust projects, retain lockfiles or exact dependency
pins and verify the intended production entrypoint. Servers must listen on
`0.0.0.0` at the effective app port. Standard Dockerfile/Containerfile projects
retain their image-defined start/user/filesystem contract; LiveHQ still owns
runtime isolation. Do not invoke Docker to bypass a rejected LiveHQ operation.

## GUI and CLI interoperability

An app's creation surface never limits its operational controls. `list`,
`show`, `logs`, `start`, `stop`, `rollback`, `env`, `scale`, `domain`, database
attachment, and deletion commands work for apps created by either the GUI or
CLI when the caller uses the exact app name or stable ID.

A CLI-created app is shown as **CLI managed** in the GUI. On its first GUI code
redeploy, choose the same project folder once; LiveHQ redeploys the existing app
identity and remembers that folder for later one-click GUI redeploys. This does
not remove or replace the CLI project binding, so later `livehq deploy` calls
from that project still target the same app.

After a GUI redeploy, run the ordinary `livehq deploy` command from the bound
project. LiveHQ creates one fresh CLI generation only when the effective deploy
intent differs; repeating an identical settled command returns `no_change`.
Never unlink or create a replacement app merely because the latest release was
created in the other surface.

Do not interpret the one-time GUI folder choice as missing deployed source or a
failed app. The active immutable release remains available and operational.

## Inspect and operate apps

```bash
livehq list
livehq show APP
livehq logs APP
livehq logs APP --tail 500 --since 15m
livehq logs APP --follow --stream-json
livehq start APP
livehq stop APP
livehq rollback APP
```

`livehq list` returns one current row per app with its stable ID, state, URL,
CPU, and RAM. `rollback` selects only the immediately previous compatible
release. It waits for the exact local activation, authoritative route link,
and signed gateway attestation before returning success; older history is not
an arbitrary deployment target. A locally committed rollback whose public
route needs recovery directs you to `livehq start APP`; do not repeat rollback
unless its structured error explicitly permits that exact retry.

Log follow requires `--stream-json`. It uses bounded polling against the
selected provider and is not a lossless stream or an automatic follow across
redeployment. Use a bounded duration when following logs for diagnostics.

## Environment variables

Supply required values on the deploy that creates or updates the app:

```bash
API_KEY="$API_KEY" livehq deploy ./folder --env API_KEY
```

Inspect the active non-secret metadata afterward:

```bash
livehq env list APP
```

LiveHQ reports names, scopes, and opaque versions, never stored values.

```bash
API_KEY="$API_KEY" livehq env set APP API_KEY
livehq env unset APP API_KEY
```

## Scale resources

```bash
livehq scale APP --cpu 2 --ram 2048
```

At least one resource is required. LiveHQ waits for the replacement and route
to settle before returning success.

During a payment-recovery grace period, existing app redeploys and environment
repairs remain available, but LiveHQ rejects new resources and resource
increases. Do not bypass that boundary by creating a replacement app.

## Billing and Free-plan selection

```bash
livehq billing status
livehq billing selection
livehq billing selection --app APP --database DATABASE
livehq billing selection --automatic
livehq billing invoices
livehq billing open
```

`billing selection` reports every candidate, the selection version, dependency
relationships, and which resources are billing-suspended. Select resources by
stable ID or one exact unambiguous name. Repeat `--app` and `--database` up to
the reported Free-plan limits. Omitted resource types preserve their current
selection. The backend rejects a stale concurrent edit; refresh the selection
and ask the user to confirm any materially different replacement.

Never choose resources randomly. Automatic selection is deterministic and
keeps the oldest compatible apps while reserving their required databases
first. A billing-suspended resource is preserved, not failed or deleted. Do
not retry Start, redeploy, scale-up, database Start, attachment, credential, or
temporary-connection mutations until the resource is selected or Pro is
restored. Stop, deletion, inspection, logs, and data-preservation work remain
valid where the command supports them.

When the workspace has exhausted its Free bandwidth allowance, all public
routes return the typed bandwidth-limit response until the UTC calendar-month
reset or a confirmed Pro restoration. Local apps and database data remain
intact. Do not create a replacement app or hostname to bypass the workspace
limit.

## Domains

```bash
livehq domain list APP
livehq domain add APP app.example.com
livehq domain check APP app.example.com
livehq domain remove APP app.example.com
```

After `domain add`, return the exact DNS type, name, and value from the result.
Do not infer provider settings. Domain creation does not mean DNS/TLS is live;
after the user sets DNS, run `domain check` once. If it remains pending, report
the current state and let the user request another check. Do not poll without a
bounded user request. A private/password app keeps the same access policy on
its custom hostname.

## Managed databases

```bash
livehq database list
livehq database show app-data
livehq database create app-data --type postgres
livehq database create app-data --type sqlite
livehq database attach app-data APP
livehq database attach app-data APP --env DATABASE_URL
livehq database detach app-data APP
livehq database start app-data
livehq database stop app-data
livehq database delete app-data --yes
```

Database type is always explicit. Do not infer PostgreSQL or SQLite from the
framework or dependencies. PostgreSQL defaults to `DATABASE_URL`; SQLite
defaults to `DATABASE_PATH`. Database deletion refuses while attachments
remain.

Keep `--database TYPE` on every redeploy of a project that was originally
deployed with its managed database; omitting it produces a database-free plan
and can make a migration/release task fail. When the user wants to connect a
different existing database, run `database list` and attach its exact ID
instead of asking deploy to create another resource.

## Delete an app

```bash
livehq delete APP --yes
```

Deletion removes every route, detaches every database while preserving its
data, retires the exact runtime app, and reconciles the gateway. Never delete
without explicit user intent for the exact app. A retry uses the same durable
intent and must not recreate resources.

## Machine-readable results

Results use `livehq.cli.result.v2`; supported progress uses
`livehq.cli.event.v2`. Ordinary output is JSON; `--output text` is for people.
Use `--stream-json` for a supported stream, including log follow.

| Exit | Meaning |
| ---: | --- |
| 0 | Success or complete no-change |
| 2 | Invalid input |
| 3 | Setup or authorization required |
| 4 | Missing or ambiguous selector |
| 5 | Conflict, entitlement, or forbidden operation |
| 6 | Terminal failure |
| 7 | Partial/retryable convergence; read the error action before retrying |

The current public CLI has no `app`, `db`, `inspect`, `plan`, `link`, `unlink`,
`operation`, standalone-task, backup, People/Teams, or GitHub-administration
commands. Do not infer public commands from older examples or internal helpers.

## Failure handling

- Treat `succeeded` and complete `no_change` as success.
- A returned `status: failed` result is terminal, including exit 6. Do not
  say it is still processing or wait for a URL. Poll the same shell process
  only while the execution tool reports that process is still running;
  progress events are not a final result.
- If the result says setup is required, stop and relay the exact LiveHQ action.
- If a required environment value is missing, ask the user to export it in
  their terminal or provide it through an approved secret/stdin mechanism.
  Never ask them to paste the value into chat.
- Check `error.retryable` and its action; exit 7 alone does not authorize a
  retry. If the exact mutation is retryable, repeat it once. The same
  durable intent resumes; do not add force flags or create replacement
  resources.
- For `error.action.kind: edit_project`, inspect the release-task exit code
  and redacted stderr, repair the identified source/image/configuration issue,
  then deploy the same bound folder with the same app name, database and
  privacy options. `retryable: false` forbids blindly repeating the failed
  intent; it does not forbid deploying corrected source. Preserve the project
  binding and returned app/database/attachment IDs: provisioning may have
  succeeded even when the app is `unpublished` with a null URL. Do not use
  `--new`, delete the database, or provision a replacement to recover.
- For example, release stderr `ENOENT /app/package.json` from `npm run migrate`
  means the final image lacks the package at the command's working directory.
  Check the Vite static-image distinction above and correct the final image
  layout. A secondary npm log-directory warning is not the cause of that
  missing package. Do not fix it by changing database credentials or disabling
  the migration. A failed release is not evidence that the schema completed.
- There is no public `--force` rerun flag. Do not rerun release/migration work
  outside its journaled operation or claim success until the corrected deploy
  returns `succeeded` or complete `no_change` with its canonical URL.
- Stop after the same failure repeats. Return the redacted JSON error and
  retain operation/app/database identities for recovery.
- Never expose secrets, connection credentials, one-time browser URLs, or
  generated passwords in logs or responses.
