Handoff Creates comprehensive handoff documents that enable fresh AI agents to seamlessly continue work with zero ambiguity. Solves the long-running agent context exhaustion problem. Mode Selection Determine which mode applies: Creating a handoff? User wants to save current state, pause work, or context is getting full. - Follow: CREATE Workflow below Resuming from a handoff? User wants to continue previous work, load context, or mentions an existing handoff. - Follow: RESUME Workflow below Proactive suggestion? After substantial work (5+ file edits, complex debugging, major decisions), sugge…

, content, re.MULTILINE)\n title = match.group(1).strip() if match else filepath.stem\n except Exception:\n title = filepath.stem\n\n # Parse date from filename\n date_match = re.match(r'(\\d{4}-\\d{2}-\\d{2})-(\\d{6})', filepath.name)\n if date_match:\n try:\n date = datetime.strptime(\n f\"{date_match.group(1)} {date_match.group(2)}\",\n \"%Y-%m-%d %H%M%S\"\n )\n except ValueError:\n date = None\n else:\n date = None\n\n handoffs.append({\n \"filename\": filepath.name,\n \"path\": str(filepath),\n \"title\": title,\n \"date\": date,\n })\n\n # Sort by date, most recent first\n handoffs.sort(key=lambda x: x[\"date\"] or datetime.min, reverse=True)\n return handoffs\n\n\ndef get_previous_handoff_info(project_path: str, continues_from: str = None) -> dict:\n \"\"\"Get information about the previous handoff for chaining.\"\"\"\n handoffs = find_previous_handoffs(project_path)\n\n if continues_from:\n # Find specific handoff\n for h in handoffs:\n if continues_from in h[\"filename\"]:\n return {\n \"exists\": True,\n \"filename\": h[\"filename\"],\n \"title\": h[\"title\"],\n }\n return {\"exists\": False, \"filename\": continues_from, \"title\": \"Not found\"}\n\n elif handoffs:\n # Suggest most recent\n most_recent = handoffs[0]\n return {\n \"exists\": True,\n \"filename\": most_recent[\"filename\"],\n \"title\": most_recent[\"title\"],\n \"suggested\": True,\n }\n\n return {\"exists\": False}\n\n\ndef generate_handoff(\n project_path: str,\n slug: str = None,\n continues_from: str = None\n) -> str:\n \"\"\"Generate a handoff document with pre-filled metadata.\"\"\"\n\n # Generate timestamp and filename\n now = datetime.now()\n timestamp = now.strftime(\"%Y-%m-%d %H:%M:%S\")\n file_timestamp = now.strftime(\"%Y-%m-%d-%H%M%S\")\n\n if not slug:\n slug = \"handoff\"\n\n # Sanitize slug\n slug = slug.lower().replace(\" \", \"-\").replace(\"_\", \"-\")\n slug = \"\".join(c for c in slug if c.isalnum() or c == \"-\")\n\n filename = f\"{file_timestamp}-{slug}.md\"\n\n # Create handoffs directory\n handoffs_dir = Path(project_path) / \".claude\" / \"handoffs\"\n handoffs_dir.mkdir(parents=True, exist_ok=True)\n\n filepath = handoffs_dir / filename\n\n # Gather git info\n git_info = get_git_info(project_path)\n\n # Get previous handoff info for chaining\n prev_handoff = get_previous_handoff_info(project_path, continues_from)\n\n # Build pre-filled sections\n branch_line = git_info[\"branch\"] if git_info[\"branch\"] else \"[not a git repo or detached HEAD]\"\n\n # Recent commits section\n if git_info[\"recent_commits\"]:\n commits_section = \"\\n\".join(f\" - {c}\" for c in git_info[\"recent_commits\"])\n else:\n commits_section = \" - [no recent commits or not a git repo]\"\n\n # Modified files section\n all_modified = list(set(git_info[\"modified_files\"] + git_info[\"staged_files\"]))\n if all_modified:\n modified_section = \"\\n\".join(f\"| {f} | [describe changes] | [why changed] |\" for f in all_modified[:10])\n if len(all_modified) > 10:\n modified_section += f\"\\n| ... and {len(all_modified) - 10} more files | | |\"\n else:\n modified_section = \"| [no modified files detected] | | |\"\n\n # Handoff chain section\n if prev_handoff.get(\"exists\"):\n chain_section = f\"\"\"## Handoff Chain\n\n- **Continues from**: [{prev_handoff['filename']}](./{prev_handoff['filename']})\n - Previous title: {prev_handoff.get('title', 'Unknown')}\n- **Supersedes**: [list any older handoffs this replaces, or \"None\"]\n\n> Review the previous handoff for full context before filling this one.\"\"\"\n else:\n chain_section = \"\"\"## Handoff Chain\n\n- **Continues from**: None (fresh start)\n- **Supersedes**: None\n\n> This is the first handoff for this task.\"\"\"\n\n # Generate the document\n content = f\"\"\"# Handoff: [TASK_TITLE - replace this]\n\n## Session Metadata\n- Created: {timestamp}\n- Project: {project_path}\n- Branch: {branch_line}\n- Session duration: [estimate how long you worked]\n\n### Recent Commits (for context)\n{commits_section}\n\n{chain_section}\n\n## Current State Summary\n\n[TODO: Write one paragraph describing what was being worked on, current status, and where things left off]\n\n## Codebase Understanding\n\n### Architecture Overview\n\n[TODO: Document key architectural insights discovered during this session]\n\n### Critical Files\n\n| File | Purpose | Relevance |\n|------|---------|-----------|\n| [TODO: Add critical files] | | |\n\n### Key Patterns Discovered\n\n[TODO: Document important patterns, conventions, or idioms found in this codebase]\n\n## Work Completed\n\n### Tasks Finished\n\n- [ ] [TODO: List completed tasks]\n\n### Files Modified\n\n| File | Changes | Rationale |\n|------|---------|-----------|\n{modified_section}\n\n### Decisions Made\n\n| Decision | Options Considered | Rationale |\n|----------|-------------------|-----------|\n| [TODO: Document key decisions] | | |\n\n## Pending Work\n\n### Immediate Next Steps\n\n1. [TODO: Most critical next action]\n2. [TODO: Second priority]\n3. [TODO: Third priority]\n\n### Blockers/Open Questions\n\n- [ ] [TODO: List any blockers or open questions]\n\n### Deferred Items\n\n- [TODO: Items deferred and why]\n\n## Context for Resuming Agent\n\n### Important Context\n\n[TODO: This is the MOST IMPORTANT section - write critical information the next agent MUST know]\n\n### Assumptions Made\n\n- [TODO: List assumptions made during this session]\n\n### Potential Gotchas\n\n- [TODO: Document things that might trip up a new agent]\n\n## Environment State\n\n### Tools/Services Used\n\n- [TODO: List relevant tools and their configuration]\n\n### Active Processes\n\n- [TODO: Note any running processes, servers, etc.]\n\n### Environment Variables\n\n- [TODO: List relevant env var NAMES only - NEVER include actual values/secrets]\n\n## Related Resources\n\n- [TODO: Add links to relevant docs and files]\n\n---\n\n**Security Reminder**: Before finalizing, run `validate_handoff.py` to check for accidental secret exposure.\n\"\"\"\n\n # Write the file\n filepath.write_text(content)\n\n return str(filepath)\n\n\ndef main():\n parser = argparse.ArgumentParser(\n description=\"Create a new handoff document with smart scaffolding\"\n )\n parser.add_argument(\n \"slug\",\n nargs=\"?\",\n default=None,\n help=\"Short identifier for the handoff (e.g., 'implementing-auth')\"\n )\n parser.add_argument(\n \"--continues-from\",\n dest=\"continues_from\",\n help=\"Filename of previous handoff this continues from\"\n )\n\n args = parser.parse_args()\n\n # Get project path (current working directory)\n project_path = os.getcwd()\n\n # Check for existing handoffs to suggest chaining\n if not args.continues_from:\n prev_handoffs = find_previous_handoffs(project_path)\n if prev_handoffs:\n print(f\"Found {len(prev_handoffs)} existing handoff(s).\")\n print(f\"Most recent: {prev_handoffs[0]['filename']}\")\n print(f\"Use --continues-from \u003cfilename> to link handoffs.\\n\")\n\n # Generate handoff\n filepath = generate_handoff(project_path, args.slug, args.continues_from)\n\n print(f\"Created handoff document: {filepath}\")\n print(f\"\\nNext steps:\")\n print(f\"1. Open {filepath}\")\n print(f\"2. Replace [TODO: ...] placeholders with actual content\")\n print(f\"3. Focus especially on 'Important Context' and 'Immediate Next Steps'\")\n print(f\"4. Run: python validate_handoff.py {filepath}\")\n print(f\" (Checks for completeness and accidental secrets)\")\n\n return filepath\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":10666,"content_sha256":"566794a9bfbafc60a9f26fc95e061bfc6158fabfd1f31e4ad2025a1a37992217"},{"filename":"scripts/list_handoffs.py","content":"#!/usr/bin/env python3\n\"\"\"\nList available handoff documents in the current project.\n\nSearches for handoff documents in .claude/handoffs/ and displays:\n- Filename with date\n- Title extracted from document\n- Status (if marked complete)\n\nUsage:\n python list_handoffs.py # List handoffs in current project\n python list_handoffs.py /path # List handoffs in specified path\n\"\"\"\n\nimport os\nimport re\nimport sys\nfrom datetime import datetime\nfrom pathlib import Path\n\n\ndef extract_title(filepath: Path) -> str:\n \"\"\"Extract the title from a handoff document.\"\"\"\n try:\n content = filepath.read_text()\n # Look for first H1 header\n match = re.search(r'^#\\s+(?:Handoff:\\s*)?(.+)

