●CORPS — Anthropic unveils Claude Corps (Jun 11), a $150M national fellowship placing 1,000 early-career workers inside US nonprofits; the first cohort starts in October●SUBAGENTS — Claude Code sub-agents can now spawn their own sub-agents, up to 5 levels deep — multi-stage delegation workflows out of the box●WORKFLOWS — Dynamic workflows arrive in research preview across CLI, Desktop, and VS Code for codebase-wide bug hunts and large migrations (Max/Team/Enterprise)●BILLING — 2 days to the Jun 15 change: Agent SDK, headless runs, and GitHub Actions move to monthly credits ($20/$100/$200); Sonnet 4 and Opus 4 retire from the API the same day●FABLE5 — Fable 5 remains included free on Pro, Max, Team, and Enterprise through Jun 22●CODE80 — IPO coverage reports Claude now writes over 80% of its own code, up from under 10% in February 2025●CORPS — Anthropic unveils Claude Corps (Jun 11), a $150M national fellowship placing 1,000 early-career workers inside US nonprofits; the first cohort starts in October●SUBAGENTS — Claude Code sub-agents can now spawn their own sub-agents, up to 5 levels deep — multi-stage delegation workflows out of the box●WORKFLOWS — Dynamic workflows arrive in research preview across CLI, Desktop, and VS Code for codebase-wide bug hunts and large migrations (Max/Team/Enterprise)●BILLING — 2 days to the Jun 15 change: Agent SDK, headless runs, and GitHub Actions move to monthly credits ($20/$100/$200); Sonnet 4 and Opus 4 retire from the API the same day●FABLE5 — Fable 5 remains included free on Pro, Max, Team, and Enterprise through Jun 22●CODE80 — IPO coverage reports Claude now writes over 80% of its own code, up from under 10% in February 2025
Pin Your Execution Model with enforceAvailableModels — Don't Let Auto-Upgrades Burn Through Your Credits
From June 15, monthly credits become non-rolling. This is a setup-layer approach to keep subagents and fallbacks from silently upgrading to pricier models, using enforceAvailableModels to pin the model set from the managed-settings layer, with a verification step you can run in CI.
From June 15, headless claude -p, the Agent SDK, GitHub Actions, and third-party agents move off subscription caps and onto API-rate monthly credits with no rollover. As an indie developer I run four technical blogs (Dolice Labs) through a nightly batch, and the first thing I worried about with this change wasn't quality dropping — it was credits running dry mid-month because of an unintended model upgrade.
The failure path is mundane. The parent agent is assigned Haiku, but a subagent definition still carries model: opus, or the fallbackModel for overload points at a heavier model, or — during a new model's launch window — I reach for "the smartest one" on a whim and leave it there. The per-run difference is small, but across a batch that runs every night, it adds up by the end of the month.
This article centers on a managed setting called enforceAvailableModels and a design that pins the very set of models a session can pick, keeping credit consumption inside a predictable range. It's not a prompt trick — it's a ceiling built at the settings layer.
Why pinning the model pays off after the billing change
In months with rollover, or back when we ran inside subscription caps, an accidental heavy run got absorbed the following month. With non-rolling monthly credits, that cushion is gone. Credits are a budget that simply stops when exhausted, which makes in-month allocation a real part of operations design.
This is where suppressing consumption at the entrance matters. Asking, in the prompt, to "please use a cheaper model" isn't reliably honored inside recursive subagents or automatic workflows. But if you narrow the set of selectable models in a managed setting, no path — wherever it originates — can launch a model outside that set. The whole point here is turning cost control from a request into a constraint.
One data point from my own pipeline: generating a single article (research + draft + JA/EN consistency check) on Haiku versus accidentally running the same steps on Opus turned the per-token price gap directly into a several-fold consumption gap. At a scale of six articles a night across four sites, a single night of that mistake pushes the daily budget up. That's exactly why I want a setting to stop it, not human vigilance.
Which layer enforceAvailableModels lives in
Claude Code resolves its final settings by stacking several layers. Roughly, from highest precedence down:
Managed settings — placed by a device or org admin and not overridable by the user
Project settings — the repo's .claude/settings.json
User settings — ~/.claude/settings.json
Runtime flags and in-session choices
If you want your cost ceiling to be a floor that can't be broken, put it in the non-overridable managed-settings layer. enforceAvailableModels declares, at this layer, "the set of models any session on this machine (or in this org) is allowed to use." Anything outside the set can't be selected — not by a runtime flag, not by a subagent definition.
Here's where the managed-settings file lives on macOS (on Linux it's /etc/claude-code/managed-settings.json).
# Managed settings on macOS (placed as root; not user-overridable)/Library/Application Support/ClaudeCode/managed-settings.json
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦A concrete managed-settings configuration that pins the model set a session may use, combining enforceAvailableModels with permissions.deny globs
✦A three-tier fallback that only ever steps down inside the allowed set, so an overloaded run never bounces up to a pricier model
✦A small inverted-assertion script to verify in CI that out-of-set models are actually rejected, plus how to roll the policy out across multiple repos
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
Start by declaring the allowed set in managed settings. Here I allow just two — "Sonnet as the workhorse, Haiku for light work" — and deliberately exclude Opus-class and the new tiers.
enforceAvailableModels is the allowed set; model is the session default. Defaulting to Haiku means runs stay on the lighter model unless Sonnet is explicitly requested, which keeps consumption quiet.
In this state, if a session requests Opus, it's refused at launch. Even if a subagent definition still says model: claude-opus-4-8, that value sits outside the allowed set and never fires. The strength of this setup is that it absorbs the "a stale setting was left in place" accident at the layer level.
Before / After: when I relied on the project side
My earlier setup leaned on project settings for cost control.
// Before: .claude/settings.json (user-overridable; subagents can carry their own model){ "model": "claude-haiku-4-5-20251001"}
Here the default is Haiku, but a subagent definition or a --model flag overrides it trivially. In fact, I once left --model opus on while debugging, committed that setting, and had the nightly batch running on Opus for several days.
// After: managed-settings.json (a floor that can't be overridden){ "enforceAvailableModels": ["claude-sonnet-4-6", "claude-haiku-4-5-20251001"], "model": "claude-haiku-4-5-20251001"}
With the After setup, --model opus is rejected at launch. Moving the floor to the managed layer means a project-side misconfiguration no longer feeds straight into cost.
Make fallbackModel step down inside the allowed set
Many of you use fallbackModel to handle overload (529 Overloaded). The trap is that if you point the fallback at a smarter model, you bounce up to a pricier model precisely when things are congested, and credits swell. For cost, the fallback should go down, not sideways — toward the lighter model inside the allowed set.
// managed-settings.json — step down to Haiku under overload{ "enforceAvailableModels": ["claude-sonnet-4-6", "claude-haiku-4-5-20251001"], "model": "claude-sonnet-4-6", "fallbackModel": "claude-haiku-4-5-20251001"}
Now runs normally use Sonnet and step down to Haiku to keep going when busy. The fallbackModel value must also be a member of the enforceAvailableModels set. If you point it outside the set, the fallback itself is disabled the moment overload hits, and the run stalls — so be careful. For three tiers, keep both primary and secondary inside the set.
Close off model-switching commands with a deny glob
If a session can switch models via the shell, you've punched a hole in the floor. Use a permissions.deny glob to forbid command execution that carries a model flag.
Blocking the ANTHROPIC_MODEL environment variable too closes the path that rewrites the default model from a subprocess. Globs match by prefix in a straightforward way, so the trick is to put the wildcard "right after the flag," as in claude --model *. Enumerate the flag's variants (with -p, etc.) so spacing differences don't let anything slip through.
Verify in CI that out-of-set models are actually rejected
The scary part of settings is that they leak when you only think you wrote them. After I deploy managed settings, I confirm with a small script that out-of-set models are reliably refused. Wired into CI, it catches the accident where an edited settings file lets a heavier model creep back in.
#!/usr/bin/env bash# verify-model-guardrail.sh# An inverted test: we *expect* launching with an out-of-set model to fail.set -uo pipefailDENIED_MODEL="claude-opus-4-8"PROMPT="Reply with only the two letters OK."echo "▶ Trying to launch with out-of-set model ${DENIED_MODEL} (failure expected)"if claude -p "$PROMPT" --model "$DENIED_MODEL" >/tmp/out.txt 2>/tmp/err.txt; then echo "❌ FAIL: the out-of-set model launched. The floor isn't holding." cat /tmp/err.txt exit 1else echo "✅ Rejected as expected (the floor is working)"fiecho "▶ Confirming an in-set model launches (success expected)"if claude -p "$PROMPT" --model "claude-haiku-4-5-20251001" >/dev/null 2>&1; then echo "✅ In-set model launched normally"else echo "❌ FAIL: even the in-set model is blocked. Re-check the set declaration." exit 1fi
The key is the inverted assertion: "rejection means success." A normal test expects success, but a guardrail check confirms that a prohibition holds, so the exit-code handling is reversed. Pairing it with an in-set launch check makes sure you didn't narrow the set so far that legitimate work also stops.
Roll the managed settings out across repos
If, like me, you run several repos through one machine's nightly batch, a single managed-settings file on the machine applies uniformly to every repo. That's the big difference from project settings — no need to fix .claude/settings.json per repo.
# Place the managed settings and lock down permissions (run as root)SRC="./managed-settings.json"DEST="/Library/Application Support/ClaudeCode/managed-settings.json"sudo install -d -m 755 "$(dirname "$DEST")"sudo install -m 644 -o root "$SRC" "$DEST"# Confirm after placementecho "▶ Checking the enforceAvailableModels declaration"python3 -c "import json,sys; d=json.load(open('$DEST')); print('allowed:', d.get('enforceAvailableModels'))"
Make root the owner and keep write permission away from regular users. If the very user running the nightly batch can edit the settings, the "floor" loses its meaning. When you do want to formally adopt a new model, you append it to the set in this one file and re-place it, and the allowance widens across all repos at once.
Keep a numeric view of credit consumption
Finally, it's reassuring to estimate — even roughly — how much a pinned model setup consumes in a month. I use a simple formula to derive a "daily token allowance" and shift the steps most likely to exceed it toward the lighter model.
monthly credits (no rollover) / working days = daily budgetdaily budget / (avg unit price of the primary model) = rough tokens per day
For example, with $100 of monthly credit over 30 working days you have roughly $3.3 per day. In my setup a single article runs around 40k tokens on a Haiku-led path, and fitting that into the $3.3 envelope shows numerically whether you can afford Sonnet as the workhorse at six articles a day. My recommendation is to start with a two-tier setup: pin one workhorse (Sonnet) and absorb the rest with Haiku step-downs. Plug in real numbers and you can answer questions like "does keeping Sonnet as the workhorse stay within budget?" or "what changes if congestion keeps forcing Haiku step-downs?" with figures rather than gut feel. Because enforceAvailableModels narrows the set, no heavier model that isn't in this estimate can suddenly enter the consumption mix, so estimate and actuals stay close. As a premise for budget control, having "the set of usable models nailed down" first is what makes the rest tractable.
Non-rolling monthly credits become surprisingly manageable with a small design change. The first move is to add one line — enforceAvailableModels — to your machine's managed settings, narrow the allowed models to two or three, and run the inverted test above once. Once you've seen the floor hold with your own eyes, batch operations after June 15 get far more predictable.
Share
Thank You for Reading
Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.