Chapter 1. What Claude Code Is, and the Four Places It Runs

Claude Code is Anthropic’s coding agent: you hand it a goal in plain language and it reads your files, edits them, runs commands, reads the output, and keeps going until the goal is met or it needs a decision from you. It ships as a terminal program first, with IDE plugins, a desktop app, and a hosted surface behind it. I run more than twenty live surfaces with it, alone.

This book is the manual I wanted when I started: a reference half checked against a live install, and a practice half written from the operating log. The install behind the reference half prints one line worth quoting before anything else:

$ claude --version
2.1.211 (Claude Code)

I verified the binary claims in this book against that build, on macOS, on 2026-07-27. Features that landed after 2.1.211 carry their version gate in the text.

How the agent loop works

The loop is one turn repeated. Your prompt joins the conversation, the model reads it along with its instructions and the context that has accumulated, and it responds with text or with a tool call. A tool call passes through a permission gate, executes, and its output lands back in the conversation as input for the next model response. The loop ends when the model decides the work is done, or when the gate hands control back to you. The same machine sits under each surface.

Three properties of that loop carry most of the weight.

First, the tools are real programs against your real filesystem. The CLI’s own help names Bash, Edit, and Read as its example list for the --tools flag; --tools "" disables all tools and --tools default enables all of them. An Edit is a write to disk. A Bash call is a process running with your user’s privileges. The permission gate stands between a suggestion and a mutation, and 2.1.211 ships six gate modes: acceptEdits, auto, bypassPermissions, dontAsk, manual, and plan. Permission rules take the form Tool or Tool(specifier), Bash(npm run *) for instance, and Claude Code evaluates them deny first, then ask, then allow, with the first match deciding.

Second, the loop leaves a record. Session transcripts are plaintext JSONL under ~/.claude/projects/. claude -c reopens the most recent conversation in the current directory and appends to it, and --fork-session copies history into a new session ID so an investigation can branch without contaminating the original. When a session goes wrong, you read the transcript instead of reconstructing events from memory.

Third, the loop manages its own context. Instructions from CLAUDE.md arrive as a user message after the system prompt, not inside it. When the window fills, Claude Code clears older tool outputs first, then summarizes the conversation; if a single oversized output refills the window after each summary, auto-compaction stops after a few attempts and surfaces a thrashing error rather than looping. Durable state lives on disk; the window is a working set.

The loop also runs headless. claude -p "prompt" executes one run and exits, and --output-format json wraps the result in an envelope whose keys include session_id and total_cost_usd. Print mode is implied when stdout is not a TTY: pipe the output and the envelope shows up without an explicit -p. Two sharp edges are worth carrying from day one. Streaming has strict pairing rules (-p --output-format stream-json is rejected without --verbose, with an exact error saying so), and the envelope’s subtype field reported success on a run that failed auth, alongside is_error: true and terminal_reason: "api_error". Scripts must check is_error and terminal_reason, not subtype. That flag family turns an interactive assistant into a scriptable unit of work.

Inside a session, slash commands steer the machine. /context renders context usage as a colored grid and lists the loaded memory files; /usage shows session cost and plan limits, with /cost and /stats as aliases; /clear starts an empty conversation (aliases /reset and /new); /compact summarizes on demand and takes focus instructions; /rewind rolls the conversation, the code, or both back to a checkpoint. Three of them, /status, /tasks, and /usage, run without interrupting a response; the rest queue until the turn finishes. Slash commands and skills are one surface: the --disable-slash-commands flag’s own help says it disables all skills.

Terminal, IDE, desktop, and web: one shared configuration

Anthropic’s docs count five first-party surfaces: the terminal CLI, a VS Code extension that also installs in Cursor, a JetBrains plugin, a desktop app, and a hosted surface at claude.ai/code. All five share the same CLAUDE.md files, settings, and MCP servers. I count four places, because the two IDE plugins are one kind of seat with two vendors. Moving between the seats changes where your hands are, and little else: the shared configuration spine travels with you.

The spine has layers: user settings in ~/.claude/, shared project settings in .claude/ inside the repository, a local overlay in .claude/settings.local.json, and a managed tier above them all. Precedence runs managed, then command-line arguments, then local, then project, then user. One set of files governs the agent no matter which seat you take it from.

The terminal CLI, the deepest surface

The terminal is the primary surface and the deepest one. On my machine, claude is a symlink at ~/.local/bin/claude pointing into ~/.local/share/claude/versions/2.1.211: a single Mach-O 64-bit x86_64 executable of 251,966,736 bytes, a native build rather than a wrapper script around Node.

The canonical install on macOS, Linux, and WSL:

curl -fsSL https://claude.ai/install.sh | bash

Windows takes irm https://claude.ai/install.ps1 | iex in PowerShell, or an install.cmd variant in CMD. The other routes:

Route Package Update behavior
Native installer install.sh / install.ps1 / install.cmd Auto-updates in the background
Homebrew claude-code (stable) or claude-code@latest No auto-update; brew upgrade; the stable cask runs about a week behind
WinGet Anthropic.ClaudeCode No auto-update; winget upgrade Anthropic.ClaudeCode
Linux repos Signed apt, dnf, and apk repositories under downloads.claude.ai/claude-code, each with stable and latest channels Through the package manager
npm @anthropic-ai/claude-code Requires Node 22 or later as of v2.1.198; pulls the native binary through per-platform optional dependencies

