| name | handoff |
| description | Save the current session state for later resumption. Captures session progress, decisions, blockers, next actions, and memory extractions into a structured XML file. Use when the user says "handoff", "save session", "wrap up", or "end session". |
| argument-hint | [tag-name] |
| allowed-tools | Read Write Bash(git *) |
| disable-model-invocation | true |
/handoff — Save Current Session State
You are an AI assistant running inside VS Code Copilot. Your job is to save the
current chat session state to a portable, structured XML file so it can be resumed
later. Follow each step in order. Do not skip steps.
Step 0: Extract Tag Name
The user invoked this skill as /handoff [tag-name].
The tag name is the text the user typed after /handoff. It is available in the
user's message as the word(s) following the /handoff command. Extract it exactly.
Cases:
| User types | Tag name |
|---|
/handoff auth-refactor | auth-refactor |
/handoff my project | my-project (slugify: lowercase, spaces→hyphens) |
/handoff (nothing after) | Auto-generate from session topic: <topic>-YYYY-MM-DD |
Slugification rules: lowercase only, spaces and underscores → hyphens, strip
non-alphanumeric except hyphens. Pattern must match [a-z0-9][a-z0-9-]*[a-z0-9].
If no tag was given: generate a slug from the main topic of this conversation,
appended with today's date in YYYY-MM-DD format (UTC+8 timezone).
Step 1: Create Directory Structure
Run in terminal:
mkdir -p .github/skills/handoff/data/sessions
mkdir -p .github/skills/handoff/data/memory
Step 2: Capture Git State
Run these commands and remember the output for Step 3:
git branch --show-current 2>/dev/null || echo "no-git"
git status --short 2>/dev/null || echo "no-git"
git diff --staged --name-only 2>/dev/null || echo "no-git"
git log --oneline -5 2>/dev/null || echo "no-git"
Step 3: Write Handoff XML
Write a completed XML file to:
.github/skills/handoff/data/sessions/<name>.xml
Fill in ALL fields marked REQUIRED. For OPTIONAL fields, either fill them or remove
the element entirely (no empty tags). Use your full context window to extract content.
<?xml version="1.0" encoding="UTF-8"?>
<handoff version="1.0">
<session>
<name>REQUIRED: replace with session name slug</name>
<timestamp>REQUIRED: ISO-8601 with offset, e.g., 2026-05-30T21:00:00+08:00</timestamp>
<platform>vscode-copilot</platform>
<transcript_ref>sessions/REPLACE-NAME.transcript.md</transcript_ref>
</session>
<state>
<goal>REQUIRED: Primary goal of this session in one sentence</goal>
<status>REQUIRED: in_progress | completed | blocked</status>
<branch>REQUIRED: current git branch name, or "none" if no git repo</branch>
<modified_files>
</modified_files>
<todos>
</todos>
</state>
<progress>
<completed>
</completed>
<remaining>
</remaining>
<next_action>REQUIRED: exact first step</next_action>
</progress>
<decisions>
</decisions>
<blockers>
</blockers>
<gotchas>
</gotchas>
<memory_extractions>
</memory_extractions>
</handoff>
Step 4: Write Transcript
Write the conversation transcript to:
.github/skills/handoff/data/sessions/<name>.transcript.md
Template:
# Session Transcript: <name>
> Captured at: <timestamp>
> Platform: VS Code Copilot
> Note: This transcript captures context visible at /handoff time. VS Code Copilot
> summarizes early context automatically — if early conversation is absent, it was
> already summarized by the platform before this capture.
---
<Write the full conversation here. Include:
- User messages (prefix with "**User:**")
- Your responses (prefix with "**Assistant:**")
- Write as much as you can see in your current context window
- If the session started with a summary (indicating prior context was compacted),
start with: "<!-- NOTE: Session began with a context summary. Full early history not available. -->"
>
Step 5: Extract Memory
Read <memory_extractions> from the XML you just wrote.
For each <project_fact>:
- Read
.github/skills/handoff/data/memory/project-memory.xml (create if missing):
<?xml version="1.0" encoding="UTF-8"?>
<project_memory version="1.0">
</project_memory>
-
Check if a fact on the same topic already has status="active":
- If YES: mark it
status="superseded" and add superseded_by="<session-name>" attribute
- Then append new entry as
status="active"
- If NO conflict: just append new entry
-
New entry format:
<fact confidence="FILL" status="active" session="<name>" timestamp="<ISO-8601>">
FILL: the fact text
</fact>
For each <user_preference>:
Same logic, but use .github/skills/handoff/data/memory/user-memory.xml:
<?xml version="1.0" encoding="UTF-8"?>
<user_memory version="1.0">
</user_memory>
Entry format:
<preference confidence="FILL" status="active" session="<name>" timestamp="<ISO-8601>">
FILL: the preference text
</preference>
Step 6: Update Index
Read .github/skills/handoff/data/index.xml (create if missing):
<?xml version="1.0" encoding="UTF-8"?>
<index version="1.0" updated="FILL-ISO-8601">
</index>
Prepend (insert at top, inside <index>) a new entry — newest first:
<session>
<name>FILL: session name slug</name>
<timestamp>FILL: ISO-8601</timestamp>
<platform>vscode-copilot</platform>
<status>FILL: mirrors state.status from the handoff XML</status>
<goal>FILL: goal shortened to max 80 characters</goal>
<file>sessions/FILL-NAME.xml</file>
<transcript>sessions/FILL-NAME.transcript.md</transcript>
</session>
Update the updated attribute on <index> to the current timestamp.
Step 7: Show Confirmation
Render this confirmation box (fill in the actual values):
╔══════════════════════════════════════════════════════════════════╗
║ ✅ HANDOFF SAVED: <name> ║
╠══════════════════════════════════════════════════════════════════╣
║ Files written: ║
║ • .github/skills/handoff/data/sessions/<name>.xml ║
║ • .github/skills/handoff/data/sessions/<name>.transcript.md ║
║ • .github/skills/handoff/data/index.xml (updated) ║
║ Memory: <N> project facts, <M> user preferences extracted ║
╚══════════════════════════════════════════════════════════════════╝
Resume this session later with: /resume <name>
Edge Cases
- No git repo: Set
<branch>none</branch>, leave <modified_files> and todos empty.
- Name collision: If
<name>.xml already exists, append -2, -3, etc. to the name.
- No memory extractions: Skip Step 5. Note "0 project facts, 0 user preferences" in confirmation.
- Large transcript: If context window is extremely large, write a truncated transcript
and note
<!-- Transcript truncated at <N> characters to avoid file size limits -->.