2233 words
11 minutes
Claude Code Mastery (P2): Context, Commands & Modes — How to Teach the Agent About Your Project and Control It

In Part 1, you learned that AI Agents operate through an Agentic Loop: LLM thinks → calls tools → receives results → repeats. But what does the LLM think based on? The answer: Context — all the information the agent has within a session.

Context determines whether Claude is smart or clueless, whether it follows your conventions or makes things up. This Part 2 explains the context mechanism under the hood, how you control it via CLAUDE.md and Memory, every command you need to know, and when to use which mode.

Context Window — Short-Term Memory#

How It Works Internally#

Every time the LLM is invoked within the Agentic Loop, it receives the entire conversation as input:

graph TD
    subgraph CW["Context Window (~200K tokens)"]
        direction TB
        A["System Prompt<br/><i>Claude Code's internal instructions</i>"]
        B["CLAUDE.md Contents<br/><i>Project instructions - all levels</i>"]
        C["Memory Files<br/><i>Learnings from previous sessions</i>"]
        D["Rules Files<br/><i>.claude/rules/*.md</i>"]
        E["Tool Definitions<br/><i>JSON schema for each tool</i>"]
        F["Message 1: User → Your first prompt"]
        G["Message 2: Assistant → Response + tool calls"]
        H["Message 3: Tool result → Results"]
        I["..."]
        J["Message N: User → Your latest prompt"]
    end

    A --> B --> C --> D --> E --> F --> G --> H --> I --> J

    style A fill:#4a90d9,color:#fff
    style B fill:#50b356,color:#fff
    style C fill:#50b356,color:#fff
    style D fill:#50b356,color:#fff
    style E fill:#4a90d9,color:#fff
    style F fill:#f5a623,color:#fff
    style G fill:#f5a623,color:#fff
    style H fill:#f5a623,color:#fff
    style I fill:#f5a623,color:#fff
    style J fill:#f5a623,color:#fff

All of this combined = the context window. Claude Code has a context window of roughly 200K tokens (approximately ~150K words or ~500 pages of text).

Compaction — When Context Gets Full#

As the conversation grows longer, the context approaches its limit. Claude Code automatically compacts — summarizing old messages to free up space:

graph LR
    subgraph BEFORE["Before Compaction"]
        direction TB
        B1["System + CLAUDE.md +<br/>Memory + Rules + Tool defs"]
        B2["100 detailed messages:<br/>reading files, editing,<br/>building, discussing..."]
        B3["New prompt"]
        B1 ~~~ B2 ~~~ B3
    end

    BEFORE -- "Compact" --> AFTER

    subgraph AFTER["After Compaction"]
        direction TB
        A1["System + CLAUDE.md +<br/>Memory + Rules + Tool defs<br/><b>RELOADED intact</b>"]
        A2["1 summary message:<br/><i>Implemented cancel order<br/>endpoint, fixed build error...</i>"]
        A3["New prompt"]
        A1 ~~~ A2 ~~~ A3
    end

    style B1 fill:#50b356,color:#fff
    style B2 fill:#e74c3c,color:#fff
    style B3 fill:#f5a623,color:#fff
    style A1 fill:#50b356,color:#fff
    style A2 fill:#f5a623,color:#fff
    style A3 fill:#f5a623,color:#fff

The key point: CLAUDE.md, Memory, and Rules are always reloaded intact after compaction. Conversation history gets summarized (details are lost). This is why you must put important information in CLAUDE.md, not just mention it in chat.

