{"id":"d9c73e69-badd-4e54-9ffb-a0935e4fdf83","shortId":"TLqZEU","kind":"skill","title":"context-save","tagline":"Save working context. Captures git state, decisions made, and remaining work\nso any future session can pick up without losing a beat.\nUse when asked to \"save progress\", \"save state\", \"context save\", or\n\"save my work\". Pair with /context-restore to resume later.\nFormerly /checkpoi","description":"## Preamble\n\n```bash\neval \"$(~/.vibestack/bin/vibe-slug 2>/dev/null)\" 2>/dev/null || SLUG=\"unknown\"\n_LEARN_FILE=\"${VIBESTACK_HOME:-$HOME/.vibestack}/projects/${SLUG:-unknown}/learnings.jsonl\"\nif [ -f \"$_LEARN_FILE\" ]; then\n  _LEARN_COUNT=$(wc -l < \"$_LEARN_FILE\" 2>/dev/null | tr -d ' ')\n  echo \"LEARNINGS: $_LEARN_COUNT entries loaded\"\n  if [ \"$_LEARN_COUNT\" -gt 5 ] 2>/dev/null; then\n    ~/.vibestack/bin/vibe-learnings-search --limit 5 2>/dev/null || true\n  fi\nelse\n  echo \"LEARNINGS: none yet\"\nfi\n```\n\n# /context-save — Save Working Context\n\nYou are a **Staff Engineer who keeps meticulous session notes**. Your job is to\ncapture the full working context — what's being done, what decisions were made,\nwhat's left — so that any future session (even on a different branch or workspace)\ncan resume without losing a beat via `/context-restore`.\n\n**HARD GATE:** Do NOT implement code changes. This skill captures state only.\n\n---\n\n## Detect command\n\nParse the user's input to determine the mode:\n\n- `/context-save` or `/context-save <title>` → **Save**\n- `/context-save list` → **List**\n\nIf the user provides a title after the command (e.g., `/context-save auth refactor`),\nuse it as the title. Otherwise, infer a title from the current work.\n\nIf the user types `/context-save resume` or `/context-save restore`, tell them:\n\"Use `/context-restore` instead — save and restore are separate skills now.\"\n\n---\n\n## Save flow\n\n### Step 1: Gather state\n\n```bash\neval \"$(~/.vibestack/bin/vibe-slug 2>/dev/null)\" && mkdir -p ~/.vibestack/projects/$SLUG\n```\n\nCollect the current working state:\n\n```bash\necho \"=== BRANCH ===\"\ngit rev-parse --abbrev-ref HEAD 2>/dev/null\necho \"=== STATUS ===\"\ngit status --short 2>/dev/null\necho \"=== DIFF STAT ===\"\ngit diff --stat 2>/dev/null\necho \"=== STAGED DIFF STAT ===\"\ngit diff --cached --stat 2>/dev/null\necho \"=== RECENT LOG ===\"\ngit log --oneline -10 2>/dev/null\n```\n\n### Step 2: Summarize context\n\nUsing the gathered state plus your conversation history, produce a summary covering:\n\n1. **What's being worked on** — the high-level goal or feature\n2. **Decisions made** — architectural choices, trade-offs, approaches chosen and why\n3. **Remaining work** — concrete next steps, in priority order\n4. **Notes** — anything a future session needs to know (gotchas, blocked items,\n   open questions, things that were tried and didn't work)\n\nIf the user provided a title, use it. Otherwise, infer a concise title (3-6 words)\nfrom the work being done.\n\n### Step 3: Compute session duration\n\nTry to determine how long this session has been active:\n\n```bash\nif [ -n \"$_TEL_START\" ]; then\n  START_EPOCH=\"$_TEL_START\"\nelif [ -n \"$PPID\" ]; then\n  START_EPOCH=$(ps -o lstart= -p $PPID 2>/dev/null | xargs -I{} date -jf \"%c\" \"{}\" \"+%s\" 2>/dev/null || echo \"\")\nfi\nif [ -n \"$START_EPOCH\" ]; then\n  NOW=$(date +%s)\n  DURATION=$((NOW - START_EPOCH))\n  echo \"SESSION_DURATION_S=$DURATION\"\nelse\n  echo \"SESSION_DURATION_S=unknown\"\nfi\n```\n\nIf the duration cannot be determined, omit the `session_duration_s` field from the\nsaved file.\n\n### Step 4: Write saved-context file\n\nCompute the path in bash (NOT in the LLM prompt) so user-supplied titles can't\ninject shell metacharacters into any subsequent command. The sanitizer is an\nallowlist: only `a-z 0-9 - .` survive.\n\n```bash\neval \"$(~/.vibestack/bin/vibe-slug 2>/dev/null)\" && mkdir -p ~/.vibestack/projects/$SLUG\nCHECKPOINT_DIR=\"${VIBESTACK_HOME:-$HOME/.vibestack}/projects/$SLUG/checkpoints\"\nmkdir -p \"$CHECKPOINT_DIR\"\nTIMESTAMP=$(date +%Y%m%d-%H%M%S)\n# Bash-side title sanitize. Pass the raw title as $1 when running this block.\n# Example: TITLE_RAW=\"wintermute progress\" bash -c '...'\nRAW=\"${TITLE_RAW:-untitled}\"\n# Lowercase, collapse whitespace to hyphens, strip to allowlist, cap length.\nTITLE_SLUG=$(printf '%s' \"$RAW\" | tr '[:upper:]' '[:lower:]' | tr -s ' \\t' '-' | tr -cd 'a-z0-9.-' | cut -c1-60)\nTITLE_SLUG=\"${TITLE_SLUG:-untitled}\"\n# Collision-safe filename: if ${TIMESTAMP}-${SLUG}.md already exists (same-second\n# double save with same title), append a short random suffix. Filenames are\n# append-only — never overwrite.\nFILE=\"${CHECKPOINT_DIR}/${TIMESTAMP}-${TITLE_SLUG}.md\"\nif [ -e \"$FILE\" ]; then\n  SUFFIX=$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom 2>/dev/null | head -c 4 || printf '%04x' \"$$\")\n  FILE=\"${CHECKPOINT_DIR}/${TIMESTAMP}-${TITLE_SLUG}-${SUFFIX}.md\"\nfi\necho \"CHECKPOINT_DIR=$CHECKPOINT_DIR\"\necho \"TIMESTAMP=$TIMESTAMP\"\necho \"FILE=$FILE\"\n```\n\nThe on-disk directory name is `checkpoints/` (not `contexts/`) — this is a legacy\npath kept so existing saved files remain loadable. Users never see it.\n\nWrite the file to the `$FILE` path printed above (use the exact string — do not\nreconstruct it in the LLM layer).\n\nThe file format:\n\n```markdown\n---\nstatus: in-progress\nbranch: {current branch name}\ntimestamp: {ISO-8601 timestamp, e.g. 2026-04-18T14:30:00-07:00}\nsession_duration_s: {computed duration, omit if unknown}\nfiles_modified:\n  - path/to/file1\n  - path/to/file2\n---\n\n## Working on: {title}\n\n### Summary\n\n{1-3 sentences describing the high-level goal and current progress}\n\n### Decisions Made\n\n{Bulleted list of architectural choices, trade-offs, and reasoning}\n\n### Remaining Work\n\n{Numbered list of concrete next steps, in priority order}\n\n### Notes\n\n{Gotchas, blocked items, open questions, things tried that didn't work}\n```\n\nThe `files_modified` list comes from `git status --short` (both staged and unstaged\nmodified files). Use relative paths from the repo root.\n\nAfter writing, confirm to the user:\n\n```\nCONTEXT SAVED\n════════════════════════════════════════\nTitle:    {title}\nBranch:   {branch}\nFile:     {path to saved file}\nModified: {N} files\nDuration: {duration or \"unknown\"}\n════════════════════════════════════════\n\nRestore later with /context-restore.\n```\n\n---\n\n## List flow\n\n### Step 1: Gather saved contexts\n\n```bash\neval \"$(~/.vibestack/bin/vibe-slug 2>/dev/null)\" && mkdir -p ~/.vibestack/projects/$SLUG\nCHECKPOINT_DIR=\"${VIBESTACK_HOME:-$HOME/.vibestack}/projects/$SLUG/checkpoints\"\nif [ -d \"$CHECKPOINT_DIR\" ]; then\n  echo \"CHECKPOINT_DIR=$CHECKPOINT_DIR\"\n  # Use find + sort instead of ls -1t: filename YYYYMMDD-HHMMSS prefix is the\n  # canonical order (stable across copies/rsync; mtime is not), and empty-result\n  # behavior is clean (no files → no output, no \"lists cwd\" fallback).\n  find \"$CHECKPOINT_DIR\" -maxdepth 1 -name \"*.md\" -type f 2>/dev/null | sort -r\nelse\n  echo \"NO_CHECKPOINTS\"\nfi\n```\n\n### Step 2: Display table\n\n**Default behavior:** Show saved contexts for the **current branch** only.\n\nIf the user passes `--all` (e.g., `/context-save list --all`), show contexts\nfrom **all branches**.\n\nRead the frontmatter of each file to extract `status`, `branch`, and\n`timestamp`. Parse the title from the filename (the part after the timestamp).\n\nPresent as a table:\n\n```\nSAVED CONTEXTS ({branch} branch)\n════════════════════════════════════════\n#  Date        Title                    Status\n─  ──────────  ───────────────────────  ───────────\n1  2026-04-18  auth-refactor            in-progress\n2  2026-04-17  api-pagination           completed\n3  2026-04-15  db-migration-setup       in-progress\n════════════════════════════════════════\n```\n\nIf `--all` is used, add a Branch column:\n\n```\nSAVED CONTEXTS (all branches)\n════════════════════════════════════════\n#  Date        Title                    Branch              Status\n─  ──────────  ───────────────────────  ──────────────────  ───────────\n1  2026-04-18  auth-refactor            feat/auth           in-progress\n2  2026-04-17  api-pagination           main                completed\n3  2026-04-15  db-migration-setup       feat/db-migration   in-progress\n════════════════════════════════════════\n```\n\nIf there are no saved contexts, tell the user: \"No saved contexts yet. Run\n`/context-save` to save your current working state.\"\n\n---\n\n## Important Rules\n\n- **Never modify code.** This skill only reads state and writes the context file.\n- **Always include the branch name** in frontmatter — critical for cross-branch\n  `/context-restore`.\n- **Saved files are append-only.** Never overwrite or delete existing files. Each\n  save creates a new file.\n- **Infer, don't interrogate.** Use git state and conversation context to fill in\n  the file. Only use AskUserQuestion if the title genuinely cannot be inferred.\n- **This is a vibestack skill, not a Claude Code built-in.** When the user types\n  `/context-save`, invoke this skill via the Skill tool. The old `/checkpoint`\n  name collided with Claude Code's native `/rewind` alias — the rename fixed that.","tags":["context","save","vibestack","timurgaleev","agent-skills","ai-agents","claude-code","cursor-ide","developer-tools","kiro","mcp","prompt-engineering"],"capabilities":["skill","source-timurgaleev","skill-context-save","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-cursor-ide","topic-developer-tools","topic-kiro","topic-mcp","topic-prompt-engineering","topic-slash-commands"],"categories":["vibestack"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/timurgaleev/vibestack/context-save","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add timurgaleev/vibestack","source_repo":"https://github.com/timurgaleev/vibestack","install_from":"skills.sh"}},"qualityScore":"0.457","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 15 github stars · SKILL.md body (8,541 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:06:20.207Z","embedding":null,"createdAt":"2026-05-18T19:06:20.207Z","updatedAt":"2026-05-18T19:06:20.207Z","lastSeenAt":"2026-05-18T19:06:20.207Z","tsv":"'-04':764,1037,1047,1055,1082,1093,1102 '-07':769 '-1':923 '-10':304 '-15':1056,1103 '-17':1048,1094 '-18':765,1038,1083 '-3':788 '-6':393 '-60':614 '-8601':760 '-9':529 '/.vibestack/bin/vibe-learnings-search':96 '/.vibestack/bin/vibe-slug':51,248,533,893 '/.vibestack/projects':253,538,898 '/checkpoi':47 '/checkpoint':1230 '/context-restore':42,162,231,883,1160 '/context-save':109,186,188,190,203,223,226,993,1126,1220 '/dev/null':53,55,79,94,100,250,272,279,287,297,306,437,445,535,673,895,965 '/dev/urandom':671 '/learnings.jsonl':66 '/projects':63,545,905 '/rewind':1238 '0':528 '00':768,770 '04x':678 '1':243,323,569,787,887,959,1035,1080 '2':52,54,78,93,99,249,271,278,286,296,305,308,336,436,444,534,672,894,964,974,1045,1091 '2026':763,1036,1046,1054,1081,1092,1101 '3':348,392,401,1053,1100 '30':767 '4':357,489,676 '5':92,98 '9':611,670 'a-z':525 'a-z0':608,667 'abbrev':268 'abbrev-ref':267 'across':935 'activ':414 'add':1068 'alia':1239 'allowlist':523,592 'alreadi':628 'alway':1148 'anyth':359 'api':1050,1096 'api-pagin':1049,1095 'append':638,646,1165 'append-on':645,1164 'approach':344 'architectur':339,804 'ask':28 'askuserquest':1196 'auth':204,1040,1085 'auth-refactor':1039,1084 'bash':49,246,260,415,499,531,560,579,891 'bash-sid':559 'beat':25,160 'behavior':944,978 'block':367,573,824 'branch':152,262,754,756,866,867,985,1000,1010,1030,1031,1070,1075,1078,1151,1159 'built':1214 'built-in':1213 'bullet':801 'c':442,580,664,675 'c1':613 'cach':294 'cannot':475,1201 'canon':932 'cap':593 'captur':7,127,172 'cd':607 'chang':169 'checkpoint':540,549,651,680,689,691,706,900,909,913,915,956,971 'choic':340,805 'chosen':345 'claud':1211,1234 'clean':946 'code':168,1137,1212,1235 'collaps':586 'collect':255 'collid':1232 'collis':621 'collision-saf':620 'column':1071 'come':838 'command':176,201,518 'complet':1052,1099 'comput':402,495,774 'concis':390 'concret':351,816 'confirm':858 'context':2,6,34,112,131,310,493,708,862,890,981,997,1029,1073,1117,1123,1146,1188 'context-sav':1 'convers':317,1187 'copies/rsync':936 'count':73,85,90 'cover':322 'creat':1175 'critic':1155 'cross':1158 'cross-branch':1157 'current':217,257,755,797,984,1130 'cut':612 'cwd':953 'd':81,555,908 'date':440,454,552,1032,1076 'db':1058,1105 'db-migration-setup':1057,1104 'dc':666 'decis':10,137,337,799 'default':977 'delet':1170 'describ':790 'detect':175 'determin':183,407,477 'didn':376,831 'diff':281,284,290,293 'differ':151 'dir':541,550,652,681,690,692,901,910,914,916,957 'directori':703 'disk':702 'display':975 'done':135,399 'doubl':633 'durat':404,456,462,464,468,474,481,772,775,876,877 'e':658 'e.g':202,762,992 'echo':82,104,261,273,280,288,298,446,460,466,688,693,696,912,969 'elif':425 'els':103,465,968 'empti':942 'empty-result':941 'engin':117 'entri':86 'epoch':422,430,451,459 'eval':50,247,532,892 'even':148 'exact':736 'exampl':574 'exist':629,716,1171 'extract':1008 'f':68,963 'fallback':954 'feat/auth':1087 'feat/db-migration':1108 'featur':335 'fi':102,108,447,471,687,972 'field':483 'file':59,70,77,487,494,650,659,679,697,698,718,727,730,747,779,835,848,868,872,875,948,1006,1147,1162,1172,1178,1193 'filenam':623,643,925,1018 'fill':1190 'find':918,955 'fix':1242 'flow':241,885 'format':748 'former':46 'frontmatt':1003,1154 'full':129 'futur':17,146,361 'gate':164 'gather':244,313,888 'genuin':1200 'git':8,263,275,283,292,301,840,1184 'goal':333,795 'gotcha':366,823 'gt':91 'h':556 'hard':163 'head':270,674 'hhmmss':928 'high':331,793 'high-level':330,792 'histori':318 'home':61,543,903 'home/.vibestack':62,544,904 'hyphen':589 'implement':167 'import':1133 'in-progress':751,1042,1061,1088,1109 'includ':1149 'infer':212,388,1179,1203 'inject':512 'input':181 'instead':232,920 'interrog':1182 'invok':1221 'iso':759 'item':368,825 'jf':441 'job':124 'keep':119 'kept':714 'know':365 'l':75 'later':45,881 'layer':745 'lc':662 'learn':58,69,72,76,83,84,89,105 'left':142 'legaci':712 'length':594 'level':332,794 'limit':97 'list':191,192,802,814,837,884,952,994 'llm':503,744 'load':87 'loadabl':720 'log':300,302 'long':409 'lose':23,158 'lower':602 'lowercas':585 'ls':922 'lstart':433 'm':554,557 'made':11,139,338,800 'main':1098 'markdown':749 'maxdepth':958 'md':627,656,686,961 'metacharact':514 'meticul':120 'migrat':1059,1106 'mkdir':251,536,547,896 'mode':185 'modifi':780,836,847,873,1136 'mtime':937 'n':417,426,449,874 'name':704,757,960,1152,1231 'nativ':1237 'need':363 'never':648,722,1135,1167 'new':1177 'next':352,817 'none':106 'note':122,358,822 'number':813 'o':432 'off':343,808 'old':1229 'omit':478,776 'on-disk':700 'onelin':303 'open':369,826 'order':356,821,933 'otherwis':211,387 'output':950 'overwrit':649,1168 'p':252,434,537,548,897 'pagin':1051,1097 'pair':40 'pars':177,266,1013 'part':1020 'pass':564,990 'path':497,713,731,851,869 'path/to/file1':781 'path/to/file2':782 'pick':20 'plus':315 'ppid':427,435 'preambl':48 'prefix':929 'present':1024 'print':732 'printf':597,677 'prioriti':355,820 'produc':319 'progress':31,578,753,798,1044,1063,1090,1111 'prompt':504 'provid':196,382 'ps':431 'question':370,827 'r':967 'random':641 'raw':566,576,581,583,599 'read':1001,1141 'reason':810 'recent':299 'reconstruct':740 'ref':269 'refactor':205,1041,1086 'relat':850 'remain':13,349,719,811 'renam':1241 'repo':854 'restor':227,235,880 'result':943 'resum':44,156,224 'rev':265 'rev-pars':264 'root':855 'rule':1134 'run':571,1125 'safe':622 'same-second':630 'sanit':520,563 'save':3,4,30,32,35,37,110,189,233,240,486,492,634,717,863,871,889,980,1028,1072,1116,1122,1128,1161,1174 'saved-context':491 'second':632 'see':723 'sentenc':789 'separ':237 'session':18,121,147,362,403,411,461,467,480,771 'setup':1060,1107 'shell':513 'short':277,640,842 'show':979,996 'side':561 'skill':171,238,1139,1208,1223,1226 'skill-context-save' 'slug':56,64,254,539,596,616,618,626,655,684,899 'slug/checkpoints':546,906 'sort':919,966 'source-timurgaleev' 'stabl':934 'staff':116 'stage':289,844 'start':419,421,424,429,450,458 'stat':282,285,291,295 'state':9,33,173,245,259,314,1132,1142,1185 'status':274,276,750,841,1009,1034,1079 'step':242,307,353,400,488,818,886,973 'string':737 'strip':590 'subsequ':517 'suffix':642,661,685 'summar':309 'summari':321,786 'suppli':508 'surviv':530 't14':766 'tabl':976,1027 'tel':418,423 'tell':228,1118 'thing':371,828 'timestamp':551,625,653,682,694,695,758,761,1012,1023 'titl':198,210,214,384,391,509,562,567,575,582,595,615,617,637,654,683,785,864,865,1015,1033,1077,1199 'tool':1227 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-cursor-ide' 'topic-developer-tools' 'topic-kiro' 'topic-mcp' 'topic-prompt-engineering' 'topic-slash-commands' 'tr':80,600,603,606,665 'trade':342,807 'trade-off':341,806 'tri':374,405,829 'true':101 'type':222,962,1219 'unknown':57,65,470,778,879 'unstag':846 'untitl':584,619 'upper':601 'use':26,206,230,311,385,734,849,917,1067,1183,1195 'user':179,195,221,381,507,721,861,989,1120,1218 'user-suppli':506 'via':161,1224 'vibestack':60,542,902,1207 'wc':74 'whitespac':587 'wintermut':577 'without':22,157 'word':394 'work':5,14,39,111,130,218,258,327,350,378,397,783,812,833,1131 'workspac':154 'write':490,725,857,1144 'xarg':438 'y':553 'yet':107,1124 'yyyymmdd':927 'yyyymmdd-hhmmss':926 'z':527 'z0':610,669","prices":[{"id":"6b9fbee5-d9ef-4efc-8056-3c1770e55f98","listingId":"d9c73e69-badd-4e54-9ffb-a0935e4fdf83","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"timurgaleev","category":"vibestack","install_from":"skills.sh"},"createdAt":"2026-05-18T19:06:20.207Z"}],"sources":[{"listingId":"d9c73e69-badd-4e54-9ffb-a0935e4fdf83","source":"github","sourceId":"timurgaleev/vibestack/context-save","sourceUrl":"https://github.com/timurgaleev/vibestack/tree/main/skills/context-save","isPrimary":false,"firstSeenAt":"2026-05-18T19:06:20.207Z","lastSeenAt":"2026-05-18T19:06:20.207Z"}],"details":{"listingId":"d9c73e69-badd-4e54-9ffb-a0935e4fdf83","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"timurgaleev","slug":"context-save","github":{"repo":"timurgaleev/vibestack","stars":15,"topics":["agent-skills","ai-agents","claude-code","cursor-ide","developer-tools","kiro","mcp","prompt-engineering","slash-commands"],"license":"mit","html_url":"https://github.com/timurgaleev/vibestack","pushed_at":"2026-05-18T18:19:05Z","description":"vibestack is a portable skill pack for AI coding agents. Slash commands like /office-hours, /ship, /investigate, /tdd, /review install once and work across every agent that supports the Agent Skills open standard — Claude Code, Cursor, Kiro, and a growing list of others. ","skill_md_sha":"b7c606b44e05f308617955bba40cd8d1e313aabc","skill_md_path":"skills/context-save/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/timurgaleev/vibestack/tree/main/skills/context-save"},"layout":"multi","source":"github","category":"vibestack","frontmatter":{"name":"context-save","description":"Save working context. Captures git state, decisions made, and remaining work\nso any future session can pick up without losing a beat.\nUse when asked to \"save progress\", \"save state\", \"context save\", or\n\"save my work\". Pair with /context-restore to resume later.\nFormerly /checkpoint — renamed because Claude Code treats /checkpoint as a\nnative rewind alias in current environments, which was shadowing this skill."},"skills_sh_url":"https://skills.sh/timurgaleev/vibestack/context-save"},"updatedAt":"2026-05-18T19:06:20.207Z"}}