Module 4: The agentic workflow: Explore → Plan → Code

Explore, Plan, and Code: Claude Code's three modes

Explore, Plan, and Code: Claude Code's three modes

Overview

Claude Code has three operating modes: Explore (read-only analysis), Plan (design without execution), and Agent/Code (full execution). Each mode exists for a specific reason, and knowing when to use which one transforms your productivity.

This capsule covers the three modes in depth: how to activate them, what each one does internally, when to pick one over another, and how to combine them in the Explore → Plan → Code cycle. It also covers Opus's effort level, which controls how much reasoning capacity Claude spends on each answer.

The difference between a casual Claude Code user and a professional comes down to this: the professional picks the right mode for each situation. The casual user always sits in Agent mode and hopes Claude guesses what they need.


Explore Mode

Explore is the read-only analysis mode. Claude reads files, analyzes dependencies, looks for patterns, and builds a mental map of your codebase — but it doesn't run commands and doesn't write code.

When to use Explore

  • Opening a project for the first time
  • Before implementing a complex feature
  • To understand code you didn't write
  • To find bugs with no risk of breaking anything
  • To analyze dependencies and architecture

How to activate Explore

There is no /explore command. You activate Explore through how you phrase your prompt. Claude picks up that you want analysis when you use verbs like "analyze", "explain", "find", "understand":

> Analyze the structure of this project. What framework is used?
  How are the files organized? Where does the main logic
  live?

Claude Code also has a built-in Explore subagent that automatically operates in read-only mode when Claude needs to investigate your codebase during a task. That subagent reads files and gathers information without modifying anything.

Basic example

> I'm starting to work on this project. Explain the overall
  structure: what technologies it uses, how the files are
  organized, and what the main entry points are.

Claude will:

  1. Read package.json, requirements.txt, or the equivalent
  2. Scan the directory structure
  3. Identify the framework and the main dependencies
  4. Find the entry points (main.py, index.ts, app.py)
  5. Give you a structured summary

Typical output:

The project uses FastAPI (Python 3.11) with this structure:

src/
├── main.py          → Entry point, configures the FastAPI app
├── routers/         → 4 routers: users, products, orders, auth
├── models/          → SQLAlchemy models (5 tables)
├── schemas/         → Pydantic schemas for validation
├── services/        → Business logic, separated from routers
└── tests/           → Pytest, 23 tests (18 passing, 5 skipped)

Main dependencies: FastAPI 0.109, SQLAlchemy 2.0, Pydantic v2
Database: PostgreSQL (via asyncpg)
Auth: JWT with python-jose

Intermediate example

> Analyze the current authentication system. I want to understand:
  1. How are the JWT tokens generated?
  2. Where are they validated?
  3. Are there refresh tokens?
  4. What middleware protects the routes?
  Don't make changes, just analyze.

Claude will read the relevant files and give you a full analysis of the auth flow, including any potential problems it spots.

Advanced example

> Analyze this project's dependencies. Identify:
  - Outdated dependencies (more than 6 months old)
  - Dependencies with known vulnerabilities
  - Dependencies that get imported but never used
  - Duplicate or redundant dependencies
  Report only, change nothing.

What Explore does NOT do

  • ❌ It doesn't run terminal commands
  • ❌ It doesn't modify files
  • ❌ It doesn't create new files
  • ❌ It doesn't install dependencies
  • ❌ It doesn't commit

That restriction is intentional. Explore is safe by design — you can use it on any codebase without risk.


Plan Mode

Plan is the design-without-execution mode. Claude analyzes your request, weighs the options, and produces an implementation plan you can review and approve before a single line of code runs.

When to use Plan

  • Before implementing complex features
  • Refactors that touch multiple files
  • Database migrations
  • Architecture changes
  • When you want to weigh options before committing

How to activate Plan

Use the /plan command:

/plan I need to add a caching layer to the API. Redis or
in-memory. Give me a full plan.

You can also activate it with explicit language:

> Design a plan to migrate the database from SQLite to PostgreSQL.
  Don't implement anything yet. I want to see the plan first.

Basic example

/plan Add pagination to every endpoint that returns a list.

Typical Plan output:

## Plan: Add pagination

### Files to modify:
1. src/schemas/pagination.py (CREATE) — Reusable pagination schema
2. src/routers/users.py (MODIFY) — Add offset/limit query params
3. src/routers/products.py (MODIFY) — Same
4. src/routers/orders.py (MODIFY) — Same
5. src/services/base.py (MODIFY) — Generic pagination method
6. tests/test_pagination.py (CREATE) — Tests for pagination

