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 | bashWindows 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.