Use Cases (更新: 2026/6/6)

技術的負債は「大掃除」だと失敗する。Claude Codeで小さく返す型

技術的負債をClaude Codeで棚卸し→ICE/RICEで優先順位→300行のPRで安全に返す型。コピペで動くスキャナと、僕がやらかした失敗込みで紹介。

技術的負債は「大掃除」だと失敗する。Claude Codeで小さく返す型

「来月こそ技術的負債を返そう」。僕はこのセリフを、たぶん2年は言い続けました。

返せたためしはありません。スプリントが始まれば新機能に押し流され、気づけば any と落ちるテストと、誰も意味を覚えていない TODO がまた増えている。負債は「いつかまとめて」と言った瞬間に、ほぼ確実に失敗します。

転機は、返し方を「大掃除」から「毎週ちょっとずつ」に変えたことでした。そしてその地味なループの相棒が、Claude Codeです。

この記事の要点

  • 技術的負債は一括リファクタで返そうとすると、差分が巨大になりレビューされず、リリース直前に戻される。小さく返すループにするのが正解。
  • Claude Codeの本当の強みは「魔法で直す」ことではなく、負債を棚卸しし、根拠を付け、レビューできる小さなPRに分解すること。
  • 優先順位は感覚ではなく ICE/RICE でそろえる。ただしスコアは正解ではなく、チームの会話をそろえる道具。
  • 機械で拾える負債(巨大ファイル・TODOany)はスキャナに任せ、設計の歪みだけ人間とAIで議論する。
  • 返済PRは 300行以内を目安に。flaky test(時々失敗する不安定なテスト)とセキュリティ依存は優先度を一段上げる。

この記事では、僕が小規模プロジェクトで実際に回している返済ループを、コピペで試せるプロンプトとNode.jsスクリプト付きでまとめます。Claude Codeのリファクタリングやテストの基本は公式の Common workflows、プロジェクト知識の残し方は Memory、安全な運用設定は Settings を合わせて見てください。社内ルールを CLAUDE.md に残すコツは CLAUDE.mdベストプラクティス、テスト設計は Claude Codeテスト戦略、権限の絞り方は 承認とサンドボックスの設計 が参考になります。

なぜ「一括リファクタ」はだいたい失敗するのか

僕が最初にやった失敗は、3週間こもって「全部きれいにする」巨大ブランチを作ったことです。

差分は8,000行を超えました。レビュー担当は1ページ見て「これ、挙動変わってないって誰が保証するの?」と固まり、結局そのブランチはマージされないまま腐りました。3週間が消えました。

負債返済が失敗するパターンは、だいたいこの4つに集約されます。

  • 差分が大きすぎて誰もレビューできない(挙動が同じか追えない)
  • テスト範囲が曖昧で、直したつもりが別の箇所を壊す
  • 効果が見えないので、次のスプリントで誰もやらなくなる
  • 権限を絞っていないので、AIが親切心で関係ないファイルまで「整理」する

だから僕は、返済を一発のイベントではなく、回り続ける短いループとして設計し直しました。図にするとこうです。

flowchart LR
  A["棚卸し"] --> B["証拠を集める"]
  B --> C["ICE/RICEで優先順位"]
  C --> D["小さなPRに分割"]
  D --> E["テストとレビュー"]
  E --> F["負債台帳を更新"]
  F --> A

ここでいう棚卸しは、「なんかこのファイル臭うよね」と感覚で語ることではありません。ファイル行数、TODO/FIXMEany、重複ロジック、依存の古さ、flaky test など、あとから議論できる証拠を集める作業です。感覚は人によってブレますが、行数は誰が見ても同じ数字です。

進め方ごとの向き不向きを、僕の感覚で表にするとこうなります。

