1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ガバナンスの土台は公開ベースを当てるだけ。その上にブログ層を足す境界の引き方

1
Posted at

この記事はシリーズ「Claude Code で技術ブログを無人運用する — 無料章から読む仕組みの全体像」の第 2 回(全 6 回)です。

Claude Code のスケジュール実行だけで技術ブログ(Qiita 主軸・Zenn 試験投稿・X 告知・画像生成)が人手なしで回り続ける仕組みを、運用しているリポジトリの実測ログとコマンド結果で解説する連載です。Zenn 本『Claude Code で技術ブログを無人運用する』の無料章(第 1〜3 章・第 18 章・第 20 章)をもとにしており、各回は本の該当章へ戻れる導線を持ちます。掲載する数値と実行結果は各回の執筆時点で採取し直します。

仕組み全体を自分のリポジトリで組み直したい方へ: 無料章の続き(記事の型・品質ゲート・Qiita/Zenn/X の公開設計・無人実行・計測)を全 20 章の手順書として書いた Zenn Book を公開しています(有料 500 円・試し読みあり)。

シリーズ全体の目次
  • 第 1 回 1 日 4 スロットのスケジュール実行で、技術ブログが人手なしで出続ける仕組みの全体像
  • 第 2 回 ガバナンスの土台は公開ベースを当てるだけ。その上にブログ層を足す境界の引き方(この記事)
  • 第 3 回 無人ブログの現在地を 3 か所から数える: 台帳・公開ログ・エンゲージメント実績(公開予定)
  • 第 4 回 Zenn がデプロイ成功なのに公開されない・Qiita の 429: 無人運用で踏んだ公開まわりの症状(公開予定)
  • 第 5 回 X の 403・承認待ちでスロットが空振り・git push が 403: 無人運用の拡散と運用の症状(公開予定)
  • 第 6 回 本を Claude Code に読ませて自分のリポジトリに再現する: 読む順路・検証済み SHA・改訂の追随(公開予定)

はじめに

第 1 回では、1 日 4 回の起動で記事の執筆から公開・告知までが人手なしで回る流れを追いました。その流れを支えるファイルは、大きく 2 種類に分かれます。1 つは Claude Code に何をさせ、何をさせないかを決めるガバナンスの層で、もう 1 つが記事を書いて外へ出すためのブログ運用の層です。

前者を、本リポジトリは自分で書いていません。同じアカウントで公開している汎用の土台 kai-kou/claude-code-repository-base(MIT ライセンス、以下「公開ベース」)を当てて手に入れ、その上にブログ層を足しています。悩ましいのは境界です。公開ベースは今も更新が続いていて、取り込むたびに、自分で足した部分とぶつからないかを気にすることになります。

この回で立てる問いは 1 つです。共通の土台とブログ層の境界を、どこに、どうやって引くか。 答えは末尾の「結論」で出します。

対象読者は、第 1 回で連載の全体像をつかみ、自分のリポジトリで「どこまでを共通の土台に任せ、どこから自前で持つか」を決めたい人です。

掲載したコマンドの出力は、2026-09-28 JST に本リポジトリのコミット d3b778b で採取したものです。どれも数える・読む・検査するだけのコマンドで、投稿や課金を伴う処理は実行していません。

2 層を分けるのは「誰の更新に追随するか」

下の層に入っているのは、大原則(ユーザーへの確認を最小にして自律的に進めるための行動規範)、セッション安全(圧縮や切断で作業を失わないための規則)、PR 自律化(作業ブランチから PR を作り、セルフレビューを経てマージまで進める流れ)、教訓管理、そしてそれらを強制するフックです。どれもブログに固有のものではなく、Claude Code でリポジトリを無人運用するなら題材を問わず必要になります。

上の層は、記事の型、投稿先ごとの上限、公開パイプライン、X での告知、画像生成、コメントや返信への対応です。こちらは本リポジトリの中でしか意味を持ちません。

2 つを分ける基準は、機能の種類ではなく「そのファイルが誰の更新に追随するか」です。下の層のファイルは公開ベースの更新とともに変わり、上の層のファイルは本リポジトリの運用に合わせて変わります。1 つのファイルを両方の理由で書き換えると、公開ベースを取り込むたびに、どちらの変更を残すかをその場で判断することになります。境界を先に決めておくのは、この判断を毎回発生させないためです。

土台は当てるだけで、書き換えない

