---
description: Recover deleted, overwritten, or accidentally-modified files. Prefers launch-recall's shadow-git backup when wired (per-file snapshot history, debounced, doesn't need commits); falls back to git reflog / git stash / git log when recall isn't available. Read-only by default; restore is one-shot and prompts before overwriting. Never suggests destructive ops (git reset / git clean / rm) — recovery only.
when_to_use: |
  Auto-fire whenever the user signals they've lost work or want to undo something on disk. Trigger phrases: "I lost X", "lost my changes", "deleted by mistake", "accidentally deleted / removed / overwrote", "auto-formatter ate", "prettier ate my comments", "can I get back / recover / restore X", "undo my last edit", "undo what I did to X", "go back to previous version", "previous version of X", "what was in X before", "revert this file", "rollback this file" (note: "rollback the deploy" is NOT this — that's deploy-check / orbit territory), "the file is gone", "where did X go" when framed as loss. Also auto-fire on manual subcommand usage: status / doctor / history / show / restore / diff / report. Do NOT auto-fire for: bug investigation ("why doesn't X work" → /kit:debug), code structure ("how does X work" → /kit:analyse), git workflow ("how do I commit / push / merge" → general git help).
allowed-tools:
  - mcp__launch-recall__recall_status
  - mcp__launch-recall__recall_doctor
  - mcp__launch-recall__recall_history
  - mcp__launch-recall__recall_report
  - Bash(git --git-dir=*)
  - Bash(git reflog*)
  - Bash(git stash list*)
  - Bash(git log*)
  - Bash(git show*)
  - Bash(git diff*)
---

# /kit:recovery

Recover deleted / overwritten / lost files. **Recall-first** when wired, **git-fallback** when not. Read-only except for `restore` (which prompts).

## Preflight — detect which path is available

Always start by checking which recovery backend is reachable. Run BOTH probes (cheap, in parallel):

1. `mcp__launch-recall__recall_status` → if it returns `{running: true, lastSnapshotAt: …}`, recall is the preferred path. Note the `watchTree` for context.
2. `Bash("git rev-parse --is-inside-work-tree 2>&1")` → confirms a regular git repo exists (for the fallback path and for cross-checks).

Surface what's available before doing anything else:
- Both available → use recall first, mention git as fallback.
- Only git available → tell user `"launch-recall not wired in this project — falling back to git reflog/log. (Recall would give you per-file history without needing commits. Run `npx @launchsecure/launch-kit refresh` to wire it.)"`
- Neither available → stop and surface that. Can't recover blind.

## Subcommand interface (manual invocation)

Parse `$ARGUMENTS` — first token is the subcommand. If the first token doesn't match any known subcommand, treat the whole input as a **natural-language recovery request** (see below).

- **status** — recall watcher liveness + last snapshot age (one line).
- **doctor** — recall health check (3-line report: shadow_repo / watcher_alive / recent_snapshot).
- **report** — project-wide recall stats (totalSnapshots, shadowSizeBytes, recentSnapshots).
- **history `<path>`** — `[--limit=N]` — snapshots for the path (recall) OR `git log -p -- <path>` rows (fallback). Default limit 20.
- **show `<path>` `<sha>`** — print the file at that snapshot (no write).
- **diff `<path>` `<sha>`** — unified diff vs current working tree (or "file deleted from working tree" if absent). Cap 500 lines.
- **restore `<path>` `<sha>`** — `[--to=<target-path>]` — restore the file. Strict confirmation protocol below.

Examples:
- `/kit:recovery status`
- `/kit:recovery history src/server/comms/build-feed.ts`
- `/kit:recovery show src/server/comms/build-feed.ts a1b2c3d`
- `/kit:recovery restore src/server/comms/build-feed.ts a1b2c3d`
- `/kit:recovery restore prisma/schema.prisma a1b2c3d --to=prisma/schema.recovered.prisma`

## Natural-language recovery flow (auto-invoke path)

