1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code を編集長にして Qiita 記事生成パイプラインを作る

1
Posted at

この記事では、Claude Code を編集長として進行・品質判断に使い、llm-task-router を実行レイヤーとして組み合わせることで、Qiita 記事の生成パイプラインを自分の環境で回す手順をまとめます。
読むと、テーマ出しから本文生成、評価、修正、書き出しまでの流れを、VSCode と Node/CLI に抵抗のない中級エンジニア向けの前提で組み立てやすくなります。
理由の詳細や設計上の分担は、後の「なぜ Claude Code 単体ではなく llm-task-router を使うのか」で説明します。

llm-task-router は、タスクごとに最適なモデルへ振り分けて、記事の生成・評価・修正・書き出しを行う薄い ModelRouter CLI です。

前提はシンプルで、本文を最初から手書きしない ことです。
人間はテーマ、ブリーフ、出力ルール、品質基準を与え、本文は 生成 → 評価 → 修正 の流れで仕上げます。

以降では llm-task-router コマンドを使って進めます。インストール手順は後述のセットアップで示します。
また、/draft-topic/write-articlearticle-editor-in-chief などのスキル名・サブエージェント名は llm-task-router init が生成する .claude/ に依存するため、読者環境で同名が無い場合があります。

なぜ Claude Code 単体ではなく llm-task-router を使うのか

Claude Code 単体でも、記事生成の流れ自体はかなり進められます。
ただ、継続運用を始めると、用途ごとに生成モデルを分けたい / レビュー担当を別モデルにしたい / profile ごとに出力作法を固定したい / 実行履歴を run 単位で残したい といった要件が出やすいです。
llm-task-router は、そのあたりを整理して扱うための実行レイヤーとして使えます。
Claude Code に進行管理を任せつつ、実処理は CLI と設定ファイルに寄せる、という分担です。


まず全体像: 3 層で考える

役割分担は次の 3 層で見ると把握しやすいです。

Claude Code は進行管理と品質判断を担う

Claude Code は記事作成の司令塔です。/write-article の進行役となる編集長エージェントが article-editor-in-chief です。

  • テーマからブリーフを起こす
  • 本文生成の開始を指示する
  • 評価結果を見て修正に回す
  • 必要に応じて事実確認や検証を挟む
  • 最後に GO/NO-GO の推奨判断を出す

編集長エージェントは進行と品質判断を担いますが、最終判断(公開してよいか)と承認はユーザーが行います

llm-task-router は薄い実行層として動く

llm-task-router は、task ごとに適切なモデルや処理へ振り分ける CLI です。

  • article:create: ブリーフから構成と下書きを生成
  • article:import: 既存 Markdown を run に取り込む
  • article:evaluate: 本文を審査
  • article:revise: 修正指示を反映
  • article:refine: article:evaluate → article:revise を自動ループ
  • article:export: 出力先の作法に合わせて書き出し

設定ファイルがモデル選択と出力作法を担う

主に見るのは次の 2 つです。

  • config/models.yaml
  • config/profiles/

Qiita 向けなら profile 側で、たとえば次を表現します。

  • Markdown で出力する
  • コードブロックは言語指定つきフェンスにする
  • :::note info / :::note warn を使ってよい
  • front-matter は本文に含めない

実際の profile は、たとえば次のような形です。

# config/profiles/qiita.yaml
platform: Qiita
language: ja
criteria_file: config/criteria/default.md
style: |
  Qiita の作法に従う。本文は Markdown。
  - コードブロックは言語指定つきのフェンスを使う。
  - 補足や注意は `:::note info` / `:::note warn` の記法を使ってよい。
  - 記事先頭の front-matter は本文に含めない。

platform は生成プロンプトに使うラベル、style は draft / final / revise の本文生成に注入される作法として読むと分かりやすいです。


セットアップ: 作業フォルダーで初期化する

まず作業フォルダーを作って移動します。

mkdir qiita-article-pipeline
cd qiita-article-pipeline

llm-task-router をインストールする

前提として、Node.js と npm が使える環境を用意しておきます。

グローバルインストールは次の通りです。

npm install -g @rex0220/llm-task-router

インストール後は llm-task-router コマンドが使えるようになります。動作確認として、次を実行してバージョンが表示されることを確認します。

llm-task-router --version

