会话清理
先审计,再删除,而且要在检查目标之后进行。目标是让仓库拥有者可以安心离开会话,知道没有东西在运行,没有东西丢失,也没有过时的遗留物。遗漏一个遗留物代价很小;但删除一个未推送的提交则代价高昂。有疑问时,发现项应标记为 询问(ASK) ,绝不自动清理。
适用于任何 Git 仓库。状态管理器(lanes harness)、珠子(beads)和 Vercel 部分仅在存在时启用;否则静默跳过。
第一阶段:审计(只读)
从仓库(或其任意工作树)运行捆绑的审计脚本。使用适合你操作系统的脚本;技能文件夹可能位于 ~/.claude/skills/、~/.codex/skills/ 或 ~/.agents/skills/:
# Linux 和 macOS
bash <技能目录>/scripts/audit.sh # 加 --no-fetch 可在离线时使用
# Windows(PowerShell 5.1 或 7)
powershell -NoProfile -ExecutionPolicy Bypass -File <技能目录>\scripts\audit.ps1 # 加 -NoFetch 可在离线时使用
两个脚本都会按区域打印出各个部分(上下文、工作树、同步、工作树、分支、贮藏、状态管理器、进程、产物、追踪器、部署、会话日志)。其唯一的写入操作是简单的 git fetch(从不加 --prune)。它从不读取 .env 文件或打印进程环境。
关于“本次会话”的判定方式(这对所有分类都很重要):
- 进程:
owner=this_session表示本次会话(或其启动的对象)启动了该进程。在 Linux 上,这通过继承的CLAUDE_CODE_SESSION_ID来证明,该 ID 在nohup后依然存在。macOS 和 Windows 会隐藏其他进程的环境,因此在那里它表示“Claude 进程的后代”(CLAUDE_PID);一个被分离并重新父进程化的进程会显示为started_during_session,这属于询问(ASK),除非你能在当前对话中追溯它。owner=harness_do_not_kill是 Claude Code 自己的 MCP 服务器和插件:绝不要碰它们。other_session_or_user是其他人的。 - 文件、分支、贮藏:
this_session/pre_session是通过将时间戳与会话开始时间(本次会话转录中的第一个时间戳)进行比较来判定的。时间戳只是一个提示,而非证据:在会话窗口期间创建的内容可能来自并行会话。只有当时间戳显示为本次会话 并且 你能在当前对话中追溯它(是你运行了创建它的命令)时,才将其视为本次会话的。否则,它属于询问(ASK)。
在 Claude Code 之外(例如在 Codex 中),不存在 CLAUDE_CODE_SESSION_ID 或 CLAUDE_PID,因此 session_id 为 unknown,所有内容都标记为 pre_session,进程仅通过 in_repo 匹配。如果你知道会话开始时间,请传递 --since <ISO 时间>(Windows 上为 -Since);否则,除非你能在当前对话中将其追溯到你运行的命令,否则将文件和进程视为询问(ASK)。
然后,填补脚本无法看到的空白,尽可能并行进行:
- 你自己的后台工作。 列出你在本次对话中启动且仍在运行的后台 Bash 任务、监控器、子代理和定时唤醒。使用启动它们的工具(TaskStop、Monitor stop 等)停止已完成或空闲的任务。
- 请求遗留物。 扫描对话,查找仓库拥有者要求稍后删除或仅临时保留的内容(如上传文件夹、调试标志、测试账号、临时文件)。检查它是否仍然存在。
- 部署状态(仅当 DEPLOY 部分显示了平台时才进行)。获取最新生产部署的提交 SHA,并将其与
main_tip进行比较。对于 Vercel:使用vercel ls --prod查找最新的生产部署,然后使用vercel inspect <url>(或 Vercel MCP / 仪表板)获取其 Git 提交。如果你无法获取 SHA,则报告“部署:未验证”并说明原因。切勿通过时间戳推断匹配。 - 会话接触过的仓库之外的任何内容(另一个仓库的工作树、全局安装)。报告它,不要修改它。
第二阶段:对每个发现分类
自动清理(AUTO-CLEAN)(安全且可恢复;执行,然后报告):
- 完全合并到主分支的本地分支(使用
git branch -d,绝不使用-D),排除主分支、当前分支以及任何在工作树中检出的分支。 - 文件夹已不存在的可修剪工作树记录(
git worktree prune)。 - 此仓库内已链接的干净工作树,其分支已合并到主分支且没有领先的提交(
git worktree remove <路径>,不加--force;然后git branch -d)。如果状态管理器(lanes harness)拥有它,则改用状态管理器脚本(见下文)。 - 其 lane 或分支不再存在且没有任何进程打开该文件夹的临时文件夹(
open_handles=0;立即删除前使用lsof +D <目录>重新检查)。 owner=this_session的进程,你能在当前对话中追溯它,且该进程处于空闲或不再需要状态(开发服务器、监听器、无头浏览器)。仅通过 PID 终止(Linux/macOS 上用kill <pid>,Windows 上用Stop-Process -Id <pid>)。- 过时的构建类型缓存(
.next/types、.next/dev/types),这些文件被 gitignore 忽略,会在下次构建时重新生成。 - 本次会话在其草稿板文件夹中的临时文件,以及仓库中属于
this_session并且 可以追溯到你运行的命令的未跟踪垃圾文件(*.orig、*.rej、零散的日志文件)。
询问(ASK)(可能丢失工作,或无法证明属于本次会话):
- 未合并的分支,或任何不在主分支中的提交。标记为
PATCHES_ALREADY_IN_main的分支很可能是压缩合并(squash)或变基合并(rebase)的:要说明这一点,但仍然在-D之前询问。 - 脏工作树(
dirty_files > 0)、贮藏(stashes)、coverage/和test-results/,这些可能需要作为证据。 other_session_or_user或started_during_session的进程,以及任何你无法追溯的进程。- 任何
pre_session的内容,以及任何不是你创建的未跟踪文件。
仅报告(REPORT ONLY)(由仓库拥有者操作,或仅为信息性):
- 主分支与远程分支之间的差异(未推送或落后)。建议推送或拉取;不要将其作为清理的一部分执行。
- 部署不匹配或“未验证”的部署状态。
- 没有进行中工作但有未完成任务项(beads 中的
in_progress、tasks.md 中的 WIP),以及工作已完成但其任务仍处于打开状态的情况。指出该项的名称和你看到的内容。 - 此仓库之外的工作树或文件夹,以及仍有独特提交的
upstream_gone分支。
安全规则
这些规则保护无法重新创建的工作。每一条的存在是因为明显的捷径曾经破坏过工作。
- 删除前检查。 对于每个文件夹,先列出其内容和大小。对于每个分支,先显示
git log --oneline main..<分支>。将证据放在报告中。 - 未经仓库拥有者明确批准,绝不删除未合并的提交、脏工作树或贮藏。批准一项不意味着批准下一项。
- 仅通过 PID 终止进程,在确认
owner=this_session且是你启动的后。首次尝试绝不使用pkill、killall、kill -9或仅凭端口终止。 - 绝不使用裸
git stash、git reset --hard、git clean -fdx(或任何git clean -f),或带通配符的rm -rf。这些操作无法撤销。一次删除一个具名路径。 git branch -D、git stash drop和git worktree remove --force仅在仓库拥有者批准了单个项目后运行,并在运行前展示将会丢失的内容(提交、差异统计)。在报告中记录分支顶点的 SHA,以便可以恢复。- 绝不读取、打印、移动或删除
.env文件、密钥或凭据,即使它们看起来像是垃圾。仅通过路径报告它们。 - 停留在此仓库内。 其他应用的工作树、分离的检出或共享的
/tmp文件夹仅报告,不触碰。绝不要在/tmp中使用通配符删除。 - 绝不终止
harness_do_not_kill进程或 Claude 进程本身。
当状态管理器(lanes harness)存在时
仅当 LANES 部分显示了一个状态目录时才执行此块。否则跳过此块。
- 使用状态管理器自己的脚本(而不是
rm)移除 lane 工作树、lane 临时目录、中继作业目录和lanes.tsv中的行:对于已合并的 lane,运行bash ~/.claude/skills/lanes/lane/cleanup.sh <lane-dir> <branch>,然后运行bash ~/.claude/skills/lanes/lane/cleanup.sh --sweep。在主工作树中运行。 WORKTREE_MISSING和BRANCH_MERGED的行通过 sweep 处理。未合并 lane 的行属于询问(ASK)。- 仍在运行(没有
rc文件)的中继作业仅报告(REPORT ONLY);状态管理器看门狗拥有它们。 - 在
/lanes会话中,主 lane 是集成的;不要删除工作尚未合并到 origin/main 的 lane 分支。
没有状态管理器时,.claude/worktrees/ 下的工作树(例如来自 Claude Code 的 EnterWorktree)遵循上述纯 Git 规则。
第三阶段:报告
精确使用此结构。保持可扫描性;仓库拥有者会在一个长会话结束时阅读它。
## 会话清理
**已清理:** 工作树、同步、工作树、分支、贮藏、进程、产物、追踪器、部署
(仅列出已通过的检查区域)
**已清理**
- `feat/login-form` 分支:已合并到 main 于 a1b2c3d,领先 0 个提交。使用 `git branch -d` 删除(恢复:`git branch feat/login-form a1b2c3d`)。
- `python3 -m http.server 3000`(PID 170308):由本次会话启动用于预览,已空闲。已停止。
- `.next/types`(1.2M):被 gitignore 忽略,会在构建时重新生成。
**需要您决定**
- `feat/wip` 分支:1 个提交不在 main 中(“wip: draft parser”),上次提交 2 小时前,关联任务 bd-42 进行中。
继续保留(保持它)还是放弃(`git branch -D feat/wip`)?
- `stash@{0}` “On main: sc test stash”,5 天前。应用还是删除?
**仅报告**
- main 领先 origin/main 2 个提交(未推送)。建议推送。
- 生产部署:未验证(vercel CLI 未登录)。
**后续操作**
- 运行 `git worktree list`,预期仅看到主工作树。
- 运行 `git status --short`,预期无输出。
报告的规则:
- 每个“已清理”行说明它是什么、其大小(对于文件和文件夹)以及为什么是安全的。对于分支,要包含顶点 SHA 以便可以恢复。
- 每个“需要您决定”项目给出做出决定所需的事实(存在时间、提交数量、提交主题、关联任务)以及两个具体选项。
- 除非审计或本次会话中的某个命令显示了该区域是干净的,否则绝不说一个区域是干净的。如果某个检查被跳过(离线、缺少 CLI、没有权限),在“仅报告”下说明。
- 后续操作始终包含至少一个验证命令及其预期输出。
在仓库拥有者回答了询问(ASK)项目后,精确执行他们所批准的内容,重新运行相关的审计部分,并报告结果。
日志记录
如果仓库有一个会话日志文件夹(SESSION_LOG 显示 _sessions/ 或类似),追加一条简短的清理记录:日期、清理了什么、等待仓库拥有者处理什么。仅当项目的规则允许提交会话日志时才提交它;请检查 CLAUDE.md 或文件夹的忽略状态(ignored=yes 表示不要提交)。
范围外
重构、lint 修复、死代码移除和依赖升级。如果你注意到它们,将其记录为积压项(记忆或追踪器)并用一行提及。推送、拉取和部署也不在范围内:建议它们,不要执行它们。