Requirements are modest: macOS 13.0+, Windows 10 1809+ or Server 2019+, Ubuntu 20.04+, Debian 10+, or Alpine 3.19+, with 4 GB of RAM. ripgrep is an additional dependency, bundled with most installs.

claude --help lists 12 commands: agents, auth, auto-mode, doctor, gateway, install, mcp, plugin, project, setup-token, ultrareview, and update. The help is not the whole surface. --bg starts a session as a background agent and hands the shell back, and the commands that manage those agents, attach, logs, stop, and rm, do not appear in the help at all. claude agents --json prints the live ones as a JSON array, pid, cwd, and session ID among the fields, and works without a TTY. One terminal can supervise many.

Two more flags shape how sessions start on a busy machine. -w/--worktree opens the session in an isolated git worktree (docs place it at <repo>/.claude/worktrees/<name>, with the name auto-generated when omitted) and accepts #<number> or a GitHub PR URL to branch from that PR; --tmux layers panes on top and refuses to run without --worktree. -n/--name sets a display name that shows in the prompt box, the /resume picker, and the terminal title; with several sessions live, the label is how you tell them apart.

The VS Code, Cursor, and JetBrains plugins

VS Code (Cursor runs the same extension) and JetBrains get plugins that put the agent beside the editor. Configuration is shared with the CLI, so a permission rule or a CLAUDE.md line written for the terminal binds the IDE seat too. From the terminal side, --ide auto-connects at startup when one valid IDE, and no other, is available. Two related preferences, autoConnectIde (default false) and autoInstallIdeExtension (default true), live in ~/.claude.json rather than settings.json, and settings.json ignores them without a warning if you put them there.

I use the IDE seat for reading: diffs beside source, long review passes. The estate work happens in terminals, several at once. That split is a workflow preference, not a capability ranking; the loop underneath is identical.

The desktop app

The desktop app runs the same agent in a standalone window, against the same CLAUDE.md files, settings, and MCP servers as the other seats. The shared spine is the load-bearing fact: a deny rule written once applies wherever the agent runs. My practice leans on the terminal, and the book’s coverage follows that weight.

The hosted seat at claude.ai/code

The hosted seat lives at claude.ai/code and rides the same configuration spine. The bridge between a local terminal and the hosted side is the Remote Control family, and my install shows its gate more than its features: claude remote, claude remote-control, claude rc, and claude sync all exist, and all four demand a claude.ai subscription login before they print help, so their flag surfaces are unmapped in this book. claude doctor reports Remote Control readiness as three separate checks and, on my machine, names the missing OAuth scope: user:profile. Where the install cannot see, the book says so.

How I checked the claims against 2.1.211

claude doctor on the reference machine reports Running: native (2.1.211), Commit: 17a4b6d7b2ee, Platform: darwin-x64, auto-updates disabled by an environment variable the report names (DISABLE_AUTOUPDATER), and a last update attempt that succeeded to 2.1.211 on 2026-07-16.

The reference half of this book draws on two sources: the official docs at code.claude.com/docs, and the binary itself. When the two disagree, the binary wins and I write the disagreement down. Reading the binary takes more than grep: strings -a over the 251,966,736-byte executable returns zero matches for help text it prints at runtime, so static enumeration fails and the command surface has to be probed live.

Two probe rules make that workable. Unknown commands do not error; the parser consumes them as the prompt argument, and a trailing --help then prints top-level help. The existence test for a command is therefore a byte comparison against a known-bogus control:

diff <(claude config --help) <(claude zzzbogusnotacommand --help)

That diff comes back empty on 2.1.211, which proves claude config is not a command anymore: the get/set syntax in older material is dead, and configuration now flows through settings files, --settings, --setting-sources, and the in-session /config. The same test shows there is no top-level claude serve (the MCP server starts with claude mcp serve) and that migrate-installer and bug are gone. Unknown options behave the opposite way: they fail with error: unknown option '--bogus-flag-xyz', so a flag the parser accepts exists, documented or not. That is how hidden flags like --max-turns and --thinking surfaced.

Docs-versus-binary conflicts are real, and one sits on a flag you will type often. The docs enumerate --permission-mode values as default, acceptEdits, plan, auto, dontAsk, bypassPermissions, and manual, describing manual as a v2.1.200+ alias for default. The binary’s error message on 2.1.211 lists acceptEdits, auto, bypassPermissions, manual, dontAsk, plan; it does not accept default. Script against the binary’s list.

The version pin cuts both ways. Docs features gated after this build are absent from it: the v2.1.214 modified frontmatter timestamp on memory files, the v2.1.216 over-limit warning in /context, the v2.1.217 fix for rules brace-expansion budgets. When this book cites one of those, the gate rides along.

The two halves: reference and practice

The book runs on two halves with two standards of evidence. The reference half covers the command surface, settings machinery, memory, and permissions, and each claim in it traces to a --help dump, a runtime probe, or a docs page. The practice half is what operating an estate with this tool teaches: the discipline that keeps concurrent sessions from trampling each other, and the failures, with dates and numbers attached, that bought each rule.

I hold the text to the rules I hold a deploy log to. Numbers are copied, not remembered. A missing detail is marked missing instead of smoothed over. A claim about software says shipped when it shipped and dark when it is dark. You are assumed competent; nothing here explains git or HTTP, and the pages go to what this tool does on this build and what running it hard looks like.

Start in the terminal. It is where I sit, and it is the one seat where the whole command surface, hidden pieces included, answers a probe.