graph TD
    subgraph SURVIVE["Survives Intact"]
        S1["CLAUDE.md<br/><i>all levels</i>"]
        S2["Memory files<br/><i>~/.claude/projects/.../memory/</i>"]
        S3[".claude/rules/*.md"]
    end

    subgraph SUMMARIZED["Summarized - Details Lost"]
        M1["Contents of files read"]
        M2["Terminal output"]
        M3["Previous discussions"]
    end

    subgraph LOST["Lost Entirely"]
        L1["Nuance in your wording"]
        L2["Small details not captured<br/>in the summary"]
    end

    style SURVIVE fill:#d4edda,stroke:#28a745
    style SUMMARIZED fill:#fff3cd,stroke:#ffc107
    style LOST fill:#f8d7da,stroke:#dc3545
    style S1 fill:#28a745,color:#fff
    style S2 fill:#28a745,color:#fff
    style S3 fill:#28a745,color:#fff
    style M1 fill:#ffc107,color:#000
    style M2 fill:#ffc107,color:#000
    style M3 fill:#ffc107,color:#000
    style L1 fill:#dc3545,color:#fff
    style L2 fill:#dc3545,color:#fff
TIP

When a session runs long and Claude starts “forgetting” instructions, type /compact to trigger manual compaction. Claude will summarize the history and reload CLAUDE.md — like a memory “refresh”.

Context Loading — Load Order at Session Start#

flowchart TD
    A["Session starts"] --> B["Load System Prompt"]
    B --> C["Load User CLAUDE.md\n~/.claude/CLAUDE.md"]
    C --> D["Load Project CLAUDE.md\n./CLAUDE.md"]
    D --> E["Load Folder CLAUDE.md\nsubdirectory (if exists)"]
    E --> F["Load Memory Files"]
    F --> G["Load Tool Definitions"]
    G --> H["✅ Ready for prompt"]

CLAUDE.md — Project DNA#

CLAUDE.md is the single most important file when working with Claude Code. It serves as system instructions for your project, read at the start of every session and after every compaction.

Three Levels of CLAUDE.md#

graph TD
    A["User-level<br/><b>~/.claude/CLAUDE.md</b><br/><i>All projects, only you</i><br/>Not committed to git"]
    B["Project-level<br/><b>&lt;repo&gt;/CLAUDE.md</b><br/><i>This project, whole team</i><br/>Committed to git"]
    C["Folder-level<br/><b>&lt;repo&gt;/src/Api/CLAUDE.md</b><br/><i>Specific folder</i><br/>Committed to git"]

    A -->|"Personal preferences"| MERGED["Claude reads ALL<br/>at once"]
    B -->|"Team conventions"| MERGED
    C -->|"Specific rules"| MERGED

    style A fill:#9b59b6,color:#fff
    style B fill:#3498db,color:#fff
    style C fill:#1abc9c,color:#fff
    style MERGED fill:#f39c12,color:#fff
LevelFileScopeCommit to git?
User~/.claude/CLAUDE.mdAll projects, only youNo
Project<repo>/CLAUDE.mdThis project, whole teamYes
Folder<repo>/src/Api/CLAUDE.mdSpecific folderYes

User-Level CLAUDE.md#

Things you want Claude to always do, regardless of the project:

# ~/.claude/CLAUDE.md

## Preferences
- Communicate in Vietnamese
- Never commit automatically, always ask first
- When creating PRs, write descriptions in English
- Prefer dotnet CLI over Visual Studio

## My Context
- Senior .NET developer, 5 years of experience
- Team of 8, using GitHub Actions + AKS
- Currently migrating from monolith to microservices

Project-Level CLAUDE.md#

Things the entire team needs Claude to know. Committed to git so everyone shares the same context:

# CLAUDE.md — OrderService

## Project Overview
.NET 8 microservice handling order lifecycle.
MassTransit for messaging, EF Core for data access.

## Commands
| Command | Purpose |
|---------|---------|
| `dotnet build src/OrderService` | Build |
| `dotnet test tests/OrderService.Tests` | Run tests |
| `dotnet ef migrations add <Name> --project src/OrderService.Data` | New migration |
| `docker compose up -d` | Start local infra (RabbitMQ, SQL Server) |

## Architecture
- CQRS via MediatR: Commands/Queries in Features/
- MassTransit State Machines for order flow (StateMachines/)
- EF Core Code-First, DbContext in Data/
- Result<T> pattern, no throwing exceptions for business logic

