Skip to content

Latest commit

 

History

History
435 lines (291 loc) · 21 KB

File metadata and controls

435 lines (291 loc) · 21 KB

/save-context — Design Spec

A Claude Code skill that captures session context before /clear, so nothing important is lost when the user starts a new task.

一个 Claude Code skill,在 /clear 前抢救 session 上下文,避免开新任务时丢失重要信息。


1. Background / 背景

The user runs many long Claude Code sessions ("harness coding"). At the end of a task they typically /clear and start fresh. The problem: across a session, the conversation accumulates context that never landed in any file — decisions made, root causes found, half-finished approaches, TODOs the user mentioned offhand, references, mental models. Once /clear runs, all of it is gone.

用户经常跑很长的 Claude Code session("harness coding")。一个任务结束时通常 /clear 重开。问题在于:整个 session 里对话积累了大量从未落入任何文件的上下文 —— 做过的决策、查到的根因、半成品方案、随口说的 TODO、引用资源、形成的心智模型。/clear 一跑全部归零。

Existing safeguards don't cover this case:

  • Git captures committed code changes, not the reasoning around them.
  • CLAUDE.md / project docs capture intentional, curated knowledge — not in-flight session state.
  • User memory (~/.claude/.../MEMORY.md) is for cross-project, durable preferences — not per-project, per-session work.

现有手段都覆盖不到这个场景:

  • Git 只记已提交的代码变更,不记围绕它的推理过程。
  • CLAUDE.md / 项目文档记的是有意整理过的知识,不是 session 中流动的状态。
  • 用户级 memory~/.claude/.../MEMORY.md)是跨项目、长期稳定的偏好,不是单项目单 session 的工作流。

This skill fills the gap with a deliberate, auditable checkpoint.

这个 skill 用一个明确、可审计的 checkpoint 来填补这个空缺。


2. Goals & non-goals / 目标与非目标

Goals / 目标

  • G1 — Prevent loss of session-only context across /clear.
  • G2 — Make saving deliberate: user always sees what will be written before it is written.
  • G3 — Keep the project tree clean: only .md docs are touched; uncategorized info lands in one known file at the project root.
  • G4 — Cumulative: multiple invocations append, never overwrite.
  • G5 — Cheap when there's nothing to save — no empty file pollution.
  • G1 —— 防止 session-only 的上下文在 /clear 时丢失。
  • G2 —— 落盘是明确动作:用户在任何写入前都先看到要写什么。
  • G3 —— 保持项目树整洁:只动 .md 文档;归不到现存文档的信息全部进项目根的一个已知文件。
  • G4 —— 可累积:多次调用追加,绝不覆盖。
  • G5 —— 没东西可保存时零成本,不产生空文件污染。

Non-goals / 非目标

  • NG1 — Auto-running /clear. Claude cannot, and shouldn't pretend to.
  • NG2 — Automating the cleanup of TempContext.md. Humans curate.
  • NG3 — Cross-project memory. Already covered by user-level memory.
  • NG4 — Reading the raw transcript. Works on what Claude still remembers — anything compacted out is gone regardless.
  • NG5 — Modifying source code, configs, or any non-.md file.
  • NG1 —— 自动跑 /clear。Claude 没这能力,也不应假装有。
  • NG2 —— 自动清理 TempContext.md。这件事人工 curate。
  • NG3 —— 跨项目记忆。用户级 memory 已经覆盖。
  • NG4 —— 读原始 transcript。只工作在 Claude 还记得的内容上 —— 被 compact 掉的部分本来也救不回来。
  • NG5 —— 改源代码、配置文件、或任何非 .md 文件。

3. User flow / 用户流程

The user invokes /save-context. Claude scans, summarizes, attributes, and shows a review panel before writing anything. On approval, edits are applied and TempContext.md is appended.

用户调用 /save-context。Claude 扫描、总结、归属,并在写入前展示 review 面板。批准后,现存文档应用 edits,TempContext.md 追加一条新条目。

User: /save-context

