Skip to content

feat: add fan-out budgets and auto-mode/workflow settings keys - #16

Merged
intech merged 2 commits into
feat/remote-control-by-defaultfrom
feat/agent-limits-and-auto-mode-keys
Aug 3, 2026
Merged

feat: add fan-out budgets and auto-mode/workflow settings keys#16
intech merged 2 commits into
feat/remote-control-by-defaultfrom
feat/agent-limits-and-auto-mode-keys

Conversation

@intech

@intech intech commented Aug 3, 2026

Copy link
Copy Markdown
Member

Stacked on #15, which is stacked on #14. Merge order: #14#15 → this. Retarget the base to main once the parents land.

What

Adds the runaway-fan-out budgets and the auto-mode / workflow settings keys that appeared between claude-code 2.1.183 and 2.1.220.

Baked env vars (all overridable from .envdocker -e wins over image ENV)

Var Image Upstream default
CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS 12 20
CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION 100 200
CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION 100 200
CLAUDE_CODE_RETRY_WATCHDOG 1 off

The concurrency number is measured, not guessed. Inside this image: 4 processes before claude, ~11 with claude plus the four MCP servers attached, peaking at 15 with three parallel Bash tool calls — roughly 1–2 PIDs per in-flight tool call over an ~11-PID floor. At the upstream 20, a fan-out where every subagent holds a shell lands close enough to the --pids-limit=100 cgroup cap that the container, not Claude Code, decides what fails. 12 leaves ~40 PIDs of headroom.

The two per-session counters are cost/runaway guards rather than PID guards, so 100 is a deliberately conservative choice, not a measured ceiling.

⚠️ 0 does not disable them. Observed: with either counter set to 0 the action still ran, i.e. 0 behaves as if the variable were unset. Use 1 for the tightest real limit. Documented in CLAUDE.md and .env.example, because "set it to 0 to disable" is the obvious wrong guess.

settings.json keys

Key Value Upstream default
autoMode.classifyAllShell true — every shell command goes through the auto-mode classifier, not only arbitrary-code-execution patterns false
agentPushNotifEnabled true — proactive phone push once Remote Control connects false
workflowSizeGuideline "small" — advisory dynamic-workflow size (unrestricted|small|medium|large) medium

workflowSizeGuideline: "small" is the one judgement call here rather than a safety measure — flag it if you'd rather keep medium.

Verification — stated per key, not uniformly

Behaviourally verified — the two that matter most. With CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION=1, the first WebSearch succeeds and the next two are refused with the CLI's own message:

Web search was not performed: this session has used its web search budget
(1 of 1 WebSearch calls). ... ask the user to raise
CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION.

With CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS=1, three parallel Agent calls in one message produce one success and two refusals:

Concurrent subagent limit reached. You can run 1 subagents at once. Do not
retry. If the user wants more concurrent subagents, ask them to increase
CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS.

Inferred, not exercised. CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION shares the read path of the two above. CLAUDE_CODE_RETRY_WATCHDOG is read through the boolean env parser that accepts 1/true/yes/on.

Accepted, but effect not observed. classifyAllShell, agentPushNotifEnabled, workflowSizeGuideline are in 2.1.220's settings-key table, their values come from the binary's own enum/parser, and claude doctor reports no invalid settings — but the workflow-size system reminder is not injected in -p/headless runs, so it could not be confirmed end to end, and agentPushNotifEnabled cannot act until Remote Control actually connects (which needs claude auth login — see #15).

Rebuilt image. Build exits 0; baked ENV present; ~/.claude/settings.json carries every key; claude doctor clean; all four MCP servers ✔ Connected at the default MCP_TIMEOUT=10000.

Not verified locally: arm64 (no qemu binfmt on the build host) — covered by the pull_request CI job.

🤖 Generated with Claude Code

intech and others added 2 commits August 3, 2026 09:46
Four env vars baked into the image (all overridable from .env, since
`docker -e` wins over image ENV):

  CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS=12      (upstream default 20)
  CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION=100    (upstream default 200)
  CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION=100 (upstream default 200)
  CLAUDE_CODE_RETRY_WATCHDOG=1

The concurrency number is measured, not guessed. Inside this image: 4 processes
before `claude`, ~11 with `claude` plus the four MCP servers attached, peaking at
15 with three parallel Bash tool calls - roughly 1-2 PIDs per in-flight tool call
over an ~11-PID floor. At the upstream 20 a fan-out where every subagent holds a
shell lands close enough to the --pids-limit=100 cgroup cap that the container,
not Claude Code, decides what fails. 12 leaves ~40 PIDs of headroom.

The two per-session counters are cost/runaway guards rather than PID guards, so
100 is a deliberately conservative choice, not a measured ceiling. Their lower
bound is 1: a value of 0 is rejected by validation and silently falls back to the
upstream default. That is documented in CLAUDE.md and .env.example because "set
it to 0 to disable" is the obvious wrong guess.

Three settings.json keys:

  autoMode.classifyAllShell: true   - route every shell command through the
                                      auto-mode classifier (upstream false)
  agentPushNotifEnabled: true       - proactive phone push once Remote Control
                                      connects (upstream false)
  workflowSizeGuideline: "small"    - advisory dynamic-workflow size; accepted
                                      values unrestricted|small|medium|large,
                                      upstream default medium

Verification, stated honestly rather than uniformly:

- Behaviourally verified: the session counters. With
  CLAUDE_CODE_MAX_WEB_SEARCHES_PER_SESSION=1 the first WebSearch succeeds and the
  next two are refused with "this session has used its web search budget (1 of 1
  WebSearch calls)". A value of 0 was ignored, which is how the lower bound was
  found. CLAUDE_CODE_RETRY_WATCHDOG is read through the boolean env parser that
  accepts 1/true/yes/on.
- Accepted but effect not observed: classifyAllShell, agentPushNotifEnabled,
  workflowSizeGuideline. They are in 2.1.220's settings-key table, their values
  come from the binary's own enum/parser, and `claude doctor` reports no invalid
  settings - but the workflow-size system reminder is not injected in -p/headless
  runs, and agentPushNotifEnabled cannot act until Remote Control connects, which
  needs `claude auth login`.
- Rebuilt image: build exits 0, baked ENV present, ~/.claude/settings.json carries
  all keys, `claude doctor` clean, all four MCP servers Connected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two corrections to the previous commit's documentation.

1. The "0 falls back to the upstream default because validation rejects it"
   claim asserted a mechanism that was never observed. What was actually seen is
   that with either per-session counter set to 0 the action still ran - i.e. 0
   behaves as if the variable were unset. The practical warning is unchanged
   ("0 does not disable these, use 1"); the invented explanation is gone.

2. CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS is now behaviourally verified rather
   than inferred from a shared read path. With the value set to 1, three
   parallel Agent calls in one message produce one success and two refusals:

     Concurrent subagent limit reached. You can run 1 subagents at once. Do not
     retry. If the user wants more concurrent subagents, ask them to increase
     CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS.

   CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION remains the one counter inferred from
   the shared read path rather than exercised, and CLAUDE.md now says so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@intech
intech merged commit 31d1586 into main Aug 3, 2026
@intech
intech deleted the feat/agent-limits-and-auto-mode-keys branch August 3, 2026 06:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant