v2.1.113 shipped Thursday with a change most people will never notice from the outside and that every serious operator should understand: Claude Code is no longer a bundled JavaScript program. The claude binary on your machine today is a native executable. No Node process, no node_modules, no JS runtime to warm up.
The release note is one line: *"Changed the CLI to spawn a native Claude Code binary (via a per-platform optional dependency) instead of bundled JavaScript."* The mechanics behind that sentence rewrite how Claude Code is distributed, updated, and verified.
The distribution architecture. Installs now fan out across eight per-platform packages: darwin-arm64, darwin-x64, linux-x64, linux-arm64, linux-x64-musl, linux-arm64-musl, win32-x64, win32-arm64. Whether you install via the curl script, Homebrew, WinGet, or npm install -g @anthropic-ai/claude-code, you get the same native binary — npm just pulls it through an optional dependency like @anthropic-ai/claude-code-darwin-arm64 and links it via postinstall. The installed claude binary does not itself invoke Node.
The binaries are large. The v2.1.113 linux-x64 build is ~236 MB; darwin-arm64 is ~205 MB. That's the cost of shipping everything statically linked instead of assuming a Node runtime.
Why this matters for your workflow.
- Cold-start latency disappears. Spawning a native binary is dramatically faster than booting a Node process and its module graph. For headless
claude -pinvocations in tight loops, cron jobs, or agent fleets, this is a real throughput win — especially on boxes where Node startup was the bottleneck. - Auto-update changes shape. Native installs update in the background on startup and periodically while running. Homebrew and WinGet stay on manual updates. If you're running headless agents via cron, pin your channel:
"autoUpdatesChannel": "stable"tracks about a week behind latest and skips releases with major regressions. Add"minimumVersion": "2.1.111"to set a floor that even stable can't downgrade past. - The npm install pathway still works, but it's now a wrapper around the same native binary.
npm install -g @anthropic-ai/claude-coderequires Node 18+ only for the postinstall step. Your package manager must allow optional dependencies. Alpine/musl users needlibgcc,libstdc++,ripgrepandUSE_BUILTIN_RIPGREP=0. - Provenance is now verifiable. Every release publishes a
manifest.jsonwith per-platform SHA256 checksums, plus a detachedmanifest.json.sigsigned with Anthropic's GPG key (fingerprint31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE). On macOS, binaries are signed by "Anthropic PBC" and notarized by Apple. On Windows, they carry an Authenticode signature from "Anthropic, PBC". Linux binaries are verified through the signed manifest. The Practice Lab below walks you end-to-end.
The disabling telemetry escape hatch is gone from the changelog, by the way — if you still see your claude process talking to Node, you're on a pre-2.1.113 build. claude --version confirms.
v2.1.113 is also the biggest bash-permission security release since v2.1.98. Five separate hardening changes closed long-standing bypass patterns, plus a new setting lets you override broad wildcards with specific denials. If you run agents unattended or ship allowlists to a team, you need to re-read your rules against the new semantics.
The headline fix — dangerouslyDisableSandbox no longer escapes the prompt. A Bash call that used the dangerouslyDisableSandbox parameter was running commands outside the sandbox without a permission prompt. That's now patched: every unsandboxed command goes back through the normal permission flow before running. If you've been relying on seeing approval prompts for escape-hatch commands, you actually are again. If you want to disable the escape hatch entirely, "allowUnsandboxedCommands": false in sandbox settings makes dangerouslyDisableSandbox a no-op.
Wrapper commands now match deny rules. Previously, Bash(rm:*) deny rules could be dodged by wrapping rm in env rm, sudo rm, watch rm, ionice rm, or setsid rm. Deny rules now unwrap those prefixes before matching. If your ruleset denies a dangerous command, the wrapped form is now denied too.
Bash(find:*) allow rules no longer auto-approve find -exec or -delete. An allowlist for find is a file-walking permission, not an arbitrary-execution permission. Those two flags now fall out to the normal permission flow even under a broad find:* allow. If you had find:* in your allowlist relying on free -exec, update your rules.
macOS /private/{etc,var,tmp,home} treated as dangerous rm targets. On macOS these paths are symlinked to the "real" system roots (/etc → /private/etc), which means a naïve Bash(rm:*) allow could delete /etc/passwd via /private/etc/passwd. Now flagged.
sandbox.network.deniedDomains — new surgical network control. The sandbox's allowedDomains supports wildcards, which is convenient but blunt. deniedDomains is a new setting that blocks specific hosts even when a broader wildcard would otherwise permit them. The canonical example: allow *.github.com for tooling but block raw.githubusercontent.com to stop agents from pulling arbitrary scripts. Merged across all settings scopes.
UI-spoofing closed. Multi-line bash commands whose first line was a comment previously showed only the comment in the transcript, hiding the actual command from the user. Now the full command shows. This was a real prompt-injection attack surface — a malicious instruction could have Claude run # harmless-looking-comment\nrm -rf ~ and the user saw only the comment before approving.
Micro-fixes worth knowing: cd no longer triggers a prompt when the cd is a no-op (Claude's favorite prefix), and MCP concurrent-call watchdog timeouts no longer silently disarm when one tool's message arrives during another tool's wait window.
If you hand-maintain a tight allowlist for a headless agent, read the Sandboxing docs with the new deniedDomains and deny-rule-wrapper behavior in mind.
Quietly tucked into v2.1.113: *"Subagents that stall mid-stream now fail with a clear error after 10 minutes instead of hanging silently."* If you've ever woken up to a headless agent run where one of the subagents entered the void and the parent sat patiently forever, this is the fix.
The old failure mode was ugly. A subagent would start, emit a few tokens, and then the upstream API call would stall — no tokens, no error, no timeout on the client side. The parent agent was blocked on the subagent's streaming completion, which never arrived. Your cron-driven headless session burned wall-clock time and held its API connection open until something external (TCP timeout, process kill, workflow step timeout) knocked it down. In an agent-teams setup you could lose an entire run to one bad subagent.
The new behavior: 10 minutes of mid-stream silence triggers a loud failure. The subagent raises a clear error, the parent observes it as a failure, and control returns to the parent's decision loop. You can now write subagent-aware error handling that actually fires.
Two companion fixes in the same release matter if you lean on subagents:
- MCP concurrent-call watchdog no longer cross-talks. Previously, a message destined for one MCP tool call could silently disarm another call's timeout watchdog. If you run multiple long-lived MCP tools in parallel, this was a source of phantom hangs. Fixed.
- Messages typed while watching a running subagent used to be hidden from the subagent's transcript and misattributed to the parent. Now they land where you intended.
Also worth knowing if you integrate with Claude via SDK: image content blocks that fail to process no longer crash the session — they degrade to a text placeholder. And Remote Control sessions now stream subagent transcripts properly (previously silent) and get archived when Claude Code exits (previously leaked).
How this changes your agent architecture: if you were designing around "subagent never returns" as a real outage class, you can now treat it as a bounded failure. Your wrapping script still needs an outer timeout (the 10-minute silent-stream budget is per subagent, and a malicious prompt could consume it back-to-back), but the typical "one subagent ghosts and takes the run with it" scenario is gone. Keep your outer wall-clock cap anyway — defence in depth.
A practitioner named Jock published a post titled *Token Waste Management: I audited 9,667 Claude Code sessions for $19*. Skip the paid kit at the bottom — the methodology is the value, and it's reproducible against your own session logs for pocket change.
The frame. Most token waste advice is anecdotal ("try smaller prompts", "reduce context"). Jock's audit treats waste as a *classification problem* over real traces. He ran 133,087 assistant turns across 9,667 sessions through a heuristic presort followed by an LLM judge, and grouped turns into a 9-category taxonomy. Total cost: $19. The punchline: Haiku as the judge catches twice as much waste as Sonnet at one-fifth the price. That's the pattern to internalise — for *classifying* traces (as opposed to generating solutions for them), the cheap model wins.
The top waste cluster was not what you'd guess. Browser and Playwright failures dominated — 136 sessions affected, and critically, when the author sampled only the most expensive sessions, these showed up only 5 times. That's a 27× undercount from sampling bias. Infrastructure failures wedge a session into a retry loop that burns tokens evenly across many sessions rather than spiking a few. If you're only reviewing your biggest invoices, you're blind to the systemic leaks.
Other recurring clusters: stale auth credentials, Cloudflare walls, non-existent tool calls, and "platform confusion" errors. Not reasoning failures — infrastructure bugs. The agent is fine; its tools are broken.
Opus 4.7 is paying a tokenizer tax. The author measured up to 35% more tokens for the same fixed input text under the new tokenizer versus Opus 4.5. That's a bill increase you didn't earn through changing anything — it's just the math of the new encoder. Worth budgeting for if you track spend.
Three actions you can lift today without paying anyone:
- Keep
CLAUDE.mdunder ~3,000 tokens. The audit found smaller CLAUDE.md files produce better outcomes *and* lower bills — the context-overflow failure mode costs more than the guidance saves. - Cap
max_tokensand enforce structured output where the task doesn't need prose. Boundaries beat hope. - Audit your WebFetch and browser-tool failures independently of your "expensive session" review. That's where the 27× undercount lives. Group by tool + error-class, not by total cost per session.
How to run this yourself. Your session logs live at ~/.claude/projects/. Feed the assistant turns into Haiku via the API with a classification prompt ("Was this turn productive progress or unproductive retry/failure? Category?"). Aggregate. A few thousand turns runs you a few dollars. The evaluation itself becomes a reusable skill — you're building a *feedback loop for your own agent habits* rather than trusting vibes.
The meta-pattern: when you need judgment at scale, reach for Haiku, not your default model. The advisor strategy blog (covered in issue #11) is the other side of the same coin — use the strong model where it matters, the cheap model where volume matters.
Note: jock.pl is a practitioner blog, not an Anthropic source. The tokenizer-overhead and audit-cost figures are the author's measurements; your own mileage will vary. The *methodology* is what travels.
A new plugin from Not-Diamond dropped April 6 that operationalises the token-waste audit idea above: Self-Care (19 stars, MIT, JavaScript) reads your agent traces, classifies quality issues across 14 categories, and proposes concrete diffs against your prompts, tool descriptions, and context docs.
What it detects. "Goal drift, hallucinations, missed actions, and more" — the repo description lists the targets explicitly. Where it gets interesting is the two-phase architecture: first pass scans traces and partitions problems into auto-fixable vs manual-review; second pass locates the relevant project files (prompt templates, tool schemas, CLAUDE.md fragments) and generates minimal diffs for human review before applying them to the codebase.
How it plugs in.
/self-care:init— configure your trace source (LangSmith and LangFuse supported out of the box)/self-care:run— analyse and generate a report under.self-care/reports//self-care:autosync-enable— background monitoring via scheduled tasks/self-care:config— customise detection rules
Config lives in .self-care/config.json. Reports are markdown. The trace integration is the non-obvious piece — it assumes you already have traces being collected somewhere observability-wise. If you're not running LangSmith or LangFuse, the plugin will still work on raw log ingestion but you lose the structured context.
Why this is worth watching more than its star count suggests. The idea — agent *self-improvement through trace triage* — is where the craft is heading. Individual CLAUDE.md fixes based on one bad run are anecdote-driven. Running a classifier over hundreds of real sessions and generating a prioritised diff of what to fix is a different discipline. Self-care is early (created April 6, 19 stars, 156 KB) and Claude Code-specific, but the pattern generalises.
Compare and contrast. AgentLint (featured in issue #9) is a *static* ruleset over your agent definitions — checks your configs match good-practice patterns. Self-care is *dynamic* — reads what happened and recommends fixes. They're complementary: static for the setup, dynamic for the operation.
How to evaluate it for your own setup:
- Install as a Claude Code plugin; run
/self-care:initand point it at whatever trace source you have. - Run it over one week of traces. Review the report. Count false positives.
- If signal-to-noise is usable, enable
autosyncfor background monitoring. If noisy, adjust detection rules in.self-care/config.json.
Worth a weekend afternoon. Worth less than that if you don't already emit structured traces — wire up LangFuse or similar first, or skip this until you do.
Outcome: You've imported Anthropic's release-signing GPG key, verified its fingerprint out-of-band, fetched and verified a detached signature on manifest.json, and cross-checked your installed claude binary against the manifest's SHA256. Next time Anthropic publishes a release, you can do this in under a minute.
Why this is a weekend exercise, not a daily one. The manifest + signature chain only landed as standard practice from v2.1.89 onward, the fingerprint is what matters (the key URL could theoretically be MITM'd, the fingerprint cannot), and most operators never verify supply chains in the AI-agent stack even though they verify it for package managers. With v2.1.113 shipping as a native binary, you're running a ~236 MB statically-linked executable downloaded from Google Cloud Storage. Worth knowing it is what Anthropic signed.
Prerequisites
gpg2.2+,curl,sha256sum(Linux) orshasum(macOS) or PowerShellGet-FileHash(Windows)jqfor pulling the checksum out of the manifest cleanly- A POSIX shell (Git Bash or WSL on Windows works)
Step 1 — import and verify the signing key
gpg --fingerprint security@anthropic.com
The output must contain this exact fingerprint:
If it doesn't match, stop. Someone has swapped the key URL or you've imported a different key. The fingerprint is your root of trust — not the URL, not the file.
Step 2 — fetch the manifest and its detached signature
VERSION=2.1.113
curl -fsSLO "$REPO/$VERSION/manifest.json"
curl -fsSLO "$REPO/$VERSION/manifest.json.sig"
Step 3 — verify the signature
A valid result reports:
gpg will also print WARNING: This key is not certified with a trusted signature!. That's expected for a freshly imported key — you haven't locally signed it yet. The "Good signature" line is the cryptographic check. The fingerprint comparison in Step 1 is the authenticity check. Both must pass.
If you want to silence the warning for future runs, locally certify the key:
Step 4 — cross-check your installed binary
Find your platform key. On a Linux x64 box running glibc it's linux-x64. On Apple Silicon, darwin-arm64.
EXPECTED=$(jq -r ".platforms.\"$PLATFORM\".checksum" manifest.json)
ACTUAL=$(sha256sum ~/.local/bin/claude | awk '{print $1}')
echo "expected: $EXPECTED"
echo "actual: $ACTUAL"
[ "$EXPECTED" = "$ACTUAL" ] && echo "MATCH" || echo "MISMATCH — do not run this binary"
macOS: use shasum -a 256 instead of sha256sum.
Windows PowerShell: (Get-FileHash claude.exe -Algorithm SHA256).Hash.ToLower().
Step 5 — verify the platform code signature (macOS/Windows only)
macOS:
codesign -dv --verbose=4 ~/.local/bin/claude 2>&1 | grep Authority
Expect Authority=Developer ID Application: Anthropic PBC and notarization by Apple.
Windows PowerShell:
Expect SignerCertificate from Anthropic, PBC.
Linux binaries don't carry individual code signatures — Step 4's manifest-signature verification is how you pin provenance.
Step 6 — automate it
Put the whole flow in a ~/bin/verify-claude script and wire it into your install/upgrade workflow. On a fleet of headless agents, run it post-claude update as a hook:
"hooks": {
"SessionStart": [{
"command": "verify-claude || { echo 'binary verification failed'; exit 1; }"
}]
}
}
If verification fails at SessionStart, the session refuses to boot. Belt and braces for long-running agent fleets.
What you've built: a cryptographic receipt that your claude binary is the one Anthropic published, end-to-end. This is the supply-chain stance the AI-tooling industry needs and nobody is doing. Starting with your own machine is the right place.