xurl — X(Twitter)API 公式 CLI
xurl は X 開発者プラットフォームが提供する X API 用の公式 CLI です。一般的な操作のショートカットコマンドと、任意の v2 エンドポイントへの raw curl スタイルのアクセスをサポートします。すべてのコマンドは JSON を stdout に出力します。
このスキルは以下に使用します:
- 投稿、返信、引用、削除
- 投稿の検索、タイムライン/メンションの読み取り
- いいね、リポスト、ブックマーク
- フォロー、アンフォロー、ブロック、ミュート
- ダイレクトメッセージ
- メディアアップロード(画像と動画)
- 任意の X API v2 エンドポイントへの raw アクセス
- マルチアプリ/マルチアカウントワークフロー
このスキルは、サードパーティ製 Python CLI をラップした古い xitter スキルを置き換えます。xurl は X 開発者プラットフォームチームがメンテナンスしており、OAuth 2.0 PKCE と自動リフレッシュをサポートし、はるかに広い API サーフェスをカバーします。
シークレットの安全性(必須)
エージェント/LLM セッション内で操作する際の重要なルール:
- 絶対に
~/.xurlを読み取り、印刷、解析、要約、アップロード、LLM コンテキストに送信しないでください。 - 絶対に ユーザーにチャット内で認証情報/トークンを貼り付けるよう要求しないでください。
- ユーザーは自分のマシン上で手動で
~/.xurlにシークレットを入力する必要があります。Docker 内では、Hermes ツールサブプロセスから見える~である必要があります。以下の Docker に関する注意を参照してください。 - 絶対に エージェントセッション内でインラインシークレットを含む認証コマンドを推奨または実行しないでください。
- 絶対に エージェントセッション内で
--verbose/-vを使用しないでください — 認証ヘッダー/トークンが漏洩する可能性があります。 - 認証情報が存在することを確認するには、
xurl auth statusのみを使用してください。
エージェントコマンドで禁止されているフラグ(インラインシークレットを受け入れるため):
--bearer-token、--consumer-key、--consumer-secret、--access-token、--token-secret、--client-id、--client-secret
アプリ認証情報の登録とローテーションは、ユーザーがエージェントセッション外で手動で行う必要があります。認証情報登録後、ユーザーは xurl auth oauth2 で認証します — これもエージェントセッション外で行います。トークンは ~/.xurl に YAML 形式で保持されます。各アプリには分離されたトークンがあります。OAuth 2.0 トークンは自動リフレッシュされます。
インストール
いずれか一つの方法を選択してください。Linux ではシェルスクリプトまたは go install が最も簡単です。
# シェルスクリプト(~/.local/bin にインストール、sudo 不要、Linux + macOS で動作)
curl -fsSL https://raw.githubusercontent.com/xdevplatform/xurl/main/install.sh | bash
# Homebrew(macOS)
brew install --cask xdevplatform/tap/xurl
# npm
npm install -g @xdevplatform/xurl
# Go
go install github.com/xdevplatform/xurl@latest
確認:
xurl --help
xurl auth status
xurl がインストールされているが auth status がアプリまたはトークンを表示しない場合、ユーザーは手動で認証を完了する必要があります — 次のセクションを参照してください。
一度だけ行うユーザー設定(ユーザーがエージェント外で実行するもの)
これらの手順は、ユーザー自身が直接実行する必要があります。エージェントが実行してはいけません。シークレットを貼り付ける操作が含まれるためです。ユーザーをこのブロックに誘導し、代わりに実行しないでください。
-
https://developer.x.com/en/portal/dashboard でアプリを作成または開く
-
リダイレクト URI を
http://localhost:8080/callbackに設定する -
アプリの Client ID と Client Secret をコピーする
-
アプリをローカルに登録する(ユーザーが実行):
xurl auth apps add my-app --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET -
認証する(
--appを指定してトークンをアプリにバインドする):xurl auth oauth2 --app my-app(これにより OAuth 2.0 PKCE フローのブラウザが開きます。)
X が OAuth 後の
/2/users/meルックアップでUsernameNotFoundエラーまたは 403 を返す場合は、ハンドルを明示的に渡します(xurl v1.1.0+):xurl auth oauth2 --app my-app YOUR_USERNAMEこれによりトークンがハンドルにバインドされ、壊れた
/2/users/me呼び出しをスキップします。 -
アプリをデフォルトに設定して、すべてのコマンドがそれを使用するようにする:
xurl auth default my-app -
確認:
xurl auth status xurl whoami
この後、エージェントは以下のコマンドを追加設定なしで使用できます。OAuth 2.0 トークンは自動リフレッシュされます。
よくある落とし穴:
xurl auth oauth2から--app my-appを省略すると、OAuth トークンは組み込みのdefaultアプリプロファイルに保存されます — これには client-id や client-secret がありません。OAuth フローが成功したように見えても、コマンドは認証エラーで失敗します。これに遭遇した場合は、xurl auth oauth2 --app my-appとxurl auth default my-appを再実行してください。
Docker HOME の落とし穴: 公式の Hermes Docker レイアウトでは、
/opt/dataがHERMES_HOMEですが、Hermes ツールサブプロセスは/opt/data/homeをHOMEとして使用します。つまり、Hermes で実行されるxurlコマンドでは~/.xurlは/opt/data/.xurlではなく/opt/data/home/.xurlに解決されます。同じ HOME でユーザー設定を実行してください:HOME=/opt/data/home xurl auth apps add my-app --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET HOME=/opt/data/home xurl auth oauth2 --app my-app YOUR_USERNAME HOME=/opt/data/home xurl auth default my-app YOUR_USERNAME HOME=/opt/data/home xurl auth status
HOME=/opt/data xurl auth statusが成功してもHOME=/opt/data/home xurl auth statusがアプリやトークンを表示しない場合、Hermes ツール呼び出しは認証情報を認識しません。
クイックリファレンス
| アクション | コマンド |
|---|---|
| 投稿 | xurl post "Hello world!" |
| 返信 | xurl reply POST_ID "Nice post!" |
| 引用 | xurl quote POST_ID "My take" |
| 投稿を削除 | xurl delete POST_ID |
| 投稿を読む | xurl read POST_ID |
| 投稿を検索 | xurl search "QUERY" -n 10 |
| 自分は誰か | xurl whoami |
| ユーザーを検索 | xurl user @handle |
| ホームタイムライン | xurl timeline -n 20 |
| メンション | xurl mentions -n 10 |
| いいね / いいね解除 | xurl like POST_ID / xurl unlike POST_ID |
| リポスト / 取り消し | xurl repost POST_ID / xurl unrepost POST_ID |
| ブックマーク / 削除 | xurl bookmark POST_ID / xurl unbookmark POST_ID |
| ブックマーク / いいね一覧 | xurl bookmarks -n 10 / xurl likes -n 10 |
| フォロー / アンフォロー | xurl follow @handle / xurl unfollow @handle |
| フォロー中 / フォロワー | xurl following -n 20 / xurl followers -n 20 |
| ブロック / ブロック解除 | xurl block @handle / xurl unblock @handle |
| ミュート / ミュート解除 | xurl mute @handle / xurl unmute @handle |
| DM を送信 | xurl dm @handle "message" |
| DM 一覧 | xurl dms -n 10 |
| メディアをアップロード | xurl media upload path/to/file.mp4 |
| メディアステータス | xurl media status MEDIA_ID |
| アプリ一覧 | xurl auth apps list |
| アプリを削除 | xurl auth apps remove NAME |
| デフォルトアプリを設定 | xurl auth default APP_NAME [USERNAME] |
| リクエストごとのアプリ | xurl --app NAME /2/users/me |
| 認証ステータス | xurl auth status |
注意:
POST_IDは完全な URL も受け付けます(例:https://x.com/user/status/1234567890)— xurl が ID を抽出します。- ユーザー名は先頭の
@があってもなくても動作します。
コマンド詳細
投稿
xurl post "Hello world!"
xurl post "Check this out" --media-id MEDIA_ID
xurl post "Thread pics" --media-id 111 --media-id 222
xurl reply 1234567890 "Great point!"
xurl reply https://x.com/user/status/1234567890 "Agreed!"
xurl reply 1234567890 "Look at this" --media-id MEDIA_ID
xurl quote 1234567890 "Adding my thoughts"
xurl delete 1234567890
読み取りと検索
xurl read 1234567890
xurl read https://x.com/user/status/1234567890
xurl search "golang"
xurl search "from:elonmusk" -n 20
xurl search "#buildinpublic lang:en" -n 15
X Articles の場合は、read ショートカットの代わりに raw API モードを使用してください。xurl read は投稿 ID または投稿 URL を期待します。read を /2/tweets/... エンドポイントの前に置かないでください。article ツイートフィールドをリクエストし、JSON レスポンスから data.article.plain_text を取り込んでください:
xurl --app APP_NAME '/2/tweets/2057909493250539891?expansions=author_id,attachments.media_keys,referenced_tweets.id&tweet.fields=created_at,lang,public_metrics,context_annotations,entities,possibly_sensitive,conversation_id,in_reply_to_user_id,referenced_tweets,article'
ユーザー、タイムライン、メンション
xurl whoami
xurl user elonmusk
xurl user @XDevelopers
xurl timeline -n 25
xurl mentions -n 20
エンゲージメント
xurl like 1234567890
xurl unlike 1234567890
xurl repost 1234567890
xurl unrepost 1234567890
xurl bookmark 1234567890
xurl unbookmark 1234567890
xurl bookmarks -n 20
xurl likes -n 20
ソーシャルグラフ
xurl follow @XDevelopers
xurl unfollow @XDevelopers
xurl following -n 50
xurl followers -n 50
# 他のユーザーのグラフ
xurl following --of elonmusk -n 20
xurl followers --of elonmusk -n 20
xurl block @spammer
xurl unblock @spammer
xurl mute @annoying
xurl unmute @annoying
ダイレクトメッセージ
xurl dm @someuser "Hey, saw your post!"
xurl dms -n 25
メディアアップロード
# タイプ自動検出
xurl media upload photo.jpg
xurl media upload video.mp4
# 明示的なタイプ/カテゴリ
xurl media upload --media-type image/jpeg --category tweet_image photo.jpg
# 動画はサーバー側の処理が必要 — ステータスを確認(またはポーリング)
xurl media status MEDIA_ID
xurl media status --wait MEDIA_ID
# 完全なワークフロー
xurl media upload meme.png # メディア ID を返す
xurl post "lol" --media-id MEDIA_ID
raw API アクセス
ショートカットは一般的な操作をカバーしています。それ以外の場合は、任意の X API v2 エンドポイントに対して raw curl スタイルのモードを使用してください:
# GET
xurl /2/users/me
# JSON ボディで POST
xurl -X POST /2/tweets -d '{"text":"Hello world!"}'
# DELETE / PUT / PATCH
xurl -X DELETE /2/tweets/1234567890
# カスタムヘッダー
xurl -H "Content-Type: application/json" /2/some/endpoint
# ストリーミングを強制
xurl -s /2/tweets/search/stream
# 完全な URL も動作
xurl https://api.x.com/2/users/me
グローバルフラグ
| フラグ | 短縮形 | 説明 |
|---|---|---|
--app | 特定の登録アプリを使用(デフォルトを上書き) | |
--auth | 認証タイプを強制:oauth1、oauth2、または app | |
--username | -u | 使用する OAuth2 アカウント(複数存在する場合) |
--verbose | -v | エージェントセッションでは禁止 — 認証ヘッダーが漏洩します |
--trace | -t | X-B3-Flags: 1 トレースヘッダーを追加 |
ストリーミング
ストリーミングエンドポイントは自動検出されます。既知のものは以下を含みます:
/2/tweets/search/stream/2/tweets/sample/stream/2/tweets/sample10/stream
任意のエンドポイントで -s を使用してストリーミングを強制します。
出力形式
すべてのコマンドは JSON を stdout に返します。構造は X API v2 を反映しています:
{ "data": { "id": "1234567890", "text": "Hello world!" } }
エラーも JSON です:
{ "errors": [ { "message": "Not authorized", "code": 403 } ] }
一般的なワークフロー
画像付きで投稿
xurl media upload photo.jpg
xurl post "Check out this photo!" --media-id MEDIA_ID
会話に返信
xurl read https://x.com/user/status/1234567890
xurl reply 1234567890 "Here are my thoughts..."
検索してエンゲージ
xurl search "topic of interest" -n 10
xurl like POST_ID_FROM_RESULTS
xurl reply POST_ID_FROM_RESULTS "Great point!"
自分のアクティビティを確認
xurl whoami
xurl mentions -n 20
xurl timeline -n 20
複数アプリ(認証情報は手動で事前設定)
xurl auth default prod alice # prod アプリ、alice ユーザー
xurl --app staging /2/users/me # staging に対して一回限り
エラーハンドリング
- エラー時はゼロ以外の終了コード。
- API エラーも JSON として stdout に出力されるので、解析可能です。
- 認証エラー → ユーザーにエージェントセッション外で
xurl auth oauth2を再実行してもらいます。 - 発信者のユーザー ID を必要とするコマンド(いいね、リポスト、ブックマーク、フォローなど)は
/2/users/me経由で自動取得します。そこで認証に失敗すると、認証エラーとして表示されます。
エージェントワークフロー
- 前提条件を確認:
xurl --helpとxurl auth status。 - デフォルトアプリに認証情報があるか確認します。
auth statusの出力を解析してください。デフォルトアプリは▸でマークされています。デフォルトアプリがoauth2: (none)と表示しているが、別のアプリに有効な oauth2 ユーザーがいる場合、ユーザーにxurl auth default <そのアプリ>を実行して修正するよう伝えてください。これが最も一般的な設定ミスです — ユーザーはカスタム名でアプリを追加したが、デフォルトに設定しなかったため、xurl は空のdefaultプロファイルを使い続けます。 - 認証が完全に欠落している場合は、停止してユーザーを「一度だけ行うユーザー設定」セクションに誘導してください — 自分でアプリを登録したりシークレットを渡したりしないでください。
- 安価な読み取りコマンド(
xurl whoami、xurl user @handle、xurl search ... -n 3)から始めて、到達可能性を確認します。 - 書き込みアクション(投稿、返信、いいね、リポスト、DM、フォロー、ブロック、削除)の前に、対象の投稿/ユーザーとユーザーの意図を確認します。
- JSON 出力を直接使用してください — すべてのレスポンスはすでに構造化されています。
~/.xurlの内容を会話に貼り付けないでください。
トラブルシューティング
| 症状 | 原因 | 修正 |
|---|---|---|
| OAuth フロー成功後の認証エラー | トークンが名前付きアプリではなく default アプリ(client-id/secret なし)に保存された | xurl auth oauth2 --app my-app その後 xurl auth default my-app |
OAuth 中の unauthorized_client | X ダッシュボードでアプリタイプが「ネイティブアプリ」に設定されている | ユーザー認証設定で「ウェブアプリ、自動アプリ、またはボット」に変更 |
OAuth 直後の /2/users/me での UsernameNotFound または 403 | X が /2/users/me からユーザー名を確実に返さない | xurl auth oauth2 --app my-app YOUR_USERNAME を再実行(xurl v1.1.0+)してハンドルを明示的に渡す |
| すべてのリクエストで 401 | トークンの期限切れ、または間違ったデフォルトアプリ | xurl auth status を確認 — ▸ が oauth2 トークンを持つアプリを指しているか確認 |
client-forbidden / client-not-enrolled | X プラットフォームの登録問題 | ダッシュボード → アプリ → 管理 → 「従量課金」パッケージ → 本番環境に移動 |
CreditsDepleted | X API の残高が $0 | 開発者コンソール → 課金でクレジットを購入(最低 $5) |
画像アップロード時の media processing failed | デフォルトカテゴリが amplify_video | --category tweet_image --media-type image/png を追加 |
| X ダッシュボードに「Client Secret」の値が2つある | UI のバグ — 最初のものは実際は Client ID | 「Keys and tokens」ページで確認。ID は MTpjaQ で終わる |
注意事項
- レート制限: X はエンドポイントごとにレート制限を適用します。429 は待って再試行を意味します。書き込みエンドポイント(投稿、返信、いいね、リポスト)は読み取りよりも厳しい制限があります。
- スコープ: OAuth 2.0 トークンは広範なスコープを使用します。