Claude Code 2.1.302: Fork Subagents Default On — Batch Tasks Lose Automatic Isolation
Claude Code 2.1.302 enables fork subagents by default in headless and editor entry points, breaking the assumption that batch subtasks run in isolated contexts; the article details trade-offs between fork (shared history, tools, model, cache, permissions) and custom subagents (fresh context, configurable tools/model), and guides choosing based on whether subtasks need shared context or independent isolation.
Fork Subagents Enabled by Default in Headless and Editor Entry Points
A nightly batch job built with the Agent SDK previously assumed each subagent worked in an independent context: the main session dispatched work, subagents read files and ran commands, and only returned summaries. After upgrading to Claude Code 2.1.302, that assumption no longer holds automatically. The official changelog for 2.1.302 states that fork subagents ( subagent_type: "fork") are now enabled by default in claude -p, the Agent SDK, the desktop app, and VS Code; previously they were only default in interactive terminals.
This change is not merely a toggle. A fork is not "another kind of subagent" but a branch of the main session: it inherits the full conversation history, system prompt, tools, and model. Default-on does not mean every subagent becomes a fork; it means Claude can choose fork when dispatching in those entry points, and the option is available by default. Batch tasks can no longer treat input isolation as a default property of subagents; it now depends on whether the dispatched agent is a fork or a custom subagent.
Four Default Changes in the Same Release
Released on October 16, 2026, version 2.1.302 changed four defaults in a single changelog entry:
Fork subagents enabled by default in the above entry points; CLAUDE_CODE_FORK_SUBAGENT=0 disables this; claude mcp serve does not provide fork.
When fork mode is on, the desktop app and VS Code run all main-session subagents in the background (terminal already did); turning fork mode off lets Claude wait for subagents.
Subagent-initiated Agent calls now default to foreground in claude -p, Agent SDK, desktop, and VS Code when fork mode is on. claude -p and Agent SDK sessions without an explicit permission mode now start in default mode (instead of possibly auto) when using third-party providers, telemetry off, or fresh installs; --permission-mode auto still retains auto.
These four changes interlock in a batch pipeline: fork determines what the subagent sees, backgrounding determines when it runs, foregrounded nested calls determine whether the parent waits for results, and the permission default determines whether tool calls are rejected. Upgrading and only checking for task errors may miss changes in any of these four layers.
Terminal fork default is not new: docs show interactive terminals have had it since 2.1.232; 2.1.302 extends it to claude -p, Agent SDK, desktop, and VS Code. Fork became default where humans watch first, then entered unattended tasks.
Fork Sacrifices Input Isolation
The documentation's fork comparison table states the semantics directly. Fork inherits the main session's full conversation history, same system prompt and tools, same model, and shared prompt cache. A custom subagent gets a fresh context with only the delegated prompt; its system prompt, tools, and model come from its own definition file, and its cache is independent.
Context: Fork — full conversation history; Custom — fresh context, only delegation prompt.
System prompt & tools: Fork — same as main; Custom — from definition file, filtered again when backgrounded.
Model: Fork — same as main; Custom — set by model field, can use a smaller model.
Prompt cache: Fork — shared with main; Custom — independent cache.
Permission mode: Fork — inherits main, cannot exit plan mode; Custom — can set permissionMode, but main overrides when in auto, bypassPermissions, or acceptEdits.
Further derivation: Fork — cannot spawn another fork; can spawn normal subagent, depth limit returns Agent error; Custom — can spawn normal subagent, depth limit recalls Agent.
The last two rows are easily overlooked. Docs only add a type restriction for fork derivation: cannot spawn another fork; at depth limit it still has the Agent tool but calls return an error. So "fork unsuitable as recursive root" only holds if the next layer must also inherit full history and use fork. On permissions, 2.1.285 changelog notes fork runs under the parent's permission mode and cannot exit plan mode; custom subagent can set permissionMode but main overrides in auto, bypassPermissions, or acceptEdits.
Input is shared, output remains separate. Docs explicitly state fork's tool calls stay in its window; only the final result returns to main. Thus fork gives up input isolation, not output isolation. This distinction matters: main context isn't polluted by fork's intermediate steps, but fork sees everything already in main — credentials, customer data, unpublished changes — as a direct consequence of inheriting full history.
Background execution has an exception worth noting: docs say background subagents run on a smaller built-in toolset, except conversation forks and resumed foreground subagents. So a custom subagent going background loses tools; a fork retains the full toolset. This is counter-intuitive for isolation: the more context a fork inherits, the more tools it keeps.
Cache Reuse Does Not Guarantee Lower Total Cost
Docs give a conditional cost judgment: because fork shares system prompt and tool definitions with parent, its first request reuses the parent's prompt cache; for tasks needing the same context, fork is cheaper than a new subagent. This is often truncated to "fork saves money," dropping the condition and leading to wrong choices.
Cache hit avoids rebuilding the shared prefix on the first request, but the inherited conversation stays in context for every subsequent turn. Fork also locks to the main session's model — cannot specify model: haiku in the definition to downgrade exploration tasks — and cannot narrow the toolset. Cost must be evaluated in two scenarios: a short-turn, context-heavy side task where fork saves re-explaining background; versus a many-turn, tool-heavy task that doesn't need main history, where a custom subagent with a smaller model and narrower tools is often cheaper.
This embodies "context reuse trades cost, isolation loss trades consistency." Fork uses shared prefix for first-request cache hit and inherited history for consistency without re-briefing; the price is that model, tools, permissions, and data exposure all follow the main session. It's not a free cost optimization but a packaged trade-off of several isolations.
Independent Items vs. Shared Context: Different Choices
The most common batch-task mistake is treating "a batch of independent items" as "multiple side branches from the same context." These two scenarios yield opposite results under fork.
Suppose a nightly job processes dozens of unrelated PRs. Each PR has different context — files read, failed tests, prior discussions — that must not leak to the next. Use a custom subagent per item: fresh context, delegation prompt specifies repo path, branch, error details, tools limited to needed read/write set. If you open a fork per item in the same main session, later items inherit earlier conversations; previous PR conclusions become "known background" for later PRs, causing silent judgment drift.
Conversely, if the main session has already read thirty files and derived migration constraints, and now needs to simultaneously draft a migration checklist, add tests, and evaluate rollback plans — all three branches need the same context. Making each re-read files is wasteful; fork fits. Docs list "other subagents need too much background to be useful" and "parallel attempts from the same starting point" as fork-appropriate scenarios. Here consistency comes from shared context, not smarter prompts.
Tool boundary is the second dividing line. A review-only custom subagent can define only Read, Grep, Glob, Bash, excluding Edit and Write; fork inherits main's tools — if main has write tools, fork has them. If parallel forks all edit files, docs offer isolation: "worktree": fork writes to an independent git worktree instead of the current checkout. Without this, concurrent forks editing the same workspace raise conflict risk with parallelism.
When nested delegation is needed, check whether the next layer also needs fork. Fork cannot spawn another fork; custom subagent can continue delegating within the default three-layer depth if it retains the Agent tool. A review subagent spawning a verifier per finding can use fork as root if verifiers only need independent context; only if verifiers must also inherit the same full history and use fork does the structure need changing.
On October 21, 2.1.307 added a related improvement: concurrently launched forks are now told which launch is theirs, reducing cross-pickup of work. This improvement itself confirms that parallel fork coordination cost is real and doesn't vanish just because the default is on.
Background Execution Does Not Mean Early Process Exit
With fork mode on, desktop and VS Code background all main-session subagents (terminal already did); turning fork mode off lets these entry points wait for subagents. claude -p and Agent SDK retain "Claude may decide whether to wait, or wait per your request." Backgrounding's direct benefit is unblocking the main loop, but it has three side effects in unattended tasks.
Background subagent permission prompts bubble to main. Docs say if the answer is a longer-lasting grant (e.g., session-wide), Claude Code applies it to the whole session including main. One subagent's approval can widen the entire pipeline's permission surface — acceptable when supervised, but unattended runs need a callback or prompt tool to catch it.
Subagent's own Agent calls default to foreground. In claude -p and Agent SDK with fork mode on, the parent waits for each subagent's report; with fork mode off, nested subagents launch in background. So default config makes "fork default on" and "nested subagents background, parent doesn't wait" mutually exclusive. Multiple nested calls can still fire concurrently, but parent waits for results; to restore nested background you must turn off fork mode, losing fork's default capability and, in terminal/desktop/VS Code, reverting top-level subagents from "always background" to "can wait." This is the most practical coupling in the 2.1.302 changes.
Background doesn't equal early exit, but waiting has a ceiling. Headless docs state after stdin closes, claude -p can keep waiting for background commands, background subagents, and workflows; but unless main's own background commands are still running, it stops after 10 minutes of continuous idle waiting, discarding partial results. This ceiling maps to CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS default 600000 ms; set to 0 for unlimited wait. Main's own background commands are an exception — they keep the process alive until command ends or times out. Batch jobs relying on long-running subagents hit a 10-minute real boundary; treating background as "fire and forget" or waiting as unlimited both misjudge runtime.
Permission Defaults Split Unattended Tasks into Two Categories
Before 2.1.302, claude -p and Agent SDK on third-party providers, telemetry off, or fresh installs might start in auto mode due to missing feature flags. 2.1.302 changes these sessions to default mode. Docs explain: from 2.1.302, claude -p and Agent SDK sessions without an explicit permission mode start in Manual mode (config shows default); tool calls needing approval are rejected unless allowed via allow rules, hooks, canUseTool callback, or --permission-prompt-tool. To keep auto, explicitly pass --permission-mode auto or set permissionMode: "auto" in SDK.
The subtlety: not all entry points changed together. Docs' starting-point table shows interactive terminal and VS Code have had built-in auto default since 2.1.283; claude -p and Agent SDK default to default. Without explicit permission mode, a human running in terminal and a CI job start in different modes. If CI tasks suddenly see tool calls rejected after upgrade, check whether they ever explicitly set a permission mode.
Explicit --permission-mode auto isn't an unconditional guarantee. Docs say when flag or default selects auto but the session doesn't meet auto's availability conditions (e.g., model doesn't support it or settings disable auto), the session still starts in Manual. Unattended tasks treating auto as a given should verify actual mode at startup or prepare allow rules and prompt tools as fallback.
Fork amplifies this default. Because fork runs under the parent's permission mode, if parent is Manual, fork's writes require approval; unattended without approval channels, those calls are rejected. Parent auto → fork auto. Permission default isn't just about the main session's first command; it propagates down every fork.
To prevent Claude from auto-spawning forks in unattended tasks, the environment variable isn't enough. CLAUDE_CODE_FORK_SUBAGENT=0 disables fork mode (Claude's default behavior of spawning forks); docs note that in interactive sessions /subtask can still launch fork when fork mode is off. Agent(fork) deny rule is more direct; SDK equivalent is disallowedTools: ["Agent(fork)"]; but this blocks Claude's autonomous fork spawn, not a global guarantee against explicit /subtask. Unattended scenarios usually lack manual /subtask, so deny suffices; to also block explicit /subtask, docs offer no guarantee — restrict at the outer entry point.
{
"permissions": {
"deny": ["Agent(fork)"]
}
} claude mcp serveis another easily miscalculated entry. 2.1.302 changelog explicitly says it does not provide fork; MCP docs currently only describe exposing Claude Code tools to MCP clients, not listing fork as a callable type. Scope per changelog; don't count MCP server as a fork host.
Documentation vs. Changelog Coverage
Doc pages may lag behind changelog; version facts per 2.1.302 changelog, mechanism semantics per docs. Sub-agents doc includes 2.1.302 defaults and fork comparison table; permissions doc covers starting-mode change; core semantics don't conflict. Changelog's "third-party provider, telemetry off, fresh install" scope appears narrower than docs; docs explain: pre-2.1.302, -p /SDK sessions missing feature flags might have fallen into auto; changelog lists conditions where change occurs, not all conditions.
MCP docs don't mention claude mcp serve lacking fork — only changelog does. Another not-fully-documented boundary: env var, deny rule, and explicit fork interaction. Docs say fork mode off still allows /subtask to launch fork, and don't state whether Agent(fork) deny overrides /subtask. SDK explicit subagent_type: "fork" interception by env var is also not spelled out. In unattended tasks, deny to stop autonomous fork spawn works; but it's not a global guarantee covering all fork entry points.
One unanswered question from public data: how much does fork's cache reuse actually save? Docs give qualitative judgments — "first request reuses parent prompt cache" and "cheaper for tasks needing same context" — no hit rates, turn distributions, or cross-model comparisons. Building fork into a cost model requires your own load data, not doc extrapolation.
For batch tasks, answering two questions suffices: does the subtask need the main session's context? Does it need independent tools, model, or permissions? If both answers are no, fork simplifies; if either is yes, fork's defaults shouldn't decide for you.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architecture Development Notes
Focused on architecture design, technology trend analysis, and practical development experience sharing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