進め方向いている場面危険な点Claude Codeでの使い方
大規模一括リファクタフレームワーク移行など境界が明確な時差分が巨大でレビュー不能事前調査と移行計画だけ任せる
小さな返済PR日常的な負債削減効果が見えにくい台帳・スコア・PRチェックリストで可視化
依存関係更新スプリントセキュリティ更新やEOL対応破壊的変更を見落とすchangelog確認とテスト範囲の洗い出し
テスト安定化CIが信用されていない時原因を見ずリトライで隠す失敗ログの分類と再現手順の作成

僕が常用するのは2行目です。1行目は移行のような「やると決まっている」時だけ。残りは状況に応じて差し込みます。

まず棚卸し:直さず、証拠だけ集めさせる

最初のコツは1つだけ。Claude Codeに「まだファイルを変更するな」と明言することです。

これを言わないと、AIは調査のついでに直し始めます。直してくれるのはありがたい——と思いきや、根拠の薄い変更が混ざって、結局どれが妥当なのか分からなくなる。最初は調査・分類・仮説出しだけ任せ、優先順位は人間が決めます。

claude -p "
src/ と tests/ を読んで、技術的負債の棚卸しをしてください。
まだファイルは変更しないでください。

観点:
- 80行を超える関数
- 300行を超えるファイル
- 4段以上のネスト
- 重複している入力検証、日付処理、権限チェック
- TypeScript の any、as any、@ts-ignore
- TODO / FIXME / HACK コメント
- テストがない分岐、または名前だけのテスト

出力は docs/tech-debt/register.md に貼れる Markdown 表にしてください。
列は ID, File, Line, Debt type, Evidence, Risk, Suggested first PR, Confidence としてください。
"

返ってくるのは「直し」ではなく「地図」です。この地図を見て、どこから手を付けるかは人間が決める。役割分担をここでハッキリさせておくと、あとがラクになります。

依存関係の負債:件数ではなく「実害」で見る

依存関係も立派な負債です。古いライブラリ、メンテ停止、重大な脆弱性、同じ用途のライブラリの併用。

ここで僕がよくハマったのは、npm audit の件数に振り回されることでした。警告が47件と出ると焦って全部潰しにいく。でも実害の薄い深い依存の警告に半日使い、肝心のEOL直前の主要ライブラリを見逃す、という本末転倒をやりがちです。

なので分類を先にAIへ任せます。

claude -p "
package.json, lockfile, npm outdated, npm audit の結果を前提に、依存関係の負債を分類してください。

分類:
1. セキュリティ修正が必要
2. major update が必要だが破壊的変更が大きい
3. メンテナンス停止または代替推奨
4. 同じ用途のライブラリ重複
5. 今は保留でよいもの

各項目について、影響範囲、先に読むべき changelog、必要なテスト、最小PRの作り方を書いてください。
自動更新してよいものと、人間レビュー必須のものを分けてください。
"

依存更新は「ビルドが通ったからOK」ではありません。日付処理、認証、暗号、ビルドツール、ルーティングは、小さなAPI差分が本番障害に直結します。Claude Codeにはchangelogの要約と影響ファイルの候補出し、テストコマンドの整理をさせ、押すボタンは人間が押す。これを徹底します。

flaky test と重複ロジックを「返済候補」に変える

flaky test は、CIへの信頼をじわじわ削ります。「もう一回回せば通るやつ」と一度でも思われた瞬間、そのテストは安全装置をやめて、ただの邪魔者になります。

CIログやローカルの失敗履歴を渡して、分類させます。

claude -p "
直近20件の CI 失敗ログを読み、flaky test 候補を分類してください。

分類軸:
- 時刻、タイムゾーン、ランダム値に依存
- ネットワークまたは外部 API に依存
- テスト間で共有状態が漏れている
- 非同期処理の待ち方が不安定
- 実装バグの可能性が高く、flaky 扱いしてはいけない

各候補について、再現コマンド、最小修正案、追加すべきアサーションを書いてください。
"

最後の「実装バグの可能性が高く、flaky扱いしてはいけない」を入れておくのが大事です。これを外すと、AIは本物のバグまで「不安定なテストですね」と握りつぶそうとします。

