Mastering Context Engineering for Claude Code: A Practical Guide to Optimizing LLM Outputs

In the realm of AI-driven coding tools like Claude Code, the days of blaming “AI slop” on the model itself are long gone. Today, the onus falls squarely on the user—and the single most controllable input in these black-box systems is context. So, how do we optimize context to unlock the full potential of large language models (LLMs) like Claude Code? This comprehensive guide will break down everything you need to know about context engineering, from the basics of what context is to advanced strategies for maximizing token efficiency and avoiding common pitfalls.

What Is Context in Claude Code (and Why Does It Matter)?

Before diving into optimization tactics, it’s critical to define what we mean by “context” in the context of LLMs like Claude Code. Simply put, context encompasses every piece of information you provide to the LLM when sending a message. This includes:

  • The core prompt you craft
  • System prompts that guide the model’s behavior
  • Metadata attached to your requests
  • All previous messages in the conversation thread
  • The LLM’s generated responses, thinking processes, and tool calls
  • Every other bit of information that shapes the model’s understanding of your request

LLMs operate within fixed context windows, and Claude Code is no exception—its context window caps out at 200,000 tokens. At first glance, 200k tokens might seem like an enormous amount of space, but in practice, it fills up far faster than most users realize. Running the /context command in Claude Code reveals the harsh reality: 22.5% of the window is reserved as a buffer, and 10.2% is already occupied by default system prompts. After accounting for MCP servers, subagents, and built-in rules, users are left with just 120,000 tokens to work with.

Worse yet, LLM performance degrades as the context window fills—even before hitting the hard limit. The model struggles to track details, maintain consistency, and generate accurate outputs as irrelevant or low-signal tokens pile up. This means that optimizing context isn’t just about staying under the token limit; it’s about curating the “optimal set of tokens” to maximize the quality of the LLM’s outputs.

The 80/20 Rule: Master the Basics First

Like most things in tech (and life), the 80/20 rule applies to “vibe coding” with Claude Code. You can get 80% of the way to optimal performance by simply installing Claude Code and nailing three foundational steps:

1. Upgrade to the Max Plan

First and foremost, run the /upgrade command to unlock Claude Code’s Max Plan. This isn’t a luxury—it’s a necessity. The Max Plan grants access to the full range of features and token allocations needed to leverage context effectively, and skimping here will limit your ability to implement even basic optimization strategies.

2. Switch to Opus 4.5

Next, use the /model command to set your model to Opus 4.5. Opus is Anthropic’s most powerful model, and version 4.5 offers significant improvements in context retention, code accuracy, and problem-solving capabilities. While cheaper models like Sonnet have their place (more on that later), Opus 4.5 is the gold standard for core coding tasks that demand precision.

3. Initialize Your Project with /init

Finally, run the /init command to create a dedicated file that helps Claude Code understand your project’s setup. This file should include key details like:

  • Project architecture (e.g., frontend/backend stack, database choices)
  • Coding standards and style guides your team follows
  • Existing dependencies and version requirements
  • High-level project goals and milestones

This initial setup ensures that Claude Code starts with a clear baseline understanding of your project, reducing ambiguity and cutting down on the need for repetitive clarifications later.

Beyond the Basics: Generic (But Critical) Best Practices

Once you’ve nailed the three core steps above, the generic advice you’ve likely heard about LLM prompting holds true—because it works. Here’s how to apply it to Claude Code:

  • 「Start in Plan Mode」: Use Shift + Tab to switch to plan mode before diving into coding tasks. Plan mode encourages the model to outline steps, identify potential roadblocks, and align with your objectives before writing a single line of code.
  • 「Force Clarification」: Ask Claude Code to clarify ambiguity by posing targeted questions about your plan. Don’t let vague requests lead to vague outputs—push the model to dig deeper into edge cases, requirements, and expectations.
  • 「Execute and Refine」: Once the plan is drafted, execute it step-by-step, then refine it repeatedly. Even the best initial plans have gaps, and iterative refinement ensures that the model stays aligned with your goals as the project evolves.

It’s tempting to jump into flashy features like subagents, custom commands, hooks, and multi-agent orchestration—and we’ll cover those later—but mastering the basics is far more important. Complex setups won’t fix a poorly structured prompt or a lack of clear objectives; solid foundational habits will.

How to Structure Conversations for Optimal Context

The way you frame your conversations with Claude Code has a direct impact on context quality. The key principle here is: 「treat each new conversation as a single objective, and stick to that objective’s scope」.

Define Clear Thread Goals

Every new thread in Claude Code should have a specific, narrow goal. Examples of effective thread objectives include:

  • “I need to fix the authentication bug in my Node.js API that’s causing 401 errors for valid users”
  • “I want to build a responsive checkout form for my React e-commerce app that integrates with Stripe”
  • “I need to refactor the legacy Python data processing script to improve performance and readability”

