From 677f710f279ad9d37100bb5825682b531fea4e8e Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 12 Sep 2026 05:19:11 +0000 Subject: [PATCH] image(debian): move the shell history to a mountable directory Dev container templates can keep bash history across rebuilds by mounting a named volume, but the history file has to sit in a directory of its own for that: a named volume cannot be mounted over ~/.bash_history, and mounting one over the home directory would shadow everything the image puts there. Set HISTFILE to /home/dev/.local/state/bash/history and create that directory, the way the terraform and opentofu images set TF_PLUGIN_CACHE_DIR and create the directory their templates mount. The path follows the XDG Base Directory specification, which names history as state data under $XDG_STATE_HOME. Creating the directory in the image also makes the mount belong to "dev": Docker creates a mount point missing from the image owned by root, and nothing in the container could fix that afterwards. Bash also wrote the history file only when the shell exited, which a container stop does not always allow. Appending on every prompt keeps the session's history even when the shell is killed. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01L6orjBAZq9L5t7rV5RDmXd --- debian/Dockerfile | 3 +++ debian/README.md | 6 ++++++ debian/assets/.bashrc | 3 +++ debian/smoke-test.sh | 3 +++ 4 files changed, 15 insertions(+) diff --git a/debian/Dockerfile b/debian/Dockerfile index 96fbe63..5717d64 100644 --- a/debian/Dockerfile +++ b/debian/Dockerfile @@ -51,3 +51,6 @@ COPY --chown=${USERNAME}:${USERNAME} assets/.bashrc /home/${USERNAME}/.bashrc USER ${USERNAME} WORKDIR /workspaces + +ENV HISTFILE=/home/${USERNAME}/.local/state/bash/history +RUN mkdir -p "${HISTFILE%/*}" diff --git a/debian/README.md b/debian/README.md index 1771a99..81a7ec9 100644 --- a/debian/README.md +++ b/debian/README.md @@ -55,6 +55,12 @@ The image runs as the non-root user `dev` (UID/GID 1000) and its working directo Container clients pick up the user without extra configuration. Every image built on this one inherits that label. +`dev`'s login shell is bash, which appends each command to `$HISTFILE` as it is entered rather +than at exit. `HISTFILE` is `/home/dev/.local/state/bash/history` rather than the default +`~/.bash_history`, and that directory is created in the image, so mounting a volume on it keeps +the shell history across container rebuilds, which is what the +[Dev Container template](#dev-container-template) does. + ## Not installed - **No development headers beyond libc.** `build-essential` covers the compiler, linker, and diff --git a/debian/assets/.bashrc b/debian/assets/.bashrc index 9ac42fb..33ccd5c 100644 --- a/debian/assets/.bashrc +++ b/debian/assets/.bashrc @@ -9,6 +9,9 @@ HISTCONTROL=ignoreboth HISTSIZE=${HISTSIZE:-10000} HISTFILESIZE=${HISTFILESIZE:-20000} shopt -s histappend +# Append each command to HISTFILE as it is entered. Waiting for the shell to exit +# loses the session when the container is stopped before bash gets to write it. +PROMPT_COMMAND=${PROMPT_COMMAND:+${PROMPT_COMMAND}$'\n'}'history -a' # Check terminal size after each command. shopt -s checkwinsize diff --git a/debian/smoke-test.sh b/debian/smoke-test.sh index 7f45bc8..5b41fa7 100755 --- a/debian/smoke-test.sh +++ b/debian/smoke-test.sh @@ -7,6 +7,9 @@ git --version cc --version make --version +echo "=== Verifying the shell history directory is writable ===" +[ -w "${HISTFILE%/*}" ] + echo "=== Verifying the C toolchain compiles and links ===" TMPDIR=$(mktemp -d) trap 'rm -rf "$TMPDIR"' EXIT