執筆時点では 0.2.8 が表示されます。利用できるサブコマンド一覧は llm-task-router --help(必要に応じて各サブコマンドの --help)で手元の CLI を確認するのが確実です。ソースや背景情報は公開リポジトリも参照できます。
https://github.com/rex0220/llm-task-router

必要なら、グローバルインストールの代わりに npx @rex0220/llm-task-router <command> でも実行できます。

続いて llm-task-router を初期化します。

llm-task-router init

執筆時点では、たとえば次のような土台が生成されます。

.
├── .claude/        # Claude Code 用の編集長セット(スキル・サブエージェント定義)
├── config/         # models.yaml / profiles/ などの設定
├── .env.example
└── CLAUDE.md        # 作業の原則

topics/runs/ は init では作られず、トピックを起案したり記事生成を回す中で作られます。

ここで重要なのは、init が単に設定ディレクトリを作るだけではないことです。
Claude Code 用の編集長セット として .claude/CLAUDE.md も生成されるので、以後のワークフローをそのまま始めやすくなります。

.env.example.env にコピーする

次に API キーを設定します。

cp .env.example .env

.env を開いて、少なくとも次を埋めます。

OPENAI_API_KEY_ARTICLE=your_openai_api_key
ANTHROPIC_API_KEY_ARTICLE=your_anthropic_api_key

これらは本ツールが実際に使う環境変数名です。
キー名は、後述する config/models.yamlproviders.*.api_key_env と対応します。
.env のキー名と config/models.yamlproviders.*.api_key_env は完全に一致させる必要があります。

本文生成系(draft / rewrite)と審査系(final_review)を別系統、できれば別プロバイダに分けると、同じモデルが自分の出力を甘く採点する自己採点バイアスを下げる狙いを持たせやすいです。
ただし、この効果の大きさはテーマや運用条件によって変わりうるため、定量的には環境ごとの確認が必要です。

.env には機密情報が入るため、コミットしないでください。.gitignore に含まれているかも確認しておくと安全です。

VSCode で Claude Code を開く

VSCode では、この作業フォルダー自体をルート として開くのが分かりやすいです。
Claude Code 拡張を開いたら、まず CLAUDE.md を見ておくと後で詰まりにくくなります。

CLAUDE.md には、たとえば次のような作業原則がまとまっています。

  • 直接触ってよいファイルと触らないファイル
  • 修正指示の戻し方
  • 公開相当の書き出し条件
  • 品質判断の流れ

Claude Code 上の最短ワークフロー

まずは次の 2 つを Claude Code のチャット入力欄で使うだけです。

/draft-topic <テーマ>
/write-article

この 2 コマンドで、ブリーフ起こし → 本文生成 → 編集長の GO/NO-GO 推奨判断 まで進められます。
その後、ユーザーが内容を確認して承認したら article:export を実行して書き出します。

ここで出てくる /draft-topic/write-article は、ターミナルで実行するシェルコマンドではなく、Claude Code のチャット入力欄に打ち込んで送信するスラッシュコマンド です。
一方で、後で出てくる llm-task-router article:createarticle:export は、ターミナルで実行する CLI コマンド です。似た名前でも入力する場所が違うので、先に区別しておくと混乱しにくいです。

1. /draft-topic <テーマ> でブリーフを起こす

まずは本文ではなく企画書を作ります。Claude Code のチャット入力欄に、たとえば次のように入れて送信します。

/draft-topic llm-task-router と Claude Code で Qiita 記事生成パイプラインを組む方法

ここでやりたいのは、topics/llm-task-router-with-claude-code.txt のような brief を起こすことです。

大事なのは、いきなり本文を書かせない ことです。
先に brief を見て、

  • 何を書くか
  • 誰向けか
  • ゴールは何か
  • どこまで扱うか

をレビューしてから次に進みます。

2. /write-article で本文生成から推奨判断まで進める

ブリーフを承認したら、Claude Code のチャット入力欄に次を入れて送信します。

/write-article

この段階で、編集長役のエージェントが

  • 本文生成
  • 評価
  • 必要に応じた修正
  • 必要に応じた事実確認や検証
  • GO/NO-GO の推奨判断

を進めます。

見た目は 1 コマンドでも、内部では生成と審査を行き来しながら仕上げていく流れです。
公開してよいかの最終判断はユーザーが行います。
細かい CLI の対応や内部 task は、後半で説明します。

