Communityライティング&編集github.com

ストックルーム検索 (sr-query)

エージェントコーディング履歴のローカルかつ忠実な検索可能倉庫に対する、読み取り専用のSQLクエリを実行します。

ストックルーム検索 (sr-query) とは?

sr-queryは、CursorおよびClaude Codeの会話履歴をキャプチャした単一ファイルのDuckDBデータベース「Stockroom」に対して、読み取り専用SQLを実行するためのツールです。このデータベースは書き込みを受け付けないため、誤ったデータ破損のリスクがなく安全です。特定のメッセージIDやセッションIDによる行の取得、件数カウント、グループ化、トークン合計、日付範囲フィルタなど、明確な構造を持つ質問に最適です。また、ツール呼び出しの分析やセッションごとのトークン使用量集計なども可能です。sr-queryは意味ベースの検索には使用せず、その場合はsr-semanticやsr-searchスキルを利用するようガイドされます。最終的には、クエリ結果を自然言語でユーザーに伝えることが推奨されています。

対応✓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に質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

sr-query

sr-query は、ストックルーム倉庫(Stockroom)——Cursor + Claude Code の履歴をキャプチャした単一ファイルの DuckDB データベース——に対して 読み取り専用の SQL を実行します。表面は設計上読み取り専用です。DuckDB はそこを通じた書き込みを全て拒否するため、クエリによってデータを壊すことはありません。

sr-query を使用すべき時

質問に 既知の形状 があり、名前を指定できるフィールドに対する正確または構造化された検索が答えである場合に sr-query を使ってください。

  • ID による特定の行(WHERE message_id = '…'、WHERE session_id = '…')
  • フィルター、カウント、ロールアップ(COUNT(*)、GROUP BY harness、WHERE harness = 'claude'、トークン合計、日付範囲)
  • VIEW session_token_usage を介したセッションごとのトークンロールアップ(手動で messages に対して SUM を書くよりもこちらを推奨)
  • sessions / messages / tool_calls 間の結合
  • 「いくつあるか」「どのセッションか」「ツール呼び出しをリストアップ」「どのモデルか」——名前付きカラムに対して SQL で表現できるもの全て

意味ベース の想起(「flaky tests に関する会話を探す」)には 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)は、読み取り時に 切り詰められるため、1つの太いカラムがコンテキストを圧迫することはありません。切り詰めは表示のみで、全文は常に取得可能です。

値フィールドあたりの予算使用すべき時
compact約40文字多くの候補行を低コストでスキャンし、その後1つを選ぶ場合。
snippet (デフォルト)約120文字デフォルト。行をダンプせずに認識するのに十分。
full無制限、単一行フィールド全体の長さが必要で、単一行への折りたたみで問題ない場合(テーブル/TSVは安全)。
raw無制限、正確な空白保存されたまま のテキストが必要な場合——改行や内部スペースもそのまま。--format json と組み合わせて推奨。

予算を超えたフィールドは、何文字隠されたかを示すマーカー(例: …(+2284) )とともに省略されます。このマーカーが「さらに存在する」というシグナルです。実際に必要であれば、そのフィールドだけを特定の行について --detail full(長さ)または --format json --detail raw(正確な空白)で再取得してください。ガードレールを参照。

ガードレール

このスキルが防止すべき障害モード:

  • コンテキストを圧迫しないこと。 多くの行に対して --detail full/raw で SELECT *(または幅広い text カラム)を決して実行しないでください。代わりに、明示的なカラムリストと LIMIT を使って --detail compact/snippet で狭くスキャンし、目的の行を特定してから、その行の幅広いフィールドだけを ID で WHERE して再取得してください。単一の SELECT text FROM messages WHERE message_id = '…' は低コストですが、SELECT * FROM messages --detail full はコンテキスト爆弾です。正確な 空白(マークダウンテーブル、コードブロック)が必要な場合は、--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 (…)2SQL が渡されませんでした。ステートメントを提供してください。
error: no warehouse found at … — run \stockroom ingest` first`1倉庫が構築されていません。ユーザーに stockroom ingest を実行するよう伝えてください(マシンが一度もセットアップされていない場合は sr-initialize)。クエリを再試行しないでください。
query failed: …1無効な SQL、または書き込みが拒否されました。ステートメントを修正してください(DuckDB のメッセージを読んでください)——同じ SQL を再実行しないでください。

倉庫の中身

まずライブスキーマを発見してください——これによりスキーマの進化に正しく対応できます:

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

