`__pycache__/` next to `tab_bar.py` is excluded in `.chezmoiignore.tmpl`.
## Theme and colors
Every config ends with:
```conf ~/.config/kitty/kitty.conf
include ~/.local/state/omarchy/current/theme/kitty.conf
```
Colors come from the active Omarchy theme; it is included last so it wins. `symlink_current-theme.conf` creates `~/.config/kitty/current-theme.conf` as a symlink to `themes/noctalia.conf`. Only the legacy `dot_config/herdr/kitty.conf` includes `current-theme.conf`; the main config does not. `themes/` holds `cyberdream`, `koda-dark`, `koda-light` and `noctalia` color files.
## kitty.conf
| Option | Value |
| --- | --- |
| `font_family` | `VictorMono Nerd Font`, then overridden in the `BEGIN_KITTY_FONTS` block to `family="VictorMono Nerd Font Mono"`; bold/italic `auto` |
| Tab bar | `powerline`, `angled`, aligned left, top edge, `tab_title_template "{custom}"` |
:::note
Transparency uses kitty's own alpha, so text stays opaque. This alpha is also what lets the compositor blur the window: Hyprland enables blur globally and opts out every window except terminal classes.
:::
The socket also exports `KITTY_LISTEN_ON` into each pane. nvim reads it to know kitty owns the panes and hands `ctrl+h/j/k/l` back to kitty at an edge.
| `geninclude day_session.py` | Creates today's (empty) session file and emits `startup_session <path>` whenever no running kitty owns today's session. Ownership is an `flock` on `$XDG_RUNTIME_DIR/kitty-day-<day>.kitty-session.lock`, held until that kitty exits, so closing kitty and launching it again always reopens the day, even if other kitties (or yesterday's) are still running. A second concurrent instance starts plain instead of duplicating today's tabs. |
| `watcher day_session.py` | About 1 s after a window opens, closes, resizes or splits, changes focus or finishes a command (catches `cd`), and every 30 s for output from long-running programs, rewrites the session this instance started with. Title changes are ignored so spinners don't trigger saves. Skips the save once the session has no windows, so closing kitty keeps the last good state. |
| `map ctrl+shift+d kitten day_session.py` | Picker over every archived day, newest first; opens the choice with `goto_session`. Past days are snapshots: tabs opened from them are not saved back. |
| `tab_bar_filter session:~ or session:^$` | Tab bar shows only the active day's tabs plus tabs outside any session. |
What a restored window gets back:
- **Scrollback**: each window carries a `day_scrollback=<key>` user var (kept by kitty's `launch --var`); its history is dumped as ANSI to `<key>.ansi`, minus the idle prompt, and dumps of closed windows are pruned. On restore, the shell runs `cat <key>.ansi` through kitty's shell-integration startup command, so it needs shell integration (fish here). A dump is only written after the shell has drawn a prompt, so a restored window can't overwrite its history before replaying it.
- **Running program**: saved with `--use-foreground-process` and re-run after the `cat`, so the shell is still there when it exits (`nvim`, `sleep 700`, dev servers). Commands still at shell init when saved (mise/direnv hooks) are ignored. A command is never replayed if any of its words is `rm`, `rmdir`, `mv`, `dd`, `shred`, `truncate`, `mkfs*`, `wipefs`, `fdisk`, `parted`, `sudo`, `doas`, `su`, `run0`, `pkexec`, `kill`, `pkill`, `killall`, `reboot`, `shutdown` or `poweroff` (`NO_REPLAY`).
- Programs launched as the window's own command (`ctrl+shift+e` nvim, `ctrl+shift+g` lazygit) were already restored by kitty; they have no shell, so no scrollback.
Only windows that belong to the session are saved: `new_tab_with_cwd` and the `--cwd=current` launch aliases join it; `new_os_window` (`ctrl+shift+space`) does not.
Launched by `super+t`. kitty stays a dumb terminal; tmux owns panes, windows and sessions. `listen_on unix:@kitty-tmux`, `tab_bar_style hidden`, `shell kitty-tmux` (a launcher script), and `clear_all_shortcuts yes`, so only the bindings below exist. Prefix byte `\x02` is `ctrl+b`; see [tmux](/terminal/tmux) for what each prefix key does.
Launched by `super+a`. Class `kitty-herdr`, `tab_bar_style hidden` (herdr draws its own sidebar and tab strip), `shell herdr` (launches or attaches the persistent session; closing the window detaches). Base appearance matches `kitty.conf`, without a `listen_on`. Keys mirror the [Ghostty](/terminal/ghostty) config so both drive herdr identically; an uppercase letter after `\x02` is the shift variant. See [herdr](/terminal/herdr).
Opens straight into the tmux session `main` on host `goliath` via `mosh goliath -- tmux new-session -A -s main`. `font_size 9.0`, `listen_on unix:@kitty-goliath`, `env MOSH_TITLE_NOPREFIX=1` (drops mosh's `[mosh] ` title prefix), `tab_bar_style hidden`.
:::warning
mosh bootstraps ssh with `-S none`, so non-interactive key auth to goliath must work. It needs mosh on both ends and UDP 60000–61000 open. mosh sets `TERM=xterm-256color`, so kitty-only capabilities such as undercurl are unavailable inside.
:::
| Key | Sends |
| --- | --- |
| `super+w` | `prefix x` |
| `super+t` | `prefix %` |
| `super+n` | `prefix "` |
| `super+enter`, `alt+n` | `prefix t` |
| `alt+h` / `alt+l` | `prefix H` / `prefix L` |
| `alt+q w e r t y u i o` | `prefix 1`–`9` (`alt+t` is bound twice; the later `prefix 5` wins) |
Kitten `ssh` config: for `hostname goliath`, `share_connections yes`.
## Kittens and Python
| File | Purpose |
| --- | --- |
| `tab_bar.py` | Provides `draw_title` for `{custom}` in the tab template. Title is `<index> <icon> <label>`: the label is the git repo root name of the tab's cwd (walks up for `.git`), or the file nvim is editing (parsed from nvim's title). Icon comes from the foreground process cmdline (editors, AI agents like claude/omp/opencode/codex, git tools, docker, herdr, tmux, yazi, btop, atuin, ssh, chezmoi, …) with a folder fallback. Labels are elided at 28 chars. No subprocesses or timers. |
| `pass_keys.py` | Bound to `ctrl+h/j/k/l`. If the window's foreground process matches `vim`, `nvim`, `fzf`, `tv`, `tmux` or `herdr`, the key is forwarded; otherwise kitty moves to the neighboring window. |
| `navigate_kitty.py` | No-UI kitten that calls `neighboring_window` with a direction argument; the counterpart nvim can invoke. Not mapped in `kitty.conf`. |
| `select_tab.py` | Full-screen fuzzy tab picker using `kitty @ ls` data; shows cwds zsh-style. Keys: Up/Down/PgUp/PgDn scroll, Enter selects, typing filters, `ctrl+c`/Esc quits. Not mapped in `kitty.conf`. |
| `switchtab.py` | Focuses the tab whose `vt` user var matches the argument, or launches one with that var and reorders tabs by `vt`. Not mapped. |
| `window_titler.py` | Watcher that appends `[<vt> <pty>]` to window titles. Not referenced in `kitty.conf`. |
Related: the [tmux](/terminal/tmux) `is_vim` check and herdr's `vim-herdr-navigation` plugin complete the `ctrl+h/j/k/l` chain. Niri window rules match the `kitty`, `kitty-tmux` and `kitty-herdr` app-ids ([Niri](/desktop/niri)).