出発点: 自分のXを自分で読むのが面倒になってきた
自分のXハンドル @EUREKAPU_com の直近のポストを読み返したい場面が増えてきた。前日のポスト傾向を踏まえて翌日の投稿案を考える、決算ネタを過去に何と言っていたか掘り返す、フォロワーがどの話に反応したか棚卸しする。やりたい用途は全部「自分の過去ポストを横断で要約する」に着地する。
ブラウザを開いてプロフィールに飛んで、スクロールしながら読み返す動きを何度か繰り返したあと、これは Claude Code に派遣すべき仕事だと諦めた。手で読むのを諦めて、検索 → 要約まで自動化する経路を探しに行った。
経路選定: Hermes Agent の x_search_tool を選んだ
候補はいくつかあった。X API を直接叩く案、サードパーティの検索ラッパーを使う案、xAI の Grok を経由する案。最終的に Hermes Agent の x_search_tool に絞った。理由は3つある。
- xAI の Grok が X の検索インデックスを直接持っている(X 社内データ)
uvx --from hermes-agentのワンライナーで呼べる(Python パッケージのインストール不要)- xAI OAuth でログインすれば、自分の Premium Plus / SuperGrok サブスク枠で課金が走る
筆者は別件で広告ゼロが必要になって Premium Plus に課金していたので、追加のサブスクなしで済む。ここが決め手になった。
認証セットアップ
uvx で hermes-agent を一発実行できる前提で、認証だけ一度通せばよい。
uvx --from hermes-agent hermes auth add xai-oauth
ブラウザが xAI のログインに飛んで、認可するとローカルに credential が保存される。次回からは認証なしで x_search_tool を叩ける。
最初の動作確認: ハンドル指定でつまずいた
最小ワンライナーで @EUREKAPU_com の直近1ヶ月を要約させようとした。最初の試行はこう書いた。
uvx --from hermes-agent python -c "from tools.x_search_tool import x_search_tool; print(x_search_tool('Summarize the recent posts of the past month.', allowed_x_handles=['EUREKAPU_com'], from_date='2026-04-20'))"
返ってきた answer を読むと、Grok から「どのアカウントを要約すればよいか教えてください」というメッセージが返ってきていた。allowed_x_handles を指定したのに、Grok 側ではそれを「対象指定」として解釈してくれていない。クエリ本文が Summarize the recent posts で対象が一切書かれていないので、検索範囲を絞るための allowed_x_handles と、要約対象の指示は別物として扱われているらしい。
クエリ本文にもハンドル名を明示する形に書き直した。
uvx --from hermes-agent python -c "from tools.x_search_tool import x_search_tool; print(x_search_tool('Summarize the recent posts by @EUREKAPU_com. Quote 5-10 representative posts in their original Japanese.', allowed_x_handles=['EUREKAPU_com'], from_date='2026-04-20'))"
今度は1分弱の沈黙のあと、自分のポストの要約と原文引用がずらっと返ってきた。allowed_x_handles と本文の両方にハンドルを書く、これが正解だった。
レスポンスを開いて、どこから引いているか確かめた
返ってきた JSON は出力が長かったので、stdout 全部を読むより一度ファイルに落としたほうが追いやすい。一時的に x-search-result.json を作って中身を確認した。
uvx --from hermes-agent python -c "import json; print(json.load(open('x-search-result.json',encoding='utf-8'))['model'])"
# → grok-4.20-reasoning
uvx --from hermes-agent python -c "import json; print(json.load(open('x-search-result.json',encoding='utf-8'))['credential_source'])"
# → xai-oauth
model が grok-4.20-reasoning だった。SuperGrok 系の上位推論モデルが裏で走っている。credential_source は xai-oauth なので、Premium Plus のサブスク枠で動いていることもここで腑に落ちた。仮にここが xai-api になっていたら、API キー経由の従量課金が走っている合図なので、毎回チェックする習慣に組み込みたいフィールドだ。
answer フィールドは Markdown 形式で、各引用ポストの URL が脚注で添えられていた。inline_citations にも引用 URL のリストが入っていて、内訳が突き合わせできるようになっている。
一時ファイルは確認後すぐ消した
検証中に作った x-search-result.json と、ワンライナーが入り組んだので一時的に作った run-x-search.py の2つは、内容を確認した直後に削除した。理由は2つある。
- JSON 本体に自分のポスト原文がそのまま入っており、個人発信データをディスクに長期保存する積極的な理由がない
- リポジトリにうっかり混入させる事故を未然に消したかった
ファイル保存が必要な場面は出てくると思うので、スキル本文には memo/{YYYY-MM-DD}/x-search-{topic}.json 形式で保存する選択肢だけ残し、今回のような検証用途では stdout で済ませる方針をメモに書いた。
ユーザースキルに固めた
ワンライナーが手に馴染んだので、~/.claude/skills/x-search/SKILL.md にユーザーレベルのスキルとして固めた。プロジェクト直下ではなくユーザースキルにしたのは、Xの検索はプロジェクトを跨いで使いたいから。どのリポジトリで Claude Code を起動してもこのスキルが効く。
description には音声入力時のフックを意識して、表記揺れを全部詰め込んだ。
「Xを検索」「Twitterを検索」「ツイッターを検索」「エックスを検索」
「ツイートを調べて」「ポストを調べて」「@xxxの直近の投稿を要約」
音声入力では「エックス」「ツイッター」「ツイート」「ポスト」あたりが頻出する。description にこれらの表記を並べておくと、口頭で投げた指示でも Claude Code がスキルを引き当ててくれる。
スキル本体には以下を盛り込んだ。
- 前提(uv インストール、
uvx --from hermes-agent hermes auth add xai-oauthで OAuth、Premium+ または SuperGrok 必須) - 最小ワンライナー
- パラメータ仕様(
allowed_x_handles,from_date,to_date,enable_image_understandingほか) - レスポンス主要フィールド(
model,credential_source,answer,inline_citations) - クエリ作成のコツ(ハンドルは本文と allowed の両方に書く / 原文引用を明示 / 期間を絞る)
- トラブルシューティング(
I need more informationが返る時の対処、credential_source: xai-apiの警告)
学び
allowed_x_handles だけで通じるはずだ、と最初に決め打ちしたのが小さい遠回りだった。クエリ本文と allowed_x_handles の役割が分かれている、と分かった瞬間に挙動が腑に落ちた。スキルのトラブルシューティング欄に「ハンドル名を教えてください」が返ってきたら本文にも書け、という導線を最初から残せたのは、この遠回りのおかげだ。
credential_source の確認を習慣化する、というメモも今回のうちに刻んでおいた。xai-oauth のまま動いていることを毎回見にいけば、サブスク枠で済んでいることを自分の目で確かめられる。xai-api に静かに切り替わっていたら、従量課金が走っている合図として早めに気づける。
ポストデータをディスクに残すか即削除するか、という判断は、毎回考えるとブレるので、スキル側のメモに方針として書いておくのが正解だった。一時確認は stdout、残すなら memo/{YYYY-MM-DD}/ 配下、という線引きを最初から書いておけば、次に使うときに迷わない。
次にやること
- 前日のポスト傾向を踏まえてポスト案を出す
/review-yesterday-tweetsの入り口を、x-search スキル経由に差し替える - 決算ネタの過去ポストを横断要約する用途で、
from_dateを四半期単位で動かす定型クエリを memo に残す - フォロワーが反応したポストを抽出する用途で、
enable_image_understanding=True付きの呼び出しを試す