How the Karpathy Guidelines Prevent Over-Abstraction of Single-Use Code
The Karpathy guidelines explicitly prohibit creating abstractions for code that will only be used once, mandating inline implementations until actual duplication emerges.
The forrestchang/andrej-karpathy-skills repository encodes Andrej Karpathy's coding philosophy into concrete rules for LLM-assisted development. Among these principles, the stance against over-abstraction of single-use code represents a deliberate architectural decision to prioritize readability and simplicity over premature generalization.
The Rule Against Over-Abstraction of Single-Use Code
The prohibition appears in the "Simplicity First" section of both primary documentation files. In CLAUDE.md at line 22, the rule "No abstractions for single-use code" appears directly after the admonition to avoid unnecessary features. This file serves as the central behavioral guide for LLM-assisted coding within the repository.
The same guidance is echoed in skills/karpathy-guidelines/SKILL.md at line 28, where the bullet point "No abstractions for single-use code" is listed among the simplicity rules. This skill definition file allows the guidelines to be reused across different contexts while maintaining the same strict stance on abstraction.
Three Core Principles Behind the Guideline
This architectural stance operates through three specific mandates that govern when to abstract:
Write only what is required. If functionality will be invoked a single time, implement it inline rather than extracting it into a generic helper. This eliminates the cognitive overhead of navigating unnecessary indirection.
Avoid premature generalization. Introducing abstractions before concrete needs appear adds cognitive load, maintenance burden, and hidden coupling. The guidelines treat speculative reuse as a form of over-engineering.
Encourage refactoring only after duplication emerges. When the same logic truly repeats across different contexts, extraction into a shared component becomes permissible—but only after the duplication is evident and the abstraction is justified by actual usage patterns.
Code Examples: Over-Abstraction vs. Inline Implementation
Consider a scenario where you need to normalize text within a single processing function.
The discouraged approach creates a generic utility that serves only one call site:
def normalize_text(text: str) -> str:
# Generic utility that could be reused elsewhere
return text.strip().lower()
def process_user_input(raw: str) -> str:
# Uses the generic normalizer even though it's only needed here
cleaned = normalize_text(raw)
return f"Processed: {cleaned}"
The recommended approach keeps the logic inline, eliminating the unnecessary abstraction layer:
def process_user_input(raw: str) -> str:
# Inline, single-use normalization
cleaned = raw.strip().lower()
return f"Processed: {cleaned}"
If the normalization logic later needs to be shared across multiple modules, you can refactor it into a dedicated function at that point—fulfilling the "only after duplication" guideline.
Summary
- Explicit prohibition: Both
CLAUDE.md(line 22) andSKILL.md(line 28) contain the rule "No abstractions for single-use code" within their simplicity sections. - Inline first: Single-use functionality should be implemented directly at the call site without extraction into helper functions.
- Wait for duplication: Only create shared abstractions after the same logic appears in multiple places.
- Repository context: These guidelines live in the
forrestchang/andrej-karpathy-skillsrepository, designed to govern LLM-assisted coding workflows according to Karpathy's philosophy.
Frequently Asked Questions
When should I extract code into a reusable function?
You should only extract code into a shared abstraction after the same logic appears in multiple locations and the duplication becomes evident. According to the guidelines in CLAUDE.md and SKILL.md, premature extraction creates unnecessary cognitive load and coupling that outweighs the benefits of reuse.
Does this guideline mean I should never write utility functions?
No, utility functions are appropriate when they serve multiple call sites. The rule specifically targets single-use code—functionality invoked only once within the entire codebase. If a helper function genuinely eliminates duplication across modules, it aligns with the guidelines' intent to reduce repetition.
How do I distinguish between single-use code and potentially reusable code?
Ask whether the logic is needed in exactly one context or if it's genuinely domain-agnostic. If the code contains business logic specific to a single workflow, keep it inline. If it represents a general pattern that has already appeared twice, consider extraction according to the principle of refactoring only after duplication emerges.
What if I anticipate the code will be reused in future features?
The guidelines explicitly reject speculative abstraction. Future reuse is not justification for early extraction; you should refactor only when the second usage actually materializes. This prevents the maintenance burden of unused generic interfaces and keeps the codebase minimal.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →