Harness

Claude Code, taken apart

One harness seen two ways: from its command-line flags, and from inside a session.

Checked against the official docs on 2026-09-23, with Claude Code 2.1.281.

This page looks at Claude Code version 2.1.281, as of 2026-09-23. The first half comes from claude --help. The second half is written by the model running inside one Claude Code session, describing what it receives. The two views are different kinds of evidence. The flags show what someone can configure. The inside view shows what one particular setup actually delivers. Neither shows how any of it is implemented.

Both views are checked against the official docs, and each claim links the page that confirms it. Where the docs don't cover a claim, it's marked as observed. For a feature-by-feature comparison with Codex, see Claude Code vs Codex.

From outside: the flags

These are the CLI flags, sorted into the parts from the front page. The CLI reference documents all of them.

PartFlags
Who drives-p (answer one prompt and exit, instead of an interactive session), --max-turns, --max-budget-usd, --fallback-model
Tools--tools ("" turns off every built-in tool), --allowed-tools, --disallowed-tools, --mcp-config, --strict-mcp-config, --chrome
Context--system-prompt, --append-system-prompt, --autocompact (how full the context window gets before older turns are summarized), --add-dir, --exclude-dynamic-system-prompt-sections, --system-prompt-snapshot
Checks--permission-mode (manual, acceptEdits, auto, plan, dontAsk, bypassPermissions), --permission-prompts, --json-schema, --restricted
Memory--continue, --resume, --fork-session, --no-session-persistence
Delegation--agents (define subagents as JSON), --agent, --bg (run in the background), --worktree, --cloud
Interfacean interactive terminal by default; with -p, output as text, JSON or a JSON stream; --ide, --remote-control, --ax-screen-reader

Three ways to strip it down

Three flags each turn off a whole group of features at once. They draw the line in different places:

--bare: for speed and scripting
Skips hooks, CLAUDE.md discovery, auto memory, plugins and other background work. Any context has to be passed in explicitly with flags. Built-in tools are unaffected.
--safe-mode: for a configuration you can't trust
Turns off everything you've customized: CLAUDE.md, skills, plugins, hooks, MCP servers, custom agents. Built-in tools and permissions still work normally. It's meant for troubleshooting a broken setup.
--restricted: for safety
Removes the tools that run code (Bash and similar) and WebFetch, limits file access to the working directories, ignores settings files, and refuses to bypass permissions.

So Claude Code draws at least three boundaries around its core: what slows it down, what the user added, and what could do harm. A layer diagram of it would need all three.

From inside: what the model receives

This section describes the session that wrote this page: interactive, in the terminal, auto permission mode, Opus 5.5 with a 1M-token context window, with the owner's connectors and CLAUDE.md files. A different setup would look different.

A layered system prompt

The system prompt comes in sections: who the model is and how the harness works; guidance specific to this session; how to use the memory directory; the environment (working directory, whether it's a git repo, platform, model, date); a note on context management; and instructions supplied by each connected MCP server. The owner's CLAUDE.md files aren't in the system prompt. They arrive as a <system-reminder> attached to the first user message, with a note that they override default behavior. The docs confirm this: "CLAUDE.md content is delivered as a user message after the system prompt" (memory).

Since v2.1.277, Claude Code also reads AGENTS.md, the file Codex uses, when a project has no CLAUDE.md. A CLAUDE.md that imports @AGENTS.md still works and never loads it twice (same page).

Tools in two tiers

About 17 tools are fully loaded from the start: reading, editing and writing files; running shell commands; launching subagents; asking the user a question; invoking skills; publishing pages; and one called ToolSearch. Another 91 are listed by name only, including web fetch and search, plan mode, the browser, Gmail, Drive and Calendar. Their full definitions have to be fetched with ToolSearch before they can be called. Skills work the same way: about 30 appear as a name and a one-line description, and the full instructions load only when a skill is invoked.

Docs: tool search is on by default for MCP tools (MCP), and a skill's description is always in context while its body loads when invoked (skills). The counts are from this session.

This is context management applied to tools. A full tool definition takes up context on every turn, so the harness shows the model only a list of what exists and loads the details when needed. The survey of my own agents didn't turn up this problem, because each of them had at most one tool per agent.

Messages that arrive mid-conversation

The harness adds <system-reminder> blocks to the conversation as it goes. The model is told these come from the system, not the user, and to treat them that way. In this session they delivered the CLAUDE.md instructions, the user's email address for attribution only, how to attribute git commits, tools that became available partway through, and a notice that a file had changed on disk since it was last read.

The system prompt is fixed at the start. Reminders are how the harness updates what the model knows as the session goes on.

Observed. The docs mention system reminders only in passing, for example as the way hook output reaches the model (hooks).

Permissions, seen from the model's side

The model is told which mode it's in, and that a denied tool call means the user declined it. In auto mode, it's also told it can do more of its work through the shell. What it isn't given is the rule set, or whatever decides whether a call needs approval. From the model's side, permissions are something that happens to its calls, not something it can inspect.

The docs fill in what the model can't see. In auto mode, a classifier reviews each tool call and blocks anything irreversible, destructive, or aimed outside your environment. Deny and ask rules are checked before it. Claude Code also has an operating-system sandbox for shell commands, like Codex's. It's opt-in, through /sandbox, and it isn't turned on in this setup. When it is on, a blocked command's result tells the model which path or host was denied, so the model does see the sandbox's decisions.

Instructions from several places, in an order

The model gets guidance from the harness, the MCP servers, the user's CLAUDE.md, reminders and hooks. The harness says how they rank: the user's instructions override the harness's defaults, and hook output counts as feedback from the user. In this session the ranking mattered. The harness says to launch subagents when useful, while the owner's CLAUDE.md says to ask first, and the CLAUDE.md wins. Some of the harness's own tools, such as the multi-agent Workflow, require the user to opt in explicitly.

Memory and context

Memory is a directory of Markdown files, one fact per file, with an index file loaded at the start of each session. The model writes to it with the ordinary file tools. There's no dedicated memory tool. The docs call this auto memory and say it's on by default.

For context, the model is told that older turns will be summarized when the window fills, and that it doesn't need to wrap up early because of it. It can't see where the cutoff is. The docs are much more specific than what the model is told. The context window page lists what survives compaction: CLAUDE.md, auto memory and the plan are re-read from disk; up to five recently used files are re-read; invoked skills come back with a cap on their size. So the harness rebuilds part of the context after compacting. It doesn't just summarize.

What this adds to the survey

Next

The flags make experiments possible: give claude -p the same small task with the full default setup, with --bare, with --tools Read,Bash, and with a replaced system prompt. The model stays the same across runs. Only the harness changes.

Keeping this current

This repo's check.py compares the installed CLI and every doc page linked here against saved snapshots, and reports what has changed. A changed page means the claims that link to it need re-reading.