AIに手綱をつける——Claude Code で 150 コミットを重ねてわかったハーネスエンジニアリングの実践
「バイブコーディング」の次にやってくるもの
2025 年の後半あたりから「バイブコーディング」という言葉をよく聞くようになりました。コードの細部を自分が理解せずとも、AI に感覚的に指示を出しながら開発を進めていくスタイルのことです。
そして、名村もその流れに乗りました。2026 年の 2 月ごろからほぼ毎日 Claude Code で何かを作っています。最初のうちは「すごい時代になったな」という感動が先行していましたが、しばらく使い込むうちに違う問題意識が出てきました。
「AI に丸投げすると、ちゃんと丸投げできているときと、なんか違うな…?ということになるときの差がかなり大きい気がする…」
その差がどこから来るのかを考えていたときに出会ったのが「ハーネスエンジニアリング」という考え方です。Xでは(2026/05/11時点の)今もタイムラインには「これが最先端の生成AIの使い方だ」という話題が溢れていますが、この「ハーネスエンジニアリング」はその話題の一つでした。見つけて組み込んだのは一ヶ月ぐらい前だったと思います。
「ハーネス」とは、元々は馬に装着する馬具——手綱や胴回りのベルト——のことですが、転じて「能力を制御・誘導する仕組み」を意味しているようです。ハーネスエンジニアリングとは要するに、「AI の能力を安全かつ高品質なアウトプットに変換するための環境設計」という趣旨で語られています。
この記事では、名村が実際に開発期間1か月、Gitへのコミット数が 150を超える規模の Next.js + TypeScript プロジェクトを Claude Code を使って開発をした経験から、「AI との開発においてハーネスエンジニアリングとは何か」「実際に何が起きて、何を学んだか」「これからどう変えたか」を纏めておきたいと思います。
Claude Code を使っていなくても、AI ツールを業務に取り入れている方に参考になる部分があれば嬉しいです。
ハーネスエンジニアリングとは何か——「on the loop」という立場
少し概念の話から説明をしておきいます。
AI 開発の世界では、「in the loop」と「on the loop」という対比があります。
「in the loop」は AI と並走して細かく指示・修正を繰り返すスタイルのことで、「on the loop」は AI が自律的に動く環境を設計・監視し、全体の方向性をコントロールするスタイルを指します。(この「in the loop」は軍事でも同じ言葉が使われていて、ミサイルの発射にはそのプロセスに「ヒューマン・イン・ザ・ループ(Human-in-the-Loop:HITL)」が組み込まれて、人間が最後に判断をするようになっている方法があったりします)
バイブコーディングが「in the loop で感覚的にやる」のだとすれば、ハーネスエンジニアリングは「on the loop でいい環境を育てる」ということに重きを置いているといえます。
具体的に言うと、以下のような手順となってきます。
CLAUDE.md(Claude Code が常時参照するルールファイル)にプロジェクトの絶対ルール・禁止パターン・コーディング規約を書く
ミスや想定外の挙動が起きたら、再発防止ルールを lessons.md に記録する
コードレビューは 別エージェントに担当させる(Generator-Evaluator パターン)
定型タスクはスラッシュコマンドとして定義し、繰り返し呼び出せるようにする
「プロンプトをその都度磨く」という行為をすでにやっている方は多いと思います。ただハーネスエンジニアリングはそれをもう一段構造化したものと考えてください。
一つひとつの会話で頑張って指示するのではなく、「どのセッションでも・どのプロジェクトでも同じ品質が出るための仕組みを常設する」という発想です。
この記事を書くことになったプロジェクトについて
ハーネスエンジニアリングの話を深ぼる前に、その前提となった今回の開発の規模感を少し説明しておきます。
私が個人で進めていたあるSaaSサービスの開発プロジェクトがありました。
技術スタック
Next.js 15 (App Router) + TypeScript (strict) + PostgreSQL + Prisma + Redis + Cloudflare R2 + Google Maps Platform
ローカルでDockerを動かして開発
pm2 で管理する 3 プロセスが 11 本の cron ジョブを回している
生成ファイル数はログ、サイト用の画像などもありまうが、およそ90,000ファイル
最終的にはWebサイトとして公開をするSaasのサービスにするもの。
(詳細はちょっと書きづらいので、ご了承ください…)
実際の開発期間はおよそ2週間で、仕事のスキマ時間か深夜帯に毎平日に2時間ぐらい費やしていました、一人開発ではありましたが、履歴管理的な意味合いからも一定の変更単位でGitHubに保存はしていて、この期間でのコミット数は 150でした。2週間でこの規模ですので、まぁまぁ大きい方だとは思います。
Claudeで要件定義→生成されたドキュメントが28ファイル、その後Claude Codeで実装を進める、という形でしたが、「バイブコーディング」でここまで規模の大きなプロジェクトの経験は、名村にとって初めてのことでした。
このプロジェクト以前に用意していたハーネス
この開発プロジェクトを始める前から、名村の Claude Code 環境にはいくつかのハーネスが組み込まれていました。それはXで流れてきたものを元にして、いろいろ手を加えて名村の使い方に合う合わないをみて、取捨選択した結果です。
CLAUDE.md という「生きた指示書」
Claude Code を使う開発では、その開発ソースコードなどを配置する「ディレクトリ」を「プロジェクト」と判断しますが、この「プロジェクト」リポジトリのルートに CLAUDE.md というファイルを置くと、Claude Code がそのセッション中ずっと参照してくれます。
ここに「このプロジェクトの絶対ルール」「禁止パターン集」「コーディング規約」などを書き込んでいく訳です。
前述の名村のプライベートプロジェクトでは、 CLAUDE.md には最終的に「17 章・450 行以上」の記述が入りました。「Node.js は v22 LTS 固定」「SQL は Prisma のパラメータ化クエリ必須」「any 型禁止」「console.log を本番に残さない」「外部 API 呼び出しは必ず trackApiUsage ラッパー経由」……といったプロジェクト固有の縛りがずらっと並んでいます。
ここで重要なのは、このファイルを「コードと同等の成果物」として扱うことです。
僕は本業はWebディレクターですので、開発におけるバッドケースはこの30年で何度も経験をしてきたので、「バッドケース」「ミスをした」ときの痛い経験はある意味血肉になり、記憶に残っているので、ある程度プロジェクト中に先回りして、「こうなったりしない?」「このまま進んだら〇〇になったりするでしょ?」というのが分かります。
ですが、生成AIに僕のすぐに言語化できない経験は伝えられません。
ですので、バイブコーディングではコードを書くのはもちろんですが、プロジェクトの「CLAUDE.md」も「一回書いて終わり」ではなく、ミスが起きるたびに更新するようにしています。
同じミスが 2 回繰り返されたら必ずルールに追加する、という運用をしている、ということです。
Generator-Evaluator パターン
「作る役」と「検証する役」を分離するルールのことを指しています。
コードを書いた Claude Code 自身がそのコードをレビューすると、どうしても客観性が失われます。これは人間がやっても全く同じことで、自分が書いたコードは、自分の「意図」に引っ張られて、潜在的なバグを見逃しやすくなるわけです。
そこでコードレビューは別の「code-reviewer エージェント」で実施をするようにしています。これは開発において、基本的には一つのタスクが終わったら必ずコードレビューを通すように設計しています。まぁ、実際に人でやっている開発と全く同じですね。
Claude Code に実装してもらった後、「このコードを独立した視点でレビューしてください」と別のセッションの Claude に渡す、というイメージです。この分離だけで、ある開発Phaseの実装時には「CRITICAL 2 件・HIGH 6 件・MEDIUM 7 件・LOW 7 件」が発見されました…(あれ、結構多くね?)
「バイブコーディング、SUGEEEEE!」みたいな話題で盛り上がっていますが、今(2026年5月6日)時点だと、規模が大きくなったり、複雑な連係をしているプログラムでは設計をかなり丁寧にしていても、Claude Codeもまだ不具合やバグは全然仕込んでしまっているといえます。
PR でのマージ前にこれらの指摘をゼロにできたのは、このパターンを組んでいたおかげでした。(余談ですが、その意味では2026年5月6日時点では「どんなSaaSやスマホアプリもバイブコーディングで秒で作れる」というの大嘘だと思います。)
コードレビュー指摘は確認なしに全件即修正
/code-review というスラッシュコマンドを使うと、コードの品質・セキュリティ・型安全性等をスキャンしてくれます。
当初、「LOW 指摘が出ました。修正しますか?」と Claude Code が確認してくることがありました。
ただ、これを毎回やられると開発の速度が遅くなる…というか私の手が不定期に止まります。それもあって結果的に面倒くさくなり「LOW は軽微だから後で……」という流れになりがちです。
なのでルールに「CRITICAL / HIGH / MEDIUM / LOW を問わず、ユーザーへの確認なしに全件即修正する。指摘ゼロになるまでレビューと修正を繰り返す」と明記しました。これで「コードレビューを回しておけば最終的には必ず品質が担保される」という安心感が生まれます。
lessons.md という教訓ログ
ミスや予期せぬ挙動があったときに、「何が起きたか・なぜ起きたか・次回防ぐルール」を記録するファイルです。グローバル版(全プロジェクト共通)とプロジェクト固有版の 2 層構造になっています。
セッション開始時に直近 3 件を読み返す運用で、「前回のセッションで起きたことを次のセッションに引き継ぐ」装置として機能しています。
150 コミットで見えてきた「楽観的判断」というリスク
ここまで準備をしたり、CLAUDE.mdに設定をいれていましたが、開発が進むにつれて、Claude Code が特定のパターンでミスをすることに気づいてきました。
「セキュリティ違反」とか「構文エラー」とかではなく、もっと根が深い種類のミスです。
私はそれを「楽観的判断」と呼んでいました。だってどう考えてもClaude Codeが「あ、それで行けるとおもってやっちゃいました…」って感じでやった結果なんですもん…
正確に言うと、「確認すれば防げたはずの仮定を、確認せずに通してしまった」というパターンですね…
いくつか具体例を挙げます。
「このサービスのホスト名は 1 つだろう」という思い込み
外部サービスを許可リストに登録するとき、hogehoge.jp には aaaa.hogehoge.co.jp という別サブドメインが存在することを見落としていました。外部サービスが複数のホスト名を持つことは珍しくないのに、「1 サービス = 1 ドメイン」という前提で実装していたわけです。実際外部サービスと連係していたらサブドメインの情報もでてきていたりするので、全く分からなかった…ではなく、調べたら分かったのに無視した感じでした。
「テストが通る = devサーバーも正常」という誤った等価関係
結構あちこちに手を入れる改修をして結果的に20 ファイル以上を一度に変更してコミットした後、全ルートが HTTP 500 を返すようになりました…
まぁまぁ焦りました。
なんせユニットテスト・型チェック・lint はすべてパスしていたので、Claude Codeも「コードに問題はないはず」と判断してしてしまっていました。
実際には Next.js のホットリロードが大量変更を処理しきれず不整合な状態になっていただけです。
そこまで正しいのに動かないのって…??と、は見ていて感じた(過去のトラブルシュートの経験からくる勘がこういう時に生きますw)ので、手元で別ポートで新しいサーバーを起動してみたら即座に 200 が返ってきました…(ホラ見ろ…)。
コードの正しさ(テスト)とサーバーの健全性(HTTP 応答)は全く別の話なので、個別に確認する——というのはリアルで開発やってきたら誰しも通る「え、そういうこと?」という経験であり教訓です。このミスは後に CLAUDE.md の「Definition of Done」にコミット後の「スモークテスト必須」という項目が追加されるきっかけになりました。
「小さな変更にコードレビューは不要」という省略バイアス
「parser ロジックが中心でセキュリティリスクが低い」という判断でコードレビューを省略したことがあります。後から実施してみると、HIGH 指摘(parseFloat の結果に NaN が混入するリスク)が検出されました。
parseFloat("文字列") が NaN を返すことは JavaScript 開発者なら分かりやすいのですが、「このフィールドは必ず数値だろう」という楽観的仮定が入ってしまっているように見受けられました。
常に想定外のフォーマットが来る可能性はあります。コードレビューは「セキュリティ確認」だけではなく「型安全性・NaN 安全性の複合チェック」でもあります。変更規模による省略は禁止すべきでした。
「楽観的判断」を生む構造的原因
これらのミスを並べてみると、共通する構造が見えてきます。
それは「確認すれば防げたが、確認する習慣がルール化されていなかった」ということです。
優秀な Claude Code でも、「ここで立ち止まって実データを確認する」という行動規範がなければ、効率を優先して仮定に基づいて進んでしまいます。これは人間のエンジニアと全く同じです。締め切りが迫っているときほど「たぶんこうだろう」で進めてしまいがちですよね。
ハーネスに「何をすべきか」は書いていたのに、「どのタイミングで一度立ち止まるか」が書けていなかったわけです。
もう一つの問題:「自律判断の境界」が曖昧だった
同時期に気づいたことがもう一つあります。
ミスのパターンを整理すると 2 種類に分かれていました。「楽観的判断による技術的ミス」(URL パターンの検証漏れ、NaN ガード漏れ等)と、「確認すべき場面で確認しなかった判断ミス」(外部サービスの認証方式を変更する、など)です。
後者について考えてみると、Claude Code が「ここは自分で判断して進んでいい」と思っていた場面と「ここはユーザーに確認すべきだった」と思い返せる場面が、明確に分かれていることがわかりました。
例えば、コードレビューの指摘修正は確認なしに即実行すべきです。いちいち「LOW の指摘がありますが修正しますか?」と聞かれていたら開発速度が落ちる一方です。しかし、認証方式を変更する場合や DB のカラムを削除するような操作は、必ず事前にユーザーの承認を得るべきです。
では「npm パッケージを新規追加する」はどちらでしょうか。「外部サービスの認証を Webhook から Bot Token に切り替える」は?
こういった「グレーゾーン」に対して明示的なルールが存在していませんでした。それが「気づいたら想定と違う変更がされていた」という体験につながっていたんだと思います。
新たに加えた「信号機」ルール
そこで追加したのが「自律判断の境界ルール(Autonomy Boundaries)」です。Claude Code の行動を 3 段階に分類しました。ファイルとしては ~/.claude/rules/common/autonomy-boundaries.md に書き起こし、全プロジェクトに適用されるグローバルルールとして登録しています。
🟢 緑 — 確認不要、即実行
コード品質・バグ修正・ドキュメント更新の範囲内であれば、ユーザーへの確認は不要です。実行後に結果を報告します。
代表例として、/code-review 指摘の全件修正、ビルドエラー・型エラー・lint エラーの修正、コミット後のスモークテスト、テスト追加、ドキュメント更新などが該当します。これらは「今やるべきことが明らか」で、迷う余地がありません。確認を入れると開発のリズムが落ちるだけです。
🟡 黄 — 1 行説明してから実施
新しいコスト・依存関係・構成を伴う変更は「〇〇を △△ の理由で追加します」と 1 行告知してから実行します。
npm パッケージ追加の場合は「パッケージ名・目的・週間ダウンロード数・採用理由」を明示します。DB マイグレーション、新規環境変数追加、新しい cron ジョブ追加、外部サービスの設定変更なども「黄」です。
「黄」の本質は「ユーザーが後から知ったら驚くかもしれないことを先に伝える」です。告知することで、反論があれば止められます。
🔴 赤 — 承認必須、着手前に方針を提示
アーキテクチャ変更・既存コードに対しての破壊的といえる変更(これはやってはいけないという意味ではなく、実施することは必須だが大きくロジックを書き換える、という意味です)・セキュリティ設計・スコープ外の変更は、承認を得てから着手します。
技術スタックの変更、DB のカラム削除・型変更、認証方式の変更、本番環境の設定変更、要求から逸脱した機能追加などが該当します。
セキュリティに関わるものはすべて「赤」です。これだけは絶対に妥協しません。「自律性を上げる = セキュリティ基準を下げる」という図式は成立しないということを、ルールの根幹に置いています。
迷ったときの 4 問
どの色に分類するか迷うときは次の 4 問を自問します。全て「No」なら「緑」(即実行)です。
セキュリティが下がるか?
データが消えるか・本番が壊れるか?
要求スコープを超えているか?
新しいコストやパッケージが発生するか?
プロジェクト固有の失敗を「汎用ナレッジ」に翻訳する
もう一つ、今回取り組んだ重要な作業があります。プロジェクト固有の失敗を「他のプロジェクトでも使える形」に翻訳することです。
「detailPathPattern を実 URL で検証せずに書いた」という 今回のプロジェクトにおける固有の失敗は、汎用化すると「パターンマッチング(regex/glob)は必ず実データで検証する」になります。
同様に:
ビルドエラーの件 →「Tailwind 等のビルドツールはテスト・ドキュメントも対象にする。明示的に除外設定を書く」(Tailwind だけでなく、UnoCSS・Windi CSS・styled-components の JIT モードでも同様)
Client/Server 境界の件 →「Next.js 等では Client Component からのインポートは推移的インポートの末端までサーバー専用モジュールが入っていないことを確認する。クライアント向けの薄いアダプターモジュールを分離する」
devサーバーの件 →「コミット後は HTTP レベルのスモークテストを必ず行う。全ルート 500 の診断は別ポートで新インスタンスを起動することから始める」
NaN の件 →「外部データ(スクレイプ結果・API レスポンス・ユーザー入力)の数値変換は
Number.isFinite()またはNumber.isNaN()でガードし、失敗時はnullを返す。parseNumberOrNull()のような汎用ユーティリティをlib/utils/に定義して使い回す」CI テストの不定期失敗の件 →「Testcontainers 等を使った統合テストは
globalSetupで一度だけ起動する。コンテナの準備確認は sleep でなくヘルスチェック API の polling で行う」
これら 9 件の汎用ナレッジを ~/.claude/lessons.md(全プロジェクト共通の教訓ファイル)に追記しました。次のプロジェクトから自動的に参照されます。「同じ失敗を次のプロジェクトでも繰り返す」という無駄を防ぐ仕組みです。
ハーネスエンジニアリングの本質:「育て続けること」
振り返ってみると、ハーネスエンジニアリングは「AI を縛る」ことではありませんでした。正確には「AI が迷わなくていい場面では迷わせず、立ち止まるべき場面では必ず立ち止まらせる環境を育てること」です。
150 コミットに至るまでのClaude Codeとのやり取りで「なんでそうなった?」ということを多数経験しましたが、それらから最後にまとめておきます。
ルールは「書いたもの勝ち」
どんなに優れた AI でも、「ここはこうする」というルールが明文化されていなければ、文脈から推量して進んでしまいます。推量はほとんどの場合うまくいきますが、ときどき外れます。その「外れ方」が「楽観的判断」という形で現れます。
ルールを書いておくことで、「推量が外れる可能性がある場面」を事前に潰せます。書いていないルールは存在しないのと同じです。この部分は日本語を文脈にしているわ我々日本人には難しい部分があると感じます。それは日本語では「行間を読み取る」「主語や目的語、極端にいえば動詞すらなくても成立する」言語を我々は使っています。ここら辺は私がやっている「誰がどう見てもそうとしか受け取れない文書術」のセミナーでも伝えていることですが、とにかく「論理的に言語化する」のが苦手な日本人には辛い部分です。
同じミスは「構造の問題」として捉える
1 回起きたミスをルールに書くかどうかは、「このミスは構造的に繰り返しうるか」で判断します。一度切りのタイポは書かなくていい。でも「URL パターンを想像で書く」は、次のサイト追加でまた起きます。
名村の運用では「同じミスが 2 回繰り返されたら必ず CLAUDE.md のルールに昇格させる」を原則にしています。
ハーネスは「最初から完璧」でなくていい
最初から完璧なルールを書こうとすると、むしろ手が動かなくなります。
起きたことを記録して→繰り返さないためのルールに変換して→それを次のプロジェクトに持ち越す、という積み重ねがハーネスになります。今回の 150 コミットを経て、CLAUDE.md は 17 章・450 行になり、lessons.md には 10 件以上の教訓が蓄積されました。これは最初に書いたものではなく、「育てた」ものです。
セキュリティは絶対に妥協しない
最後にこれだけは強調しておきたいのですが、「自律性を上げること」と「セキュリティ基準を守ること」はトレードオフではありません。
今回のルール設計では「セキュリティが下がるなら必ず赤(承認必須)」を最優先にしました。開発速度を上げるための自律性拡張が、セキュリティホールの温床になってはいけません。ハーネスエンジニアリングの根幹は「高品質を保ちながら速く動く」であって、「速く動くために品質を妥協する」ではありません。
おわりに
「ハーネスエンジニアリング」という言葉を知らなくても、「AI と仕事してたらなんか違うな……と感じる瞬間がある」という方は多いんじゃないかと思います。
その「なんか違う」の正体は、多くの場合「ハーネス(AI への指示書・ルールファイル・教訓ログ)の欠如か、陳腐化」です。
150 コミットという経験から言えることは、「ハーネスは作り始めのタイミングよりも、作り続けることに意味がある」ということです。最初から完璧なルールを書こうとしなくていい。起きたことを記録して、繰り返さないためのルールに変換して、それをまた次のプロジェクトに持ち越す。その積み重ねがハーネスになります。
CLAUDE.md 一枚・lessons.md 一枚から始めるだけでも、AI との開発の「再現性」はがらっと変わります。
この記事が、Claude Code をはじめとした AI との開発を「なんとなく」から「仕組みとして」に進化させたいと考えている方のヒントになれば嬉しいです。