### Design:
- Generic `PaginatedResponse[T]` schema with items, total, offset, limit
- Query params: offset (default 0), limit (default 20, max 100)
- The service layer handles the SQL query with OFFSET/LIMIT
- Response includes metadata: total_count, has_more, next_offset

### Implementation order:
1. Pagination schema
2. Generic method in the service layer
3. Update the routers one by one
4. Tests

### Risks:
- Existing endpoints will change their response format (breaking change)
- You need a migration strategy for current clients

Shall I proceed with the implementation?

Intermediate example

/plan I want to refactor error handling. Right now every
router has its own try/catch. I want to centralize it. Give me the
options and your recommendation.

Claude will give you several options with pros and cons:

## Options for centralizing errors

### Option A: FastAPI exception handlers
- Register handlers for each exception type
- Pros: Native to FastAPI, well documented
- Cons: Less granular control per endpoint

### Option B: Custom middleware
- Middleware that catches every exception
- Pros: Total control, one single place
- Cons: Can hide errors during development

### Option C: Custom decorator (RECOMMENDED)
- An @handle_errors decorator wrapping each endpoint
- Pros: Explicit, easy to test, opt-in per endpoint
- Cons: Requires adding the decorator to every endpoint

### Recommendation: Option C
[Technical justification...]

Which one should I go with?

Advanced example

/plan I need to redesign the permissions system. Right now it's
role-based (admin/user). I need to migrate to granular RBAC with
per-resource permissions. The system has 4 models, 12 endpoints,
and 3 current roles. Full plan with a migration strategy.

What Plan does NOT do

  • ❌ It doesn't run the plan automatically
  • ❌ It doesn't modify files
  • ❌ It doesn't run commands
  • ❌ It doesn't make irreversible changes

Plan produces a document you review. Only when you say "go ahead" or "implement" does Claude switch to Agent mode.


Agent/Code Mode (default)

Agent is the full-execution mode. It's Claude Code's default — when you hand it a task without specifying a mode, it operates in Agent.

What Agent mode can do

  • ✅ Read project files
  • ✅ Write and modify files
  • ✅ Create new files
  • ✅ Run terminal commands (npm, pip, git, etc.)
  • ✅ Run tests
  • ✅ Install dependencies
  • ✅ Make commits

The permission system

Claude Code asks for confirmation before potentially destructive actions:

Claude wants to run: rm -rf node_modules && npm install
Allow? [y/n/always]

You can configure permissions in your CLAUDE.md or in settings to pre-approve certain actions (for instance, always allow npm test).

Basic example

> Create a GET /api/health endpoint that returns
  { "status": "ok", "timestamp": "..." }

Claude will:

  1. Identify the framework (FastAPI/Express/etc.)
  2. Find where the routers live
  3. Create the endpoint in the right format
  4. Run tests if there are any

Intermediate example

> The test test_create_user is failing with "IntegrityError:
  UNIQUE constraint failed: users.email". Fix it.

Claude will:

  1. Read the test
  2. Read the User model
  3. Spot that the test doesn't clean the database between runs
  4. Add a cleanup fixture or use a unique email per test
  5. Run the test to verify

Advanced example

> Implement the pagination plan we designed. Start with the
  generic schema and then update the users router. Run
  the tests after each change.

When to use Agent directly (without Explore/Plan)

You don't always need the full cycle. Going straight to Agent is right for:

  • Simple bug fixes ("the button doesn't work, fix it")
  • Mechanical tasks ("rename X to Y across every file")
  • Boilerplate generation ("create a User model with these fields")
  • Running commands ("run the tests and show me the results")

The Explore → Plan → Code cycle

The full flow

┌──────────┐     ┌──────────┐     ┌──────────┐
│ EXPLORE  │────▶│ PLAN     │────▶│ CODE     │
│ (read)   │     │ (design) │     │ (build)  │
└────┬─────┘     └────┬─────┘     └────┬─────┘
     │                │                │
     │                │                │
     └────────────────┴────────────────┘
                   ITERATE

The cycle isn't strictly linear. After Code, you can go back to Explore to verify. After Plan, you can go back to Explore to dig deeper. It's iterative.

Complete example: a new feature

Say you need to add email notifications to your API.

Step 1 — Explore:

> Analyze how emails are currently handled in this project.
  Is there an integration with an email service? Is there a
  message queue? Are there email templates?

Step 2 — Plan:

