Community写作与编辑github.com

Texarkanine/stockroom

一个本地、忠实、可搜索的代理编码历史仓库。

stockroom 是什么?

`sr-query` 是一个只读 SQL 查询技能,基于 Stockroom 仓库——一个单文件 DuckDB 数据库,用于存储捕获的 Cursor 和 Claude Code 历史记录。其核心设计是只读的:DuckDB 会拒绝任何写入尝试,因此查询不会损坏数据。此技能适用于精确的结构化查找,例如按 ID 检索特定行、过滤计数、按会话汇总 token 使用量,或在会话、消息和工具调用表之间进行联接。它不适合基于语义的回忆(如“查找关于不稳定测试的对话”),因为 SQL 的 `ILIKE` 仅执行字面子串匹配;对于这类语义搜索,请使用 `sr-semantic` 技能。当不确定该使用哪个技能时,由 `sr-search` 技能进行判断。该技能通过 `stockroom query` 命令调用,支持 `--format` 和 `--detail` 选项以控制输出形状和字段宽度,并提供明确的防护措施,如防止上下文溢出、仅读限制以及安全处理异构 JSON。

兼容平台✓Claude Code~Codex CLI✓Cursor✓Antigravity
npx skills add Texarkanine/stockroom

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

sr-query

sr-query 针对 stockroom 仓库运行只读 SQL——这是一个单文件 DuckDB 数据库,存储了你捕获的 Cursor + Claude Code 历史记录。该表面层本身是只读的:DuckDB 会拒绝任何通过它尝试的写入操作,因此查询不会损坏任何数据。

何时使用 sr-query

当问题具有已知模式,并且答案是对你能命名的字段进行精确或结构化查找时,请使用 sr-query:

  • 按 ID 查找特定行(WHERE message_id = '…',WHERE session_id = '…')。
  • 过滤器、计数和汇总(COUNT(*),GROUP BY harness,WHERE harness = 'claude',token 求和,日期范围)。
  • 通过视图 session_token_usage 进行每个会话的 token 汇总(优先使用此视图,而非手动对 messages 进行 SUM)。
  • 跨 sessions / messages / tool_calls 表的联接。
  • “有多少”、“哪些会话”、“列出工具调用”、“什么模型”——任何你可以通过命名列用 SQL 表达的内容。

不要将 sr-query 用于基于含义的回忆(如“查找关于不稳定测试的对话”)。SQL 的 ILIKE 是字面子串匹配,而非语义搜索——对于含义搜索,请使用 sr-semantic 技能。当你不确定哪个合适时,应由 sr-search 技能来判断。

如何调用引擎

stockroom query "SELECT DISTINCT harness FROM sessions ORDER BY harness"

你也可以通过标准输入使用 - 来传递 SQL:

echo "SELECT count(*) FROM messages" | stockroom query -

如果 command -v stockroom 失败,则表示机器尚未设置:告诉用户运行 sr-initialize 技能,并且不要尝试其他调用方式。

输出规范:--format 和 --detail

默认设置对代理来说已经是安全的——裸调用会提供有限且可解析的输出——因此仅在特定情况下使用这些标志。

--format — 输出形状,默认为 tsv

值形状使用场景
tsv (默认)标题行 + 制表符分隔的行,无计数尾部默认。对流友好,对 Unix 管道(cut,awk,wc -l)也友好。
json单个 {"columns": [...], "rows": [...]} 对象用户要求结构化/机器输出,或者你想将其传递给 jq。
table列对齐的 ASCII,带 (N rows) 尾部用户要求人类可读的输出/用于查看的复制粘贴命令。

优先使用默认的 tsv。当用户要求人类可读或结构化输出时,再提供 --format table 或 --format json——“如果你需要,还有其他形状可用。”

--detail — 每字段宽度,默认为 snippet

宽字符串字段(特别是 messages.text 和 tool_calls.tool_input)在读取时会被截断,以防止一个大的列充斥你的上下文。截断仅影响显示——完整文本始终可检索。