## Code Conventions
- Feature folder structure: Features/{Name}/Command.cs, Handler.cs, Validator.cs
- record types for DTOs, Commands, Queries, Events
- PascalCase methods, _camelCase private fields
- FluentValidation for request validation
- xUnit + FluentAssertions for testing

## Important Patterns
- Order states: Submitted → Accepted → Processing → Completed/Cancelled
- Saga pattern: OrderStateMachine handles multi-step workflows
- Outbox pattern: reliable messaging via MassTransit Outbox
- Idempotency: every consumer must handle duplicate messages

Folder-Level CLAUDE.md#

When Claude is working inside the StateMachines/ folder, it automatically picks up the CLAUDE.md there:

# src/OrderService/StateMachines/CLAUDE.md

## MassTransit State Machine Rules
- Inherit from MassTransitStateMachine<TState>
- States: public State property
- Events: public Event<T> property
- Transitions: During(state, When(event).Then(...).TransitionTo(next))

## IMPORTANT
- DO NOT use async void in activities
- State instance MUST have a CorrelationId (Guid)
- Always handle Faulted state
- Test with InMemoryTestHarness
WARNING

The more specific your CLAUDE.md is, the more accurately Claude follows your conventions from the very first attempt. Don’t write vague things like “write clean code”. Be specific: “use record types for DTOs”, “Resultinstead of throwing exceptions”.

Memory — Remembering Across Sessions#

The Problem#

You tell Claude: “This project uses SQL Server, not PostgreSQL.” Claude understands and writes correct code. The next day you start a new session — Claude has forgotten everything.

Memory solves this by persisting information to files on disk.

How It Works#

Memory files live at ~/.claude/projects/<project-hash>/memory/. Each file has frontmatter:

---
name: database-config
description: Database configuration per service
type: project
---

OrderService uses SQL Server (Azure SQL).
PaymentService uses PostgreSQL.
NotificationService uses MongoDB.
Connection strings in appsettings.{Environment}.json.

Claude reads all memory files at the start of every session, just like CLAUDE.md.

Saving Memory#

Method 1: Tell Claude directly

"Remember that OrderService uses SQL Server, PaymentService uses PostgreSQL"

Claude creates a memory file automatically.

Method 2: Claude figures it out (Auto Memory) When you confirm a pattern multiple times, Claude may save it on its own. For example: you keep correcting Claude when it uses var → Claude saves a memory note “team uses explicit types, no var”.

Method 3: Forgetting

"Forget the rule about using var — the team has switched back to allowing var"

Memory vs CLAUDE.md — When to Use Which?#

CLAUDE.mdMemory
ScopeWhole team (committed to git)Only you (personal)
ContentConventions, architecture, commandsPatterns you’ve discovered, personal decisions
Example”Use FluentValidation""User XuanPD prefers explicit types”
ManagementEdit the file manuallyTell Claude to remember/forget

.claude/rules/ — Topic-Based Rules#

Rules work like CLAUDE.md but are organized by topic:

.claude/rules/
  ef-core.md       → "AsNoTracking for read-only queries, explicit Include()"
  masstransit.md   → "Consumers must be idempotent, always handle Faulted"
  react.md         → "TanStack Query for server state, Zustand for client"
  testing.md       → "xUnit + FluentAssertions, Arrange-Act-Assert"
  git.md           → "Conventional commits: feat(order): description"

Commands — Controlling Claude Code#

Essential Commands#

CommandFunctionWhen to Use
/helpView all commandsWhen you forget a command
/modelSwitch model (Opus/Sonnet/Haiku)When you need a different model
/fastToggle fast modeSimple tasks, need speed
/compactCompress conversation historyLong session, Claude “forgets” context
/clearWipe all context, start freshSwitching to a completely different task
/planEnter Plan ModeComplex tasks, need to design first
/costView token cost of current sessionTracking expenses
/effortAdjust thinking levelTasks needing deeper/faster reasoning

