handoff — 扛过上下文压缩、把你的会话串成链的技能
一个会话交接技能:把你的对话里挖出决策、失败尝试与真实数据,写成一份结构化、自我校验的简报,让新会话从你停下的地方继续——而不必重走死胡同。
一个长的编码会话,就是一个上下文窗口慢慢被填满的过程。填满时,模型会压缩自己——而压缩正是决策丢失的时刻。agent 把两小时的对话压成一份摘要,摘要丢掉的恰恰是当时看起来不重要、事后才重要的一部分:哪些尝试过又被否掉、为什么、真实数字是多少。你的下一个会话得把这些全部重新发现一遍,有时候还会把同样的死胡同重走一遍。
handoff(claude-handoff 项目)就是为这个造的。它是一对 Claude Code 技能——/handoff 与 /handoffplan——把你的会话捕捉成一份结构化、自我校验的快照,写进上下文窗口之外的一个文件里,让新会话能精确地从你停下的地方接上。 项目自己在同一个 bug、同一份代码库上的受控 A/B 测试里的说法是:从 handoff 文件恢复的会话零用户干预、能追出完整的失败调用链;而只做了压缩的会话,给出的是一个表面层的修复。
它做什么
每份 handoff 写一个固定形状的 markdown 文件:
| 小节 | 装什么 |
|---|---|
| The Goal | 在解决什么、为什么 |
| Where We Are | 15–25 条当前状态 |
| What We Tried | 每一个尝试,按时间顺序——试了什么、结果如何、为什么保留或放弃 |
| Key Decisions | 选了什么,以及否掉了什么 |
| Evidence & Data | 真实数字,不是摘要 |
| User Feedback | 偏好、纠正、语气 |
| Where We’re Going | 有序的下一步 |
| Quick Start | 下一个会话最先跑的精确命令 |
项目明确说 “What We Tried” 是最有价值的小节:失败尝试是最贵的需要重新发现的东西,而这一节就是让下一个会话不再重走它们的那一节。
文件背后的流程有五步:
-
用 12 项抽取清单挖对话——目标、尝试、失败、决策、度量、代码分析、用户偏好。
-
并行采集外部状态——
git log、git diff、未提交的改动、活动任务。 -
检测链式连续性。 它找到同一工作流里之前的 handoff,继承链标签和序号,于是 handoff 跨会话串成链:
HANDOFF_fix-auth_2026-03-17.md (seq 1) └─ HANDOFF_fix-auth_2026-03-18.md (seq 2) └─ HANDOFF_fix-auth_2026-03-19.md (seq 3)你在一个功能上的第三个会话,知道前两个会话做过什么。
-
自我校验。 第一次落盘必须达到及格线;第二次补到上限。这是「一份看起来像 handoff 的文件」和「一份被检查过的文件」之间的差别。
-
按上下文大小自适应。 超过 500K token 时切换到多趟 map-reduce 抽取,避开「lost in the middle」问题。
/handoff 与 /handoffplan:两者都捕捉会话;差别在下一个会话做什么。/handoff 用于中途暂停——下个会话读简报、做 onboarding、去探索。/handoffplan 用于研究完成、准备动手——它额外写一份带跟踪任务的阶段计划,阶段间有依赖链,有从失败尝试推导出的反目标,有回滚策略,以及绑定到你会话里真实数字的成功判据。两者都以一段可直接粘贴的恢复提示收尾。
它消除了什么痛点
- 压缩税。
/compact在上下文已经塞满时才触发,而塞满的模型是迟钝的:它自己决定什么重要,而每次压缩都丢一点。handoff 是由一个知道哪些字段必须存活的流程、刻意写出来的。 - 重新发现已经试过的东西。 恢复的会话里最常见的浪费,是重跑一个已经失败的尝试。“What We Tried” 一节就是为消除这一点设计的。
- 活不过会话的上下文。 文件住在你的仓库里,在上下文窗口之外。它是一个你能读、能改、能 diff 的纯 markdown 文件,不是一个你无法检查的模型黑盒摘要。
- 思考链的丢失。 因为 handoff 按序号成链,一个跨三个会话的功能保有一份连续记录,而不是三份孤立的摘要。
怎么用
安装两个技能:
git clone https://github.com/REMvisual/claude-handoff.git
cp -r claude-handoff/skills/handoff ~/.claude/skills/
cp -r claude-handoff/skills/handoffplan ~/.claude/skills/
在 Claude Code 里输入 /handoff 验证——它应该出现在自动补全里。用法:
/handoff # 中途暂停:捕捉上下文,下个会话去探索
/handoffplan # 研究完成:捕捉上下文 + 写计划,下个会话去执行
不需要参数。它挖对话、采 git 状态、校验,然后给你一段可粘贴的提示:
Read `plans/handoffs/HANDOFF_fix-auth-bug_2026-03-19.md` (seq 2, PROJ-abc1)
and continue from "Where We're Going".
把它粘进新会话。它接上链条开始干活。
两个配套件,可选但值得知道:
- 防止技能被遮蔽。 没有规则时,Claude 可能在会话结束时自由发挥地生成「handoff」——文档看起来对,但跳过了流程。加进
CLAUDE.md:“结束会话或保存进度时,永远使用 /handoff 技能。绝不在没有它的情况下生成 handoff 摘要。” - PreCompact 钩子。 一道安全网,在上下文压缩前运行,捕捉约 50 行 git 状态与活动任务,以防你在想起要交接之前就先撞上了压缩阈值。
它也配合任务跟踪器(默认 Beads,或 Linear / Jira / GitHub Issues)与持久记忆工具,把它们用作链标签与历史决策查询。
它帮不上忙的地方
- 短的、单会话能装下的工作。 如果任务在一个上下文窗口内就装得下,一份结构化 handoff 的开销不值得。
- 它不能替代你边做边记。 技能挖的是对话,但它只能抽出实际被说过的东西。一个只在你脑子里做过的决定,不在转录里。
- 文件只和它捕捉的那个会话一样好。 一个充满半成品探索的会话,产出一份充满半成品状态的 handoff。它放大清晰度,但不创造清晰度。
- 链式连续性取决于你把 handoff 放在一个地方。 把它们散到不同分支或改名,序号检测就丢了线索。
为什么这是「会话间记忆」的正确形状
持久的洞见不是文件格式,而是原则:把重要的东西以结构化形式留在上下文窗口之外,需要时只把那份拿回来。 这正是 Anthropic 在上下文工程指南里所说的「结构化笔记」。/compact 是一个疲惫模型做的有损压缩;handoff 是一个带着清单的流程做的刻意抽取。这个技能把后者变成了一个一键的习惯。
这篇文章怎么写成的
事实(安装路径、命令、文件小节、链模型、A/B 说法)取自仓库的 README.md,截至 2026-09-10。A/B 结果是项目自己的测量,这里按原样转述,不是我们的独立测试。关于它在哪里有用的判断是我们的编辑意见。依赖任何细节前请回到仓库核对——项目还年轻,还在变。