Presence of ~/.bashrc (even empty) triggers full shell state capture with `set -o onecmd`, breaking npm/subprocess stdout on Windows/Git Bash

Resolved 💬 18 comments Opened Jan 18, 2026 by MannyFigs Closed May 23, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

On Windows with Git Bash, the mere presence of a ~/.bashrc file (even if completely empty) causes Claude Code to create bloated shell snapshots (~2254 bytes) that include set -o onecmd. This breaks all subprocess stdout, causing npm and other bash wrapper scripts to return no output.

When ~/.bashrc does NOT exist, Claude Code creates minimal snapshots (~282 bytes) that work correctly.

Root Cause: The onecmd shell option (equivalent to bash -t) causes bash to exit after executing one command, breaking subprocess stdout handling.

Minimal snapshot (282 bytes, works):

# Snapshot file
unalias -a 2>/dev/null || true
shopt -s expand_aliases
if ! command -v rg >/dev/null 2>&1; then
  alias rg='...'
fi
export PATH=$PATH

Bloated snapshot (2254 bytes, broken):

# Snapshot file
unalias -a 2>/dev/null || true
# Functions
eval "$(echo '...' | base64 -d)" > /dev/null 2>&1
# Shell Options
shopt -u autocd
... (50+ shopt lines)
set -o braceexpand
set -o hashall
set -o interactive-comments
set -o monitor
set -o onecmd    # <-- THIS BREAKS EVERYTHING
...

What Should Happen?

  1. npm --version and other bash wrapper scripts should return output correctly regardless of whether ~/.bashrc exists
  2. Shell snapshots should NOT include set -o onecmd as this breaks subprocess stdout
  3. Claude Code should either:
  • NOT capture set -o onecmd in shell snapshots
  • Explicitly disable it (set +o onecmd) in all snapshots
  • Use the same minimal snapshot logic regardless of whether .bashrc exists

Error Messages/Logs

Expected output (when ~/.bashrc does NOT exist):
$ npm --version
11.6.2

Actual output (when ~/.bashrc IS present):
$ npm --version
⎿  no content
(Tool ran without output or errors)

$ npm install
⎿  no content
(Tool ran without output or errors)

The command appears to succeed (no error code) but stdout is completely empty. This makes the bug extremely difficult to diagnose since there's no error message - just silent failure.