Claude:
  [scans .md docs, summarizes session, attributes each item]

  📋 /save-context preview

  ➤ Proposed edits to existing docs (2):
    • CLAUDE.md       → "Testing" section, +2 lines
        - Mock DB is forbidden in integration tests (see <session>'s
          decision; mocks masked a broken migration last quarter).
    • docs/api.md     → "Endpoints" section, +1 line
        - /v2/foo accepts an optional `since` cursor param.

  ➤ New entry to append to TempContext.md:
    ## 2026-04-27 14:30 · session: ts-20260427-143015-a3f7

    **Topic**: Investigating the v2 cursor pagination bug

    ### Decisions
    - Picked offset-then-cursor migration over cursor-only because of
      backwards-compat with mobile client v3.2.x users on 30-day TTL.

    ### Open Questions / TODOs
    - Verify cursor encoding survives base64 round-trip in Android client.

    ### Investigations
    - Root cause of pagination off-by-one was that `since` was applied
      after limit, not before. See src/api/pagination.go:142.

  ➤ Dropped (already documented): 3 items

  Approve and write?
  [Approve and write] [Cancel] [Other...]

User: Approve and write

Claude:
  ✅ Saved 2 doc edits + 1 TempContext.md entry. Safe to /clear now.

4. Design decisions (with rationale) / 设计决策(含理由)

D1 — Trigger via slash command /save-context. Rejected: auto-trigger on /clear — no pre-clear hook surface, and explicit user intent is desirable.

D1 —— 用 slash 命令 /save-context 触发。否决:在 /clear 时自动触发 —— 没有 pre-clear hook 接口,且需要明确用户意图。

D2 — Comparison scope = .md files only. Rejected: also code/configs (too easy to accidentally edit code), also memory files (per-user not per-project, wrong scope).

D2 —— 对比范围只限 .md 文件。否决:同时改代码/配置(太容易误改代码);同时改 memory 文件(per-user 不是 per-project,scope 错了)。

D3TempContext.md at project root. Rejected: .claude/TempContext.md — user wants visibility; this file is meant to be reviewed, not hidden. Tracking via git is user's call.

D3 —— TempContext.md 放项目根。否决:.claude/TempContext.md —— 用户要可见性;这个文件就是给人看的,不该藏。要不要 git track 由用户自己决定。

D4 — Show review panel before any write. Rejected: auto-write — skill can mis-attribute; the cost of a bad insertion into CLAUDE.md is much higher than one extra confirmation step.

D4 —— 写入前必须展示 review 面板。否决:自动写入 —— skill 可能归错文件;误插一段进 CLAUDE.md 的代价远高于多一次确认。

D5 — Session tag = timestamp + 4 random hex. Rejected: real session ID — Claude Code does not expose a stable session id to skills as of 2026-04. Timestamp is good enough to locate an entry later.

D5 —— session 标识用时间戳 + 4 字节随机 hex。否决:用真实 session id —— 截至 2026-04 Claude Code 没有给 skill 暴露稳定的 session id 接口。时间戳足够日后定位。

D6TempContext.md is append-only. Rejected: rewriting / merging — multiple sessions must coexist; user curates manually.

D6 —— TempContext.md 仅追加。否决:重写或合并 —— 多个 session 的条目必须共存;用户手动 curate。

D7 — No empty-file creation. Rejected: always-create — projects that never need it shouldn't get a stub file.

D7 —— 没东西可写时不创建文件。否决:总是创建 —— 永远用不上的项目不该多一个空文件。

D8 — When uncertain, route to TempContext.md, not to an existing doc. Rejected: always best-effort attribute — wrong attribution to CLAUDE.md is harder to undo than an over-stuffed temp file.

D8 —— 不确定时倒向 TempContext.md,不强行归到现存文档。否决:永远尽力归属 —— 错插 CLAUDE.md 比 temp 文件略胖更难撤销。

D9 — Skill never writes to user memory. Rejected: auto-promoting "user preferences" — user memory is durable; user must approve each entry. Skill surfaces candidates only.

D9 —— skill 永不直接写用户 memory。否决:自动把"用户偏好"提升到 memory —— 用户级 memory 是长期的,每一条都必须用户亲自批;skill 只负责把候选项列出来。