For brand-new projects, your objective can be broader (e.g., “I want to build a full-stack SaaS app for project management”), but broader scopes require more extensive planning and refinement. The wider the scope, the more room there is for misinterpretation—so you’ll need to compensate with extra detail.

Plan Extensively (Then Refine Even More)

For narrow objectives, spend 10–15 minutes planning; for broader project goals, allocate 30+ minutes to planning. The goal is to eliminate ambiguity at every turn, and that means:

  • Asking Claude Code to review your plan multiple times
  • Requesting feedback on architecture choices (e.g., “Is a microservices approach overkill for this small app?”)
  • Vetting best practices (e.g., “Are there security risks in using JWT tokens without refresh tokens here?”)
  • Assessing production readiness (e.g., “What steps are missing to deploy this to AWS?”)
  • Outlining a testing strategy (e.g., “Should I use unit tests, integration tests, or both for this feature?”)

Push Claude Code to ask questions until it’s practically asking for trivial details—this means it’s fully aligned with your vision and has no room for misinterpretation. The more detail you provide (or extract via clarification), the better the model’s outputs will be.

When (and How) to Reset Your Context

Knowing when to keep a conversation going and when to hit reset is one of the most underrated context engineering skills. Here’s a clear framework to follow:

When to Keep the Thread Going

If your workflow is on track and you’re working on tasks that are similar or relevant to what’s already in the context window—keep going! There’s no need to restart a thread if the model is generating high-quality outputs and the context remains focused on your objective.

When to Compact Context

If you’re approaching the context window limit, run the /compact command to free up space. The compact feature condenses previous messages and responses into a concise summary, removing redundant or low-signal tokens while preserving key information. This is exactly what the 22.5% reserved buffer is for—Claude Code can also compact context automatically if you prefer hands-off management.

For added visibility into your context usage, I’ve built a custom Claude Code plugin that displays real-time metrics on how full your context window is. This tool takes the guesswork out of knowing when to compact or reset.

When to Rewind or Start Over (And What to Avoid)

The worst mistake you can make is continuing in a thread where the model has already produced poor outputs. If you find yourself stuck in a loop of:

  • “That’s terrible—please fix this bug” → low-quality AI slop →
  • “This is even worse—what were you thinking?” → even worse slop

…it’s time to hit reset. Continuing down this path pollutes the context window with negative feedback and irrelevant outputs, making it harder (not easier) for the model to recover. Instead, choose one of two options:

Option 1: Use /rewind

The /rewind command lets you roll back the conversation to a point where things were going well—e.g., right after the model drafted a solid plan, or after it successfully implemented a small part of your feature. This preserves the relevant context while cutting out the messy, unproductive back-and-forth.

Option 2: Start a New Thread with /new

If rewinding isn’t enough (or if the thread is already too cluttered), use /new to start a fresh conversation. Take your original prompt, refine it to address what went wrong the first time, and explicitly include warnings about what the model should avoid. For example:

  • Original prompt: “Build a login form with React”
  • Refined prompt: “Build a responsive React login form with email/password validation. Do NOT use inline styles (I need CSS modules), and ensure the form handles error states for invalid email formats and incorrect passwords. Also, avoid hardcoding API endpoints—use environment variables instead.”

This explicit guidance eliminates the ambiguity that led to poor outputs in the first place, and a fresh context window ensures the model isn’t weighed down by previous mistakes.

Avoid the Complexity Trap: Focus on High-Signal Tokens

If you’re active on X (formerly Twitter), you’ve likely seen endless posts about flashy Claude Code setups: MCP servers, subagents, custom skills, and more. It’s easy to feel like you’re falling behind if you’re not using every feature—but this is a trap.

Anthropic’s core guidance for context engineering is simple: 「find the smallest possible set of high-signal tokens」. Flooding your context window with low-signal information (e.g., irrelevant data from MCP servers) doesn’t just waste tokens—it also drives up costs and degrades the model’s performance.

That said, complex features do have their place—when used strategically. Let’s break down how to leverage MCP servers, subagents, and skills to boost context quality without cluttering your window.

Using MCP Servers for Targeted, High-Value Context

MCP (Model Context Protocol) servers are third-party tools that let Claude Code pull in external context: think documentation, GitHub code snippets, Linear tickets, Figma designs, and more. When MCP servers first launched, they were hyped as a game-changer—but users quickly realized that many of them eat up tokens at an alarming rate, often for little return.

My Go-To MCP Servers (And Why They Work)

