Karpathy Guidelines — code you will not rewrite
This exists because language models make predictable mistakes — the same ones, over and over. Not suggestions: rules. The model is fast at generating plausible code and slow to notice that plausible is not the same as correct, so the discipline has to come from the process around it.
Tradeoff: biases toward caution over speed. Trivial one-liners — use judgment, skip.
I. Read before you write
The biggest source of bad model-written code is writing before reading the
codebase. Read the files you're about to touch — read, not skim. Copy the patterns
that already exist; check the imports so you don't reach for axios where
everything is fetch. When you can't find a pattern, ask instead of guessing.
II. Think before you code
Figure out what you're doing before you type. State assumptions ("add auth" is five different things — name the one you picked) and name the tradeoffs. If something is genuinely confusing, stop and ask rather than filling the gap with plausible-looking code — that's exactly the code that passes a casual review and fails when it matters.
III. Simplicity
Write the minimum code that solves the problem in front of you, not the minimum that could solve every future version of it. Resist premature abstraction, skip error handling for errors that cannot occur, hardcode until there's a real reason to configure. Test: if the only reason something is abstracted is "in case we need to," you've over-built it.
IV. Surgical changes
Your diff should be as small as the task allows. Don't touch what you weren't asked to touch, match the existing style, don't reformat — a formatter pass buries the three lines that matter inside three hundred that don't. Can you justify every changed line by the task? If a line is there because "while I was in there," revert it.
V. Verification
The gap between code that works and code you think works is testing. Fixing a bug: write the failing test first, watch it fail, then fix — that's the only proof you fixed the cause and not the symptom. Test behavior that can actually break, not that a constructor sets a field. If something is hard to test, that's information about the design, not permission to skip.
VI. Goal-driven execution
Every task needs a success criterion before code is written. "Add validation" becomes "reject a missing or malformed email, return 400 with a clear message, test both cases." For anything multi-step, state the plan first so the user can catch a wrong approach before you spend an hour building it.
VII. Debugging
When something breaks, investigate — don't guess. Read the whole error and the stack trace, reproduce the problem before you change anything, change one thing at a time. Don't paper over an unexpected null with a null check; find out why it's null, or the bug just moves somewhere quieter.
VIII. Dependencies
Every dependency is permanent code you don't control. Before adding one, ask whether
the project or the standard library already does it (crypto.randomUUID() over a
uuid package). When you do add one, say why — so the choice is visible rather than
smuggled into the manifest.
IX. Communication
Say what you did and why, not just a block of code. Flag concerns even when you did exactly what was asked. Be precise about uncertainty: "I'm not sure this library supports streaming" tells the user what to verify; "I think this should work" does not.
X. Common failure modes — catch yourself, then stop
- Kitchen Sink — restructuring half the codebase while you're at it.
- Wrong Abstraction — abstracting before you've copy-pasted twice.
- Optimistic Path — happy path handled, the 500 ignored.
- Runaway Refactor — a fix that cascades across files.
Catch yourself in any of these and the right move is to stop, not push through.
Consolidated 2026-07-24 from the definitive 10-section field notes. Supersedes the
former clarity + 4-rule karpathy-guidelines duplicates (clarity archived).
Referenced by ~/.claude/CLAUDE.md; that inline 4-line block is the always-on
summary, this is the progressive-disclosure detail.