ECC /sessions 命令全解析:Claude Code 会话历史、别名与元数据的清单化管理 ECC /sessions 命令全解析Claude Code 会话历史、别名与元数据的清单化管理【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC本篇技术指南聚焦 ECCEverything Claude Code仓库中的/sessions会话管理命令文档入口见 commands/sessions.md系统讲解如何对存放在~/.claude/session-data/兼容读取旧版~/.claude/sessions/下的 Markdown 会话文件进行列表、加载、别名、统计与信息查询。读完本文你将掌握/sessions全部子命令与参数语义理解其背后的会话文件命名与解析规则、别名 JSON 的写入与校验机制并能在多分支 / 多 worktree 并行工作的场景中把它用成可靠的“运营控制台”。会话历史管理的目标与使用场景Claude Code 本身会以“日期 短 ID”的形式为每次会话留下历史文件但当会话数量积累到一定规模后单纯依靠目录浏览无法回答三个高频问题这次会话是什么时候、在哪个项目 / 分支 / worktree 上发生的里面完成了多少任务能不能用一个好记的名字快速找回它/sessions命令正是为回答这些问题而设计的。它的输入输出面向两类使用者单个开发者查找某一天的会话、按短 ID 加载内容、为高频会话建立别名operator / 编排者在并行 tmux、多 worktree、swarm 场景中通过/sessions info拿到 branch、worktree 路径与会话新鲜度判断每个运行实例的归属与状态。底层数据模型会话文件与别名的存放约定/sessions并不维护自有的数据库而是直接读写两个位置的文本文件数据存放位置说明会话内容$ECC_AGENT_DATA_HOME/session-data/默认~/.claude/session-data/主目录Markdown 格式的会话快照文件扩展名为.tmp旧版会话$ECC_AGENT_DATA_HOME/sessions/默认~/.claude/sessions/旧安装遗留目录只读兼容search / list / load 时会被扫描别名映射$ECC_AGENT_DATA_HOME/session-aliases.json默认~/.claude/session-aliases.json记录“别名 → 会话文件”的映射及元数据路径解析的精确实现位于 scripts/lib/utils.jsgetClaudeDir()实际委托给getAgentDataHome()即 scripts/lib/agent-data-home.js 中的resolveAgentDataHome()支持通过环境变量自定义数据根目录getSessionsDir()拼接session-datagetLegacySessionsDir()拼接sessions而getSessionSearchDirs()则用Set去重后返回[session-data, sessions]的规范目录优先顺序。文件名即元数据SESSION_FILENAME_REGEX会话文件能否被识别取决于文件名是否匹配 scripts/lib/session-manager.js 中的正则/^(\d{4}-\d{2}-\d{2})(?:-([a-zA-Z0-9_][a-zA-Z0-9_-]*))?-session\.tmp$/据此存在两种合法形态2026-02-01-session.tmp # 旧格式无短 ID同日只能有一个 2026-02-01-a1b2c3d4-session.tmp # 新格式带短 ID可同日并存 2026-02-01-frontend-worktree-1-session.tmp # 短 ID 允许字母、数字、下划线、连字符解析器parseSessionFilenamesession-manager.js会做两项严格校验日历级校验不仅检查YYYY-MM-DD格式还会用Date回读月份与日拒绝2026-02-31这类“格式合法但日历不存在”的文件名本地时区构造刻意用new Date(year, month-1, day)而非new Date(dateStr)避免YYYY-MM-DD被按 UTC 零点解析后在负 UTC 偏移时区显示成前一天。旧格式无短 ID 的会话统一被标记为shortId no-id因此在列表与加载时你会看到它们以日期而非 ID作为身份。相关命名规则在配套的 commands/save-session.md 中有更详细的规定新建文件推荐使用 8 个字符以上的小写字母 / 数字 / 连字符组合作为短 ID以规避同日碰撞。会话文件头部以 Markdown 形式固化控制面元数据parseSessionMetadatasession-manager.js从会话正文中提取以下字段这些正是/sessions list与/sessions info展示信息的来源元数据字段解析来源用途title首个#一级标题会话的可读摘要date/started/lastUpdated正文中**Date:**、**Started:**、**Last Updated:**标记时间维度检索project/branch/worktree正文中**Project:**、**Branch:**、**Worktree:**行并行实例归属判定completed### Completed小节中的- [x]条目完成量统计inProgress### In Progress小节中的- [ ]条目进行中任务统计notes### Notes for Next Session小节下轮会话提示context### Context to Load后的代码块可恢复的上下文“头部固化 Project / Branch / Worktree”是/sessions能在并行场景中工作的关键设计——它让纯文本会话文件具备了操作面可查询的“结构化字段”具体生成这些文件的方式见配套命令文档 commands/save-session.md保存会话与 commands/resume-session.md恢复会话。命令语法与参数总览/sessions [list|load|alias|info|help] [options]动作语法作用list默认/sessions list [options]带元数据、过滤与分页地列出全部会话load/sessions load id\|alias加载并展示某会话内容与统计alias/sessions alias id name为会话创建别名alias --remove/sessions alias --remove name删除别名等价unaliasinfo/sessions info id\|alias展示会话统计信息aliases/sessions aliases列出全部别名help/sessions help显示帮助list的可选参数--limit n最多显示的会话数默认 50--date YYYY-MM-DD按日期过滤--search pattern按会话短 ID 模糊搜索。ID 有三种定位方式日期用于no-id旧格式会话、短 ID如a1b2c3d4、别名如my-alias。其中短 ID 采用前缀匹配通常前 4~8 个字符已足够唯一详见下文getSessionById的实现逻辑。列表会话过滤、分页与操作面视图默认执行list子命令等价于直接输入/sessions/sessions # 列出全部会话默认行为 /sessions list # 同上 /sessions list --limit 10 # 只看最近 10 个 /sessions list --date 2026-02-01 # 只看某一天的会话 /sessions list --search abc # 短 ID 中包含 abc 的会话文档中给出了可独立运行的等价格式化脚本这里保留其完整逻辑其中_r前缀用于在 Claude Code 插件环境中解析 ECC 根目录详细兜底顺序见后文“脚本执行原理”node -e const _r (function(){var prequire(path),frequire(fs),orequire(os);var eprocess.env.CLAUDE_PLUGIN_ROOT;if(ee.trim())return e.trim();var dp.join(o.homedir(),.claude);function L(x){try{return require(p.join(x,scripts,lib,resolve-ecc-root)).resolveEccRoot()}catch(_){return null}}var rL(d);if(r)return r;var s[ecc,eccecc,marketplaces/ecc,everything-claude-code,everything-claude-codeeverything-claude-code,marketplaces/everything-claude-code];for(var i0;is.length;i){rL(p.join(d,plugins,s[i]));if(r)return r}try{var g[ecc,everything-claude-code];for(var j0;jg.length;j){var cp.join(d,plugins,cache,g[j]);var Of.readdirSync(c);for(var k0;kO.length;k){var qp.join(c,O[k]);var Vf.readdirSync(q);for(var m0;mV.length;m){rL(p.join(q,V[m]));if(r)return r}}}}catch(_){}return d})(); const sm require(_r /scripts/lib/session-manager); const aa require(_r /scripts/lib/session-aliases); const path require(path); const result sm.getAllSessions({ limit: 20 }); const aliases aa.listAliases(); const aliasMap {}; for (const a of aliases) aliasMap[a.sessionPath] a.name; console.log(Sessions (showing result.sessions.length of result.total ):); console.log(); console.log(ID Date Time Branch Worktree Alias); console.log(────────────────────────────────────────────────────────────────────); for (const s of result.sessions) { const alias aliasMap[s.filename] || ; const metadata sm.parseSessionMetadata(sm.getSessionContent(s.sessionPath)); const id s.shortId no-id ? (none) : s.shortId.slice(0, 8); const time s.modifiedTime.toTimeString().slice(0, 5); const branch (metadata.branch || -).slice(0, 12); const worktree metadata.worktree ? path.basename(metadata.worktree).slice(0, 18) : -; console.log(id.padEnd(8) s.date time branch.padEnd(12) worktree.padEnd(18) alias); } 输出表的每一列都来自不同的数据面ID取自文件名解析出的shortId无 ID 的旧会话显示为(none)Date / Time取自文件名日期与文件mtimeBranch / Worktree来自会话正文头部元数据Alias来自session-aliases.json。这正好对应文档中“列表即运营视图”的定位——用一屏看清“哪个 worktree 上发生过什么”。分页与排序的实现语义getAllSessionssession-manager.js是列表动作的后端核心需要注意三点实现细节安全钳制offset/limit先做数值化再做非负整数钳制避免负数 offset 让slice()从尾部倒着数、或NaN导致返回空结果注释专门指出不能用|| default因为0是 falsy去重顺序候选会话先按规范目录优先收集再按文件名去重——若新旧目录存在同名文件以session-data为准排序统一按modifiedTime倒序因此--limit 10语义是“最近修改的 10 个会话”。扫描目录时的健壮性也有专门处理目录不存在直接跳过读取目录失败只记录日志不中断文件 stat 失败同样跳过。文件系统时间戳方面resolveCreatedTimesession-manager.js优先取birthtime仅在birthtimeMs 0时回退ctime——这是为了兼容容器 overlayfs 等把 birthtime 报为纪元 0 的场景该情形下birthtime || ctime的回退会失效因为Date对象恒为 truthy必须比较毫秒。加载与信息查询短 ID 前缀匹配机制load用于把某次会话完整调出支持三种定位符/sessions load 2026-02-01 # 按日期针对无 ID 的旧会话 /sessions load a1b2c3d4 # 按短 ID /sessions load my-alias # 按别名完整脚本如下注意先尝试把参数当作别名解析解析成功则用其sessionPath否则把原参数当作 ID 继续查询node -e const _r /* 同前文 ECC 根目录解析前缀略 */; const sm require(_r /scripts/lib/session-manager); const aa require(_r /scripts/lib/session-aliases); const id process.argv[1]; // First try to resolve as alias const resolved aa.resolveAlias(id); const sessionId resolved ? resolved.sessionPath : id; const session sm.getSessionById(sessionId, true); if (!session) { console.log(Session not found: id); process.exit(1); } const stats sm.getSessionStats(session.sessionPath); const size sm.getSessionSize(session.sessionPath); const aliases aa.getAliasesForSession(session.filename); console.log(Session: session.filename); console.log(Path: session.sessionPath); console.log(); console.log(Statistics:); console.log( Lines: stats.lineCount); console.log( Total items: stats.totalItems); console.log( Completed: stats.completedItems); console.log( In progress: stats.inProgressItems); console.log( Size: size); console.log(); if (aliases.length 0) { console.log(Aliases: aliases.map(a a.name).join(, )); console.log(); } if (session.metadata.title) console.log(Title: session.metadata.title); if (session.metadata.started) console.log(Started: session.metadata.started); if (session.metadata.lastUpdated) console.log(Last Updated: session.metadata.lastUpdated); if (session.metadata.project) console.log(Project: session.metadata.project); if (session.metadata.branch) console.log(Branch: session.metadata.branch); if (session.metadata.worktree) console.log(Worktree: session.metadata.worktree); $ARGUMENTS底层的 ID 匹配逻辑在sessionMatchesId/getMatchingSessionCandidatessession-manager.js它同时支持三种命中短 ID 前缀metadata.shortId.startsWith(normalizedSessionId)——这正是“前 4~8 位通常足够唯一”的代码来源完整文件名参数等于filename或filename .tmp无 ID 旧会话按日期shortId no-id且filename 参数-session.tmp即传入2026-02-01可命中2026-02-01-session.tmp。多个候选命中时按modifiedTime倒序取第一个因此“今天有多个带短 ID 的会话”时load 今天日期只会命中那个无 ID 旧文件——带短 ID 的会话必须用短 ID 精确定位。统计口径与性能细节info子命令与load共享几乎相同的脚本骨架仅输出排版不同使用════分隔线与固定字段名二者统计字段的含义定义于getSessionStatssession-manager.jstotalItems completed inProgress依据 Markdown 中- [x]/- [ ]条目数lineCount按换行符计数hasNotes/hasContext标记会话是否带有可恢复的上下文。实现上的一个优化是getSessionStats接受“预读内容字符串”若调用方已持有正文就无需二次磁盘读取它通过“不含换行、以.tmp结尾、以/或盘符开头”来判断参数是路径还是内容。文件大小展示由getSessionSizesession-manager.js按B / KB / MB格式化。别名的增删查命名约束与原子写入创建别名/sessions alias 2026-02-01 today-work # 为 2026-02-01 的会话创建别名 today-work /sessions alias id name # 通用形式脚本内部先通过sm.getSessionById(sessionId)找到会话取session.filename后调用aa.setAlias(aliasName, session.filename)成功输出✓ Alias created: name → filename失败输出✗并携带错误信息、以非零码退出。删除与列举/sessions alias --remove name # 删除别名 /sessions unalias name # 同上 /sessions aliases # 列出全部别名删除脚本调用aa.deleteAlias(aliasName)列举脚本调用aa.listAliases()无别名时提示No aliases found.否则以Name / Session File / Title三列排版输出会话文件过长时截断到 27 字符加...。别名的 JSON 存储与校验规则别名存储层在 scripts/lib/session-aliases.js 中实现单文件承载全部映射结构带版本号与元数据{ version: 1.0, aliases: { today-work: { sessionPath: 2026-02-01-a1b2c3d4-session.tmp, createdAt: 2026-02-01T08:00:00.000Z, updatedAt: 2026-02-01T09:30:00.000Z, title: null } }, metadata: { totalCount: 1, lastUpdated: 2026-02-01T09:30:00.000Z } }setAliassession-aliases.js强制三类约束违反时直接返回失败而不是静默写入长度1 ~ 128 字符字符集仅允许字母、数字、连字符、下划线即/^[a-zA-Z0-9_-]$/保留字list、help、remove、delete、create、set不可用作别名避免与命令动作冲突。同一函数还承担“更新”职责若别名已存在则保留其createdAt刷新updatedAt与可选的title。deleteAlias删除不存在的别名会返回Alias name not found。库中还内置了renameAlias重命名失败时回滚并重写旧映射、getAliasesForSession反查某会话的全部别名、cleanupAliases通过注入的sessionExists回调清理指向已删除会话的僵尸别名等供上层脚本与 hooks 调用的工具方法。防损坏写入备份 原子 rename别名文件虽小却是高频读写的索引因此saveAliasessession-aliases.js实现了“临时文件 备份 原子 rename”三段式写入先写session-aliases.json.tmp平台差异处理Windows 上rename到已存在目标会报EEXIST须先unlink目标Unix / macOS 上rename(2)本身就是原子替换刻意跳过 delete 以避免制造“先删后写”的非原子窗口失败时从.bak备份恢复并尽力清理临时文件。解析损坏 JSON 时loadAliases会记录日志并按默认结构重置避免一处坏数据导致整个别名系统不可用。脚本执行原理ECC 根目录的自举解析文档中所有node -e脚本都以一段近 20 行的自举代码开头其作用是把变量_r解析为ECC 插件根目录再require(_r /scripts/lib/...)加载库模块。兜底顺序依次为环境变量CLAUDE_PLUGIN_ROOT显式指定时最高优先~/.claude/scripts/lib/resolve-ecc-root的resolveEccRoot()~/.claude/plugins/下的常见安装名ecc、eccecc、marketplaces/ecc、everything-claude-code、everything-claude-codeeverything-claude-code、marketplaces/everything-claude-code插件缓存目录~/.claude/plugins/cache/下的ecc/everything-claude-code逐层探测全部失败则回退到~/.claude。该自举逻辑依赖 scripts/lib/resolve-ecc-root.js 提供实际解析能力。这意味着文档中的每一段脚本都能在 Claude Code 插件被安装到任意位置含 marketplace 别名与缓存目录时依然找到正确的库文件——这也是node -e单行脚本能脱离命令注册表独立运行的原因。运行任一脚本时$ARGUMENTS会被替换为当前命令的入参并注入process.argv供load / alias / unalias / info等脚本取用。Operator 实践多 worktree / swarm 场景的会话定位原文档“Operator Notes”给出的两条实战经验值得展开用头部元数据消除并行歧义会话文件会在头部持久化Project、Branch、Worktree因此/sessions info可以准确回答“这条会话到底跑在哪个仓库的哪个 worktree 上”。在多分支并行可参考 commands/multi-execute.md、commands/multi-workflow.md 的编排场景或 tmux 多窗格同时运行多个 Claude Code 实例时文件名里的日期与短 ID 往往雷同头部字段才是区分的可靠依据。拼接“指挥中心”式监控将/sessions info的会话统计、git diff --stat的代码变更概览、以及 scripts/hooks/cost-tracker.js 通过 hooks 输出的 token / 成本指标三者组合即可在单屏内同时观察“会话进行度 变更规模 成本消耗”。成本侧指标的具体 hook 集成与上报路径可在 scripts/hooks/cost-tracker.js 及其测试中进一步确认。补充一点版本背景/sessions面向 Claude Code 的 Markdown 会话文件与仓库中另一入口 scripts/sessions-cli.js面向 SQLite state store 的 ECC 会话查询 CLI输出 worker、skill-run、decision 详情并不冲突——前者管理 Claude Code 原生历史后者面向 ECC 自身的结构化状态存储两者服务不同的数据面。典型操作演练将上述子命令串成一条完整工作流# 1. 列出全部会话快速浏览最近的运行实例 /sessions list # 2. 为今天的会话建立一个好记的别名 /sessions alias 2026-02-01 today # 3. 通过别名加载会话内容或查看其统计信息 /sessions load today /sessions info today # 4. 查看所有已建别名确认没有重复或拼写错误 /sessions aliases # 5. 清理删除不再需要的别名 /sessions alias --remove today /sessions unalias today # 等价写法注意事项与边界最后是与数据安全直接相关的四条约定会话以 Markdown 文件存放于session-data/旧数据可继续从sessions/被读取但新写入应落在session-data/目录与文件位置由ECC_AGENT_DATA_HOME/~/.claude决定别名统一存储在session-aliases.json单点索引版本1.0写入带原子性保护不要把别名信息散落在会话文件内短 ID 支持前缀匹配前 4~8 个字符通常已足够唯一无短 ID 的旧格式会话只能按日期定位且同一日期只能存在一个对高频复用的会话建议使用别名既避免记忆长 ID也让/sessions list的运营视图更易读。若需进一步验证上述行为仓库测试 tests/lib/session-manager.test.js覆盖文件名解析、日期日历校验、短 ID 前缀匹配、分页语义等与 tests/lib/session-aliases.test.js覆盖命名校验、保留字、增删改查提供了可直接运行的行为规格可配合文档交叉阅读。【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考