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

# CLI Operations

> Command-line flags for inspecting the GoModel binary, probing a running gateway's health, and reloading its configuration.

## Overview

The `gomodel` binary exposes a small set of command-line flags for operational
tasks. Flags accept both single-dash (`-flag`) and double-dash (`--flag`) forms;
the examples below use the long form.

| Flag               | Description                                                   | Default |
| ------------------ | ------------------------------------------------------------- | ------- |
| `--version`        | Print version information and exit                            | —       |
| `--health`         | Probe the local `/health` (liveness) endpoint and exit        | —       |
| `--health-timeout` | Maximum time to wait for the `--health` probe                 | `2s`    |
| `--ready`          | Probe the local `/health/ready` (readiness) endpoint and exit | —       |
| `--ready-timeout`  | Maximum time to wait for the `--ready` probe                  | `4s`    |
| `--reload`         | Tell the running gateway to reload its configuration and exit | —       |

## Version

Print the build version and exit:

```bash theme={null}
gomodel --version
```

## Health probe

`--health` makes the binary act as a health-check client: it loads the same
configuration as the server, requests the local `/health` endpoint, and exits.

```bash theme={null}
gomodel --health
```

* Exits `0` when the endpoint returns HTTP `200` with `{"status":"ok"}`.
* Exits non-zero otherwise (connection refused, non-`200` status, or any other
  status value).

The probe always targets the loopback interface (`127.0.0.1`) since it runs
inside the same container as the server, but it derives the `PORT` and
`BASE_PATH` from configuration instead of hardcoding `8080` and `/health`. Bound
the request with `--health-timeout`:

```bash theme={null}
gomodel --health --health-timeout 5s
```

### Docker `HEALTHCHECK`

Because the probe is built into the binary, container images can report health
without shipping `curl` or `wget` — useful for minimal/distroless runtimes. The
official image wires it up automatically:

```dockerfile theme={null}
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD ["/gomodel", "--health"]
```

Orchestrators (Docker, Compose, Kubernetes) can then detect and restart an
unhealthy gateway.

## Readiness probe

`--ready` probes `/health/ready`, which reports whether the instance should
receive traffic. Unlike liveness, readiness checks the dependencies the gateway
owns:

* **Storage** is required. If the backend (SQLite/PostgreSQL/MongoDB) is
  unreachable, readiness reports `not_ready` (HTTP `503`).
* **Redis exact cache** (when configured) is a performance optimization. If it
  is unreachable, readiness reports `degraded` but stays HTTP `200` — the
  gateway still serves requests.

Upstream **provider** reachability is deliberately excluded: a provider outage
must not pull a healthy gateway out of rotation.

```bash theme={null}
gomodel --ready
```

* Exits `0` when the endpoint returns HTTP `200` (`ready` or `degraded`).
* Exits non-zero on `not_ready` (HTTP `503`), connection refused, or an
  unexpected status value.

```json theme={null}
{ "status": "ready", "components": { "storage": "ok", "cache": "ok" } }
```

## Configuration reload

`--reload` applies configuration changes to a running gateway without
restarting it — the same operation as `nginx -s reload`:

```bash theme={null}
gomodel --reload
```

It loads the same configuration the gateway does to find the pid file, signals
that process, and exits. Loading it first means a `config.yaml` the binary
cannot parse fails the command — non-zero exit, no signal sent — before the
running gateway is ever asked to look at it. On success the gateway:

1. Re-reads the `.env` file. New and edited values are applied; values removed
   from the file are unset. Variables exported into the process environment
   keep winning over the file, exactly as they do at startup — a container's
   environment is not overridden by a file inside it.
2. Re-reads `config/config.yaml` (or `config.yaml`) and every environment
   variable, then rebuilds itself from the result. Providers, virtual models,
   budgets, rate limits, guardrails, MCP servers, caching, logging, admin
   settings — all of it reloads, because the reload re-runs the same startup
   path rather than a hand-picked subset.

The replacement is built **before** the running configuration is stopped, so a
configuration that fails to load or initialize changes nothing: the gateway logs
`reload failed; keeping the running configuration` and keeps serving on what
already works.

The listening socket is held for the lifetime of the process and handed to each
configuration in turn, so requests arriving mid-reload wait to be accepted
rather than being refused. In-flight requests get the same 10-second drain
window as a shutdown, and streamed responses that outlive it are cut, so a
reload during heavy streaming traffic is not free — but no connection is dropped
at the socket.

That last guarantee depends on the operating system letting the gateway
duplicate a listening socket, which covers every platform that can be sent a
reload signal in the first place. Where duplication is unavailable, the next
configuration rebinds the address instead, and connections are refused for the
length of the swap.

Sending the signal directly does the same thing, which is what a process manager
or a container without a shell can use:

```bash theme={null}
kill -HUP "$(cat data/gomodel.pid)"
```

<Note>
  Reload is a POSIX signal feature and is not available on Windows.
</Note>

### The pid file

The gateway writes its process id to `PID_FILE` / `server.pid_file` at startup
and removes it on shutdown. The default is `data/gomodel.pid` when a `./data`
directory exists (Docker images and existing deployments) and the
OS-conventional per-user data directory otherwise — the same resolution the
SQLite database uses.

Give each instance its own path when several gateways share a host, since
`--reload` signals whichever process the file names. To write no pid file at
all, set `server.pid_file: ""` in `config.yaml` — that disables `--reload`,
though `kill -HUP` still works. An empty `PID_FILE` env var reads as unset and
keeps the default, the same as every other setting. If the path is not writable
the gateway logs a warning and serves normally, only without `--reload` support.

Both the gateway and `gomodel --reload` resolve the path from the same
configuration, so run the command from the same working directory (or with the
same `PID_FILE`) as the gateway:

```bash theme={null}
docker exec my-gateway /gomodel --reload
```

### What a reload does not change

* **`PORT`** — the socket stays bound so no connection is refused; a port change
  needs a restart. The gateway logs a warning naming both ports.
* **`PID_FILE`** — it names the process that is already running.
* **`GOMODEL_DEMO_MODE`** — the demo warnings are wired up once at startup.
* **In-memory state** — rate limit counters, virtual-model session affinity, and
  live log buffers start fresh, exactly as they would after a restart. Budgets
  and usage are stored in the database and are unaffected.

For refreshing provider model catalogs and admin-managed data *without* re-reading
configuration, the dashboard's runtime refresh (`POST /admin/runtime/refresh`) is
the lighter option.

Liveness (`--health`) is the right signal for a Docker `HEALTHCHECK` (restart on
crash). Readiness (`/health/ready`) is the right signal for a Kubernetes
`readinessProbe` (gate traffic) — point it at the HTTP endpoint directly or run
`gomodel --ready` as an exec probe. Keep `--ready-timeout` larger than the
server's internal per-dependency probe timeout (`2s`) so a slow backend returns
a clean `not_ready` instead of the client timing out first.
