--- description: 将当前会话状态保存到 ~/.claude/sessions/ 目录下带日期的文件中,以便在未来的会话中恢复完整上下文并继续工作。 --- # 保存会话命令 捕获本次会话中发生的一切——构建了什么、什么成功了、什么失败了、还有哪些遗留事项——并将其写入一个带日期的文件,以便下次会话能从此处继续。 ## 使用时机 * 在关闭 Claude Code 之前,工作会话结束时 * 在达到上下文限制之前(先运行此命令,然后开始一个新会话) * 解决了一个想要记住的复杂问题之后 * 任何需要将上下文移交给未来会话的时候 ## 流程 ### 步骤 1:收集上下文 在写入文件之前,收集: * 读取本次会话期间修改的所有文件(使用 git diff 或从对话中回忆) * 回顾讨论、尝试和决定的内容 * 记录遇到的任何错误及其解决方法(或未解决的情况) * 如果相关,检查当前的测试/构建状态 ### 步骤 2:如果不存在则创建会话文件夹 在用户的 Claude 主目录中创建规范的会话文件夹: ```bash mkdir -p ~/.claude/sessions ``` ### 步骤 3:写入会话文件 创建 `~/.claude/sessions/YYYY-MM-DD--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:向用户展示文件 写入后,显示完整内容并询问: ``` Session saved to [actual resolved path to the session file] Does this look accurate? Anything to correct or add before we close? ``` 等待确认。如果用户要求,进行编辑。 *** ## 会话文件格式 ```markdown # 会话:YYYY-MM-DD **开始时间:** [若已知大致时间] **最后更新:** [当前时间] **项目:** [项目名称或路径] **主题:** [关于本次会话的一行摘要] --- ## 正在构建的内容 [1-3段文字,描述功能、错误修复或任务。包含足够的背景信息,让对此会话毫无记忆的人也能理解目标。包含:它做什么、为什么需要它、它如何融入更大的系统。] --- ## 已确认有效的工作(附证据) [仅列出已确认有效的事项。对于每个事项,说明你如何知道它有效——测试通过、在浏览器中运行、Postman 返回 200 等。没有证据的,请移至"尚未尝试"部分。] - **[有效的事项]** — 确认依据:[具体证据] - **[有效的事项]** — 确认依据:[具体证据] 如果尚无任何事项确认有效:"尚无确认有效的事项——所有方法仍在进行中或未测试。" --- ## 无效的事项(及原因) [这是最重要的部分。列出所有尝试过但失败的方法。对于每个失败,写出确切原因,以便下次会话不再重试。要具体:"因 Y 而抛出 X 错误"是有用的。"无效"是无用的。] - **[尝试过的方法]** — 失败原因:[确切原因 / 错误信息] - **[尝试过的方法]** — 失败原因:[确切原因 / 错误信息] 如果无失败事项:"尚无失败的方法。" --- ## 尚未尝试的事项 [看起来有希望但尚未尝试的方法。对话中产生的想法。值得探索的替代方案。描述要足够具体,以便下次会话确切知道要尝试什么。] - [方法 / 想法] - [方法 / 想法] 如果无待办事项:"未确定具体的待尝试方法。" --- ## 文件当前状态 [本次会话中修改过的每个文件。准确说明每个文件的状态。] | 文件 | 状态 | 备注 | | ----------------- | -------------- | ---------------------------- | | `path/to/file.ts` | ✅ 完成 | [其作用] | | `path/to/file.ts` | 🔄 进行中 | [已完成什么,剩余什么] | | `path/to/file.ts` | ❌ 损坏 | [问题所在] | | `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` | ✅ 已完成 | 工作正常,已测试 | | `app/api/auth/login/route.ts` | 🔄 进行中 | 令牌已生成但尚未设置 cookie | | `lib/auth.ts` | ✅ 已完成 | 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/sessions/` * 对于任何新的会话文件,首选短 ID 文件名形式(`YYYY-MM-DD--session.tmp`)