Claude Code 2.1.233 on Linux: cap Bash tool memory before a build stalls the host
Quick answer
Claude Code 2.1.233 adds opt-in memory cgroup support for Bash tool commands on Linux through CLAUDE_CODE_TOOL_MEMORY_LIMIT. The goal is containment: if a build, test, or search command runs away, the child workload should hit its own memory boundary instead of making the whole machine and Claude session unresponsive.
Do not treat this as a session-wide RAM limit. The new boundary covers Bash tool command processes, not the Claude Code parent, MCP servers, IDE, other sessions, or every subagent process. Start with one disposable session, size the limit from a healthy build, verify the child really enters the claude-code-bash cgroup, and keep host-level monitoring.
Who this is for
This guide is for developers running Claude Code on native Linux or WSL with memory-heavy compilers, test suites, package installs, static analysis, or parallel agent work. It is especially useful on shared runners and 8–32 GB development machines where one abnormal command can trigger swap thrashing or a host OOM.
The setting is not a macOS or Windows control. It also does not replace the subagent concurrency budget or a managed-agent spend cap: API concurrency, token cost, and Linux process memory are separate limits.
What changed, and what the boundary means
Anthropic's release note names the environment variable and says it places Linux Bash tool commands under a memory cgroup. Inspection of Anthropic's official 2.1.233 Linux package gives a more precise launch contract:
| Question | Verified contract | Rollout implication |
|---|---|---|
| Accepted values | Positive numbers with optional K, M, G, or T, and optional B or iB; for example 4G or 4096MiB
|
Use an explicit unit and record the resolved byte value |
| Kernel path | cgroup v2 uses memory.max; legacy cgroup v1 uses memory.limit_in_bytes
|
Verify the actual host hierarchy instead of assuming enforcement |
| Child group | The package creates a claude-code-bash child cgroup beneath the current memory cgroup |
Check Bash process membership from inside a tool command |
| Disable path |
none disables the opt-in limit |
Restart the session after rollback |
| Failure boundary | If Claude Code cannot find or write a usable memory hierarchy, the cgroup feature is disabled | A configured variable is not proof that the limit took effect |
On cgroup v2, memory.max is a hard limit. The kernel may reclaim memory first; if usage cannot be reduced, the cgroup OOM killer can terminate a process inside that group. memory.events records max, oom, and oom_kill, so those counters are stronger evidence than a generic exit code.
Choose a limit from evidence
Run the same representative build or test three times without the new setting. Record peak memory, duration, exit code, and output correctness. A practical starting rule is:
candidate limit = healthy peak × 1.5
host reserve = max(2 GiB, 15% of host RAM)
final limit = no higher than host RAM - host reserve
This is an IndieSeek rollout heuristic, not an Anthropic default. If several Bash commands or sessions can overlap, budget their combined working sets. A 4 GiB limit on each of four concurrent sessions can still exhaust a 16 GiB host.
A seven-step acceptance workflow
1. Pin the release
Upgrade one canary host and confirm claude --version reports 2.1.233 or newer. Keep the previous installer or version route available. Do not change every login shell or runner image yet.
2. Verify the Linux memory controller
On a cgroup v2 host, run these checks outside Claude Code:
uname -s
stat -fc %T /sys/fs/cgroup
grep -w memory /sys/fs/cgroup/cgroup.controllers
Expect Linux, cgroup2fs, and a visible memory controller. A container may expose cgroup v2 but deny child-cgroup creation, so this preflight is necessary but not sufficient.
3. Launch one bounded session
Use the measured candidate, not a copied universal number:
CLAUDE_CODE_TOOL_MEMORY_LIMIT=4GiB claude
The official package accepts 4G, 4GB, and 4GiB as binary-unit forms. Keep the value session-local during the canary.
4. Prove cgroup membership and the resolved limit
Ask Claude to run this harmless Bash command:
set -eu
cg_rel=$(awk -F: '$1 == "0" { print $3 }' /proc/self/cgroup)
cg_dir="/sys/fs/cgroup${cg_rel}"
printf 'cgroup=%s\n' "$cg_rel"
printf 'memory.max=' && cat "$cg_dir/memory.max"
printf 'memory.current=' && cat "$cg_dir/memory.current"
cat "$cg_dir/memory.events"
Require the cgroup path to end in claude-code-bash and memory.max to match the intended bytes. For 4GiB, that is 4294967296. If either check fails, stop: the environment variable exists, but containment is not proven.
5. Run the positive control
Run the normal build, test, and one search-heavy task. Require correct output, acceptable duration, a responsive Claude session, and no increase in oom_kill. If ordinary work is killed, the limit is too low or the workload needs a different lane.
6. Run one disposable failure canary
Only on a disposable VM or isolated runner, use a non-secret program that allocates memory in fixed chunks until the cgroup kills it. Do not run an intentional OOM on a production host. After the failure, verify:
-
memory.eventsincrementsoomoroom_kill. - The shell command fails clearly instead of hanging indefinitely.
- Claude can execute a fresh harmless Bash command afterward.
- The host, terminal, and unrelated services remain responsive.
This proves containment and recovery. A killed child without a surviving session is not a passing result.
7. Promote one workload class at a time
Roll out builds first, then tests, then heavier parallel work. Keep concurrency separately bounded and sample memory.current, memory.events, host available RAM, and swap. Roll back by removing the variable or setting it to none, then restarting Claude Code.
Decision tree
Is the host Linux/WSL with a usable memory cgroup?
no -> keep host-level isolation; do not claim this setting works
yes -> does a Bash child enter claude-code-bash with the expected memory.max?
no -> stop and fix delegation or permissions
yes -> does the normal workload pass below the limit?
no -> raise the evidence-based limit or split the workload
yes -> does the disposable OOM canary kill only the child?
no -> keep the feature canary-only
yes -> promote one workload class and monitor events
Common mistakes
- Setting the cap equal to one observed peak and leaving no variance headroom.
- Assuming the limit covers Claude Code, MCP servers, IDEs, and all subagents.
- Checking only the exported variable instead of cgroup membership and
memory.max. - Running an intentional OOM test on a laptop or production runner.
- Increasing session concurrency without adding the limits together.
- Treating every killed build as a product bug instead of distinguishing a real leak from an undersized cap.
Copyable rollout record
date / owner / host / kernel / WSL-or-native:
claude_version / install_source:
cgroup_version / memory_controller / delegation_result:
healthy_task / run_count / peak_memory / duration / exit_result:
configured_value / resolved_memory.max / cgroup_path:
positive_control / output / duration / memory.events_delta:
disposable_oom_canary / child_result / session_recovery / host_health:
concurrent_sessions / aggregate_budget / host_reserve:
decision: hold | raise-limit | limited-rollout | promote | rollback
rollback_value / restart_proof:
FAQ
What should I set CLAUDE_CODE_TOOL_MEMORY_LIMIT to?
There is no universal number. Measure a representative healthy workload, add variance headroom, reserve memory for the OS and non-Bash processes, and account for concurrent sessions. Start on one host.
Does the limit stop Claude Code itself from using too much memory?
No. The 2.1.233 release describes cgroup support for Bash tool commands. Use Anthropic's /compact, safe-mode, restart, and /heapdump troubleshooting path for high memory in the Claude Code process itself; never publish a heap snapshot because it can contain conversations and credentials.
Is an OOM-killed Bash command a successful test?
Only if it ran in a disposable environment, memory.events proves the cgroup OOM, the Claude session recovers, and the host remains healthy. The goal is controlled failure, not merely process death.
Top comments (0)