aro-mobi

ライター石井徹の個人ブログ

Blueskyの投稿をClaudeから閲覧できるスキルを作った

ClaudeからBlueskyを検索するスキルを作りました

Claudeに話しかけるだけで、Blueskyのユーザー投稿やカスタムフィードを取得できるスキルを作りました。

たとえば「Blueskyでnikkei.comの最近の投稿を見せて」と入力すると、日経電子版(@nikkei.com)の最近の投稿をClaude上に一覧表示できます。「いいねが多い順に並べて」「3月の投稿だけ表示して」といった絞り込みもできます。

日経電子版のBlueskyの投稿を検索している様子

Claudeのスキルとは

Claudeには「スキル」という拡張機能があります。スキルを追加すると、Claude単体ではアクセスできない外部サービスの情報を取得したり、特定の処理を実行できるようになります。スキルの実体は、設定ファイルとスクリプトをまとめたZipファイル(拡張子を.skillに変えたもの)です。

たとえば以前作った国会議事録検索スキルは、国会図書館が公開しているデータベースから議事録を検索します。今回のスキルはBlueskyから投稿を取得します。どちらもClaude単体ではできないことを、スキルを追加することで可能にしています。

スキルはClaude Desktop、claude.aiのWebブラウザ、モバイルアプリのいずれでも動きます。

インストール方法

以下からスキルファイルをダウンロードしてください。

bluesky-search.skill - Google ドライブ

Claudeにスキルを追加

  1. Claude Desktopまたはclaude.aiの設定画面を開く
  2. 「カスタマイズ」→「スキル」セクションへ
  3. 「+」ボタンから「スキルをアップロード」を選択
  4. ダウンロードした.skillファイルをアップロード

ネットワーク許可を設定

このスキルはBlueskyに接続して情報を取得するため、ネットワーク許可の設定が必要です。

  1. 設定画面の「機能」→「コード実行とファイル作成」セクションへ
  2. 「許可されたドメイン」に public.api.bsky.app を追加

この設定をしないとBlueskyに接続できず、スキルが動作しません。

※スマホアプリからは設定できない場合があります。ブラウザでclaude.aiを開いて設定してください。

使ってみる

新しい会話を開いて、「(ご自身のハンドル)のBluesky投稿を見せて」と入力してみてください。投稿が表示されれば成功です。

できること

ユーザーの投稿取得

一番よく使う機能です。ハンドル名を指定すると最近の投稿を取得します。

「aroka.netの最近の投稿を見せて」
「nikkei.comの投稿から半導体に言及しているものだけ表示して」
「3月1日から15日までの投稿に絞って、いいね順で」

キーワードフィルタ、エンゲージメント順ソート、日付範囲の指定、複数ページの一括取得に対応しています。

カスタムフィードの閲覧

Blueskyにはユーザーが作ったカスタムフィード(アルゴリズムフィード)があります。フィード名を指定するだけで投稿を取得できます。

「サメの洗濯フィードの人気投稿を3つピックアップして」
「買っちゃったフィードを時系列順に10件取得して」

試しに「サメの洗濯」という自作フィード(IKEAのサメのぬいぐるみを洗濯している写真が集まるフィード)の人気投稿を取得してみたところ、ちゃんと動きました。

「サメの洗濯」フィードの人気投稿を表示

その他

ユーザー検索、プロフィール取得、ハンドル名とDID(分散ID)の相互変換、特定ユーザーが作成したフィードの一覧取得ができます。

取得した投稿はClaudeが内容を要約してくれるほか、表形式・引用カード・集計サマリー・タイムラインの4つの表示形式で画面に表示することもできます。

できないこと

このスキルはログイン不要で誰でも見られる公開データだけを使っています。そのため、いくつか制約があります。

投稿・いいね・フォローはできません。 読み取り専用です。Blueskyへの書き込み操作は一切できません。

キーワードによる全文検索はできません。 2026年3月にBluesky側でログイン必須に変更されました。代わりに、特定ユーザーの投稿を取得してからキーワードで絞り込む機能を入れています。

Discoverフィードなど、ログインしたユーザーごとに内容が変わるフィードは取得できません。 自分のホームタイムラインも同様です。誰が見ても同じ内容が返るカスタムフィード(「サメの洗濯」など)は取得できます。

投稿画像は表示できません。 Claudeの画面内にBlueskyの画像を埋め込む方法がないため、画像付き投稿は「[画像]」というテキスト表記になります。実際の画像はbsky.appのリンクから確認してください。

フォロー・フォロワー一覧、いいねした投稿の一覧は取得できません。 これらもログインが必要なデータです。

なぜ作ったか

BlueskyにはMCPサーバー(Claude Desktopに接続して使う拡張機能)もあって、以前からそれを使ってBlueskyの投稿をClaudeの会話内で参照していました。月次の振り返りをClaudeとやるときに、自分のBluesky投稿を引っ張ってきて傾向を分析してもらう、という使い方です。

ただ、MCPサーバーはClaude Desktopでしか動きません。出先でスマホからclaude.aiを開いて投稿を確認したいときには使えない。スキルなら、Webブラウザやモバイルアプリからでも使えます。ログインなしで取得できるデータに限定されますが、誰かの投稿を見たりカスタムフィードを覗いたりする日常の操作はカバーできるので、十分実用になると考えました。

