本記事は、Claude Code ベースのブログ運用環境(000-partner)からブログ執筆ハーネスを切り出し、テンプレートリポジトリ(claude-blog-harness)として汎用化、別ジャンルのお酒ブログ(こはくのおと)を約3時間で展開した実施記録だ。展開作業中に顕在化した4つの「単一ジャンル前提」と、母リポジトリへの双方向反映サイクルを報告する。
テクブログ(このブログ)を Claude Code で運用し始めてから、ずっと気になっていたことがある。「このブログ執筆の仕組みって、他のジャンルにも使えるんじゃないか?」という疑問だ。
Claude Code によるブログ自動化のコアは、リポジトリに配置したエージェント定義・Playbook・スクリプト群の組み合わせだ。これがうまく機能しているなら、テクブログ専用のロジックを取り除いた「ハーネス」として切り出せるはずだった。
今日(2026-05-16)それを実行した。テクブログ用の実行環境からハーネスを切り出してテンプレートリポジトリを作り、そのテンプレートからお酒ブログを展開した。結果的に約3時間で初記事を公開できたが、展開の過程で「テクブログ固定」の前提が4箇所出てきた。その話をする。
テンプレートの設計方針
まず、テンプレートリポジトリ(claude-blog-harness)の設計を簡単に説明する。
ブログ運用環境のうち「ブログ種別によって変わる部分」を {{PLACEHOLDER}} 形式の変数に置き換え、.template 拡張子のファイルとして管理する方式にした。今回実測したところ、10ファイルに .template 拡張子を付与している。
CLAUDE.md.template .claude/agents/writer.md.template .claude/agents/reader.md.template .claude/agents/secretary.md.template ops/playbooks/coo-startup.md.template ops/playbooks/INDEX.md.template ops/playbooks/article/crosspost.md.template ops/playbooks/article/publish.md.template ops/playbooks/article/writing.md.template ops/playbooks/article/state-management.md.template
置換変数の例は以下の通り(.env.example に全一覧がある):
{{BLOG_NAME}}— ブログ名(「こはくのおと」など){{GITHUB_REPO}}— GitHub リポジトリ識別子{{AFFILIATE_ID}}— Amazon アソシエイト ID
.template ファイルを sed で一括置換すれば、新しいブログ用のリポジトリが組み上がる、という設計だ。
展開した時系列(git log 実測)
今日の作業は以下の順で進んだ(全て JST、git log 実測)。
| 時刻 | 内容 |
|---|---|
| 07:10 | claude-blog-harness リポジトリ初期化(b35743f) |
| 08:59 | kohakunooto(お酒ブログ)をテンプレートから展開(7f62d7f) |
| 09:04 | GITHUB_REPO オーナー名の誤りを手修正(4f4ae6a) |
| 09:10 | AFFILIATE_ID を設定(9a176cb) |
| 10:14 | アードベッグ記事を初回投稿、はてな公開フロー一式を整備(9613007) |
| 10:35 | about ページ「こはくのおとについて」公開(d4a7e58) |
リポジトリ初期化から初記事公開まで約3時間4分。「半日で立ち上げ」という表現は正確で、午前中に完結している。
ただし「半日で完成した」ではない。10:14 以降も不具合修正が続く。
テンプレート展開で何が見えてくるか——顕在化した4つの前提
ここからが本題だ。テンプレートから展開してみると、テクブログで1年以上運用してきた環境の中に「テクブログ固定」の前提が潜んでいた。同じリポジトリを一種のブログでしか使ってこなかったため、気づけなかった前提だ。
前提1: エージェント定義ファイルの UTF-8 BOM 混入
writer.md と secretary.md に UTF-8 BOM が混入していた。テクブログ環境(000-partner)では問題が出ていなかったが、新規リポジトリに展開した段階で git diff のバイナリ変化として発覚した。
テンプレート側(claude-blog-harness)と展開先(kohakunooto)の両方で BOM 除去を実施した(10:44、7829368 / b60bd44)。
テクブログだけを動かしていた間は「差分が出ない」ため見えなかった問題だ。
前提2: GITHUB_REPO のオーナー名が古い初期値のまま
{{GITHUB_REPO}} のプレースホルダーは用意していたが、テンプレートのデフォルト値に古いアカウント名(saitokoichi)が残っていた。展開直後の環境で実際に動かすまでわからなかった。
展開 15分後の 09:04 に手修正(4f4ae6a)。展開コストとしては軽いが、テンプレートの値管理の甘さが露わになった。
前提3: hatena-publish.sh が独自ドメインに非対応
これが一番実害に直結した前提だ。
テクブログのはてなブログ URL は blog.saitoko.net(独自ドメイン)だが、内部では saitoko.hatenablog.com という hatenablog.com ベースの URL も使っている。一方、今回展開したお酒ブログ「こはくのおと」は kohakunooto.saitoko.net という独自ドメインのみで管理する方針にした。
そうすると、hatena-publish.sh の update_article_state() 関数が問題を起こした。記事公開後の URL 組み立てのロジックが https://${HATENA_BLOG}/entry/... 固定になっており、独自ドメインを考慮していなかった。HATENA_BLOG_URL 環境変数が設定されている場合はそちらを使うよう修正し(83ce73a、10:53)、この変数が未設定の場合は従来通りの ${HATENA_BLOG} ベースにフォールバックする後方互換も確保した。
この修正はお酒ブログ側だけの問題ではなく、テクブログ側にも潜在していたバグだったため、11:38 にテクブログ用リポジトリ(000-partner)にも横展開した(d60f7aa)。
前提4: CWD 依存 push 事故の同型4件目
さて、今日最も時間を取られた問題がこれだ。
10:55、アードベッグ記事に note 版へのリンクを追記するため bash scripts/hatena/post.sh 2026/05/16/120000 を実行した。すると blogsync の push レスポンスに次のメッセージが返ってきた。
URL changed: /entry/2026/05/16/120000
-> /entry/kohakunooto.hatenablog.com/entry/2026/05/16/120000
パスが二重になっている。正規 URL https://kohakunooto.saitoko.net/entry/2026/05/16/120000 が 404 になり、13分間アクセス不能になった。復旧は CoWork(ブラウザ経由のはてな管理画面操作)に依頼し、11:08 に完了確認。
この事故の原因は blogsync の CWD 依存だ。blogsync は設定ファイル blogsync.yaml の local_root を相対パスで持っており、実行時の作業ディレクトリが違うとパスの組み立てがおかしくなる。今日で同型事故は4件目になる(過去3件: 2026-05-04 push×4記事 / 2026-05-14 pull 後 post.sh / 2026-05-15 hatena-publish)。
毎回 governance-incident を記録し、ガードを追加してきたが、「警告ログを出して処理は続行」というゆるい実装だった。今日の4件目を契機に blogsync_detect_double_path 関数の検出時の処理を || true(素通り)から || exit 2(中断)に変更した(48552db、11:26)。被害が発生してから復旧するのではなく、発覚した時点で止める設計に切り替えた。
この厳格化もテクブログ側(000-partner)に横展開している(d60f7aa)。
展開先で見つけた修正を母リポジトリに戻す(双方向反映サイクル)
今日の作業を振り返ると、「展開先で見つかった問題が母リポジトリに還元される」サイクルが自然に動いていた。
- お酒ブログ(kohakunooto)で独自ドメイン対応の不足に気づく
- お酒ブログ側を修正する
- 同じ修正がテクブログ(000-partner)にも必要だと判断して横展開する
- テンプレートリポジトリ(claude-blog-harness)も更新する
テクブログ1本だけ運用していた期間は「自分の環境が唯一の実装」だったので、潜在的なバグは表面化しにくかった。異なる設定・異なる要件のブログへ展開したことで、想定外の利用パターンが明らかになった。
テンプレート化の副産物として「設計の試験台が増える」という効果がある。
Claude Code でブログを複数ジャンル運用するには何が必要か
テンプレート化して異ジャンルブログに展開してみると、「単一環境では見えなかったこと」が具体的に見えてくる。
1ジャンル1リポジトリで運用している間は「自分の環境が唯一の実装」なので、暗黙の前提が積み重なっていく。今回の4つの前提(BOM混入・プレースホルダー誤値・独自ドメイン非対応・CWD依存)はそのいずれも、テクブログ単独では顕在化しなかったものだ。
「Claude Code でブログ運用を始めたい人向け」に聞こえるかもしれないが、すでに1ジャンルで運用している人こそメリットが大きい。自分の環境を別文脈で動かすことが、設計の試験台になる。複数ジャンル展開を前提にするなら、ハーネス化・テンプレート化は早い段階で着手したほうがフィードバックサイクルが速い。
また、Guard の設計(警告→中断の厳格化)はブログ固有の話ではなく、「同型事故を繰り返さないためにガードをソフトからハードに変える」という判断そのものはあらゆるエージェント運用に転用できる考え方だ。
テンプレート化で残った3つの未解決課題(展開自動化・crosspost分岐・CWD依存)
今日の範囲では解決できていないことも書いておく。
テンプレート展開の手動作業が残っている: 現時点では .template ファイルを sed で一括置換する作業は手動だ。SETUP.md に手順を書いてあるが、セットアップスクリプト化はまだやっていない。
crosspost 方針の違いがテンプレートに吸収しきれていない: テクブログは Zenn/Qiita にクロスポストするが、お酒ブログはエンジニア向け媒体の読者層とミスマッチのため note のみにする。この違いをテンプレート変数でどこまで表現するかは設計中だ。
CWD 依存事故の根本原因が未解消: Guard D を厳格化して「発覚時に中断」できるようにしたが、そもそも CWD に依存しない blogsync の呼び出し方に完全統一できていない箇所がまだある。ガードの強化で被害は止まっても、事故が起きないようにはなっていない。
テンプレート化の動機は「同じ設定を一から書き直したくない」というシンプルなものだったが、やってみると「別ジャンルのブログで運用することが設計の試験になる」という副産物があった。
すでに Claude Code で何かを運用している人は、テンプレート化を「別環境への横展開」としてではなく「自分の設計への負荷試験」として考えてみると、今日の事例のような逆還元サイクルが自然に動き出す。CWD 依存ガードの厳格化に手をつけたい人は、まず || true(素通り)になっている箇所を || exit 2(中断)に変えることから始めると、被害が起きる前に止められる設計に近づく。
実施記録(2026-05-16)
テクブログ用の Claude Code 実行環境(000-partner)からブログ執筆ハーネスを切り出し、{{PLACEHOLDER}} 形式のテンプレートリポジトリ(claude-blog-harness)を作成。そのテンプレートからお酒ブログ「こはくのおと」を展開し、07:10 のリポジトリ初期化から 10:14 の初記事公開まで約3時間で立ち上げた。展開作業中に「テクブログ専用設計」の前提が4箇所顕在化し、そのうち2件(独自ドメイン対応・Guard D 厳格化)は母リポジトリ側にも横展開した(d60f7aa)。
ハーネスをテンプレート化して別ジャンルのブログを展開すると、次の問いが出てくる——そもそも「このハーネスの中身はどう設計されているのか、そして Claude Code のエージェントたちはどう組まれているのか」。私はこの問いに答えるために、Claude Code による AI チーム構築から記事公開自動化まで、実際に動いている仕組みを1冊にまとめた。ブログ執筆・記事公開・クロスポスト自動化の設計詳細は Vol.3『書き続けるまで』で取り上げている。また、ハーネスの土台となる AI チームの組み方・エージェント設計から知りたい場合は Vol.1『作るまで』が出発点になる。