Rescue Prior Session
When a Claude Code project folder gets moved or renamed, the old sessions stay in their original ~/.claude/projects/<encoded-old-path>/ dir and don't show up in /resume. This skill puts them back where they belong, lets the user pick one, generates a summary in the conversation's original language, and saves the full conversation to a markdown file for future reference.
How to talk to the user (READ THIS FIRST)
The user is not a technical person. Every time you narrate what's happening or ask a question, translate every piece of jargon into plain language. Examples:
| Don't say | Do say |
|---|---|
| "Phase 1: Detect orphans" | "Looking for old conversations that got left behind when you moved the folder" |
| "Worktree orphan session" | "An old conversation from a temporary working folder you used before" |
| "Rewrite the cwd field" | "Update where the conversation thinks it belongs" |
| "Encoded project dir" | (don't mention it at all — just say "Claude's storage for this project") |
| "Session history file" | "the markdown file with your past conversation" (or just refer to the actual path) |
| "JSONL" | "The conversation file" |
If you must use a technical term because there's no good plain-language substitute, give a one-sentence layman's explanation immediately after.
Same rule applies to AskUserQuestion: the question text and every option label should read naturally to someone who has never heard of git, file paths, or JSON.
The output is always the same
This skill produces two things together, every time:
- A summary shown in the conversation (snapshot, key decisions, open questions, files touched, last exchange)
- A session history file written to
<project-root>/.claude-session-rescue/<short-id>-<YYYY-MM-DD>.mdcontaining the full conversation, formatted for human reading
No mode picker. No "how deep do you want to go" question. Both outputs are cheap to produce and serve different needs (summary = read now, file = read later or feed to a future session).
One rescue per conversation
Loading two old conversations into the same new session mixes contexts in a way that hurts more than it helps — the new Claude ends up with conflicting decisions, ambiguous "what were we doing" signals, and double the noise. So: do at most one rescue per conversation. If the user asks for a second:
"I already loaded session
<previous-id>in this conversation. Loading another would mix things up. Open a new Claude session and run/claude-session-rescuethere."
Phase 0: Route on argument
| Arg | Goes to |
|---|---|
| empty | Full flow: Phase 1 → 2 → 3 |
migrate | Phase 1 only |
list | Phase 2 only |
| 4+ hex chars (uuid prefix) or full uuid | Phase 3 with the given id |
ends in .jsonl | Phase 3 with the given path |
| anything else | Reply with usage and stop |
$SKILL_DIR below means wherever this SKILL.md lives. The default install path is ~/.claude/skills/claude-session-rescue/.
Phase 1: Look for stranded conversations
Narrate to the user, plainly: "Let me first check whether you have any old conversations sitting in other places — when you moved or renamed the folder, some of them might have been left behind."
Run:
python3 "$SKILL_DIR/scripts/find_orphans.py"
The output is JSON with an orphans array. If empty, just say "All your past conversations are already where they should be — moving on to the list." and continue to Phase 2.
If non-empty, for each orphan use AskUserQuestion. Phrase it in plain language:
- Question text: "I found <N> old conversation(s) from <human-readable-description-of-old-path>. The original folder doesn't exist anymore. Want me to move these into your current project so you can see them again?"
- Options:
- "Yes, move them" (default)
- "Skip this one"
- "Skip all and continue"
If the orphan is a worktree subfolder (basename contains worktrees), add a note: "this one came from a temporary working folder created by a tool like gstack — the conversation content is still useful, but its original location no longer exists."
For each confirmed orphan, run:
python3 "$SKILL_DIR/scripts/migrate.py" \
--orphan "<encoded_dir>" \
--old-cwd "<old_cwd>" \
--new-cwd "$(pwd)"
The script copies each conversation file, rewrites every occurrence of the old folder path inside the file (not just the "belongs to this folder" field — also file references inside tool calls and message text, so files in the conversation stay clickable from the new location), and archives the old location with a .trash- prefix (so the user can roll back if it was the wrong move).
Then report plainly: "Moved <N> conversation(s) over. The old location is preserved under .trash-... in case you ever need to undo this."
Phase 2: Show what's there and let the user pick
Narrate plainly: "Here's everything you've discussed with Claude in this project. Pick one and I'll write up a summary."
Run:
python3 "$SKILL_DIR/scripts/list_sessions.py" \
--dir "$HOME/.claude/projects/$(pwd | sed 's|/|-|g')" \
--exclude "<current-session-uuid-if-known>"
Identifying the current session is unreliable (no env var for it). If unsure, list everything and warn the user "skip the entry that matches what you're typing right now". The current session is usually the most recent.
Present the list as numbered items. For each, show:
- A short readable date ("May 11, 2026")
- Turn count ("12 turns")
- A one-line topic hint — take the first user message and trim to ~80 chars
- Fork relationship, if any (see "Fork detection" below)
Use AskUserQuestion if 2–4 sessions, freeform reply (id prefix) if more.
If 0 sessions remain, say "Nothing else to load." and stop.
Fork detection
list_sessions.py automatically detects when two sessions share a long common prefix (Claude Code sometimes stores a single logical conversation across multiple jsonl files — e.g., when one is interrupted and another continues). The output fields:
is_canonical: true— this session has the most turns within its fork group; treat it as the "complete" versionfork_of: <short_id>— this session is a shorter fork of anothercommon_prefix_turns: N— how many turns are byte-identical with siblingsdivergent_turns: N— turns unique to this session after divergencefork_siblings: [...]— short_ids of other sessions in the same group
When narrating, tell the user plainly:
"
28df8c9eandc04c652alook like the same conversation captured in two files — they share 49 turns at the start.28df8c9ehas 2 more turns after that point (looks like the complete version).c04c652aalso has 2 turns after the split (likely a different ending — perhaps an interrupt). Recommend loading28df8c9eunless you specifically want to see the other ending."
Don't auto-hide the shorter fork — the user might want to see its 2 divergent turns (which could include important info like "[Request interrupted]" markers, or a different conversational branch).
Phase 3: Load it
Resolve the chosen session to a file path:
if [ -f "$ARG" ]; then
FILE="$ARG"
else
matches=( "$PROJECT_DIR/$ARG"*.jsonl )
# 1 match: use it. 0 or >1: tell the user plainly.
fi
3a. Fork confirmation (BEFORE extracting)
If the chosen session has fork_of set (i.e. it's a non-canonical fork of a longer sibling), DO NOT proceed silently. Stop and confirm with AskUserQuestion:
- Question text (plain language, source-language matched): "You picked
<short_id>. Heads up — this is a shorter fork of<canonical_id>(the complete version). They share the first<common_prefix_turns>turns; this one has only<divergent_turns>unique turns after that. Most of what you'd recall from this one is also in<canonical_id>. What do you want to do?" - Options:
- "Switch to
<canonical_id>(the co
- "Switch to