← Back to Blog

Karpathy's Four AI Coding Rules Are the Floor, Not the System

Karpathy's Four AI Coding Rules Are the Floor, Not the System

Part of the Claude Code workflow series. New here? Start with the install primer, then what to do after install. This post assumes you already have a CLAUDE.md and are deciding what belongs in it.

Someone sent me the andrej-karpathy-skills repo and asked if I run it. It packages four behavioral rules, distilled from a Karpathy post about how LLMs fail at coding, into a drop-in CLAUDE.md. The rules are: think before coding, simplicity first, surgical changes, goal-driven execution.

Short answer: I follow all four, every day, and I wouldn't install the file. That sounds like a contradiction. It isn't, and the difference is worth a whole post, because it's the difference between advice and a system.

What the four rules get right

Karpathy's diagnosis is accurate. Coding models really do fail in these four ways:

  1. Hidden assumptions. The model guesses what you meant and runs with the guess.
  2. Overcomplication. Three abstractions where a function would do.
  3. Side-effect edits. You asked for a button, it also reorganized your imports and renamed two variables.
  4. No definition of done. It declares victory because the code looks plausible, not because anything verified it.

If you've spent a week with any coding agent you've watched all four happen. The repo turns each failure into a counter-instruction: surface assumptions, write the minimum, touch only what was asked, define success before starting. As a description of how good work happens, no notes.

Where the drop-in file makes sense

I want to be fair to it, because there are three situations where I'd recommend it without hesitating:

A brand-new repo with no CLAUDE.md at all. The four principles cost about a hundred lines and they're better than an empty file. Day one, paste it in, move on.

Your first week with a coding CLI. While you're still learning what these tools get wrong, a checklist of the famous failure modes keeps you skeptical at the right moments.

As a human review checklist. Honestly, this might be its best use. Reading AI output and asking "did it assume something, overbuild something, touch something unrelated, skip verification?" catches most bad diffs. Print it, tape it to the monitor, done.

Where it stops making sense

I run a couple dozen production sites through Claude Code, including this one, which carries 300+ browser tools and a couple hundred blog posts. Several hundred deploys a quarter. At that scale the generic file goes from harmless to mildly negative, for four reasons.

Generic rules never fire. "Keep it simple" cannot be violated at a specific moment. There's no diff where the model stops and says "this breaks the simplicity rule." It reads the line, agrees with it, and does whatever it was going to do. I wrote about this failure class in CLAUDE.md anti-patterns: a rule that can't be violated detectably is a placeholder, not a rule.

Every line competes for attention. A CLAUDE.md is a budget. The model reads it on every turn, and the generic paragraphs dilute the specific ones. My file says "never name a scheduled function with a -background suffix because the platform silently drops the schedule." That line has prevented real outages. It should not have to share attention with "consider tradeoffs carefully."

"Ask for clarification" breaks autonomous work. The repo's first rule tells the model to stop and ask when requirements are unclear. That's correct when you're sitting there. It's wrong when you've kicked off a forty-minute job and walked away. An agent that halts at minute three to ask a question you won't see until minute forty wasted the whole run. The mature version is different: state your assumptions and keep going. More on that below.

The models already internalized most of this. The original Karpathy complaints describe 2024-era behavior. Current models surface assumptions and keep diffs tight far more reliably than they used to. The failures that remain are the ones no generic file can catch, because they're specific to your stack, your templates, your deploy pipeline.

The earned version

Here's what each rule turned into after a year of corrections on a real stack. The pattern, every time: the principle survived, but it narrowed into something checkable, with the project's own details baked in. Copy these as starting shapes, then replace my specifics with yours.

1. Think before coding → state assumptions, then go

## Autonomous work protocol
Before any task expected to run unattended for 15+ minutes:
1. List the assumptions you're building on (data shapes, naming,
   what "done" means) in your first status message.
2. Then proceed. Do not wait for confirmation.
3. If a later discovery contradicts a stated assumption, stop and
   name the broken assumption before continuing.

