VSCode DevContainer loads wrong .zshrc and writes history into /tmp

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.

zsh
# /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.

zsh
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:

zsh
# 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.

Comments

Leave a Reply