跳转到内容

会话管理与状态持久化

会话管理与状态持久化

学习目标

本章要解决什么问题:理解 ECC 如何在 Claude Code 的会话之间保持上下文连续性。

读完本章后,你将了解:

  • SessionStart/PreCompact/Stop 钩子在会话生命周期中的角色
  • SQLite 状态存储的设计与查询能力
  • 会话 CLI 工具(/sessions、session-inspect)
  • tmux worktree 编排的多会话管理

前置知识

本章涉及记忆系统和 Hook 系统的基础知识,建议先阅读:


项目实践

会话生命周期

ECC 通过 Hook 系统在完整的会话生命周期中管理状态:

关键 Hook 实现

Hook脚本职责
SessionStartscripts/hooks/session-start-bootstrap.js加载上次会话状态 + 包管理器检测 + 环境初始化
PreCompactscripts/hooks/pre-compact.js上下文压缩前保存关键状态
Stop (会话持久化)scripts/hooks/session-end.jstranscript_path 可用时持久化会话状态
Stop (成本追踪)scripts/hooks/cost-tracker.js每会话 Token/费用标记
Stop (模式提取)scripts/hooks/evaluate-session.js评估会话以提取可复用模式
SessionEndscripts/hooks/session-end-marker.js生命周期标记 + 清理日志

SQLite 状态存储

ECC 在 scripts/lib/state-store/ 中实现了 SQLite-backed 的状态管理系统:

存储内容

  • 会话元数据(ID、开始时间、结束时间、模型)
  • 工具调用记录
  • 成本追踪数据
  • 安装操作历史
  • 治理事件

为什么选 SQLite

  • 查询能力:/sessions 命令可以按时间、状态过滤
  • 并发安全:WAL 模式支持读写并发
  • Schema 约束:防止脏数据
  • 零部署:单文件数据库

会话 CLI

ECC 提供会话管理的 CLI 工具:

Terminal window
# 查看会话历史
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 文件?

维度SQLiteJSON 文件
查询能力SQL 查询,支持过滤/排序/聚合需要全部加载后手动过滤
并发安全WAL 模式,读写并发文件锁,易冲突
Schema 约束类型/非空/唯一约束需要手动验证
容量GB 级别无压力大文件解析慢

ECC 的选择:会话管理需要查询能力(“最近 10 次会话”、“某天的所有会话”),JSON 文件不支持高效查询。

为什么在 Hook 中管理会话而非独立进程?

ECC v1.x 的会话管理在 Hook 中实现:

  • 优势:与 Claude Code 生命周期同步,不需要额外部署
  • 代价:无法在 Claude Code 之外管理会话
  • ECC 2.0 的改变:Rust 控制平面将提供独立的会话管理(ecc2 sessionsecc2 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 编排
  • 记忆系统设计 — 通用状态持久化模式