Two-patch changelog window (Oct 14–16, 2026) covering six transferable changes in Claude Code, each read against a parallel implementation in yoyo (Day 231) to expose analogous — or unpatched — failure modes. The recurring themes are input validation at the tool boundary (Read tool file types, MCP tool schemas, hook updatedInput), the anchor question for path fences after a cd, defaults for headless -p runs, and exit-code honesty: whether a process's exit status actually reflects what happened.
Key Points
Read tool hardens against special files and huge images: pipes/devices named like images are no longer slurped whole; images over 128 MB are refused; binary formats are no longer read as text.
MCP tool schema rejection no longer poisons a conversation: instead of 400-ing on every turn, the rejected tool is sent without parameters for the remainder of the conversation.
cwd anchor after cd: workflow scripts were refused or permission-prompted after a Bash cd, raising the open question of whether outside-cwd fences key off launch dir or live cwd.
Hooks: at most 12 instances of one hook event run concurrently; updatedInput from PreToolUse hooks is validated like model input.
claude -p defaults: with no permission mode given, -p starts in default mode on third-party providers; fork subagents are on by default in -p.
daemon stop exits 1 when the service is still present rather than optimistically printing "stopped".
Concepts
Read tool size gate — the pre-read check that decides whether a file is safe to load.
metadata.len() trust — using stat-reported file size as the sole gate; unreliable for non-regular files.
FIFO / named pipe — a non-regular file that reports length 0 but never reaches EOF for a reader.
MCP tool input schema — the JSON schema a server declares for a tool; rejection by the API fails the turn.
updatedInput — hook-supplied mutation of tool input, validated on the same footing as model-generated input.
Permission mode — the session-level policy governing tool approvals; implicit default in headless -p runs.
Fork subagent — a subagent spawned as a fork of the parent context, now default-on under -p.
Exit-code honesty — the principle that a process exit status must reflect the real outcome (still running, refused, etc.).
Details
1. Read tool: special files, oversized images, binaries
The Read tool previously loaded a pipe or device that merely looked like an image entirely into memory. Two hardening changes landed: images above 128 MB are refused, and binary formats that were being decoded as text — .xlsm, .parquet, .epub, .heic — are no longer treated as text reads.
The yoyo analogue is instructive because it fails differently. yoagent 0.25.7's ReadFileTool gates solely on metadata.len(). A FIFO reports length 0, so the gate passes and read_file on a FIFO hangs the session — measured and killed at 75 seconds. Filed as yoyo #1047.
Takeaway: a size gate is not a file-type gate. Detecting non-regular files (FIFO, character device, socket) must be a separate check from checking length.
Rendering diagram…
2. MCP tool input schema rejection
A conversation could fail every turn with a 400 when the API rejected an MCP tool's input schema. Claude Code now degrades: it sends that tool without parameters for the rest of the conversation, keeping the session alive instead of failing repeatedly.
yoyo has not probed this path, but exposure grew after the #1041 prefixing change let more servers connect — more connected servers means more schemas that can be rejected.
3. cwd anchoring for outside-cwd read fences
Workflow scripts were refused, or had to ask for permission, after a Bash cd in the same session. The underlying design question — the anchor question for any outside-cwd read fence — is whether the fence is measured against the launch directory or the live cwd. This remains open on yoyo #879.
4. Hook semantics
Concurrency cap: at most 12 instances of a single hook event run concurrently.
Input validation: updatedInput returned by PreToolUse hooks is now validated exactly like model input — unknown keys are dropped, and input that fails validation denies the call.
5. Headless -p defaults
claude -p invoked with no permission mode now starts in default mode on third-party providers.
Fork subagents are on by default in -p runs.
6. Exit-code honesty
daemon stop now exits 1 when the service is still present, instead of printing "stopped" and appearing successful. This belongs to the exit-code-honesty class tracked in yoyo #982 / #1026.
A related yoyo finding from the same day cuts the other way: a -p run that ends in StopReason::Refusalexits 0, reporting success for a refusal outcome. Noted as a comment on #1026.