重複ロジックも考え方は同じです。たとえば権限チェックが3箇所にコピペされているなら、最初のPRでは共通関数を作るだけ。置き換えは次以降のPRで1箇所ずつ。全部を一度に置き換えると、レビュー担当が「挙動が本当に同じか」を追えなくなります。

コピペで動く簡易スキャナ

AIの調査と並行して、機械的に拾える負債はスクリプトに任せます。毎週同じ基準で数えられるのが利点です。次のファイルを scripts/debt-scan.mjs として保存し、node scripts/debt-scan.mjs src で実行してください。

import fs from "node:fs";
import path from "node:path";

// 走査対象のディレクトリ(デフォルトは src)
const root = process.argv[2] || "src";
// 「巨大ファイル」とみなす行数のしきい値
const maxLines = Number(process.env.MAX_LINES || 300);
const extensions = new Set([".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"]);
const findings = [];

// ディレクトリを再帰的にたどる
function walk(dir) {
  if (!fs.existsSync(dir)) return;

  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
    const fullPath = path.join(dir, entry.name);

    if (entry.isDirectory()) {
      // 成果物や依存はスキップ
      if ([".git", "node_modules", "dist", "build", ".next", "coverage"].includes(entry.name)) continue;
      walk(fullPath);
      continue;
    }

    if (entry.isFile() && extensions.has(path.extname(entry.name))) {
      scanFile(fullPath);
    }
  }
}

function add(file, line, type, severity, detail) {
  findings.push({ file, line, type, severity, detail });
}

// 1ファイルを走査して負債の「匂い」を拾う
function scanFile(file) {
  const text = fs.readFileSync(file, "utf8");
  const lines = text.split(/\r?\n/);

  // 巨大ファイル
  if (lines.length > maxLines) {
    add(file, 1, "large-file", 3, `${lines.length} lines`);
  }

  lines.forEach((line, index) => {
    const lineNumber = index + 1;

    // TODO / FIXME / HACK コメント(FIXME・HACK は重め)
    if (/\b(FIXME|TODO|HACK)\b/i.test(line)) {
      add(file, lineNumber, "unsafe-comment", /FIXME|HACK/i.test(line) ? 4 : 3, line.trim());
    }

    // TypeScript の any 系(型の抜け穴)
    if (/\.(ts|tsx)$/.test(file) && /(:\s*any\b|as\s+any\b|<any>)/.test(line)) {
      add(file, lineNumber, "typescript-any", 4, line.trim());
    }
  });
}

walk(root);

// Markdown 表として出力(そのまま台帳に貼れる)
console.log("| file | line | type | severity | detail |");
console.log("| --- | ---: | --- | ---: | --- |");
for (const item of findings.sort((a, b) => b.severity - a.severity || a.file.localeCompare(b.file))) {
  const detail = item.detail.replaceAll("|", "\\|");
  console.log(`| ${item.file} | ${item.line} | ${item.type} | ${item.severity} | ${detail} |`);
}

if (findings.length === 0) {
  console.error("No obvious debt markers found.");
}

このスクリプトは万能ではありません。重複ロジックや設計の歪みは検出しきれない。それでも、TODOFIXMEany・巨大ファイルという「議論の入り口」を、毎週まったく同じ物差しで集められます。感覚のブレが消えるだけで、レビューの空気がかなり変わりました。

負債台帳テンプレート:Issueに散らさず1枚にまとめる

棚卸し結果をIssueにバラバラに立てると、優先順位を比べられなくなります。僕は1枚の台帳にまとめています。

# Technical Debt Register

| ID | Area | Evidence | User or team impact | ICE | RICE | Owner | Next PR | Status |
| --- | --- | --- | --- | ---: | ---: | --- | --- | --- |
| TD-001 | Auth permissions | src/auth/guard.ts duplicates role checks in 4 places | New role changes take 2 days and often miss one path | 420 | 1680 | Backend | Extract pure canAccess() with tests | Ready |
| TD-002 | Dependencies | vite is 2 major versions behind | Security patches and plugin updates are blocked | 280 | 900 | Platform | Upgrade in isolated branch and run build/test | Investigating |

