Claude Code, Deep Dive
Claude Code is Anthropic's agentic coding tool — it reads your codebase, edits files, runs commands, and integrates with your dev tools. This page covers how to install it, how its interaction loop actually works, and the levers — memory, subagents, hooks, permissions, plan mode — you use to keep it moving fast without letting it run wild.
Claude Code is like hiring a very capable intern who can actually see your whole desk, pick up any file, and type on your own keyboard — not just tell you what to do from across the room. The interesting part is deciding how closely you watch them: you can make them ask before every single move, or hand them a checklist and only get pulled in when something risky is about to happen.
What Claude Code Is
Anthropic's own docs define Claude Code as "an agentic coding tool that reads your codebase, edits files, runs commands, and integrates with your development tools." It isn't a chat window bolted onto an editor — it's a loop that hands Claude a set of tools (file read/write, grep, bash, web fetch, and more) and lets it decide which ones to call, in what order, until the task is done.
You can run it four ways: the terminal CLI, the VS Code and JetBrains editor extensions, a desktop app, and a web version at claude.ai/code. This page focuses on the CLI and the VS Code extension, since VS Code is this course's reference IDE.
Install the terminal CLI with Anthropic's install script (macOS/Linux/WSL), or via Homebrew, WinGet, apt, or dnf on other setups, then start a session by running claude from inside any project directory. In VS Code, the same command works from the integrated terminal (Ctrl+` / Cmd+`), or you can install the dedicated extension covered later on this page for a graphical panel alongside your editor.
The Core Interaction Loop
☺ Like you're 10: Think of it like a contractor fixing something in your house — they look around first, do the actual work, then flip the switch to check it worked. If it didn't, they go around the loop again instead of just guessing.
Every Claude Code session runs the same underlying loop, whether you're in the terminal or VS Code. Anthropic describes it as three phases that "blend together and repeat": gather context, take action, and verify work. Verification is deliberately deterministic where possible — linters, type checkers, test suites, and runtime errors give Claude ground truth about whether an action actually worked, rather than trusting its own judgment alone.
Each cycle through this loop is a "turn": Claude evaluates the conversation so far, responds with text and/or tool calls, the tools execute and their results feed back in automatically, and the cycle repeats until Claude produces a response with no further tool calls. This is the same agent loop the Claude Agent SDK exposes for embedding into your own applications — Claude Code is, at its core, that loop wrapped in a terminal and editor experience with a curated tool set (file edits, bash, search, web access) already wired up.
Slash Commands and Skills
☺ Like you're 10: Slash commands are speed-dial — type /init instead of explaining what you want from scratch every single time.
Slash commands are how you steer Claude Code outside of plain prompting. Built-in session and utility commands include /clear (reset context), /compact (summarize and shrink context), /context, /memory, /init (generate a starter CLAUDE.md from your codebase), /model, /help, /mcp, /hooks, /permissions, and /config. On top of those, bundled Skills are exposed as commands too — /code-review, /debug, /doctor, and /security-review are shipped this way.
Custom commands and Skills are now the same mechanism: a file at .claude/commands/deploy.md and a Skill at .claude/skills/deploy/SKILL.md both create a working /deploy command. A SKILL.md file's YAML frontmatter can set name, description (what Claude uses to decide when to auto-invoke it), when_to_use, argument-hint, arguments, disable-model-invocation (restrict to manual /name use only), user-invocable (hide it from the / menu but let Claude call it), allowed-tools, disallowed-tools, and model.
> /init
Scans the repo and writes a starter CLAUDE.md
> /model claude-opus-5
Switches this session to a more capable model for a hard refactor
> /plan
Add rate limiting to the /checkout endpointRun /init the first time you use Claude Code on a repo. It reads your codebase and drafts a CLAUDE.md for you to edit, which is usually faster than writing one from scratch.
Persistent Memory and Delegation
☺ Like you're 10: CLAUDE.md is the sticky note you leave a new roommate — house rules, where things go — so you're not repeating yourself every morning. A subagent is like sending a helper to dig through the garage for one specific box, so your kitchen table stays clear.
CLAUDE.md
CLAUDE.md is a markdown file you add to your project that Claude Code reads at the start of every session — the mechanism for persistent, project-specific instructions: coding standards, architecture decisions, build and test commands, workflows Claude should always follow. Keep it short; Anthropic recommends staying under roughly 200 lines per file so it doesn't crowd out the actual context Claude needs to do the task.
# invoice-service
## Stack
TypeScript, Node 20, Express, PostgreSQL via Prisma.
Tests run with Vitest.
## Conventions
- Named exports only, no default exports.
- Every file in src/routes/*.ts needs a matching src/routes/*.test.ts.
- Never hand-edit files under prisma/generated/.
## Workflow
- Run `npm run lint && npm test` after any change under src/.
- Prefer several small diffs over one large rewrite.CLAUDE.md files load in a hierarchy, broadest to narrowest: managed policy (org-wide, deployed by IT), user (~/.claude/CLAUDE.md, applies to everything you touch), project (./CLAUDE.md or ./.claude/CLAUDE.md, checked into source control and shared with the team), then local (./CLAUDE.local.md, gitignored, for your own personal notes). Use /memory to view or edit what's currently loaded.
CLAUDE.md is separate from "auto memory" — notes Claude writes about your project on its own (build quirks, debugging insights) into ~/.claude/projects/<project>/memory/MEMORY.md and topic files, capped at the first 200 lines / 25KB loaded per session. CLAUDE.md is what you author; auto memory is what Claude accumulates.
Subagents
Subagents are specialized assistants for focused sub-tasks, each running "in its own context window with a custom system prompt, specific tool access, and independent permissions." Delegating to a subagent keeps your main session's context clean — a subagent can burn through dozens of file reads exploring a subsystem without any of that noise landing in your main conversation, returning only its conclusion. Claude Code ships three built-in subagents: Explore (read-only search), Plan (research for plan mode), and general-purpose (exploration plus modification). You define your own as markdown files with YAML frontmatter in .claude/agents/ (project-level) or ~/.claude/agents/ (user-level).
---
name: test-runner
description: Runs the test suite and reports failures. Use after any code change to verify correctness.
tools: Bash, Read, Grep
model: claude-sonnet-5
permissionMode: acceptEdits
---
You are a focused test-running subagent. Run the project's test
suite, summarize any failures with file and line references, and
suggest the likely cause. Do not modify source files yourself —
report findings back to the main agent instead.Because a subagent has its own tool access and permission mode, you can hand it narrower privileges than the main session — a test-runner subagent that only needs Bash, Read, and Grep has no business also holding Write or Edit.
Controlling How Much Claude Code Can Do
☺ Like you're 10: Permission modes are the house rules you give a teenager with the car keys — sometimes you want a text before every trip, sometimes a curfew and a full tank check is enough.
Permission modes
Permission modes set the default posture for every tool call in a session. There are six.
| Mode | Behavior | Typical use |
|---|---|---|
default ("Manual") | Reads freely; every edit, command, or other action prompts for approval | Everyday interactive coding, reviewing each step |
acceptEdits | Auto-approves file edits and common filesystem commands, nothing beyond that | Fast iteration on changes you already trust |
plan | Research and propose only — no source edits until you approve the plan | Reviewing an approach before anything touches the repo |
auto | A background classifier model auto-approves or auto-denies actions by risk | Semi-autonomous runs where risky actions still get caught |
dontAsk | Auto-denies anything not already pre-approved | CI pipelines running against a fixed allowlist |
bypassPermissions | Skips virtually all permission checks | Isolated, disposable sandboxes only |
bypassPermissions is documented for isolated environments only — it cannot even be run as root or with sudo. Never use it against a real repository with live credentials, production access, or anything you'd mind losing.
Plan mode
Plan mode "tells Claude to research and propose changes without making them. Claude reads files, runs shell commands to explore, and writes a plan, but does not edit your source." Enter it with Shift+Tab or by prefixing a prompt with /plan. Claude uses this to gather context and reason about an approach — sometimes handing the research off to the built-in Plan subagent — then presents a plan for you to read before anything changes. Once it's done, you choose how to proceed: "Yes, and use auto mode," "Yes, manually approve edits," or "No, keep planning" if the approach needs adjustment.
Hooks
Hooks are user-defined shell commands that execute at specific points in Claude Code's lifecycle, giving you "deterministic control... rather than relying on the LLM to choose to run" a check. Key events include SessionStart, UserPromptSubmit, PreToolUse (can block the tool call outright via exit code 2), PostToolUse, Notification, SubagentStart/SubagentStop, PreCompact/PostCompact, Stop, and SessionEnd. Hooks are configured in .claude/settings.json (project) or ~/.claude/settings.json (user), matched against tool names.
A common pattern is gating risky commands on a passing test suite. A PreToolUse hook matching the Bash tool can inspect the command about to run, and if it's a git commit, run your lint and test scripts first — exiting with code 2 (blocking the commit) if either fails.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": ".claude/hooks/gate-commit.sh" }
]
}
]
}
}gate-commit.sh checks whether the pending command contains git commit; if it does, it runs your test and lint commands and exits 2 (blocking the commit) on any failure, or 0 to let it through. Claude sees the block and can react — fix the failing test, then retry — without you having to babysit every commit.
Foxy: bypassPermissions sounds amazing — no more clicking "approve" forty times an hour!
Professor Owl: Sounds amazing right up until Claude misreads one requirement, and "edit the whole tree" becomes literal.
Pico the Penguin: That's why I start in plan mode — I read the whole plan before a single file changes.
Benny the Beaver: And I keep a hook at the door: no commit gets through until tests and lint say yes. Autonomous, not unsupervised.
Start in plan mode so you review the approach before any file changes; grant only the tool access a task actually needs (a narrowly-scoped subagent, or acceptEdits instead of bypassPermissions); and add a PreToolUse hook that blocks commits or deploys until lint and tests pass. Claude still moves autonomously — but every irreversible step has a deterministic gate in front of it.
Running Claude Code with bypassPermissions (or a very broad acceptEdits/allowlist) against your real repository, no plan step, and no hooks — Claude edits, runs commands, and commits with nothing checking its work. One misread requirement or a destructive shell command executed with good intentions can leave you with unintended changes across the tree before you notice.
Claude Code in VS Code
The "Claude Code" (also called "Claude for VS Code") extension requires VS Code 1.94.0 or later and installs from the Extensions view by searching "Claude Code." It adds a native graphical panel, opened via the Spark icon in the Editor Toolbar or Activity Bar, that sits alongside your integrated terminal rather than replacing it.
Inside the panel you get inline side-by-side diffs with accept/reject controls for every edit, @-mentions to pull specific files, folders, or line ranges into context (for example @app.ts#5-10), and a plan mode UI that "automatically opens the plan as a full Markdown document where you can add inline comments" before approving it. The extension also gives you conversation and session history browsing, checkpoints to rewind code or fork a conversation down a different path, in-panel MCP server management via /mcp, and plugin management via /plugins.
The extension bundles its own copy of the CLI for the chat panel, but that's not the same as having the standalone claude command available. If you want to run bare claude in the integrated terminal — for scripting, hooks, or just habit — install the standalone CLI separately.
In a real (or throwaway) git repository opened in VS Code with the Claude Code extension installed, run /init to generate a starter CLAUDE.md, then trim it to a handful of lines about your stack and test command. Enter plan mode (Shift+Tab) and ask Claude to add a small, low-risk feature — read the plan it produces before approving anything. Finally, add a PreToolUse hook in .claude/settings.json that blocks any Bash command containing git commit unless your test command exits 0, and confirm a failing test actually blocks the commit.
You should now be able to explain Claude Code's core loop — gather context, take action, verify work, repeat — and how it maps onto the same agent loop the Claude Agent SDK exposes. You should also be able to say how CLAUDE.md differs from auto memory, when a subagent earns its own context window, and how plan mode, permission modes, and hooks combine to keep an autonomous agent from doing something irreversible. Next up: Safety and Responsible Use, for the broader guardrails that apply beyond just Claude Code.
Check your answers
- What are the three phases of Claude Code's core loop, and why does verification lean on tools like linters and test suites instead of Claude's own judgment? Gather context, take action, verify work — repeated turn by turn until Claude responds with no further tool calls. Deterministic checks (linters, type checkers, tests, runtime errors) give Claude actual ground truth about whether an action worked, rather than relying on self-assessment.
- What's the difference between CLAUDE.md and auto memory? CLAUDE.md is a file you author and check into your project — persistent instructions Claude reads every session, loaded in a managed-policy → user → project → local hierarchy. Auto memory is separate: notes Claude writes on its own about build quirks and debugging insights, capped at 200 lines / 25KB per session.
- How do plan mode, permission modes, and hooks work together to keep Claude Code safe to run autonomously? Plan mode lets you review an approach before any file changes; permission modes (like
acceptEditsinstead ofbypassPermissions) scope what gets auto-approved; andPreToolUsehooks add a deterministic gate — for example, blocking agit commituntil lint and tests pass — so irreversible actions always have a check in front of them, not just good intentions.