This keeps the good part of "think before coding" (assumptions become visible and reviewable) without the part that kills unattended runs (blocking on a human who isn't there). When I come back, I read the assumption list first. If one is wrong, I know exactly what to re-check instead of auditing the whole diff.

2. Simplicity first → ban the specific temptation

"Write the minimum" does nothing. Naming the actual temptation in your stack does everything:

## Simplicity rules (enforceable)
- No new dependencies without asking. If a problem seems to need
  one, re-read the problem.
- Client JS is vanilla ES. No frameworks, no bundlers, no
  TypeScript in tool pages. They must run without a build step.
- Dates are ISO YYYY-MM-DD everywhere. No helper that "also
  accepts" other formats.

Each of those can be violated in a visible way, which means each one actually constrains behavior. The first line alone has stopped more bloat than any paragraph about minimalism ever did.

3. Surgical changes → additive by default, and name your surfaces

## Change discipline
- "Add X" means add it alongside what exists. Never remove or
  rewrite neighboring code as a side effect. If removal seems
  required, say so and stop.
- The brief JSON renders in TWO places: the client app and the
  server-rendered page. Any field change updates BOTH, plus the
  smoke-test fixture.
- Match the file's existing comment density and naming. A diff
  that restyles code it didn't need to touch is a failed diff.

The second line is the one I'd defend in a fight. Most real codebases render the same data in more than one place, and "surgical changes" doesn't help if the model doesn't know the second place exists. Naming every surface a data shape touches has saved me more broken pages than everything else in the file combined. No generic ruleset can contain that line, because the line is the map of your repo.

4. Goal-driven execution → gates the agent runs, not goals it holds

## Definition of done (machine-checkable)
- `npm run smoke` passes before any commit. It renders real
  fixtures through the real templates and fails on [object Object],
  NaN, undefined, or a missing section.
- Build exits clean, deploy, then fetch the changed URLs on
  production and confirm the new content is actually there.
- A deploy that times out is NOT a failed deploy. Check the live
  site before re-deploying.

The shift here: "define success criteria" became "run this command, and here is what failure looks like." A goal lives in the model's intentions. A gate is a thing that exits non-zero. Only one of them works when nobody's watching. If your repo has no smoke test, that's the first thing to build, before any rules file, because a rule without a mechanism is an aspiration.

5. The rule Karpathy's set doesn't have: a correction loop

This is the real difference, and it's structural. The four-rule file is static. Nothing in it gets smarter when something goes wrong. The earned system has one habit at its core: every correction becomes a one-line standing rule, and stale rules get deleted.

Mine accumulate in a traps section. A few real entries:

## Traps (each one cost a real outage or a real hour)
- Inline <script> strings: escape "</script>" as "<\/script>"
  or the parser ends the block early.
- String.replace with content as the replacement: use the
  function form. "$&" or "$1" inside the content corrupts output.
- Scheduled serverless functions: never name them *-background.*;
  the platform silently drops the schedule.
- Stagger animations written to nth-child(4): children 5+ never
  appear. Fix the generic rule, not the one instance.

One line each: trap, symptom, fix. Every line earned its place by costing something. That's why nobody else's file can substitute for it. Karpathy's four rules describe everyone's first month with these tools. The trap ledger describes your repo's sixth month, and it compounds while the generic file just sits there.

The deletion half matters as much as the addition half. When you migrate off a tool, finish the migration in your CLAUDE.md too. I do a read-through about quarterly: anything that's no longer true gets cut, because a file the model has stopped trusting is worse than a short one. The skills, rules, memory breakdown covers where overflow should go when the file wants to grow past ~200 lines.

The rubric

  • Day one, empty repo: paste in the four principles. They're the floor, and the floor beats dirt.
  • First time you correct the model: start your earned-rules section that same day. One line, with the why.
  • Month two: any generic principle now covered by two or three specific rules gets deleted. The file should be getting more specific, not longer.
  • Mature repo, autonomous runs: the principles live in your review habits and your gates. The file holds mechanisms, traps, and surface maps. Keep Karpathy's four taped to the monitor for you, not for the model.

The same arc applies beyond code, for what it's worth. If you're running your whole business on an AI stack, the asset isn't the tool list, it's the accumulated, specific, checkable operating rules you've earned. That argument, applied to marketing a small business for about $20 a month, is most of what The $20 Dollar Agency is about. Search it on Amazon Kindle if that's your situation.

Related reading

Fact-check notes and sources

  • The four guidelines, their wording, and their provenance from Andrej Karpathy's public post on LLM coding failures: multica-ai/andrej-karpathy-skills on GitHub. The repo ships them as a CLAUDE.md, a Claude Code plugin, and a Cursor rules variant.
  • Anthropic's own guidance on CLAUDE.md content and keeping it concise and specific: Claude Code: Best practices for agentic coding.
  • The trap examples, smoke-gate pattern, and dual-surface rule are from my own production sites and deploy logs; specifics like the -background scheduling behavior are Netlify-specific and verified against my own function deployments.

This post is informational, not consulting advice. Mentions of Andrej Karpathy, the multica-ai repository, Anthropic, Claude Code, and Cursor are nominative fair use. No affiliation or endorsement is implied.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026