3. 推奨判断のあと、ユーザー承認後に article:export で書き出す

編集長エージェントが GO/NO-GO の推奨判断を出したあと、ユーザーが内容を確認して承認したら書き出します。

書き出しは Claude Code のチャットではなく、シェルで CLI コマンドとして 実行します。

llm-task-router article:export \
  --run <runId> \
  --out out/llm-task-router-with-claude-code.md

これで、Qiita 向けの最終 Markdown を出力して完成です。


用語整理

ここまでで runprofilebriefrefine などの語が出てきたので、ここで一度整理しておきます。

  • brief
    topics/<slug>.txt に置く企画書
  • profile
    出力先の作法。Qiita なら Qiita 向け Markdown ルール
  • run
    1 回の記事生成の作業単位
  • runId
    run を識別する ID。成果物は runs/<runId>/ に集約される
  • slug
    トピックや出力名に使う識別子。topics/ 配下のファイル名に使う識別子で、ここでは手動で llm-task-router-with-claude-code のように決める
  • refine
    article:evaluate → article:revise を回す磨き込みループ

ここから先は、中で何が起きているかさらに細かく調整したいときにどこを見るか の話です。
普段は前半の最短ワークフローだけでも回せますが、挙動を理解したいときや詰まりどころを調整したいときに後半が役立ちます。

スラッシュコマンドと CLI の対応

名前が多いので、ここは対応を固定して覚えると混乱しにくいです。

Claude Code 上の操作 役割 対応する CLI
/draft-topic <theme> テーマから brief 案を作る topics/<slug>.txt を準備
/write-article 記事生成フロー全体を進行する article:create → article:refine → (ユーザー承認後)article:export

左側のスラッシュコマンドは Claude Code のチャットに入力し、右側の article:* はシェルで実行する CLI です。表は「似た役割だが実行場所が異なる」対応として読むと分かりやすいです。

/write-article を 1 コマンドで見せていても、内部では複数の CLI を順に使っています。流れを 1 か所にまとめると、次の通りです。

  1. article:create
  2. article:refine(内部で前述の「生成 → 評価 → 修正」を反復)
  3. 編集長による GO/NO-GO の推奨判断
  4. ユーザーの最終判断と承認
  5. article:export

CLI コマンド / 内部 task / models.yaml の対応

CLI と内部 task の対応は、次の 1 表にまとめておくと追いやすいです。

CLIコマンド 役割 内部task config/models.yaml のキー
article:create brief から構成と本文生成を開始する複合コマンド outlinedraft_markdown outline, draft_markdown
article:import 既存 Markdown を run に取り込む入口(取り込んだ本文が final.md になる) なし なし
article:evaluate 現在の本文を審査する final_review final_review
article:revise 修正指示を本文へ反映する rewrite rewrite
article:refine 審査と修正を自動反復する final_review, rewrite final_review, rewrite
article:export profile に沿って最終書き出しする なし 主に config/profiles/

article:create は、現行実装では outlinedraft_markdown を順に実行する複合コマンド です。内部の組み立ては今後変わる可能性があります。
一方で article:import は、すでにある Markdown 本文を起点に run へ取り込む入口です。取り込み後は article:evaluate / article:refine / article:revise で同じ磨き込みパイプラインに乗せられます。
また article:export は、執筆時点では profile に沿った決定論的な機械整形で、LLM 呼び出しは行いませんmarkdown_formattitle_suggestions のような LLM 利用タスクは export とは別物で、整形やタイトル候補が必要なときに別途使う補助タスクです。

対応表にあるのは主線の task です。models.yaml にはこれ以外の task も定義されますが、本記事の主フローで中心となるのは outline / draft_markdown / final_review / rewrite です。
たとえば article_brief/draft-topic の brief 起こし相当で使われ、technical_review は draft 段階の審査、final_review は最終本文の審査です。markdown_format / title_suggestions は整形やタイトル候補生成などの補助タスクで、上記の主線とは別に必要に応じて使われます。


CLI を直接たたく基本フロー

Claude Code から回す前に、CLI 単体の流れを知っておくと挙動を理解しやすくなります。

# brief から記事生成を開始
llm-task-router article:create \
  --topic-file topics/llm-task-router-with-claude-code.txt \
  --profile qiita
# => runId が標準出力に出る

