Please πŸ–±οΈ here for Github Blogs

Context Engineering for Claude Code

  • June 15, 2026
Table of Contents

What Is Context Engineering

  • The practice of deliberately designing, structuring and optimizing context provided to an LLM to produce more accurate, reliable outputs.
  • It’s the natural next level of prompt engineering
  • While Prompt engineering: writing LLM instructions, Context engineering: manages entire context state β€” system prompts, tools, MCP, data sources, conversation history
  • Model has a limited attention span and Every token depletes the attention budget.
  • As context grows, recall accuracy decreases -> this is also called Context Rot
  • Guiding principle: Smallest possible set of high-signal tokens that maximize likelihood of desired outcome (https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)

How Coding Agents Consume Context (Claude Code)

CLAUDE.md β€” Per-Session Foundation

  • Loaded at every session start - seems like being injected directly into system prompt. Root level CLAUDE.md - They are not evicted or lazily loaded when not needed.

  •   [SYSTEM PROMPT]
      You are Claude...
      (tool instructions, safety rules, etc.)
    
      [PROJECT CONTEXT]
      Contents of CLAUDE.md
    
      [CONVERSATION]
      User: ...
      Assistant: ...
    
  • The context space occupied/Cost induced by CLAUDE.md is fixed - whether you use the session to write 1 single prompt or many. So keep it small and applicable to all prompts Not all prompts require all that info.

  • Every token competes for attention on every user turn

  • Anthropic guidance: for every line ask “would the agent make a mistake without this?” If not, delete it (https://docs.anthropic.com/en/docs/claude-code/overview)

  • Ancestor CLAUDE.md files (above working dir): Claude walks UP the directory tree, loading every CLAUDE.md and CLAUDE.local.md found. All are concatenated into context (additive, not replaced), ordered from root downward. So instructions closer to your working directory get read last (higher priority).

  • Subdirectory CLAUDE.md files (below working dir): Not loaded at session start. They are lazy-loaded on demand when Claude reads files in that subdirectory. This means you can place focused CLAUDE.md files in subdirectories and only pay the token cost when the agent actually works in those areas β€” useful for any multi-module project, not just monorepos.

  • Separate CLAUDE.local.md exists for local-only instructions (gitignored, not shared). It sits alongside CLAUDE.md and is appended after it within the same directory.

# CLAUDE.md
## Project Overview
Python monorepo, uv workspaces. Core packages: core/, api/, cli/.

## Conventions
- Use `pydantic` for data validation and settings, not dataclasses
- Always run `pytest` before committing

Path-Filtered Rules (.claude/rules/*.md)

  • Middle ground between CLAUDE.md (always loaded) and skills (user/model invoked)
  • Loads only when file path patterns match
  • Uses paths glob in frontmatter to control activation β€” the filename is just a label, not the trigger:

e.g. database.md

---
paths:
  - "**/*.sql"
  - "**/migrations/**"
  - "**/schema/**"
---

# Database Conventions

- Use `VARCHAR(255)` for short strings
- Always include `created_at` and `updated_at`

Example project tree:

project/
β”œβ”€β”€ CLAUDE.md                        # always loaded
β”œβ”€β”€ .claude/
β”‚   └── rules/
β”‚       β”œβ”€β”€ python-testing.md        # paths: ["**/test_*.py", "**/tests/**"]
β”‚       β”œβ”€β”€ database.md              # paths: ["**/*.sql", "**/migrations/**", "**/schema/**"]
β”‚       └── react-components.md      # paths: ["**/*.tsx", "**/*.jsx"]
β”‚
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ src/main.py
β”‚   β”œβ”€β”€ tests/test_api.py            # β†’ python-testing.md
β”‚   └── migrations/001_users.sql     # β†’ database.md
β”‚
β”œβ”€β”€ frontend/
β”‚   └── src/
β”‚       └── App.tsx                  # β†’ react-components.md
β”‚
└── database/
    └── schema/init.sql             # β†’ database.md
  • Claude Code reads the paths globs at session start and loads the rule body only when the agent’s file operations match one of them.
  • A file like frontend/tests/App.test.tsx can match multiple rules (react-components + python-testing), each adding its domain knowledge when needed β€” without polluting context during unrelated work.

Skills β€” On-Demand Workflows

  • Reusable instruction sets in ~/.claude/skills/<name>/SKILL.md (global) or .claude/skills/<name>/SKILL.md (project)
  • Progressive disclosure: agent loads name + description at startup, full content only when task detected (https://code.claude.com/docs/en/skills)
  • Keep under 500 lines β€” move reference material to supporting files (https://code.claude.com/docs/en/skills)
  • Frontmatter controls:
    • disable-model-invocation: true β€” manual-only (deploys, side effects), false allows invocation by intent by model.
    • user-invocable: false β€” model can invoke, hidden from slash menu, true allows manual invocation using slash command.
    • allowed-tools β€” auto-approve tools while skill is active
    • context: fork β€” run in isolated subagent, instructions vanish after completion
---
name: deploy
description: Deploy to staging or production
disable-model-invocation: true
context: fork
---

Subagents

  • Run in own context window with custom prompt, tool access, permissions, model (https://code.claude.com/docs/en/sub-agents)
  • Only result summary returns to parent (typically 1K-2K tokens)
  • Built-in: Explore (Haiku, read-only), Plan (inherits, read-only), General-purpose (all tools)
  • Defined in .claude/agents/ or ~/.claude/agents/
  • Key frontmatter: permissionMode, skills (preload), memory (cross-session), isolation: worktree, background: true
---
name: db-explorer
description: Explores database schemas using MCP
model: haiku
disallowedTools: Write, Edit, Bash
---

MCP Servers (Model Context Protocol)

  • Connect agent to external systems β€” databases, browsers, APIs, file systems (https://code.claude.com/docs/en/mcp)
  • In VS Code: added via claude mcp add in terminal, managed via /mcp in chat panel
  • Scoping: .mcp.json (project, shared), ~/.claude/settings.json (user, all projects), plugin .mcp.json (bundled)
  • Use allowedTools with wildcards (mcp__server__*) for permissions β€” narrower than bypassPermissions (https://code.claude.com/docs/en/permissions)

Hooks

  • Shell commands that fire automatically on lifecycle events (https://code.claude.com/docs/en/plugins-reference)
  • Defined in .claude/settings.json or ~/.claude/settings.json
  • Events: PreToolUse, PostToolUse, SessionStart, Stop, PreCompact, PostCompact
  • Run with user’s local privileges, receive event JSON on stdin
  • Use sparingly β€” every hook adds latency
{
  "PostToolUse": [
    {
      "matcher": "Write|Edit",
      "hooks": [{ "type": "command", "command": "npm run lint:fix" }]
    }
  ]
}

Plugins

  • Package skills, agents, hooks, MCP servers, executables into shareable bundles (https://code.claude.com/docs/en/plugins-reference)
  • In VS Code: managed through graphical /plugins interface
  • Common mistake: putting skills/agents/hooks inside .claude-plugin/ β€” only plugin.json goes there

VS Code Extension Settings

  • Under claudeCode.* namespace in VS Code settings (https://code.claude.com/docs/en/vs-code)
  • Key settings: initialPermissionMode, useTerminal, preferredLocation, respectGitIgnore, allowDangerouslySkipPermissions
  • Extension and CLI share config files and conversation history
  • Some features are CLI-only: ! bash shortcut, tab completion, claude mcp add

Configuration Layering (later overrides earlier)

  1. Managed settings (org defaults)
  2. ~/.claude/settings.json (user global)
  3. .claude/settings.json (project)
  4. .claude/settings.local.json (project-local, not committed)
  5. VS Code extension settings (claudeCode.*)
  6. CLI flags and env vars

Config is merged, not replaced β€” omitting a key inherits it from lower layers. Must explicitly set to false/null to disable.


What Goes Where: Choosing the Right Primitive

PrimitiveLoadedToken CostBest For
CLAUDE.mdEvery sessionFull content, alwaysProject conventions, critical constraints, build commands
Rules (.claude/rules/)On path matchContent only when matchedDeep domain knowledge, path-specific conventions
SkillsOn demandContent only when loadedDomain workflows, deploy, testing guides
SubagentsOn delegationSummary only (1K-2K tokens)Isolated tasks, parallel research, dangerous operations
PluginsOn enableCumulativeShareable packages, cross-project reuse
MCP serversOn config loadTool defs + responsesLive data access, external API integration
HooksOn lifecycle eventEvent + execution overheadAutomation, enforcement, observability
Permission rulesOn tool invocationNegligibleSecurity boundaries, blast radius reduction

CLAUDE.md β€” Do’s and Don’ts

Put in:

  • Project structure, language, framework β€” e.g. “Python monorepo with uv workspaces. Packages live in packages/, each with its own pyproject.toml.”
  • Critical conventions β€” error handling, naming, style β€” e.g. “Use pydantic for data validation, not dataclasses. Use snake_case for variables and PascalCase for classes.”
  • Exact build/test/run commands agent would guess wrong β€” e.g. “Run npm run dev for the dev server (not npm start, not node server.js). Run nox -s tests to test, not pytest.”
  • Architectural decisions and rationale β€” e.g. “PostgreSQL over MySQL for JSONB support. Rationale: flexible schema for event sourcing.”
  • Security constraints (“never commit secrets”) β€” e.g. “Never commit .env files. Never hardcode API keys. Run git secrets --scan before every commit.”
  • “Stuck record” β€” mistakes the team has actually made β€” e.g. “Don’t import from utils.py directly; import from the public API in __init__.py β€” this has caused circular imports three times.” or “We use pip not uv β€” every time someone runs uv add it breaks the lockfile.”

Leave out:

  • Lengthy reference tables, API docs, framework guides β€” e.g. don’t paste the entire numpy function reference or a SQL cheatsheet. Link to docs instead.
  • Rarely-needed workflows (infrequent deploys, migrations) β€” e.g. don’t include “how to do the quarterly database migration” or “how to rotate SSL certs.” Put these in a skill.
  • Instructions for specific subdirectories only β€” e.g. don’t document frontend testing conventions if the repo also has backend, data, infra code. Use path-filtered rules instead.
  • Verbose examples β€” e.g. don’t include a 30-line worked example of every function. One-line patterns are fine.

Keep under 100-150 lines. Anthropic’s own CLAUDE.md fits one screen.

Skills β€” Do’s and Don’ts

Put in: domain workflows, language conventions, integration guides, repetitive tasks, anything too long for CLAUDE.md, tasks needing tool auto-approval

Leave out: every-session content (put in CLAUDE.md), one-time instructions, security-sensitive auto-execution, content better as subagent prompt

Rule of thumb: if you describe the same workflow more than once a week, make it a skill.

Subagents β€” When to Create

Create when:

  • Task needs different model (Haiku for cheap exploration, Opus for hard reasoning)
  • Task needs restricted tools (read-only, MCP only, no Write/Edit)
  • Task benefits from isolation (clean context, no pollution)
  • Task is long-running (background: true)
  • Task is parallelizable (spawn multiple)
  • Task is dangerous (isolation: worktree)

Don’t create for: simple Read+Grep cycles, tasks needing full conversation history, cases where delegation overhead exceeds the work.

Name for routing, not marketing β€” description is how Claude decides to delegate.

MCP Servers β€” When to Connect

Use when: agent needs live data, integration has defined tool contract, external state changes, need permission gating.

Don’t use for: static reference data (load as instructions), built-in tool operations (Read, Grep, Bash), one-off scripts.

Worked Example β€” Python Web Service

project-root/
β”œβ”€β”€ CLAUDE.md                    # 60 lines: layout, build, test, conventions
β”œβ”€β”€ .claude/
β”‚   β”œβ”€β”€ settings.json            # Permissions, MCP, hooks
β”‚   β”œβ”€β”€ rules/postgres.md        # SQL schema conventions (applies to .sql/.py)
β”‚   β”œβ”€β”€ skills/deploy/SKILL.md   # /deploy: build, test, deploy
β”‚   β”œβ”€β”€ skills/code-review/      # Auto-invoked on PRs
β”‚   └── agents/db-explorer.md    # Read-only, Haiku, postgres MCP
└── .mcp.json                    # Shared MCP: postgres, bandit
  • CLAUDE.md: session essentials only
  • Postgres rule: path-filtered to database code
  • Skills: deploy + code-review load on demand
  • DB explorer subagent: isolated, Haiku, never touches filesystem
  • MCP: project-scoped, shared by team
  • Permission mode: acceptEdits in VS Code settings

Design Patterns

Just-in-Time Context Retrieval

  • Maintain lightweight identifiers (file paths, queries, MCP tool names) β€” fetch data only when needed
  • Mirrors human cognition: external organization + indexing, not memorization (https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)
  • CLAUDE.md = upfront orientation. Agent uses reads, searches, tool calls on demand
  • VS Code extension: @-mentions provide direct file context channel
  • Hybrid strategy: retrieve some data upfront (speed) + autonomous exploration (depth)

Context Compaction

Structured Note-Taking (Agentic Memory)

.claude/memory/architecture.md
  ## Decisions
  - 2026-06-14: Chose PostgreSQL over MySQL for JSONB support.
    Rationale: Flexible schema for event sourcing.

  ## Active Context
  - Implementing payment webhook handler (src/webhooks/payment.py)
  - Blocked on: webhook signature verification library

Sub-Agent Architecture

Progressive Disclosure vs Just-in-Time Retrieval

These two terms are often conflated but describe different scopes.

Just-in-time retrieval (broad pattern): defer loading any context β€” files, data, search results, tool output β€” until the agent actually needs it. Applies to everything the agent does: reading a source file only when it needs to understand a function, querying an API only when it needs live data, running a search only when it needs to find something.

Progressive disclosure (specific implementation of JIT): defer loading instruction content based on an initial metadata scan. The agent loads skill names and descriptions at startup (cheap), but waits to load the full skill body until a matching task is detected (https://code.claude.com/docs/en/skills). The agent knows the skill exists and what it does, but the 200 lines of instruction text don’t enter context until actually needed.

The distinction matters because they have different costs:

  • JIT for data (files, APIs) costs a tool invocation round-trip β€” generally worthwhile
  • Progressive disclosure for instructions costs nothing until triggered β€” strictly better than loading everything upfront
  • You can have JIT without progressive disclosure (reading a file on demand), but progressive disclosure is always a form of JIT applied to the instruction layer

Progressively disclosed skills are Claude Code’s answer to the “single responsibility” principle for context: each domain gets its own block of instructions that only loads when relevant, rather than one monolithic CLAUDE.md that pays the token cost on every turn.

Skills as Modular Context

  • CLAUDE.md loads every session and consumes attention budget from turn one
  • Defer detailed knowledge to skills that load only when task requires (https://code.claude.com/docs/en/skills)
  • Especially valuable for: deployment, language conventions, testing, API guides

Tool Design Principles

Layered Documentation Strategy

  • Combine llms.txt with MCP for two-tier context system (../mcp/)
  • llms.txt: orientation, summaries, key links (lightweight, always available)
  • llms-full.txt: comprehensive docs (loaded on demand)
  • MCP tools: live query, mutation, data access (gated by permissions)

Inverted Configuration

  • Intuition: pack everything into CLAUDE.md
  • Pattern: CLAUDE.md is the smallest file β€” only what’s needed every turn
  • Everything else β†’ skills (load on demand)
  • Team trimmed CLAUDE.md from 300 to 40 lines β†’ ~50% token drop on routine tasks
  • Every token in CLAUDE.md competes on every turn. Skill tokens only enter when relevant

Subagent Sandbox

  • Subagents as security boundaries, not just parallelism
  • disallowedTools: Write, Edit, Bash + Haiku model + MCP to production observability
  • Result: read-only investigator that literally cannot modify state
  • Machine-enforced by tool layer, not prompt instructions
  • Use case: on-call incident triage β€” query logs, inspect metrics, return diagnosis

Forked Skill Isolation

  • Unforked skills: instructions persist in main context until compaction or session end
  • context: fork: runs in isolated subagent, instructions vanish after execution
  • Main session retains only result summary β€” zero token overhead after completion
  • Use for: deploys, database migrations, API mutations β€” anything with side effects

Prohibitive Constraints

  • Positive instructions (“do this”) = heuristics, may or may not be followed
  • Prohibitive constraints (“never do this”) = unconditional rules, higher priority
  • “Never commit secrets” in CLAUDE.md > 50 lines of “how to write good code”
  • Self-writing technique: when Claude makes a mistake β†’ “Update CLAUDE.md so you never do this again” β€” results are “creepily accurate” (https://docs.anthropic.com/en/docs/claude-code/overview)
  • Combine with permission system for machine enforcement

Agentic Memory Journaling

  • Agent writes structured notes at session milestones (decisions, bugs, rationale)
  • Next session: reads notes during initialization
  • Over several sessions: agent builds its own institutional memory
  • Lifecycle: journal on session end, rehydrate on session start
  • memory field on subagents provides persistence layer

MCP as Contract Interface

  • Natural language = ambiguous. MCP tool definitions = exact (typed params, clear schemas, defined return types) (../mcp/)
  • Expose project operations as MCP tools rather than describing in prose
  • query(sql: string, params: object[]) cannot be misinterpreted like “query the database carefully”
  • Shifts context engineering from prose β†’ interface-based contracts
  • More predictable, easier to audit across sessions

Permission Configuration as Deployable Policy

  • Interactive prompts don’t scale across teams
  • Permission block in .claude/settings.json = machine-enforceable security policy
  • Version-controlled, reviewed in PRs, deployed with project
  • New team members clone repo and inherit policy β€” no tribal knowledge
{
  "permissions": { "allow": ["Read", "Edit", "Bash(git *)", "Bash(npm run *)"] }
}

Two-Phase Compaction

  • Compaction alone = lossy β€” summarizes history but doesn’t extract decisions or rationale
  • Phase 1: run compaction to free context window
  • Phase 2: agent writes structured notes capturing what future session needs to know
  • Compacted summary = short-term continuity. Notes = long-term memory across sessions

Design Considerations & Caveats

Context Rot and Lost-in-the-Middle

Tool Bloat

Permission Security

  • Permission rules enforced by tool layer, not model β€” prompt instructions alone can’t prevent tool access (https://code.claude.com/docs/en/permissions)
  • Deny-first precedence: matching deny blocks even if allow also matches
  • VS Code: mode controlled via claudeCode.initialPermissionMode, toggled per-session

Bash Command Pattern Fragility

  • Pattern matching on Bash command arguments is unreliable (https://code.claude.com/docs/en/permissions)
  • Bash(curl http://github.com *) won’t catch curl -X GET https://github.com/...
  • Don’t rely on Bash patterns for security β€” use tool-level denials and MCP scoping

Compaction Trade-Offs

Stale Retrieval

Skills Lifecycle Surprises

  • Skill content enters conversation once and stays until compaction removes it (https://code.claude.com/docs/en/skills)
  • Skills are for standing instructions (duration of task), not one-time steps
  • context: fork prevents pollution β€” use for deploys, commits, API mutations

CLI-Only Features in VS Code

  • VS Code extension panel lacks: ! bash shortcut, tab completion, claude mcp add (https://code.claude.com/docs/en/vs-code)
  • Workaround: run claude in integrated terminal instead of extension panel
  • Extension and CLI share config files and conversation history β€” seamless switching

Things One Might Miss

The Built-in IDE MCP Server

  • VS Code extension runs a local MCP server the CLI connects to automatically (https://code.claude.com/docs/en/vs-code)
  • Named ide, hidden from /mcp, nothing to configure
  • Exposes two tools: mcp__ide__getDiagnostics (VS Code errors/warnings, read-only) and mcp__ide__executeCode (Jupyter, requires confirmation)
  • Binds to 127.0.0.1 random port, fresh auth token per extension activation

CLAUDE.md Cascading in Monorepos

  • Root CLAUDE.md + subdirectory CLAUDE.md both load when working in subdirectory
  • Different from rules (path-filtered). Cascading is directory-based
  • Be deliberate about what goes at each level

@-mention as Context Channel

  • In VS Code: @filename attaches file context to prompt
  • Extension sees your editor selection automatically β€” indicated in prompt box footer
  • Alt+K: inserts @-mention with file path + line range
  • Different from CLI where context is via --file flags or conversation history

Plugin Agent Restrictions

Variable Substitution Timing

  • {env:VARIABLE} at runtime. {file:path} at config load
  • ${CLAUDE_PLUGIN_ROOT} / ${CLAUDE_PLUGIN_DATA} / ${CLAUDE_PROJECT_DIR} at plugin init (https://code.claude.com/docs/en/plugins-reference)
  • ${user_config.KEY} at plugin user config
  • Different evaluation times matter for debugging path issues in MCP/hooks

Config Merge (Not Replace) Gotcha

  • Omitting mcpServers in project config inherits from global config
  • Must explicitly false or null to disable
  • Common source of “why is this tool available?” confusion

CLI-Only: ! Bash Shortcut

  • Start message with ! to run shell command inline β€” output added as tool result
  • Not available in VS Code extension panel
  • Use integrated terminal if you need it

Self-Writing CLAUDE.md

  • Most powerful pattern: when Claude makes a mistake, tell it “Update CLAUDE.md”
  • Claude writes its own rules β€” described as “creepily accurate” (https://docs.anthropic.com/en/docs/claude-code/overview)
  • Compound effect over time: CLAUDE.md captures actual failure modes, not idealized conventions

References

Share :
comments powered by Disqus

Related Posts

Claude Agent SDK

Reference for building production AI agents with the Claude Agent SDK, the agent loop, sessions, tools, MCP, hooks, subagents, permissions, context management, structured output, streaming and deployment.

Read More

Model Context Protocol

Model Context Protocol - Notes, Best Practices, Design Patterns.

Read More

LiteLLM

LiteLLM explores lightweight large-language-model approaches focused on efficiency, deployability, and fast iterationβ€”ideal for on-device inference, constrained environments, and rapid prototyping.

Read More