---
description: 将当前会话状态保存到 ~/.claude/session-data/ 目录下带日期的文件中，以便在未来的会话中恢复完整上下文并继续工作。
---

# 保存会话命令

捕获本次会话中发生的一切——构建了什么、什么成功了、什么失败了、还有哪些遗留事项——并将其写入一个带日期的文件，以便下次会话能从此处继续。

## 使用时机

* 在关闭 Claude Code 之前，工作会话结束时
* 在达到上下文限制之前（先运行此命令，然后开始一个新会话）
* 解决了一个想要记住的复杂问题之后
* 任何需要将上下文移交给未来会话的时候

## 流程

### 步骤 1：收集上下文

在写入文件之前，收集：

* 读取本次会话期间修改的所有文件（使用 git diff 或从对话中回忆）
* 回顾讨论、尝试和决定的内容
* 记录遇到的任何错误及其解决方法（或未解决的情况）
* 如果相关，检查当前的测试/构建状态

### 步骤 2：如果不存在则创建会话文件夹

在用户的 Claude 主目录中创建规范的会话文件夹：

```bash
mkdir -p ~/.claude/session-data
```

### 步骤 3：写入会话文件

创建 `~/.claude/session-data/YYYY-MM-DD-<short-id>-session.tmp`，使用今天的实际日期和一个满足 `session-manager.js` 中 `SESSION_FILENAME_REGEX` 强制规则的短 ID：

* 允许的字符：小写 `a-z`，数字 `0-9`，连字符 `-`
* 最小长度：8 个字符
* 不允许大写字母、下划线、空格

有效示例：`abc123de`、`a1b2c3d4`、`frontend-worktree-1`
无效示例：`ABC123de`（大写）、`short`（少于 8 个字符）、`test_id1`（下划线）

完整有效文件名示例：`2024-01-15-abc123de-session.tmp`

旧文件名 `YYYY-MM-DD-session.tmp` 仍然有效，但新的会话文件应首选短 ID 形式，以避免同一天的冲突。

### 步骤 4：用以下所有部分填充文件

诚实地写入每个部分。不要跳过任何部分——如果某个部分确实没有内容，则写“Nothing yet”或“N/A”。一个不完整的文件比诚实的空部分更糟糕。

### 步骤 5：向用户展示文件

写入后，显示完整内容并询问：

```
会话已保存至 [实际解析的会话文件路径]

这看起来准确吗？在关闭之前，还有什么需要纠正或补充的吗？
```

等待确认。如果用户要求，进行编辑。

***

## 会话文件格式

```markdown
# 会话：YYYY-MM-DD

**开始时间：** [若已知大致时间]
**最后更新：** [当前时间]
**项目：** [项目名称或路径]
**主题：** [关于本次会话的一行摘要]

---

## 正在构建的内容

[1-3段文字，描述功能、错误修复或任务。包含足够的背景信息，让对此会话毫无记忆的人也能理解目标。包含：它做什么、为什么需要它、它如何融入更大的系统。]

---

## 已确认有效的工作（附证据）

[仅列出已确认有效的事项。对于每个事项，说明你如何知道它有效——测试通过、在浏览器中运行、Postman 返回 200 等。没有证据的，请移至"尚未尝试"部分。]

- **[有效的事项]** — 确认依据：[具体证据]
- **[有效的事项]** — 确认依据：[具体证据]

如果尚无任何事项确认有效："尚无确认有效的事项——所有方法仍在进行中或未测试。"

---

## 无效的事项（及原因）

[这是最重要的部分。列出所有尝试过但失败的方法。对于每个失败，写出确切原因，以便下次会话不再重试。要具体："因 Y 而抛出 X 错误"是有用的。"无效"是无用的。]

- **[尝试过的方法]** — 失败原因：[确切原因 / 错误信息]
- **[尝试过的方法]** — 失败原因：[确切原因 / 错误信息]

如果无失败事项："尚无失败的方法。"

---

## 尚未尝试的事项

[看起来有希望但尚未尝试的方法。对话中产生的想法。值得探索的替代方案。描述要足够具体，以便下次会话确切知道要尝试什么。]

- [方法 / 想法]
- [方法 / 想法]

如果无待办事项："未确定具体的待尝试方法。"

---

## 文件当前状态

[本次会话中修改过的每个文件。准确说明每个文件的状态。]

| 文件              | 状态           | 备注                         |
| ----------------- | -------------- | ---------------------------- |
| `path/to/file.ts` | PASS: 完成        | [其作用]                     |
| `path/to/file.ts` |  进行中      | [已完成什么，剩余什么]       |
| `path/to/file.ts` | FAIL: 损坏        | [问题所在]                   |
| `path/to/file.ts` |  未开始      | [计划但尚未接触]             |

如果未修改任何文件："本次会话未修改任何文件。"

---

## 已作出的决策

[架构选择、接受的权衡、选择的方法及其原因。这些可防止下次会话重新讨论已确定的决策。]

- **[决策]** — 原因：[选择此方案而非其他方案的原因]

如果无重大决策："本次会话未作出重大决策。"

---

## 阻碍与待解决问题

[任何未解决、需要下次会话处理或调查的事项。出现但未解答的问题。等待中的外部依赖。]

- [阻碍 / 待解决问题]

如果无："无当前阻碍。"

---

## 确切下一步

[若已知：恢复工作时最重要的单件事项。描述要足够精确，使得恢复工作时无需思考从何处开始。]

[若未知："下一步未确定——在开始前，请查看'尚未尝试的事项'和'阻碍'部分以决定方向。"]

---

## 环境与设置说明

[仅在相关时填写——运行项目所需的命令、所需的环境变量、需要运行的服务等。若为标准设置，请跳过。]

[若无：请完全省略此部分。]
```

