[BUG] Shell snapshots capture interactive functions without dependencies, breaking cd and other commands
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?
Shell snapshots capture interactive shell function definitions (from .zshrc) but source them in non-interactive contexts where their dependencies don't exist. This breaks commands like cd for users with zoxide and any other shell functions that depend on tools initialized in .zshrc.
Error example:
cd:1: command not found: __zoxide_z
The root cause is an architectural issue: snapshots capture function references (e.g., cd() { __zoxide_z "$@" }) without capturing function dependencies (the __zoxide_z implementation itself).
This affects:
- Users with
zoxide(2.5M+ installs) - Users with
fzfkeybindings - Users with Oh My Zsh, zinit, or similar frameworks
- Anyone with custom shell functions in
.zshrc
What Should Happen?
When Claude Code sources shell snapshots in non-interactive contexts, either:
Option A (Ideal): Resolve and capture all function dependencies so they work in non-interactive shells
Option B (Acceptable): Don't capture functions that override builtins or have external dependencies
Option C (Minimum): Fail early with a clear error message explaining the missing dependency and suggesting workarounds
Error Messages/Logs
# Running Bash tool command
cd /tmp
# Error output
cd:1: command not found: __zoxide_z
# Verification
$ type cd
cd is a shell function from /Users/username/.claude/shell-snapshots/snapshot-zsh-1760588587940-0rl83n.sh
$ type __zoxide_z
zsh: command not found: __zoxide_z
Steps to Reproduce
- Install zoxide:
```bash
# macOS
brew install zoxide
# Linux
curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
```
- Configure
.zshrc(add this line):
``bash``
# In ~/.zshrc
eval "$(zoxide init zsh --cmd cd)"
- Start new terminal to load configuration:
``bash``
exec zsh
- Verify cd override in interactive shell:
```bash
type cd
# Output: cd is a shell function
type __zoxide_z
# Output: __zoxide_z is a shell function (shows definition)
```
- Start Claude Code and run Bash tool command:
``bash``
cd /tmp
- Observe error:
````
cd:1: command not found: __zoxide_z
Technical Root Cause
Snapshot capture flow:
- Captures shell state from interactive shell (where
.zshrcis loaded) - Serializes ~6,074 lines with 146 functions to snapshot file (~196KB)
- Sources snapshot in non-interactive shell (where
.zshrcis NOT loaded) - Function definitions reference commands that don't exist
Example from actual snapshot:
$ grep -A 3 "^cd ()" ~/.claude/shell-snapshots/snapshot-zsh-*.sh
cd () {
__zoxide_z "$@"
}
$ grep "__zoxide_z ()" ~/.claude/shell-snapshots/snapshot-zsh-*.sh
# (no output - dependency not captured)
The broken contract:
- Interactive context:
.zshrcloads →zoxide init→ defines__zoxide_z→ definescdwrapper - Non-interactive context:
.zshrcNOT loaded →__zoxide_zmissing →cdfunction fails
Environment
- Claude Code Version: 2.0.19
- Shell: zsh (issue likely affects zsh users specifically)
- OS: macOS Darwin 24.6.0 (likely affects Linux as well)
- Reproduction Rate: 100% with zoxide or similar tools
Additional Context
Related to GitHub Issue #3601: Shell snapshot migration from file-based to in-memory implementation. This architectural issue persists in the new implementation.
Impact scope:
cdwith zoxide's--cmd cdflag ❌lsif aliased toeza/exa❌catif aliased tobat❌- Any fzf keybinding functions ❌
- Custom functions using plugin commands ❌
- Framework-specific commands (zinit, oh-my-zsh) ❌
Current workarounds:
- Guard interactive customizations in
.zshrc:
``bash``
if [[ -o interactive ]]; then
eval "$(zoxide init zsh --cmd cd)"
fi
- Use alternative command names (don't override builtins):
``bash``
eval "$(zoxide init zsh)" # Creates 'z' command instead of overriding 'cd'
Suggested Fixes
- Dependency resolution during capture: Recursively capture function dependencies or skip functions with missing dependencies
- Match execution context: If snapshot is from interactive shell, execute commands with
zsh -i -cto load.zshrc
- Selective capture: Only capture shell state valid in non-interactive contexts (skip builtin overrides)
- Clear error handling: Detect missing dependencies and fail with actionable guidance
Files Available
Can provide:
- Shell snapshot files
.zshrcconfiguration- Complete reproduction environment
- Any other debugging information needed
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