$npx -y skills add entireio/skills --skill session-handoffUse when the user wants to continue work from one agent in another agent, inspect recent sessions, or summarize a saved session or checkpoint for handoff
| 1 | # Hand-Off Session |
| 2 | |
| 3 | ## Response Format |
| 4 | |
| 5 | Begin the first response to this skill invocation with the line: |
| 6 | |
| 7 | `Entire Session Handoff:` |
| 8 | |
| 9 | followed by a blank line, then the content. Apply the header to the **first response of the invocation only** — not on follow-up turns and not on error / early-exit responses (no sessions found, transcript missing). Its presence signals the skill ran and produced real output. The "Unanswered Question" branch still gets the header. |
| 10 | |
| 11 | ## STOP — Read these rules before doing ANYTHING |
| 12 | |
| 13 | 1. **Do NOT ask clarifying questions.** Auto-detect the session and read the transcript. |
| 14 | 2. **Do NOT run** `git log`, `git status`, `git branch`, `ps aux`, or any other exploratory commands. Use only the `entire` CLI commands listed below. |
| 15 | 3. **Do NOT say** "Would you like me to continue?" or "Let me know if you want me to pick this up." Just read the transcript and start working. Exception: if the previous agent asked the user a question that was never answered, you MUST ask the user that question before proceeding. |
| 16 | |
| 17 | Required CLI: entire 0.6.2+ (`session list --json`, `session info --transcript`, `session current --json|--transcript`, `checkpoint explain --json|--transcript|--raw-transcript --session-index N`). If a flag is rejected, tell the user to upgrade and stop. |
| 18 | |
| 19 | ## Flow: Active session handoff (default — also covers bare invocation and "current"/"active") |
| 20 | |
| 21 | ### Step 1: Resolve the canonical worktree path |
| 22 | |
| 23 | ```bash |
| 24 | entire session current --json |
| 25 | ``` |
| 26 | |
| 27 | If the output is valid JSON, read its `worktree_path` field — that is **the** canonical worktree root for this invocation, set by Entire itself. Use it verbatim in the next step (no `cwd` heuristic needed; symlinks, `/private/var`/`/var` quirks, and subdirectory invocation are all handled). |
| 28 | |
| 29 | If the output is not JSON (Entire prints `No active session found in this worktree.` when nothing is active), set the canonical worktree path to `null` and rely on the bidirectional prefix-match fallback in Step 2. |
| 30 | |
| 31 | ### Step 2: Pick the session |
| 32 | |
| 33 | ```bash |
| 34 | entire session list --json |
| 35 | ``` |
| 36 | |
| 37 | Each entry has `session_id`, `agent`, `status`, `worktree_path`, `started_at`, `last_active`, `turns`, `last_prompt`, `files_touched`. Apply filters in this order: |
| 38 | |
| 39 | 1. **Worktree scope.** If you got a canonical worktree path in Step 1, keep entries where `worktree_path` equals it exactly. Otherwise, keep entries where `cwd` starts with `worktree_path` **or** `worktree_path` starts with `cwd`. If either filter yields zero entries, fall back to the unscoped list — better to summarize a slightly-off session than to refuse the handoff. |
| 40 | 2. **User-named agent filter** (optional). If the user said "codex", "claude", "kiro", "gemini", etc., keep only entries whose `agent` matches case-insensitively as a substring (so `gemini` matches `Gemini CLI`). |
| 41 | 3. **Drop self.** Drop entries where `agent` matches the agent currently running this skill (e.g. `Claude Code`, `Codex`, `Cursor`, `Gemini CLI`, `Copilot CLI`, `Factory AI Droid`, `OpenCode`). **If this empties the list**, undo this filter and keep self — the user is asking you to summarize *your own* current session for compaction. Note that fact in the announcement (Step 5). |
| 42 | 4. **Pick most recent.** Sort by `last_active` (fall back to `started_at`) descending; take the first. |
| 43 | |
| 44 | If filtering still leaves zero entries (truly nothing in the list, even self), print a one-line error (no header) and stop. |
| 45 | |
| 46 | ### Step 3: Stream the raw transcript |
| 47 | |
| 48 | ```bash |
| 49 | entire session info <session_id> --transcript > /tmp/handoff-<session_id>.jsonl |
| 50 | ``` |
| 51 | |
| 52 | Snapshot is bounded to the file size at command start. Output is JSONL for most agents and a single JSON document for Gemini CLI. |
| 53 | |
| 54 | ### Step 4: Extract conversation content |
| 55 | |
| 56 | **JSONL agents** (Claude Code / Codex / Cursor / Copilot CLI / Factory AI Droid / OpenCode): |
| 57 | |
| 58 | ```bash |
| 59 | grep -E '"type":"(message|function_call|user|assistant)"' /tmp/handoff-<session_id>.jsonl | cut -c1-2000 | head -20 # original task |
| 60 | grep -E '"type":"(message|function_call|user|assistant)"' /tmp/handoff-<session_id>.jsonl | cut -c1-2000 | tail -100 # final state |
| 61 | ``` |
| 62 | |
| 63 | **Gemini CLI** (single JSON document — no JSONL grep): |
| 64 | |
| 65 | ```bash |
| 66 | jq 'keys' /tmp/handoff-<session_id>.jsonl |
| 67 | ``` |
| 68 | |
| 69 | The top-level shape varies by Gemini CLI version, but messages live under one of `messages`, `contents`, `history`, or `turns`. Each entry has a `role` (`user`/`model`/`function`/`tool`) and a content payload under one of `parts[].text`, `content`, or `text`. Extract role + text in chronological order: |
| 70 | |
| 71 | ```bash |
| 72 | # Example — adapt the path based on what `jq 'keys'` showed. |
| 73 | jq -r '.messages[] | "\(.role): \([.parts[]? | .text // ""] | join(" "))"' /tmp/handoff-<session_id>.jsonl | head -20 |
| 74 | jq -r '.messages[] | "\(.role): \([.parts[]? | .text // ""] | join(" "))"' /tmp/handoff-<sess |