[{"data":1,"prerenderedAt":430},["ShallowReactive",2],{"content-/x-search-skill":3,"all-pages-for-dir":428,"og-image-/x-search-skill":429},{"id":4,"title":5,"body":6,"category":410,"description":411,"extension":412,"meta":413,"navigation":176,"ogImage":414,"path":415,"project_name":416,"published":417,"publishedAt":418,"seo":419,"stem":420,"tags":421,"todo":414,"unpublished":417,"updatedAt":414,"__hash__":427},"pages/2026-05/2026-05-20/x-search-skill.md","x_search_tool を Claude Code スキルに固めて、自分のXハンドルを派遣調査させる仕組みを作った",{"type":7,"value":8,"toc":399},"minimark",[9,14,23,26,30,41,57,60,63,69,85,91,95,101,110,129,132,141,144,148,155,190,212,221,224,234,242,249,252,259,262,270,273,276,330,333,338,349,356,359,395],[10,11,13],"h2",{"id":12},"出発点-自分のxを自分で読むのが面倒になってきた","出発点: 自分のXを自分で読むのが面倒になってきた",[15,16,17,18,22],"p",{},"自分のXハンドル ",[19,20,21],"code",{},"@EUREKAPU_com"," の直近のポストを読み返したい場面が増えてきた。前日のポスト傾向を踏まえて翌日の投稿案を考える、決算ネタを過去に何と言っていたか掘り返す、フォロワーがどの話に反応したか棚卸しする。やりたい用途は全部「自分の過去ポストを横断で要約する」に着地する。",[15,24,25],{},"ブラウザを開いてプロフィールに飛んで、スクロールしながら読み返す動きを何度か繰り返したあと、これは Claude Code に派遣すべき仕事だと諦めた。手で読むのを諦めて、検索 → 要約まで自動化する経路を探しに行った。",[10,27,29],{"id":28},"経路選定-hermes-agent-の-x_search_tool-を選んだ","経路選定: Hermes Agent の x_search_tool を選んだ",[15,31,32,33,40],{},"候補はいくつかあった。X API を直接叩く案、サードパーティの検索ラッパーを使う案、xAI の Grok を経由する案。最終的に ",[34,35,36,37],"strong",{},"Hermes Agent の ",[19,38,39],{},"x_search_tool"," に絞った。理由は3つある。",[42,43,44,48,54],"ul",{},[45,46,47],"li",{},"xAI の Grok が X の検索インデックスを直接持っている（X 社内データ）",[45,49,50,53],{},[19,51,52],{},"uvx --from hermes-agent"," のワンライナーで呼べる（Python パッケージのインストール不要）",[45,55,56],{},"xAI OAuth でログインすれば、自分の Premium Plus / SuperGrok サブスク枠で課金が走る",[15,58,59],{},"筆者は別件で広告ゼロが必要になって Premium Plus に課金していたので、追加のサブスクなしで済む。ここが決め手になった。",[10,61,62],{"id":62},"認証セットアップ",[15,64,65,68],{},[19,66,67],{},"uvx"," で hermes-agent を一発実行できる前提で、認証だけ一度通せばよい。",[70,71,76],"pre",{"className":72,"code":73,"language":74,"meta":75,"style":75},"language-powershell shiki shiki-themes vitesse-light vitesse-light","uvx --from hermes-agent hermes auth add xai-oauth\n","powershell","",[19,77,78],{"__ignoreMap":75},[79,80,83],"span",{"class":81,"line":82},"line",1,[79,84,73],{},[15,86,87,88,90],{},"ブラウザが xAI のログインに飛んで、認可するとローカルに credential が保存される。次回からは認証なしで ",[19,89,39],{}," を叩ける。",[10,92,94],{"id":93},"最初の動作確認-ハンドル指定でつまずいた","最初の動作確認: ハンドル指定でつまずいた",[15,96,97,98,100],{},"最小ワンライナーで ",[19,99,21],{}," の直近1ヶ月を要約させようとした。最初の試行はこう書いた。",[70,102,104],{"className":72,"code":103,"language":74,"meta":75,"style":75},"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'))\"\n",[19,105,106],{"__ignoreMap":75},[79,107,108],{"class":81,"line":82},[79,109,103],{},[15,111,112,113,116,117,120,121,124,125,128],{},"返ってきた ",[19,114,115],{},"answer"," を読むと、Grok から「",[34,118,119],{},"どのアカウントを要約すればよいか教えてください","」というメッセージが返ってきていた。",[19,122,123],{},"allowed_x_handles"," を指定したのに、Grok 側ではそれを「対象指定」として解釈してくれていない。クエリ本文が ",[19,126,127],{},"Summarize the recent posts"," で対象が一切書かれていないので、検索範囲を絞るための allowed_x_handles と、要約対象の指示は別物として扱われているらしい。",[15,130,131],{},"クエリ本文にもハンドル名を明示する形に書き直した。",[70,133,135],{"className":72,"code":134,"language":74,"meta":75,"style":75},"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'))\"\n",[19,136,137],{"__ignoreMap":75},[79,138,139],{"class":81,"line":82},[79,140,134],{},[15,142,143],{},"今度は1分弱の沈黙のあと、自分のポストの要約と原文引用がずらっと返ってきた。allowed_x_handles と本文の両方にハンドルを書く、これが正解だった。",[10,145,147],{"id":146},"レスポンスを開いてどこから引いているか確かめた","レスポンスを開いて、どこから引いているか確かめた",[15,149,150,151,154],{},"返ってきた JSON は出力が長かったので、stdout 全部を読むより一度ファイルに落としたほうが追いやすい。一時的に ",[19,152,153],{},"x-search-result.json"," を作って中身を確認した。",[70,156,158],{"className":72,"code":157,"language":74,"meta":75,"style":75},"uvx --from hermes-agent python -c \"import json; print(json.load(open('x-search-result.json',encoding='utf-8'))['model'])\"\n# → grok-4.20-reasoning\n\nuvx --from hermes-agent python -c \"import json; print(json.load(open('x-search-result.json',encoding='utf-8'))['credential_source'])\"\n# → xai-oauth\n",[19,159,160,165,171,178,184],{"__ignoreMap":75},[79,161,162],{"class":81,"line":82},[79,163,164],{},"uvx --from hermes-agent python -c \"import json; print(json.load(open('x-search-result.json',encoding='utf-8'))['model'])\"\n",[79,166,168],{"class":81,"line":167},2,[79,169,170],{},"# → grok-4.20-reasoning\n",[79,172,174],{"class":81,"line":173},3,[79,175,177],{"emptyLinePlaceholder":176},true,"\n",[79,179,181],{"class":81,"line":180},4,[79,182,183],{},"uvx --from hermes-agent python -c \"import json; print(json.load(open('x-search-result.json',encoding='utf-8'))['credential_source'])\"\n",[79,185,187],{"class":81,"line":186},5,[79,188,189],{},"# → xai-oauth\n",[15,191,192,195,196,199,200,203,204,207,208,211],{},[19,193,194],{},"model"," が ",[19,197,198],{},"grok-4.20-reasoning"," だった。SuperGrok 系の上位推論モデルが裏で走っている。",[19,201,202],{},"credential_source"," は ",[19,205,206],{},"xai-oauth"," なので、Premium Plus のサブスク枠で動いていることもここで腑に落ちた。仮にここが ",[19,209,210],{},"xai-api"," になっていたら、API キー経由の従量課金が走っている合図なので、毎回チェックする習慣に組み込みたいフィールドだ。",[15,213,214,216,217,220],{},[19,215,115],{}," フィールドは Markdown 形式で、各引用ポストの URL が脚注で添えられていた。",[19,218,219],{},"inline_citations"," にも引用 URL のリストが入っていて、内訳が突き合わせできるようになっている。",[10,222,223],{"id":223},"一時ファイルは確認後すぐ消した",[15,225,226,227,229,230,233],{},"検証中に作った ",[19,228,153],{}," と、ワンライナーが入り組んだので一時的に作った ",[19,231,232],{},"run-x-search.py"," の2つは、内容を確認した直後に削除した。理由は2つある。",[42,235,236,239],{},[45,237,238],{},"JSON 本体に自分のポスト原文がそのまま入っており、個人発信データをディスクに長期保存する積極的な理由がない",[45,240,241],{},"リポジトリにうっかり混入させる事故を未然に消したかった",[15,243,244,245,248],{},"ファイル保存が必要な場面は出てくると思うので、スキル本文には ",[19,246,247],{},"memo/{YYYY-MM-DD}/x-search-{topic}.json"," 形式で保存する選択肢だけ残し、今回のような検証用途では stdout で済ませる方針をメモに書いた。",[10,250,251],{"id":251},"ユーザースキルに固めた",[15,253,254,255,258],{},"ワンライナーが手に馴染んだので、",[19,256,257],{},"~/.claude/skills/x-search/SKILL.md"," にユーザーレベルのスキルとして固めた。プロジェクト直下ではなくユーザースキルにしたのは、Xの検索はプロジェクトを跨いで使いたいから。どのリポジトリで Claude Code を起動してもこのスキルが効く。",[15,260,261],{},"description には音声入力時のフックを意識して、表記揺れを全部詰め込んだ。",[70,263,268],{"className":264,"code":266,"language":267},[265],"language-text","「Xを検索」「Twitterを検索」「ツイッターを検索」「エックスを検索」\n「ツイートを調べて」「ポストを調べて」「@xxxの直近の投稿を要約」\n","text",[19,269,266],{"__ignoreMap":75},[15,271,272],{},"音声入力では「エックス」「ツイッター」「ツイート」「ポスト」あたりが頻出する。description にこれらの表記を並べておくと、口頭で投げた指示でも Claude Code がスキルを引き当ててくれる。",[15,274,275],{},"スキル本体には以下を盛り込んだ。",[42,277,278,285,288,304,316,319],{},[45,279,280,281,284],{},"前提（uv インストール、",[19,282,283],{},"uvx --from hermes-agent hermes auth add xai-oauth"," で OAuth、Premium+ または SuperGrok 必須）",[45,286,287],{},"最小ワンライナー",[45,289,290,291,293,294,293,297,293,300,303],{},"パラメータ仕様（",[19,292,123],{},", ",[19,295,296],{},"from_date",[19,298,299],{},"to_date",[19,301,302],{},"enable_image_understanding"," ほか）",[45,305,306,307,293,309,293,311,293,313,315],{},"レスポンス主要フィールド（",[19,308,194],{},[19,310,202],{},[19,312,115],{},[19,314,219],{},"）",[45,317,318],{},"クエリ作成のコツ（ハンドルは本文と allowed の両方に書く / 原文引用を明示 / 期間を絞る）",[45,320,321,322,325,326,329],{},"トラブルシューティング（",[19,323,324],{},"I need more information"," が返る時の対処、",[19,327,328],{},"credential_source: xai-api"," の警告）",[10,331,332],{"id":332},"学び",[15,334,335,337],{},[19,336,123],{}," だけで通じるはずだ、と最初に決め打ちしたのが小さい遠回りだった。クエリ本文と allowed_x_handles の役割が分かれている、と分かった瞬間に挙動が腑に落ちた。スキルのトラブルシューティング欄に「ハンドル名を教えてください」が返ってきたら本文にも書け、という導線を最初から残せたのは、この遠回りのおかげだ。",[15,339,340,342,343,345,346,348],{},[19,341,202],{}," の確認を習慣化する、というメモも今回のうちに刻んでおいた。",[19,344,206],{}," のまま動いていることを毎回見にいけば、サブスク枠で済んでいることを自分の目で確かめられる。",[19,347,210],{}," に静かに切り替わっていたら、従量課金が走っている合図として早めに気づける。",[15,350,351,352,355],{},"ポストデータをディスクに残すか即削除するか、という判断は、毎回考えるとブレるので、スキル側のメモに方針として書いておくのが正解だった。一時確認は stdout、残すなら ",[19,353,354],{},"memo/{YYYY-MM-DD}/"," 配下、という線引きを最初から書いておけば、次に使うときに迷わない。",[10,357,358],{"id":358},"次にやること",[42,360,363,376,385],{"className":361},[362],"contains-task-list",[45,364,367,371,372,375],{"className":365},[366],"task-list-item",[368,369],"input",{"disabled":176,"type":370},"checkbox"," 前日のポスト傾向を踏まえてポスト案を出す ",[19,373,374],{},"/review-yesterday-tweets"," の入り口を、x-search スキル経由に差し替える",[45,377,379,381,382,384],{"className":378},[366],[368,380],{"disabled":176,"type":370}," 決算ネタの過去ポストを横断要約する用途で、",[19,383,296],{}," を四半期単位で動かす定型クエリを memo に残す",[45,386,388,390,391,394],{"className":387},[366],[368,389],{"disabled":176,"type":370}," フォロワーが反応したポストを抽出する用途で、",[19,392,393],{},"enable_image_understanding=True"," 付きの呼び出しを試す",[396,397,398],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":75,"searchDepth":167,"depth":167,"links":400},[401,402,403,404,405,406,407,408,409],{"id":12,"depth":167,"text":13},{"id":28,"depth":167,"text":29},{"id":62,"depth":167,"text":62},{"id":93,"depth":167,"text":94},{"id":146,"depth":167,"text":147},{"id":223,"depth":167,"text":223},{"id":251,"depth":167,"text":251},{"id":332,"depth":167,"text":332},{"id":358,"depth":167,"text":358},"dev","Hermes Agent の x_search_tool を uvx で呼び、SuperGrok の grok-4.20-reasoning を裏で回す経路を確立した。ハンドル指定の落とし穴に1回つまずいたあと、ポストデータをディスクに残さない手順ごとユーザースキル化して、音声入力からも叩けるようにした","md",{},null,"/x-search-skill","claude-code-tools",false,"2026-05-20T00:00:00.000Z",{"title":5,"description":411},"2026-05/2026-05-20/x-search-skill",[422,423,424,425,426],"X","Grok","Claude Code","スキル","SuperGrok","aFNqosJjO5Og-V9i13I2TEMlp4t-rCvOAzKM5zMSJjI",[],"https://log.eurekapu.com/og/blog/x-search-skill.png?v=2026-05-20T00%3A00%3A00.000Z&title=x_search_tool%20%E3%82%92%20Claude%20Code%20%E3%82%B9%E3%82%AD%E3%83%AB%E3%81%AB%E5%9B%BA%E3%82%81%E3%81%A6%E3%80%81%E8%87%AA%E5%88%86%E3%81%AEX%E3%83%8F%E3%83%B3%E3%83%89%E3%83%AB%E3%82%92%E6%B4%BE%E9%81%A3%E8%AA%BF%E6%9F%BB%E3%81%95%E3%81%9B%E3%82%8B%E4%BB%95%E7%B5%84%E3%81%BF%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%9F&author=Kei%20Komatsu&sig=e8d7836e876547fd",1782528840263]