CC-101: Mastering Claude Code
Listen instead
Overview: What You Will Learn
Claude Code is not autocomplete. It is not a fancy tab-completion engine that guesses the next line you want to type. It is a fully autonomous software engineering agent that lives inside your terminal, reads your codebase, reasons about problems, selects tools, executes actions, and observes results -- all in a continuous loop until the task is done. Understanding this distinction is the single most important mental shift you need to make before touching any configuration or workflow optimization.
In this module you will learn the fundamental architecture of Claude Code: how it thinks, how it acts, how it communicates, and how you control it. By the end, you will have a precise mental model of what happens between the moment you type a prompt and the moment Claude Code delivers a result.
The Agentic Paradigm
Traditional code assistants operate on a request-response cycle. You type, they suggest, you accept or reject. Claude Code operates on an agentic loop -- a continuous cycle of autonomous reasoning and action. The difference is not cosmetic; it changes everything about how you interact with the tool.
Think of Claude Code as a junior developer sitting at your machine. It can read any file, write any file, run any command, search your entire codebase, and make decisions about what to do next. It does not wait for you to tell it which file to open. It figures that out. It does not ask which grep pattern to use. It decides. Your job shifts from doing the work to directing the work -- setting intent, reviewing results, and course-correcting when needed.
The Agentic Loop: Reason, Select, Execute, Observe
Every action Claude Code takes follows a four-step cycle:
- Reason -- Analyze the current state. What does the user want? What do I know? What do I still need to find out? What is the best next step?
- Select Tool -- Choose the right tool for the job. Should I read a file? Search the codebase? Run a shell command? Edit a file in place?
- Execute -- Call the tool with specific parameters. Read line 45-80 of
src/auth/middleware.ts. Grep forhandleApiErroracross all TypeScript files. Runnpm test. - Observe -- Process the result. Did the test pass? Is this the right file? Does the output match expectations? Then loop back to Reason.
This loop repeats autonomously until Claude Code determines the task is complete or it needs your input. A single prompt from you might trigger dozens of loop iterations -- searching files, reading code, making edits, running tests, fixing failures, and verifying results.
The Four-Part Conversation Model
Under the hood, Claude Code communicates using four distinct message types. Understanding these is essential for debugging unexpected behavior and writing better prompts.
Human Turn → Your prompt or instruction
Assistant Turn → Claude Code's reasoning and response text
Tool Use → Claude Code calling a tool (Read, Edit, Bash, etc.)
Tool Result → The output returned from that tool call
A typical interaction looks like this in the conversation stream:
# You type:
"Fix the broken authentication middleware test"
# Claude Code internally processes:
[Assistant] I need to find the auth middleware test file first.
[Tool Use] Glob { pattern: "**/*auth*middleware*test*" }
[Tool Result] src/__tests__/api/auth/middleware.test.ts
[Assistant] Let me read the test file to understand the failure.
[Tool Use] Read { file_path: "src/__tests__/api/auth/middleware.test.ts" }
[Tool Result] (file contents...)
[Assistant] The test expects a 401 but the handler returns 403. Let me check the source.
[Tool Use] Read { file_path: "src/api/auth/middleware.ts" }
[Tool Result] (file contents...)
[Assistant] Found the bug. Line 47 returns 403 instead of 401 for missing tokens.
[Tool Use] Edit { file_path: "src/api/auth/middleware.ts", old_string: "return new Response(..., { status: 403 })", new_string: "return new Response(..., { status: 401 })" }
[Tool Result] File edited successfully.
[Tool Use] Bash { command: "npm test -- --grep 'auth middleware'" }
[Tool Result] All tests passing.
Every Tool Use message consumes context window tokens -- both the request and the result. This is why context management matters, and why you will learn about /compact and strategic prompting in Module CC-102.
The Core Toolbelt
Claude Code has access to a specific set of tools. These are not plugins you install; they are built into the agent runtime. Knowing what each tool does helps you understand Claude Code's decisions and write prompts that guide it toward the right tools.
Read
Reads a file from the filesystem. Supports line offsets and limits for targeted reading. Can read images, PDFs, and Jupyter notebooks.
Read { file_path: "/src/lib/auth.ts", offset: 20, limit: 50 }
Write
Writes an entire file to disk. Used for creating new files or complete rewrites. Requires that the file was read first (if it already exists) to prevent accidental overwrites.
Write { file_path: "/src/lib/new-util.ts", content: "export function ..." }
Edit
Performs surgical string replacement in an existing file. This is the preferred tool for modifications because it sends only the diff, not the entire file. The old_string must be unique in the file, or the edit fails.
Edit {
file_path: "/src/lib/auth.ts",
old_string: "const TOKEN_EXPIRY = 3600",
new_string: "const TOKEN_EXPIRY = 900"
}
Glob
Fast file pattern matching. Returns matching file paths sorted by modification time. Use this to find files by name pattern rather than find commands.
Glob { pattern: "src/**/*.test.ts" }
Grep
Content search powered by ripgrep. Supports regex, file type filters, and context lines. Faster and more capable than shell grep.
Grep { pattern: "handleApiError", type: "ts", output_mode: "content", -C: 3 }
Bash
Executes shell commands. Used for running tests, build commands, git operations, and anything that requires a terminal. Working directory persists between calls, but shell state does not.
Bash { command: "npm run test -- --coverage", timeout: 120000 }
The System Prompt and How Claude Code Receives Instructions
When Claude Code starts a session, it constructs a system prompt from multiple sources. This system prompt tells the agent who it is, what tools it has, what rules to follow, and what context applies. The instruction hierarchy (from highest to lowest priority) is:
- Anthropic system instructions -- Hardcoded safety and behavioral rules. You cannot override these.
- CLAUDE.md files -- Project and user-level instructions that are injected into the system prompt at session start.
- User prompts -- What you type during the session.
- Tool results -- Information returned from tool calls that feeds back into the agent's context.
This means your CLAUDE.md files are extremely powerful. Instructions placed there are treated with nearly the same weight as system-level instructions. This is where you encode your project conventions, coding standards, testing requirements, and workflow rules. You will deep-dive into CLAUDE.md configuration in Module CC-103.
The Permission Model
Claude Code operates under a permission system that controls which tools it can use without asking. This is critical for balancing autonomy with safety.
Allowlist and Denylist
Permissions are configured in .claude/settings.json at the project or user level. There are two key arrays:
{
"permissions": {
"allow": [
"Read",
"Edit",
"Glob",
"Grep",
"Bash(npm test*)",
"Bash(git status)",
"Bash(git diff*)"
],
"deny": [
"Bash(rm -rf*)",
"Bash(git push --force*)"
]
}
}
Tools on the allow list execute without prompting you for approval. Tools on the deny list are blocked entirely. Everything else triggers an interactive approval prompt where you can accept, reject, or modify the action before it runs.
The pattern matching supports wildcards. Bash(npm test*) allows any bash command starting with npm test, including npm test -- --coverage or npm test -- --grep "auth". This lets you grant broad permissions for safe operations while blocking dangerous ones.
The CLAUDE.md Hierarchy
CLAUDE.md files form a layered instruction system. Claude Code reads them in a specific order, with more specific files taking precedence:
# Load order (later overrides earlier):
~/.claude/CLAUDE.md # Global: applies to ALL projects
./CLAUDE.md # Project root: applies to this repo
./src/CLAUDE.md # Subdirectory: applies when working in /src
./.claude/settings.json # Project settings: permissions, model, etc.
A global CLAUDE.md might contain your universal preferences -- your preferred test framework, your commit message style, your code review standards. A project-level CLAUDE.md adds project-specific context -- the tech stack, the database schema quirks, the API patterns your team uses. A subdirectory CLAUDE.md can add even more specific rules for a particular part of the codebase.
This layered system means you write instructions once at the appropriate level and they apply automatically. You do not need to repeat yourself in every prompt.
The Mental Model: Junior Developer at Your Machine
The most productive mental model for Claude Code is this: it is a competent but literal junior developer who has full access to your machine and will do exactly what you tell it to do -- including making mistakes if your instructions are ambiguous.
This mental model has practical implications:
- Be specific about intent, not implementation. Say "fix the auth test that's failing because of the wrong status code" rather than "change line 47 of middleware.ts from 403 to 401." Claude Code will figure out the implementation -- and might find a better fix than the one you assumed.
- Review the work. Just like you would review a junior developer's pull request, review what Claude Code produces. It will sometimes make reasonable but incorrect assumptions.
- Provide context upfront. A junior developer who knows your project's conventions writes better code. The same applies to Claude Code -- your CLAUDE.md files are the onboarding document.
- Correct and redirect. When Claude Code goes down the wrong path, tell it directly. "Stop. That approach won't work because X. Instead, try Y." The agent will course-correct immediately.
Best Practices for Getting Started
- Start with read-only exploration. Before asking Claude Code to write code, ask it to explain existing code. "Walk me through how authentication works in this codebase." This builds context for both you and the agent.
- Use the right granularity. Claude Code handles both "rename this variable" and "implement the entire user settings page." Start with smaller tasks to build trust, then scale up.
- Do not fight the tools. If you find yourself typing shell commands that Claude Code could run, let it run them. The value is in the autonomous loop, not in manual execution.
- Watch the tool calls. Early on, pay attention to which tools Claude Code selects and how it uses them. This teaches you how the agent thinks and helps you write better prompts.
- Set up your CLAUDE.md early. Even a minimal CLAUDE.md with your tech stack and testing requirements makes a meaningful difference in output quality from day one.
Official Documentation
For the complete reference on Claude Code's architecture, capabilities, and setup, consult the official Anthropic documentation:
- Claude Code Overview -- Architecture, capabilities, and getting started guide.
- CLI Usage Reference -- Complete command-line interface documentation.
- Settings and Configuration -- Permissions, CLAUDE.md, and environment setup.