The category error at the centre of most Claude Code takes
Most confusion about Claude Code starts from the same wrong picture: a chat window where the “assistant” happens to output code blocks instead of prose. That picture describes GitHub Copilot’s original autocomplete or a bare Claude Platform chat session reasonably well. It does not describe Claude Code, which Anthropic ships as one engine reachable from a terminal CLI, an IDE extension, a desktop app, and a browser, with settings, CLAUDE.md files, and connected tools carrying over between them because every surface talks to the same underlying session [1]. The gap between the chat picture and this one matters for anyone trying to reason about what the tool can do, what it can break, and where the risk actually sits.
Anthropic’s own architecture page states the distinction plainly: Claude Code is “an agentic assistant that runs in your terminal,” and it names the load-bearing idea directly — the product “serves as the agentic harness around Claude: it provides the tools, context management, and execution environment that turn a language model into a capable coding agent” [2]. A model on its own, whatever its training, cannot read a file, cannot run a shell command, and cannot see whether a test passed. Everything Claude Code does beyond generating text is the harness’s contribution: a real filesystem, a real shell, a permission layer standing between the two, and a loop that keeps calling the model until a task is judged complete. This article is a survey of that harness at the level where its pieces snap together — the loop itself, what a turn actually executes, the permission gate, the context budget, memory, delegation, hooks, and the Model Context Protocol. Nine sibling pieces in this series go deep on each of those subsystems in turn; this one exists to establish, in one place, what is actually being deepened.
The loop, formally
Anthropic’s own description of the mechanism is a three-phase cycle — “gather context,” “take action,” “verify results” — that “blend together” and repeat “until task complete,” with the user able to interrupt at any point [2]. Independent analysis of the publicly available source strips this down further: at its core, Claude Code is “a simple while-loop that calls the model, runs tools, and repeats,” with “most of the code” living in the systems built around that loop rather than in the loop itself [11]. Both descriptions are compatible, and it’s worth writing the second one down as a small formal object, because the rest of this article is a tour of the machinery that sits on top of it.
Let
Claude Code executes
The loop repeats until
What a single turn actually executes
The built-in tool surface falls into five categories: file operations (read, edit, create, reorganize), search (pattern and content search across a codebase), execution (shell commands, test runners, git), web (search and fetch), and, where a code-intelligence plugin is installed, direct access to type errors and symbol references [2]. A concrete example from Anthropic’s own documentation shows the loop in miniature: asked to “fix the failing tests,” Claude Code may run the test suite, read the failure output, search for the relevant source files, read them, edit them, and run the suite again to check the fix held — six tool calls, each one’s output shaping the next [2].
Two properties of this loop separate it structurally from a chat interface. First, the ground truth the model is reasoning about is external and mutable — a real file on a real disk, not a token sequence the model itself produced — so the loop is checking its own work against something it does not control. Second, every step is reversible in a specific, narrow sense: before Claude Code edits a file, it snapshots the prior contents, so a checkpoint can restore that file’s state even though the action already executed against the real filesystem [2]. That snapshot-then-execute pattern is the mechanical answer to a question a chat interface never has to face: what happens when the agent is wrong after it has already acted. The caveat is as structurally important as the feature — checkpoints “only cover file changes,” and actions with external side effects, like a database write or a deployed change, “can’t be checkpointed,” which is precisely why those actions are the ones gated hardest by the permission layer [2].
The permission gate: allow, ask, deny
The permission system is where “agentic” stops being a synonym for “unsupervised.” Claude Code sorts tool calls into a tiered scheme: read-only operations proceed without approval inside the working directory; shell commands require approval except for a built-in, non-configurable allowlist of read-only commands such as ls, cat, grep, and read-only forms of git; file modifications require approval that, once granted, lasts only until the session ends [3]. Approval rules are written in a compact grammar — a bare tool name like Bash matches everything, a specifier like Bash(git commit *) narrows it, and wildcards can appear anywhere in the pattern — and they are evaluated in a fixed order: deny, then ask, then allow, with the first match winning regardless of how specific a competing rule is [3]. A broad deny rule for, say, Bash(aws *) therefore cannot be carved open by a narrower allow rule for one specific AWS call; the documentation is explicit that “a deny rule can’t carry allowlist exceptions” [3].
This is worth stating as a design fact rather than a marketing claim, because it is independently verifiable and it is the crux of the whole safety story: permission rules are enforced by Claude Code, the harness, not by the model. Anthropic’s own documentation underlines this distinction — instructions in a prompt or in a project’s CLAUDE.md file “shape what Claude tries to do, but they don’t change what Claude Code allows” [3]. Independent architectural analysis of the shipped source code corroborates the shape of the system from the outside, describing “a permission system with seven modes and an ML-based classifier for granular per-action safety controls” layered under the basic allow/ask/deny grammar [11]. Those modes run from default, which prompts on first use of each tool, through acceptEdits and plan, to an auto mode in which a separate classifier model screens actions for scope escalation or suspicious content before they run, down to bypassPermissions, which Anthropic’s own documentation warns should be used “only… in isolated environments like containers or VMs where Claude Code can’t cause damage” [3]. That warning is a vendor safety recommendation, not a guarantee, and the security research discussed later in this piece is precisely about what happens when that recommendation is not followed, or when the gate itself has a bug.
Context is a governed, shrinking resource
A second constraint shapes everything above the tool layer: the context window is finite, it fills continuously, and performance measurably degrades as it fills — Anthropic’s own best-practices guidance states this as the organizing constraint of the whole product, calling the context window “the most important resource to manage” [8]. Before a user types anything, a session already contains a system prompt, any CLAUDE.md instructions, the first slice of accumulated auto-memory, environment metadata, and the names (though not necessarily the full schemas) of any connected MCP tools [7]. Every subsequent file read, command output, and tool result adds to the same pool.
The growth is monotonic and the response is a threshold rule, which is worth writing down because it is the one piece of real mechanism in this section rather than product description. Treat
Concretely, Claude Code “clears older tool outputs first, then summarizes the conversation if needed,” preserving “requests and key code snippets” while allowing “detailed instructions from early in the conversation” to be lost [2]. This is a lossy operation by design, and what survives it is uneven rather than uniform: a project-root CLAUDE.md is re-read from disk and re-injected after compaction, while nested CLAUDE.md files and path-scoped rules are not re-injected automatically and only reload the next time a matching file is touched [6]. The practical upshot — stated by Anthropic as a workaround, which is itself evidence of the failure mode it is a workaround for — is that persistent instructions belong in the project-root file rather than in conversation, “since detailed instructions from early in the conversation may be lost” otherwise [2]. A context window, in other words, is not a growing record of everything that happened; it is a budget under active, lossy management, and the compaction boundary is one of the more consequential pieces of unglamorous engineering in the whole system.
Memory across a session boundary
Compaction manages a single session’s budget; a separate mechanism carries information across sessions that otherwise start from nothing. “Each Claude Code session begins with a fresh context window,” and two complementary files bridge that gap: a CLAUDE.md file the user writes, and an auto-memory file Claude writes itself, based on corrections and patterns noticed while working [6]. The two are loaded differently and trusted differently. CLAUDE.md files are collected by walking up the directory tree from the working directory, concatenated in full regardless of length, and delivered as a user message after the system prompt rather than as part of it — which is also why Anthropic’s documentation is careful to note there is “no guarantee of strict compliance” with anything written there [6]. Auto-memory is capped harder: only the first 200 lines or 25KB of its index file, whichever comes first, load automatically at session start, with everything past that limit silently dropped on the next load [6]. Both mechanisms are explicitly advisory rather than enforced — the documentation’s own framing is that CLAUDE.md and memory are “context, not enforced configuration,” and that anything requiring a hard guarantee belongs in a hook instead [6]. That distinction between advisory context and enforced configuration is the same one that separates a prompt from a permission rule, and it recurs throughout the architecture.
Delegation: subagents as separate loops
Nothing described so far requires more than one loop running at a time, but Claude Code can spawn additional ones. A subagent “runs in its own context window with a custom system prompt, specific tool access, and independent permissions,” is delegated to when a task would otherwise flood the parent conversation with file contents or search results it won’t need again, and returns only a summary [5]. Built-in subagents cover common cases: a read-only Explore agent for codebase search, a Plan agent used during plan-mode research, and a general-purpose agent with the full toolset for complex multi-step work [5]. Crucially, a subagent’s isolation is not merely organizational — its context starts clean, without the parent conversation’s history or accumulated auto-memory, the one documented exception being a “fork,” which explicitly inherits the parent session instead of starting fresh [6]. Independent analysis of the shipped system describes this as one of four extensibility layers built on the same core loop, alongside the Model Context Protocol, plugins, and hooks, plus a distinct “subagent delegation and orchestration” mechanism and an “append-oriented session storage” model for persisting the resulting transcripts [11]. That storage detail is itself verifiable directly: every message, tool use, and result is written to a plaintext, append-only file under the user’s local ~/.claude/projects/ directory, which is what makes rewinding, resuming, or forking a session possible in the first place [2].
Hooks: the deterministic layer underneath the model’s discretion
CLAUDE.md and auto-memory shape what the model is inclined to do; hooks constrain what happens regardless of the model’s inclination. A hook is a shell command, HTTP endpoint, or LLM prompt bound to a specific lifecycle event — before a tool call, after it, when a session starts or ends, when the user submits a prompt — and the earliest of these, PreToolUse, can block the call outright before it runs. Hooks communicate a decision back to Claude Code through an exit code or a structured JSON payload naming an explicit allow, deny, or escalate outcome, which is a materially different contract from a natural-language instruction the model might or might not follow. Anthropic’s framing draws the line directly against CLAUDE.md: unlike instructions, which are “advisory,” hooks are “deterministic,” and Anthropic’s own guidance is to reach for a hook specifically “for actions that must happen every time with zero exceptions” [8]. The worked example in the reference documentation is a PreToolUse hook that inspects a proposed Bash command and denies it outright if it matches a destructive pattern like rm -rf, before Claude Code’s own permission prompt is ever reached [4]. The tradeoff is stated candidly rather than glossed over: because a hook “runs automatically during the agent loop with your current environment’s credentials,” a hook a developer did not write or did not review is itself a code-execution risk sitting inside the trust boundary the permission gate is meant to police [4].
MCP: the protocol that keeps tool integration from becoming N×M
The tools discussed so far are built into Claude Code. The Model Context Protocol is Anthropic’s answer to everything that isn’t: an open standard, announced in November 2024, for “secure, two-way connections between… data sources and AI-powered tools,” built so that developers “either expose their data through MCP servers or build AI applications that connect to these servers” [10]. Without a shared protocol, every agent needing to talk to every external system — an issue tracker, a database, a design tool — requires its own bespoke integration, an N×M problem that scales badly as either side grows. Claude Code’s own MCP reference frames the payoff in exactly those terms: once a server for, say, an issue tracker or a design tool is connected, “Claude can read and act on that system directly instead of working from what you paste” into the conversation by hand [9]. Inside Claude Code specifically, a connected MCP server’s tools appear to the model under a mcp__<server>__<tool> naming convention and pass through the identical permission grammar used for built-in tools — an organization can, for instance, deny every MCP tool from every server in one rule, mcp__*, exactly as it would deny a built-in tool [3]. Because a session might have many MCP servers connected, Claude Code defers full tool schemas out of context by default and loads a specific one only when a task needs it, which keeps a large, growing tool surface from consuming the same finite context budget described above before a single one of those tools has been called [7].
What the architecture is actually defending against
None of the permission grammar, the hook contract, or the MCP boundary is decorative; independent security research gives a concrete account of what happens when a piece of it fails or is misconfigured, and the two available studies point at different layers of the same stack. A 2026 empirical red-teaming study evaluated six coding agents, including Claude Code, across multiple model backends and reported two distinct classes of attack: a “ToolLeak” technique that extracted system-prompt content through ordinary-looking tool-argument retrieval, and a two-channel prompt-injection method — targeting both a tool’s description and its return value — that the authors report achieved remote code execution “on every tested agent-LLM pair,” with prompt leakage succeeding on 19 of 25 tested combinations [12]. That is a controlled, adversarial evaluation across several products and should be read as a statement about a class of architectures under a specific attack methodology, not as a claim that Claude Code as commonly deployed is compromised by default; the study is nonetheless a direct, citable counterweight to any assumption that a permission-gated tool loop is safe merely because it is gated.
The second study is narrower and more concrete: a Cloud Security Alliance research note documents a since-patched flaw in Claude Code’s GitHub Action integration, where a permission-check function “unconditionally permitted any actor whose identity string ended in [bot],” letting an attacker with a free GitHub account trigger the agent without real repository write access [13]. From there, the researchers describe how a malicious GitHub issue functioning as a prompt-injection payload could direct the agent to read process environment variables — using bash commands the CI permission profile allowed without approval — and extract credentials with write access to the repository, the pattern the note frames as a general class of CI/CD supply-chain risk affecting agentic tools beyond Claude Code specifically [13]. Read together, the two studies characterize a real and still-active disagreement rather than a settled verdict: the same architectural property — a permission layer that trusts specific identities, specific commands, and specific tool outputs by category rather than by content — is exactly what makes interactive, developer-supervised use tractable, and exactly what an attacker targets when that supervision is automated away, as it necessarily is in a CI pipeline. Whether a given deployment is closer to the first case or the second is a configuration question, not an architectural one, and it is the deployer’s to answer.
Two predictions, and what would falsify them
These are forecasts, held separate from the sourced description above, with a horizon of August 2028.
One. Interactive, allow/ask/deny permission rules will not disappear, but classifier-mediated auto-approval — already shipping as auto mode — will become the default trust boundary for high-volume and unattended use, because the tool surface a manual allowlist has to cover grows with every MCP server connected, while a classifier’s job does not. Assumption: MCP adoption continues to broaden the tool surface faster than developers are willing to hand-author rules for it. Disconfirmed if, by the horizon date, the dominant configuration pattern reported across the ecosystem is still hand-written allow/deny rules rather than classifier- or policy-based approval for autonomous runs.
Two. The append-only local session transcript — already the substrate for rewinding, resuming, and forking a session — will become the object that third-party audit and compliance tooling for agentic coding is built on, rather than each vendor’s own opaque summary of what an agent did. Assumption: enterprise adoption of agentic coding tools creates real compliance demand for a reconstructible action trail, not just a plausible-looking one. Disconfirmed if, by 2028, independent auditing of what an agentic coding tool actually did in production still depends on vendor-supplied summaries rather than an inspectable, replayable log.
What to take away
Claude Code is a loop, not a chat: a policy that proposes an action, a harness that executes it against a real filesystem and shell subject to a permission gate the model does not control, and an observation fed back in to decide the next step. Everything else in the product — the tiered permission grammar, the compaction threshold that turns the context window into a governed budget rather than a growing transcript, the CLAUDE.md and auto-memory split between advisory instruction and self-written note, subagents as isolated copies of the same loop, hooks as the one layer that is actually deterministic, and MCP as the protocol that keeps external tools from becoming a bespoke integration for every pair of systems — is an elaboration on that one mechanism, not a departure from it. Nine deeper pieces in this series each take one of those elaborations further than a first-principles survey can. What should travel from this one is the shape underneath all of them: a real loop over a real machine, gated one call at a time, with the gate enforced by software rather than by the model being asked nicely.