## Scoring note

- ICE = Impact x Confidence x Ease
- RICE = Reach x Impact x Confidence / Effort
- Keep evidence links concrete: file path, line, CI run, or user-facing incident.

ICEは速く並べたい時の指標。RICEは影響人数や工数まで入れたい時に向きます。どちらも「正解を出す計算式」ではなく、会話をそろえる道具だと割り切るのが大事です。スコアが高くても、テストがない領域なら「先に観測とテストを足す」が最初のPRになることはよくあります。

安全なリファクタ計画を作らせるプロンプト

返す対象が決まったら、実装の前に計画を作らせます。ここでも「まだ編集するな」を忘れずに。

claude -p "
TD-001 を安全に返済する計画を作ってください。まだ編集しないでください。

対象:
- src/auth/guard.ts
- src/auth/roles.ts
- tests/auth/guard.test.ts

制約:
- 外部 API の挙動を変えない
- 既存テストを先に確認する
- テストが不足していれば、挙動固定テストを先に追加する
- PR は 300 行以内を目標にする
- リスク、ロールバック方法、レビュー観点を書く

出力:
1. 現状の挙動まとめ
2. 変更しないこと
3. 最初のPRの差分案
4. 実行するテストコマンド
5. レビュー依頼文
"

このプロンプトの肝は「変更しないこと」を書かせる行です。Claude Codeは改善案をどんどん広げられる反面、境界が曖昧だと親切心で余計な整理を始めます。「ここは触らない」を先に宣言させると、レビューしやすい小さな差分に収まります。権限まわりの自動・手動の線引きは 承認とサンドボックスの設計 も参考にしてください。

リファクタPRチェックリスト

PR本文を作らせる時、僕はこのチェックリストを一緒に渡します。

## Refactor PR checklist

- [ ] This PR changes structure, not product behavior.
- [ ] Existing behavior is covered by tests before the refactor.
- [ ] New helper names describe domain behavior, not implementation detail.
- [ ] Public API, response shape, permissions, and logging are unchanged or explicitly documented.
- [ ] The diff is small enough to review in one sitting.
- [ ] Rollback is simple: revert this PR without reverting unrelated work.
- [ ] The debt register is updated with status and follow-up PRs.

「This PR changes structure, not product behavior(このPRは構造を変えるだけで、製品の挙動は変えない)」が一番上にあるのが意図です。返済PRに新機能を相乗りさせた瞬間、レビューは一気に難しくなる。構造変更と機能変更は、別のPRに分けます。

僕がやらかした失敗5つ

正直に書きます。きれいに回るまで、けっこう転びました。

1. 自動修正を信じすぎた。 Claude Codeの差分は型が通っていても安全とは限りません。認可・課金・日付・非同期・DBマイグレーションで、一度「通ったしOK」と本番に出して冷や汗をかきました。今はこの5領域だけは、挙動固定テストと人間レビューを必須にしています。

2. TODO を全部消そうとした。 TODO には「今すぐ危険な未実装」と「将来の改善メモ」が混在します。FIXME: bypass auth のような危険語を最優先で潰し、ただのメモは台帳に記録するだけ。全消しは時間の無駄でした。

3. 依存更新をまとめすぎた。 10個のmajor updateを1PRに突っ込んだら、CIが落ちた時に原因を切り分けられず、結局全部revert。ビルドツール・UI・認証・テストランナーは分ける、と痛い目で学びました。

4. スコアを政治に使いかけた。 ICE/RICEは会話の道具です。「高いスコアを付けた人の勝ち」にした瞬間、誰もスコアを信用しなくなる。証拠・影響・工数をセットで書く運用に戻したら、また機能し始めました。