D10 — Exclude only node_modules/, .git/, dist/, build/ when scanning. Rejected: larger excludelist — kept minimal per user direction; user can adjust later if a specific repo needs more.

D10 —— 扫描只排除 node_modules/.git/dist/build/。否决:更大的排除列表 —— 按用户意见保持最小集;后续具体项目需要再加。


5. Technical design / 技术设计

5.1 Skill mechanism / Skill 机制

Skills in Claude Code are markdown files at ~/.claude/skills/<name>/SKILL.md, with YAML frontmatter (name, description) and instructions in the body. The harness loads them as available skills; the user invokes one by typing /<name>, which causes Claude to call the Skill tool.

Claude Code 的 skill 是位于 ~/.claude/skills/<name>/SKILL.md 的 markdown 文件,YAML frontmatter(namedescription)+ 正文指令。harness 把它们注册为可用 skill;用户输 /<name> 触发,Claude 通过 Skill tool 调用。

This skill is developed at:

/Users/wheam/Downloads/ClaudeProjects/skills/SaveContextBeforeClear/SKILL.md

To deploy globally, symlink the dev directory under ~/.claude/skills/. The trigger name (save-context) is determined by the directory name under ~/.claude/skills/, not by the development folder name.

开发路径在上面那个目录。全局部署用 symlink 把开发目录链到 ~/.claude/skills/ 下。触发名(save-context)由 ~/.claude/skills/ 下的目录名决定,跟开发目录名无关。

ln -s /Users/wheam/Downloads/ClaudeProjects/skills/SaveContextBeforeClear ~/.claude/skills/save-context

5.2 File scanning / 文件扫描

find . -name '*.md' \
  -not -path './node_modules/*' \
  -not -path './.git/*' \
  -not -path './dist/*' \
  -not -path './build/*'

For each .md found, read enough to build a topic map: title + section headings, plus full content for short files. Cache mentally for attribution.

每个找到的 .md 都读够建立 topic map:标题 + 章节 heading;小文件直接读全文。在心里 cache 住,后面归属用。

5.3 Summarization / 总结

Pull from current conversation context only (not transcript files). Categories considered:

  • Decisions + rationale
  • In-progress / uncommitted work
  • Open questions / TODOs voiced by user
  • Investigations (RCAs, ruled-out hypotheses, surprises)
  • Architecture / system understanding pieced together
  • External references (URLs, doc paths, ticket IDs)
  • User preferences expressed mid-session

Excluded:

  • Already-committed code changes (git captures them)
  • Routine command output
  • Anything already present in a .md read in 5.2
  • Conversational filler

只从当前对话上下文里拉(不读 transcript 文件)。考虑的类别:

  • 决策 + 原因
  • 进行中 / 未提交的工作
  • 用户口头说的待解决问题 / TODO
  • 调研发现(根因分析、被排除的假设、意外行为)
  • 拼凑出来的架构 / 系统理解
  • 外部引用(URL、文档路径、ticket id)
  • session 中表达的用户偏好

排除的:

  • 已提交的代码变更(git 已记)
  • 常规命令输出
  • 5.2 步骤里读过的 .md 已经写到的内容
  • 对话填充语

5.4 Attribution algorithm / 归属算法

For each surviving item:

  1. Match against the topic map from 5.2. If a clear fit (e.g., an architecture insight when CLAUDE.md has an "Architecture" section) → propose an Edit insertion at end of that section.
  2. No clear fit → add to the TempContext.md entry pool.
  3. Item duplicates content already in a doc → drop.

Tie-breaker: when uncertain, route to TempContext.md (per D8).

对每一条幸存下来的信息:

  1. 跟 5.2 的 topic map 匹配。明确能归(比如架构洞察对应 CLAUDE.md 的 "Architecture" 章节)→ 准备一个该章节末尾插入的 Edit
  2. 找不到合适归处 → 进 TempContext.md 条目池。
  3. 已经在某文档里说过 → 丢弃。

平局规则:不确定时倒向 TempContext.md(见 D8)。