土台の導入は、公開ベースに含まれる scripts/apply-to-repo.sh を対象リポジトリで実行するだけです。ルール・スキル定義・フック・ツールが一式展開され、本リポジトリもこの方法で土台を得ています。適用の実行例や、次回の差分判定の基準点になる状態ファイルの扱いは、既刊『Claude Code 自律運用ハンドブック』が手順書として扱っているため、この連載では繰り返しません。

当てたあとの約束は 2 つだけです。

  • 公開ベースの管理下にあるファイルは直接書き換えない
  • 独自のルールは docs/rules/ に新しいファイルとして足す

2 つ目が効くのは、公開ベースに存在しないファイルはそもそも同期の対象に入らないからです。本リポジトリでは、Qiita・Zenn・X の投稿上限を docs/rules/posting-limits.md、Zenn のデプロイ頻度を docs/rules/zenn-deploy-rules.md という独立したファイルに持たせています。公開ベース由来のルールに「Qiita は 1 日 2 本まで」と 1 行書き足しても動きはしますが、その 1 行は、公開ベースが同じファイルを更新するたびに衝突の候補になります。

境界の台帳は modules.yaml が持つ

どのファイルが公開ベース由来かは、リポジトリ直下の modules.yaml が台帳として持っています。公開ベースは「全部入りで配り、要らないモジュールを外す」方式で、有効なモジュールごとにルール・スキル・フック・ツールの名前を列挙しています。そこで、modules.yaml に名前があるものは公開ベース由来、リポジトリにあって modules.yaml に無いものは自前で足したもの と読めます。

スキルで数えます。まず modules.yaml の各モジュールにある skills: 配下の項目を合算します。

$ awk '/^ *skills:/{f=1;next} /^ *[a-z_]+:/{f=0} f && /^ *- /{n++} END{print n+0}' modules.yaml
17

skills: の行で数え始め、次のキー(hooks: や次のモジュール名)で数えるのをやめるだけの awk です。続いて、リポジトリに実在するスキルの数です。

$ ls .claude/skills | wc -l
34

34 個のうち 17 個が台帳に載っていて、残る 17 個が台帳の上ではブログ層になります。台帳側の 17 個は apply-base・code-review・pr-review-watcher・weekly-retrospective・self-improvement-loop・discussion-review などで、名前を見ればブログと無関係なことが分かります。

この数え方は、時点を変えて同じ手順で比べられるのも利点です。本のもとになった第 3 章は 2026-09-18 に同じ方法で数えていて、当時は総数 33 個・ブログ層 16 個でした。10 日のあいだに総数が 1 個増え、台帳の登録数は 17 個のまま動いていないので、増えた 1 個は引き算の上ではブログ層の側に入ります。

ブログ層のスキル 17 個を役割で分ける

引き算で残った 17 個を役割で並べると、5 つの群になります。※ 印の 3 個については次の節で扱います。

群 スキル 個数
パイプライン本体 write-article / collect-news / generate-draft / verify-draft / publish-draft / quality-review 6
スケジュール実行 hourly-dispatch 1
速報・即時化 fast-article 1
画像・分析 generate-article-images / analyze-trends / typesafe-ai ※ 3
監査・note レーン skill-inventory-audit / governance-review / audit-runner ※ / interactive-guide ※ / note-paid-dispatch / note-paid-article 6

パイプライン本体は、ニュースを集め(collect-news)、ドラフトを書き(generate-draft)、ファクトチェックをかけ(verify-draft)、公開の準備をする(publish-draft)一連の工程です。write-article はそれを 1 本の流れとして通す入口で、quality-review は公開したあとの品質と実績を振り返ります。hourly-dispatch は第 1 回で扱ったスロット表の持ち主で、fast-article は大きなリリースを即日で記事にする別経路です。監査・note レーンには、スキル全体の棚卸しやルール・フックの横断監査と、note の有料記事を書いて出す別レーンが入っています。

表を眺めると、記事の本文を生み出す工程はパイプライン本体と速報の 7 個で、残りは「いつ動かすか」「動いた結果をどう測るか」「仕組みそのものをどう監査するか」を受け持っています。ブログ層の半分以上が「書く」以外の仕事をしているという配分は、第 1 回の結論(機械に持たせたのは書くことより、止まる場所と気づく場所だった)と同じ形をしています。

引き算の答えは、自前で書いた数の上限でしかない

この回のために数え直していて、引き算だけでは境界が確定しないことに気づきました。

きっかけは、10 日で増えた 1 個の typesafe-ai です。ファイルの冒頭には、外部の公開リポジトリから MIT ライセンスで取り込んだことと、「本ベースでの活用方針」の正本が docs/jev-integration.md であることがコメントで書かれています。その docs/jev-integration.md は、自分自身を「本ベースおよび下流プロジェクト」でどう使うかの正本と名乗っています。自前のブログ層なら、こうした書き方にはなりません。