Advanced Commands#

CommandFunctionExample
/initAuto-generate CLAUDE.md for projectFirst-time setup
/add-dirAdd another directory to context/add-dir ../shared-lib when you need a reference
/agentsManage SubAgentsView, create, edit custom agents
/mcpManage MCP serversView, add MCP servers
/resumeResume a previous sessionContinue unfinished work
/configConfigure settingsMemory, thinking mode, theme
/renameName the session/rename order-cancel-feature

Special Characters in Prompts#

@ — Reference a file/directory:

"Explain @src/OrderService/OrderStateMachine.cs"

Claude automatically reads the file — no need to say “read file X first”.

# — Reference a file (older syntax):

"Refactor OrdersController following the pattern in #ProductsController.cs"

Both syntaxes automatically include the CLAUDE.md from the referenced file’s directory.

Modes — Different Ways of Thinking#

Normal Mode (default)#

Claude receives the prompt, thinks, and acts immediately. Full tool access.

Use for: bug fixes, feature implementation, small refactors, Q&A.

Plan Mode#

Problem it solves: Complex tasks where Claude acts immediately → goes in the wrong direction → has to undo → wastes time and tokens.

How it works internally: Claude is only allowed to call read-only tools (Read, Glob, Grep). No Edit, Write, or Bash. It analyzes the codebase, lists files that need changes, and proposes an execution order.

/plan Add a caching layer for OrderService queries

Claude (Plan Mode):
1. [Read] Read OrdersController → sees IMediator injection
2. [Grep] Find query handlers → 5 handlers, all query DB directly
3. [Read] Read appsettings.json → no Redis config yet
4. [Glob] Find existing cache patterns → none found

Proposed plan:
Step 1: Add Redis package + configuration
Step 2: Create ICacheService interface + RedisCacheService
Step 3: Create CachingBehavior (MediatR pipeline behavior)
Step 4: Decorate query handlers that need caching
Step 5: Add cache invalidation in command handlers
Step 6: Update docker-compose.yml to add Redis container
Estimated files: 8 new files, 6 modified files

Risks:
- Cache invalidation for OrderStateMachine state changes
- Race condition when multiple instances invalidate simultaneously

You review the plan, provide feedback (“add distributed lock for invalidation”), then approve → Claude switches to Normal Mode and implements.

Enter Plan Mode: /plan or Shift+Tab (cycle through modes) or --permission-mode plan at startup.

TIP

/plan accepts a direct argument: /plan migrate from Dapper to EF Core. No need to enter plan mode first and then type.

Fast Mode#

Mechanism: Uses Sonnet model (faster, cheaper) instead of Opus. Significantly faster output, suitable for simple tasks. Toggle with /fast.

Use for: scaffolding boilerplate, fixing typos, adding imports, generating DTOs, writing docs.

Do NOT use for: debugging race conditions, state machine logic, architectural decisions.

Auto-Accept Mode#

How it works: Claude auto-approves all file edits without asking you. Still asks for destructive Bash commands.

Use for: when you trust Claude with the current task and want a faster workflow.

Enter: Shift+Tab from Normal Mode.

Headless Mode — Claude in CI/CD#

How it works: Claude runs non-interactively, receives prompts via the -p flag, and returns results via stdout.

# Code review in GitHub Actions
claude -p "Review diff of this PR. Check for:
  1. N+1 queries in EF Core
  2. Missing null checks
  3. Idempotency in MassTransit consumers
  Output as PR comment markdown" \
  --output-format json \
  --allowedTools "Read,Grep,Glob,Bash(dotnet build*)"

Application for .NET/React teams:

# .github/workflows/ai-review.yml
name: AI Code Review
on: [pull_request]
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Claude Review
        run: |
          claude -p "Review the PR diff. Focus on:
            - EF Core query performance
            - MassTransit consumer idempotency
            - React useEffect dependency arrays
            - Missing FluentValidation rules
            Format as markdown checklist." \
            --allowedTools "Read,Grep,Glob"