值每字段预算使用场景
compact~40 字符在挑选一行之前,廉价地扫描许多候选行。
snippet (默认)~120 字符默认。足以识别一行,而无需转储其全部内容。
full无限制,单行你需要整个字段长度,并且单行折叠是可以接受的(表格/TSV 保持安全)。
raw无限制,精确空白你需要原样存储的文本——保留换行符和内部空格。优先与 --format json 一起使用。

超出预算的字段会用一个标记进行省略,报告隐藏了多少字符,例如 …(+2284)。这个标记表明还有更多内容:如果你确实需要它,请以 --detail full(长度)或 --format json --detail raw(精确空白)重新获取特定行的那个字段——请参阅防护措施。

防护措施

以下是此技能旨在防止的故障模式:

  • 不要撑爆你的上下文。 永远不要在 --detail full/raw 下对多行执行 SELECT *(或一个宽的 text 列)。相反:在 --detail compact/snippet 下使用明确的列列表和 LIMIT 进行窄范围扫描,确定你需要的行,然后只使用该行的 ID 和 WHERE 子句重新获取其宽字段。单个 SELECT text FROM messages WHERE message_id = '…' 是廉价的;而 SELECT * FROM messages --detail full 则是一个上下文炸弹。当你需要精确空白时(markdown 表格,代码块),请使用 --format json --detail raw。
  • 它是只读的——永远不要尝试写入。 INSERT / UPDATE / DELETE / CREATE 均会失败(query failed: …)。不要通过不同的措辞重试写入;该表面层仅用于查询。
  • tool_input 是异构 JSON。 其键因工具而异(Shell 有 command,Read 有 path,……),因此简单的 tool_input->>'key' 可能引发类型转换错误。通过在子查询/CTE 中首先按 tool_name 过滤,然后使用明确的函数来安全地提取:
stockroom query "SELECT json_extract_string(tool_input, '\$.command') AS cmd
  FROM (SELECT tool_input FROM tool_calls WHERE tool_name = 'Shell') LIMIT 5"

无抖动处理错误

每个故障都会输出清晰的 stderr 消息和退出码——读取它并执行相应的操作,不要循环重试:

消息退出码含义 / 下一步操作
error: empty query (…)2未传递 SQL。提供一个语句。
error: no warehouse found at … — run \stockroom ingest` first`1仓库尚未构建。告诉用户运行 stockroom ingest(如果机器从未设置过,则运行 sr-initialize);不要重试查询。
query failed: …1SQL 无效,或写入被拒绝。修复语句(阅读 DuckDB 的消息)——不要重新运行相同的 SQL。

仓库中包含什么

首先发现实时模式——这能确保你获取的是最新的模式:

stockroom query "SELECT table_name, column_name, data_type
  FROM information_schema.columns ORDER BY table_name, ordinal_position"