/plan Based on what you found, design an email notification
system. I need: a welcome email on signup, a password
reset email, and a purchase confirmation email. Give me the
plan with service options (SendGrid, SES,
Resend).

Step 3 — Code (incremental):

> Implement step 1 of the plan: the Resend integration
  and the base email-sending service.
> Now implement the welcome template and the signup
  trigger.
> Add tests for the email service.

Step 4 — Verify (back to Explore):

> Review everything we implemented. Are there edge cases we
  didn't cover? Do the tests cover the main scenarios?
  Is there any security problem?

Comparisons and decisions

Without a workflow vs with one

AspectWithout a workflowWith a workflow (E→P→C)
First prompt"Add auth to my app""Analyze how routes are currently handled"
ResultA generic implementation that may not fitAn implementation that respects the existing architecture
ErrorsYou find problems after implementingYou find problems before writing code
RefactoringFrequent — the first attempt is rarely rightMinimal — the plan already weighed the options
Total timeMore (because you redo work)Less (it's done right the first time)
Context windowFills up with failed attemptsGets used efficiently

Which variation of the cycle to use

SituationWorkflow
Complex new featureExplore → Plan → Code (full cycle)
Simple bug fixCode directly
Complex bug fixExplore → Code
RefactoringExplore → Plan → Code
New code in a familiar projectPlan → Code
Understanding somebody else's codebaseExplore (only)
Quick prototypeCode directly
MigrationExplore → Plan → Code → Explore (verify)

Effort Level

The effort level controls how much reasoning capacity the model spends on each answer. It shifts the balance between speed and depth.

Important: The available levels depend on the model. You set it with /effort, inside /model with the ← → arrows, in settings (effortLevel), or via an env var (CLAUDE_CODE_EFFORT_LEVEL).

Available levels per model

ModelLevelsDefault
Opus 5, Sonnet 5, Fable 5low, medium, high, xhigh, maxhigh (xhigh recommended for coding)
Haiku 4.5Not configurable—

Haiku 4.5 doesn't expose a configurable effort: if you set a level while on it, Claude Code simply ignores it.

Effort low    → Light reasoning, fast answers
Effort medium → Speed/depth balance (cost-sensitive)
Effort high   → Deep reasoning
Effort xhigh  → Very deep (Opus 5 default)
Effort max    → Maximum depth, no thinking-token cap (applies to the current session only)

When to use each level

LevelUse caseExample
lowDirect questions, mechanical edits"Rename getData to fetchData in this file"
mediumCost-sensitive work that can trade off some intelligence"Create a CRUD endpoint for products"
highThe minimum for intelligence-sensitive work"Refactor the auth middleware"
xhighRecommended for coding/agentic (Opus 5 default)"Design the permissions system for the API"
maxExhaustive reasoning — use with care (it can overthink)"Analyze every race condition in this system"

How it affects each mode

  • In Explore: More effort = deeper analysis, catches more patterns
  • In Plan: More effort = more options considered, better trade-offs
  • In Code: More effort = more robust code, better edge-case handling

A practical example

/plan Redesign the caching system. Right now it uses an in-memory
dictionary that doesn't survive restarts. I need to consider:
Redis, Memcached, and a file-based cache. Give me pros/cons for each
one for our case (API with 10K req/min, 3 instances).

With Opus at effort high (the default), Claude weighs several dimensions before answering.

At effort high (default), Claude will:

  • Analyze the current access patterns
  • Consider each option in detail
  • Evaluate the pros/cons specific to your case
  • Consider edge cases (cache stampede, invalidation, replication)
  • Give a recommendation with technical justification

At effort low, it would just give you a basic comparison table.

Fast Mode

On top of the effort level, Opus 5 supports fast mode — an optimization that generates output faster without switching models.

> /fast     ← Toggle on/off

Important: Fast mode uses the same Opus 5. It does NOT switch to Sonnet or any other model. It's Opus with output-speed optimization.

Fast mode is especially useful during the Code phase of the Explore - Plan - Code cycle, where you generate code iteratively and want faster feedback loops. For the Plan phase with deep analysis, consider turning fast mode off so Opus reasons at full depth.

Cycle phaseFast mode recommended
ExploreOFF (deep analysis)
PlanOFF (exhaustive reasoning)
Code (fast iteration)ON (implementation speed)
Code (complex task)OFF (maximum quality)

Common patterns

Pattern 1: "Explore first, always"

Before any significant task, run Explore. Even if you think you know the codebase. Claude can spot things you don't see:

> Before we start, analyze the current state of the payments module.
  Is there technical debt? Missing tests? Dead code?

Pattern 2: "Plan with options"

Don't ask for one plan. Ask for options:

/plan Give me 2-3 options for implementing the notification
system. Include pros, cons, and your recommendation.

Pattern 3: "Incremental code"

Don't ask for everything at once. Implement in steps:

> Implement only the model and the migrations. Nothing else for now.
> Now add the service with the business logic.
> Now the endpoints. Run tests afterward.

Pattern 4: "Verify loop"

After implementing, go back to Explore to verify:

> Review what we just implemented. Does it follow the pattern
  used in the rest of the project? Are there inconsistencies?

Pattern 5: "Tiered effort"

Start at low effort for simple tasks, raise it for complex ones:

# Simple task → Sonnet
/model sonnet
> Rename the file config.py to settings.py and update the imports.

# Complex task → Opus
/model opus
> Now refactor the configuration system to use Pydantic
  Settings with environment variable validation.

Pitfalls and edge cases

Pitfall 1: Using Agent mode for everything

The mistake: Giving implementation instructions without exploring first.

❌ "Add WebSockets to the app"

The problem: Claude doesn't know what infrastructure exists, what patterns are used, or what constraints there are. It'll implement something generic that probably won't fit.

The fix: Explore first.

✅ "Analyze the current API architecture. Is there any
   real-time system? Are there WebSockets, SSE, or long-polling?"

Pitfall 2: Plans that are too ambitious

The mistake: Asking for a plan that covers far too much scope.

❌ /plan Redesign the whole API to use microservices.

The problem: The plan will be shallow because the scope is enormous.

The fix: Scoped plans.

✅ /plan Design how to extract the payments module as an
   independent service. Just that module, not the whole API.

Pitfall 3: Not verifying after Code

The mistake: Assuming what Claude implemented is correct without reviewing it.

The fix: Always verify:

> Run all the tests.
> Check whether what you implemented follows the conventions in CLAUDE.md.
> Is there any edge case we didn't cover?

Pitfall 4: Ignoring the Plan output

The mistake: Saying "yes, implement it" without reading the plan.

The fix: Read the whole plan. Question decisions. Ask for alternatives. The plan is your chance to shape the solution before any code gets written.

Pitfall 5: Opus for everything

The mistake: Using Opus for trivial tasks.

The problem: Slower and more expensive answers with no benefit on simple tasks. It also burns more quota.

The fix: Use Sonnet for routine tasks and Opus for tasks that need deep reasoning. If you do use Opus, drop effort to low for the easier tasks.


Complete worked example

A real scenario: you add structured logging to an existing FastAPI project.

Phase 1: Explore

> Analyze how logging is currently handled in this project.
  Is any logger in use? Are there logs in the routers? In the
  services? Are errors logged? Give me a full report.

You discover the project uses print() statements scattered around, with no structured logging.

Phase 2: Plan

/plan I need to replace every print() with structured
logging. Requirements:
- JSON format for production
- Human-readable for development
- Request ID for traceability
- Log levels: DEBUG, INFO, WARNING, ERROR
- Integration with FastAPI middleware
Give me the plan with the files to create/modify.

Claude produces a detailed plan. You review it and ask for a tweak:

> In the plan, you add structlog. What if we use loguru
  instead? It's simpler. Update the plan.

Phase 3: Code (incremental)

> Implement step 1: install loguru and create the logging
  configuration module in src/core/logging.py
> Implement step 2: create the request ID middleware
  and the request/response logging.
> Implement step 3: replace every print() in
  src/routers/ with logger calls.
> Run the tests. If something fails, fix it.

Phase 4: Verify

> Review the full logging implementation. Is there any
  print() left unreplaced? Do the tests cover the middleware?
  Does the JSON format work correctly?

Practice exercises

Exercise 1: Basic — Explore your project

Open Claude Code in your project and run a full exploration:

> Analyze this project. Give me a report that includes:
  1. Tech stack
  2. File structure
  3. Main dependencies
  4. Entry points
  5. Test status (if there are any)

Goal: Get familiar with the output of Explore mode.

What to expect

Claude should produce a structured report with all the information you asked for. If your project is small, the report will be short. If it's large, Claude will prioritize the most important files.

Check that the information is correct. If Claude gets something wrong, correct it — that improves its later answers in the same session.

Exercise 2: Basic — Plan an improvement

Find something you could improve in your project and use Plan mode:

/plan [describe the improvement you want to make]

Goal: Receive a structured plan and evaluate it critically.

What to expect

The plan should include:

  • Files to create/modify
  • Implementation order
  • Identified risks

If the plan is too vague, ask for more detail:

> Step 3 of the plan is very generic. Give me more detail
  on exactly what changes you'd make in that file.

If the plan has an error, point it out:

> In step 2 you mention modifying auth.py, but that file
  doesn't exist. It's called authentication.py. Update the plan.

Exercise 3: Intermediate — The full E→P→C cycle

Run the full cycle on a real task:

  1. Explore: Analyze a specific module of your project
  2. Plan: Design an improvement for that module
  3. Code: Implement the first step of the plan
  4. Verify: Ask Claude to review what got implemented

Goal: Experience the full cycle from start to finish.

Tips for this exercise

Pick a scoped task:

  • ✅ "Add input validation to an endpoint" (scoped)
  • ✅ "Add a missing test" (scoped)
  • ❌ "Redesign the architecture" (way too big)

During Code, implement only the first step of the plan. Don't try to do it all at once. The goal is to practice the cycle, not to finish a whole feature.

Exercise 4: Intermediate — Compare with and without the workflow

Do the same task two ways:

Without the workflow:

> [Describe the task directly and let Claude implement it]

With the workflow:

> [Explore → Plan → Code for the same task]

Compare the results. Which produced better code? Which consumed less context?

What you should notice

In most cases, the workflow approach produces:

  • Code that respects the existing conventions better
  • Fewer errors on the first implementation
  • Better edge-case coverage (the Plan identifies them)
  • Less back-and-forth to fix problems

The no-workflow approach can be faster for trivial tasks, but it produces worse results on complex ones.

Exercise 5: Advanced — Tiered model and effort

Practice switching model and effort within a session:

# Simple task → Sonnet
/model sonnet
> What version of Python does this project use?

# Standard implementation → Sonnet
> Create a test for the login endpoint.

# Refactoring → Opus (effort high by default)
/model opus
> Refactor the users service to separate the validation
  logic from the persistence logic.

# Architecture → Opus + Plan
/plan Design a rate limiting system for the API.
Consider: per IP, per user, per endpoint. I want a
full plan with options.

Goal: Feel the difference between models and learn to pick the right combination.

What you should notice
  • Sonnet for simple questions: Immediate, direct answer
  • Sonnet for implementation: Correct and fast
  • Opus (effort high): Robust implementation, considers more edge cases, better structure
  • Opus + Plan: Exhaustive analysis, multiple options, detailed trade-offs

The difference between models is most visible on design and architecture tasks (where Opus shines) rather than mechanical ones (where Sonnet is plenty).

Exercise 6: Challenge — Multi-mode in a real session

Simulate a real 30-minute working session using all three modes:

  1. Start with Explore to understand your project's current state
  2. Identify 2-3 possible improvements
  3. Use Plan to design the most important one
  4. Implement with Code (incrementally, step by step)
  5. Verify with Explore
  6. Commit the result

Goal: Fold everything into a natural working flow.

Execution guide

Minutes 0-5: Explore

> Give me an analysis of the project's current state. What areas
  need improvement? Is there technical debt? Missing tests?

Minutes 5-10: Plan

/plan [Pick the highest-impact improvement Claude identified
and ask for a plan]

Minutes 10-25: Code (incremental)

Implement the plan step by step. After each step, verify that the tests pass.

Minutes 25-30: Verify + Commit

> Review everything we implemented. Is it all correct?

> Commit with a descriptive message.

Summary

What you learned in this capsule:

  • Explore mode is read-only analysis. Use it to understand before you act. It activates through analysis prompts or via the built-in Explore subagent.
  • Plan mode is design without execution. It activates with /plan or by explicitly asking for a plan. It produces a plan you review before anything runs.
  • Agent/Code mode is full execution (the default). It reads, writes, runs commands. It asks for confirmation on destructive actions.
  • The Explore → Plan → Code cycle is iterative, not linear. Adapt the variation to the task.
  • Effort level (Opus 5, Sonnet 5, and Fable 5) controls reasoning depth. The current models have 5 levels (low, medium, high, xhigh, max) with high as the default; xhigh is the one recommended for coding. You set it with /effort, inside /model with the arrows, or in settings.
  • Without a workflow, you get generic results. With a workflow, you get results that respect your existing architecture.

Next capsule: 03 - Multi-turn conversations — how to iterate effectively with Claude Code across multi-message conversations.


Additional resources

Official documentation

Context and configuration

  • Memory — How CLAUDE.md shapes each mode
  • Settings — Configuring permissions and scopes

Complementary