## 経緯 [[Claude Code]]の練習の一環 かつ 地味に面倒な作業でもあるので。 > [!attention] > 最終的に自動投稿は諦めて、クリップボードに文言コピーしてもらうようにした。 ## 環境 | 対象 | バージョン | | --------------- | ---------- | | [[macOS]] | 15.5 | | [[Ghostty]] | 1.1.3 | | [[Claude Code]] | 1.0.34 | ## Claude Codeにヒアリング > [!right-bubble] ![[minerva-face-right.webp]] > BlueskyにGitHubでリリースした内容を共有するタスクをあなたにお願いしたいです。そのための準備に必要なことを教えて下さい。 > [!left-bubble] ![[claude-san-face.webp]] > BlueuskyにGitHubリリースを共有するための準備として、以下が必要です: > [!left-bubble] ![[claude-san-face.webp]] > ## 必要な準備 > > 1. **Bluesky APIアクセス** > - Bluesky アカウント作成 > - App Password の生成(Settings > Privacy and Security > App Passwords) > - AT Protocol APIの認証情報 > > 2. **GitHub API認証** > - Personal Access Token(リリース情報読み取り権限) > - リポジトリアクセス権限 > > 3. **技術的実装方針** > - GitHub Actions での自動化 vs ローカルスクリプト > - 投稿フォーマットの定義 > - エラーハンドリング戦略 > > どの部分から始めたいですか?また、手動実行かGitHub Actionsでの自動化のどちらを希望しますか? > [!right-bubble] ![[minerva-face-right.webp]] > ★でコメントします。 > > 1. Bluesky APIアクセス > - Bluesky アカウント作成 > - ★アカウントは作成済です > - App Password の生成(Settings > Privacy and Security > App Passwords) > - AT Protocol APIの認証情報 > 2. GitHub API認証 > - Personal Access Token(リリース情報読み取り権限) > - ★リリース情報は公開情報であり、GitHub CLIも使える状態になっているので必要ないかなと > - リポジトリアクセス権限 > 3. 技術的実装方針 > - GitHub Actions での自動化 vs ローカルスクリプト > - ★スクリプトで自動化するのではなくClaude Codeの方で考えてやってほしいです > - 投稿フォーマットの定義 > - ★基本的なフォーマットや要件はもちろん用意します > - エラーハンドリング戦略 > - ★これは一旦保留で > > [!left-bubble] ![[claude-san-face.webp]] > 了解しました。Claude Codeで手動実行する方針ですね。 > > ## 次に必要な準備 > > 1. **Bluesky App Password生成** > - Bluesky > Settings > Privacy and Security > App Passwords > - 新しいApp Passwordを作成(名前は"GitHub Release Bot"など) > > 2. **投稿フォーマット定義** > - どのような内容を投稿したいか(リリース名、変更点、URL等) > - 文字数制限(Blueskyは300文字) > - ハッシュタグの有無 > > App Passwordを生成後、投稿フォーマットの要件を教えていただければ、Claude CodeでGitHub CLI + Bluesky APIを使った投稿スクリプトを作成できます。 > > 投稿したい内容の例があれば教えてください。 ## [[Bluesky]]の[[アプリパスワードを作成 (Bluesky)|アプリパスワードを作成]] ![[2025-06-25-17-44-31.avif]] [[アプリパスワード (Bluesky)|アプリパスワード]]が表示されるので、それを利用する。 ## `/release` コマンドの作成 > [!right-bubble] ![[minerva-face-right.webp]] > 1のApp Passwordを作成しました。Carnelianの設定にApp Passwordの指定項目を追加すればOKかなと思っています。 > [!left-bubble] ![[claude-san-face.webp]] > App Password作成完了ですね。CarnelianでBlueskyのApp Passwordを設定できるようにするのは良いアイデアです。 > > 次に**投稿フォーマット**を決めましょう。GitHubリリースをBlueskyに投稿する際の内容として、どのような情報を含めたいですか? > > 例: > - リリース名とバージョン > - 主要な変更点(箇条書き) > - GitHub リリースページのURL > - ハッシュタグ(#ObsidianPlugin など) > > 投稿例のイメージがあれば教えてください。それに基づいてClaude Codeで投稿処理を実装します。 > [!right-bubble] ![[minerva-face-right.webp]] > 以下のフォーマットを想定しています。 > > ``` > 📦 ${プロダクト名} ${バージョン} 🚀 > > ・箇条書きで新機能やメインの変更点を列挙 > > ${GitHubリリースページのURL} > ``` > > また、この機能は `.claude/commands/**.md` でのコマンド登録を想定しており、そのコマンドではBluesky通知前に行うリリースジョブ実行なども定義するつもりです。 > > 1. 私がClaude Codeで `/release` を実行 > 2. 現在のリポジトリのリリース作業を実行 > - `CLAUDE.md` に記載なければ `README.md` を参照 > 3. リリースジョブ実行後はリリースが完了しているかを定期的に確認し、完了していたら該当バージョンのリリースノートURLにアクセスし、リリースしていることを確認 > 4. リリースURLとリリースノートの内容から、先程提示したフォーマットに従いBlueskyへの投稿を行う > > [!right-bubble] ![[minerva-face-right.webp]] > **作業中の割り込み指示:** > ちょっと待ってください。一度中断してください。 > [!right-bubble] ![[minerva-face-right.webp]] > すいません。このリリースフローは本リポジトリだけでなく、私が開発する場合に共通するものです。そのため.claudeはホームディレクトリの方を使います。 > [!left-bubble] ![[claude-san-face.webp]] > 理解しました。ホームディレクトリの `~/.claude/commands/` を使って汎用的な `/release` コマンドを作成しますね。 > > 現在のリポジトリのリリースプロセスを確認したところ: > - GitHub Actions の Release workflow(手動トリガー)でsemantic-releaseを使用 > - package.json のバージョンは現在 13.6.0 > > 次にホームディレクトリに `/release` コマンドを作成して、以下の流れを実装します: > 1. Release Action手動実行 > 2. リリース完了の定期確認 > 3. 完了後にBluesky投稿 > > ホームディレクトリの `.claude/commands/` ディレクトリ作成から始めましょうか? > [!right-bubble] ![[minerva-face-right.webp]] > お願いします。 > [!right-bubble] ![[minerva-face-right.webp]] > **作業中の割り込み指示:** > ちょっと待ってください。一度中断してください。 > [!right-bubble] ![[minerva-face-right.webp]] > すいません。Carnelianは関係ありませんでした。。app passwordは環境変数に設定されている前提で大丈夫です。 > [!left-bubble] ![[claude-san-face.webp]] > 了解しました。App Passwordは環境変数設定前提で進めます。 > > `~/.claude/commands/release.md` を作成しますね。以下の内容で作成します: > > 1. 現在のリポジトリのリリース作業実行 > 2. リリース完了確認 > 3. 環境変数のApp Passwordを使ってBluesky投稿 > > 作成してよろしいですか? > [!right-bubble] ![[minerva-face-right.webp]] > ok > [!left-bubble] ![[claude-san-face.webp]] > `~/.claude/commands/release.md` を作成しました。 > > これで `/release` コマンドが使用できるようになりました。必要な環境変数は: > - `BLUESKY_APP_PASSWORD` - 先ほど作成したApp Password > - `BLUESKY_HANDLE` - あなたのBlueskyハンドル > > 環境変数を設定後、現在のリポジトリで `/release` を実行すると、リリース作業からBluesky投稿まで自動実行されます。 ## `/release` コマンドの実行 (リリース完了から) リリース完了してて[[Bluesky]]への通知だけしたかったのでイレギュラーな指令を出す。 > [!right-bubble] ![[minerva-face-right.webp]] > **`/release`** > > <command-args>GitHubにはリリース済の状態からスタートして</command-args> > [!left-bubble] ![[claude-san-face.webp]] > GitHubにリリース済みの状態からスタートしてBlueskyに投稿するということですね。まず現在のリポジトリ状況を確認して、最新のリリース情報を取得します。 > [!left-bubble] ![[claude-san-face.webp]] > リリース情報を確認できました。v13.6.0が最新リリースですね。今からBluesky投稿用のフォーマットを作成します。 > [!left-bubble] ![[claude-san-face.webp]] > 次にBlueskyに投稿します。環境変数を確認してから投稿を実行します。 > [!left-bubble] ![[claude-san-face.webp]] > JSONエスケープエラーが発生しました。投稿テキストをJSONエスケープしてもう一度試します。 > [!left-bubble] ![[claude-san-face.webp]] > 日時フォーマットに問題があるようです。正しいフォーマットで再試行します。 > [!right-bubble] ![[minerva-face-right.webp]] > **作業中の割り込み指示:** > ちょっと待ってください。一度中断してください。 ## 動作確認... しかし... > [!right-bubble] ![[minerva-face-right.webp]] > 投稿はできていたのですが、GitHubのリリースURLがOGPとして登録されないまま(リンクではないただの文字列として)投稿されてしまいました。該当の投稿は削除済なので、OGPリンクとなるように調整して投稿し直してください。 > [!left-bubble] ![[claude-san-face.webp]] > OGPリンクとして認識されるように、URLを独立した行にして再投稿します。 > [!left-bubble] ![[claude-san-face.webp]] > 投稿完了しました!URLを独立した行に配置することで、BlueskyでOGPリンクとして認識されるはずです。 > [!right-bubble] ![[minerva-face-right.webp]] > [Image #1] だめそうです。。投稿は削除しました。 > [!left-bubble] ![[claude-san-face.webp]] > URLがOGPとして認識されていませんね。Blueskyでは特定の条件でないとリンクカードが表示されないようです。別のアプローチを試してみましょう。 > [!right-bubble] ![[minerva-face-right.webp]] > **作業中の割り込み指示:** > ちょっと待ってください。一度中断してください。 > [!right-bubble] ![[minerva-face-right.webp]] > 投稿フォーマットは変えないでください。恐らくfeedのPOST APIの使い方が間違っているだけだと思います。DeepwikiでBluesky APIの仕様を確認してみてください。 > [!left-bubble] ![[claude-san-face.webp]] > わかりました!Blueskyでリンクカードを表示するには、単純にURLを投稿するだけでは不十分で、OGPメタデータを自分で取得して`embed`として明示的に指定する必要があるようです。 > [!left-bubble] ![[claude-san-face.webp]] > HTMLパースがうまくいかないようです。別のアプローチを試してみます。 ## 代替案の提供 > [!right-bubble] ![[minerva-face-right.webp]] > **作業中の割り込み指示:** > ちょっと待ってください。一度中断してください。 > [!right-bubble] ![[minerva-face-right.webp]] > OGP対応難しそうなら、Blueskyに投稿する文言を作ってもらうところまでで大丈夫です。pbcopyでクリップボードに入れてもらえれば自分の方で投稿します。その方が環境変数も不要でセキュアですし、動画を貼ったりもできますしね。 > [!left-bubble] ![[claude-san-face.webp]] > 投稿内容をクリップボードにコピーしました! > > ``` > 📦 Another Quick Switcher 13.6.0 🚀 > > ・ファイル内検索でクォート文字の引用検索に対応 > ・クォート文字のエスケープ機能を追加 > > https://github.com/tadashi-aikawa/obsidian-another-quick-switcher/releases/tag/13.6.0 > ``` > > このフォーマットで手動投稿していただければ、動画の添付やOGPカードの表示も適切に行えますね。 ## コマンド内容のふりかえり > [!right-bubble] ![[minerva-face-right.webp]] > OKです。次回以降の `/release` コマンドに向けて、release.md に変更したほうがいい点あればお願いします。 > [!left-bubble] ![[claude-san-face.webp]] > release.mdファイルが存在しないようですね。今回の経験を踏まえて、`/release`コマンド用の設定ファイルを作成しますか? > [!left-bubble] ![[claude-san-face.webp]] > API Error: Request was aborted. > [!right-bubble] ![[minerva-face-right.webp]] > ~/.claude/commands/release.md の話でした > [!left-bubble] ![[claude-san-face.webp]] > 今回の経験を踏まえて、release.mdを改善すべき点があります: > [!right-bubble] ![[minerva-face-right.webp]] > **作業中の割り込み指示:** > ちょっと待ってください。一度中断してください。 > [!right-bubble] ![[minerva-face-right.webp]] > すいません。その変更でOKです。 > [!left-bubble] ![[claude-san-face.webp]] > release.mdを更新しました。今回の経験を踏まえて、APIによる自動投稿ではなく手動投稿に変更し、環境変数の設定も不要にしました。これで次回以降の`/release`コマンドはよりシンプルで確実に動作するはずです。 ## `~/.claude/commands/release.md` ````markdown # Release Command GitHubリポジトリのリリース作業を自動化し、完了後にBlueskyに投稿します。 ## 実行手順 1. **現在のリポジトリ情報確認** - リポジトリ名とプロダクト名を取得 - 現在のバージョンを確認 2. **リリース作業実行** - CLAUDE.mdまたはREADME.mdを参照してリリースコマンドを確認 - GitHub Actions Release workflowを手動実行 - または適切なリリースコマンドを実行 3. **リリース完了確認** - GitHubリリースページを定期的に確認 - 新しいリリースが作成されたことを確認 4. **Bluesky投稿準備** - リリース情報を取得してフォーマット - 投稿内容をクリップボードにコピー - ユーザーが手動でBlueskyに投稿(OGPカード表示や動画添付が可能) ## 必要な設定 - GitHub CLIが認証済みであること - pbcopyコマンドが利用可能であること(macOS標準) ## 投稿フォーマット ``` 📦 ${プロダクト名} ${バージョン} 🚀 ・箇条書きで新機能やメインの変更点を列挙 ${GitHubリリースページのURL} ``` ## 使用方法 ``` /release ``` このコマンドを実行すると、上記の手順が自動的に実行されます。 ````