After extensive testing, I’ve narrowed down my MCP server stack to three tools that deliver consistent, high-signal value:

  1. 「exa.ai」: Web search for AI agents. Exa.ai specializes in finding up-to-date, relevant information for coding tasks—far better than generic web search for technical queries.
  2. 「context7」: Real-time documentation for AI agents. Context7 aggregates official docs, community tutorials, and best practices for popular libraries and frameworks, cutting down on the time I’d spend digging through docs myself.
  3. 「grep.app」: GitHub code search for AI agents. Grep.app lets Claude Code find real-world examples of how developers implement specific features or fix bugs in open-source repos—an invaluable resource for troubleshooting or learning best practices.

The “Just-in-Time” Context Strategy

I use these MCP servers to implement what Anthropic calls a “just-in-time” context strategy: the agent uses tools to find information only when it’s needed, rather than loading all possible context upfront. For example, if I ask Claude Code to “implement OAuth2 authentication with NextAuth.js,” the model will trigger exa.ai to pull the latest NextAuth.js docs, grep.app to find working examples of OAuth2 setups in Next.js repos, and context7 to verify best practices—all in real time.

This approach ensures that the context window only includes information relevant to the current task, rather than cluttering it with generic docs or irrelevant code snippets. That said, even just-in-time MCP usage eats up tokens—so how do we make it more efficient? The answer: subagents.

Using Subagents to Save Context (and Money)

Claude Code lets you create subagents—child instances of the main Claude Code agent—that operate independently of your primary thread. You can view your subagents with the /agents command, and each one has its own system prompts, trigger rules, and access to tools (including MCP servers).

Key Benefits of Subagents

Subagents offer two game-changing advantages for context engineering:

  1. 「Separate Context Windows」: Each subagent has its own context window, which means token-heavy operations (like research via MCP servers) don’t eat into your main agent’s 120k token allocation.
  2. 「Flexible Model Selection」: Subagents can use cheaper models (e.g., Sonnet instead of Opus) for tasks that don’t require Opus’s precision—slashing costs while maintaining quality.

How to Use Subagents for Efficient Context Management

The core idea is simple: use subagents to handle token-expensive, low-precision tasks (like research) and have them return a concise, high-signal summary to the main agent. This way, the main agent only receives a value-dense snapshot of the research—rather than the hundreds (or thousands) of tokens of raw data.

My “Librarian” Subagent Workflow

My favorite implementation of this strategy is a custom “Librarian” subagent that I’ve built to handle research tasks. Here’s how it works:

  1. I configure the Librarian subagent to use Sonnet (instead of Opus) to keep costs low.
  2. I grant it access to my three MCP servers (exa.ai, context7, grep.app) and set system prompts that guide it to:

    • Search for official documentation and trusted community resources
    • Filter out irrelevant or outdated information
    • Summarize key findings in 200–300 tokens (max)
    • Highlight potential pitfalls or best practices
  3. When I need research done, I ask my main Opus agent: “Use the Librarian to research how to implement [X] with [Y] library, then build [Z].”
  4. The main agent triggers the Librarian, which runs its MCP-powered research and returns a condensed summary.
  5. The main agent uses this summary to build the feature—without ever cluttering its context window with raw research data.

This workflow is a win-win: it preserves the main agent’s context for high-value coding tasks, and it saves money by using a cheaper model for research. I’ve shared the full configuration details for the Librarian subagent in a separate post (link included at the end of this guide) for anyone looking to replicate it.

Using Skills to Pull in Specialized Context (Without Bloat)

Skills are the reverse of subagents: instead of delegating tasks to a separate agent with its own context, you bring specialized, pre-defined context into your main agent’s window—only when you need it.

What Are Skills, Exactly?

Skills are pre-written prompt chunks that Claude Code can pull into the context window on demand. Each skill is tailored to a specific task or domain and includes dos, don’ts, best practices, and guidelines for the model to follow. For example, Claude Code’s built-in “Frontend Designer” skill includes a detailed prompt that outlines:

  • UI/UX best practices for frontend design
  • Common mistakes to avoid (e.g., poor accessibility, cluttered layouts)
  • Brand alignment guidelines (if configured)
  • Responsive design requirements for mobile/desktop

How to Use Skills Effectively

The beauty of skills is that they add context only when needed—so you’re not wasting tokens on frontend design guidelines when you’re working on a backend API. To use a skill:

  1. Identify the task that requires specialized guidance (e.g., designing a checkout page).
  2. Trigger the relevant skill (via the /skills command or automatic triggering if configured).
  3. Claude Code pulls the skill’s prompt chunk into the context window, uses it to guide its output, and then the skill’s context is only retained if it’s relevant to subsequent tasks (or compacted if not).

For example, when I ask Claude Code to “design a responsive checkout page for my e-commerce app,” the model automatically triggers the Frontend Designer skill. The skill’s prompt chunk is added to the context window, ensuring the model follows UI/UX best practices for checkout pages—without me having to write those guidelines into every prompt.