# 審査
llm-task-router article:evaluate \
  --run <runId>

# 自動磨き込み
llm-task-router article:refine \
  --run <runId> \
  --max-rounds 3 \
  --until clean

# 個別修正が必要なときだけ明示的に反映
llm-task-router article:revise \
  --run <runId> \
  --instruction-file instructions/revise-01.md

# 公開相当の形式で書き出し
llm-task-router article:export \
  --run <runId> \
  --out out/llm-task-router-with-claude-code.md

runIdarticle:create 実行時に標準出力から確認します。現行実装では日付ベースの命名例を見かけますが、その形式が固定仕様という前提では見ない ほうが安全です。

主線は article:create → article:refine → (ユーザー承認後)article:export です。
article:reviserefine の自動修正とは別に、個別の修正指示を手で当てたいときに使う選択肢です。

article:create

article:create --topic-file topics/<slug>.txt --profile qiita は生成の入口です。
brief を受けて、構成と下書きを段階的に作ります。

article:evaluate

article:evaluate --run <runId> は現在の本文を審査します。
重大な問題だけを見るか、軽微な改善提案まで含めるかを調整できます。

article:refine

article:refine --run <runId> は、前述の「生成 → 評価 → 修正」を CLI レベルで見ると、article:evaluate → article:revise を自動で回すコマンドです。
人間が毎回コピペで修正指示を戻さなくても、一定回数まで磨き込みを進められます。

article:revise

article:revise --run <runId> --instruction-file <path> は、明示した修正指示を本文へ反映するコマンドです。

article:export

article:export --run <runId> --out <path> は、Qiita profile に沿って最終成果物を書き出します。
ここは LLM に文章を再生成させる段階ではなく、公開先向けに整える機械整形 と考えると分かりやすいです。

article:import(既存記事を取り込んで磨き直す)

article:import は、すでにある Markdown 記事を run に取り込んで、article:evaluate / article:refine / article:revise で磨き直すためのコマンドです。取り込んだ Markdown がその run の final.md になります。

使いどころは、パイプラインの外で手書きした記事や別ツールで作った記事を、後からこのパイプラインに乗せたいときです。過去に article:export で書き出した記事を、再び run に戻して改稿する、という往復もできます。

llm-task-router article:import \
  --from export/2026-06-18-llm-task-router-with-claude-code.md \
  --run 2026-06-19-llm-task-router-with-claude-code-v028 \
  --topic-file topics/llm-task-router-with-claude-code.txt \
  --profile qiita

最低限見ることが多いのは、取り込む Markdown を指定する --from、run id を与える --run、profile を選ぶ --profile です。トピックを明示したいときは --topic / --topic-file も指定できます。--run を省略した場合はファイル名から導出され、--profile の既定値は qiita です。


runs/<runId>/ の成果物を読む

成果物が runs/<runId>/ にまとまるのが、この方式の扱いやすいところです。

runs/<runId>/
├── brief.json
├── outline.json
├── draft.md
├── review.json
├── final.md
├── final.bak.md
├── final-review.json
├── final-review.md
├── refine-r1-review.json
├── refine-r1-instruction.md
├── refine-r2-review.json
└── refine-r2-instruction.md

段階ごとの見方は次の通りです。

  • review.json
    draft 段階の審査結果
  • final-review.json / final-review.md
    最終本文に対する審査結果
  • refine-r*-*
    refine 各ラウンドの審査と修正指示の痕跡

この構成にしておくと、

  • どの段階で品質が崩れたか確認する
  • run 単位で作り直す
  • 修正前後の差分を見る
  • モデル設定を変えて比較する

といった運用がしやすくなります。


config/models.yaml の見どころ

実務上の調整ポイントはかなり config/models.yaml に集まります。
プロバイダと API キー環境変数の対応も、このファイルの providers: セクションで持ちます。

代表例としては次のようになります。

providers:
  openai:
    api_key_env: OPENAI_API_KEY_ARTICLE
  anthropic:
    api_key_env: ANTHROPIC_API_KEY_ARTICLE

tasks:
  outline:
    primary:
      provider: anthropic
      model: claude-opus-4-8
    fallback:
      - provider: anthropic
        model: claude-sonnet-4-6
      - provider: openai
        model: gpt-5.4-mini

  draft_markdown:
    primary:
      provider: openai
      model: gpt-5.4
    fallback:
      - provider: anthropic
        model: claude-sonnet-4-6

  final_review:
    primary:
      provider: anthropic
      model: claude-opus-4-8
    fallback:
      - provider: anthropic
        model: claude-sonnet-4-6
      - provider: openai
        model: gpt-5.4-mini

