From 19dfb32cf6d7cc6d5836d40444b48477cc002432 Mon Sep 17 00:00:00 2001 From: Emma Thorpe Date: Wed, 10 Jun 2026 11:08:49 +0100 Subject: [PATCH] feat(shell): zsh tooling, tmux plugins, nix-index, nh zsh: history tuning (100k, dedup, share, timestamps); oh-my-zsh sudo / colored-man-pages / extract; fzf, zoxide, direnv (+nix-direnv), eza, bat; ls-family aliases. command-not-found via the prebuilt nix-index DB (+comma). nh with $NH_FLAKE and a weekly user-GC timer. tmux: escape-time 10 (was the 500ms default -> laggy vim ESC), focus-events, base-index 1; plugins sensible / vim-tmux-navigator / yank / catppuccin (mocha statusline) / resurrect / continuum (restore on); renumber-windows and set-clipboard. Co-Authored-By: Claude Opus 4.8 (1M context) --- lyrathorpe/home/shell.nix | 122 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 117 insertions(+), 5 deletions(-) diff --git a/lyrathorpe/home/shell.nix b/lyrathorpe/home/shell.nix index f9ce679..259aacf 100644 --- a/lyrathorpe/home/shell.nix +++ b/lyrathorpe/home/shell.nix @@ -1,6 +1,17 @@ # Interactive shell: zsh + tmux. Wanted on every host. -{ lib, ... }: { + lib, + pkgs, + inputs, + ... +}: +{ + imports = [ + # Prebuilt nix-index database -> working command-not-found + # ("cmd not found -> which nix package provides it"), no manual indexing. + inputs.nix-index-database.homeModules.default + ]; + programs.zsh = { enable = true; enableCompletion = true; @@ -21,12 +32,24 @@ "^[OB" ]; }; - history.append = true; + history = { + append = true; # append, don't overwrite, on shell exit + size = 100000; # in-memory (HISTSIZE) + save = 100000; # on-disk (SAVEHIST) + ignoreDups = true; # drop consecutive duplicates + ignoreSpace = true; # leading-space commands stay out of history + expireDuplicatesFirst = true; + share = true; # live-share history across sessions + extended = true; # record timestamps + }; oh-my-zsh = { enable = true; plugins = [ "git" "man" + "sudo" # double-Esc prefixes the last command with sudo + "colored-man-pages" + "extract" # `extract ` for any format ]; theme = "robbyrussell"; }; @@ -37,9 +60,59 @@ export PS1="%M $PS1" fi ''; - envExtra = '' - alias cls=clear - ''; + shellAliases = { + # eza's zsh integration also defines these; set explicitly so the + # icons/git intent is obvious. + ls = "eza --icons --git"; + ll = "eza --icons --git -l"; + la = "eza --icons --git -la"; + lt = "eza --icons --git --tree"; + cls = "clear"; + }; + }; + + # Fuzzy finder: Ctrl-R fuzzy history, Ctrl-T files, Alt-C cd. + programs.fzf = { + enable = true; + enableZshIntegration = true; + }; + + # Frecency directory jumping: `z `. + programs.zoxide = { + enable = true; + enableZshIntegration = true; + }; + + # Per-project environments auto-loaded on cd, with the Nix dev-shell cache. + programs.direnv = { + enable = true; + nix-direnv.enable = true; + }; + + # Modern ls (drives the ls aliases above). + programs.eza = { + enable = true; + git = true; + icons = "auto"; # boolean form is deprecated + }; + + # Syntax-highlighting pager, used as `bat` (acts like cat when piped). + programs.bat.enable = true; + + # command-not-found backed by the prebuilt nix-index DB (module imported + # above). `comma` runs an uninstalled program once: `, cowsay hi`. + programs.nix-index.enable = true; + programs.nix-index-database.comma.enable = true; + + # Nicer nixos-rebuild/home-manager (diffs) + a weekly user-GC timer. + programs.nh = { + enable = true; + flake = "$HOME/code/nixfiles"; + clean = { + enable = true; + dates = "weekly"; + extraArgs = "--keep 5 --keep-since 3d"; + }; }; programs.tmux = { @@ -50,6 +123,33 @@ keyMode = "vi"; historyLimit = 500000; mouse = true; + escapeTime = 10; # was the 500ms default -> laggy ESC in vim + focusEvents = true; # let vim see focus changes (autoread) + baseIndex = 1; # sets both base-index and pane-base-index + + plugins = with pkgs.tmuxPlugins; [ + sensible + vim-tmux-navigator # Ctrl-h/j/k/l across vim splits and tmux panes + yank + { + # Catppuccin Mocha statusline (v2 API: flavour + window options must be + # set before the plugin loads, which home-manager does for plugin + # extraConfig; the status modules below go in the main extraConfig, + # which HM appends after all plugins). + plugin = catppuccin; + extraConfig = '' + set -g @catppuccin_flavor 'mocha' + set -g @catppuccin_window_status_style 'rounded' + ''; + } + resurrect # save/restore sessions + { + plugin = continuum; # auto-save + restore on tmux start (after resurrect) + extraConfig = '' + set -g @continuum-restore 'on' + ''; + } + ]; # `reverseSplit = true` already binds s -> vertical and v -> horizontal # split (the dotfiles' vim-style splits). extraConfig = '' @@ -75,6 +175,18 @@ set -as terminal-features ",foot*:title" set -as terminal-features ",foot*:ccolour" set -as terminal-features ",foot*:cstyle" + + # No home-manager options for these. + set -g renumber-windows on + set -g set-clipboard on + + # Catppuccin v2 statusline. Must run after the plugin has loaded; + # home-manager appends this extraConfig after the whole plugin list. + set -g status-left-length 100 + set -g status-right-length 100 + set -g status-left "" + set -g status-right "#{E:@catppuccin_status_application}" + set -ag status-right "#{E:@catppuccin_status_session}" ''; }; }