そこで GitHub 上の公開ベースの main(2026-09-28 時点)を確認すると、.claude/skills/ には typesafe-ai のほか、audit-runner と interactive-guide も同じ名前で入っていました。3 個とも公開ベースから届くスキルなのに、本リポジトリの modules.yaml には名前がありません。公開ベースの側でスキルが増えても、下流の台帳に名前が足されなければ、引き算はそれを自前の側に数えます。本の第 3 章が 2026-09-18 に数えた 16 個にも、このうち 2 個(audit-runner と interactive-guide)が含まれていました。

この 3 個を除くと、本リポジトリが自前で書いたスキルは 14 個になります。群ごとには、パイプライン本体 6・スケジュール実行 1・速報 1・画像と分析 2・監査と note レーン 4 です。

ルールも同じ手法で数えられますが、こちらは別の理由で引き算が合いません。

$ find docs/rules -maxdepth 1 -name '*.md' | wc -l
73
$ ls .claude/rules | wc -l
14

docs/rules/ 直下の Markdown が 73 本あり、そのうち全セッションに常に読み込ませる Hot 層(.claude/rules/ からの symlink)が 14 本、残りの 59 本がタスクに応じて読む Warm 層です。公開ベースのルールには「常駐用のサマリー+ -detail.md」の 2 ファイル構成があり、台帳にはサマリー側しか載っていません。対応するサマリーが台帳にある -detail.md は、登録が無くても公開ベース由来として扱う必要があります。

もう 1 つ、Hot か Warm かの区別は、公開ベース由来かブログ層かの区別と独立しています。公開ベース由来の core-principles.md も、ブログ層の posting-limits.md や datetime-jst-rules.md も、同じ Hot 層に常駐しています。投稿上限や日時の基準は、破ると取り返しがつかないか集計が壊れる規則なので、ブログ層でも毎セッション読ませています。「常に読ませるか」は由来ではなく、破ったときの被害の大きさで決めています。

ブログ層のディレクトリは 4 組

スキルやルールと違い、ディレクトリはおおむね物理的に分かれています。ブログ層が持つのは次の 4 組です。

  • articles/ と public/: articles/ が Zenn 形式の記事本体で、public/ はそこから変換した Qiita 形式です。編集するのは articles/ だけで、public/ は生成物として扱います。
  • research/ と drafts/: research/ がニュース収集の素材、drafts/ が執筆途中のドラフトです。
  • content/ と books/: content/ は分析・連載定義・企画レーンの作業領域で、サブディレクトリが 10 個あります(analytics/・audits/・books/・context/・discussions/・note-paid/・pipeline-state/・research/・series/・writing-plans/)。books/ は Zenn の本で、この連載のもとになっている本もここに入っています。本の企画や販売運用の資料は content/books/ に、読者に届く本文は books/ に分けています。
  • logs/: 公開と投稿の構造化ログ(JSONL)です。

「おおむね」と書いたのは、content/ が例外だからです。content/discussions/ と content/research/ は、公開ベース由来の議論型レビューや調査のスキルも出力先に使います。ディレクトリの単位では、content/ だけが 2 層の共有地になっています。

境界をまたぐ漏れは、出口で止める

2 層の境界をまたいで問題を起こしたものが 1 つあります。チャットの文体です。

本リポジトリでは、Claude Code のチャット応答にキャラクターの口調を設定しています。ところが同じセッションが、X の投稿文、Qiita のコメント返信、インフォグラフィックの描画テキストといった対外の文言も書きます。2026-09-08、記事告知のリプライがチャット用の語尾のまま X に実投稿されました。混入源は X 投稿文ビルダーの CTA(行動を促す一文)の定数配列 1 件で、その配列から文言を選ぶ決定論的なハッシュにより、URL を本投稿に置くパターンに割り当てた記事の 21%(310 本中 65 本)が汚染の対象でした。「対外には敬体で書く」という規範は文書にあっても、それを機械で強制する仕組みはありませんでした。

対策は二段です。1 段目は実行時のガードで、対外の文言を組み立てる収束点(X 投稿文ビルダー・Qiita コメント返信・描画テキストの組み立て)が共有ライブラリ scripts/lib/outbound-tone-guard.js を呼び、チャット専用の語尾を検出したら送信を止めます。

$ node scripts/lib/outbound-tone-guard.js --self-test
PASS 38 outbound-tone-guard tests

