I’ve run hundreds of Claude Code sessions over the past few months. I’ve watched it refactor entire service layers, hit context limits mid-task and recover, spawn sub-agents to explore codebases, and occasionally do something so clever it made me stop and think about what just happened under the hood.
Most developers use Claude Code like a black box. Type a prompt, get code back. But understanding what actually happens between your keystroke and the final code change makes you dramatically better at using it. You learn when to split tasks, when to /compact, when to use Plan Mode, and why some prompts cost $0.50 while others cost $8.
In this article, I’ll trace the complete lifecycle of a Claude Code session, from the moment you type claude in your terminal to the final tool call. I’ve measured real token budgets, traced the agentic loop, and mapped out every system that fires along the way. Let’s get into it.
Claude Code Tutorial for Beginners
New to Claude Code? Start here - this covers installation, first run, and the basics you need before diving into internals.
The 10-Second Version
Claude Code is an agentic harness around Claude. It provides tools, context management, and an execution environment that turns a language model into a coding agent. When you type a prompt, Claude Code assembles a system prompt (~2,900 base tokens), loads your CLAUDE.md instructions, injects 18+ tool definitions, and sends everything to the Claude API. The model responds with either text (done) or tool calls (keep going). This loop - call model, execute tools, feed results back, call model again - repeats until the model produces a text-only response with no tool invocations. A typical task runs 5-50 iterations of this loop.
That’s the core architecture. Everything else - sub-agents, context compaction, hooks, permissions - is infrastructure that makes this loop reliable, safe, and cost-effective. Let’s break it all down.
What Loads Before You Type a Single Character
When you run claude in a project directory, a lot happens before you see the prompt. Here’s the startup sequence, in order:
- Managed policy settings load first (organization-level, cannot be overridden)
- User settings from
~/.claude/settings.json - Project settings from
.claude/settings.jsonand.claude/settings.local.json - CLAUDE.md files - Claude Code walks UP the directory tree from your current directory, loading every CLAUDE.md it finds. Project-level, user-level, even organization-level if configured.
- Rules from
.claude/rules/*.md- unconditional ones load immediately, path-scoped ones load on-demand when Claude reads matching files - Auto-memory -
MEMORY.md(first 200 lines) from~/.claude/projects/<project>/memory/ - Skills discovery - scans
~/.claude/skills/and.claude/skills/for available slash commands - MCP servers connect
- Git status injection - current branch, uncommitted changes, recent commit history
- System prompt assembly - all of the above gets compiled into the final prompt
Here’s the part that surprised me: the system prompt isn’t a single monolithic string. Claude Code assembles dozens of conditional prompt strings based on your environment, settings, and context. The base system role definition alone is ~2,900 tokens. Add tool definitions (~3,000 tokens for 18+ tools), CLAUDE.md content (500-2,000 tokens typically), git status, and skill descriptions - and you’ve spent 8,000-12,000 tokens before typing a single character.
That’s 4-6% of a 200K context window. On the 1M context window that Fable 5, Opus 5, and Sonnet 5 now ship with by default, it’s negligible. On a 200K window like Haiku 4.5’s, it means you have ~190K tokens for actual conversation and tool results.
A critical detail: CLAUDE.md content is injected as a user message, not as part of the system prompt. This is a deliberate design choice. It means CLAUDE.md instructions are treated as context rather than hard configuration. More specific, concise instructions produce better adherence. Keep your CLAUDE.md under 200 lines.
CLAUDE.md for .NET Developers
I wrote a complete guide to CLAUDE.md with copy-paste templates for Clean Architecture, Minimal APIs, and enterprise solutions. Understanding the loading hierarchy matters for session behavior.
The Agentic Loop - The Heart of Claude Code
This is where the magic happens. The core of Claude Code is a deceptively simple while loop (documented in Anthropic’s official architecture overview):
while (response contains tool_calls): execute tool(s) feed results back as tool_result messages call model again with updated conversation
when response is plain text (no tool calls): loop terminates, return to userThat’s it. No complex multi-agent orchestration, no swarm intelligence, no parallel reasoning threads. A single-threaded master loop that calls the model, executes tools, and feeds results back until the model decides it’s done.
The Three Phases
Every iteration of the loop falls into one of three phases, though Claude blends them fluidly:
- Gather context - Read files, search code, explore the codebase
- Take action - Edit files, run commands, create new files
- Verify results - Run tests, check builds, read the output
Claude decides what each step requires based on what it learned from the previous step. There’s no rigid state machine forcing it through phases. The model’s reasoning drives the flow.
The .NET Middleware Pipeline Analogy
If you’re a .NET developer, think of it like the ASP.NET Core middleware pipeline - but in reverse. In ASP.NET Core, a request flows through middleware layers, each one potentially short-circuiting or modifying the request/response. In Claude Code, each loop iteration is like a request through the pipeline:
- PreToolUse hooks fire (like request middleware - can allow, deny, or modify)
- Permission check runs (like authorization middleware)
- Tool executes (like your endpoint handler)
- PostToolUse hooks fire (like response middleware - can provide feedback)
- System reminders inject (like logging middleware adding context)
- Model receives everything and decides the next action
The key difference: in ASP.NET Core, the pipeline processes one request. In Claude Code, the pipeline loops until the model produces a text-only response. Each iteration builds on everything that came before.
Middlewares in ASP.NET Core
If the pipeline analogy resonated, this deep dive covers execution order, custom middleware, IMiddleware, and short-circuiting in ASP.NET Core.
What Stops the Loop?
The loop terminates when:
- The model produces plain text without any tool invocations (most common)
- You interrupt by pressing Escape
- Context window exhaustion triggers auto-compaction
maxTurnslimit on sub-agents prevents runaway loops- A Stop hook with
decision: "block"prevents termination (yes, hooks can force Claude to keep going)
The Async Queue
There’s one more piece: a dual-buffer async queue that enables pause/resume and mid-task user interjections. This is what lets you press Escape while Claude is mid-edit, type a correction, and have Claude adjust without restarting the entire task. It’s a small but critical detail that makes Claude Code feel interactive rather than batch-processed.
The 18+ Built-In Tools - How Claude Picks the Right One
Claude Code ships with 18+ built-in tools, each with a JSON schema description embedded in the system prompt. The model selects tools based on the user’s intent, previous tool results, and explicit instructions in the tool descriptions.
Tool Categories
File Operations:
- Read - Read files (default ~2,000 lines, supports images, PDFs, Jupyter notebooks)
- Write - Create or overwrite entire files
- Edit - Surgical string replacement with uniqueness check (preferred over Write for modifications)
Search:
- Glob - Fast file pattern matching, sorted by modification time
- Grep - Ripgrep-powered regex search with multiple output modes
Execution:
- Bash - Persistent shell with risk classification, injection filtering, timeout support
Web:
- WebFetch - URL retrieval with AI summarization and 15-minute cache
- WebSearch - Web search with domain filtering
Orchestration:
- Agent - Spawn sub-agents with isolated context
- Skill - Invoke skills (custom slash commands) by name
- NotebookEdit - Jupyter notebook cell editing
Planning and Communication:
- TodoWrite - Structured task lists with priorities
- AskUserQuestion - Ask the user for input
- SendMessage - Inter-agent communication
How Claude Decides Which Tool to Use
This isn’t random. The system prompt contains explicit routing instructions:
- “Use Read instead of
cat,head,tail, orsed” - “Use Grep instead of
greporrgvia Bash” - “Use Glob instead of
findorls” - “For broader codebase exploration, use Agent with
subagent_type=Explore” - “For simple, directed searches, use Glob or Grep directly”
There’s a hierarchy: dedicated tools are always preferred over Bash equivalents. This is because dedicated tools give the user visibility into what Claude is doing - a Grep call is transparent, while rg pattern inside Bash is opaque.
My take: Understanding this hierarchy is one of the biggest productivity wins. When Claude uses the wrong tool (like Bash for file reading), the system prompt is literally telling it not to. If your CLAUDE.md reinforces the right tool choices for your project (“always use dotnet test for testing, never dotnet run on test projects”), Claude follows those instructions within the agentic loop.
Prompt Engineering for Claude Code
Writing effective prompts is the other half of the equation. This guide covers 10 bad-vs-better patterns and the 4-layer prompt hierarchy.
Sub-Agents - When Claude Calls for Backup
Sometimes a single thread isn’t enough. Claude Code can spawn sub-agents: isolated instances that run in their own context window with their own system prompt.
Built-In Sub-Agent Types
| Agent Type | Model | Tools | Purpose |
|---|---|---|---|
| Explore | Haiku (fast) | Read-only | File discovery, codebase exploration |
| Plan | Inherits | Read-only | Research for plan mode decisions |
| general-purpose | Inherits | All tools | Complex multi-step tasks |
How Context Forking Works
When Claude spawns a sub-agent, it does NOT copy the entire conversation history. The sub-agent receives:
- Its own system prompt (much smaller than the main one)
- Basic environment details (working directory, platform)
- The task description from the parent
- CLAUDE.md content (still loaded)
The sub-agent runs its own agentic loop, potentially making dozens of tool calls. When it finishes, only a condensed summary returns to the parent - typically 1,000-2,000 tokens from what might have been tens of thousands of tokens of exploration.
This is the key insight: sub-agents are context-efficient. They let Claude explore deeply without filling the parent’s context window. An Explore sub-agent might read 50 files (consuming 100K+ tokens internally) but return a 1,500-token summary to the parent.
Nesting: Sub-Agents Can Spawn Sub-Agents Now
This changed, and if you learned Claude Code in early 2026 you’re probably still carrying the old rule. Sub-agents used to be capped at a single level - they could not delegate further. They can now, up to three layers below your main conversation by default.
At the depth limit, Claude Code withholds the Agent tool from the sub-agent entirely, so it does the delegated work itself and returns one summary rather than failing. The ceiling enforces itself.
Where nesting earns its keep is a delegated task that itself fans out. A reviewer sub-agent that dispatches one verifier per finding is the canonical shape: the verifiers’ intermediate chatter never reaches your main conversation, and only the reviewer’s summary comes back. Applied to .NET, that’s “review this pull request” spawning a verifier per changed project, with your context seeing one consolidated result instead of twelve.
You can change the ceiling:
{ "env": { "CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH": "2" }}Set it to 1 to turn nesting off entirely and get the old behaviour back. To stop one specific sub-agent from spawning - a reviewer you want kept read-only, say - omit Agent from its tools list or add it to disallowedTools instead of changing the global depth.
The sub-agent panel below the prompt input shows the whole tree, with a (+N) descendant count per row, so a runaway fan-out is visible rather than mysterious.
Background by Default
The other change that catches people out: as of v2.1.198 sub-agents run in the background by default. Claude keeps working while they run, and their results arrive as a notification rather than blocking the turn.
That’s usually what you want, but it does mean the mental model of “spawn a sub-agent, wait, get the answer” no longer matches what happens. Press Ctrl+B to background a running task manually, mark a custom sub-agent with background: true in its frontmatter to always run it that way, or set CLAUDE_CODE_DISABLE_BACKGROUND_TASKS to turn the behaviour off wholesale.
Custom sub-agents can also keep their own persistent memory with a memory field in frontmatter, stored separately from your main conversation’s auto memory. A code-reviewer sub-agent that accumulates “this repo’s tests need Docker running” across sessions stops relearning it every time.
When to Use Sub-Agents
Here’s my decision matrix from real usage:
| Scenario | Use Sub-Agent? | Which Type? |
|---|---|---|
| Find a specific file/function | No - use Glob/Grep directly | - |
| Understand a module’s architecture | Yes | Explore |
| Run tests independently | Yes | general-purpose |
| Research before a complex refactor | Yes | Explore or Plan |
| Parallel independent tasks | Yes (background) | general-purpose |
| Simple file edits | No - do it inline | - |
Context Window - Where Your Tokens Actually Go
Every turn in a Claude Code session reprices the entire context. The model processes ALL accumulated input tokens on each interaction. This means your 50th prompt is dramatically more expensive than your 1st, because the model reads the entire conversation history every time.
Real Token Budget Breakdown
Here’s what I’ve measured from my own sessions:
| Component | Tokens | % of a 200K window | % of a 1M window |
|---|---|---|---|
| Base system prompt | ~2,900 | 1.5% | 0.3% |
| 18+ tool definitions | ~3,000 | 1.5% | 0.3% |
| CLAUDE.md (typical project) | ~1,200 | 0.6% | 0.1% |
| Rules files | ~500 | 0.3% | 0.05% |
| Git status | ~300 | 0.2% | 0.03% |
| Skill descriptions | ~800 | 0.4% | 0.08% |
| Total overhead | ~8,700 | ~4.5% | ~0.9% |
Two columns, because the top three model tiers now carry a 1 million token context window rather than the 200K that was standard when I first measured this. The absolute overhead didn’t change - the window around it grew five-fold.
That shift matters more than it first looks, because it moves the bottleneck. On a 200K window, trimming your CLAUDE.md and pruning skill descriptions was worth doing: overhead was a real percentage of your budget. On a 1M window it’s noise. Optimising a 1,200-token CLAUDE.md to save 400 tokens is now rounding error, and time better spent elsewhere.
What fills a 1M window is what always actually filled the 200K one: accumulated tool results. A single file read can return 2,000+ lines, easily 8,000 to 15,000 tokens. A dotnet build on a large solution dumps thousands more. After 10-15 tool calls you’ve consumed 50-80K tokens, and none of it is overhead you can configure away.
So the discipline that pays off is about controlling what enters context in the first place - reading targeted line ranges instead of whole files, delegating exploration to sub-agents whose results never land in your window, and using /compact deliberately rather than waiting for it to fire. See the Claude Code cost documentation for the official token accounting.
The 3-Tier Compaction Strategy
When you approach ~92-95% context capacity, Claude Code triggers automatic compaction (Anthropic’s engineering blog has a deep dive on context engineering that explains the philosophy). It uses three tiers:
Tier 1 - Tool result clearing: Removes raw tool outputs from deep in message history. Lightest touch, safest option.
Tier 2 - Conversation summarization: The compactor passes the full history to the model for summarization. It preserves architectural decisions, unresolved bugs, implementation details, and key decisions. It discards redundant tool outputs, verbose intermediate results, and detailed instructions from early in the conversation. Typical compression: 60-80%.
Tier 3 - Manual compaction: /compact [focus] lets you direct what to preserve. You can say /compact focus on the auth refactor and the compactor will prioritize auth-related context.
What Survives Compaction
This is the part nobody explains clearly. Here’s what I’ve observed:
Always survives:
- CLAUDE.md (re-read from disk after compaction, guaranteed fresh)
- Current file states (Claude re-reads if needed)
- The most recent tool results
- Active TODO list items
Usually survives (summarized):
- Architectural decisions from earlier in the session
- Key code patterns and approaches chosen
- Error messages and their resolutions
Gets discarded:
- Early exploratory file reads (the raw content, not the insight)
- Verbose command outputs from successful operations
- Superseded approaches that were abandoned
My take: Knowing this changes how I work. For long refactoring sessions, I run /compact focus on [the key changes] proactively at around 60-70% capacity rather than waiting for auto-compaction at 92%. This gives me control over what survives instead of leaving it to the summarizer.
Plan Mode in Claude Code
Plan Mode restricts Claude to read-only tools, forcing it to explore and plan before acting. Understanding the agentic loop explains why this constraint is so effective.
.NET Claude Kit
Open-source Claude Code companion with 47 skills and 10 specialist agents
The Permission and Safety Model
Claude Code doesn’t just execute whatever the model asks. Every tool call goes through a permission pipeline.
Rule Evaluation: deny > ask > allow
Permission rules are evaluated in strict order:
- Deny rules - checked first. If any deny rule matches, the tool call is blocked. Period.
- Ask rules - checked second. If matched, the user is prompted for approval.
- Allow rules - checked last. If matched, the tool call proceeds silently.
First match wins. This means a deny rule always overrides an allow rule, making the system fail-safe.
Permission Modes
| Mode | Behavior |
|---|---|
default (labelled Manual) | Prompts for permission on first use of each tool |
acceptEdits | Auto-accepts file edits and common filesystem commands, still asks for the rest |
plan | Read-only tools only (this is Plan Mode) |
auto | A classifier model reviews each action and blocks what escalates |
dontAsk | Auto-denies anything not pre-approved; never waits for input |
bypassPermissions | Skips prompts entirely |
You cycle through modes with Shift+Tab during a session.
Auto mode is the one that changes the shape of the loop, and it’s worth understanding mechanically because it’s the newest layer here. Instead of surfacing a prompt to you, non-trivial actions are routed to a separate classifier model that sees your messages, the tool calls, and your CLAUDE.md - but explicitly not tool results. That last part is the interesting design decision: stripping tool results means hostile content sitting in a file or a fetched web page can’t reach the thing deciding whether an action is safe. A separate server-side probe scans incoming tool results for suspicious content before Claude reads them at all.
The decision order is fixed, and first match wins:
- Your explicit allow, ask, and deny rules resolve immediately
- Read-only actions and working-directory edits are auto-approved
- Everything else goes to the classifier
- If the classifier blocks, Claude receives the reason and tries another route
Two behaviours worth knowing. On entering auto mode, broad allow rules that grant arbitrary code execution get dropped - blanket Bash(*), wildcarded interpreters like Bash(python*), package-manager run commands, and Agent rules. Narrow ones like Bash(dotnet test) carry over, and the dropped rules come back when you leave the mode. And if the classifier blocks three actions consecutively or twenty across the session, auto mode pauses and hands prompting back to you.
The classifier runs on a mid-tier model by default rather than whatever /model you picked, and its calls count toward your token usage. Reads and working-directory edits skip it entirely, so the overhead lands on shell commands and network operations.
Hooks - Intercepting the Loop
Hooks are shell commands or HTTP endpoints that fire at lifecycle events (see the full hooks reference for all 12+ event types). They intercept the agentic loop at specific points:
- PreToolUse - fires BEFORE a tool executes. Can allow, deny, or modify the tool’s input.
- PostToolUse - fires AFTER successful execution. Can provide corrective feedback.
- Stop - fires when Claude tries to finish. Can force Claude to keep going (quality gates).
- SessionStart/SessionEnd - lifecycle bookends.
The most powerful pattern I’ve found: a PreToolUse hook that runs dotnet format before every Edit tool call, ensuring code style is consistent. And a Stop hook that runs dotnet test and blocks stopping if tests fail.
Extended Thinking and Prompt Caching
Two features that significantly affect session cost and quality:
Extended Thinking
Enabled by default. Claude Code allocates thinking tokens based on task complexity (adaptive reasoning). Thinking tokens are billed as output tokens but dramatically improve planning quality.
Control it with effort levels, set via /effort or the --effort flag:
- low - faster, cheaper, straightforward tasks that aren’t intelligence-sensitive
- medium - a cost-saving step down for routine work
- high - balances tokens against capability, and is the default on current models
- xhigh - deeper reasoning at higher token spend, worth it for genuine architectural tradeoffs
- max - the deepest reasoning, but prone to overthinking and subject to diminishing returns; session-only, and worth testing before you adopt it broadly
low through xhigh persist across sessions once you set them interactively. max deliberately does not - it resets, so an experiment doesn’t quietly become your default.
Prompt Caching
Claude Code automatically caches system prompts and tool definitions across requests within a session. The first request pays full input token cost. Subsequent requests with the same prefix get significantly cheaper cache-read pricing.
This is why long sessions with consistent system prompts are more cost-efficient per-turn than many short sessions. The system prompt (~8,700 tokens) is cached after the first turn and essentially free for every subsequent turn.
What This Means for Your Daily Workflow
Understanding the internals changes how you use Claude Code. Here are the practical implications:
Split large tasks: The single-threaded design means Claude can’t parallelize within a session. If you have 3 independent changes, running them as 3 sessions (or using sub-agents) is faster than one mega-prompt.
Front-load context: Since CLAUDE.md loads before everything else and survives compaction, invest in a good CLAUDE.md. Every minute you spend on it saves hours across sessions.
Use /compact proactively: Don’t wait for auto-compaction at 92%. Run /compact focus on [key context] at 60-70% to stay in control of what the model remembers.
Prefer dedicated tools: If Claude is using Bash for file operations, your instructions aren’t clear enough. Add “always use Read/Edit/Grep, never cat/sed/grep via Bash” to your CLAUDE.md.
Understand the cost curve: Early turns are cheap (cached system prompt). Late turns are expensive (full conversation history repriced). For cost-sensitive work, keep sessions focused and compact early.
Use Plan Mode for exploration: Plan Mode restricts to read-only tools. This means Claude can explore freely without the risk of making changes. Use it for “understand this codebase” tasks, then switch to execution mode.
Skills in Claude Code
Skills turn repetitive workflows into reusable slash commands. Understanding how the Skill tool injects instructions into the agentic loop explains why well-designed skills are so powerful.
Claude Code Prompts for .NET Developers
Now that you know how the loop consumes your instructions, grab 11 copy-paste .NET prompts built around context, constraints, and verification.
Key Takeaways
- Claude Code is a single-threaded agentic loop: call model, execute tools, feed results back, repeat. No multi-agent swarms. Deliberate simplicity for debuggability.
- ~8,700 tokens of overhead load before you type anything (system prompt + tools + CLAUDE.md + git status). That was ~4.5% of a 200K window; on the 1M windows current models ship with, it’s under 1% - so the thing worth optimising is no longer your setup, it’s what your tool calls drag in.
- Context compaction fires at ~92% capacity with a 3-tier strategy: clear tool results first, then summarize conversation, then manual
/compact. CLAUDE.md always survives - it’s re-read from disk. - Sub-agents are context-efficient: they run their own loop, potentially consuming 100K+ tokens internally, but return only a 1,000-2,000 token summary to the parent.
- The permission model is fail-safe: deny rules always override allow rules. Hooks let you intercept every tool call in the agentic loop.
Troubleshooting
Context window filling up too fast
Your tool results are too large. Use --limit on Read calls, be specific with Grep patterns, and run /compact focus on [key context] before hitting 80%. Avoid reading entire large files when you only need a section.
Claude using Bash instead of dedicated tools
Your CLAUDE.md needs explicit tool routing instructions. Add: “Always use Read instead of cat, Grep instead of rg, Edit instead of sed. Reserve Bash for commands that require shell execution.”
Session feels slow after many turns
Each turn reprices the entire context. The 50th turn processes 50x more input tokens than the 1st. Run /compact to reset the conversation to a condensed summary, or start a fresh session with claude and reference the previous session’s approach.
Sub-agent returning unhelpful results
The task description you pass to the Agent tool is the sub-agent’s entire context. Be specific: “Find all files that implement the IProductRepository interface and list their public methods” not “Look at the repository layer.”
Hooks not firing
Check settings precedence. Hooks in managed settings override project settings. Run in verbose mode to see hook execution. Verify the hook command exits with code 0 (success) or code 2 (blocking error). Any other exit code is treated as a non-blocking error and silently ignored.
Claude ignoring CLAUDE.md instructions
CLAUDE.md is injected as a user message, not system prompt. Long CLAUDE.md files (200+ lines) get less adherence. Keep instructions concise, specific, and actionable. Vague instructions (“write good code”) are ignored. Specific instructions (“use primary constructors, file-scoped namespaces, and always pass CancellationToken”) are followed.
How does Claude Code's agentic loop work?
Claude Code uses a single-threaded agentic loop: it sends your prompt plus the full conversation history to the Claude API, receives a response that contains either text (done) or tool calls (keep going), executes the tools, feeds the results back as tool_result messages, and calls the model again. This loop repeats until the model produces a text-only response. A typical task runs 5-50 iterations.
How many tokens does a typical Claude Code session use?
A fresh Claude Code session starts with approximately 8,700 tokens of overhead (system prompt, tool definitions, CLAUDE.md, git status). A simple bug fix might use 30,000-50,000 total tokens. A complex refactoring session can consume 150,000-200,000 tokens before triggering context compaction. Average cost is about $6 per developer per day.
What tools does Claude Code have access to?
Claude Code ships with 18+ built-in tools across several categories: Read, Write, Edit for file operations, Glob and Grep for search, Bash for shell execution, WebFetch and WebSearch for web access, Agent and Skill for orchestration, and TodoWrite, AskUserQuestion, SendMessage for planning and communication. The exact count varies by version and configuration. Each tool has a JSON schema description that helps the model decide when to use it.
How does Claude Code manage the context window when it gets full?
Claude Code uses a 3-tier compaction strategy. Tier 1 clears old tool outputs from message history. Tier 2 triggers at approximately 92-95% capacity and summarizes the conversation, preserving architectural decisions and key context while discarding redundant outputs. Tier 3 is manual compaction via the /compact command where you can specify what to focus on. CLAUDE.md always survives compaction because it is re-read from disk.
How does Claude Code decide which tool to use?
The system prompt contains explicit routing instructions that tell Claude to prefer dedicated tools over Bash equivalents. For example, Read instead of cat, Grep instead of rg, Glob instead of find. Claude's model reasoning selects tools based on the user's prompt, previous tool results, tool descriptions, and any instructions in CLAUDE.md. Dedicated tools are preferred because they give users visibility into what Claude is doing.
What happens to CLAUDE.md instructions during context compaction?
CLAUDE.md always survives compaction. After any compaction event, Claude Code re-reads the CLAUDE.md file from disk and re-injects it fresh into the context. This is why CLAUDE.md is the most reliable way to persist instructions across long sessions. Only conversation-specific instructions that exist purely in chat history can be lost during compaction.
How do sub-agents work in Claude Code?
Sub-agents are isolated instances that run in their own context window with their own system prompt. When Claude spawns a sub-agent, it receives a task description and basic environment details but not the full conversation history. The sub-agent runs its own agentic loop and returns a condensed summary (typically 1,000-2,000 tokens) to the parent. Sub-agents can spawn their own sub-agents, up to three layers below the main conversation by default. At the depth limit Claude Code withholds the Agent tool, so the deepest sub-agent completes the work itself instead of failing. Change the ceiling with the CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH environment variable, or set it to 1 to disable nesting. Sub-agents also run in the background by default as of v2.1.198.
How much does a Claude Code session cost?
The average cost is approximately $6 per developer per day, with the 90th percentile under $12 per day, which puts monthly costs in the $100-200 range for steady use on a mid-tier model. Prompt caching significantly reduces costs for long sessions because the system prompt and tool definitions are cached after the first turn. Early turns in a session are cheap, while later turns are more expensive because the entire conversation history is repriced on each turn.
Summary
Claude Code’s architecture is a masterclass in constrained simplicity. A single-threaded agentic loop, 18 well-defined tools, a hierarchical context system, and a fail-safe permission model. No multi-agent swarms, no complex orchestration, no magic. Just a while loop that calls the model, executes tools, and feeds results back until the job is done.
The practical takeaway: the more you understand about this architecture, the better your prompts become, the more efficient your sessions are, and the lower your costs. Front-load context in CLAUDE.md, compact proactively, use dedicated tools, and split independent tasks into separate sessions or sub-agents.
Happy Coding :)
What's your take?
Push back, share a war story, or ask the obvious question someone else is wondering. I read every comment.