Shell History
Code name:
shell-history
Keeps your bash, zsh and fish history across container rebuilds, --no-cache included, and
GitHub Codespaces. The history lives in a Docker named volume dedicated to this devcontainer:
each project keeps its own commands, and never sees another project’s.
Also included automatically: repairs broken host paths in your git config and restores your SSH commit-signing key on every attach, on both local and cloud containers, with nothing to set up on your end — see
helpers4-commonfor how it works.
Formerly
shell-history-per-project. That feature kept history under/workspaces/.shell-history, which only survived a rebuild where/workspacesitself was persisted (GitHub Codespaces) — with VS Code’s default mount, it was lost every time. See the migration notes.
When to use this
Section titled “When to use this”Use this when you want the commands you typed in a devcontainer to still be there after a rebuild, without one project’s history showing up in another’s.
Alternatives:
- Bind-mounting your host’s own history file (
~/.zsh_history) shares one history across every project and the host itself, and fails the container build wherever that file doesn’t exist (Codespaces, a fresh machine). - stuartleeks/dev-container-features
also has a
shell-historyfeature built on a named volume.
No initializeCommand required — Docker creates the volume automatically the first time it’s
needed.
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
username | string | auto | Container user whose shells keep their history. auto detects vscode/node/codespace/uid-1000, in that order. |
maxHistorySize | string | 10000 | Number of history entries to keep, in memory and in the history file (bash and zsh). |
How it works
Section titled “How it works”Every shell found in the image (bash, zsh, fish) is configured; there’s nothing to pick.
-
Build time (
install.sh): points each shell’s history at/mnt/h4history, owned by the container user and private (700/600— history often holds a token typed on a command line).- bash — a block at the end of
~/.bashrc:HISTFILE,HISTSIZEandHISTFILESIZE(overriding the distro’s own defaults, e.g. Debian’s 1000 / 2000),histappend, andhistory -ainPROMPT_COMMANDso each command is saved as soon as it runs — not only when the shell exits cleanly, which a container stop or a closed terminal never does. - zsh — a block at the end of
~/.zshrc:HISTFILE,HISTSIZE,SAVEHIST,SHARE_HISTORY(each command saved as it runs, and shared between open terminals). - fish —
~/.local/share/fishis linked to the volume. fish has no setting for its history path, and saves through a temporary file it then renames, so linking the file alone would not survive the first save. ~/.bash_historyand~/.zsh_historylink to the volume too, for tools that read them directly.
The blocks sit between
# >>> helpers4 shell-history >>>markers: installing again replaces them instead of stacking copies. - bash — a block at the end of
-
Mount (
devcontainer-feature.json → mounts): the Docker named volumehelpers4-shell-history-${devcontainerId}is attached at/mnt/h4historybefore any shell starts. -
Once per container (
postCreateCommand):setup-volume.shmakes sure the volume is writable by the container user, and imports the historyshell-history-per-projectleft in/workspaces/.shell-history, if any.
OS and Architecture Support
Section titled “OS and Architecture Support”- OS: Linux (Debian/Ubuntu-based images)
- Architectures: amd64, arm64
Version History
Section titled “Version History”- v1.0.0: Renamed from
shell-history-per-project(last release v1.2.3), and history now actually survives rebuilds: a named volume dedicated to this devcontainer replaces/workspaces/.shell-history. Also fixed along the way:maxHistorySizenow applies to bash’s history file too (Debian’sHISTFILESIZE=2000used to win), bash saves each command as it runs, fish history is really persisted, history files are private instead of world-readable, and installing again no longer stacks duplicate blocks in~/.bashrc/~/.zshrc. ThetargetShellandhistoryDirectoryoptions are gone: every installed shell is configured, and the history lives in the volume.