When the user says "I lost X" / "deleted by mistake" / "prettier ate my comments" / "can I get back…", follow this loop:

1. **Identify the target**: parse the user's prompt for a file path. If absent, ask: `"Which file or directory? (full path from repo root)"`. Do not guess.
2. **Preflight** (see above) so you know which backend you're on.
3. **List options**:
   - Recall path: `recall_history(path: <path>, limit: 20)` → table of `sha | age | message`.
   - Git path: `git log --oneline -20 -- <path>` (committed) AND `git reflog | head -20` (recent HEAD moves) AND `git stash list` (stashes). Present each source separately so the user knows which kind of recovery they're picking.
4. **Show a candidate's content** before any restore: `show` the latest snapshot/commit so the user can confirm it's what they want.
5. **Confirm restore** per the protocol below. NEVER restore without explicit `yes`.

## Restore protocol (the only write operation)

1. Resolve target path: `--to=<target>` if given, else the original `<path>`.
2. If the target **exists on disk**:
   - Print a side-by-side summary: `current size <N> bytes, snapshot size <M> bytes`.
   - Show the first ~20 lines of the diff (current → snapshot).
   - Ask: `"Overwrite <target>? (yes / show full diff / no)"` — wait for explicit `yes`.
3. If the target does **NOT exist** on disk (file was deleted), restore without prompt but tell the user before writing: `"Restoring deleted file to <target> from snapshot <sha>."`
4. Restore command:
   - Recall path: `git --git-dir=<shadowRepoPath> --work-tree=<projectRoot> show <sha>:<path> > <target>`
   - Git path: `git show <sha>:<path> > <target>` (against the regular repo)
5. After restore: `"Restored. (Recall — if active — just captured a new snapshot of the restore itself, so your prior working-tree state is also recoverable.)"`

## When recall is NOT wired — git fallback instructions

If `recall_status` says recall isn't running OR the MCP isn't reachable, walk the user through the git-only path:

- **Recently deleted file but no commit since**: `git checkout HEAD -- <path>` (restores from last commit). Confirm before running — this overwrites uncommitted changes if any exist.
- **Lost edits made after the last commit, no stash**: usually unrecoverable from git alone unless your editor has a local history feature (VS Code: "Timeline" view, JetBrains: "Local History"). Surface this honestly: `"Git only tracks what you commit. Your editor may have local history — check VS Code's Timeline or JetBrains' Local History panel for unsaved changes."`
- **File existed in a previous commit, deleted later**: `git log --oneline --all -- <path>` to find the last commit that contained it, then `git show <sha>:<path>` to view, then `git show <sha>:<path> > <path>` to restore.
- **Stashed changes**: `git stash list` to enumerate, `git stash show -p stash@{N}` to view, `git stash apply stash@{N}` to apply (non-destructive — keeps the stash).
- **Recent HEAD moves (force-push, rebase, reset)**: `git reflog` shows the prior positions. `git show <sha>:<path>` to view, then restore via `git show > file` (NOT `git reset --hard` — that moves your branch).

## Constraints

- **Read-only by default.** Only `restore` writes; everything else reads.
- **Restore requires explicit `yes` confirmation** when overwriting an existing file. Never auto-overwrite — per project memory `feedback_no_dumb_reverts`, destructive ops need explicit confirmation.
- **Never suggest `git reset --hard` / `git clean -f` / `rm` as recovery.** These DESTROY more state than they recover. Always restore via `git show > file` so the rest of the tree is untouched.
- **Never auto-init recall.** If recall isn't wired, point at `npx @launchsecure/launch-kit refresh` — don't run it for the user. Their project, their choice.
- **Surface both paths when both are available.** Recall has per-file granularity without needing commits; git has the canonical commit history. Sometimes the user wants the committed version, not the latest in-flight edit. Let them choose.
- **Quote both ambiguities when history is empty.** If `recall_history` returns nothing AND the file still exists, say BOTH "path may be in recall's ignore list" AND "file may simply have no churn" — don't guess.