実際には各タスクで max_tokenstimeout_ms なども調整できます。

本文系と審査系を別プロバイダに置くなら、draft_markdownfinal_review の割り当てを見比べると意図がつかみやすいです。
全タスクは llm-task-router init で生成された手元の config/models.yaml に揃っているので、詳細はそちらを見るのが確実です。

生成と審査を別系統に置く設計は、品質の絶対保証というより、レビューの偏りを抑えるための実務的な工夫として捉えると分かりやすいです。

モデル ID や単価は、価格改定やモデル更新でドリフトします。利用時点の公式ドキュメントやダッシュボードで必ず確認してください。

調整の観点

このファイルで調整するのは「どのモデルを使うか」だけではありません。

  • 生成品質
  • 応答速度
  • コスト
  • タイムアウトしやすさ
  • fallback の効き方

まで含めて変わります。

outlinemax_tokens を厚めにする理由

outline は構成 JSON を返すことが多く、ここが途中で切れると後段の検証に失敗しやすくなります。
そのため、max_tokens はやや厚め、たとえば 8000 くらいを確保しておくと安定しやすいです。

timeout_ms はどう読むか

timeout_ms は、primary が長く返ってこないときに fallback へ切り替えるための上限時間です。
draft_markdownrewrite のような長い生成は厚め、technical_reviewfinal_review のような審査はやや短め、という調整が実用的です。


つまずきやすい点

API キー未設定

まず疑うべきは .env です。
OPENAI_API_KEY_ARTICLEANTHROPIC_API_KEY_ARTICLE が正しく入っているか確認します。

モデル ID 不一致

config/models.yaml に書いたモデル ID が、その時点の契約プランや利用条件と合わないことがあります。

profile の取り違え

Qiita 向けのつもりで別 profile を使うと、Markdown 作法や書き出し形式が噛み合わなくなります。

final.md を直接編集してしまう

これをやるとパイプライン外の変更になり、履歴の追跡や再現性が崩れます。
修正は article:revise --instruction-file 経由に寄せたほうが安全です。

外部 API 前提であることを忘れない

この CLI は外部 LLM API を呼ぶので、ネットワーク、課金、レート制限、プロバイダ障害、タイムアウトの影響を受けます。
ローカルスクリプトのような一定の安定性を前提にしすぎないほうが運用しやすいです。


仕上げに外部の LLM レビューを挟む

このパイプラインには article:evaluate / article:refine があり、本文系と審査系を別プロバイダに置く工夫もできます。
ただし、どちらも同じツールチェーンの中で完結したレビューではあるので、視点の独立性という意味では限界があります。

そこで公開前に、出来上がった final.md を ChatGPT や Gemini など別の LLM にそのまま貼ってレビューしてもらうと、第三者的な視点を補いやすくなります。たとえば次のような点は拾われやすいです。

  • 構成や見出し順、読者目線での分かりやすさ
  • 誤解を招きやすい表現(例: 誰が最終判断するのか)
  • タイトルの強さや差別化
  • 抜け漏れ(例: なぜこの構成なのかの説明不足)

指摘を反映するときは、final.md を直接手で直すより、llm-task-router article:revise --instruction-file 経由に寄せるほうが扱いやすいです。
runs/ に履歴が残り、final.bak.md も保持されるため、内部の article:refine による自動磨き込みと、外部レビューを人手で取捨選択して article:revise に渡す流れを併用しやすくなります。

外部 LLM の指摘は常に正しいとは限りません。たとえば実在するモデル ID を「架空だ」と誤って指摘することもあります。
指摘は鵜呑みにせず、事実やこの記事の前提である brief と照らしながら、反映するものを選ぶのが無難です。

まとめ

最短で回すなら、次の 4 ステップです。

  1. /draft-topic で brief を作る
  2. brief をレビューする
  3. /write-article で生成とレビューを回し、編集長の推奨判断を受ける
  4. ユーザー承認後に article:export で書き出す

運用しながら必要になったら runs/<runId>/config/models.yaml を調整すれば十分です。

1
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?