会话管理与状态持久化
会话管理与状态持久化
学习目标
本章要解决什么问题:理解 ECC 如何在 Claude Code 的会话之间保持上下文连续性。
读完本章后,你将了解:
- SessionStart/PreCompact/Stop 钩子在会话生命周期中的角色
- SQLite 状态存储的设计与查询能力
- 会话 CLI 工具(/sessions、session-inspect)
- tmux worktree 编排的多会话管理
前置知识
本章涉及记忆系统和 Hook 系统的基础知识,建议先阅读:
项目实践
会话生命周期
ECC 通过 Hook 系统在完整的会话生命周期中管理状态:
关键 Hook 实现
| Hook | 脚本 | 职责 |
|---|---|---|
| SessionStart | scripts/hooks/session-start-bootstrap.js | 加载上次会话状态 + 包管理器检测 + 环境初始化 |
| PreCompact | scripts/hooks/pre-compact.js | 上下文压缩前保存关键状态 |
| Stop (会话持久化) | scripts/hooks/session-end.js | transcript_path 可用时持久化会话状态 |
| Stop (成本追踪) | scripts/hooks/cost-tracker.js | 每会话 Token/费用标记 |
| Stop (模式提取) | scripts/hooks/evaluate-session.js | 评估会话以提取可复用模式 |
| SessionEnd | scripts/hooks/session-end-marker.js | 生命周期标记 + 清理日志 |
SQLite 状态存储
ECC 在 scripts/lib/state-store/ 中实现了 SQLite-backed 的状态管理系统:
存储内容:
- 会话元数据(ID、开始时间、结束时间、模型)
- 工具调用记录
- 成本追踪数据
- 安装操作历史
- 治理事件
为什么选 SQLite:
- 查询能力:
/sessions命令可以按时间、状态过滤 - 并发安全:WAL 模式支持读写并发
- Schema 约束:防止脏数据
- 零部署:单文件数据库
会话 CLI
ECC 提供会话管理的 CLI 工具:
# 查看会话历史node scripts/sessions-cli.js
# 检查特定会话详情node scripts/session-inspect.js <session-id>/sessions 命令列出历史会话,/resume-session 命令恢复上次会话状态。
tmux Worktree 编排
ECC 的 tmux-worktree-orchestrator.js 支持多会话并行管理:
适用场景:
- 多分支并行开发(每个 worktree 对应一个 git 分支)
- 多 Agent 并行(每个 Claude Code 实例处理不同任务)
- 长期运行的会话(tmux 确保不丢失日志)
包管理器检测
SessionStart 钩子自动检测项目的包管理器:
检测顺序:1. 锁定文件存在性 (package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lockb)2. 环境变量 CLAUDE_PACKAGE_MANAGER(用户显式指定)3. 项目配置文件(如 .npmrc / .yarnrc.yml)4. 默认 fallback: npm这使得 ECC 的测试和安装脚本自动使用正确的包管理器。
问题与规避
会话状态膨胀
问题:长期运行的会话积累大量上下文,SQLite 文件变大。
ECC 的规避:
- PreCompact 钩子在压缩前保存关键状态,丢弃非必要信息
- 会话状态文件有大小上限
/clear命令清除当前会话上下文
transcript_path 不可用
问题:Stop 钩子依赖 transcript_path 来持久化会话,但某些环境下 Claude Code 不提供此路径。
规避方案:
- 回退到环境变量
CLAUDE_TRANSCRIPT_PATH - 如果都不可用,跳过持久化(不报错)
- 30 天自动清理过期状态文件
tmux 不可用
问题:Windows 或没有安装 tmux 的环境。
规避方案:
- tmux-worktree-orchestrator 检测 tmux 是否存在
- 不存在时优雅降级(不使用 tmux 功能)
- 跨平台 Node.js 实现(不依赖 shell 脚本)
设计取舍
为什么用 SQLite 而非 JSON 文件?
| 维度 | SQLite | JSON 文件 |
|---|---|---|
| 查询能力 | SQL 查询,支持过滤/排序/聚合 | 需要全部加载后手动过滤 |
| 并发安全 | WAL 模式,读写并发 | 文件锁,易冲突 |
| Schema 约束 | 类型/非空/唯一约束 | 需要手动验证 |
| 容量 | GB 级别无压力 | 大文件解析慢 |
ECC 的选择:会话管理需要查询能力(“最近 10 次会话”、“某天的所有会话”),JSON 文件不支持高效查询。
为什么在 Hook 中管理会话而非独立进程?
ECC v1.x 的会话管理在 Hook 中实现:
- 优势:与 Claude Code 生命周期同步,不需要额外部署
- 代价:无法在 Claude Code 之外管理会话
- ECC 2.0 的改变:Rust 控制平面将提供独立的会话管理(
ecc2 sessions、ecc2 daemon)
参考来源
- 源码验证:
scripts/hooks/session-start-bootstrap.js— SessionStart 钩子 - 源码验证:
scripts/hooks/pre-compact.js— 压缩前状态保存 - 源码验证:
scripts/hooks/session-end.js— 会话持久化 - 源码验证:
scripts/hooks/cost-tracker.js— 成本追踪 - 源码验证:
scripts/lib/state-store/— SQLite 状态存储 - 源码验证:
scripts/sessions-cli.js,scripts/session-inspect.js— 会话 CLI - 源码验证:
scripts/lib/tmux-worktree-orchestrator.js— tmux 编排 - 记忆系统设计 — 通用状态持久化模式