The New Rules of Context Engineering for Claude 5 Generation Models
Anthropic just dropped a bombshell: they removed over 80% of Claude Code's system prompt for the newer Claude 5 generation models — and nothing broke. No measurable loss on coding evaluations. Zero regression.
This isn't just a fun fact. It signals a fundamental shift in how we should interact with AI coding agents. The old rules of prompt engineering — the careful guardrails, repeated instructions, and rigid constraints — are now actively holding back these more capable models.
This post breaks down the six new rules from Anthropic's official guide by Thariq Shihipar, explains why each matters, how to apply it, and gives you a concrete example so you can update your workflow today.
The Core Insight: Overconstraining Hurts Performance#
Before we dive into the rules, let's understand the problem. In the old days, Claude Code's system prompt and CLAUDE.md files contained detailed rules for every possible scenario. But as models got smarter, these rules started conflicting with each other.
Imagine you're a skilled chef, and someone hands you a 50-page recipe manual where page 12 says "season generously" and page 37 says "NEVER add salt." You'd spend more time reconciling contradictions than actually cooking.
That's what was happening to Claude. Instructions like "leave documentation as appropriate" clashed with "DO NOT add comments." The model could usually figure out the right intent — but it had to waste thinking time resolving these conflicts instead of solving your actual problem.
The fix? Trust the model's judgement. Remove the constraints that were designed to prevent worst cases in older, less capable models, and let the newer models use their own reasoning.
Rule 1: Let Claude Use Judgement (Instead of Giving Rigid Rules)#
Why This Rule Exists#
Older models needed strict guardrails because, without them, they made poor decisions. For example, they'd generate excessive, unhelpful comments or accidentally delete important files. So we wrote rules like:
"In code: default to writing no comments. Never write multi-paragraph
docstrings or multi-line comment blocks"
The problem? This rule is sometimes wrong. What if the code is genuinely complex and needs a multi-line explanation? What if the user's project uses extensive documentation by convention? The rigid rule overrides the correct decision.
How To Apply It#
Instead of writing absolute rules ("NEVER do X", "ALWAYS do Y"), write principles that describe the desired outcome and trust the model to figure out when to apply them.
Example#
Old approach (rigid rule):
# CLAUDE.md
- NEVER write comments in code
- ALWAYS use single-line functions where possible
- DO NOT create files longer than 200 lines
New approach (principle-based guidance):
# CLAUDE.md
- Write code that reads like the surrounding code: match its
comment density, naming, and idiom.
- Prefer conciseness, but not at the cost of clarity.
The new approach gives Claude room to make the right call depending on context. If the existing codebase has detailed JSDoc comments on every function, Claude will follow that pattern. If it's a minimal codebase with zero comments, Claude will stay minimal too.
When Rigid Rules Still Make Sense#
There are still cases where hard rules are appropriate — usually around safety boundaries:
# Still good as a hard rule:
- Never commit .env files or credentials to git
- Always validate user input at API boundaries
The distinction: use hard rules for safety invariants that should never have exceptions. Use principles for style and approach decisions that depend on context.
Rule 2: Design Interfaces (Instead of Giving Examples)#
Why This Rule Exists#
With older models, the top recommendation was: "Give Claude examples of what you want." You'd show it an example API call, an example test, an example refactoring — and it would pattern-match from there.
But with Claude 5 generation models, examples actually constrain the model to a narrow exploration space. It treats your example as a template and sticks too close to it, even when a better approach exists.
How To Apply It#
Instead of showing examples of usage, design better interfaces — the tools, parameters, and data structures that Claude interacts with. A well-designed interface communicates intent through its shape.
Example#
Old approach (example-based):
# CLAUDE.md
When using the Todo tool, here's an example:
- TodoWrite({items: [{id: "1", content: "Fix the bug", status: "pending"}]})
- After starting work: TodoWrite({items: [{id: "1", content: "Fix the bug", status: "in_progress"}]})
- After finishing: TodoWrite({items: [{id: "1", content: "Fix the bug", status: "completed"}]})
New approach (interface design):
// The tool definition itself communicates usage through its shape
interface TodoItem {
id: string
content: string
status: "pending" | "in_progress" | "completed" // enum hints at lifecycle
}
// Brief behavioral note in the tool description:
// "Keep at most one item in 'in_progress' at a time."
By making status an enum with clear lifecycle states (pending -> in_progress -> completed), Claude understands the intended workflow without needing a step-by-step example. The interface is the documentation.
Practical Tip#
When you're designing tools or functions that Claude will use, ask yourself: "If someone saw only the type signature and parameter names, would they understand how to use this correctly?" If yes, you don't need examples.
Rule 3: Use Progressive Disclosure (Instead of Putting Everything Upfront)#
Why This Rule Exists#
Previously, everything Claude might need was crammed into the system prompt. Code review instructions, verification steps, deployment procedures — all loaded at the start of every conversation, just in case.
This is like reading an entire textbook before answering a single homework question. Most of that information is irrelevant to the current task, but it's consuming precious context window space and potentially confusing the model.
How To Apply It#
Structure your instructions in layers. Put only the essentials upfront, and let Claude load additional context when it actually needs it.
Example#
Old approach (everything upfront):
# CLAUDE.md (2000 lines)
## Project Overview
...
## Code Review Process
When reviewing code, check for:
1. Security vulnerabilities (SQL injection, XSS, ...)
2. Performance issues (N+1 queries, ...)
3. Test coverage (every public method, ...)
...50 more lines of review instructions...
## Deployment Process
When deploying:
1. Run the full test suite...
2. Check staging environment...
...40 more lines...
## Database Migrations
When creating migrations:
...30 more lines...
New approach (progressive disclosure):
# CLAUDE.md (focused and brief)
## Project Overview
Next.js app with PostgreSQL. See /docs/architecture.md for details.
## Gotchas
- All types live in `src/types/index.ts` (not co-located)
- Use `pnpm` not `npm` — the lockfile matters
- The `auth` middleware must run before any API handler
## Skills
- Code review: .claude/skills/code-review.md
- Deployment: .claude/skills/deployment.md
- Database migrations: .claude/skills/migrations.md
Then create separate skill files that Claude loads on demand:
# .claude/skills/code-review.md
Loaded when: Claude is asked to review code
## Review Checklist
1. Security: check for injection, XSS...
2. Performance: check for N+1 queries...
...
# .claude/skills/deployment.md
Loaded when: Claude is asked about deployment
## Steps
1. Run full test suite...
...
Claude Code is smart enough to load the right skill at the right time. Your CLAUDE.md stays clean and focused on what matters for every interaction.
The Deferred Loading Pattern#
This same principle applies to tools. Claude Code now uses "deferred loading" for some tools — it knows they exist by name, but only loads their full definitions (via ToolSearch) when it actually needs them. This keeps the context lean while still giving access to a wide range of capabilities. (For more on how Claude Code's architecture handles lazy loading, see Claude Code: Architecture Deep Dive.)
Think of it like lazy imports in JavaScript:
// Old: import everything upfront
import { reviewCode, deploy, migrate, format, lint } from './tools'
// New: import only when needed
const reviewCode = () => import('./tools/review')
Rule 4: Use Simple Tool Descriptions (Instead of Repeating Yourself)#
Why This Rule Exists#
With older models, you sometimes had to repeat instructions multiple times in different locations — in the system prompt, in the tool description, and again in a skill file — just to make sure the model followed them. You'd even strategically place critical instructions at the end of the context window because models weighted recent tokens more heavily.
Claude 5 generation models don't need this. They read and follow instructions reliably regardless of where they appear. Repetition now just wastes tokens and can introduce contradictions when one copy gets updated but the other doesn't.
How To Apply It#
Put instructions about a tool in that tool's description. Don't repeat them in the system prompt. One canonical location per instruction.
Example#
Old approach (redundant instructions):
# System prompt
When using the Bash tool, always quote file paths that contain spaces.
Never use `rm -rf` without user confirmation.
...
# Also in a skill file
Remember: when running bash commands, always quote paths with spaces.
Never use rm -rf without asking first.
...
# Also in the tool description
Bash: Executes commands. Quote paths with spaces. No rm -rf without confirmation.
Three places saying the same thing. When you update one, you'll forget the others. They'll drift apart.
New approach (single source of truth):
# Tool description for Bash
Executes a given bash command and returns its output.
- Always quote file paths that contain spaces with double quotes.
- Never use destructive commands (rm -rf, git reset --hard)
without explicit user confirmation.
That's it. The system prompt doesn't mention quoting paths or rm -rf at all. The instruction lives with the tool.
Practical Rule of Thumb#
If you find yourself writing the same instruction in more than one place, delete all but one copy. Pick the most natural home for it (usually the tool description or the relevant skill file) and put it there.
Rule 5: Use Auto-Memory (Instead of Manual CLAUDE.md Entries)#
Why This Rule Exists#
Previously, the recommended way to teach Claude about your preferences was to manually save things to CLAUDE.md files using the # hotkey. This worked, but it was manual work that most people forgot to do consistently. Important context got lost between sessions.
Claude 5 generation models now automatically detect and save memories that are relevant to your work and preferences. It notices patterns in how you work — your preferred testing style, naming conventions, review habits — and remembers them across sessions.
How To Apply It#
Instead of manually curating your CLAUDE.md with every preference, let Claude learn from your interactions naturally. Focus your manual entries on the things auto-memory can't figure out on its own: project-specific gotchas, team conventions, and non-obvious architectural decisions.
Example#
Old approach (manual memory management):
# CLAUDE.md (manually maintained)
## My Preferences
- I prefer functional React components with hooks
- Use named exports, not default exports
- I like tests colocated with source files
- Use `describe`/`it` not `test`
- I prefer explicit return types on public functions
New approach (auto-memory + focused CLAUDE.md):
# CLAUDE.md (only non-obvious things)
## Gotchas
- The `useAuth` hook must be called inside `AuthProvider`
— it silently returns null otherwise (no error thrown)
- Run `make prisma_gen` after any schema change, even in dev
- The CI pipeline rejects PRs that increase bundle size by >5%
The preferences (functional components, named exports, test structure) get learned automatically from your code and feedback. Your CLAUDE.md is freed up for the things Claude genuinely can't learn by reading your codebase — the traps, the tribal knowledge, the "I spent 3 hours debugging this" lessons.
What Auto-Memory Captures#
Auto-memory picks up on:
- User preferences — how you like code written, structured, and organized
- Feedback patterns — things you've corrected ("don't do X") or confirmed ("yes, exactly like that")
- Project context — ongoing initiatives, deadlines, team agreements
- External references — where to find things in external systems
You can still explicitly tell Claude to remember something — but auto-memory means you no longer need to manually maintain these preferences in your CLAUDE.md file.
Rule 6: Use Rich References (Instead of Simple Specs)#
Why This Rule Exists#
Older workflows relied on simple markdown plan files to communicate what you wanted built. You'd write a plain-text spec describing the feature, maybe with some bullet points, and hope Claude interpreted it correctly.
Claude 5 generation models can handle much richer reference material. They can work from HTML mockups, test suites, code from other projects, and even structured rubrics. The richer your reference, the better the output.
How To Apply It#
Instead of describing what you want in prose, show it. Use code, mockups, tests, or existing implementations as your specification. Code is unambiguous in a way that natural language never is.
Example#
Old approach (prose spec):
## Feature: User Profile Page
- Should display user avatar, name, and bio
- Should have an edit button that opens a modal
- The modal should have form fields for name and bio
- Save button should call PUT /api/users/:id
- Show a success toast after saving
New approach (code as spec):
Option A — Provide an HTML mockup:
<!-- mockup.html — give this to Claude as a reference -->
<div class="profile-card">
<img src="/avatar.jpg" class="w-16 h-16 rounded-full" />
<h2 class="text-xl font-bold">Jane Smith</h2>
<p class="text-gray-600">Full-stack developer who loves TypeScript</p>
<button class="btn-primary">Edit Profile</button>
</div>
Option B — Point to an existing implementation to port:
Port the UserProfile component from our mobile app (`/mobile/src/screens/Profile.tsx`)
to the web app. Same behavior, adapted for React DOM instead of React Native.
Why Code References Work Better#
Code is Claude's native language. When you give it an HTML mockup, it sees the precise layout, spacing, and structure you want. When you give it existing code to port, it understands the patterns and edge cases already handled. You could also provide a test suite as a spec — Claude would know exactly what behavior to implement with zero ambiguity.
A prose description like "display user avatar" leaves dozens of decisions unspecified (size? shape? fallback? loading state?). A code reference answers all of them implicitly.
Putting It All Together: A Before/After#
Here's what applying all six rules looks like in practice:
| Aspect | Old Approach | New Approach |
|---|---|---|
| Rules | Hundreds of specific rules and constraints | Brief principles; trust model judgement |
| Examples | Detailed step-by-step usage examples | Well-designed interfaces that communicate intent |
| Context Loading | Everything loaded upfront, always | Progressive disclosure via skills and deferred tools |
| Repetition | Same rule in 3+ locations for emphasis | Single source of truth in the most natural location |
| CLAUDE.md | Central repository of everything (2000+ lines) | Lightweight gotchas + auto-memory for preferences |
| Specifications | Prose descriptions in markdown | Code references: HTML mockups, test suites, existing implementations |
Quick Start: Simplifying Your Setup#
If you're using Claude Code today and want to apply these rules, here's a practical starting point:
Step 1: Audit your CLAUDE.md. Remove anything that:
- States the obvious (things Claude can figure out by reading your files)
- Repeats instructions already in tool descriptions
- Contains rigid rules that should be principles
Step 2: Extract skills. Move specialized instructions (code review checklists, deployment procedures) into separate skill files under .claude/skills/.
Step 3: Upgrade your specs. Next time you ask Claude to build something, try giving it a test file or HTML mockup instead of a prose description.
Step 4: Trust the model. When you catch yourself writing "NEVER" or "ALWAYS" in your instructions, ask: "Is this a safety invariant, or am I just anxious?" If it's anxiety, rewrite it as a principle.
Step 5: Run /doctor. Claude Code's new /doctor command will automatically analyze your skills and CLAUDE.md files and suggest simplifications for newer models.
The Bigger Picture#
These six rules all point in the same direction: as models get more capable, your job shifts from controlling them to collaborating with them.
It's the difference between micromanaging a junior developer (here are your exact steps, don't deviate) and working with a senior colleague (here's the goal, here are the constraints, use your judgement on the details).
The models haven't just gotten better at code. They've gotten better at understanding intent, resolving ambiguity, and applying judgement. Your context engineering should evolve to match — less controlling, more empowering. Less instruction, more interface. Less repetition, more trust.
The payoff is real: leaner context means faster responses, fewer token costs, and better outputs. The model spends its thinking on your problem, not on reconciling your contradictions.