关于 handoff
`/handoff` 是用于结束会话时保存工作上下文的技能。它通过 MCP 记录独立记忆,并写入叙述式会话日志和当前项目状态文件。
主要功能
- 01逐条记录决策与经验
- 02预览待确认的记录
- 03写入叙述式会话日志
- 04更新项目状态和时间戳
- 05在条件允许时提交 `~/.origin/` 更改
适用场景
- 01结束会话前保存项目上下文
- 02记录决策和技术经验
- 03跟踪进行中与待处理工作
- 04查看尚未确认的记录
MCP 相关
该技能通过 MCP 列出待处理的记忆记录,并将决策、经验和其他值得保留的信息逐条存储。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ davepoon/ buildwithclaude --skill handoff安装后在 Claude Code 中输入/handoff确认已加载。
详细介绍
/handoff
会话结束回顾。每次交接都要生成 3 项内容:
- 粒度化 MCP 记录 — 每项决策、经验或易错点各记录一条(数据库为权威来源)。
- 会话日志 md — 位于
~/.origin/sessions/<YYYY-MM-DD-HHmm>-<slug>.md的叙述线索。 - 项目状态 md + json — 当前目标 + 上次交接时间戳,位于
~/.origin/sessions/_status/。
这 3 项各自独立:记录是可查询的原子信息,会话日志是叙述线索,状态文件让下一次会话知道我们上次进行到了哪里。
步骤
1. 检测项目和上次交接时间
Bash: cd_repo=$(git -C "$PWD" rev-parse --show-toplevel 2>/dev/null); echo "${cd_repo:-no-git}"
- 如果输出是路径 → 将其 basename 作为
<project>(例如origin)。 - 如果输出为
no-git→ 使用 cwd 的 basename。跳过以下 git 步骤,完全依赖对话上下文。
读取 ~/.origin/sessions/_status/handoff-<project>.json 中的 lastHandoff 时间戳(ISO-8601)。如果文件不存在,默认使用“12 小时前”。
1.5 待确认记录预览
确定 <lastHandoff> 后,调用:
list_pending(limit=50)
MCP 会返回包含 source_id、content、created_at 和其他元数据的记忆行。将 lastHandoff(ISO-8601 字符串,例如
2026-05-13T22:50:00Z)转换为 Unix 纪元秒整数,然后再进行筛选:
Bash: date -j -f %Y-%m-%dT%H:%M:%SZ "$lastHandoff" +%s
也可以使用你选择的脚本语言(Python 的 datetime.fromisoformat、
JavaScript 的 Date.parse 等)。将结果保存为 lastHandoffEpoch。
然后筛选响应行:保留 row.created_at >= lastHandoffEpoch 的行。
这些是本次会话产生、但质量门禁未确认的记录(不可信来源记录)。
如果筛选结果为空,不要输出任何内容。继续执行步骤 2。
如果结果非空,在现有记录流程之前渲染一次预览块:
Pending captures this session (<N> total, top 3 shown):
1. mem_xyz789 "..." (untrusted source: <agent>)
2. ...
Default: proceed (captures stay pending). Opt in by running
`/review captures` before re-invoking /handoff if you want to walk them.
不要在行内提示用户对每项采取操作。无论如何,用户都会继续执行 /handoff;预览仅供参考。
2. 收集会话上下文(仅在 git 仓库中并行执行)
Bash: git -C <repo> log --oneline --since=<lastHandoff>
Bash: git -C <repo> status --short
Bash: git -C <repo> diff --stat HEAD~5..HEAD 2>/dev/null
Bash: git -C <repo> worktree list
捕获输出。结合对话历史推断发生了什么。如果不是 git 仓库,则跳过——以对话上下文为准。
3. 推断,不要提问
根据 git 输出和对话内容静默归纳。将每项归入面向用户的类别。每个类别对应捕获调用中的 daemon memory_type:
| 显示标签 | daemon memory_type | 内容范围 |
|---|---|---|
| 决策 | decision | 架构选择、工具或模式选择(附带原因) |
| 经验 | lesson | 发现的根本原因、找到的解决方法、技术见解 |
| 见解 | gotcha | 意外行为、调试发现、容易踩坑的地方 |
| 更正 | preference | 用户提出异议、纠正做法或假设 |
| 事实 | fact | 值得留存的持久项目、人员或工具事实 |
非记忆类事项(不存储,仅写入会话日志):
- 未完成事项 — 已启动但尚未完成的工作、阻碍因素。
跳过 git 中已有的纯机械事实(文件路径、函数名、配置值)。提交日志会保留这些信息。
4. MCP 记录(每项一条)
对每项重要内容,使用对应的 memory_type 调用:
capture(content="<one self-contained sentence with WHY>", memory_type="<decision|lesson|gotcha|preference|fact>")
保持原子性:每次调用记录一项决策。不要将多项内容合并为一条记忆。daemon 会与现有知识去重,因此重复存储已知事实不会产生任何影响。
仅当符合以下任一条件时,才在存储前向用户展示内容:
- 与现有记忆矛盾(召回结果中存在冲突事实)。
- 涉及重大事件、不可逆操作或生产环境变更。
- 无法确定该内容是长期有效还是暂时性的。
其他情况只需存储,并在最后汇报数量。
5. 编写会话日志
使用 Bash heredoc 写入 ~/.origin/sessions/<YYYY-MM-DD-HHmm>-<slug>.md:
# Session <YYYY-MM-DD HH:MM> — <slug>
**Project:** <project>
**Range:** <lastHandoff> → <now>
## Accomplished
- <item>
## Decisions
- <decision and rationale>
## Lessons & Gotchas
- <root cause / workaround>
## Open Threads
- <what's unfinished>
## Captures stored
- <source_id_or_brief_summary>
## Git summary
<git log --oneline output>
<slug> = kebab-case 格式的 2–4 个词摘要(session-handoff-md-writer)。
6. 更新项目状态
覆盖 ~/.origin/sessions/_status/<project>.md:
# <Project> — Current Status
## Last session (<date>)
- <accomplished bullet>
## Active
- <item> (added <YYYY-MM-DD>)
- <blocked item> (added <YYYY-MM-DD>) (gated: <trigger>)
## Backlog
- <item> (added <YYYY-MM-DD>)
每个项目一个文件。新会话会覆盖旧内容——这里记录的是当前状态,而不是日志。
分成两个部分,而不是一个平铺列表: ## Active 和 ## Backlog 用于区分两类任务,避免它们混在一起。Active = 值得接下来处理的新近动态。Backlog = 较早搁置的事项,保留作参考,但不纳入“接下来做什么?”的考虑范围。
每条项目符号都加上日期标记,格式为 (added <YYYY-MM-DD>)。添加新事项时使用今天的日期;延续事项时保留原始日期。日期能让人一眼看出事项的存续时间,也避免相对时间不断变化。
受阻事项在行内加标签,格式为 (gated: <trigger>)——不单独设一个部分。标签说明事项为何暂时无法推进;项目符号仍放在反映其新近程度的部分中。
升格 / 降级规则:
- 本次会话中的新事项 → 移至
## Active,并标注今天的日期 ## Active中本次会话未处理、且上次会话也未处理的事项 → 降至## Backlog(保留原始日期)## Backlog中已恢复处理的事项 → 升回## Active(保留原始日期——陈旧程度取决于事项本身,而不是项目符号文本)
7. 写入时间戳
覆盖 ~/.origin/sessions/_status/handoff-<project>.json:
{
"lastHandoff": "<ISO-8601 now>",
"project": "<project>",
"summary": "<one-line>"
}
每个项目单独存储文件,避免并行会话相互覆盖。
8. 自动提交 ~/.origin/
写入上述文件后,保存此次变更快照,方便用户通过 git log 查看记忆的时间线。此操作具有防护机制——若缺少 git 或 ~/.origin/ 尚未成为仓库,则静默跳过。
Bash: git -C ~/.origin add -A && \
git -C ~/.origin -c user.name=Origin -c [email protected] \
commit --quiet -m "session: <slug>" 2>/dev/null || \
(sleep 1 && git -C ~/.origin add -A && \
git -C ~/.origin -c user.name=Origin -c [email protected] \
commit --quiet -m "session: <slug>" 2>/dev/null) || true
重试机制可应对 index.lock 竞争——守护进程可能恰好在同一时刻写入
~/.origin/(捕获内容时自动提交)。等待一秒足以让守护进程释放锁。
9. 确认
输出一个摘要块,按显示标签分组列出捕获内容:
Handoff stored.
Decisions: <N> (brief list)
Lessons: <N> (brief list)
Insights: <N> (brief list)
Corrections: <N> (brief list)
Facts: <N> (brief list)
Session: ~/.origin/sessions/<filename>
Status: ~/.origin/sessions/_status/<project>.md
Git: <commit hash> session: <slug>
仅在标签下有内容时显示该标签。将条目写成简短短语,而非完整句子——会话日志中已有详细信息。
使用时机
- “收尾吧”、“就到这里吧”、“我们完成了”。
- 会话即将结束,否则有用的状态会丢失。
不要使用的情况
- 工作过程中途捕获 → 使用
/capture(单条记忆)。 - 搜索 / 查找 → 使用
/recall。 - 没有决定或经验教训的一次性聊天——仅捕获内容即可。
关于三类产物的说明
- 记忆(MCP 捕获内容)仅存储在守护进程数据库中。确认操作会切换
stability标记——它们永远不会导出到 md 文件。 - 页面是知识库风格的综合内容,由守护进程在运行
/distill时写入~/.origin/pages/。引用会链接回源记忆 ID。 - 会话(本技能)仅存储在
~/.origin/sessions/。它们是叙事主线:按时间顺序组织,而非按主题组织。可将其作为工作的变更日志来浏览。