<!-- zibby-template-version: 1 -->
# /zibby-app-destroy — permanently remove a Zibby Managed App

You are helping the user destroy a hosted app. **This is irreversible.** Always confirm with the user before running.

Canonical docs: **https://docs.zibby.app/apps/lifecycle**

## What destroy does

`zibby app destroy <instanceId>`:

1. Stops the app's task (drains in-flight requests for ~30s, then SIGKILL).
2. **Deletes the persistent data volume** attached to the instance — this is where the app stored its database, config, uploads, anything stateful. **This data is gone.** No backup, no recovery.
3. Releases the public URL (cookie-pinned routes invalidate immediately).
4. Removes the instance record. The instanceId is invalid after this.
5. Tears down the per-instance auth sidecar (if any) and the task definition.

Billing stops at the destroy timestamp.

## Steps

1. **Identify the instanceId.** If user gave a friendly name:
   ```
   Bash(zibby app list)
   ```
   Verify with the user that the row you're about to destroy is the right one. Show them `name`, `appType`, `url`, `createdAt`.

2. **Spell out the data loss explicitly.** Examples:
   - For an n8n instance: "destroying will delete your workflows, credentials, execution history, and SQLite DB."
   - For wordpress: "destroying will delete the site files, uploads, and MySQL data."
   - For grafana: "destroying will delete your dashboards, data sources config, and SQLite DB."
   - For a goal-mode install: "destroying will delete whatever the agent installed AND the persistent volume holding its state."

3. **Get explicit confirmation.** Don't proceed on a "yeah" — make them name the app:
   > "Type the instance's friendly name to confirm destroy: `<name>`"

4. **Run destroy:**
   ```
   Bash(zibby app destroy <instanceId> --yes)
   ```
   The `--yes` flag skips the CLI's own interactive confirm. Only pass it AFTER you've confirmed with the user yourself.

5. **Verify.** After 30-60s:
   ```
   Bash(zibby app status <instanceId>)
   ```
   Should return 404 (instance gone). If it's stuck in `destroying`, that's a backend cleanup race — let it sit another 60s.

## When NOT to destroy

- **Just want to stop billing for the night** → there's no "pause" today (every running app is billed by the minute). Destroy is the only way to stop billing, and it's destructive. Tell the user.
- **Want to upgrade** → use `/zibby-app-upgrade` instead. Upgrade preserves the app's persistent data.
- **Want to change auth** → use `/zibby-set-auth` instead.
- **Want to retry a failed bootstrap** → for goal-mode failures, destroy + redeploy with a different goal is reasonable. For catalog failures, file a bug (catalog should self-heal).

## Common pitfalls

- **Race with in-flight requests.** Destroy SIGTERMs the task first; long-running webhooks can be cut off mid-response. Tell the user to drain their callers if they care.
- **`destroyed` status briefly returns 200 with `status: destroying`** before flipping to 404. Don't panic.
- **Multi-service instances destroy together** — there's no "destroy just the worker service". The whole instance goes.
