毎週コンスタントにブログ記事を出すために、テーマ選定・本文生成・画像連動・自動投稿まで Claude Code に任せる仕組みを 1 日で組み上げた。「LLM が知らない直近トレンド」をどう拾うか、「2 つの Claude Code セッションを git 経由で連携させる」とどう設計したか、「毎週金曜の cron 自動投稿」をどう安定させるか、3 つの試行錯誤の経緯と最終形を全部書く。Claude Code を使うと、これだけの仕組みが 1 日で動くところまで立ち上がる。
この記事でできること
- ブログのテーマ選定を Claude Code で自動化するアプローチがわかる
- 画像生成のような重い処理を別の Claude Code セッションと git 連携させる方法がわかる
- cron で headless 実行するときのハマりどころと回避策がわかる
- 「Claude Code に任せる範囲」と「人間が判断する範囲」の線引きの考え方がわかる
使ったもの
- Claude Code — Anthropic の CLI 版エージェント。本記事の主役
- Blogger(投稿先)+ Blogger API v3
- GitHub Pages — 画像配信
- Python — テーマ偵察スクリプトと MCP サーバ
- WSL2 + systemd cron — 毎週金曜 18:00 起動
最初にやったこと: 既存記事を Claude Code に読ませて文体を学習させる
このブログは 2015 年から書いてきて記事が約 80 本ある。新しい記事を AI に書かせるとき、これまでの文体・構成・カテゴリ傾向と揃っていないと 「いつもと別人が書いた感」が出る。検索からたどり着いた読者にも、定期読者にも違和感を与える。
そこで最初にやったのは、既存記事を Claude Code に全部読ませて、文体ガイドとトピック傾向をまとめさせること。具体的にはこうした:
- Blogger API(
posts.list+posts.get)で全公開記事の HTML をローカルにバックアップ - Claude Code に「あなたが今後この同じ著者として記事を書くために、文体の特徴・よく使う章立て・カテゴリ分布・避けるべき書き方を分析して、再利用できるようにまとめて」と依頼
- 出力は
memory(Claude Code がプロジェクト固有の知識を持続的に保持する仕組み)に保存
抽出された知見の例:
- 言い回しの癖: 「最短手順」「全部書く」「詰まりポイント」のような実用記事ボキャブラリ、固有のユーモアの分量感(1〜2 文に収める)
- 章立てのよく使う形: リード → 使ったもの → 手順 → 詰まりポイント → まとめ → 関連記事
- 14 のカテゴリ分布: 電子工作 / Raspberry Pi / Arduino / IoT / AI / 3Dプリンタ / 製品レビュー / ルンバ / ガジェット改造 / 音声合成 など
- 避けるべき書き方: 過剰な絵文字、シリアスすぎて読み手を選ぶ語り口、「〜と思います」の連発
- 過去 8 年分の記事タイトル全リスト: 「同じテーマを再度書かない」ための重複チェック源
これらが memory に入っていることで、Claude Code は新規記事を書くときに 「過去の自分の延長として」書ける。新規生成記事と過去記事の間の連続性が保たれる。memory はセッションをまたいで残るので、毎回プロンプトに長文の文体ガイドを貼り付ける必要がない。
なぜ自動化したのか
毎週コンスタントに記事を出したい。一方で、毎回ゼロから「最近何が話題か」を調べるのは時間が取れない。
Claude Code に「電子工作系で最近話題のテーマで書いて」と素直に頼むと、LLM の学習時点で知っているテーマから拾ってきてしまう。直近 1 年のトレンドや自分の興味とは微妙にズレる。
解決アプローチは 「直近のトレンド」「自分の興味」「過去記事との重複回避」を構造化した情報として外から流し込むこと。LLM 単体で完結させるのを諦めて、Python スクリプトで事前に下調べし、その結果を Claude Code への入力として渡す。
全体の流れ
テーマ偵察 → 記事生成 → 画像連動 → ドラフト投稿
テーマスコアリング
画像生成サービス
画像配信
ハマり 1: テーマ選定 — 「LLM が知らない直近トレンド」をどう拾うか
ここで一番悩んだ。文体は memory で揃えられても、「何について書くか」を決めるのはまた別の問題。
最初の試行: WebSearch だけ → キーワードが偏る
「電子工作系で最近話題のテーマで書いて」と Claude Code に頼んで、WebSearch を数回叩いてもらう運用から始めた。やってみるとキーワードが偏る。「Raspberry Pi」「ESP32」「Home Assistant」のような LLM がよく知っている定番に収束する。直近の新製品(Pico 2 W、XIAO ESP32-S3、SCD41 など)にうまくフォーカスできず、過去にも書いたようなネタが繰り返される。
原因: WebSearch クエリ自体が LLM 知識空間内の単語に依存する。新しい単語は知らないのでクエリに含まれず、結果も新しいトレンドを拾わない、という鶏卵問題。
解決策: 構造化された「直近 1 年のトレンド」を外部から流し込む
国内 10 + 海外 10、計 20 サイトの RSS フィードを Python で定期取得して、直近 1 年分の記事タイトルからキーワードを抽出・スコアリングする research_topics.py を作った。20 サイトの内訳:
- 国内 10: Qiita、Zenn、MONOist、ASCII.jp、ギズモード Japan、家電 Watch、ITmedia、IoT News、deviceplus、ROBOT WATCH 等
- 海外 10: Hackaday、Adafruit Blog、Hackster、CNX Software、Tom's Hardware、The Verge、Engadget、Home Assistant Blog、Ars Technica、Raspberry Pi 公式
国内サイトだけだと国内ネタに偏るので、海外 10 を併用して「日本未紹介の海外先行ネタ」を拾えるようにした。海外で話題になっているのに国内サイトでは未紹介のテーマは「日本語先行紹介」枠として候補入り。
スコアリング式
各キーワードに以下のスコアを付ける:
score = frequency × (1 + cross_source × 0.4) × cross_region_bonus × affiliate_fit × novelty × sns_boost
- frequency: 直近 1 年でそのキーワードが何記事に出てきたか
- cross_source: 何サイトで言及されているか(広く話題なら高)
- cross_region: 国内・海外の両方で言及されていれば +bonus(信頼性が高いトレンド)
- affiliate_fit: Amazon で購入できる物理製品が紐づくテーマか(マイコン・センサー・部品系は高、純ソフトウェアは低)
- novelty: 過去記事のタイトル一覧(Blogger API で取得)と照合して、すでに書いたテーマは下げる
- sns_boost: 後述
SNS シグナル: 「自分も触れたガジェット」を 2 倍ブースト
世間で話題なテーマと、自分が SNS で言及したことがあるテーマは別物。前者だけだと「自分の興味」を反映しないし、自分が試したことがないハードを書くと内容も薄くなる。
そこで X と Facebook の公式アーカイブ(個人データダウンロードで取得できる ZIP)を sns_data/ 以下に展開しておき、過去 1 年の自分の投稿テキストからキーワードを抽出。外部 RSS で言及があり、かつ自分も SNS で触れたキーワードはスコアを 2 倍ブースト。
結果として上位に来るのは、「世間で盛り上がっている × 自分も触ったことがある」テーマ。経験ベースで深く書ける。
SNS アーカイブは月〜四半期に 1 回手動で再取得して上書きする運用。API スクレイピングではなく公式アーカイブを使うことで、X / Facebook の API 仕様変更で壊れないし、画像も同梱されるので記事の写真素材にも流用できる。
NG ワードフィルタ: 「ガジェットのハック」と「ライフハック」を区別する
もう一つのハマり: 「ライフハック」「生活ハック」のような汎用ワードが上位に紛れ込む。スマホアプリの組合せや時短テクなど、本ブログの読者が期待していない汎用ネタ。
これらは NG ワードとして明示的にフィルタした。「電子工作系の改造ネタ」と「単なる便利ライフハック」を区別する基準を文字列ベースで明示する必要があった。人間にとっては自明でも LLM の判断は揺れるので、ルールを文字列で固定する方が安定する。
22 種類の記事タイプ分類でローテーション
もう一段: 22 種類の「記事タイプ」分類を作った。マイコン+センサー型ばかり連発しないようにするため。例(一部):
| 型 | 説明 |
|---|---|
| A | マイコン+センサー(Pico/ESP32 + I2C 温湿度・CO2 → MQTT 等) |
| B | 既製ガジェット改造・API ハック(SwitchBot / Echo / AirTag 等) |
| C | 3D プリンター + 機構自作 |
| D | AI × エッジ(Ollama on Pi、ローカル音声・画像認識) |
| M | レトロ・エミュレーション |
| N | 時計・タイムキーパー(Word clock、Nixie 時計、E-ink カレンダー) |
| P | OS 移行・デュアルブート・サーバ化(Asahi Linux、Proxmox 等) |
| T | 開発環境・IDE・ワークフロー(Node-RED、WSL2、Claude Code 等。本記事の型) |
| … | 他 14 型(ロボット、無線・通信、電源、オーディオ、ストレージ、レビュー、ウェアラブル、自作 PC など) |
正規表現でキーワードと型を対応付けた分類器を組んでおき、直近 5 記事でどの型が多いかを research_topics.py 出力に含める。Claude Code は CLAUDE.md の指示で「直近 5 件のうち 2 件以上が同じ型なら、別の型を選ぶ」運用になっている。マイコン+センサーの記事を 2 週連続で出さないための仕組み。
最終的な出力フォーマット
スクリプトは毎回こんな感じの候補リストを出す(簡略例):
# 直近 5 記事の型分布: A×2, B×3 → A,B 以外を優先
# 投稿候補テーマ Top 8
1. ✨🌐💰 XIAO ESP32-S3 で CO2 モニタを ESPHome から Home Assistant に流す【型 A】
根拠: 国内 4 サイト × 海外 6 サイト言及 / SNS で 3 回触れた / アフィリエイト適性高
2. 🌐💰 ファミコン互換機を Wipeout 移植機にする【型 M レトロ】
根拠: 海外 5 サイト言及(国内未紹介)/ アフィリエイト適性中
3. 💰 Asahi Linux で Mac mini を Linux サーバ化する【型 P OS 移行】
...
(以下省略)
各候補に ✨ SNS シグナル / 🌐 国内外横断 / 💰 アフィリエイト適性のフラグが付き、根拠と該当する記事タイプも併記される。Claude Code はこの中から、直近の型分布と被らない 1〜3 件を選んで深掘り(Step 1-C のハック手法調査)に進む。
「外部から構造化情報を流し込む × LLM が選ぶ」という分業にしたことで、テーマ選定がそれなりに動くようになった。
ハマり 2: 画像をどう用意するか
記事のカバー画像(OG image)は SNS シェア時のサムネイルに使われるので、ないと CTR が大きく落ちる。LLM 単体では画像生成できないので、外部サービスとの連携が必要。
選択肢を試した: Blogger admin で手動アップロード(API 自動化と相性悪い)、xAI Grok API(月額課金)、ローカル GPU で SDXL を回す(採用)。最終的に GTX 1660 SUPER 搭載 PC に ComfyUI を立ててローカル生成、生成画像は GitHub Pages 経由で配信する構成に落ち着いた。
ローカル GPU 画像生成サーバ自体の構築過程と、参照画像から実機の見た目に寄せたり水彩イラストに変換したりする話は 前記事「ブログ用 AI 画像をローカル GPU で生成する」に詳しく書いた。本記事ではその先 — 「画像生成サービスを進化させたくなったとき、Claude Code をどう使ったか」に絞る。
ハマり 3: 2 つの Claude Code セッションを git で連携させる
これが一番面白かった。記事を書く側(BlogGen)と画像を生成する側(ImgGen)はそれぞれ 別のリポ・別のマシン・別の責務。それぞれに Claude Code セッションが付く。
でも連動はしたい。たとえば「ImgGen 側に --style illustration オプションを増やしたい」と思ったとき、その仕様は呼出側の BlogGen も知っている必要がある。
採った方法: git の仕様書ファイルを「両者が見る contract」にする。
記事生成・呼出側スクリプト・仕様書ホスト
別マシン・画像生成サービス本体・実装側
docs/<feature>_spec.md)両者が見る contract
具体的な連携サイクル:
- 段階 1(仕様起票): BlogGen 側のセッションが新機能の引数名・期待動作・ワークフロー JSON 仕様を spec に書いて push
- 段階 2(実装): ImgGen 側のセッション(GPU PC 上)がリポを pull、実装、push back
- 段階 3(検証): BlogGen 側が pull、実テスト、生成画像の品質確認
- 段階 4(フィードバック): BlogGen 側が実測値(推奨パラメータ)を spec に追記、ステータスを ✅ に更新
良かった点:
- 進行が止まらない: ImgGen 側の実装を待つ間、BlogGen 側は他の検証や記事生成に進められる
- API ズレが起きにくい: spec が contract として機能するので「引数名が微妙にズレている」が起きにくい
- 各セッションが自分のリポだけ意識すればよい: 認知負荷が低い
- 記録が git history に残る: どのフェーズが・いつ・どちらのセッションから動いたか追跡可能
ハマりポイント:
- 同時編集の上書き事故: 一度、BlogGen 側が spec を push する直前に ImgGen 側が別の修正を push していたのに気づかず、古い SHA で PUT して上書きしかけた → 直後の commit で復元
- 教訓: gh CLI で spec を更新するときは PUT 直前に必ず
gh api repos/.../contents/foo --jq .shaで最新 SHA を取り直す - 引数名のリネーム時は後方互換 alias を必ず残す(呼出側が壊れる)
ハマり 4: 毎週金曜 cron + 権限ホワイトリスト
毎週金曜 18:00 JST に cron で Claude Code を --permission-mode acceptEdits の headless 実行。指定したプロンプトを 1 回実行して終了する。
最初の試行: cron 起動時に サイレントタイムアウト。原因は権限。Claude Code は対話的セッションでは「この Bash コマンド実行していい?」と都度聞くが、headless 実行ではユーザー入力ができないため、許可されない操作で詰まる。
解決策: .claude/settings.local.json の permissions.allow に必要な Bash パターンと WebFetch ドメインを事前に許可登録。「ホワイトリスト方式」で必要な操作を一つひとつ追加していく運用。
運用上の注意: 新しいツール呼出が必要になるたびにホワイトリストの追加が要る。cron ログ(logs/weekly_draft_*.log)を週次で眺めて「許可されなくて詰まった操作」を見つけたら settings.local に追記する。「最初に全部読んで漏れなく追加」より「動かして・壊れて・直す」のサイクルのほうが結局速かった。
例: scp の複合パターン Bash(scp take@host:* *) は :* がパターン途中にある形だと無効になる。Bash(scp take@host:**) のように :* を末尾に置く形に直す、というローカルなハマりも出てくる。Claude Code の /doctor コマンドで警告が出るので気付ける。
ハマり 5: Claude Code に任せる範囲 vs 人間が判断する範囲
「全部 AI に任せる」のは怖い。一方で「全部人間がやる」のは元の問題(時間が取れない)に戻る。線引きが要る。
採った設計:
| フェーズ | 担当 |
|---|---|
| RSS / SNS からのトレンド抽出 | スクリプト |
| 候補テーマからの 1 件選定 | Claude Code |
| 記事 HTML 本文生成 | Claude Code |
| 薬機法・景表法 NG ワードチェック | Claude Code |
| 参照画像の検索 → 取得 | Claude Code |
| AI 画像生成 | 別セッション |
| GitHub Pages への画像 push | Claude Code |
| Blogger API でドラフト投稿 | Claude Code |
| 最終的な公開ボタン | 人間 |
| 事実関係・タイトルのチェック | 人間 |
キーは 「ドラフトで止める」こと。Blogger API でドラフト投稿はするが、公開ボタンは押さない。人間が中身を見て、文体・事実関係・タイトルを最終チェックしてから公開する。
これにより「変な記事が出ても可逆」になる。Claude Code が試行錯誤するときの心理的安全性が確保できる。実際、テーマ選定スクリプトの初期版が「ライフハック」を量産していた時期や、画像生成パラメータ調整中も、ドラフトで止めていたおかげで安心して試せた。
よくある質問
Q. ドラフト生成に失敗したらどうなりますか?
A. cron が weekly_draft.sh を起動して Claude Code が走るが、途中で詰まったり権限が足りなかったりするとログにエラーが残ってドラフトは作られない、というだけ。次の金曜にまた走るだけなので、致命的な事故にはならない。
Q. なぜ Claude Code を 2 セッションに分けたのですか?1 セッションで両方できないのですか?
A. 物理的に別マシン(一方は GPU 搭載 PC、一方は普段使いの Linux PC)なので、それぞれの環境に張り付いた Claude Code セッションが触れる範囲が違います。別セッションで動かすことで、それぞれ自分のリポだけ意識すればよく、認知負荷が下がります。git の仕様書を contract にするとこのスタイルが成立します。
Q. 全自動公開はやらないのですか?
A. やりません。「人間が最後に見る」前提にすることで、AI による生成を試行錯誤しやすくなる、という設計です。誤情報・薬機法・景表法などのリスクを完全には自動チェックできないため、最後の関門は人間に残します。
Q. テーマ選定スクリプトはどのくらいのペースで再実行されますか?
A. cron 起動時、つまり週 1 回。RSS と SNS アーカイブから直近 1 年分のキーワード分析をその場で計算するので、結果は毎週変わります。SNS アーカイブは月〜四半期に 1 回、手動で再ダウンロードして上書きする運用です。
Q. 立ち上げにどのくらいかかりましたか?
A. 丸 1 日です。RSS 偵察スクリプト・MCP サーバ・Blogger API 連携・cron 設定・CLAUDE.md(NG ワードや文体ガイド含む)まで、CLI で対話しながら Claude Code が書き上げました。普通なら仕様策定・実装・デバッグで数週間かかる規模の仕組みが、対話するだけで一気に動くところまで進みます。
Q. 文体や記事構成は AI とどうやって揃えるのですか?
A. 過去記事を Blogger API でローカルに取得し、Claude Code に文体の特徴・章立て・カテゴリ傾向を分析させて memory に保存しました。memory はセッションをまたいで残るので、新規記事を書くたびに毎回プロンプトに長文の文体ガイドを貼り付ける必要がありません。Claude Code は「過去の自分の延長」として記事を組み立てます。
※本記事の手順は執筆時点(2026 年 5 月)で動作確認していますが、Claude Code・Blogger API・各種 OSS のバージョン更新によりそのままでは動かない場合があります。動かない場合は コメント欄でお知らせください。
まとめ
Claude Code でブログを自動化するときに効いた設計判断は次の 4 つに集約できる:
- 過去記事を AI に読ませて memory に文体・カテゴリ傾向を保存: 「過去の自分の延長として書く」連続性を最初に作る
- 「LLM 単体で完結」を諦める: 直近トレンド・自分の興味・過去記事一覧を Python で構造化して外から流し込む。LLM の知識だけで書こうとすると定番に収束する
- 2 つのセッションを git の仕様書で連携: 別マシン・別リポをまたぐ作業で「進行が止まらない」「API ズレが起きにくい」という効果が大きい。spec を contract にする発想は、Claude Code 以外の文脈でも応用が効く
- 公開のゲートは人間が押す: ドラフトで止めることで「失敗が可逆」になり、AI による生成を試行錯誤しやすくなる。完全自動化を目指さないことが結果的に自動化を進める
そして強調したいのは 立ち上げの速さ。RSS 偵察スクリプト・MCP サーバ・Blogger API 連携・cron 設定・CLAUDE.md(NG ワードや文体ガイドを含む)まで、丸 1 日で Claude Code が書き上げた。普通なら数週間かかる仕様策定・実装・デバッグが、CLI 越しに対話するだけで一気に進む。「やりたいことを言葉で説明する → ほぼ即時に動く実装が出る」サイクルが回せるので、設計判断の試行錯誤コストが劇的に下がる。
立ち上げ後は、毎週金曜の夜にドラフトが 1 本上がってきて、土日に確認して公開、というリズムになっている。完全自動化を目指さず「人間が最後に見る」前提にすることで、安心して任せる範囲を少しずつ広げられる。
この記事が役に立ったら X(Twitter)でシェアしてもらえると喜びます。
関連記事
- ブログ用 AI 画像をローカル GPU で生成する【SDXL + IP-Adapter + img2img・実生成画像で進化を全部書く】 — 本記事の「ハマり 2」で触れた画像生成サーバの構築過程を技術的に詳しく
参考
※この記事は Claude Code を使った自動更新を試しています。
0 件のコメント:
コメントを投稿