restore-code
Recover uncommitted code that disappeared — a file an edit overwrote, a function that vanished, a working tree a command reset. This is the read-side twin of the safety-snapshot hook: that hook silently captures the full working tree before every edit into refs/bewith-safety/<session>/<epoch>; this skill reads those snapshots back.
The promise to the developer is: you never have to think about it, and you never lose code. The hook is the always-on net; this skill is how the net pays out. When the snapshots don't have it (the loss predates the hook, or it was a gitignored file), this skill falls back to git's universal recovery surfaces so it is still worth running.
When to invoke
- The command:
/restore(optionally/restore <file or description>). - Free language — invoke immediately, no confirmation needed to start the search: "I lost code", "restore what was there before", "bring back the previous version", "undo what just got deleted", "where did my changes go", Hebrew "נעלם לי קוד", "תשחזר את מה שהיה", "תחזיר את הגרסה הקודמת", "איפה השינויים שלי".
- Proactively (Claude detects loss): if you notice an edit unexpectedly shrank a file, dropped a function/import/block the developer did not ask to remove, or a command (
reset,checkout,stash) wiped uncommitted work — stop, say what you think was lost, and offer to restore from a snapshot before doing anything else. Do not silently re-create the code from memory; the snapshot is the ground truth of what was actually there.
Steps
All commands run in the developer's current working tree (this skill restores into it by design — see the exemption note). Run from the repo root.
-
Capture the current state first, so the restore is itself reversible. Before touching anything, snapshot now:
NOW=$(date +%s)PARENT=$(git rev-parse -q --verify HEAD 2>/dev/null)TMP=$(mktemp); GIT_INDEX_FILE="$TMP" git add -ATREE=$(GIT_INDEX_FILE="$TMP" git write-tree); rm -f "$TMP"C=$(printf 'pre-restore snapshot' | git commit-tree "$TREE" ${PARENT:+-p "$PARENT"})git update-ref "refs/bewith-safety/pre-restore/$NOW" "$C"Tell the developer this ref exists so they know the current state is preserved even if the restore is wrong.
-
List the available snapshots, newest first:
git for-each-ref --sort=-refname \--format='%(refname) %(objectname:short) %(creatordate:relative)' \refs/bewith-safety/The trailing path segment of each ref is the unix epoch it was taken. Present the recent ones in human time.
-
Find which snapshot has the lost code. If the developer described it (a function name, a string, a filename), search across snapshots:
for ref in $(git for-each-ref --format='%(refname)' refs/bewith-safety/); dogit grep -l 'SEARCH_TERM' "$ref" 2>/dev/null | sed "s|^|$ref: |"doneOr compare a specific file between a snapshot and the working tree:
git diff <snapshot-sha> -- path/to/file # what changed since that snapshotgit show <snapshot-sha>:path/to/file # the file's content in that snapshot -
Show the developer exactly what will be restored — a diff, before writing anything. Identify the smallest correct scope: a single file is the common case; a whole-tree restore is rare and must be called out explicitly.
git diff <snapshot-sha> -- path/to/file # the changes the restore will reverse/recoverConfirm with the developer which snapshot and which path(s).
-
Restore the chosen path(s) (working tree + index, never history, never a
reset --hard):git restore --source=<snapshot-sha> -- path/to/file# equivalently: git checkout <snapshot-sha> -- path/to/fileFor a full-tree restore (only when the developer explicitly asks):
git restore --source=<snapshot-sha> -- . -
Confirm what was restored and from which timestamp, and remind them the
pre-restoreref from step 1 reverses it if the choice was wrong.
Fallback — no bewith-safety snapshot has it
The hook only covers edits made after it shipped, and skips gitignored files. If the snapshots come up empty, recover from git's universal nets, in order:
git stash list # was it stashed?
git reflog --date=iso | head -40 # recent HEAD positions — recover after a bad reset/checkout/rebase
git fsck --lost-found --no-reflogs # dangling commits + blobs (orphaned work)
# inspect a dangling commit/blob, then restore as in step 5:
git show <dangling-sha>
Walk these with the developer rather than guessing. If nothing surfaces here either, say so plainly — do not fabricate the lost code from memory and present it as recovered.
Anti-patterns
- Re-creating lost code from memory and calling it "restored." The snapshot/reflog is the truth of what was there. Recover the real bytes; only reconstruct from memory as an explicit last resort, clearly labelled as such.
git reset --hard/git checkout .to "fix" the tree. Those destroy current uncommitted state. This skill only ever adds back viagit restore --sourceof specific paths, after a pre-restore snapshot.- Restoring the whole tree when one file was lost. Scope to what's missing; a blanket restore can revert unrelated good work done since the snapshot.
- Skipping the diff/confirm. Always show what will change before writing — except the read-only search for the lost code, which needs no confirmation.
Why this skill is exempt from the worktree pattern
session-safety.md requires git-mutating artifacts to run in an isolated worktree so they never touch the developer's working tree. This skill is the deliberate exception: its entire purpose is to write recovered code into the developer's current working tree, on explicit request, after showing a diff. It mutates the working tree and index but never branches or history, and the pre-restore snapshot (step 1) makes even a wrong restore reversible.
Cross-references
safety-snapshot.sh— the PreToolUse hook that captures the snapshots this skill reads.session-safety.md— the full session-safety discipline (worktree isolation, freshness, concurrent-session registry, and this snapshot net).session-guard.sh— the sibling guard that prevents cross-session clobber in the first place.