# `thothctl pi` lifecycle contract `thothctl` is the only component that drives Docker lifecycle operations. The `core` container does not mount a Docker socket and Pi is never updated in a running container. ## Read-only operations ```text thothctl --installation /absolute/path/thothii-installation.yaml pi status thothctl --installation /absolute/path/thothii-installation.yaml pi doctor thothctl --installation /absolute/path/thothii-installation.yaml pi test thothctl --installation /absolute/path/thothii-installation.yaml pi logs [--follow] ``` `status` executes the image-bundled `pi --version`. `doctor` requires the rendered `core` image, the external `THT_LLM_URL` contract, writable `/home/thoth/.pi`, the read-only Pi auth file, and private `/health`. `test` additionally reads private `/models` and `/settings`; this temporary composite smoke is replaced by the Pi Management API in Task 8. `logs` is core-only and uses the same credential redaction as every other `thothctl` diagnostic. `pi check` is an alias for `pi test` for operational scripts. ## Updating Pi An update always specifies a pinned Pi version and an explicit confirmation: ```text thothctl --installation /absolute/path/thothii-installation.yaml pi update \ --version 0.81.0 --source build --yes ``` `--source build` rebuilds only `core` using `PI_VERSION=`. A pulled source must be a digest-pinned image; tags are rejected: ```text thothctl --installation /absolute/path/thothii-installation.yaml pi update \ --version 0.81.0 --source pull \ --image registry.example.invalid/thothii-core@sha256:<64-lowercase-hex-digits> --yes ``` Before changing anything, the command validates the rendered Compose configuration, Pi auth/state preconditions, health, current version, active sessions, the current image ID, named-volume set, and a digest of the rendered non-secret configuration. It therefore keeps the exact installation Compose files and environment, including the external `THT_LLM_URL` endpoint, when it recreates only `core` with `--no-deps --force-recreate`. It never recreates `frontend` and never uses volume replacement flags. Open, unarchived sessions stop an update. After an operator has completed or otherwise drained their work, `--drain` makes the command re-check that the session list is empty before continuing. ## Recovery and rollback Before a candidate is built or pulled, the command atomically writes: ```text /.thothctl/update-state.json ``` The file is mode `0600` and records only the previous/candidate image references and IDs, named volume names, requested version/source, rendered-configuration digest, phase, and timestamp. It never contains credentials, endpoint values, secret paths, Compose output, or logs. After recreate, the command checks core health, the requested `pi --version`, the Pi/core smoke, unchanged configuration digest, and unchanged named-volume set. Any failure after recreation automatically retags and recreates the recorded previous image. A failed or interrupted operation leaves the same metadata for explicit operator recovery: ```text thothctl --installation /absolute/path/thothii-installation.yaml pi rollback --yes ``` Both update and rollback require `--yes`; without it they exit `2` before invoking Docker. Invalid arguments, a pending recovery, and active sessions also exit `2`. Docker or verification failures exit nonzero with concise, redacted guidance. The original Docker child exit code is preserved for direct read-only/log command failures.