When working with Visual Studio Code DevContainers and using zsh as your default shell, you may encounter an annoying issue: instead of loading the familiar ~/.zshrc
and writing history to ~/.zsh_history
, VSCode suddenly uses a temporary directory such as /tmp/xyz-code-zsh/.zsh_history
. As a result, important shell settings are lost and your history is no longer persistent.
Cause
When starting a DevContainer, VSCode sets the ZDOTDIR
variable to a temporary directory. Since zsh looks for its configuration files in $ZDOTDIR
by default, it no longer loads the files from the home directory but instead from this temporary path. As a result, the wrong history file is used.
Solution
The simplest and most robust solution is to enforce system-wide that zsh always loads the .zshrc
from the home directory. To do this, adjust the /etc/zsh/zshenv
file, because it is always loaded first – even before ZDOTDIR
is considered.
# /etc/zsh/zshenv
# Always use $HOME for ZDOTDIR
export ZDOTDIR="$HOME"
# Load home .zshrc for interactive shells
if [[ -o interactive ]] && [[ -r "$HOME/.zshrc" ]] && [[ -z "$__HOME_ZSHRC_SOURCED" ]]; then
export __HOME_ZSHRC_SOURCED=1
source "$HOME/.zshrc"
fi
This ensures that, regardless of VSCode, the correct configuration from /home/<user>/.zshrc
is always loaded. The history file will also reliably be written to ~/.zsh_history
.
Dockerfile Integration
If you build your own DevContainer images, it’s best to include this fix directly in the Dockerfile. This way the behavior is reproducible and also works after rebuilding the container.
RUN printf '%s\n' \
'# Always use $HOME for zsh config (override VS Code tmp ZDOTDIR)' \
'export ZDOTDIR="$HOME"' \
'' \
'# Load user ~/.zshrc for interactive shells (avoid double-sourcing)' \
'if [[ -o interactive ]] && [[ -r "$HOME/.zshrc" ]] && [[ -z "$__HOME_ZSHRC_SOURCED" ]]; then' \
' export __HOME_ZSHRC_SOURCED=1' \
' source "$HOME/.zshrc"' \
'fi' \
>> /etc/zsh/zshenv
Conclusion
The issue with the wrong .zshrc
and the temporary history file occurs in many DevContainer environments when VSCode sets ZDOTDIR
to its own directory. With a small patch in /etc/zsh/zshenv
, this behavior can be permanently fixed. This way, your usual zsh configuration and shell history remain consistent even inside DevContainers.
Troubleshooting
To verify that the patch in /etc/zsh/zshenv
is applied correctly, you can check the most important variables directly. Open a terminal inside the DevContainer and run the following commands:
# Show where zsh looks for its configuration files
echo $ZDOTDIR
# Expected: /home/<user>
# Check which history file is actually used
echo $HISTFILE
# Expected: /home/<user>/.zsh_history
# Test: start a new interactive shell and check the variables
zsh -ilc 'echo "ZDOTDIR=$ZDOTDIR HISTFILE=$HISTFILE"'
# Expected: ZDOTDIR=/home/<user> HISTFILE=/home/<user>/.zsh_history
If the output looks as expected, zsh is now reliably loading your home .zshrc
and writing history back to your home directory.
Leave a Reply
You must be logged in to post a comment.