corral:本地编程会话数据接口
September 5, 2026 · View on GitHub
corral 扫描本机 ~/.claude/projects/、~/.codex/sessions/、~/.kimi-code/sessions/、~/.cursor/chats/ 和 OpenCode 的
SQLite 数据库(~/.local/share/opencode/opencode.db,只读打开)下的会话历史,为大模型 Agent
提供结构化查询命令。这些命令只读、无副作用:不会拉起新会话、不会自动接续任务、不会修改
任何历史文件。拿到数据之后要做什么(继续任务、汇总给用户、转发给另一个 Agent)由调用方决定。
所有命令输出统一 JSON envelope,写到 stdout:
{"ok": true, "data": {...}, "error": null, "meta": {"version": 1}}
失败时 ok 为 false,data 为 null,error 包含:
code:程序可判断的错误分类(usage_error/not_found/ambiguous/history_unavailable)message:人类可读的错误说明hint:建议的排查方向next_commands:可以直接执行的后续命令列表
退出码:0 成功、1 一般失败、2 用法错误(参数不对)、3 会话不存在、5 会话标识有歧义。
不要只看 stdout 是否有内容来判断成功,检查退出码或 ok 字段。
命令
跑 corral describe 获取全部命令的机器可读参数说明(与实现同源,不会漂移);
corral describe <command> 看单个命令的完整参数和输出字段。
| 命令 | 用途 |
|---|---|
corral list [--runtime R] [--limit N] [--top N] [--compact] [--status S] [--cwd 子串] [--live] [--fields a,b] | 结构化列出会话 |
corral search <关键词...> [--deep] [--runtime R] [--limit N] [--top N] [--compact] [--live] [--fields a,b] | 按主题找会话 |
corral show <会话> [--messages N | --full] [--compact] [--out 路径] [--fields a,b] | 会话详情 + 对话内容 |
corral share <会话> [--out 路径] [--compact] | 导出含 thinking / 工具调用的统一 transcript,给其他 Agent 做元认知 |
corral export [--since T] [--until T] [--runtime R] [--status S] [--cwd 子串] [--limit N] [--out 路径] [--compact] | 导出某时间范围内所有会话的完整对话,合并为一个 JSON |
corral context <会话> | 生成接续该会话所需的上下文数据包 |
corral plan continue <会话> --instruction <文本> | 生成带新指令的非交互式原生续接计划;只返回数据,不执行 |
corral describe [command] | 查看命令 / 参数 / 输出字段说明 |
corral diagnose | 只读诊断:events.log / embed-error.log / last_error / 截图目录 / tmux / 配色自检 / 安装路径(package_file、install_channel、stale_source_warning);不启动 TUI |
会话标识(<会话> 参数)
支持完整会话 ID、ID 前缀(如 8892cd3d)、或带运行时限定的 runtime:id(如 claude:8892cd3d、
opencode:ses_0ae26219、kimi:session_ef8275b0、cursor:<chat-uuid>)。
前缀在多个运行时之间重复时会返回退出码 5(ambiguous),error.next_commands 里给出具体候选
的 corral show runtime:id 命令,照着执行即可消歧。
典型流程
按主题找到会话并接续未完成的工作:
corral search 天气 app # 快速搜标题/首尾消息/工作目录
corral search 天气 app --top 3 --compact # 只取最相关的 3 条,减少 token
corral search 天气 app --deep # 快速搜没结果时,搜全部对话内容(较慢)
corral show <候选会话的 short_id> # 确认是不是要找的那次会话
corral share <候选会话> --out /tmp/corral-share.json # 含工具调用与 thinking 的统一 transcript
corral show <候选会话> --full --out /tmp/corral-session.json # 纯文本对话(不含工具调用)
corral context <会话> # 拿到 history_path / suggested_prompt / resume_command
corral plan continue <会话> --instruction "继续完成剩余工作并汇报结果" # 只生成外部执行器可运行的计划
corral context 返回的 resume_command 是同运行时原生恢复该会话的 shell 命令(可能为 null,
比如原历史文件已被删除);suggested_prompt 是跨运行时接力时可以直接复用的首条提示词,内含
原会话历史文件路径、格式提示和从原会话自动提取的对话摘录(原始需求 + 最近数条对话,
截断版)——摘录给目标运行时一个任务与进展锚点,原始历史文件仍是权威来源,目标运行时应以摘录
为线索去读取历史、判断已完成和未完成的部分。
corral plan continue 用于调用方需要把同运行时续接交给后台执行器时。它会依据运行时适配器返回
session_ref、runtime、原 cwd、能力边界和 launch;其中 launch.argv 是参数数组,新指令
作为一个独立元素保留,调用方必须以 execve / subprocess 的 argv 形式执行,不能重新拼成 shell
字符串。launch.cwd 为 null 时表示原目录已不可用,调用方应自行拒绝或选择安全的工作目录。
该命令同样只读:不会启动 CLI、不会写入原会话历史、不会创建新会话,也不会消耗模型额度。返回的
capabilities.execution=external_only 明确表示执行责任属于调用方;corral 不提供执行、停止或向运行中
会话下发消息的能力。内置 Claude/Codex 计划使用各自的非交互式原生续接入口,以便外部后台任务接收
完成输出;人类在 TUI 中的原生交互恢复行为不受影响。
列出某个项目最近的会话:
corral list --cwd my-weather-app --limit 20
corral list --cwd my-weather-app --limit 80 --top 5 --compact
只要还没回复的会话:
corral list --status pending
管家编排典型流程
找到当前正在运行的 CodingAgent,判断能不能直接下指令:
corral list --live --compact # 一步拿到「现在有哪些会话进程真的在跑」
corral list --live --status pending --compact # 更进一步:正在跑、且已在等你回复的
live 是按进程真实判活(pid 存活/写文件锁定),不是文件时间推断;status 是最后一轮角色推断的
会话内容状态。两者组合判断能不能打扰:live=true 且 status=done 说明进程还开着但已经把当前
任务处理完,可以直接接着聊;live=true 且 status=pending 说明正忙着等你回复,插话前先看
last_user/last_agent 摘要搞清楚它在问什么。live=false 的会话只能走 resume_command 重新
拉起一个进程,不能"接管"——corral 不提供向运行中进程注入输入的能力(本文档开头即说明:corral 只读、无
副作用,拿到数据后要做什么由调用方决定)。
keepalive=true 的会话额外要注意:它的进程挂在 corral 的后台保活层里,live 通常也是 true,但
resume_command 此时不安全——执行它会另起一个和保活进程抢同一份会话文件的新进程。这种会话只能
由人类回到 corral TUI 按 Enter 接回现场,管家 Agent 判断"能不能直接下指令"时应把 keepalive=true
当作"这条会话已经有人在管,只能提示人类去接,不要建议或代为执行 resume_command"的信号。
list/search 默认输出已经带 last_user/last_agent(最近一轮真人消息和助手回复,硬截断精简),
多数情况下看这两个字段就够判断"这条会话在干嘛",不必为每条候选都跑一次 corral show。
字段说明要点
title:只读已生成的标题缓存或本地兜底标题,不会触发新的标题生成(不花账号额度)。live/pid:live是运行中会话的进程是否真实存活(Claude 用 pid 注册表 +os.kill,Codex 用pgrep+lsof探测持有对应会话文件的进程,OpenCode 用命令行-s/--session或完整托管会话 id 精确绑定,同一目录可同时标多条;opencode run不算运行中。Kimi 用命令行-S/--session或完整托管会话 id 精确绑定,同一目录可同时标多条;kimi -p/server/web不算运行中), 不是根据文件时间猜的。pid只在live=true时非空,供调用方定位/给该进程发信号;corral 本身不提供拉起/接管等副作用 命令,pid只是可见性。keepalive:会话是否正挂在 corral 自己的后台保活(tmux)里(人类在corralTUI 里用 Enter/a启动会话时 默认会经过这层,SSH 断开也不中断)。为true时该会话的进程实际跑在保活层里,resume_command会另起一个直接抢同一份会话文件的新进程,不应该在这种情况下使用;corral 不提供从命令行直接"接管" 保活会话的能力(这属于交互式 TUI 的 Enter 键行为),调用方需要接管时只能提示人类回到corralTUI 操作。last_user/last_agent:最后一条真人消息和助手最后一轮回复的硬截断摘要(约 120 字),用于 快速判断会话在干嘛;需要完整对话仍然用corral show。status:英文枚举done/pending/aborted/unknown,程序判断用这个字段,不要解析status_tag(中文 + emoji,只给人看)。resumable/resume_command:是否能生成同运行时原生恢复命令,以及可直接执行的恢复命令;这些字段 只基于扫描结果和运行时适配器生成,不会额外读取会话全文。session_ref/launch:仅plan continue返回。session_ref是带运行时的唯一标识;launch.argv是不经 shell 解释的启动参数数组,launch.cwd是推荐工作目录。不要把argv拼为resume_command风格的字符串,也不要让corral代为执行。score/matched_via/matched_fields:仅search返回。score是相关性分数,排序先按分数倒序, 再按更新时间倒序;matched_via是quick或deep,兼容旧调用方;matched_fields是命中的字段 列表,如title、first_user_msg、conversation。mtime:Unix 时间戳,按更新时间排序或做"最近"过滤时用这个,不要解析time的人类可读格式。--limit控制的是扫描深度(每个运行时最多看多少条历史),不是"最多返回几条"——过滤条件 (--status、--cwd、关键词)是在扫描出的这批里再筛选,如果确定目标会话较早,适当调大--limit(show/context默认扫描深度是 200,比list/search的 50 更大)。--top才是结果数量上限。给 Agent 调用时推荐同时传--limit和--top:前者决定找多深, 后者控制 stdout 体积。--compact会输出无缩进 JSON;list/search/show还会默认裁剪到常用字段。需要精确字段时用--fields覆盖(list/search/show均支持)——--compact单独使用时的默认字段集不含cwd/pid,只要调用方需要这两项(如判断会话在哪个目录、能否对运行中进程发信号),必须显式传--fields指名,不能只传--compact就假设拿得到。show --full可能很大;需要完整历史时优先加--out <path>,stdout 会只返回输出文件路径、字节数 和消息数量,完整 JSON envelope 写在该文件里。corral export是「按时间范围批量拿完整对话」的入口:等价于对区间内每条会话跑一次show --full, 再按最后更新时间正序合并成一个 JSON(data.sessions[],每条含list全部字段 +messages完整 对话)。--since/--until均为闭区间,任一侧省略即无界;时间可写2026-07-20、'2026-07-20 15:30'、 相对量7d/24h/30m(距今)或 Unix 时间戳;只给日期时--until自动补到当天 23:59:59。范围内会话 多时合并结果可达数 MB,强烈建议加--out <path>——stdout 只回文件路径、字节数、会话数与消息总数, 完整内容写在文件里。时间过滤按会话的mtime(最后更新时间)判定。corral share是给其他 Agent 做元认知 / 迭代用的统一 transcript:data.schema为corral.share/v1,data.events[]按原始历史顺序包含user_message/assistant_message/thinking/tool_call/tool_result(工具参数与结果不截断)。不要用show/export的messages充当这一用途——那两条 命令仍然只出纯文本。大结果同样优先--out。tool_result.status在 Claude 认is_error、OpenCode 认state.status、Pi 认isError;Kimi 目前只按 output 正文启发式,isError=true仍可能是ok。 TUI 高级操作「导出会话」写出同一份 envelope 到~/.cache/corral/share/(尊重CORRAL_CACHE_DIR), 并把绝对路径复制到剪贴板。
拿会话数据做总结 / 周报时的边界
corral 交出来的是对话记录,不是工作成果台账。下面 5 条是设计使然、不会改的产品边界;
用 show / export 的结果做周报、日报、工作总结前必须先按这些边界校正,否则结论会失真。
括号内是本机真实数据实测值(2026-08-01),供判断量级用。
-
show/export的对话里不含助手实际执行的动作。 这两条命令的messages只有真人消息和助手的文本回复;助手改了哪些 文件、跑了哪些命令、提交了什么代码,连同这些操作的结果全部不在show/export里——所有运行时一致 (各扫描器的load_conversation只提取文本,不提取工具调用)。实测一条 17.7 MB 的 Claude 会话, 导出后只剩约 19.6 万字符纯文本,被丢弃的 1683 次工具调用里含 361 次改文件、73 次新建文件、 837 次命令执行(其中 46 条是完整的 git 提交 / 打标签 / 推送,提交说明本身就是最好的成果素材)。 后果:只看show/export时,"索引已落地""改完了"这类话只是口述,无法据此核实真的改了、改了哪些文件。 怎么办:需要工具调用、thinking 或改码证据时,用corral share <会话>(统一事件流,含tool_call/tool_result/thinking);或用history_path自己去读原始历史文件(context的history_reading_hint说明该运行时的格式),或按下面第 5 条走 git 侧自查。show/export的纯文本契约本身不会改。 -
title只能当索引,不能当工作内容。 标题要么是运行时自己写的原生标题,要么是从首条用户 消息首行兜底而来,所以经常是"好的 做流程设计计划""那还需要改动吗"这种没有信息量的句子。 不要按标题聚类、归类或直接抄进周报;判断一条会话在干嘛,看last_user/last_agent, 不够就读messages。 -
last_agent不保证有值,不能作为唯一分流依据。 各运行时扫描 15 条的实测空值率: Cursor 15/15(扫描阶段不打开该运行时的对话库,这个字段恒为空串)、Kimi 9/15、Codex 4/15、 OpenCode 1/15、Claude 0/15。更进一步,Cursor 与 Kimi 的部分会话整条对话都取不到助手消息 (抽查 5 条:Cursor 3 条、Kimi 2 条只有用户提问侧)。 怎么办:last_agent为空时回退到last_user+messages,不要判成"这条会话没内容"而跳过。 -
messages的 user 侧混着系统注入文本,需要自行过滤。 Claude 的 task-notification 类事件 已在扫描层滤掉,但仍有几类会以"真人消息"的身份混进来(实测 Cursor 侧 206 条用户消息里有 16 条, 约 8%);2026-08 再扫约 2700 条后,还要加上 Codex / OpenConductor 那几类:- Cursor 的计划附件指令,特征是含
Implement the plan as specified, it is attached for your reference/Do NOT edit the plan file itself; Briefly inform the user about the task result…这类运行时内部提示;- Codex 的
Implement the plan.(整句)、<skill>…全文展开、<turn_aborted>、<subagent_notification>; - OpenConductor 角色提示(
你是 OpenConductor 的…、【权威对话账本、带用户最新补充的原始任务:); - corral 自己生成的跨运行时接力提示词,特征是以
任务:开头且含你正在接力一个来自 … 的会话。
$doc-update、/grilling和带<image>配文的提问是真人输入,不要当注入丢掉。TUI 的 Your prompts 小窗已经按同一套特征过滤(
is_injected_user_prompt);本接口的show/export仍返回原文,调用方写周报时要自己剔除。后果:不过滤会把这些当成真人需求,凭空多出一堆"用户要求"。汇总前按上述特征剔除。
- Cursor 的计划附件指令,特征是含
-
没有任何成果结构化字段。 不提供 commits / PR / 变更文件列表,也不会有——
corral只负责把 会话数据交出来(见本文档开头的只读约定)。所以"做完了"只能从对话文字推断,很容易把 计划了写成做完了。 怎么办:真实成果去代码仓库侧取,用corral提供的cwd和mtime做锚点即可对齐:# 1. 圈出时间范围内涉及哪些工作目录(export 没有 --fields,落盘后再取需要的字段) corral export --since 7d --out /tmp/week.json python3 -c "import json;d=json.load(open('/tmp/week.json'))['data'];\ print('\n'.join(sorted({s['cwd'] for s in d['sessions'] if s.get('cwd')})))" # 2. 再到各工作目录用 git 拿可核验的成果 git -C <上一步列出的目录> log --since=7.days --stat两边对齐后,git 侧给"实际改了什么",
corral侧给"为什么改、当时在讨论什么"。
与 OpenConductor 项目关联
corral 只提供 cwd / cwd_display(会话当时的原始工作目录),不提供、也不应该提供任何
"项目 ID"字段:OpenConductor 的项目标识是项目根目录(通常是含 .git 的目录)绝对路径的 SHA1
摘要(形如 proj_a1b2c3d4e5f6a7b8),既算不出来(corral 不知道 OpenConductor 的项目扫描结果),
也不能直接由 cwd 推导(会话当时的 cwd 可能是项目子目录,不等于项目根目录)。
调用方(如需要把某条会话关联到 OpenConductor 已注册项目的管家 Agent)应该:
- 调
oc projects --json,拿到项目列表,每项含id(proj_前缀的项目标识)和path(项目根目录绝对路径)。 - 用
corral返回的cwd去匹配:cwd等于某个path,或cwd位于该path之下(前缀匹配),命中的 那一项的id就是要用的项目标识。 - 不要在
corral侧本地计算或猜测这个 ID——匹配逻辑属于调用方职责,不属于corral。
非 Agent 用法
不带子命令直接运行 corral 会打开交互式终端 TUI,需要真实终端,供人类手动选择会话;在非真实
终端环境下会自动退化为 JSON 列表(等价于 corral list)。旧版 corral --json 参数仍然保留,但字段
少于 corral list(没有 status 英文枚举、short_id 等),新集成建议直接用本文档的子命令。
界面异常排查(只读)
TUI 卡顿、侧边栏不刷新、内嵌面板异常时:
- 先跑
corral diagnose,看data.last_error(最近一次完整 traceback;无记录则为 null)。 - 读
~/.cache/corral/events.log(JSON 行:scan_all/list_rebuild/host_session/capture_slow/error)。 - 需要更多历史时再读
~/.cache/corral/embed-error.log(后台线程 + 致命闪退的完整栈)。 - 真机 TUI 内按 F12 导出当前画面到
~/.cache/corral/screenshots/(勿把含真实对话的截图提交仓库)。 - 需要细日志时设
CORRAL_DEBUG=1后重启 TUI。