[CRITICAL] Bash tool deletes entire project root after command interrupt - PWD state corruption
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?
[CRITICAL] Bash tool deletes entire project root after command interrupt - PWD state corruption
Environment
- Claude Code Version: Latest (2026-01-11)
- Model: Sonnet 4.5
- OS: macOS 13.1 (Darwin 21.6.0)
- Shell: zsh
- Impact: Complete project directory deletion, DATA LOSS
Summary
Claude Code's Bash tool deleted my entire project directory after I interrupted a running command. The tool's persistent shell session lost track of its working directory (PWD) and executed rm -rf * in the project root instead of the intended Builds/Xcode/ subdirectory.
Only hidden files survived (.gitignore, .claude/), proving the glob pattern executed in the wrong location.
What Happened (Timeline)
08:00 - Claude runs: cd Builds/Xcode && cmake -G Xcode ../..
✅ SUCCESS - CMake configures project
08:?? - Claude runs: xcodebuild -scheme WHELMED -configuration Debug build
⚠️ USER INTERRUPTS THIS COMMAND (via UI interrupt button)
08:?? - Claude runs: cd Builds/Xcode && rm -rf * && cmake -G Xcode ../..
❌ PWD STATE CORRUPTED - Executes in wrong directory
Result: Entire project deleted
Evidence
1. Filesystem State After Incident
$ ls -la /Users/jreng/Documents/Poems/dev/whelmed/
total 24
drwxr-xr-x 5 jreng staff 160 Jan 11 08:13 .
drwxr-xr-x 7 jreng staff 224 Jan 11 05:17 ..
-rw-r--r--@ 1 jreng staff 6148 Jan 11 06:58 .DS_Store
drwxr-xr-x 3 jreng staff 96 Jan 11 08:11 .claude/
-rw-r--r-- 1 jreng staff 256 Jan 11 05:44 .gitignore
Missing:
- ❌ CMakeLists.txt
- ❌ Source/ directory (all .cpp/.h files)
- ❌ Builds/ directory
- ❌ SESSION-LOG.md
- ❌ All project files
Survived:
- ✅ .gitignore (hidden file, not matched by
*glob) - ✅ .claude/ (hidden directory, not matched by
*glob)
This pattern proves rm -rf * executed in project root, not Builds/Xcode/.
2. Independent Verification
When I switched to my build TUI (running in a separate terminal), it immediately showed:
Error: CMakeLists.txt not found
I ran ls in my terminal - empty. Opened Finder - all files gone.
This happened BEFORE I ran any commands. Files were deleted during Claude Code's execution.
3. Claude Code's Own Error Messages
After the deletion, Claude attempted to run cmake and got:
CMake Error: The source directory "/Users/jreng/Documents/Poems" does not
appear to contain CMakeLists.txt.
This proves cmake was looking in the wrong directory because PWD state was corrupted.
Root Cause
Persistent bash shell PWD tracking fails after command interrupts.
The sequence was:
- Shell is in:
/Users/jreng/Documents/Poems/dev/whelmed/ cd Builds/Xcode- shell moves to subdirectory ✅xcodebuild ...- user interrupts ⚠️- PWD state corruption occurs here 🐛
- Next command:
cd Builds/Xcode && rm -rf *
cd Builds/Xcodesucceeds (directory exists)- But shell's internal PWD is actually project root
rm -rf *executes in WRONG DIRECTORY
Reproduction Steps
- Create a project with a
Builds/Xcode/subdirectory - Use Claude Code to run:
cd Builds/Xcode && xcodebuild -scheme MyProject build - Interrupt the command (click stop/interrupt in Claude Code UI)
- Claude Code attempts to clean and retry:
cd Builds/Xcode && rm -rf * - Check project root - all files deleted
Cost Impact
- Development time lost: ~8 hours recreating project
- API costs: ~$100+ to restore files via Claude Code
- Previous incidents: This user has experienced similar bugs before (git reset incident)
Recovery
Only possible due to Claude Code's automatic file history backups at ~/.claude/file-history/.
Without this backup, this would be UNRECOVERABLE DATA LOSS.
Users should NOT rely on LLM tools having backup mechanisms to protect against catastrophic bugs.
Why This Is Critical
- Silent failure - No warning, no error, just data loss
- User interrupt is common - Users interrupt long-running commands regularly
- No safeguards - No validation before destructive operations
- Pattern of issues - User reports previous git reset incident
- Production impact - Real projects, real money, real trust loss
What Should Have Prevented This
1. PWD Verification Before Destructive Commands
# BEFORE any rm command
expected_dir="/Users/jreng/Documents/Poems/dev/whelmed/Builds/Xcode"
actual_dir=$(pwd)
if [[ "$actual_dir" != "$expected_dir" ]]; then
echo "ERROR: PWD mismatch. Expected $expected_dir, got $actual_dir"
echo "Refusing to execute rm command."
exit 1
fi
rm -rf *
2. Shell State Reset After Interrupts
After ANY interrupt, the Bash tool should:
- Clear all shell state
- Re-verify PWD with
pwdcommand - Compare against expected directory
- Refuse commands if state is uncertain
3. Destructive Command Safeguards
NEVER allow these patterns in project roots:
rm -rf *
rm -rf ./*
rm -rf ../
Only allow whitelisted patterns:
rm -rf build/
rm -rf Builds/
rm -rf node_modules/
rm -rf dist/
4. Require User Confirmation
For any rm -rf command, show user:
⚠️ DESTRUCTIVE OPERATION
Command: rm -rf *
Working Directory: /Users/jreng/Documents/Poems/dev/whelmed/
This will delete ALL FILES in the directory above.
Type 'yes' to confirm:
Recommended Fixes
Immediate (Emergency Patch)
- ✅ Add PWD verification before every command
- ✅ Disable
rm -rf *entirely until PWD tracking is fixed - ✅ Reset shell state completely after interrupts
- ✅ Add confirmation prompts for destructive operations
Medium-term
- ✅ Fix PWD state tracking in persistent shell sessions
- ✅ Add transaction-like shell state management
- ✅ Log all destructive commands for audit trail
- ✅ Add
/tmpsandbox for build operations
Long-term
- ✅ Implement shell state verification tests
- ✅ Add integration tests for interrupt scenarios
- ✅ Consider sandboxing all file operations
- ✅ Add undo/rollback mechanism for destructive operations
Related Issues
- User reports previous incident where Claude Code reset entire git repository
- This suggests a pattern of PWD/state tracking bugs, not an isolated incident
- Other users may have experienced this silently
Supporting Files
User has detailed bug report with full transcript at:
/Users/jreng/Documents/Poems/dev/whelmed/CATASTROPHIC-BUG-REPORT.md
Session backup directory:
~/.claude/file-history/8d099d08-70f2-490a-99ee-ab867de5b463/
Request
- Acknowledge this as P0/Critical severity
- Engineering investigation (not bot replies)
- Public status update on fix timeline
- User compensation for data loss and recovery costs
- Incident report to warn other users
---
This is not a feature request. This is a critical data loss bug affecting production use.
I've lost hundreds of dollars and countless hours due to this bug. I need a real response from engineering, not automated support replies.
If Claude Code cannot safely execute bash commands, it should not offer the feature.
What Should Happen?
Interruption should not delete the current project directory content duh
Error Messages/Logs
Steps to Reproduce
Reproduction Steps - PWD State Corruption After Interrupt
Prerequisites
- Claude Code CLI installed
- macOS or Linux with bash/zsh
- Any project with subdirectory structure
Setup Test Environment
# Create test project
mkdir -p /tmp/claude-bug-test
cd /tmp/claude-bug-test
# Create project structure
mkdir -p Builds/Xcode
echo "test file 1" > file1.txt
echo "test file 2" > file2.txt
echo "CMakeLists.txt content" > CMakeLists.txt
mkdir -p Source
echo "int main() {}" > Source/main.cpp
# Create .gitignore to verify glob behavior
echo "*.log" > .gitignore
# Verify structure
tree
# Expected:
# .
# ├── .gitignore
# ├── Builds
# │ └── Xcode
# ├── CMakeLists.txt
# ├── Source
# │ └── main.cpp
# ├── file1.txt
# └── file2.txt
Reproduction Steps
Step 1: Start Claude Code
cd /tmp/claude-bug-test
claude-code
Step 2: Run Command That Changes Directory
In Claude Code, ask it to run:
cd Builds/Xcode && sleep 30 && echo "done"
Or more realistically:
cd Builds/Xcode && python -m http.server 8000
Step 3: Interrupt the Command
While the command is running, click the Stop/Interrupt button in Claude Code UI.
Or send interrupt signal via the interface.
Step 4: Immediately Run Destructive Command
Without any delay, ask Claude Code to run:
cd Builds/Xcode && rm -rf * && echo "cleaned"
Step 5: Check Result
# In a separate terminal (NOT Claude Code)
cd /tmp/claude-bug-test
ls -la
Expected Behavior (Correct)
.
├── .gitignore ← Hidden file, preserved
├── Builds
│ └── Xcode ← Empty (cleaned correctly)
├── CMakeLists.txt ← Preserved
├── Source
│ └── main.cpp ← Preserved
├── file1.txt ← Preserved
└── file2.txt ← Preserved
Actual Behavior (BUG)
.
└── .gitignore ← Only hidden files remain!
All non-hidden files DELETED from project root instead of from Builds/Xcode/.
Why This Happens
- First command:
cd Builds/Xcode && sleep 30
- Shell changes to
/tmp/claude-bug-test/Builds/Xcode/ - PWD state stored in persistent session
- User interrupts command
- Shell process receives SIGINT
- PWD state becomes corrupted/desynchronized
- Next command:
cd Builds/Xcode && rm -rf *
- Shell THINKS it executes:
cd Builds/Xcodefrom/tmp/claude-bug-test/ - Shell ACTUALLY in:
/tmp/claude-bug-test/(PWD corruption) rm -rf *executes in PROJECT ROOT instead ofBuilds/Xcode/
Variations That Also Trigger Bug
Variation 1: With Build Commands
cd Builds/Xcode && cmake -G Xcode ../..
# Interrupt during cmake
cd Builds/Xcode && rm -rf * && cmake -G Xcode ../..
# Project root deleted
Variation 2: With Compilation
cd Builds/Xcode && xcodebuild -scheme MyProject build
# Interrupt during build
cd Builds/Xcode && rm -rf *
# Project root deleted
Variation 3: Multiple Directory Changes
cd Source && cd .. && cd Builds/Xcode && sleep 10
# Interrupt
cd Builds/Xcode && rm -rf *
# Project root deleted
Additional Evidence of PWD Corruption
After the bug triggers, if you ask Claude Code:
pwd
It may show the WRONG directory, or show the correct directory but still execute commands in the wrong location (PWD state vs actual location mismatch).
Cleanup After Testing
rm -rf /tmp/claude-bug-test
Notes for Anthropic Engineers
Debug Points to Check
- Persistent shell session state management
- How is PWD tracked between commands?
- Is PWD state cleared/validated after interrupts?
- Interrupt signal handling
- What happens to shell state when SIGINT received?
- Is there a race condition in state synchronization?
- Command execution flow
- Does
cd X && cmdvalidate PWD before executingcmd? - Is
cdsuccess verified before continuing?
Suggested Verification Tests
# Before ANY rm command, verify PWD
actual_pwd=$(pwd)
echo "Current PWD: $actual_pwd"
# Check if we're in expected directory
if [[ "$actual_pwd" != *"/Builds/"* ]]; then
echo "ERROR: Not in build directory!"
exit 1
fi
Shell State Logging
Add debug logging to persistent shell:
echo "[DEBUG] Before cmd: PWD=$(pwd)"
# execute command
echo "[DEBUG] After cmd: PWD=$(pwd)"
echo "[DEBUG] Exit code: $?"
This would help trace exactly when PWD corruption occurs.
Priority
This is P0/Critical because:
- ✅ Causes data loss
- ✅ Easy to trigger (just interrupt a command)
- ✅ Common workflow (users interrupt long builds regularly)
- ✅ No warning or recovery
- ✅ Silent failure (user doesn't know until files gone)
---
Reproduction rate: 100% when following steps exactly.
The bug is deterministic if PWD state corruption occurs on interrupt.
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.4 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other
Additional Information
Reproduction Steps - PWD State Corruption After Interrupt
Prerequisites
- Claude Code CLI installed
- macOS or Linux with bash/zsh
- Any project with subdirectory structure
Setup Test Environment
# Create test project
mkdir -p /tmp/claude-bug-test
cd /tmp/claude-bug-test
# Create project structure
mkdir -p Builds/Xcode
echo "test file 1" > file1.txt
echo "test file 2" > file2.txt
echo "CMakeLists.txt content" > CMakeLists.txt
mkdir -p Source
echo "int main() {}" > Source/main.cpp
# Create .gitignore to verify glob behavior
echo "*.log" > .gitignore
# Verify structure
tree
# Expected:
# .
# ├── .gitignore
# ├── Builds
# │ └── Xcode
# ├── CMakeLists.txt
# ├── Source
# │ └── main.cpp
# ├── file1.txt
# └── file2.txt
Reproduction Steps
Step 1: Start Claude Code
cd /tmp/claude-bug-test
claude-code
Step 2: Run Command That Changes Directory
In Claude Code, ask it to run:
cd Builds/Xcode && sleep 30 && echo "done"
Or more realistically:
cd Builds/Xcode && python -m http.server 8000
Step 3: Interrupt the Command
While the command is running, click the Stop/Interrupt button in Claude Code UI.
Or send interrupt signal via the interface.
Step 4: Immediately Run Destructive Command
Without any delay, ask Claude Code to run:
cd Builds/Xcode && rm -rf * && echo "cleaned"
Step 5: Check Result
# In a separate terminal (NOT Claude Code)
cd /tmp/claude-bug-test
ls -la
Expected Behavior (Correct)
.
├── .gitignore ← Hidden file, preserved
├── Builds
│ └── Xcode ← Empty (cleaned correctly)
├── CMakeLists.txt ← Preserved
├── Source
│ └── main.cpp ← Preserved
├── file1.txt ← Preserved
└── file2.txt ← Preserved
Actual Behavior (BUG)
.
└── .gitignore ← Only hidden files remain!
All non-hidden files DELETED from project root instead of from Builds/Xcode/.
Why This Happens
- First command:
cd Builds/Xcode && sleep 30
- Shell changes to
/tmp/claude-bug-test/Builds/Xcode/ - PWD state stored in persistent session
- User interrupts command
- Shell process receives SIGINT
- PWD state becomes corrupted/desynchronized
- Next command:
cd Builds/Xcode && rm -rf *
- Shell THINKS it executes:
cd Builds/Xcodefrom/tmp/claude-bug-test/ - Shell ACTUALLY in:
/tmp/claude-bug-test/(PWD corruption) rm -rf *executes in PROJECT ROOT instead ofBuilds/Xcode/
Variations That Also Trigger Bug
Variation 1: With Build Commands
cd Builds/Xcode && cmake -G Xcode ../..
# Interrupt during cmake
cd Builds/Xcode && rm -rf * && cmake -G Xcode ../..
# Project root deleted
Variation 2: With Compilation
cd Builds/Xcode && xcodebuild -scheme MyProject build
# Interrupt during build
cd Builds/Xcode && rm -rf *
# Project root deleted
Variation 3: Multiple Directory Changes
cd Source && cd .. && cd Builds/Xcode && sleep 10
# Interrupt
cd Builds/Xcode && rm -rf *
# Project root deleted
Additional Evidence of PWD Corruption
After the bug triggers, if you ask Claude Code:
pwd
It may show the WRONG directory, or show the correct directory but still execute commands in the wrong location (PWD state vs actual location mismatch).
Cleanup After Testing
rm -rf /tmp/claude-bug-test
Notes for Anthropic Engineers
Debug Points to Check
- Persistent shell session state management
- How is PWD tracked between commands?
- Is PWD state cleared/validated after interrupts?
- Interrupt signal handling
- What happens to shell state when SIGINT received?
- Is there a race condition in state synchronization?
- Command execution flow
- Does
cd X && cmdvalidate PWD before executingcmd? - Is
cdsuccess verified before continuing?
Suggested Verification Tests
# Before ANY rm command, verify PWD
actual_pwd=$(pwd)
echo "Current PWD: $actual_pwd"
# Check if we're in expected directory
if [[ "$actual_pwd" != *"/Builds/"* ]]; then
echo "ERROR: Not in build directory!"
exit 1
fi
Shell State Logging
Add debug logging to persistent shell:
echo "[DEBUG] Before cmd: PWD=$(pwd)"
# execute command
echo "[DEBUG] After cmd: PWD=$(pwd)"
echo "[DEBUG] Exit code: $?"
This would help trace exactly when PWD corruption occurs.
Priority
This is P0/Critical because:
- ✅ Causes data loss
- ✅ Easy to trigger (just interrupt a command)
- ✅ Common workflow (users interrupt long builds regularly)
- ✅ No warning or recovery
- ✅ Silent failure (user doesn't know until files gone)
---
Reproduction rate: 100% when following steps exactly.
The bug is deterministic if PWD state corruption occurs on interrupt.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