LLMにコードを書かせるなら知っておきたい「Karpathy Guidelines」を解説する
はじめに
AIにコードを書かせる時代になりました。GitHub Copilot、Cursor、Claude Code——ツールは増え続けていますが、LLMが書くコードには共通の「悪い癖」があることに気づいている人も多いのではないでしょうか。
- 頼んでもいない機能を足してくる
- 関係ない箇所まで「改善」してくる
- 聞けば「わかりました」と言うのに、前提を勝手に決めている
- 200行で書いたものが50行で済む
これらの問題について、Tesla AI / OpenAI出身のAndrej Karpathy氏が自身のポストで指摘し、大きな反響を呼びました。
本記事では、そのKarpathy氏の知見をClaude向けの行動ガイドラインとして体系化した 「Karpathy Guidelines」 というSKILL.mdファイルを紹介・解説します。これはClaude Codeなどで利用できるスキルファイルで、LLMのコーディング品質を向上させるための4つの原則をまとめたものです。
補足: SKILL.mdとは、Claude Codeやその他のAIコーディング環境でLLMの振る舞いをカスタマイズするための設定ファイルです。プロンプトの一部としてLLMに読み込ませることで、特定の行動パターンを強化できます。
4つの原則の全体像
Karpathy Guidelinesは、次の4つの原則で構成されています。
| # | 原則 | 一言で言うと |
|---|---|---|
| 1 | Think Before Coding | 前提を明示せよ。曖昧なまま進むな |
| 2 | Simplicity First | 最小限のコードで解決せよ。投機的に書くな |
| 3 | Surgical Changes | 変更は外科手術のように。触るのは必要な箇所だけ |
| 4 | Goal-Driven Execution | 成功基準を定義せよ。検証可能なゴールに変換せよ |
ファイル冒頭には次の注意書きがあります。
Tradeoff: These guidelines bias toward caution over speed. For trivial tasks, use judgment.
(これらのガイドラインはスピードよりも慎重さを重視している。些細なタスクでは自分で判断せよ。)
「常にこうしろ」ではなく、リスクの高い作業ほど厳格に適用し、単純な作業では柔軟にというバランス感覚が前提になっています。
原則1: Think Before Coding(コードを書く前に考えろ)
Don't assume. Don't hide confusion. Surface tradeoffs.
(仮定するな。混乱を隠すな。トレードオフを表に出せ。)
なぜ必要か
LLMは「わかりません」と言うのが苦手です。曖昧な指示を受けても、もっともらしい解釈を勝手に選んでそのまま実装してしまう傾向があります。結果として、ユーザーの意図とは違うものが出来上がり、手戻りが発生します。
ガイドラインの内容
実装に入る前に、次のことを行え:
- 前提を明示的に述べよ。不確かなら聞け
- 複数の解釈がある場合は、それらを提示せよ——黙って一つを選ぶな
- よりシンプルなアプローチがあるなら、それを言え。必要なら反論せよ
- 不明点があれば止まれ。何が分からないのか名指しで言え
実践のポイント
これはLLMに対して「推測で突き進むな、確認を取れ」と明示的に指示するものです。人間のエンジニアでも当たり前のことですが、LLMは特にこの点が弱いため、明示的に指示する価値があります。
たとえば「認証機能を追加して」という指示に対して、LLMが黙ってJWTベースの実装を始めるのではなく、「セッションベースとJWTベースのどちらを想定していますか?」と聞いてほしいわけです。
原則2: Simplicity First(シンプルさを最優先せよ)
Minimum code that solves the problem. Nothing speculative.
(問題を解く最小限のコード。投機的なものは一切なし。)
なぜ必要か
LLMは「親切心」で余計なことをしがちです。聞かれていない設定オプション、使われないエラーハンドリング、将来のための抽象化——これらが積み重なると、本来50行で済むコードが200行になるという現象が起こります。
ガイドラインの内容
- 頼まれた以上の機能を作るな
- 一度しか使わないコードに抽象化を入れるな
- 要求されていない「柔軟性」や「設定可能性」を追加するな
- ありえないシナリオのエラーハンドリングを書くな
- 200行で書いたものが50行で済むなら、書き直せ
そして自問せよ:
「シニアエンジニアがこれを見て『やりすぎだ』と言うか?」——Yesならシンプルにしろ。
実践のポイント
これはYAGNI(You Aren't Gonna Need It)原則をLLM向けに強化したものです。LLMは訓練データに含まれる「良い設計パターン」を再現しようとしますが、文脈に合わないパターンの適用はむしろ有害です。
具体例として、「ファイルを読んでJSONをパースする関数を書いて」に対して、ストラテジーパターンを導入したり、プラグインシステムを作ったりするのは「投機的」です。fs.readFileSync + JSON.parse で十分なら、それだけでいい。
原則3: Surgical Changes(外科的な変更を行え)
Touch only what you must. Clean up only your own mess.
(触るのは必要な箇所だけ。片付けるのは自分が散らかしたものだけ。)
なぜ必要か
これは既存コードを編集する場面で特に重要です。LLMはコードを見ると「ついでに直したく」なります。コメントの書き換え、変数名の変更、フォーマットの統一——善意ではありますが、レビューの範囲が爆発的に広がり、本来の変更が埋もれてしまう原因になります。
ガイドラインの内容
既存コードを編集するとき:
- 隣接するコード、コメント、フォーマットを「改善」するな
- 壊れていないものをリファクタリングするな
- 自分なら違うやり方をするとしても、既存のスタイルに合わせよ
- 関係のないデッドコードに気づいたら、削除せず言及だけせよ
自分の変更が生んだ孤立コードについて:
- 自分の変更で不要になったimport/変数/関数は削除せよ
- 元から存在していたデッドコードは、頼まれない限り削除するな
検証基準:
変更した全ての行が、ユーザーのリクエストに直接紐づいているか?
実践のポイント
gitの差分(diff)を想像してください。理想的なPull Requestは、変更の意図が一目でわかるものです。LLMが「ついで改善」を入れると、diffが大量に膨らみ、本質的な変更がどこにあるのか分からなくなります。
このルールの裏側には「LLMの変更を人間がレビューする」という前提があります。レビュー可能な変更を生成することは、信頼関係の基盤です。
原則4: Goal-Driven Execution(ゴール駆動で実行せよ)
Define success criteria. Loop until verified.
(成功基準を定義せよ。検証されるまでループせよ。)
なぜ必要か
「バグを直して」「バリデーションを追加して」——このような指示は人間同士なら成立しますが、LLMに対しては曖昧すぎて検証不可能です。LLMが「直しました」と言っても、本当に直ったのか確認する手段がなければ意味がありません。
ガイドラインの内容
タスクを検証可能なゴールに変換せよ:
| 曖昧な指示 | 検証可能なゴール |
|---|---|
| 「バリデーションを追加して」 | 「不正入力に対するテストを書き、それをパスさせよ」 |
| 「バグを直して」 | 「バグを再現するテストを書き、それをパスさせよ」 |
| 「Xをリファクタリングして」 | 「リファクタリング前後でテストがパスすることを確認せよ」 |
複数ステップのタスクでは、計画を明示せよ:
1. [ステップ] → 検証: [確認方法]
2. [ステップ] → 検証: [確認方法]
3. [ステップ] → 検証: [確認方法]
強い成功基準があればLLMは自律的にループできる。弱い基準(「動くようにしろ」)は常に確認が必要になる。
実践のポイント
これはTDD(テスト駆動開発)の考え方をLLMとの協業に応用したものです。「テストが通れば正しい」という明確な基準があれば、LLMは自分でコードを修正→テスト→修正のループを回せます。
特にClaude Codeのようなエージェント型ツールでは、この原則が効果を発揮します。検証基準が明確であればあるほど、人間の介入なしにLLMが自走できる範囲が広がります。
SKILL.mdとしての使い方
このガイドラインをSKILL.mdとして配置することで、Claude Codeなどの環境でLLMの振る舞いを恒常的に改善できます。
配置方法の例
プロジェクトのルートや、Claude Codeのスキルディレクトリに配置します。
my-project/
├── .claude/
│ └── SKILL.md ← ここに配置
├── src/
└── ...
あるいはClaude Codeの CLAUDE.md や類似の設定ファイルから参照させる方法もあります。
期待される効果
- 不要なコードの削減: 原則2により、投機的な実装が抑制される
- レビュー負荷の軽減: 原則3により、diffが最小限になる
- 手戻りの減少: 原則1により、前提の食い違いが早期に発見される
- 自律動作の向上: 原則4により、LLMが自分で検証ループを回せるようになる
まとめ
Karpathy Guidelinesの4原則を振り返ります。
- Think Before Coding — 推測で進むな。前提を確認しろ
- Simplicity First — 最小限のコードで解決しろ。YAGNI
- Surgical Changes — 外科的に。関係ない箇所に触るな
- Goal-Driven Execution — 検証可能なゴールを設定しろ
これらは実は、人間のエンジニアにとっても当たり前の原則です。しかし、LLMは人間と違う方向に「間違える」ため、明示的に言語化して指示する必要がある——それがこのガイドラインの本質です。
LLMとの協業は「プロンプトを投げて結果を受け取る」だけではありません。LLMの振る舞いそのものを設計するという視点が、これからますます重要になるでしょう。
SKILL.md
---
name: karpathy-guidelines
description: Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria.
license: MIT
---
# Karpathy Guidelines
Behavioral guidelines to reduce common LLM coding mistakes, derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls.
**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
## 1. Think Before Coding
**Don't assume. Don't hide confusion. Surface tradeoffs.**
Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
## 2. Simplicity First
**Minimum code that solves the problem. Nothing speculative.**
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
## 3. Surgical Changes
**Touch only what you must. Clean up only your own mess.**
When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.
When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.
The test: Every changed line should trace directly to the user's request.
## 4. Goal-Driven Execution
**Define success criteria. Loop until verified.**
Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"
For multi-step tasks, state a brief plan:
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.