5. チームの記憶を残さなかった。 「このプロジェクトでは小さなPRにする」「権限まわりは必ず承認を取る」を毎回プロンプトで説明していて疲弊しました。CLAUDE.md と Settings に書いてからは、説明コストがほぼゼロに。詳しくは CLAUDE.mdベストプラクティス にまとめています。

チーム運用の型:週1回30分でいい

おすすめは、週1回30分の負債レビューです。新しい負債を見つけて誰かを責める会ではなく、返せる最小のPRを1つ選ぶ会にします。

  1. スキャナとClaude Codeの棚卸し結果を眺める
  2. 上位10件だけ ICE/RICE を更新する
  3. 次スプリントで返済PRを「1件だけ」作る
  4. flaky test とセキュリティ依存は通常より一段高く扱う
  5. 完了後、台帳に「何がラクになったか」を1行で残す

5番が地味に効きます。「ロール追加が2日→半日になった」と1行残すだけで、次の負債レビューで「やる価値あるね」という空気が自然にできます。

ClaudeCodeLabでは、この運用をチームに合わせて整える研修・テンプレート・相談メニューを用意しています。負債台帳、PRチェックリスト、権限設定、CLAUDE.md の初期テンプレートをまとめて入れたい場合は 研修・テンプレート・相談、すぐ使える教材は 教材一覧 をのぞいてみてください。

よくある質問

Q. ICEとRICE、どっちを使えばいい? まずはICEで十分です。Impact × Confidence × Easeの3つだけなので、ホワイトボードでも5分で並べられます。影響人数や工数まで議論したくなったらRICEに切り替える、くらいの温度感でいいです。

Q. 1つのPRは何行までに抑えるべき? 目安は300行です。厳密なルールではなく「一回の集中でレビューしきれるか」が本質。テストや自動生成ファイルを除いた、人がレビューする差分で考えてください。超えそうなら、共通関数の作成と置き換えを別PRに割るサインです。

Q. Claude Codeに修正まで任せて大丈夫? 領域によります。表示まわりの整理や命名は任せやすい。一方で認可・課金・日付・非同期・DBマイグレーションは、挙動固定テストと人間レビューを必須にしてください。危険な操作の自動許可は最初は外し、安全と分かったものだけ後から格上げするのが安全です。

Q. npm audit の警告は全部消すべき? いいえ。件数に振り回されないでください。深い依存にある実害の薄い警告より、EOL間近の主要ライブラリのほうが優先度は上です。「実害」で並べ替えるのが先で、件数ゼロは目的ではありません。

Q. 棚卸しを最初から修正までやらせない理由は? 根拠の薄い変更が混ざるからです。調査と修正を一気にやらせると、どの変更が妥当か後で判断できなくなります。「まだ変更しないで」と明言して地図だけ作らせ、優先順位は人間が決める。この一線が、返済ループを破綻させないコツです。

実際に試した結果

このループを僕の小規模プロジェクトで回してみて、いちばん変わったのは「負債を見る目」でした。

最初の棚卸しで、負債が「すぐ直すべきもの」と「今は記録だけでいいもの」にスパッと分かれたんです。特に any と古い TODO を小さなPRに刻んだら、レビュー時間をほとんど増やさずに、不安な箇所だけ着実に減らせました。8,000行ブランチで3週間溶かした去年とは別世界です。

一方で、依存関係のmajor updateは予想以上に検証が重く、Claude Codeに任せきりにせず、テスト追加とリリース手順の確認を先に置くほうが安全でした。AIは「changelogを読んで整理する」のは得意でも、「本番で壊れないと保証する」のは人間の仕事です。

結局のところ、技術的負債を減らすコツは「大きく直す」ではなく「証拠を集め、小さく返す」。Claude Codeはその地味なループを、棚卸し・分類・計画・PR文の面で確実に速くしてくれます。来月から、と言い続けるのをやめて、今週30分だけ確保する。それが、僕にとって一番効いた一手でした。

#Claude Code #技術的負債 #リファクタリング #コード品質 #ICE/RICE
無料

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。

Masa

この記事を書いた人

Masa

Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。