Handoff Creates comprehensive handoff documents that enable fresh AI agents to seamlessly continue work with zero ambiguity. Solves the long-running agent context exhaustion problem. Mode Selection Determine which mode applies: Creating a handoff? User wants to save current state, pause work, or context is getting full. - Follow: CREATE Workflow below Resuming from a handoff? User wants to continue previous work, load context, or mentions an existing handoff. - Follow: RESUME Workflow below Proactive suggestion? After substantial work (5+ file edits, complex debugging, major decisions), sugge…

, content, re.MULTILINE)\n if match:\n title = match.group(1).strip()\n # Clean up placeholder text\n if title.startswith(\"[\") and title.endswith(\"]\"):\n return \"[Untitled - needs completion]\"\n return title[:50] + \"...\" if len(title) > 50 else title\n except Exception:\n pass\n return \"[Unable to read title]\"\n\n\ndef check_completion_status(filepath: Path) -> str:\n \"\"\"Check if handoff appears complete or has TODOs remaining.\"\"\"\n try:\n content = filepath.read_text()\n todo_count = content.count(\"[TODO:\")\n if todo_count == 0:\n return \"Complete\"\n elif todo_count \u003c= 3:\n return f\"In Progress ({todo_count} TODOs)\"\n else:\n return f\"Needs Work ({todo_count} TODOs)\"\n except Exception:\n return \"Unknown\"\n\n\ndef parse_date_from_filename(filename: str) -> datetime | None:\n \"\"\"Extract date from filename like 2024-01-15-143022-slug.md\"\"\"\n match = re.match(r'(\\d{4}-\\d{2}-\\d{2})-(\\d{6})', filename)\n if match:\n try:\n date_str = match.group(1)\n time_str = match.group(2)\n return datetime.strptime(f\"{date_str} {time_str}\", \"%Y-%m-%d %H%M%S\")\n except ValueError:\n pass\n return None\n\n\ndef list_handoffs(project_path: str) -> list[dict]:\n \"\"\"List all handoff documents in a project.\"\"\"\n handoffs_dir = Path(project_path) / \".claude\" / \"handoffs\"\n\n if not handoffs_dir.exists():\n return []\n\n handoffs = []\n for filepath in handoffs_dir.glob(\"*.md\"):\n parsed_date = parse_date_from_filename(filepath.name)\n handoffs.append({\n \"path\": str(filepath),\n \"filename\": filepath.name,\n \"title\": extract_title(filepath),\n \"status\": check_completion_status(filepath),\n \"date\": parsed_date,\n \"size\": filepath.stat().st_size,\n })\n\n # Sort by date, most recent first\n handoffs.sort(key=lambda x: x[\"date\"] or datetime.min, reverse=True)\n\n return handoffs\n\n\ndef format_date(dt: datetime | None) -> str:\n \"\"\"Format datetime for display.\"\"\"\n if dt is None:\n return \"Unknown date\"\n return dt.strftime(\"%Y-%m-%d %H:%M\")\n\n\ndef main():\n # Get project path\n project_path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()\n\n handoffs = list_handoffs(project_path)\n\n if not handoffs:\n print(f\"No handoffs found in {project_path}/.claude/handoffs/\")\n print(\"\\nTo create a handoff, run: python create_handoff.py [task-slug]\")\n return\n\n print(f\"Found {len(handoffs)} handoff(s) in {project_path}/.claude/handoffs/\\n\")\n print(\"-\" * 80)\n\n for h in handoffs:\n print(f\" Date: {format_date(h['date'])}\")\n print(f\" Title: {h['title']}\")\n print(f\" Status: {h['status']}\")\n print(f\" File: {h['filename']}\")\n print(\"-\" * 80)\n\n print(f\"\\nTo resume from a handoff, read the document and follow the resume checklist.\")\n print(f\"Most recent: {handoffs[0]['path']}\")\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":3813,"content_sha256":"69485ec8a25ba7795e590e96b84534d986086a769932342efb34e86a25de33f8"},{"filename":"scripts/validate_handoff.py","content":"#!/usr/bin/env python3\n\"\"\"\nValidate a handoff document for completeness and quality.\n\nChecks:\n- No TODO placeholders remaining\n- Required sections present and populated\n- No potential secrets detected\n- Referenced files exist\n- Quality scoring\n\nUsage:\n python validate_handoff.py \u003chandoff-file>\n python validate_handoff.py .claude/handoffs/2024-01-15-143022-auth.md\n\"\"\"\n\nimport os\nimport re\nimport sys\nfrom pathlib import Path\n\n# Secret detection patterns\nSECRET_PATTERNS = [\n (r'[\"\\']?[a-zA-Z_]*api[_-]?key[\"\\']?\\s*[:=]\\s*[\"\\'][^\"\\']{10,}[\"\\']', \"API key\"),\n (r'[\"\\']?[a-zA-Z_]*password[\"\\']?\\s*[:=]\\s*[\"\\'][^\"\\']+[\"\\']', \"Password\"),\n (r'[\"\\']?[a-zA-Z_]*secret[\"\\']?\\s*[:=]\\s*[\"\\'][^\"\\']{10,}[\"\\']', \"Secret\"),\n (r'[\"\\']?[a-zA-Z_]*token[\"\\']?\\s*[:=]\\s*[\"\\'][^\"\\']{20,}[\"\\']', \"Token\"),\n (r'[\"\\']?[a-zA-Z_]*private[_-]?key[\"\\']?\\s*[:=]', \"Private key\"),\n (r'-----BEGIN [A-Z]+ PRIVATE KEY-----', \"PEM private key\"),\n (r'mongodb(\\+srv)?://[^/\\s]+:[^@\\s]+@', \"MongoDB connection string with password\"),\n (r'postgres://[^/\\s]+:[^@\\s]+@', \"PostgreSQL connection string with password\"),\n (r'mysql://[^/\\s]+:[^@\\s]+@', \"MySQL connection string with password\"),\n (r'Bearer\\s+[a-zA-Z0-9_\\-\\.]+', \"Bearer token\"),\n (r'ghp_[a-zA-Z0-9]{36}', \"GitHub personal access token\"),\n (r'sk-[a-zA-Z0-9]{48}', \"OpenAI API key\"),\n (r'xox[baprs]-[a-zA-Z0-9-]+', \"Slack token\"),\n]\n\n# Required sections for a complete handoff\nREQUIRED_SECTIONS = [\n \"Current State Summary\",\n \"Important Context\",\n \"Immediate Next Steps\",\n]\n\n# Recommended sections\nRECOMMENDED_SECTIONS = [\n \"Architecture Overview\",\n \"Critical Files\",\n \"Files Modified\",\n \"Decisions Made\",\n \"Assumptions Made\",\n \"Potential Gotchas\",\n]\n\n\ndef check_todos(content: str) -> tuple[bool, list[str]]:\n \"\"\"Check for remaining TODO placeholders.\"\"\"\n todos = re.findall(r'\\[TODO:[^\\]]*\\]', content)\n return len(todos) == 0, todos\n\n\ndef check_required_sections(content: str) -> tuple[bool, list[str]]:\n \"\"\"Check that required sections exist and have content.\"\"\"\n missing = []\n for section in REQUIRED_SECTIONS:\n # Look for section header\n pattern = rf'(?:^|\\n)##?\\s*{re.escape(section)}'\n match = re.search(pattern, content, re.IGNORECASE)\n if not match:\n missing.append(f\"{section} (missing)\")\n else:\n # Check if section has meaningful content (not just placeholder)\n section_start = match.end()\n next_section = re.search(r'\\n##?\\s+', content[section_start:])\n section_end = section_start + next_section.start() if next_section else len(content)\n section_content = content[section_start:section_end].strip()\n\n # 50 chars minimum: roughly 1-2 sentences, enough to convey meaningful context\n if len(section_content) \u003c 50 or '[TODO' in section_content:\n missing.append(f\"{section} (incomplete)\")\n\n return len(missing) == 0, missing\n\n\ndef check_recommended_sections(content: str) -> list[str]:\n \"\"\"Check which recommended sections are missing.\"\"\"\n missing = []\n for section in RECOMMENDED_SECTIONS:\n pattern = rf'(?:^|\\n)##?\\s*{re.escape(section)}'\n if not re.search(pattern, content, re.IGNORECASE):\n missing.append(section)\n return missing\n\n\ndef scan_for_secrets(content: str) -> list[tuple[str, str]]:\n \"\"\"Scan content for potential secrets.\"\"\"\n findings = []\n for pattern, description in SECRET_PATTERNS:\n matches = re.findall(pattern, content, re.IGNORECASE)\n if matches:\n findings.append((description, f\"Found {len(matches)} potential match(es)\"))\n return findings\n\n\ndef check_file_references(content: str, base_path: str) -> tuple[list[str], list[str]]:\n \"\"\"Check if referenced files exist.\"\"\"\n # Extract file paths from content (look for common patterns)\n # Pattern 1: | path/to/file | in tables\n # Pattern 2: `path/to/file` in code\n # Pattern 3: path/to/file:123 with line numbers\n\n patterns = [\n r'\\|\\s*([a-zA-Z0-9_\\-./]+\\.[a-zA-Z]+)\\s*\\|', # Table cells\n r'`([a-zA-Z0-9_\\-./]+\\.[a-zA-Z]+(?::\\d+)?)`', # Inline code\n r'(?:^|\\s)([a-zA-Z0-9_\\-./]+\\.[a-zA-Z]+:\\d+)', # With line numbers\n ]\n\n found_files = set()\n for pattern in patterns:\n matches = re.findall(pattern, content)\n for match in matches:\n # Remove line numbers\n filepath = match.split(':')[0]\n # Skip obvious non-files\n if filepath and not filepath.startswith('http') and '/' in filepath:\n found_files.add(filepath)\n\n existing = []\n missing = []\n\n for filepath in found_files:\n full_path = Path(base_path) / filepath\n if full_path.exists():\n existing.append(filepath)\n else:\n missing.append(filepath)\n\n return existing, missing\n\n\ndef calculate_quality_score(\n todos_clear: bool,\n required_complete: bool,\n missing_required: list,\n missing_recommended: list,\n secrets_found: list,\n files_missing: list\n) -> tuple[int, str]:\n \"\"\"Calculate overall quality score (0-100).\n\n Scoring rationale:\n - Start at 100, deduct for issues\n - TODOs remaining (-30): Indicates incomplete work, major blocker\n - Missing required sections (-10 each): Core context gaps\n - Secrets detected (-20): Security risk, must be fixed\n - Missing file refs (-5 each, max -20): Stale references\n - Missing recommended (-2 each): Nice-to-have completeness\n \"\"\"\n score = 100\n\n # Deductions with justifications\n if not todos_clear:\n # -30: TODOs indicate unfinished work; next agent will lack critical info\n score -= 30\n if not required_complete:\n # -10 per section: Required sections are essential for handoff continuity\n score -= 10 * len(missing_required)\n if secrets_found:\n # -20: Security risk; handoffs may be shared or stored in repos\n score -= 20\n if files_missing:\n # -5 per file (max 4): Indicates stale refs; cap at -20 to avoid over-penalizing\n score -= 5 * min(len(files_missing), 4)\n\n # -2 per section: Recommended but not critical; minor impact on handoff quality\n score -= 2 * len(missing_recommended)\n\n score = max(0, score)\n\n # Rating thresholds based on handoff usability:\n # 90+: Comprehensive, ready to use immediately\n # 70-89: Usable with minor gaps\n # 50-69: Needs work before reliable handoff\n # \u003c50: Too incomplete to be useful\n if score >= 90:\n rating = \"Excellent - Ready for handoff\"\n elif score >= 70:\n rating = \"Good - Minor improvements suggested\"\n elif score >= 50:\n rating = \"Fair - Needs attention before handoff\"\n else:\n rating = \"Poor - Significant work needed\"\n\n return score, rating\n\n\ndef validate_handoff(filepath: str) -> dict:\n \"\"\"Run all validations on a handoff file.\"\"\"\n path = Path(filepath)\n\n if not path.exists():\n return {\"error\": f\"File not found: {filepath}\"}\n\n content = path.read_text()\n base_path = path.parent.parent.parent # Go up from .claude/handoffs/\n\n # Run checks\n todos_clear, remaining_todos = check_todos(content)\n required_complete, missing_required = check_required_sections(content)\n missing_recommended = check_recommended_sections(content)\n secrets_found = scan_for_secrets(content)\n existing_files, missing_files = check_file_references(content, str(base_path))\n\n # Calculate score\n score, rating = calculate_quality_score(\n todos_clear, required_complete, missing_required,\n missing_recommended, secrets_found, missing_files\n )\n\n return {\n \"filepath\": str(path),\n \"score\": score,\n \"rating\": rating,\n \"todos_clear\": todos_clear,\n \"remaining_todos\": remaining_todos[:5], # Limit output\n \"todo_count\": len(remaining_todos) if not todos_clear else 0,\n \"required_complete\": required_complete,\n \"missing_required\": missing_required,\n \"missing_recommended\": missing_recommended,\n \"secrets_found\": secrets_found,\n \"files_verified\": len(existing_files),\n \"files_missing\": missing_files[:5], # Limit output\n }\n\n\ndef print_report(result: dict):\n \"\"\"Print a formatted validation report.\"\"\"\n if \"error\" in result:\n print(f\"Error: {result['error']}\")\n return False\n\n print(f\"\\n{'='*60}\")\n print(f\"Handoff Validation Report\")\n print(f\"{'='*60}\")\n print(f\"File: {result['filepath']}\")\n print(f\"\\nQuality Score: {result['score']}/100 - {result['rating']}\")\n print(f\"{'='*60}\")\n\n # TODOs\n if result['todos_clear']:\n print(\"\\n[PASS] No TODO placeholders remaining\")\n else:\n print(f\"\\n[FAIL] {result['todo_count']} TODO placeholders found:\")\n for todo in result['remaining_todos']:\n print(f\" - {todo[:50]}...\")\n\n # Required sections\n if result['required_complete']:\n print(\"\\n[PASS] All required sections complete\")\n else:\n print(\"\\n[FAIL] Missing/incomplete required sections:\")\n for section in result['missing_required']:\n print(f\" - {section}\")\n\n # Secrets\n if not result['secrets_found']:\n print(\"\\n[PASS] No potential secrets detected\")\n else:\n print(\"\\n[WARN] Potential secrets detected:\")\n for secret_type, detail in result['secrets_found']:\n print(f\" - {secret_type}: {detail}\")\n\n # File references\n if result['files_missing']:\n print(f\"\\n[WARN] {len(result['files_missing'])} referenced file(s) not found:\")\n for f in result['files_missing']:\n print(f\" - {f}\")\n else:\n print(f\"\\n[INFO] {result['files_verified']} file reference(s) verified\")\n\n # Recommended sections\n if result['missing_recommended']:\n print(f\"\\n[INFO] Consider adding these sections:\")\n for section in result['missing_recommended']:\n print(f\" - {section}\")\n\n print(f\"\\n{'='*60}\")\n\n # Final verdict\n if result['score'] >= 70 and not result['secrets_found']:\n print(\"Verdict: READY for handoff\")\n return True\n elif result['secrets_found']:\n print(\"Verdict: BLOCKED - Remove secrets before handoff\")\n return False\n else:\n print(\"Verdict: NEEDS WORK - Complete required sections\")\n return False\n\n\ndef main():\n if len(sys.argv) \u003c 2:\n print(\"Usage: python validate_handoff.py \u003chandoff-file>\")\n print(\"Example: python validate_handoff.py .claude/handoffs/2024-01-15-auth.md\")\n sys.exit(1)\n\n filepath = sys.argv[1]\n result = validate_handoff(filepath)\n success = print_report(result)\n\n sys.exit(0 if success else 1)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":10821,"content_sha256":"e63fed866fafb7a8055c51a19e5c576bce73bc0ec474c09c9be6962f596ba677"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Handoff","type":"text"}]},{"type":"paragraph","content":[{"text":"Creates comprehensive handoff documents that enable fresh AI agents to seamlessly continue work with zero ambiguity. Solves the long-running agent context exhaustion problem.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Mode Selection","type":"text"}]},{"type":"paragraph","content":[{"text":"Determine which mode applies:","type":"text"}]},{"type":"paragraph","content":[{"text":"Creating a handoff?","type":"text","marks":[{"type":"strong"}]},{"text":" User wants to save current state, pause work, or context is getting full.","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Follow: CREATE Workflow below","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Resuming from a handoff?","type":"text","marks":[{"type":"strong"}]},{"text":" User wants to continue previous work, load context, or mentions an existing handoff.","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Follow: RESUME Workflow below","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Proactive suggestion?","type":"text","marks":[{"type":"strong"}]},{"text":" After substantial work (5+ file edits, complex debugging, major decisions), suggest:","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"\"We've made significant progress. Consider creating a handoff document to preserve this context for future sessions. Say 'create handoff' when ready.\"","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"CREATE Workflow","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Generate Scaffold","type":"text"}]},{"type":"paragraph","content":[{"text":"Run the smart scaffold script to create a pre-filled handoff document:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/create_handoff.py [task-slug]","type":"text"}]},{"type":"paragraph","content":[{"text":"Example: ","type":"text"},{"text":"python scripts/create_handoff.py implementing-user-auth","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"For continuation handoffs","type":"text","marks":[{"type":"strong"}]},{"text":" (linking to previous work):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/create_handoff.py \"auth-part-2\" --continues-from 2024-01-15-auth.md","type":"text"}]},{"type":"paragraph","content":[{"text":"The script will:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create ","type":"text"},{"text":".claude/handoffs/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory if needed","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generate timestamped filename","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Pre-fill: timestamp, project path, git branch, recent commits, modified files","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add handoff chain links if continuing from previous","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Output file path for editing","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Complete the Handoff Document","type":"text"}]},{"type":"paragraph","content":[{"text":"Open the generated file and fill in all ","type":"text"},{"text":"[TODO: ...]","type":"text","marks":[{"type":"code_inline"}]},{"text":" sections. Prioritize these sections:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Current State Summary","type":"text","marks":[{"type":"strong"}]},{"text":" - What's happening right now","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Important Context","type":"text","marks":[{"type":"strong"}]},{"text":" - Critical info the next agent MUST know","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Immediate Next Steps","type":"text","marks":[{"type":"strong"}]},{"text":" - Clear, actionable first steps","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Decisions Made","type":"text","marks":[{"type":"strong"}]},{"text":" - Choices with rationale (not just outcomes)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Use the template structure in ","type":"text"},{"text":"references/handoff-template.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/handoff-template.md","title":null}}]},{"text":" for guidance.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Validate the Handoff","type":"text"}]},{"type":"paragraph","content":[{"text":"Run the validation script to check completeness and security:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/validate_handoff.py \u003chandoff-file>","type":"text"}]},{"type":"paragraph","content":[{"text":"The validator checks:","type":"text"}]},{"type":"checkbox_list","attrs":{"id":null},"content":[{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"No ","type":"text"},{"text":"[TODO: ...]","type":"text","marks":[{"type":"code_inline"}]},{"text":" placeholders remaining","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Required sections present and populated","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"No potential secrets detected (API keys, passwords, tokens)","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Referenced files exist","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Quality score (0-100)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Do not finalize a handoff with secrets detected or score below 70.","type":"text","marks":[{"type":"strong"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4: Confirm Handoff","type":"text"}]},{"type":"paragraph","content":[{"text":"Report to user:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Handoff file location","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validation score and any warnings","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Summary of captured context","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"First action item for next session","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"RESUME Workflow","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Find Available Handoffs","type":"text"}]},{"type":"paragraph","content":[{"text":"List handoffs in the current project:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/list_handoffs.py","type":"text"}]},{"type":"paragraph","content":[{"text":"This shows all handoffs with dates, titles, and completion status.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Check Staleness","type":"text"}]},{"type":"paragraph","content":[{"text":"Before loading, check how current the handoff is:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python scripts/check_staleness.py \u003chandoff-file>","type":"text"}]},{"type":"paragraph","content":[{"text":"Staleness levels:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"FRESH","type":"text","marks":[{"type":"strong"}]},{"text":": Safe to resume - minimal changes since handoff","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"SLIGHTLY_STALE","type":"text","marks":[{"type":"strong"}]},{"text":": Review changes, then resume","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"STALE","type":"text","marks":[{"type":"strong"}]},{"text":": Verify context carefully before resuming","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"VERY_STALE","type":"text","marks":[{"type":"strong"}]},{"text":": Consider creating a fresh handoff","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"The script checks:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Time since handoff was created","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Git commits since handoff","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Files changed since handoff","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Branch divergence","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing referenced files","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Load the Handoff","type":"text"}]},{"type":"paragraph","content":[{"text":"Read the relevant handoff document completely before taking any action.","type":"text"}]},{"type":"paragraph","content":[{"text":"If handoff is part of a chain (has \"Continues from\" link), also read the linked previous handoff for full context.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4: Verify Context","type":"text"}]},{"type":"paragraph","content":[{"text":"Follow the checklist in ","type":"text"},{"text":"references/resume-checklist.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/resume-checklist.md","title":null}}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify project directory and git branch match","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check if blockers have been resolved","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validate assumptions still hold","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Review modified files for conflicts","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check environment state","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 5: Begin Work","type":"text"}]},{"type":"paragraph","content":[{"text":"Start with \"Immediate Next Steps\" item #1 from the handoff document.","type":"text"}]},{"type":"paragraph","content":[{"text":"Reference these sections as you work:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Critical Files\" for important locations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Key Patterns Discovered\" for conventions to follow","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\"Potential Gotchas\" to avoid known issues","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 6: Update or Chain Handoffs","type":"text"}]},{"type":"paragraph","content":[{"text":"As you work:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Mark completed items in \"Pending Work\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add new discoveries to relevant sections","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"For long sessions: create a new handoff with ","type":"text"},{"text":"--continues-from","type":"text","marks":[{"type":"code_inline"}]},{"text":" to chain them","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Handoff Chaining","type":"text"}]},{"type":"paragraph","content":[{"text":"For long-running projects, chain handoffs together to maintain context lineage:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"handoff-1.md (initial work)\n ↓\nhandoff-2.md --continues-from handoff-1.md\n ↓\nhandoff-3.md --continues-from handoff-2.md","type":"text"}]},{"type":"paragraph","content":[{"text":"Each handoff in the chain:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Links to its predecessor","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Can mark older handoffs as superseded","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Provides context breadcrumbs for new agents","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"When resuming from a chain, read the most recent handoff first, then reference predecessors as needed.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Storage Location","type":"text"}]},{"type":"paragraph","content":[{"text":"Handoffs are stored in: ","type":"text"},{"text":".claude/handoffs/","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Naming convention: ","type":"text"},{"text":"YYYY-MM-DD-HHMMSS-[slug].md","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Example: ","type":"text"},{"text":"2024-01-15-143022-implementing-auth.md","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Resources","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"scripts/","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Script","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Purpose","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"create_handoff.py [slug] [--continues-from \u003cfile>]","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Generate new handoff with smart scaffolding","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"list_handoffs.py [path]","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"List available handoffs in a project","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"validate_handoff.py \u003cfile>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Check completeness, quality, and security","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"check_staleness.py \u003cfile>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Assess if handoff context is still current","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"references/","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"handoff-template.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/handoff-template.md","title":null}}]},{"text":" - Complete template structure with guidance","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"resume-checklist.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/resume-checklist.md","title":null}}]},{"text":" - Verification checklist for resuming agents","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"session-handoff","author":"@skillopedia","source":{"stars":2615,"repo_name":"agent-toolkit","origin_url":"https://github.com/softaworks/agent-toolkit/blob/HEAD/skills/session-handoff/SKILL.md","repo_owner":"softaworks","body_sha256":"8964e1b846170ac9cdbaa4c3c510e3493e08917620761cbb492c46d8d3567e64","cluster_key":"a7a1e8b7bc3b4429a98711bcb8f449ccadb46bb2b298bebfaf31fc98d73b0c57","clean_bundle":{"format":"clean-skill-bundle-v1","source":"softaworks/agent-toolkit/skills/session-handoff/SKILL.md","text_bytes":76112,"source_commit":"3027f20f3181758385a1bb8c022d4041dfb4de84","skills_sh_rank":4918,"attachment_count":11,"text_attachments":11,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/session-handoff/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"general","category_label":"General"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"general","import_tag":"skills-sh-top20k-2026-11","description":"Creates comprehensive handoff documents for seamless AI agent session transfers. Triggered when: (1) user requests handoff/memory/context save, (2) context window approaches capacity, (3) major task milestone completed, (4) work session ending, (5) user says 'save state', 'create handoff', 'I need to pause', 'context is getting full', (6) resuming work with 'load handoff', 'resume from', 'continue where we left off'. Proactively suggests handoffs after substantial work (multiple file edits, complex debugging, architecture decisions). Solves long-running agent context exhaustion by enabling fresh agents to continue with zero ambiguity."}},"renderedAt":1793666380149}

Handoff Creates comprehensive handoff documents that enable fresh AI agents to seamlessly continue work with zero ambiguity. Solves the long-running agent context exhaustion problem. Mode Selection Determine which mode applies: Creating a handoff? User wants to save current state, pause work, or context is getting full. - Follow: CREATE Workflow below Resuming from a handoff? User wants to continue previous work, load context, or mentions an existing handoff. - Follow: RESUME Workflow below Proactive suggestion? After substantial work (5+ file edits, complex debugging, major decisions), sugge…