skillhub-163-sessions
217 行
12 KiB
Markdown
217 行
12 KiB
Markdown
---
|
||
name: sessions
|
||
description: "搜索并询问关于 Claude Code、Codex 和 Cursor 中编码代理会话历史的问题。当需要了解之前做过什么、之前尝试过什么、跨会话如何调查一个问题、最近发生了什么,或任何关于过去代理会话的问题时使用。当用户提及先前的会话、之前的尝试或过去的调查时也可使用——即使没有明确提到'sessions'一词。"
|
||
---
|
||
|
||
# /sessions(从 EveryInc/compound-engineering-plugin ce-sessions 安装)
|
||
|
||
跨 Claude Code、Codex 和 Cursor 搜索会话历史,综合总结之前处理过、尝试过、决定过或学到过的内容。
|
||
|
||
## 用法
|
||
|
||
```
|
||
/ce-sessions [问题或主题]
|
||
/ce-sessions
|
||
```
|
||
|
||
## 预解析上下文
|
||
|
||
**Git 分支(预解析):** !`git rev-parse --abbrev-ref HEAD 2>/dev/null || true`
|
||
|
||
如果上述行解析为一个简单的分支名(如 `feat/my-branch`),则将其用于分支过滤,并传递给综合子代理。如果它仍然包含反引号命令字符串或为空,则在运行时推导分支名。
|
||
|
||
**仓库名称(预解析):** !`basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || true`
|
||
|
||
如果上述行解析为一个简单的仓库文件夹名,则将其用于会话发现。否则在运行时推导。
|
||
|
||
## 注意:2026 年
|
||
|
||
当前年份是 2026 年。在解释会话时间戳时使用此信息。
|
||
|
||
## 防护规则
|
||
|
||
以下规则在编排和综合过程中始终适用。
|
||
|
||
- **绝不要将会话文件整体读入上下文。** 会话文件可能达到 1-7MB。始终先使用提取脚本进行过滤,然后在过滤后的输出上进行分析。
|
||
- **绝不要逐字提取或复现工具调用的输入/输出。** 只需总结尝试了什么以及发生了什么。
|
||
- **绝不要包含思考或推理块的内容。** Claude Code 思考块是内部推理;Codex 推理块已加密。两者均不可操作。
|
||
- **绝不要分析当前会话。** 其对话历史已对调用者可用。
|
||
- **呈现技术内容,而非个人内容。** 会话包含所有内容——凭据、情绪、不成熟的意见。请自行判断哪些内容属于技术总结,哪些不属于。
|
||
- **访问出错时快速失败。** 如果由于权限问题导致会话发现失败,立即报告问题。不要使用不同的工具或方法重试同一操作——重复重试只会浪费 token 而不会改变结果。
|
||
|
||
## 执行
|
||
|
||
如果未提供问题参数,则询问用户想了解会话历史中的什么内容。使用平台的阻塞式提问工具:Claude Code 中的 `AskUserQuestion`(如果其 schema 尚未加载,先调用 `ToolSearch` 并指定 `select:AskUserQuestion`),Codex 中的 `request_user_input`,Gemini 中的 `ask_user`,Pi 中的 `ask_user`(需要 `pi-ask-user` 扩展)。仅当阻塞式工具在 harness 中不存在或调用出错时(如 Codex 编辑模式),才回退到纯文本提问。绝不要因需要加载 schema 而静默跳过提问。
|
||
|
||
### 第 1 步——确定扫描窗口
|
||
|
||
从用户的问题推断时间范围。从窄窗口开始;仅在窄窗口未找到相关内容时才扩大窗口。
|
||
|
||
| 信号 | 初始扫描窗口 |
|
||
|------|---------------------|
|
||
| "今天"、"今天上午" | 1 天 |
|
||
| "最近"、"最近几天"、"这周"、或未给出时间信号 | 7 天 |
|
||
| "最近几周"、"这个月" | 30 天 |
|
||
| "最近几个月"、广泛的功能历史 | 90 天 |
|
||
|
||
Claude Code 默认保留约 30 天的会话历史。除非用户延长了保留期限,否则更宽的窗口可能在 Claude Code 上找不到任何内容。
|
||
|
||
### 第 2 步——发现会话并提取元数据
|
||
|
||
运行发现 + 元数据管道(保留空分隔符 xargs 加固机制,使 `extract-metadata.py` 能以批处理模式运行):
|
||
|
||
```bash
|
||
bash scripts/discover-sessions.sh <repo> <days> | tr '\n' '\0' | xargs -0 python3 scripts/extract-metadata.py --cwd-filter <repo>
|
||
```
|
||
|
||
每行输出是一个描述会话的 JSON 对象(平台、文件、大小、时间戳、会话 ID,以及平台特定字段)。最后的 `_meta` 行携带 `files_processed` 和 `parse_errors`。
|
||
|
||
如果清单的 `_meta` 行显示 `files_processed: 0`,则返回"未找到相关先前的会话"并停止。
|
||
|
||
如果 `parse_errors > 0`,则注明部分会话无法解析,并继续处理已返回的内容。
|
||
|
||
要缩小平台范围,可在 `discover-sessions.sh` 调用中添加 `--platform claude`、`--platform codex` 或 `--platform cursor`。默认包含所有三个平台。
|
||
|
||
### 第 3 步——过滤和排序
|
||
|
||
按顺序应用以下过滤器,筛选出值得深入分析的会话:
|
||
|
||
1. **分支过滤器(仅 Claude Code)。** 保留 `branch == dispatch_branch` 精确匹配的会话,或分支名包含问题主题关键词的会话(例如,关于"auth 中间件"的问题匹配 `feat/auth-fix`、`chore/auth-refactor` 等分支)。Codex 会话不携带 `gitBranch`——跳过此过滤器。
|
||
|
||
2. **如果分支过滤器返回零个会话,或者你在处理 Codex 会话:**
|
||
- 从问题主题中推导出 2-4 个关键词。例如,对于"auth 中间件中 session-validation 拒绝有效 token 导致最近崩溃"的问题,推导出 `auth,middleware,session,token`(或类似关键词)。
|
||
- 重新运行发现管道,在 `extract-metadata.py` 调用后追加 `--keyword K1,K2,...`。脚本返回 `match_count` 非零的会话以及每个关键词的计数。
|
||
- **如果 `files_matched: 0`,则返回"未找到相关先前的会话"并停止。** 不要提取任何内容。
|
||
- 如果 `files_matched > 0`,则将这些会话视为候选。按 `match_count` 排序,平局时按每个关键词的计数排序。
|
||
|
||
3. **删除扫描窗口之外的会话。** 优先使用 `last_ts`,回退到 `ts`。丢弃两个时间戳都在窗口开始之前的会话。
|
||
|
||
4. **排除当前会话**——其对话历史已对调用者可用。
|
||
|
||
5. **应用深度分析上限。** 在所有平台中最多取 **5 个会话**。按分支匹配 → `match_count` → 文件大小 > 30KB → 最近时间排序。
|
||
|
||
6. **过滤后至少保留一个会话时才继续。** 否则返回"未找到相关先前的会话"并停止。
|
||
|
||
**注意:`gitBranch` 仅在第一条用户消息时捕获。** 一个从 `main` 开始、通过会话中途的 `git checkout` 在功能分支上完成实质性工作的会话,记录的是 `branch: "main"`。分支匹配返回空并不是结论性证据——这就是第 2 步中关键词过滤回退机制存在的原因。
|
||
|
||
### 第 4 步——设置临时工作空间
|
||
|
||
为每次运行创建一个一次性临时工作目录:
|
||
|
||
```bash
|
||
SCRATCH=$(mktemp -d -t ce-sessions-XXXXXX)
|
||
```
|
||
|
||
捕获绝对路径;将其传入第 5 步和第 6 步。操作系统会在会话结束时处理清理工作;在第 7 步末尾显式执行 `rm -rf "$SCRATCH"` 也无害,且能使意图更明确。
|
||
|
||
### 第 5 步——提取每个会话的内容(文件中介)
|
||
|
||
对每个选中的会话,使用 `--output` 运行骨架提取器,使内容直接写入临时文件——提取的字节不会通过编排器的工具结果往返传输:
|
||
|
||
```bash
|
||
python3 scripts/extract-skeleton.py --output "$SCRATCH/<session-id>.skeleton.txt" < <session-file>
|
||
```
|
||
|
||
标准输出仅接收一行 JSON 状态(`{"_meta": true, "wrote": "...", "bytes": N, ...}`)。从每个状态行捕获 `bytes` 和 `parse_errors`。
|
||
|
||
**条件性尾部提取**——如果骨架在调查中途结束(最后一个可见轮次是一个没有解决方案的工具调用,或代理在没有结论的情况下进行调试),则使用 `tail` 格式重新提取:
|
||
|
||
```bash
|
||
python3 scripts/extract-skeleton.py --output "$SCRATCH/<session-id>.skeleton.tail.txt" < <session-file>
|
||
```
|
||
|
||
(骨架脚本本身不直接接受 `tail:N` 上限;如果需要仅尾部视图,可在提取后通过 `tail -n 50` 在 shell 中后处理临时文件。仅在头部输出表明会话在调查中途被截断时使用此方法。)
|
||
|
||
**条件性错误模式**——对于调查死胡同可能有价值的会话:
|
||
|
||
```bash
|
||
python3 scripts/extract-errors.py --output "$SCRATCH/<session-id>.errors.txt" < <session-file>
|
||
```
|
||
|
||
有选择地使用——仅当了解出了什么问题能增加价值时才使用。Cursor 代理记录不记录工具结果,因此错误模式对 Cursor 会话不会产生任何内容。
|
||
|
||
### 第 6 步——调度综合子代理
|
||
|
||
通过平台的子代理原语(Claude Code 中的 `Agent`,Codex 中的 `spawn_agent`,Pi 中的 `subagent`,需要 `pi-subagents` 扩展)调度 `ce-session-historian` 子代理。省略 `mode` 参数,以便应用用户配置的权限设置。在中档模型上运行(例如 Claude Code 中的 `model: "sonnet"`)——合成器不需要前沿推理能力。
|
||
|
||
调度提示是代理的输入合约。传递以下字段:
|
||
|
||
- `problem_topic`——用一句话描述具体问题。从用户参数中提取,如果未提供,则从无参数提示的答案中提取。
|
||
- `scratch_dir`——`$SCRATCH` 的绝对路径。
|
||
- `sessions`——对象数组,每个提取的会话对应一个,包含:
|
||
- `path`——骨架文件的绝对路径(以及提取了错误文件时的 `errors_path`)
|
||
- `platform`——`claude`、`codex` 或 `cursor`
|
||
- `branch`——存在时的 git 分支(仅 Claude Code)
|
||
- `cwd`——存在时的工作目录(仅 Codex)
|
||
- `ts` 和 `last_ts`——会话时间戳
|
||
- `match_count` 和 `keyword_matches`——使用关键词过滤时
|
||
- `output_schema`——代理响应的结构。默认 schema:
|
||
```
|
||
将你的响应组织为以下章节(如无发现则省略对应章节):
|
||
- 之前尝试过的内容
|
||
- 哪些方法无效
|
||
- 关键决策
|
||
- 相关上下文
|
||
```
|
||
当调用者(如 `ce-compound`)在技能参数中提供了 schema,则逐字传递。
|
||
|
||
调度示例格式:
|
||
|
||
```
|
||
综合来自这些先前会话的发现:
|
||
|
||
问题主题:<一行主题>
|
||
|
||
要读取的会话($SCRATCH 中的路径):
|
||
1. /tmp/ce-sessions-XXXX/abc123.skeleton.txt
|
||
platform=claude branch=feat/auth-fix ts=2026-05-01
|
||
2. /tmp/ce-sessions-XXXX/def456.skeleton.txt errors=/tmp/ce-sessions-XXXX/def456.errors.txt
|
||
platform=codex cwd=/Users/.../my-project ts=2026-05-03
|
||
...
|
||
|
||
输出 schema:
|
||
- 之前尝试过的内容
|
||
- 哪些方法无效
|
||
- 关键决策
|
||
- 相关上下文
|
||
|
||
过滤规则:仅呈现与此特定问题直接相关的发现。
|
||
忽略来自同一会话或分支的无关工作。
|
||
```
|
||
|
||
代理通过平台的原生文件读取工具读取每个路径,并返回散文格式的发现。批量提取内容仅存在于代理的子代理上下文中——编排器的工作状态仅保留文件路径和小型清单元数据。
|
||
|
||
### 第 7 步——返回发现
|
||
|
||
将合成器的输出文本逐字返回给调用者。如果发现或关键词过滤返回了零个会话(第 2 步或第 3 步),则改为返回字面字符串 `no relevant prior sessions`。
|
||
|
||
可选地清理临时空间:
|
||
|
||
```bash
|
||
rm -rf "$SCRATCH"
|
||
```
|
||
|
||
操作系统最终无论如何都会处理清理工作;显式清理是为了期望看到它的读者。
|
||
|
||
## 输出
|
||
|
||
当调用者(通常是输入 `/ce-sessions` 的用户,或通过平台技能调用原语调用 ce-sessions 的其他技能)未指定输出格式时,应包含一个简要的头部说明搜索范围:
|
||
|
||
```
|
||
**搜索的会话**: [数量]([N] 个 Claude Code,[N] 个 Codex,[N] 个 Cursor)| [日期范围]
|
||
```
|
||
|
||
然后是合成器的散文式发现。当调用者提供了 schema 时,逐字遵循该 schema,并省略默认头部。
|
||
|
||
## 时间预算
|
||
|
||
一旦获得完整答案,立即停止。如果在几秒钟内就能自信地得出"未找到相关先前的会话",这本身就是一个完整的答案;不要为了填满时间而延长搜索。第 3 步中的结构性上限(最多深度分析 5 个会话)和第 5 步中的条件性尾部/错误提取机制从结构上限制了运行时间。
|
||
|
||
## 错误处理
|
||
|
||
如果发现管道失败(例如,家目录不可读、权限失败),将错误呈现给调用者。不要用 git 日志、文件列表或其他来源替代——此技能的合约是会话元数据和综合。
|
||
|
||
如果提取的 `--output` 写入失败(磁盘满、权限问题),呈现清晰的错误信息,且不要用不完整的路径调度合成器。
|
||
|
||
如果任何脚本的 `_meta` 报告 `parse_errors > 0`,在调度提示中注明部分提取情况,然后继续处理;合成器会在发现中标记不完整的情况。
|