fix(zsh): move dotDir to XDG (~/.config/zsh), preserve history #23

Merged
lyrathorpe merged 1 commits from fix/zsh-xdg-dotdir into main 2026-06-10 15:58:47 +01:00
2 changed files with 30 additions and 16 deletions
Showing only changes of commit c7f2f5503b - Show all commits
+5 -3
View File
@@ -22,12 +22,13 @@ on top (work email, its own ssh config, extra packages).
## zsh
| Feature | Notes |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| oh-my-zsh | plugins `git`, `man`, `sudo` (Esc-Esc to prepend sudo), `colored-man-pages`, `extract`; theme `robbyrussell` |
| Autosuggestion | fish-style history suggestions as you type (→ to accept) |
| Syntax highlighting | commands coloured by validity as you type |
| Completion | menu completion; the dump is rebuilt on every activation (see Maintenance) |
| History | 100k in-memory/on-disk, deduped, space-prefixed commands ignored, timestamped, **shared live across sessions** |
| History | 100k in-memory/on-disk, deduped, space-prefixed commands ignored, timestamped, **shared live across sessions**; file stays at `~/.zsh_history` |
| Dotfiles location | `dotDir` is `~/.config/zsh` (XDG) — `.zshrc`/`.zshenv`/`.zcompdump` live there; `~/.zshenv` only bootstraps `$ZDOTDIR` |
| History substring search | type a fragment, then ↑/↓ cycles matching past commands — works in foot, iTerm2 and the Linux TTY (both CSI and SS3 arrow encodings bound) |
| Prompt | hostname is prefixed when over SSH |
@@ -128,7 +129,8 @@ forced off there) but still runs the agent.
## Maintenance behaviours
- **zcompdump reset** — `~/.zcompdump*` is removed on every activation, so a stale
- **zcompdump reset** — `~/.config/zsh/.zcompdump*` (plus legacy `~/.zcompdump*`
and the cache copy) is removed on every activation, so a stale
dump (pointing at `/nix/store` paths a rebuild or a manual GC removed) can't
break completion with `_git: function definition file not found`.
- **GC** — no scheduled timer; collect garbage deliberately (`nh clean all` /
+18 -6
View File
@@ -1,5 +1,6 @@
# Interactive shell: zsh + tmux. Wanted on every host.
{
config,
lib,
pkgs,
inputs,
@@ -28,6 +29,10 @@ in
programs.zsh = {
enable = true;
# Keep zsh dotfiles under XDG (~/.config/zsh) rather than the legacy $HOME
# layout, matching xdg.enable. history.path is pinned below so the existing
# ~/.zsh_history is reused, not orphaned by the dotDir move.
dotDir = "${config.xdg.configHome}/zsh";
enableCompletion = true;
enableVteIntegration = true;
autosuggestion.enable = true;
@@ -47,6 +52,9 @@ in
];
};
history = {
# Stay at the legacy ~/.zsh_history (default would follow dotDir into
# ~/.config/zsh and orphan the existing file). Keeps history intact.
path = "${config.home.homeDirectory}/.zsh_history";
append = true; # append, don't overwrite, on shell exit
size = 100000; # in-memory (HISTSIZE)
save = 100000; # on-disk (SAVEHIST)
@@ -324,12 +332,16 @@ in
# enables this in the work module; both being true merges cleanly.
services.ssh-agent.enable = lib.mkIf pkgs.stdenv.hostPlatform.isLinux true;
# Drop the zsh completion dump on every activation. A stale ~/.zcompdump
# caches /nix/store paths to completion functions; once a rebuild or a manual
# GC removes them, compinit fails with "_git: function definition file not
# found" for every completion. Deleting it forces a fresh rebuild from the
# current fpath on the next shell.
# Drop the zsh completion dump on every activation. A stale .zcompdump caches
# /nix/store paths to completion functions; once a rebuild or a manual GC
# removes them, compinit fails with "_git: function definition file not found"
# for every completion. Deleting it forces a fresh rebuild from the current
# fpath on the next shell. compinit dumps to $ZDOTDIR (~/.config/zsh now); the
# $HOME and cache paths are also swept to clear any legacy leftovers.
home.activation.resetZcompdump = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
$DRY_RUN_CMD rm -f "$HOME"/.zcompdump* "''${XDG_CACHE_HOME:-$HOME/.cache}"/zsh/.zcompdump* 2>/dev/null || true
$DRY_RUN_CMD rm -f \
"${config.xdg.configHome}"/zsh/.zcompdump* \
"$HOME"/.zcompdump* \
"''${XDG_CACHE_HOME:-$HOME/.cache}"/zsh/.zcompdump* 2>/dev/null || true
'';
}