WARNING

Headless mode requires --allowedTools to restrict permissions. Never allow Edit/Write in a CI/CD pipeline unless you have an approval workflow in place.

Which Mode to Choose?#

flowchart TD
    Start["Which mode?"] --> Q1{"CI/CD pipeline?"}
    Q1 -->|"Yes"| Headless["🖥️ Headless Mode\nclaude --headless"]
    Q1 -->|"No"| Q2{"Complex task\n>5 files?"}
    Q2 -->|"Yes"| Plan["📋 Plan Mode\nShift+Tab"]
    Q2 -->|"No"| Q3{"Simple task\ntypo, import?"}
    Q3 -->|"Yes"| Fast["⚡ Fast Mode\n/fast"]
    Q3 -->|"No"| Q4{"Fully trust\nClaude?"}
    Q4 -->|"Yes"| Auto["🟢 Auto-Accept\nShift+A"]
    Q4 -->|"No"| Normal["👤 Normal Mode"]

Hands-on: Setting Up Context for Your Project#

Step 1: Create CLAUDE.md#

# Option A: Let Claude auto-generate it
claude /init

# Option B: Create manually (recommended for teams)
# Create a CLAUDE.md file at the project root using the template from the CLAUDE.md section above

Step 2: Create Folder-Level CLAUDE.md#

For the most complex parts of your project:

# EF Core data layer
cat > src/OrderService/Data/CLAUDE.md << 'EOF'
## EF Core Rules
- AsNoTracking for read-only queries
- Explicit Include(), no lazy loading
- Separate migrations project
- Always check generated SQL (dotnet ef migrations script)
EOF

# React frontend
cat > frontend/src/CLAUDE.md << 'EOF'
## React Rules
- Function components only
- TanStack Query for server state
- Zustand for client state
- Tailwind CSS utility classes
EOF

Step 3: Set Up Rules#

mkdir -p .claude/rules
cat > .claude/rules/git.md << 'EOF'
## Git Conventions
- Conventional commits: feat(scope): description
- Scope = service name: feat(order): add cancel endpoint
- PR title < 70 chars
- PR description in English, include testing checklist
EOF

Step 4: Test It#

claude "Add a GET /api/orders/active endpoint.
Only return orders with status Submitted or Accepted.
Include pagination. Verify the build."

Claude will read CLAUDE.md → understand the CQRS + Resultpattern → implement following conventions → build passes. If Claude gets a convention wrong, update CLAUDE.md rather than just telling it in chat.

Part 2 Summary#

ConceptHow It Works InternallyHow to Optimize
Context Window~200K tokens, holds all info in a sessionPut important things in CLAUDE.md (survives compaction)
CompactionSummarizes old messages, reloads CLAUDE.md/Memory/compact when Claude “forgets”
CLAUDE.md3 levels: User > Project > Folder, read every sessionBe specific, keep updated, commit to git
MemoryFiles on disk, persists across sessionsTell Claude to remember important patterns
RulesLike CLAUDE.md, organized by topicSeparate rules for EF Core, React, testing, git
Plan ModeRead-only tools, analyze before coding/plan for tasks touching >5 files
Headless ModeNon-interactive, used in CI/CD--allowedTools to restrict permissions

Part 3 will dive into Tools, Hooks & Quality Gates — how the agent takes action and how you automate quality control.


Claude Code Mastery Series — P3: Tools, Hooks & Quality Gates up next.

Claude Code Mastery (P2): Context, Commands & Modes — How to Teach the Agent About Your Project and Control It
https://www.devwithxuan.com/en/posts/claude-code-context-commands/en/
Author
XuanPD
Published at
2026-03-12
Share:

Subscribe to Newsletter

Get notified when I publish new posts. No spam, unsubscribe anytime.

Comments