Steps to Reproduce

  1. On Windows with Git Bash, ensure ~/.bashrc does NOT exist
  2. Delete existing shell snapshots: rm -rf ~/.claude/shell-snapshots/*
  3. Launch Claude Code and run npm --versionWorks correctly, returns version (e.g., 11.6.2)
  4. Check snapshot size: ls -la ~/.claude/shell-snapshots/~282 bytes
  5. Create an empty .bashrc: touch ~/.bashrc
  6. Delete snapshots again: rm -rf ~/.claude/shell-snapshots/*
  7. Launch Claude Code and run any command to trigger new snapshot creation
  8. Run npm --versionReturns nothing (broken)
  9. Check snapshot size: ls -la ~/.claude/shell-snapshots/~2254 bytes
  10. Check snapshot contents: cat ~/.claude/shell-snapshots/*.sh | grep onecmdContains set -o onecmd

Reproducibility: Confirmed on TWO separate Windows machines with identical results. Both machines produce identical 2254-byte bloated snapshots containing set -o onecmd when an empty .bashrc exists.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.12 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

Important: While the .bashrc file is a Git Bash configuration file, the bug affects npm in ALL terminals (PowerShell, CMD, Git Bash) because Claude Code's internal shell snapshot mechanism uses Git Bash regardless of the user's terminal.

Environment Details:

  • Git for Windows: 2.52.0
  • Node.js: 24.13.0
  • npm: 11.6.2
  • Tested terminals: PowerShell, CMD, Git Bash - all affected

Workaround: Remove ~/.bashrc and ~/.bash_profile. Move any needed environment variables to Windows System Environment Variables instead.

Key Evidence - Snapshot from second test machine:

# Line 75 of snapshot file:
set -o onecmd    # <-- THE BUG

File size: 2254 bytes (vs 282 bytes when .bashrc doesn't exist)

Note: This bug affects ANY user who has a .bashrc file, even if it's empty. The file doesn't need to contain anything - its mere presence triggers Claude Code to capture full shell state including the problematic onecmd option.

View original on GitHub ↗

18 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/18775
  2. https://github.com/anthropics/claude-code/issues/18856
  3. https://github.com/anthropics/claude-code/issues/18670

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

KuceraJanSupport · 5 months ago

Subscribing - experiencing the same issue on Windows 11 with Git Bash. Workaround: set +o onecmd; npm run build 2>&1

ardove · 5 months ago

Yep also happening to me too. Tried updated claude code and no luck.

DjWarmonger · 5 months ago

Me 2, Windows 11.

Thanks Claude for founding this issue report ;)

jtrinklein · 5 months ago

Also experiencing the issue. Windows 11, Claude Code v2.1.20

jtrinklein · 5 months ago

simplest workaround for me is to open git bash and rename ~/.bashrc to ~/.my_bashrc. works for me because i don't actually use Git Bash for regular work and if I need to use it I can manually source the file. Big PITA though.

salvadorplj · 5 months ago

+1 on this. Running vitest via npm run test returns empty stdout and exit code 0 regardless of actual test results. Spent a good chunk of time debugging why CI was catching test failures that appeared to pass locally through Claude Code.

Environment: Windows 11, Node v24.12.0, Git Bash, Claude Code v2.1.23

Using PowerShell instead of Bash as a workaround for now.

oscarbds · 5 months ago

Confirming this also affects macOS + native bash 3.2.57 (not just Windows/Git Bash).

Same root cause: shell snapshots at ~/.claude/shell-snapshots/ capture set -o onecmd even though it is not set in any user profile (.bashrc, .bash_profile, /etc/profile). Verified with set -o | grep onecmd showing onecmd off.

This has recurred 5 times across multiple Claude Code versions (Homebrew install). Each time the corrupted snapshot is deleted, the next session recreates it with the same bug.

Cross-platform reproduction confirms this is in the snapshot capture logic itself, not a platform-specific shell quirk.

Originally filed as #23841 (closing as duplicate of this).

alexkli · 4 months ago

Same issue on macOS. No fix so far, all my claude sessions can no longer invoke Bash tools.

  • Claude code 2.1.52
  • macOS Tahoe 26.2
  • Bash 5.2.9(1) via Homebrew

All Bash commands suddenly started to exit with 127 mid session for me, and affects all my running claude sessions (about ~4 that I have open in various Terminal.app windows). Claude Code worked fine for months.

My .bashrc and .profile (that I load from .bashrc) have not changed and do not include any onecmd instruction. set -o | grep onecmd shows onecmd off in my shell, yet every snapshot captures set -o onecmd. Removing/renaming .bashrc isn't practical for me on macOS.

With the help of Claude I tried several workarounds but none helped. What I figured out was that this set -o onecmd is added by Claude code into its shell snapshot file inside ~/.claude/shell-snapshots/ _the first time_ it runs the Bash tool. Which I think the OP steps also indicate.

alexkli · 4 months ago

✅ It works when I revert back to Claude 2.1.50.

  • Previous versions I tested that are also working: 2.1.49, 2.1.48, 2.1.47, (does not exist: 2.1.46), 2.1.45, 2.1.44, (does not existL 2.1.43), 2.1.42, 2.1.30, 2.1.20. Checked a few older versions since they were mentioned above and in related bug https://github.com/anthropics/claude-code/issues/26481.

❌ Failing: 2.1.51 and 2.1.52 (current latest).

  • All Bash tool commands fail with Error: Exit code 127.

---
Minimal steps to test different versions:

  • npm install -g @anthropic-ai/claude-code@<VERSION>
  • claude
  • Prompt: run bash 'echo hi'

As one liner:

npm install -g @anthropic-ai/claude-code@<VERSION> && claude --version && claude -p "run bash 'echo hi'"
alexkli · 4 months ago

The exit code 127 problem is still happening on Claude code 2.1.68 for me.

alexkli · 4 months ago

I eventually fixed this by getting rid of my ~/.bashrc on my Mac. Working fine on stable claude 2.1.58 now.

My shell setup using bash was maybe a bit awkward:

  • ~/.profile with all my shell customizations (PATH, PS1, aliases, shell completions)
  • ~/.bashrc was sourcing the ~/.profile

I changed it to have all my customizations in ~/.bash_profile instead and remove both ~/.profile and ~/.bashrc. This seems to be a better approach on Mac and using Terminal.app anyway.

dr0uleau · 4 months ago

Workaround: BASH_ENV with DEBUG trap

Found a reliable workaround for the set -o onecmd snapshot issue on macOS.

The root cause: shell snapshots capture set -o onecmd from non-interactive bash defaults. When the snapshot is later sourced, onecmd causes bash to exit after one command, breaking Claude Code's multi-command wrapper. This manifests as intermittent "(No output)" from the Bash tool.

Fix

Create ~/.claude-bash-env.sh:

set +o onecmd
trap 'set +o onecmd' DEBUG

Add to ~/.claude/settings.json:

{
  "env": {
    "BASH_ENV": "/path/to/your/home/.claude-bash-env.sh"
  }
}

Why it works

BASH_ENV is sourced by non-interactive bash before executing any commands — including when Claude Code sources the snapshot. The DEBUG trap fires after each command, so even when the snapshot re-enables onecmd via set -o onecmd, the trap immediately disables it again before the next command runs.

Things that did NOT work

  • set +o onecmd in ~/.bashrc or ~/.bash_profile — bash re-enables onecmd after sourcing config files
  • shellSnapshotEnabled: false in settings.json — ignored
  • launchd WatchPaths agent to patch snapshot files — race condition (Claude Code reads snapshot before the patcher runs)
  • SHELLOPTS env var — read-only, cannot disable options
markslilley · 4 months ago

Linux confirmation + process accumulation (fork-bomb behaviour)

Confirming this also affects Fedora 43 (Linux 6.19.7) with Bash 5.x, Claude Code 2.1.77.

Additional finding: set -o monitor compounds the problem

The snapshot captures two problematic options:

set -o monitor    # job control — hangs in non-interactive bash -c (no TTY)
set -o onecmd     # exits after one command

set -o monitor is enabled by default in interactive bash on Linux. When restored in the non-interactive bash -c subshell, it causes the process to sleep indefinitely waiting for terminal control signals that never come.

Process accumulation → system instability

The combination creates a runaway process accumulation:

  1. Snapshot restores set -o onecmd + set -o monitor
  2. bash -c "source snapshot.sh && ... && eval 'COMMAND' && pwd -P >| /tmp/claude-*-cwd" hangs — the process never writes to the cwd file
  3. Claude Code's timeout/retry logic spawns another attempt
  4. Repeat → 771 orphaned bash processes observed, each consuming ~40MB RSS
  5. System becomes unresponsive (~30GB memory consumed by stuck shells)
$ pgrep -cf 'shell-snapshots'
771

$ ps aux | grep shell-snapshots | head -3
user 545271 0.2 0.0 271704 40592 ? S 13:26 0:00 /bin/bash -c source ~/.claude/shell-snapshots/snapshot-bash-*.sh && ...
user 545272 0.2 0.0 271700 40584 ? S 13:26 0:00 /bin/bash -c source ~/.claude/shell-snapshots/snapshot-bash-*.sh && ...
user 545278 0.2 0.0 271708 40612 ? S 13:26 0:00 /bin/bash -c source ~/.claude/shell-snapshots/snapshot-bash-*.sh && ...

All processes in S (sleeping) state — stuck on job control signals, never completing.

Suggested fix

The snapshot generation should exclude at minimum these options:

# Current (broken):
set -o | grep "on" | awk '{print "set -o " $1}'

# Fixed:
set -o | grep "on" | grep -vE '^(monitor|onecmd) ' | awk '{print "set -o " $1}'

Or better, explicitly disable them after sourcing:

bash -c "source /path/to/snapshot.sh; set +o onecmd; set +o monitor; ACTUAL_COMMAND..."

Workaround

# Kill stuck processes
pkill -9 -f 'shell-snapshots'

# Patch existing snapshots
for f in ~/.claude/shell-snapshots/snapshot-bash-*.sh; do
  sed -i '/^set -o monitor$/d; /^set -o onecmd$/d' "$f"
done

# Prevent recurrence with BASH_ENV (credit: @dr0uleau)
echo -e 'set +o onecmd\nset +o monitor\ntrap "set +o onecmd; set +o monitor" DEBUG' > ~/.claude-bash-env.sh
# Add to ~/.claude/settings.json: { "env": { "BASH_ENV": "/home/USER/.claude-bash-env.sh" } }

# Safety net: run Claude Code with process limits
alias claude='systemd-run --user --scope -p TasksMax=150 -p MemoryMax=4G claude'

Environment

  • Claude Code: 2.1.77
  • OS: Fedora 43, Linux 6.19.7
  • Bash: 5.x (default interactive shell)
  • set -o monitor is ON by default in interactive bash on all major Linux distros
DariaDitiu · 3 months ago

Additional symptoms and workaround for set -o truncation
I experienced a related but slightly different symptom on the same setup (Windows + Git Bash via Scoop).

Environment:
OS: Windows 11
Claude Code: v2.1.45
Git Bash installed via Scoop (~/.scoop/apps/git/current/bin/bash.exe)

Symptom:
The shell snapshot was truncating set -o <option> entries — stripping the set -o prefix and leaving just the option name as a bare command. For example:

set -o monitor → became or in the snapshot (line 3)
set -o checkhash → became heckhash in the snapshot (line 5)

This caused every bash command in Claude Code to fail with command not found errors for or, heckhash, and dozens of base64-encoded lines from git internals, making Claude Code completely unusable — even basic pwd and git status failed.
Root cause:
Same as #19057 — presence of ~/.bashrc triggers full shell state capture, which then gets corrupted when written to the snapshot file.
Workaround (better than removing .bashrc):
Instead of removing .bashrc, add these two lines at the top of ~/.bashrc to turn off the problematic shell options before Claude Code captures the snapshot:
bashset +o monitor
set +o checkhash
This prevents those options from appearing in the snapshot while keeping .bashrc intact for env vars and PATH configuration — which are required for tools like curl, jq, and custom CLI scripts to work inside Claude Code on Windows.
Note: Make sure .bashrc is saved with Unix line endings (LF not CRLF), otherwise bash will fail to source it correctly. In PowerShell:
powershell$content = Get-Content C:\Users\<you>\.bashrc -Raw
$content = $content -replace "rn", "`n"
[System.IO.File]::WriteAllText("C:\Users\<you>\.bashrc", $content)

arnecor · 3 months ago

Subscribing. Issue is still there (2.1.107, VS Code, Windows 11)

github-actions[bot] · 1 month ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

github-actions[bot] · 1 day ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.