Skip to content

Instantly share code, notes, and snippets.

@renezander030
Last active August 2, 2026 09:07
Show Gist options
  • Select an option

  • Save renezander030/2898eb5f0100688f4197b5e493e156a2 to your computer and use it in GitHub Desktop.

Select an option

Save renezander030/2898eb5f0100688f4197b5e493e156a2 to your computer and use it in GitHub Desktop.
Karpathy-skills CLAUDE.md v2 — extending forrestchang's pattern with lessons from building draftcat

Karpathy-skills CLAUDE.md v2 — extending forrestchang's pattern with lessons from building draftcat

Karpathy-skills CLAUDE.md v2 — extending forrestchang's pattern with lessons from building draftcat

Karpathy-skills CLAUDE.md v2 — extending forrestchang's pattern with lessons from building draftcat

Karpathy-skills CLAUDE.md v2 — extending forrestchang's pattern with lessons from building draftcat

Karpathy-skills CLAUDE.md v2 — extending forrestchang's pattern with lessons from building draftcat

CLAUDE.md

Updated 2026-04-22 — ten rules for Claude Code: four for edit-time, six for runtime.

Forrestchang's andrej-karpathy-skills CLAUDE.md is four rules aimed at the moment Claude is writing code. They work. What they don't cover is the moment Claude is running. Once a Claude-driven pipeline goes to production, a different failure mode shows up: confident outputs, silent budget overruns, destructive side-effects, prompt injection via user input.

These six extension rules are what I shipped into draftcat — a Go pipeline engine where Claude drafts, classifies, and summarizes, but never executes. Deterministic code does. The rules below are what made that claim stick.

Merge with your own project rules. Tradeoff: these bias toward caution over autonomy.

Forrestchang's four (edit-time) — unchanged

  1. Think Before Coding — state assumptions, surface tradeoffs, ask when unclear.
  2. Simplicity First — minimum code, no speculative abstractions.
  3. Surgical Changes — touch only what the task requires.
  4. Goal-Driven Execution — define success criteria, loop until verified.

(Full text: forrestchang/andrej-karpathy-skills/CLAUDE.md.)

Six runtime rules — lessons from draftcat

5. Deterministic First

Claude is for judgment calls. Plain code does everything else.

Fetching, filtering, routing, persisting, dispatching — none of it is a language task. Don't ask the model to "decide if we should retry" when a status code already answers. Use the model for: classification, drafting, summarization, extraction from unstructured text. That's the whole list.

The failure mode without this rule: the model makes a routing decision one week, a different routing decision the next, and you've reinvented flaky if-else at $0.003/token.

6. Declare Budgets, Halt On Breach

No silent overruns. Ever.

Every AI step runs under a token budget: per-step, per-pipeline, per-day. Exceeding any of the three halts the pipeline immediately, logs the breach, and surfaces it to the operator. Budgets live in config, not in prompts.

budgets:
  per_step_tokens: 2048
  per_pipeline_tokens: 10000
  per_day_tokens: 100000

The failure mode without this rule: a runaway loop burns $40 overnight and you find out from the invoice.

7. Human-In-The-Loop Is A First-Class Step Type

Label destructive actions. Require approval. No exceptions via flags.

Anything touching the outside world — sending an email, updating a CRM, posting a message — is an approval step, not an ai step. The approval is routed to an operator channel (Slack, Telegram, whatever) with approve/edit/reject controls. The pipeline blocks until a decision is recorded.

- name: approve-send
  type: approval
  mode: hitl
  channel: telegram

The failure mode without this rule: a hallucinated follow-up email goes to a real customer.

8. Validate AI Output Against A Schema

Unstructured strings don't belong in deterministic downstream code.

Every AI step declares an output schema. The runtime rejects anything that doesn't match — missing fields, wrong types, out-of-range numbers. Rejected outputs trigger a retry (under budget) or halt.

output_schema:
  type: object
  required: [match, reason, score]
  properties:
    match:  { type: boolean }
    reason: { type: string, maxLength: 280 }
    score:  { type: integer, minimum: 0, maximum: 100 }

The failure mode without this rule: a boolean comes back as the string "maybe" and a downstream if branches the wrong way.

For generated React and Next.js code, I use agentproof-react as a small deterministic review gate before shipping.

9. Sanitize Operator Input Before It Reaches A Prompt

User-supplied text is not trusted.

Before any operator or external input enters a prompt, strip role markers (system:, assistant:, <|im_start|> variants), enforce length limits, and normalize markdown so formatting can't break prompt boundaries. This is prompt-injection defense, not input validation — the goal is to stop an attacker from pivoting the model mid-run.

10. Log Rejections Silently

Don't narrate to the attacker.

When input is rejected for sanitization or schema violations, log internally — never echo the rejection reason back to the source. A detailed error message is a free signal that tells the attacker which pattern to try next.

The "working if" test

The full ten rules are working if:

  • Diffs are smaller and more targeted (rules 1–4).
  • Pipeline runs have predictable token costs (rule 6).
  • No AI output ever reaches a production side-effect without a human approval record (rule 7).
  • Downstream code never branches on a malformed AI response (rule 8).
  • Operator-channel logs show silent rejections rather than echoed errors (rules 9–10).

If even one of those is failing, the rule isn't enforced — it's aspirational.

Related gists


If this saved you time, follow @renezander030 — weekly gists on Claude Code, MCP, and automation. The runtime discipline above lives in draftcat (Go, MIT).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment