# Interactive shell environment

Everything the shell, terminal multiplexer, git and ssh do beyond their defaults,
and where each is defined. All of it is managed declaratively through
home-manager — edit the listed file and rebuild, never the generated dotfiles.

Keyboard shortcuts have their own reference: [`KEYBINDINGS.md`](./KEYBINDINGS.md).

| Area                                  | Defined in                                            |
| ------------------------------------- | ----------------------------------------------------- |
| zsh, CLI tools, tmux, ssh, auto-tmux  | [`shell.nix`](./shell.nix)                            |
| git (+ delta, commitizen)             | [`git.nix`](./git.nix)                                |
| Neovim (nixvim) + LSP                 | [`editor.nix`](./editor.nix)                          |
| GUI apps, GTK/Firefox theming, cursor | [`desktop.nix`](./desktop.nix) (graphical hosts only) |

Shared by every host via [`default.nix`](./default.nix); the work box also layers
[`work.nix`](./work.nix) on top (work email, its own ssh config, extra packages,
and the C#/Helm language servers).

---

## 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**; 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                                                                                                             |

**Aliases:** `ls`/`ll`/`la`/`lt` → `eza` (icons + git), `cls` → `clear`. git aliases live in git.nix (below).

## CLI tools

| Tool                    | What it gives you                                                                                                                                                                                                                   |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fzf`                   | `Ctrl-R` fuzzy history, `Ctrl-T` file picker, `Alt-C` fuzzy cd (Catppuccin-themed)                                                                                                                                                  |
| `zoxide`                | `z <fragment>` jumps to frecent directories                                                                                                                                                                                         |
| `direnv` + `nix-direnv` | per-project environments auto-loaded on `cd` (cached Nix dev shells)                                                                                                                                                                |
| `eza`                   | modern `ls` (drives the ls aliases)                                                                                                                                                                                                 |
| `bat`                   | syntax-highlighting pager (Catppuccin Mocha theme); behaves like `cat` when piped; also the `MANPAGER`                                                                                                                              |
| `ripgrep` / `fd`        | fast search (`rg`) and find (`fd`); also back `fzf`                                                                                                                                                                                 |
| `jq` / `btop`           | JSON processor; resource monitor                                                                                                                                                                                                    |
| `gh` / `tea`            | GitHub and Gitea (`code.emmathe.dev`) CLIs; `gh` uses SSH                                                                                                                                                                           |
| `nix-index`             | `command-not-found`: an unknown command tells you which Nix package provides it (prebuilt DB, no manual indexing)                                                                                                                   |
| `comma` (`,`)           | run an uninstalled program once: `, cowsay hi`                                                                                                                                                                                      |
| `nh`                    | nicer `nixos-rebuild`/`home-manager` with diffs; `$NH_FLAKE` set to the repo. No scheduled GC (it could reap paths a running generation still references) — collect garbage manually with `nh clean all` / `nix-collect-garbage -d` |

**Theming:** `fzf`, `bat` and `git`'s `delta` pager are all Catppuccin Mocha,
driven from the shared `../catppuccin-mocha.nix` palette / the catppuccin/bat
theme.

**Env & defaults:** `xdg.enable` on; `PAGER`/`MANPAGER` (bat) set in `default.nix`
(the editor owns `$EDITOR`/`$VISUAL`); `xdg.mimeApps` maps web→Firefox,
directories→nemo (`desktop.nix`).

## tmux

**Auto-start:** opening any interactive terminal — foot, iTerm2, the WSL shell, the
Linux console — drops you straight into a tmux session named `main` (attach if it
exists, else create). Panes run a plain non-login zsh. It deliberately does **not**
fire for SSH sessions, VS Code's integrated terminal, already-inside-tmux, or
non-interactive shells. Escape hatch: `NO_TMUX=1 <terminal>` opens a bare shell.

| Setting                          | Value                                                                                                                                      |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Mode keys                        | vi                                                                                                                                         |
| Mouse                            | on                                                                                                                                         |
| Scrollback                       | 500000 lines                                                                                                                               |
| `escape-time`                    | 10ms (the 500ms default lagged vim's ESC)                                                                                                  |
| `focus-events`                   | on (vim autoread)                                                                                                                          |
| `base-index` / `pane-base-index` | 1                                                                                                                                          |
| Splits                           | `prefix s` vertical, `prefix v` horizontal (stock `%`/`"` unbound)                                                                         |
| Pane nav                         | `Alt`+arrows (no prefix)                                                                                                                   |
| Terminal                         | `default-terminal tmux-256color`; truecolor advertised per outer terminal (`foot*`, `xterm-256color`/iTerm2) via `terminal-features … RGB` |
| Clipboard                        | `set-clipboard on`; foot `terminal-features` advertise truecolor/sync/OSC52/title/cursor                                                   |

**Plugins:** `sensible`, `vim-tmux-navigator` (Ctrl-h/j/k/l across vim ↔ tmux),
`yank`, `catppuccin` (Mocha statusline), `resurrect` + `continuum`
(sessions auto-save and restore across reboots). The statusline draws Nerd-Font
glyphs — see Fonts.

## Fonts

**JetBrainsMono Nerd Font** is installed on every host (in `common-nixos.nix`,
because tmux runs everywhere; the Mac installs it to `/Library/Fonts` via the
Darwin config). foot uses it as its main font automatically. iTerm2's font is a
GUI setting — set it to _JetBrainsMono Nerd Font_ (Settings → Profiles → Text →
Font) so the tmux statusline glyphs render instead of `?`.

## Editor (Neovim)

`nvim` — aliased to `vi`/`vim`, and set as `$EDITOR`/`$VISUAL` — is configured
declaratively with **nixvim**, so the same plugins and config are baked in on
every host. Migrated from plain vim; the practical gain is a real LSP stack in
place of the old (inert) ALE.

| Feature       | Notes                                                                                  |
| ------------- | -------------------------------------------------------------------------------------- |
| Colorscheme   | Catppuccin Mocha (matches the terminal and the rest of the desktop)                    |
| File tree     | nvim-tree, toggled with `,,` (comma twice; was nerdtree)                               |
| Indent guides | indent-blankline, on by default (was vim-indent-guides)                                |
| Git           | fugitive (`:Git …`)                                                                    |
| Pane nav      | vim-tmux-navigator — `Ctrl`+`h/j/k/l` moves across vim splits and tmux panes           |
| Syntax        | tree-sitter (nix, lua, bash, markdown, groovy) — replaces `syntax enable`              |
| LSP           | nvim-cmp completion + servers `nil` (Nix), `lua_ls`, `pyright` (Python), `terraformls` |
| Indentation   | 2-wide hard tabs (`noexpandtab`, `tabstop`/`shiftwidth` = 2); line numbers on          |
| Filetypes     | `*Jenkinsfile` → groovy                                                                |

Leader is `Space`. LSP keymaps (`gd`, `gr`, `K`, `<leader>rn`, `<leader>ca`) and
the file-tree toggle are listed in
[`KEYBINDINGS.md`](./KEYBINDINGS.md#neovim). Add a universal language server by
enabling it under `programs.nixvim.plugins.lsp.servers` in `editor.nix`;
host-specific ones go in that host's module — the work box (`work.nix`) adds
`omnisharp` (C#) and `helm_ls` (Helm), kept off the personal machines.

## git

Pager is **delta**. **commitizen** is installed on every host; `cz` defaults to
Conventional Commits.

| Aliases                  |                                                                   |
| ------------------------ | ----------------------------------------------------------------- |
| `st` `co` `sw` `br` `ci` | status / checkout / switch / branch / commit                      |
| `last` `unstage`         | last commit / unstage                                             |
| `lg`                     | graph log, all branches                                           |
| `cz` `cc`                | `git cz <sub>` (e.g. `git cz c`) and `git cc` → commitizen prompt |

| Behaviour      |                                                                                                                                                                          |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Pulls          | rebase, with autostash + autosquash                                                                                                                                      |
| Fetch          | prune deleted remote branches                                                                                                                                            |
| Conflicts      | `zdiff3` (shows the common ancestor)                                                                                                                                     |
| Diffs          | histogram algorithm, colour-moved                                                                                                                                        |
| `rerere`       | remembers + replays conflict resolutions                                                                                                                                 |
| Commit editor  | full diff shown (`commit.verbose`)                                                                                                                                       |
| Misc           | branches sorted by date, `column.ui = auto`, `help.autocorrect = prompt`, `push.autoSetupRemote`                                                                         |
| Global ignores | `result`, `result-*`, `.direnv`, `*.swp`, `.DS_Store`                                                                                                                    |
| Signing        | SSH commit + tag signing (`mkDefault`, so a host without the key in its agent can disable it). Personal email `iam@emmathe.dev`; the work box overrides email + signing. |

## ssh

| Feature      | Notes                                                                                                                                                |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| ssh-agent    | runs on Linux (launchd on macOS); keys added on **first use** so the passphrase is typed once per login session — this also feeds git commit signing |
| macOS        | `UseKeychain` caches the passphrase in the login keychain (guarded by `IgnoreUnknown`, so a non-Apple `ssh` skips it instead of erroring)            |
| Gitea remote | `code.emmathe.dev` → `HostName 10.187.1.76` (DNS-override), `Port 30009`, user `git`, dedicated key, `identitiesOnly`                                |
| Defaults     | the module's deprecated default block is opted out; equivalents kept under `settings."*"`                                                            |

The **work box keeps its own `~/.ssh/config`** (home-manager's `programs.ssh` is
forced off there) but still runs the agent.

## Maintenance behaviours

- **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` /
  `nix-collect-garbage -d`) when no important session is running.

## Per-host differences

|                             | Personal Linux (sway) | macOS             | Work WSL (EDaaS)            |
| --------------------------- | --------------------- | ----------------- | --------------------------- |
| Auto-tmux                   | yes (foot/TTY)        | yes (iTerm2)      | yes (WSL shell)             |
| git email                   | `iam@emmathe.dev`     | `iam@emmathe.dev` | `…@citrix.com` (work)       |
| ssh config managed          | yes                   | yes               | no (keeps corporate config) |
| ssh-agent                   | yes                   | launchd           | yes (work module)           |
| GUI / theming (desktop.nix) | yes                   | no                | no                          |