私はBlueskyの投稿をClaudeに渡して活動の振り返りをしています


開発メモ

ここから先は、開発の過程で気づいた技術的な話です。使うだけなら読まなくて大丈夫です。

スキルの構成

bluesky-search/
├── SKILL.md                      # スキルの説明・使い方・注意事項
├── references/
│   └── display-formats.md        # 4種類の表示形式テンプレート
└── scripts/
    └── bsky_search.py            # 本体(Python、標準ライブラリのみ)

SKILL.mdにはスキルの説明、各コマンドの使い方、Claudeへの動作指示が書かれています。Claudeはユーザーの入力を見てこのファイルを読み込み、適切なコマンドを選んで実行します。

bsky_search.pyはBlueskyの公開API(public.api.bsky.app)を叩くPythonスクリプトです。標準ライブラリのみで動くので、pip installは不要です。8つのコマンドがあります。

  • feed — ユーザーの投稿取得(メインで使う)
  • users — ユーザー検索
  • profile — プロフィール取得
  • resolve — ハンドル⇔DID相互変換
  • custom-feed — カスタムフィード投稿取得
  • feed-search — カスタムフィード検索
  • feed-list — ユーザーが作成したフィード一覧
  • posts — 全文検索(認証必須のため非推奨)

feedとcustom-feedにはクライアント側のフィルタ機能があり、取得した投稿に対して --grep(キーワードフィルタ)、--sort=top(エンゲージメント順ソート)、--since/--until(日付フィルタ)、--pages(複数ページ一括取得)を適用できます。

references/display-formats.mdには、Claudeの画面内で投稿を表示するためのHTMLテンプレートが4種類入っています。Claudeはこのテンプレートを読んで、表や引用カードを描画します。

searchPostsが突然使えなくなった

最初のバージョンでは、searchPosts APIで全文検索ができていました。ところが開発を進めている途中で403エラーが返るようになりました。

最初はレートリミット(短時間にリクエストを送りすぎた)かと思い、パラメータを変えてリトライしたり、しばらく時間を空けたりしましたが改善しない。他のAPI(feed、profile、users)は同じセッション内で正常に動いているのにsearchPostsだけが拒否される。

DEV Communityの記事を見つけて原因が判明しました。searchPostsは認証必須に変更されていた。特定のパラメータの問題でもレートリミットでもなく、認証なしでのアクセス自体がブロックされていたわけです。

スキルは認証情報を持てない(App Passwordをスクリプトに埋め込むわけにはいかない)ので、searchPostsは使わない方針に切り替えました。代わりにfeedコマンドのクライアント側フィルタを充実させて、「まず投稿を取得して、手元で絞り込む」設計にしています。公開APIに依存する以上、こういう仕様変更はいつでも起きうるので、代替手段を用意しておくのは大事だなと感じました。

カスタムフィード対応で分かったこと

カスタムフィードの投稿取得(getFeed API)が認証なしで動くことは、実際に叩いてみるまで分かりませんでした。searchPostsが403になった後だったので、「カスタムフィードも認証が必要かもしれない」と構えていたのですが、問題なく動いた。

ただ、カスタムフィードを名前で検索するAPI(getPopularFeedGenerators)でハマりました。検索クエリのパラメータ名が他のAPIとは違っていて、q ではなく query でした。q で渡すとパラメータが無視されて、デフォルトの人気フィード一覧が返ってくる。日本語のフィード名で検索しても結果が出ないので「日本語は精度が低いのかな」と思っていたのですが、単にパラメータが届いていなかっただけでした。

画像が表示できない理由

Claudeの画面内で投稿を表示するときにVisualizer(HTMLウィジェット)を使っていますが、Visualizerにはセキュリティ上の制約(CSP:Content Security Policy)があり、読み込める画像のドメインが限られています。Blueskyの画像CDN(cdn.bsky.app)は許可リストに入っていません。

「ネットワーク設定の許可ドメインに追加すれば読み込めるのでは」と試してみましたが、ネットワーク許可(スクリプトからのHTTPアクセスに適用)とVisualizerのCSP(画面内のimgタグに適用)は別の仕組みでした。Visualizer側のCSPはAnthropicが管理する固定設定なので、ユーザー側からは変更できません。

結果として、アバターはイニシャル表示、投稿画像は「[画像]」テキスト表記、という割り切りにしています。

Blueskyの公開APIとの付き合い方

Blueskyの公式ドキュメントによると、public.api.bsky.app は「public web」ユースケース向けに提供されているキャッシュ済みの公開エンドポイントです。レートリミットは「generous(寛大)」とされていますが、具体的な数値は公開されていません。

このスキルでは、複数ページ一括取得時に0.5秒の間隔を入れてレートリミットに配慮しています。また、読み取り専用で大量収集やデータセット構築には使わない、という範囲に留めています。Blueskyの公式ボットガイドでは、レートリミットの尊重とopt-inインタラクションが求められていますが、読み取り専用のAPI利用を制限する記述はありません。