
<div class="callout callout-attn"><p><strong>Alpha.</strong> VIA is under active development. APIs, operational flows, and host requirements may change between releases.</p></div>

When a deploy reaches a terminal failure, stay on first-party commands:

```bash
vary app status my-api --target prod
vary app inspect my-api --target prod
vary app logs my-api --target prod --source build --tail 200
vary app smoke my-api --target prod
vary app debug-bundle my-api --target prod
vary target doctor --target prod
```

`status` includes the latest deploy id, build id, failure phase, failure reason, and next commands. Runtime capability readiness failures include a structured failed-capability block with the capability id/type, bound resource, binding name, expected condition, observed state, failing check, and next command.

`logs` never returns empty output ambiguously: when a stream has no entries it prints `No <stream> log entries found for <object>; try <next command>`. Use `--quiet-empty` only for scripts that intentionally accept an empty stream.

`smoke` checks the externally advertised route from the workstation. If the app only has an internal or pending route, it reports that state instead of presenting the internal route as a public URL.

`debug-bundle` writes a redacted zip containing status JSON, inspect JSON, deploy/build details, selected logs, target doctor/status data, toolchain data, and version metadata.

Route readiness in `status --json` is layered. Each route can report
`domain_verification`, `certificate`, `load_balancer`, `runtime`, `readiness`,
`blocking`, `owner`, and `remediation`. If the route table and
domain/certificate state disagree, the diagnostic is `state_inconsistent` and
the route readiness is `blocked_state_inconsistent`; use the remediation command
and operator route/domain tools instead of editing proxy or database state.

## App status

```bash
vary app status my-api --target prod
```

The status command reads from the control plane and prints:

| Field group | Included data |
|---|---|
| App identity | App name and server URL |
| Current deploy | Current deploy id and state |
| Latest deploy | Latest deploy id and state |
| Source | Commit and ref |
| Artifact | Artifact hash |
| Build/runtime metadata | Toolchain and runtime image |
| Runtime instance | Container id and runtime state |
| Explainer | One-line summary at the bottom |

Healthy output ends with:

```text
=> running - container up and serving traffic.
```

If the latest deploy failed while an older one is still serving, status prints two blocks: the current healthy deploy and the latest failed deploy. In that case the command exits non-zero and the explainer ends with:

```text
=> deploy failed ...
```

## Logs and retries

```bash
vary app status my-api --target prod
vary app doctor my-api --target prod
vary app repair my-api --target prod
vary app logs my-api --target prod --source build --tail 200
vary app build <build-id> --target prod
vary app build logs <build-id> --target prod --app my-api --follow
vary app build cancel <build-id> --target prod --app my-api --follow
vary app deploy retry <deploy-id> --target prod --app my-api --apply-manifest --follow
vary app deploy <deploy-id> --target prod
```

For failed deploys, start with `status`: it prints the latest deploy/build identifiers, route health, runtime health, dependency failures, and the failed phase/reason. If smoke reports `runtime_identity_expired`, run `doctor`, then `repair`; the repair path renews runtime identity by replacing or relaunching the workload instead of reporting a no-op restart.

`logs --source build` returns the persisted build log, including redacted stdout/stderr from the failing phase. Use `build <build-id>` for phase status, heartbeat, worker id, log availability, and next commands. Stuck builds can be cancelled with `vary app build cancel <id> --target prod --app my-api --follow`, then retried with `vary app deploy retry <deploy-id> --target prod --app my-api --apply-manifest --follow`. Use `deploy <deploy-id>` for source ref, commit, build/artifact ids, events, and terminal state.

## App-owner command surface

The full `vary app` command list is in [Via CLI reference](/docs/via/cli-reference/); the workflow groupings are:

| Group | Commands | What they do |
|---|---|---|
| Lifecycle | `vary app deploy`, `vary app rollback`, `vary app restart`, `vary app stop` | Ship new releases, roll back to prior releases, and control the current runtime. |
| Status and history | `vary app status`, `vary app inspect`, `vary app builds`, `vary app build`, `vary app releases` | Inspect deploy and build state; most read commands support `--json`. |
| Logs and diagnostics | `vary app logs`, `vary app smoke`, `vary app doctor`, `vary app preflight`, `vary app debug-bundle` | Read persisted build/runtime logs, exercise the public route from the workstation, diagnose runtime/build incidents, run readiness preflight, and write a redacted support bundle. |
| Repair | `vary app repair`, `vary app restart`, `vary app build cancel`, `vary app deploy retry` | Renew runtime identity, restart unhealthy workloads, cancel stuck builds, and retry failed or cancelled deploys without direct state edits. |
| Config and env | `vary app config template/apply/patch/validate/diff/redeploy`, `vary app env set/rotate/history` | Generate config templates, apply redacted secrets, stage immutable config profile versions, and rotate secret-backed env without a new Git push. |
| Source | `vary app source show/resolve-ref/commits/remote/refs` | Inspect the Via-hosted Git source surface. |
| Manifest and platform | `vary app manifest apply`, `vary app domain list/request/verify`, `vary app route add` | Apply declarative manifest state and manage app-owned domain and route requests. |

## Cleanup decision tree

Use cleanup commands based on what should remain true after the action:

| Situation | First command |
|---|---|
| Stale route or add-on state | `vary app reconcile my-api --target prod --apply-manifest --plan --json` |
| Failed or cancelled deploy is ready to retry | `vary app deploy retry <deploy-id> --target prod --app my-api --apply-manifest --follow` |
| Temporary runtime stop | `vary app stop my-api --target prod` |
| App identity is retired or unrecoverable | `vary app delete my-api --target prod --plan --json` |

Do not use delete for routine deploy retries. Delete/decommission requires a
read-only plan first, then `--apply --confirm <app>`. It disables route/runtime
exposure before stateful cleanup, retains add-ons by default, and reports
retained resources, tombstone/name-reuse state, and audit event IDs. If the
developer command is blocked by policy, attach the plan output to an operator
escalation and have the operator run `via app delete <app> --plan --json` on
the host.

If decommissioning fails after cleanup has started, the result code is
`delete_partial_retryable`, `partial` is `true`, and the app state is
`decommission_failed`. Fix the named blocker and run the returned
`retry_command`.

Operator commands are covered by [Domains and routes](/docs/via/domains-and-routes/) and [Operations](/docs/via/operations/).
