/handoff — 跨工具工作交接
没有AI编码工具能读取另一个工具的转录:Claude Code将会话锁定在~/.claude/projects/<munged-cwd>/<uuid>.jsonl,Codex/OpenCode在它们自己的存储中,Antigravity在加密的.pb文件中。唯一跨工具可移植的是自包含文档。此技能编写该文档——你当前的目标、决策和确切的未提交编辑——这样任何其他AI代理都能从中断处继续,无需你重新解释任何事情。
使用此技能当用户代币不足、想在任务中途切换工具、正在转移到另一台机器、或说“handoff” / “continue elsewhere” / “out of tokens”。
此技能是自包含的:仅需git和shell即可运行。当该二进制文件在PATH上时,它会调用specweave handoff作为可选的加速器(高保真、感知增量)——但对SpecWeave无硬性依赖。
决策:选择哪条路径
command -v specweave >/dev/null 2>&1 && echo "ACCELERATOR" || echo "STANDALONE"
- ACCELERATOR(
specweave在PATH上)→ 运行引擎,输出其结果。转到路径A。 - STANDALONE(无
specweave)→ 从git+ 简短问答自己构建文档。转到路径B。
两条路径都生成相同的文档格式和相同的粘贴提示(参见下面的标准模板),因此无论由哪条路径生成,交接都可以在任何工具中继续。
路径 A — 加速器(specweave在PATH上)
运行引擎,传递你能便宜提供的任何简短上下文:
specweave handoff [incrementId] [--reason "..."] [--summary "..."] [--next "..."] [--gotcha "..."] [--decision "..."] [--inline]
然后按原样、按顺序展示其stdout(不要重新排序或转述):
- 绝对文档路径作为纯文本(第一),2. 可点击的Markdown链接,3.
.diff路径, - 围栏代码块的复制粘贴恢复提示,5. 每个工具的“查找源会话”提示。
完成。引擎已处理工作区检测、任务/AC解析、git捕获、完整差异转储、秘密审查和渲染。
路径 B — 独立模式(无specweave)
仅使用shell构建字节兼容的文档。
B1. 捕获git状态(免费 — 无代币消耗)
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
mkdir -p "$ROOT/.handoff"
printf '*\n' > "$ROOT/.handoff/.gitignore" # 永远不要让交接或其差异进入git
BRANCH="$(git -C "$ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo '(no git)')"
SHA="$(git -C "$ROOT" rev-parse --short HEAD 2>/dev/null || echo '(no commits)')"
STATUS="$(git -C "$ROOT" status --porcelain 2>/dev/null)"
STAT="$(git -C "$ROOT" diff --stat 2>/dev/null)"
# 完整的未提交编辑 → 兄弟.diff(工作树+暂存区),关键保真度工件
{ git -C "$ROOT" diff HEAD 2>/dev/null; git -C "$ROOT" diff --cached 2>/dev/null; } > "$ROOT/.handoff/handoff.diff"
B2. 五个问题问答(仅不可推导的字段)
询问用户(保持为~5个短字符串——即使在代币耗尽时也很便宜):
- reason — 你为什么要交接?(例如“代币用完”)
- summary — 一行:当前进展如何?
- next — 确切的下一步。
- gotcha — 下一个代理绝不能做什么/必须知道什么?
- decisions — 已做出的关键决策(分号分隔)。
B3. 秘密审查(写入前——对自由文本和差异都执行)
将匹配项替换为[REDACTED-<type>]并按模式计数。模式(12个):
sk-, ghp_, gho_, ghs_, AKIA, ASIA, -----BEGIN, vsk_, xox[bap]-, Bearer , password=, api_key=。
# 原地审查捕获的差异,例如:
sed -i.bak -E \
-e 's/sk-[A-Za-z0-9_-]+/[REDACTED-sk]/g' \
-e 's/gh[pos]_[A-Za-z0-9_-]+/[REDACTED-gh-token]/g' \
-e 's/(A[KS]IA[0-9A-Z]{16})/[REDACTED-aws-key]/g' \
-e 's/vsk_[A-Za-z0-9_-]+/[REDACTED-vsk]/g' \
-e 's/xox[bap]-[A-Za-z0-9-]+/[REDACTED-slack]/g' \
-e 's/Bearer [A-Za-z0-9._-]+/Bearer [REDACTED-bearer]/g' \
-e 's/(password=)[^[:space:]]+/\1[REDACTED-password]/g' \
-e 's/(api_key=)[^[:space:]]+/\1[REDACTED-api_key]/g' \
"$ROOT/.handoff/handoff.diff" && rm -f "$ROOT/.handoff/handoff.diff.bak"
审查是启发式的——空的审查列表不能保证文件是干净的。
B4. 编写文档
将下面的标准模板写入$ROOT/.handoff/HANDOFF.md,填充捕获和问答字段。
所有权哨兵:如果根目录的./HANDOFF.md已存在且不包含Doc format v1标记,则它是一个外部文件——不要覆盖它;改写到.handoff/HANDOFF.md(这里默认为此)。
B5. 输出——绝对路径优先,按此顺序
.handoff/HANDOFF.md的绝对路径,纯文本。- 指向它的可点击Markdown链接。
.handoff/handoff.diff的绝对路径。- 围栏代码块的粘贴提示(见下文)。
- 每个工具的“查找源会话”提示。
标准交接文档模板(内联 — 单一事实来源)
按此确切顺序渲染这些部分,以Doc format v1页脚标记结尾。方括号占位符由捕获的git状态+问答填充。这镜像了specweave的handoff-doc-format.ts,因此此处生成的文档与CLI生成的字节兼容。
# 工作交接[: <如果有标题>]
- 文档路径: <ABSOLUTE_DOC_PATH>
- 文档链接: [<ABSOLUTE_DOC_PATH>](<ABSOLUTE_DOC_PATH>)
- Diff文件: <ABSOLUTE_DIFF_PATH>
- 生成时间: <ISO_TIMESTAMP>
- 工作区: <ROOT> (非SpecWeave)
- Git: 分支 `<BRANCH>` @ `<SHA>`
## 我离开的地方
**交接原因:** <reason>
**总结:** <summary>
_没有活跃的SpecWeave增量 — 这是一个git+问答交接。_
## 已完成/待办
_没有增量任务/AC状态可用。_
## 关键决策与注意事项
- <decision 1>
- <decision 2>
**注意:** <gotcha>
## 涉及的文件
**未提交** — 在破坏性操作之前,请先提交、暂存或继续编辑。
<git status --porcelain>
<git diff --stat>
完整的未提交差异: `<ABSOLUTE_DIFF_PATH>` — 读取它或对其运行 `git apply --check` 以查看确切的编辑。
## 确切的下一步步骤
<next>
## 如何恢复
如果上述文档路径在您阅读此文档的机器上不存在,请停止并要求用户粘贴交接内容——不要即兴创建上下文。
要恢复原始转录(可选),按工具查找您的源会话:
### Claude Code
- 查找会话: ls ~/.claude/projects/<munged-cwd>/(混淆:每个非字母数字字符 → "-",不合并运行;例如 /Users/antonabyzov/Projects/github/specweave-umb/.claude-worktrees/x → -Users-antonabyzov-Projects-github-specweave-umb--claude-worktrees-x)
- 恢复: `claude -r <uuid>`
### Codex
- 查找会话: ls ~/.codex/sessions/(最新目录 = 最近会话)
- 恢复: `codex resume <uuid> (或: codex resume --last)`
### OpenCode
- 查找会话: opencode sessions list
- 恢复: `opencode -s <id> (长格式: opencode --session <id>)`
### Gemini CLI
- 查找会话: 在Gemini会话中运行/chat list查看保存的标签
- 恢复: `/chat resume <tag>`
### Antigravity
- 查找会话: 打开Antigravity代理管理器并选择先前的任务线程
- 恢复: `从Antigravity代理管理器恢复线程`
### Aider
- 查找会话: aider在仓库根目录保留.aider.chat.history.md
- 恢复: `aider --restore-chat-history`
## 审查
- <N> `<type>` 字符串已屏蔽
_审查是启发式的(正则表达式基线)。空的审查列表不能保证此文件干净——分享或提交前请检查。_
---
<!-- Doc format v1 -->
模板说明:
- 如果没有未提交的更改,则将“涉及的文件”主体替换为
_工作树干净 — 无未提交编辑。_(当没有git时替换为_不是git仓库 — 未捕获差异。_)。 - 如果没有决策,则“关键决策”主体为
_未记录决策。_;当没有给出注意点时省略**注意:**行。 - 当没有内容被屏蔽时,“审查”主体为
_未检测到类似令牌的字符串。_。 - 页脚标记
<!-- Doc format v1 -->是强制性的,必须是最后一行——它是所有权哨兵。
粘贴提示
默认(文件可访问):
恢复我的工作。读取交接文档于:<ABSOLUTE_DOC_PATH>
如果该路径在此机器上不存在,请停止并要求我粘贴交接内容——不要即兴创建上下文。
确切的未提交编辑位于:<ABSOLUTE_DIFF_PATH>
--inline(跨机器,文件不可访问): 将完整文档正文嵌入标记之间,使其在提示本身中传输:
使用下面的自包含交接文档恢复我的工作。
这是一个完整的交接文档——将标记之间的所有内容视为事实依据。如果它引用的`.diff`路径在此机器上不存在,请要求我粘贴差异。
BEGIN HANDOFF
<完整渲染的交接文档,包括Doc format v1页脚>
END HANDOFF
安全默认值
- 文档和差异默认被git忽略(
.handoff/.gitignore=*)且从不自动提交。不要打印git add提示。 - 秘密审查在任何写入之前对自由文本和差异都运行。
- 审查是启发式的——建议用户在分享或提交前检查。