2 段目は push 時のソーススキャンで、ビルダーを通らずにハードコードされた文字列を拾います。scripts/ 配下の .js と .sh を全件走査し、除外するのはガード自身・セルフテストのブロック・コメント行だけです。「対外文言を持つファイルの一覧」を作って対象を絞る方式は採っていません。一覧は追記を忘れた瞬間に素通りになるためです。

$ npm run lint:outbound-tone
OUTBOUND_TONE OK(対外文言ソースにチャット専用レジスタの混入なし・差分スコープ)

ガードを書く位置を、文言を書く箇所ごとではなく、流れが合流する出口に置いたのが設計の要点です。書く側は今後も増えますが、出口の数はほとんど増えません。一方で、ライブラリの冒頭コメントには「守れるのは列挙済みの語彙だけ」という残余リスクも明記しています。チャットの口調が変われば、全パターンが同時に効かなくなります。未知の逸脱にあとから気づけるよう、投稿した本文そのものをログに残しています。

結論: 境界は台帳・由来・出口の 3 か所で引く

冒頭の問いに戻ります。共通の土台とブログ層の境界は、1 本の線ではなく、次の 3 か所で引いています。

1 つ目は台帳です。公開ベースを当て、管理下のファイルは書き換えず、独自のルールは新しいファイルとして足します。どれが公開ベース由来かは modules.yaml が持ち、スキルなら 34 − 17 = 17 という引き算でブログ層を数え分けられます。同じ手順を時点を変えて流せば、ブログ層が増えたことも検出できます。

2 つ目は由来です。この回のために数え直して分かったのは、台帳の引き算が返すのは「台帳に載っていないものの数」であって「自前で書いたものの数」ではない、ということでした。引き算で残った 17 個のうち 3 個は公開ベースにも入っていて、自前で書いたスキルは 14 個でした。台帳は増えたことを正しく検出しましたが、増えたものがどちらの更新に追随するかまでは教えてくれません。確定させるには、公開ベースに同じものがあるかを突き合わせるか、ファイル自身が名乗る由来を読む必要があります。

3 つ目は出口です。チャットの文体のように、土台側の設定とブログ層の成果物を同じセッションが扱う以上、境界をまたぐ漏れは構造的に起こります。その漏れは書く場所ごとではなく、対外へ出る収束点と push の時点で機械的に止めます。

振り返ると、境界を引く目的は、ファイルをきれいに分類することではありませんでした。公開ベースの更新を取り込むときに「どちらの変更を残すか」という判断を発生させないことが目的で、だから判定の基準も機能ではなく追随先になります。自分のリポジトリで同じ線を引くなら、最初の作業は台帳での引き算で、次にその結果を公開ベースの実物と一度だけ突き合わせることです。そうすれば、境界の線が思っているより内側に寄っていないかを確かめられます。

この記事と本の関係

この回は、Zenn 本『Claude Code で技術ブログを無人運用する』の第 3 章「土台を入れる」をもとに、スキルとルールの本数を 2026-09-28 に数え直して書き直したものです。第 3 章は無料章で、Zenn の本のページ から読めます。続きにあたるのは有料章で、第 4 章が記事の型を、第 16 章が秘密情報の扱いを扱います。本には、Claude Code に読ませると自分のリポジトリで同じ仕組みを組めるように書いた仕様パック(第 19 章)も入っています。

参照

本リポジトリ内のファイル(リポジトリは非公開のため、パスだけを示します):

  • modules.yaml: 公開ベース由来のモジュールとその資産の台帳
  • .claude/skills/: スキル定義(公開ベース由来とブログ層が同居する)
  • .claude/skills/typesafe-ai/SKILL.md: 冒頭コメントに取り込み元と活用方針の正本が書かれている
  • docs/rules/ / .claude/rules/: ルールの実体と、Hot 層への symlink
  • docs/rules/posting-limits.md / docs/rules/zenn-deploy-rules.md: ブログ層が新規ファイルとして足したルールの例
  • scripts/lib/outbound-tone-guard.js: 対外出力の文体ガード(実行時)
  • scripts/check-outbound-tone.js: 同じガードの push 時ソーススキャン(npm run lint:outbound-tone)

外部リポジトリ:

シリーズの前後の記事

仕組み全体を自分のリポジトリで組み直したい方は、無料章の続き(記事の型・品質ゲート・Qiita/Zenn/X の公開設計・無人実行・計測)を全 20 章の手順書として書いた Zenn Book(有料 500 円・試し読みあり)へどうぞ。

関連記事

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?