/handoff,只有几行,却是Matt Pocock调用频率最高的 skill

/handoff,只有几行,却是Matt Pocock调用频率最高的 skill

封面

和 Claude Code 对话时,每一次工具调用、每一次文件编辑,都往上下文窗口里塞 token。窗口确实大——厂商说 100 万 token——但好用程度不是均匀的。聊到后半段,它开始忘记你半小时前说过的话,给出的方案越来越敷衍。

这个问题,TypeScript 大神 Matt Pocock 也遇到了。他的解决办法短到离谱——一个叫 /handoff 的 skill,内容只有几行,结果成了他自己调用频率最高的 skill。他的 skill 仓库目前 18 万星,/handoff 是他最依赖的那一个。

视频开场介绍 handoff skill


AI 聊到后面会变蠢,不是你的错觉

Matt 把上下文窗口分成两段:聪明区和愚蠢区

对话刚开始时,token 少,注意力机制没被稀释,模型输出精准。堆到后面,token 上了规模,注意力开始在所有内容上摊薄——agent 在大量无关信息里迷路。Matt 的实际体感是,120K token 左右就进入愚蠢区了。

上下文窗口的聪明区和愚蠢区示意图

厂商标 100 万,真正好用的也就前面 12 万。这个数字很重要——它不是理论值,是 Matt 反复用出来的经验线。


Compact 能用,但它是单行道

Claude Code 内置的 Compact 就是干这个的:把对话摘要成一段精简文本,塞进新会话开头,继续干活。

摘要里有什么?引用过的文件列表、对话要点、整体基调。压缩成一小块,后面追新内容时持续引用。

Compact 功能的沉积层示意图

每次 compact 像铺一层沉积物。旧对话压成摘要,新对话往上堆。这很适合死磕同一个问题——调试的时候,把所有试过的方案 compact 掉,保留当前状态,继续试。反复 compact,反复存盘。

问题也很明确:Compact 只能在单个会话内接力

Compact vs Handoff — 单行道 vs 分叉路口

你需要的是另一件事——把当前对话里和某个 bug 相关的部分切出来,新开一个独立会话去修。当前会话不动、不受影响。Compact 做不到这一点。它要么压缩整个会话(覆盖你的进度),要么你就硬撑(撞愚蠢区)。


三条指令的事

Matt 的 handoff 做的事:

当前会话 → 总结成 Markdown → 存到临时目录 → 粘贴到新会话

完了。

在 Claude Code 里实际跑一遍,长这样:

假设你正在写一个 Remotion 视频组件,会话已经跑了 80K token。agent 刚帮你调完 Scene3_Mechanism.tsx 里的 3D 粒子效果,但你突然想到——这个视频的转场动画还用的是默认 fade,应该统一换成自定义的 slide-left。

这事跟当前任务无关。如果硬塞进这个会话,上下文会迅速逼近愚蠢区。

你在 Claude Code 的输入框里敲:

/handoff 把视频所有转场从默认 fade 替换为自定义 slide-left 动画,
参考已有的 Transition 组件风格,先做一个全局搜索列出所有需要改的地方,
再逐个替换。改完跑一次 npx remotion render 验证。

Agent 在终端打印了一行:

✓ handoff document written to C:\Users\dingAI\AppData\Local\Temp\handoff-20260730-142105.md

你打开这个文件,里面是结构化的一段 Markdown——当前项目的视频框架信息、已有的 Transition 组件路径、之前讨论过的转场设计原则、一段建议加载的 skill(prototypecode-review),但没有重复任何已有的代码内容。

然后你新开一个 Claude Code 窗口,把这份 Markdown 粘贴进去。新会话的 agent 读到第一行就明白了上下文,直接开始全局搜索所有 fade 转场。跑完 75K token,全改好了,验证通过。

你原来的会话——毫发无损。继续调粒子效果。

Handoff 三步:压缩 → 分叉 → 继续

和 Compact 的区别就一个:Compact 是"压缩→延续",handoff 是"压缩→分叉"。主会话继续推进,子会话独立处理分叉出去的那件事。

Matt 自己用这个用疯了。比如做一个 grilling session——让 AI 反向追问需求,梳理项目规划——进行到一半,他突然意识到"迭代和完成信号应该拆成独立 API"。这事超出了 grilling 的范围。

在 grilling session 中发起 handoff

他直接说:把这个任务 handoff 给另一个 agent。skill 生成了一份 20 行的 Markdown——聚焦点、建议加载的 skill、但绝不重复已有内容。

同时完成了两件事:grilling 立刻收束回了核心问题(因为明确了"这不归现在管"),而那个 API 拆分任务没丢——新会话拿着 handoff 独立推进。


出去探路,再回来

第二种用法更有意思。

Grilling 过程中,agent 追问一些"不看到代码没法回答"的问题——UI 交互怎么设计?复杂逻辑的边界条件?Matt 的做法是当场 handoff 出去做原型。

流程:grilling → 生成 handoff → 新会话做原型(这个原型会话跑了 169K token,远超 grilling 能装下的量)→ 原型跑完后,再生成一份 handoff,总结"学到了什么、哪些结论不是一眼能看出来的"→ 传回 grilling。

原型会话高达 169K token

去 → 回,一个闭环。

DIY 子代理模式:Grilling → 原型 → Handoff 回来

本质上是个手工的子代理:干净上下文做单一任务 → 压缩学习成果 → 传回父会话。

交接格式是 Markdown,所以不绑定 agent。Claude Code 发起,handoff 给 Codex,或者 Copilot CLI,完全看情况。

Markdown 通用交接,不依赖任何特定 Agent

Matt 的原话是:想在几个不同 agent 之间做对抗性审查?Markdown 交接是最简单的方式。


5 条设计规则

handoff 这个 skill 短得要命,但每条规则背后都有反复踩坑的痕迹:

1. 写一段 "suggested skills"。 文档里列好下一个会话该加载什么——grill-with-docsprototype 之类的。粘贴进去自动触发。不用自己记住每个 skill 的名字。

2. 别重复已有内容。 文件路径、GitHub Issue 链接当指针用。Matt 踩过的坑是 handoff 文档越长越大,全是复制粘贴已有内容——没意义。

3. 存 OS 临时目录。 这些文件是一次性的。不是文档,不该留在代码库里腐烂。

4. 自动脱敏。 API key、密码、任何个人身份信息——不能在 Markdown 里到处飘。

5. 必须有"为什么要交接"的参数。 agent 不知道下一个会话要聚焦什么,就写不出有用的 handoff。Matt 每次都会口述目的——语音输入一开,一句话的事。

5 条设计规则一览


说真的

handoff 没有技术含量——它是一种工作习惯

handoff 没有什么技术含量。它是一种工作习惯:关注上下文预算、一个会话只做一个任务、把"交接"当成常规动作而不是临时救火。

我自己用 Remotion 做视频开发就是这样——素材准备一个 session,合成一个 session,字幕一个 session。各干各的,上下文不污染。比任何 prompt 技巧都实在。


本文基于 Matt Pocock 视频 "/handoff is my new favourite skill"(YouTube: dtAJ2dOd3ko)改写。配图为视频截图与设计图,仅供内容说明。


免责声明:本文为基于原视频的二次创作,内容仅代表原作者观点。配图均为视频截图及原创设计图,仅供学习交流,版权归原作者所有。