マイグレーション 0001–0008 時点の主要カラムのクイックリファレンス(上記のイントロスペクションクエリで確認してください):

  • sessions — 会話ごとに1行。harness('cursor'|'claude')、session_id、project_id(プロジェクトディレクトリスラッグそのもの——グループ化キー。Cursor CLI チャットの場合はチャットハッシュディレクトリ)、cwd(実パス、NULL の場合あり)、workspace_key(ハーネス横断パスロールアップ、NULL の場合あり)、entrypoint(既知の場合のハーネスからの表面出処、NULL の場合あり——リテラルを推測する代わりに SELECT DISTINCT entrypoint を使用)、models(VARCHAR[]、Cursor のみ)、title、git_branch、is_subagent、parent_session_id、started_at、ended_at、source_mtime(最終取り込み時のソーストランスクリプトの mtime)、および4つのNULL許容セッショングレインのトークン BIGINT(input_tokens、output_tokens、cache_creation_tokens、cache_read_tokens——ハーネスが会話レベルの使用量を報告する場合にのみ入力されます。Claude/Cursor はこれらを NULL のままにします)。PK (harness, session_id)。
  • messages — ターンごとに1行。message_id = '{session_id}#{ordinal}'(全ハーネスで統一)、parent_id、ordinal、role('user'|'assistant')、text(全体、思考はキャプチャされません)、model(メッセージごと、Claude のみ)、ts、first_seen_at(ストックルームがそのメッセージを最初に観測した時刻)、および4つのトークン BIGINT:input_tokens、output_tokens、cache_creation_tokens、cache_read_tokens(Claude メッセージ使用量。Cursor は NULL)。PK (harness, session_id, message_id)。
  • session_token_usage — sessions + メッセージトークン合計の VIEW。会話ロールアップにはこちらを推奨。カラム: *_from_messages(SUM)、*_native(セッションカラム)、*_total(COALESCE(native, from_messages))、token_grain('session'|'message'|'none')。合計は報告されたフィールドの倉庫ロールアップであり、ベンダーインボイスではありません。*_total に加えてメッセージトークンをさらに SUM しないでください。
  • tool_calls — ツール 入力のみ(出力は含まれません)。message_id(それを発行したターン)、ordinal、tool_name、tool_input(異種 JSON、全体として保存——ガードレールを参照)。PK (harness, session_id, message_id, ordinal)。
  • embeddings — セマンティック検索用のチャンクごとのベクトル(owner_table、owner_id、chunk_index、embed_model、vector FLOAT[384])。これを直接クエリすることはほとんどありません——sr-semantic スキルを使用してください。
  • _sync_state — 取り込み水位マークのブックキーピング。クエリ対象としては興味深くありません。

結合を書く前に知っておくべき1つの同一性ルール: 常に統一された message_id / (harness, session_id) で結合し、source_* 出処カラムでは決して結合しないでください。ハーネスごとに1つのグレインにしか存在しない値は、もう一方のハーネスでは正直に NULL になります(例: messages.model は Claude のみ、sessions.models は Cursor のみ。同じ二重グレインの正直さがトークンにも適用されます)。

実例

全て実際の倉庫で検証済みです。

# どのハーネスが存在するか?(tsv デフォルト)
stockroom query "SELECT DISTINCT harness FROM sessions ORDER BY 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>'"

# ユーザー/ツールが消費するための構造化出力:
stockroom query --format json "SELECT harness, session_id, title FROM sessions WHERE title IS NOT NULL LIMIT 5"

# セッションごとのトークンロールアップ(VIEW 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"

さらに多くのバリエーション(アクティビティウィンドウ付きの無制限ツール、日/ハーネスごとのトークンロールアップ、ハーネスごとのスキル使用 SQL)については、クックブック を参照してください。

クックブック

難解なスターター SQL: references/cookbook/。インデックスを開き、必要なレシピだけを開いてください。

人間への伝達

あなたはツールのオペレーターであり、その表示装置ではありません。SQL を実行し、結果を読み、自然言語でユーザーに答えてください。ユーザーが生の tsv を見たいと明示的に要求しない限り、人間に貼り付けないでください。ユーザーが生の出力や自分で実行できるコマンドを求めた場合は、--format table(読む用)または --format json(処理する用)のバリアントを渡してください。

システムの理解

これらの契約がなぜそのようになっているのかを理解するために——パッケージング、torch 契約、設計上の読み取り専用、切り詰めの原則、同一性/出処——共有システムモデルをお読みください: ../sr-search/references/system-model.md。

関連スキル