截至迁移 0001–0008 的关键列快速参考(请通过上述内省查询确认):

  • sessions — 每个会话一行。harness('cursor'|'claude'),session_id,project_id(项目目录的原始 slug——分组键;对于 Cursor CLI 聊天,这是聊天的哈希目录),cwd(真实路径,可能为 NULL),workspace_key(跨 harness 的路径汇总,可能为 NULL),entrypoint(已知时来自 harness 的表面来源;可能为 NULL——使用 SELECT DISTINCT entrypoint 而非猜测字面值),models(VARCHAR[],仅 Cursor),title,git_branch,is_subagent,parent_session_id,started_at,ended_at,source_mtime(上次摄取时源记录的修改时间),以及四个可为空的会话级 token BIGINT 字段(input_tokens,output_tokens,cache_creation_tokens,cache_read_tokens——仅当 harness 报告会话级使用量时才填充;Claude/Cursor 将其留为 NULL)。主键 (harness, session_id)。
  • messages — 每轮对话一行。message_id = '{session_id}#{ordinal}'(在所有 harness 中一致),parent_id,ordinal,role('user'|'assistant'),text(完整内容;不捕获思考过程),model(每个消息,仅 Claude),ts,first_seen_at(stockroom 首次观察到该消息的时间),以及四个 token BIGINT 字段:input_tokens,output_tokens,cache_creation_tokens,cache_read_tokens(Claude 消息使用量;Cursor 为 NULL)。主键 (harness, session_id, message_id)。
  • session_token_usage — 基于 sessions 和消息 token 总和的视图。优先用于会话汇总。列:*_from_messages(SUM),*_native(会话列),*_total(COALESCE(native, from_messages)),token_grain('session'|'message'|'none')。总数是报告字段的仓库汇总,而非供应商发票。不要在 *_total 之上再次对消息 token 执行 SUM。
  • tool_calls — 仅工具输入(绝不包含输出)。message_id(发出该调用的轮次),ordinal,tool_name,tool_input(异构 JSON,整体存储——请参阅防护措施)。主键 (harness, session_id, message_id, ordinal)。
  • embeddings — 用于语义搜索的每个分块向量(owner_table,owner_id,chunk_index,embed_model,vector FLOAT[384])。你很少直接查询此表——请使用 sr-semantic 技能。
  • _sync_state — 摄取水位线簿记;对查询不感兴趣。

在编写联接之前,有一个值得了解的 identity 规则:始终在统一的 message_id / (harness, session_id) 上进行联接,而永远不要在 source_* 来源列上联接。某个值如果仅在每个 harness 的一个粒度上存在,那么在另一个粒度上则诚实地为 NULL(例如 messages.model 仅在 Claude 中;sessions.models 仅在 Cursor 中;token 字段也同样诚实地遵循这种双粒度方式)。

实际示例

所有示例均已针对真实仓库验证。

# 存在哪些 harness?(tsv 默认)
stockroom query "SELECT DISTINCT harness FROM sessions ORDER BY harness"

# 每个 harness 的会话计数,为人类用户提供可读格式:
stockroom query --format table "SELECT harness, count(*) AS n FROM sessions GROUP BY harness ORDER BY n DESC"

# 最繁忙的工具:
stockroom query "SELECT tool_name, count(*) AS calls FROM tool_calls GROUP BY tool_name ORDER BY calls DESC LIMIT 5"

# 廉价扫描候选消息,然后完整重新获取所需的那个:
stockroom query --detail compact "SELECT message_id, text FROM messages WHERE text ILIKE '%flaky test%' LIMIT 10"
stockroom query --format json --detail raw \
  "SELECT text FROM messages WHERE message_id = '<id-from-the-scan>'"

# 为用户/工具提供结构化输出:
stockroom query --format json "SELECT harness, session_id, title FROM sessions WHERE title IS NOT NULL LIMIT 5"

# 每个会话的 token 汇总(视图 session_token_usage):
stockroom query --format table \
  "SELECT harness, session_id, input_tokens_total, output_tokens_total, token_grain
   FROM session_token_usage
   ORDER BY input_tokens_total DESC NULLS LAST
   LIMIT 10"

更多变体(具有活动窗口的无界工具、天粒度/harness token 汇总、每个 harness 的技能使用 SQL):请参阅 食谱。

食谱

复杂的入门 SQL:references/cookbook/。打开索引,然后只查找你需要的配方。

向人类呈现

你是工具的操作者,而非其显示器。运行 SQL,读取结果,然后用自然语言回答用户。除非用户要求查看原始 tsv,否则不要将原始 tsv 粘贴给人类。当用户确实想要原始输出——或一个他们可以自己运行的命令时,请提供 --format table(用于阅读)或 --format json(用于处理)的变体。

理解系统

要理解为什么这些约定是这样的——打包方法、torch 约定、构造上的只读、截断原则、identity/来源——请阅读共享的系统模型:../sr-search/references/system-model.md。

相关技能