[BUG] Shell snapshot produces syntax error and broken PATH when launched from VS Code Remote-WSL with .venv/ in workspace
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?
When Claude Code is launched from VS Code (Remote-WSL) in a workspace containing a .venv/ directory, the shell snapshot file (~/.claude/shell-snapshots/snapshot-bash-*.sh) is generated with two independent bugs that make every Bash tool call fail.
Bug A: Empty if/fi block (syntax error)
The snapshot contains an rg availability check with no body, which is invalid bash:
if ! (unalias rg 2>/dev/null; command -v rg) >/dev/null 2>&1; then
fi
This produces syntax error near unexpected token 'fi' on every command.
Bug B: Escaped braces in PATH (commands not found)
The snapshot writes a malformed PATH export:
export PATH=/home/user/code/project/.venv/bin:$\{PATH\}
The $\{PATH\} is never resolved, so the PATH contains only the .venv/bin directory. Basic commands (ls, env, grep) are not found.
Full broken snapshot (11 lines):
# Snapshot file
# Unset all aliases to avoid conflicts with functions
unalias -a 2>/dev/null || true
# Functions
# Shell Options
shopt -s expand_aliases
# Aliases
# Check for rg availability
if ! (unalias rg 2>/dev/null; command -v rg) >/dev/null 2>&1; then
fi
export PATH=/home/user/code/project/.venv/bin:$\{PATH\}
Compare to a working snapshot generated from an interactive terminal session: 101 lines with base64-encoded shell functions, 60+ shopt options, a full rg function body, and a fully resolved PATH.
What Should Happen?
The snapshot should:
- Write a valid
ifblock body (even justtrue) whenrgis not found, instead of an empty block - Resolve
${PATH}to actual path values instead of escaping braces as$\{PATH\} - Handle the non-interactive shell case gracefully: either source
.bashrcin a way that bypasses the interactive guard, or capture the environment from the parent process
Error Messages/Logs
~/.claude/shell-snapshots/snapshot-bash-*.sh: line 10: syntax error near unexpected token `fi'
~/.claude/shell-snapshots/snapshot-bash-*.sh: line 10: `fi'
/bin/bash: line 1: env: command not found
/bin/bash: line 1: grep: command not found
/bin/bash: line 1: sort: command not found
Steps to Reproduce
- Create a Python project with a
.venv/directory in the workspace root (e.g.python3 -m venv .venv) - Have a
~/.bashrcwith the standard Ubuntu interactive guard at the top:
``bash``
case $- in
*i*) ;;
*) return;;
esac
- Open the project in VS Code using the Remote-WSL extension
- Launch Claude Code from the VS Code integrated terminal (or via the VS Code Claude Code extension)
- Try any Bash tool call. It fails with
syntax error near unexpected token 'fi'
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.79
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
bash in terminal in VS code, not plugin sidebar
Why the snapshot is minimal (11 lines vs 101):
Claude Code spawns a non-interactive bash subprocess to capture shell state. ~/.bashrc has the standard Ubuntu interactive guard (case $-) that returns immediately for non-interactive shells. None of the shell config loads. The snapshot captures almost nothing.
Bug A (empty if/fi):
The non-interactive shell skips .bashrc, so rg (ripgrep) is not available. The snapshot generator writes the if check skeleton but never fills in the body. An empty if/fi is invalid bash.
Bug B (escaped braces in PATH):
Through 6 sessions of testing I confirmed Claude Code itself injects VIRTUAL_ENV when it detects .venv/ in the workspace. It is NOT coming from VS Code or any Python extension.
Evidence: /proc/$PPID/environ does not contain VIRTUAL_ENV, but Claude Code's shell environment does.
The snapshot generator sees VIRTUAL_ENV and writes $VIRTUAL_ENV/bin:${PATH}. It then escapes the braces to $\{PATH\}, which is not valid bash variable expansion. Since .bashrc was skipped, there's no other PATH definition, leaving PATH with only .venv/bin.
Tests performed to isolate Bug B:
| Test | Result |
|------|--------|
| Remove VIRTUAL_ENV from .vscode/settings.json | Bug persists |
| Set python.terminal.activateEnvironment: false | Bug persists |
| Set python.defaultInterpreterPath: "" | Bug persists |
| Disable ms-python.python extension | PYTHONSTARTUP gone, VIRTUAL_ENV persists |
| Disable ALL 4 Python extensions | VIRTUAL_ENV still present |
| Check /proc/$PPID/environ | VIRTUAL_ENV NOT in parent process |
Conclusion: Claude Code is the sole source of VIRTUAL_ENV. No VS Code settings or extension changes can prevent this.
Current Workaround
Manually edit ~/.claude/shell-snapshots/snapshot-bash-*.sh each session:
- Add
trueinside the emptyif/fiblock - Replace the
export PATH=...line with resolved system paths
This must be done every time Claude Code is restarted from VS Code.
Related Issues
- #19053 - Malformed PATH with escaped characters (macOS, closed)
- #15128 - Empty PATH on Windows Git Bash
- #9670 - Invalid syntax in
rgcheck (same as Bug A) - #2824 - False positive "not in PATH" warning
- #4999 - Malformed alias causing syntax error (closed/fixed)
- #1872 - Syntax error with Oh My Zsh
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