この記事自体、GitHub issueに「記事ネタ ブログ自動化」と書いておいたら、クラウド上で定期的に起動するAIエージェントが拾って書いている。issue番号は#225。
書き上がった原稿はDraft PR(レビュー待ちのプルリクエスト)として提出され、あとで自分がレビューしてから公開する。寝ている間に下書きが積まれているのは、地味に便利だ。
以前は「複数の作業ディレクトリを同時に走らせて記事を並列生成する」方式を試していたが、1日で運用をやめ、今は「クラウド環境が毎時起動してGitHubのissueとPRだけで完結するルーティン」に切り替えている。この記事では、今動いている仕組みを一通り説明する。
並列生成は1日で終わった
Gitには「worktree」という機能があり、同じリポジトリを複数のディレクトリにチェックアウトして同時に作業できる。これを使い、AIコーディングツール活用の記事など4本を並列に書かせてmainにマージする運用を1日試した。ローカルのHugo開発サーバーを常時起動させ、各worktreeで書いた記事だけをプレビューサイトに同期するスクリプトも同じ日に用意した。
このマージ履歴、リポジトリのコミット履歴を全体で見てもその日の4件以降は一度も出てこない。1日試して終わっている。
5日後には別の仕組み(後述のクラウド定期ドラフト)の実装が始まっていて、以降の下書きはすべてそちら経由になった。worktreeは同一マシン上での並列作業には向くが、「複数の下書きを人間のレビュー待ちで並べておく」という目的自体はGitHubのDraft PRがそのまま担える。ローカルのworktreeやHugoサーバーの管理をエージェント任せにする分だけ、こちらの方が手離れが良かったということだと思う。
いまの仕組み: 使用率ゲート付きクラウド定期ドラフト
クラウド環境が毎時1回起動し、手順書1枚(リポジトリ内に置いた指示ファイル)だけを読んで、ゼロから状況を把握して動く。前回までの記憶は引き継がない。手順は次の4段階。
Step 0: 使用率ゲートを判定する
まず、AIの利用量(Claude Codeの利用枠)が上限に近づいていないかを確認するスクリプトを実行する。判定は3段階のフォールバックになっている。
- セッションが書き出す利用率のJSONファイル(あれば最優先で使う)
- デスクトップPCが10分おきにGitHubの専用ブランチへ公開している利用率データ
- どちらも取得できない場合、直近のDraft PR作成からの経過時間で代用する
しきい値は「5時間の利用枠が30%以内、7日間の利用枠が70%以内」で、判定用の設定ファイルに数値として持たせている。3の時間フォールバックに落ちる条件は、2の利用率データが120分以上更新されていないとき。
この記事を書き始めた回では、デスクトップPCが公開する利用率データが772分(約13時間)前から更新されておらず、120分のしきい値を超えていたため3番目の時間フォールバックに落ちた。直近のDraft PR作成から16時間以上空いていたため「続行してよいが今回は下書き1本まで」という制限付きの判定になり、その条件で続行した。
判定結果が「NO_GO(利用枠を使いすぎている)」ならその場で終了し、ブランチもissueもPRも作らない。
Step 1: ネタを選ぶ
GitHubのissue一覧から、タイトルに「記事ネタ」を含み、まだ「ドラフト作成済み」ラベルが付いていないオープンなissueを、作成日が古い順に1件選ぶ。今回はすでに4件が「ドラフト作成済み」ラベル付きで、残っていたのが今回選ばれたissueだけだった。
選んだissueの番号が、他のオープンなDraft PRの本文に既に含まれていないかも確認する(二重着手の安全ネット)。含まれていたらそのissueはスキップし、ラベルだけ後追いで付ける。
Step 2: 記事ネタが尽きたときは自分でネタを決める
オープンな「記事ネタ」issueが0件のときのルート。まず「最終記事作成」からの経過時間を確認し、16時間未満なら独自記事は書かずに終了する。16時間以上空いていたら、直近10本の記事(公開済み記事とオープンなDraft PR両方を含む)のfront matterのタグを見て、Forza Horizon・AI・xbox・BABYMETAL・猫・映画・町田・アフィリエイトの8ジャンルに分類する。直近10本での出現回数が最も少ないジャンルのうち、最後に書いてから最も時間が経っているものを選び、その場でWebSearchして直近1週間程度の話題からネタを決め、記事ネタissueとして登録してから執筆に進む。同じジャンルの過去記事を2〜3本読んで、トーン・構成を合わせる工程も入る。
Step 3: 執筆する
日本時間の現在時刻を確認し、frontmatterのdateはその時刻より前にする(Hugoは未来日付の記事をビルドから除外するため)。frontmatterのtagsでどのサブドメインに載る記事か決まる仕組みも、この段階で反映する。事実(価格・バージョン・発表内容)はWebSearchやWebFetchで一次情報を確認してから書き、裏取りできない情報は書かない。抽象語の乱用や機械的な三段構成などのAIっぽい言い回しを避ける規範も適用され、書き終えたら禁止フレーズの自動チェックスクリプトを流してBAN該当が0件であることを確認する。
Step 4: コミットしてDraft PRを作る
新しいブランチを切って記事ファイルだけをコミットし、pushしてDraft PRを作成する。PR本文には元issueの番号、Step 0のゲート判定結果、そして「未完了(デスクトップ側で対応)」のチェックリスト(アイキャッチ画像・Xキュー更新・二重校正・鮮度再確認)を必ず添える。最後に元issueに「ドラフト作成済み」ラベルを付け、PRへのリンクをコメントする。
クラウド側でやらないことを明確に切ってある
クラウド環境にはいくつか絶対にやらないことが決められている。
- ローカルファイル・localhostへのアクセス全般(画像生成ツール・ブラウザ操作・ノート保管庫はどれもクラウドには存在しないものとして扱う)
- mainブランチへの直接pushをしない。成果物は必ずDraft PRだけ
- アイキャッチ画像生成をしない(ローカルGPU前提の画像生成ツールはクラウドで動かせない)
- Xの投稿キューを更新しない
- 複数AIによる二重校正を実行しない
- Amazon商品写真が必要な商品レビュー系のネタは選ばない(写真をスクレイプする手段がクラウド側にない)
- Cloudflare Workersスクリプトは作成・デプロイしない(従量課金を避けるためのハード制約で、これはデスクトップ側と共通のルール)
これらは全部デスクトップ側の仕事として残してあり、Draft PRの本文にチェックリストとして必ず明記される。逆に言うと、デスクトップでの執筆作業が担っていた工程のうち、一次情報の確認と執筆・Draft PR作成の部分だけをクラウドに切り出した形になる。
クラウド環境にはghコマンド(GitHub操作用のCLIツール)が無いこともあるので、その場合はissue一覧取得やPR作成をGitHubのAPI経由のツールに読み替える運用にしてある。
人間に残った仕事は変わっていない
以前からの「ネタ出しと最終チェックだけが人間の仕事」という構図は今も同じで、レビュー対象がリポジトリへの直接pushからDraft PRに変わっただけだ。
実際、この原稿もマージされるまでは公開されない。クラウドが書いた文章を自分が読んで直している今この瞬間も、その工程そのものだ。
参考
- 寝ている間にブログが2本公開されていた ― 記事量産を「止まらないモード」にした自動化の全体図(過去記事)
- Claude Codeのバックグラウンドエージェントが、worktreeでの作業完了時に自動でドラフトPRを作るようになった(過去記事)
この記事は Claude Sonnet 5 が執筆しました。
