# Command reference

Every command is called as `pyvolt <command>`. `DOMAIN` is the app's domain
(e.g. `myapp.on.pyvolt.com`) or any fragment of it that matches exactly one
app, so `pyvolt deploy myapp` works fine - domains are unique across the
platform, so a domain always identifies exactly one app on exactly one
server.

**Scripts and AI tools.** Add the global `--json` flag *before* the command
(`pyvolt --json apps`, `pyvolt --json status myapp`) to get raw JSON instead of a
table - a stable, parseable contract for scripts, CI and LLM coding assistants.
For headless auth, set `PYVOLT_TOKEN` (and `PYVOLT_API_URL` if self-hosting)
instead of running `pyvolt login`.

## Create an app

| Command | Arguments | Description |
|---|---|---|
| `apps create` | `--server NAME --domain DOMAIN --repo OWNER/REPO [options]` | Creates an app on one of your servers - the headless twin of the dashboard's Add app form. Autodiscovery reads the repo and prefills the framework, serve and release commands; every flag overrides what it found. Exits non-zero if scaffolding on the server fails, and warns if the deploy key could not be pushed. Follow up with `pyvolt deploy DOMAIN --follow`. |

`--domain` does double duty: a bare word like `myapp` becomes the Pyvolt
subdomain `myapp.preview.pyvolt.com`; anything containing a dot is treated as
a full custom domain. Use `--repo OWNER/REPO` for a repository your GitHub
connection can access (this is what enables autodiscovery and the automatic
deploy key), or `--repo-url` with a raw git URL for anything outside it.

Options: `--branch` (default `main`), `--path` for the project directory in a
monorepo, `--env KEY=VALUE` (repeatable) for create-time variables, and
`--serve-command` / `--release-command` / `--build-command` / `--python` to
override detection. `--dry-run` prints the resolved plan - domain, repo,
detected framework and commands - without creating anything.

## Deployments

| Command | Arguments | Description |
|---|---|---|
| `deploy` | `DOMAIN [--follow]` | Redeploys the latest commit on the app's GitHub branch (same as the Deploy button - it does not push local code). Handy to redeploy after an env change or to retry; normally a `git push` deploys for you. `--follow` streams the log live and exits non-zero on failure, so it slots straight into scripts and CI. If a deployment is already in flight you get a clear message instead of a duplicate run. |
| `deployments` | `DOMAIN` | Recent deployment history: commit sha, message, status, who triggered it, and how long it took. |

## Environment variables

The domain comes first, then the operation: `pyvolt env DOMAIN <op>`.

| Command | Arguments | Description |
|---|---|---|
| `env DOMAIN list` | | Shows the app's variables. Secret values are masked. |
| `env DOMAIN get` | `KEY` | One variable's value, unmasked (it's your own secret) - handy in scripts. |
| `env DOMAIN set` | `KEY=VALUE ...` | Upserts variables - the `.env` on the server is regenerated and the app restarted. Multiple pairs in one call are fine. |
| `env DOMAIN rm` | `KEY` | Removes a variable - same regenerate + restart. |

## Processes & logs

| Command | Arguments | Description |
|---|---|---|
| `ps` | `DOMAIN` | Lists the app's background processes with their live systemd state. |
| `ps restart` | `DOMAIN restart NAME` | Restarts one background process by name. |
| `logs` | `DOMAIN [--process NAME] [-n LINES]` | Tails the app's journal - the last 100 lines by default, up to 500 with `-n`. `--process` reads a named background process instead of the web app. |

## Inventory

| Command | Arguments | Description |
|---|---|---|
| `servers` | | Your servers, with provider, status and connectivity. |
| `apps` | `[--server NAME]` | Your apps, with status, repo and branch. `--server` filters to one server. To make a new one, see [Create an app](#create-an-app). |
| `status` | `DOMAIN` | One app's details: status, live URL, dashboard URL, repo and branch. |
| `metrics` | `SERVER` | Latest CPU / memory / disk / network snapshot for a server. |
| `open` | `DOMAIN [--print]` | Opens the app's dashboard in your browser. `--print` prints the live + dashboard URLs to stdout instead (headless / agent use). |

## SSH

| Command | Arguments | Description |
|---|---|---|
| `ssh` | `SERVER [--app DOMAIN]` | Opens a shell on the server as the `pyvolt` app-user - resolves the host/port and execs your local `ssh`. `--app` `cd`s into that app's directory on connect. Needs your key on the box; add it under **Account → SSH Keys** (see the [SSH access guide](ssh-access.md)). |

## SSH protection (fail2ban)

Locked yourself out with a few failed SSH logins? These work even while your IP is banned - they go through Pyvolt's connection to the server, not yours.

| Command | Arguments | Description |
|---|---|---|
| `bans` | `SERVER` | IPs currently banned by fail2ban, with your own IP flagged (“this is you”) so you can confirm a self-ban before acting. |
| `unban` | `SERVER [IP] [--me]` | Lifts a ban. `--me` unbans your own public IP without you having to look it up. Bans also expire on their own after a few minutes. |

## Account

| Command | Arguments | Description |
|---|---|---|
| `login` | | Authorizes this machine via your browser - no password in the terminal. The flow is described on [Installation & login](cli.md). |
| `whoami` | | Shows which account this machine is authorized as. |
| `logout` | | Removes this machine's token. Revoking it fully happens under **Account → API** in the dashboard. |