5.5 Review & approval / 审核与批准

Build the preview block (see §3). Call AskUserQuestion:

  • Approve and write → execute writes (5.6).
  • Cancel → no-op.
  • Other (free text) → user describes adjustments; skill revises proposal and re-shows.

拼出 §3 那种 preview block,调用 AskUserQuestion

  • Approve and write → 执行写入(见 5.6)。
  • Cancel → 什么都不做。
  • Other(自由文本)→ 用户描述要怎么调整;skill 改完提案再展示一次。

5.6 Write strategy / 写入策略

  • Existing .md files: Edit with exact-match replace, including enough surrounding context to be unambiguous.
  • TempContext.md:
    • First time: Write with the file header (§6.1) + first entry.
    • Subsequent: Read then Edit to append a blank line + new entry. Never rewrite.
  • On any mid-flight Edit failure: stop, report which writes succeeded, do not continue to the TempContext.md append. User decides next move.
  • 现存 .md:用 Edit 做精确字符串替换,带够上下文保证唯一匹配。
  • TempContext.md
    • 首次:Write 写入文件头(§6.1)+ 首条 entry。
    • 后续:Read 然后 Edit 追加一个空行 + 新 entry。绝不重写。
  • 如果中途有 Edit 失败:停下来,报告哪些写成功哪些失败,不要继续往 TempContext.md 追加。后续动作由用户决定。

5.7 Empty case / 空 session

If §5.3 yields zero items:

✅ No unsaved context detected this session. Safe to /clear now.

No file is created or modified.

如果 §5.3 总结出零条,输出上面那行成功消息,不创建也不修改任何文件。


6. File format: TempContext.md / 文件格式

6.1 File header (written once, on first creation) / 文件头(仅首次创建写入)

# TempContext

Holding pen for session context that didn't fit any existing `.md` doc.
Each `##` block below is one `/save-context` snapshot. Periodically review
and promote mature content into the proper docs, then delete the entry.

这段头说明:本文件是没归属到任何现存 .md 的 session 上下文的存放区;每个 ## 块是一次 /save-context 快照;建议定期 review,把成熟内容迁到正式文档后删除对应条目。

6.2 Per-entry schema / 单条 entry 格式

## <YYYY-MM-DD HH:MM>  ·  session: ts-<YYYYMMDD-HHMMSS>-<4 hex>

**Topic**: <one-line summary>

### Decisions
- ...

### In-Progress
- ...

### Open Questions / TODOs
- ...

### Investigations
- ...

### Architecture / Understanding
- ...

### References
- ...

### User Preferences (consider promoting to memory)
- ...

