はじめに
mattpocock/skills の /improve-codebase-architecture は、設計レビューの結果を Markdown ではなく自己完結した HTML ファイルで返すという珍しい出力形式のスキルです。一時ディレクトリに architecture-review-<timestamp>.html を書き出し、ブラウザで開いて、Before/After の図を見ながら「どれを深掘りするか」を人間に選ばせます。
筆者は以前このリポジトリの全体像について書きましたが、個々のスキルの中身までは踏み込んでいませんでした。今回は手元のプラグイン(v1.2.0)同梱の SKILL.md と HTML-REPORT.md を読み、実際にレポートを生成して、HTML 出力という設計判断が何を狙い、どこで転ぶのかを確かめました。
背景 — ボール・オブ・マッドを作るのは、もう AI の方が速い
Matt Pocock 氏は README で、エージェント開発の失敗モードを 4 つ挙げています。その 4 番目が「We Built A Ball Of Mud」です。
Most apps built with agents are complex and hard to change. Because agents can radically speed up coding, they also accelerate software entropy.
コーディングが速くなるということは、エントロピーの増加も速くなるという指摘です。対策として README は Ousterhout の『A Philosophy of Software Design』を引き、「最良のモジュールは深い(deep)」という原則を置いています。
Matt 氏は「数日に一度」走らせることを勧めています。CI に組み込むものではなく、定期メンテナンスの位置づけです。
スキルの構造 — 3 ステップ
SKILL.md のフロントマターは次のようになっています。
---
name: improve-codebase-architecture
description: Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.
disable-model-invocation: true
---
disable-model-invocation: true が効いています。モデルが自発的にこのスキルを呼ぶことはありません。「設計を見直して」と会話で頼んでも起動せず、/improve-codebase-architecture と明示的に打つ必要があります。数日に一度の重い棚卸しを、エージェントの気まぐれで走らせないための設計です。
ステップ1: Explore(スコープを絞ってから見る)
SKILL.md は、探索の前に YAGNI でスコープを決めろと指示します。ユーザーの指定がなければ git log --oneline でコミット履歴を遡り、繰り返し出てくるホットスポットを優先します。深いモジュールへの作り替えは「今後その部分を変更しやすくする」ことで回収する投資なので、最近変更されていない場所を深くしても回収できない、という理屈です。
そのうえで Agent ツールの subagent_type=Explore でコードベースを歩かせます。判定の要が deletion test です。
Imagine deleting the module. If complexity vanishes, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
そのモジュールを消して複雑さが消えるなら、単なる素通し(shallow)です。消したぶんの複雑さが呼び出し側 N か所に再出現するなら、そのモジュールは働いていたことになります。このフィルタがあるおかげで、一般論のリファクタ案が混ざりにくくなっています。
ステップ2: HTML レポートを書き出す
出力先は明確に規定されています。$TMPDIR(なければ /tmp、Windows なら %TEMP%)配下に architecture-review-<timestamp>.html を書き、リポジトリには何も残さず、OS ごとのコマンド(xdg-open / open / start)で開いて絶対パスを伝える、という手順です。
実際に走らせて出力されたレポートは下記イメージです。走らせるだけで自動生成されブラウザで閲覧できるようになります。
そして「まだインターフェースの提案はするな(Do NOT propose interfaces yet)」と釘を刺したうえで、「どれを深掘りしますか?」と問うところで止まります。
ステップ3: grilling ループ
候補を 1 つ選ぶと /grilling スキルに引き渡されます。本体は短く、要点は 2 つです。
- 質問は 1 つずつ、答えを待ってから次へ
- 事実は環境を調べてエージェント側で埋め、決定だけを人間に聞く
決定が固まる過程で CONTEXT.md や ADR を更新する副作用も、この段で走ります。
HTML レポートの規約
HTML-REPORT.md には、スキャフォールドからトーンまで細かい規約が書かれています。骨格はこれだけです。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Architecture review — {{repo name}}</title>
<script src="https://cdn.tailwindcss.com"></script>
<script type="module">
import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs";
mermaid.initialize({ startOnLoad: true, theme: "neutral", securityLevel: "loose" });
</script>
</head>
<body class="bg-stone-50 text-slate-900 font-sans">
<main class="max-w-5xl mx-auto px-6 py-12 space-y-12">
<header>...</header>
<section id="candidates" class="space-y-10">...</section>
<section id="top-recommendation">...</section>
</main>
</body>
</html>
外部依存は Tailwind CDN と Mermaid の ESM インポートだけで、アプリコードは一切書かないと明記されています。候補 1 件は 1 つの <article> で、次の要素を持ちます。
| 要素 | 内容 |
|---|---|
| Title / Badge | 深化の名前+推奨度(Strong / Worth exploring / Speculative)と依存カテゴリ |
| Files | 対象ファイルの等幅リスト |
| Before / After | 2 カラムの図。カードの主役 |
| Problem / Solution / Wins | 各 1 文と、6 語以内の箇条書き |
面白いのは「説明の段落を書くな。図を理解するのに段落が要るなら、図を描き直せ」という指示です。説明責任を文章量ではなく図に負わせる方向に、はっきり振っています。
依存カテゴリのバッジは codebase-design の DEEPENING.md にある 4 分類 — in-process(純粋計算)、local-substitutable(PGLite のようなローカル代替がある)、ports & adapters(自前のリモート。本番は HTTP、テストはインメモリ)、mock(third-party)— がそのまま使われます。
語彙を固定するという手法
HTML-REPORT.md で筆者がいちばん感心したのは、使ってはいけない語のリストが書かれていることです。
Use exactly: module, interface, implementation, depth, deep, shallow, seam, adapter, leverage, locality.
Never substitute: component, service, unit (for module) · API, signature (for interface) · boundary (for seam) …
さらに Wins の文言についても「locality: bugs concentrate in one module」のように語彙で書けと指示し、「easier to maintain」「cleaner code」はその語彙にないから書くなと切っています。
LLM は放っておくと類義語を撒き散らします。「モジュール」「コンポーネント」「サービス」を同じ意味で混ぜられると、レポートを何度走らせても差分が読めません。禁止語リストは、その揺れを潰す実用的な手当てです。
ハマりどころ
ここからは、レポートを実際にブラウザで開いて分かったことです。
1. CDN 依存なので、閉じたネットワークでは崩れる
スキャフォールドは Tailwind と Mermaid を CDN から引きます。オフラインや、外部 CDN を塞いだ環境で開くと、レポートは素の HTML として崩れて表示されます。筆者の検証環境で Chromium のコンソールを見たところ、次のエラーが出ていました。
FAILED: https://cdn.tailwindcss.com/ net::ERR_TUNNEL_CONNECTION_FAILED
FAILED: https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs net::ERR_TUNNEL_CONNECTION_FAILED
この状態では <pre class="mermaid"> は SVG に変換されず、図の文字列がそのまま出ます。社内ネットワークで使うなら、生成後にアセットをローカルへ落として書き換える手当てが要ります。
npm i mermaid @tailwindcss/browser
mkdir -p /tmp/vendor
cp node_modules/@tailwindcss/browser/dist/index.global.js /tmp/vendor/tailwind.js
cp -r node_modules/mermaid/dist /tmp/vendor/mermaid
ただし、ローカルへ落とした場合はもう一段の注意が必要です。相対パスに書き換えて file:// のまま開くと、今度は ES モジュールの読み込みが CORS で弾かれます。筆者の計測では、この状態の SVG 生成数は 0 のままでした。簡易 HTTP サーバ越しに開けば解決し、Before / After の 2 図とも SVG に描画されることを確認できました。
cd /tmp && python3 -m http.server 8899
# → http://localhost:8899/architecture-review-<timestamp>.html
CDN 版が file:// でも描画できるのは、jsDelivr が Access-Control-Allow-Origin: * を返しており、origin が null のページからでも読み込めるためです。ローカルへ落とした瞬間にこの前提が外れます。
なお、スキャフォールドが指定する cdn.tailwindcss.com は Tailwind v3 系の Play CDN です。現在の公式ドキュメントは @tailwindcss/browser@4 を案内しており、v4 系に置き換わっています。レポートが使うのは bg-stone-50 などの素直なユーティリティばかりなので実害は出にくいものの、両者は別物です。
2. Mermaid の neutral テーマと、After カードの濃色背景が噛み合わない
HTML-REPORT.md は After 側の「深いモジュール」を厚い枠と濃色(.deep クラスは #0f172a 系のグラデーション)で表現するよう勧めています。一方 Mermaid は theme: "neutral" で初期化されるため、ノードは明るいグレーで描かれます。濃色カードの中に明るい図が乗ると、図全体が白い板として浮きます。
同じ理由で、「図の高さは 320px 程度に揃える」という指示も、Mermaid が中身に応じて高さを自動決定するため素直には効きません。揃えたい場合は、After 側だけ手書きの div と SVG に切り替えるのが現実的でした。HTML-REPORT.md 自身も「Mermaid のレイアウトと喧嘩するなら手書きに逃げろ」と勧めています。
3. レポートは temp に出るので、残したいなら手動で退避する
「リポジトリを汚さない」は利点ですが、裏返すとレビュー結果はセッションをまたいで残らないということです。チームに共有したい、前回のレポートと差分を見たいなら、生成された HTML を別の場所へ手動でコピーしておく必要があります。
まとめ
-
/improve-codebase-architectureは、設計レビューを HTML レポートとして返し、そこで一旦止まって人間に選ばせる構造になっています - 探索の前に
git logでホットスポットへスコープを絞る点、deletion test で素通しモジュールを判定する点が、一般論の羅列を防いでいます -
HTML-REPORT.mdの禁止語リストは、LLM の語彙の揺れを潰す手当てとして、他のスキルにも転用できる考え方です - 実運用では CDN 依存が最大のハマりどころです。閉域網ならアセットの vendoring と、その場合に必要になるローカル HTTP サーバまでセットで用意してください
-
disable-model-invocation: trueなので、会話の流れでは起動しません。数日に一度、明示的に打つ運用が前提です
出力を HTML に振ったことで、「浅い/深い」を面積で見せられるようになっています。テキストで「このモジュールは shallow です」と言われるより、図で 4 箱が 1 箱に畳まれるのを見る方が判断が速い、というのは実際に開いてみて納得した部分でした。
参考
- mattpocock/skills — GitHub
- improve-codebase-architecture/SKILL.md — GitHub
- improve-codebase-architecture/HTML-REPORT.md — GitHub
- The /improve-codebase-architecture Skill — AI Hero (Matt Pocock)
- Claude Code Plugins — 公式ドキュメント
- Mermaid — 公式ドキュメント
- Tailwind CSS Play CDN — 公式ドキュメント
- John Ousterhout『A Philosophy of Software Design, 2nd Edition』
- Michael Feathers『Working Effectively with Legacy Code』(seam の出典)