***

## 示例输出

```markdown
# 会话：2024-01-15

**开始时间：** ~下午2点
**最后更新：** 下午5:30
**项目：** my-app
**主题：** 使用 httpOnly cookies 构建 JWT 认证

---

## 我们正在构建什么

为 Next.js 应用构建用户认证系统。用户使用电子邮件/密码注册，收到存储在 httpOnly cookie（而非 localStorage）中的 JWT，受保护的路由通过中间件检查有效的令牌。目标是在浏览器刷新时保持会话持久性，同时不将令牌暴露给 JavaScript。

---

## 哪些工作有效（附证据）

- **`/api/auth/register` 端点** — 确认依据：Postman POST 请求返回 200 并包含用户对象，Supabase 仪表板中可见行记录，bcrypt 哈希正确存储
- **在 `lib/auth.ts` 中生成 JWT** — 确认依据：单元测试通过 (`npm test -- auth.test.ts`)，在 jwt.io 解码的令牌显示正确的负载
- **密码哈希** — 确认依据：`bcrypt.compare()` 在测试中返回 true

---

## 哪些工作无效（及原因）

- **Next-Auth 库** — 失败原因：与我们的自定义 Prisma 适配器冲突，每次请求都抛出“无法在此配置中将适配器与凭据提供程序一起使用”。不值得调试 — 对我们的设置来说过于固执己见。
- **将 JWT 存储在 localStorage 中** — 失败原因：SSR 渲染发生在 localStorage 可用之前，导致每次页面加载都出现 React 水合不匹配错误。此方法从根本上与 Next.js SSR 不兼容。

---

## 尚未尝试的事项

- 在登录路由响应中将 JWT 存储为 httpOnly cookie（最可能的解决方案）
- 使用 `cookies()` 从 `next/headers` 中读取服务器组件中的令牌
- 编写 middleware.ts 通过检查 cookie 是否存在来保护路由

---

## 文件当前状态

| 文件                             | 状态           | 备注                                           |
| -------------------------------- | -------------- | ----------------------------------------------- |
| `app/api/auth/register/route.ts` | PASS: 已完成    | 工作正常，已测试                                   |
| `app/api/auth/login/route.ts`    |  进行中 | 令牌已生成但尚未设置 cookie      |
| `lib/auth.ts`                    | PASS: 已完成    | JWT 辅助函数，全部已测试                         |
| `middleware.ts`                  |  未开始 | 路由保护，需要先实现 cookie 读取逻辑 |
| `app/login/page.tsx`             |  未开始 | UI 尚未开始                                  |

---

## 已做出的决策

- **选择 httpOnly cookie 而非 localStorage** — 原因：防止 XSS 令牌窃取，与 SSR 兼容
- **选择自定义认证而非 Next-Auth** — 原因：Next-Auth 与我们的 Prisma 设置冲突，不值得折腾

---

## 阻碍与未决问题

- `cookies().set()` 在路由处理器中有效，还是仅在服务器操作中有效？需要验证。

---

## 确切下一步

在 `app/api/auth/login/route.ts` 中，生成 JWT 后，使用 `cookies().set('token', jwt, { httpOnly: true, secure: true, sameSite: 'strict' })` 将其设置为 httpOnly cookie。
然后用 Postman 测试 — 响应应包含一个 `Set-Cookie` 头。
```

***

## 注意事项

* 每个会话都有其自己的文件——切勿追加到先前会话的文件中
* “什么没有成功”部分是最关键的——没有它，未来的会话将盲目地重试失败的方法
* 如果用户要求中途保存会话（而不仅仅是在结束时），则保存目前已知的内容，并清楚地标记进行中的项目
* 该文件旨在通过 `/resume-session` 在下次会话开始时由 Claude 读取
* 使用规范的全局会话存储：`~/.claude/session-data/`
* 对于任何新的会话文件，首选短 ID 文件名形式（`YYYY-MM-DD-<short-id>-session.tmp`）