Rules:

  • Empty subsections are omitted entirely (no empty ### Foo blocks).
  • Each bullet is self-contained: spell out names, paths, and reasons. A fresh Claude session reading this entry must understand it without conversation context.
  • Session tag generation:
    echo "ts-$(date +%Y%m%d-%H%M%S)-$(openssl rand -hex 2)"

规则:

  • 空的子小节直接整个省略(不要渲染空的 ### Foo 块)。
  • 每个 bullet 必须自包含:写清楚名字、路径、理由。新开的 Claude session 读到这条 entry 必须能脱离对话上下文看懂。
  • session tag 用上面那行 bash 生成。

7. Edge cases / 边界 case

E1 — First save in a project. Behavior: Write TempContext.md with header + first entry.

E1 —— 项目首次保存。行为:Write TempContext.md,写入文件头 + 首条 entry。

E2 — Subsequent save. Behavior: Read + Edit append. Existing entries untouched.

E2 —— 后续保存。行为:Read + Edit 追加。已有 entry 不动。

E3 — Empty session (nothing worth saving). Behavior: no-op. No file created.

E3 —— 空 session(没东西值得存)。行为:no-op,不创建文件。

E4 — Mid-write Edit fails. Behavior: stop. Report what succeeded/failed. Do not append to TempContext.md.

E4 —— 中途 Edit 失败。行为:停下,报告已成功/已失败,不再追加 TempContext.md

E5 — User picks "Other" with revisions. Behavior: revise proposal, re-show review panel.

E5 —— 用户选 "Other" 提出调整。行为:改提案,重新展示 review 面板。

E6 — Item duplicates existing doc content. Behavior: drop silently; counted in "dropped" tally.

E6 —— 信息重复于已有文档。行为:静默丢弃,计入 "dropped" 计数。

E7 — Project has no .md files at all. Behavior: everything routes to TempContext.md (created at root).

E7 —— 项目里完全没有 .md 文件。行为:所有信息都去 TempContext.md(在项目根创建)。

E8CLAUDE.md section heading is non-unique. Behavior: use larger surrounding context for Edit to disambiguate, or fall back to TempContext.md for that item.

E8 —— CLAUDE.md 中存在重名章节 heading。行为:Edit 时带更多上下文消歧;实在不行那条就 fallback 到 TempContext.md


8. Known limitations / 已知局限

  • Context window bound: only what Claude still remembers is recoverable. Items compacted out of context are unreachable.
  • Session ID is local-only: timestamp tag has no link to Claude Code's internal session id, so cross-referencing to harness logs is not possible.
  • "Non-trivial" is heuristic: judgment call by Claude. May over- or under-include. Mitigations: review panel + bias-to-temp routing.
  • No auto-promotion: TempContext.md grows until the user manually moves entries into proper docs.
  • Single CWD only: does not handle monorepo sub-project boundaries beyond the active CWD.
  • 受 context window 限制:只有 Claude 还记得的东西能救。被 compact 掉的就没法捞回来。
  • session id 只在本地:时间戳 tag 跟 Claude Code 内部 session id 没关联,没法反查 harness 日志。
  • "非琐碎" 是启发式判断:Claude 自己的判断。可能多写或漏写。缓解:review 面板 + 倾向 temp 文件的归属策略。
  • 不会自动迁移TempContext.md 会一直长,直到用户手动迁到正式文档。
  • 只看当前 CWD:monorepo 多子项目场景下不识别子项目边界,只在 CWD 范围工作。

9. Future work (not in scope for v1) / 未来工作(不在 v1 范围内)

  • /promote-context companion skill: take a TempContext.md entry and migrate it into the appropriate .md doc, then delete the entry.
  • Size guardrail: warn the user when TempContext.md exceeds e.g. 50 KB or 20 entries, prompting cleanup.
  • Transcript ingestion: if Claude Code starts exposing the transcript path to skills, read it for higher-fidelity recall (esp. for long sessions where compaction has occurred).
  • Auto-detection of "save-worthy" moments: passive nudge ("you've been at this for 2h, want to /save-context?") — out of scope, would need harness hook support.
  • /promote-context 配套 skill:把 TempContext.md 的某条 entry 迁到对应的 .md 文档,迁完删除该 entry。
  • 大小护栏:当 TempContext.md 超过比如 50 KB 或 20 条 entry 时提醒用户清理。
  • 吃 transcript:如果以后 Claude Code 给 skill 暴露 transcript 路径,可以读它做更高精度的回忆(特别是发生过 compact 的长 session)。
  • 自动检测"该存了"时机:被动提示("你已经搞了 2h,要不要 /save-context?")—— 超出 v1 范围,需要 harness hook 支持。

10. Implementation status / 实现状态

  • SKILL.md — skill definition and runtime instructions
  • spec.md — this document
  • README.md — bilingual public intro
  • LICENSE — MIT
  • Public repo at https://github.com/wheam/save-context
  • Deployment (symlink to ~/.claude/skills/save-context) — manual, user does it
  • First real-world test in a project with existing docs
  • Tuning pass on attribution bias after first 3–5 real uses
  • SKILL.md —— skill 定义 + 运行时指令
  • spec.md —— 本文档
  • README.md —— 双语公开介绍
  • LICENSE —— MIT
  • 公开仓库 https://github.com/wheam/save-context
  • 部署(symlink 到 ~/.claude/skills/save-context)—— 用户手动
  • 在有现存文档的项目里实际试一次
  • 真实使用 3–5 次后调归属判断的 bias