Split niri, hypr, fish into submodules; tmux, tmux-palette, television, yazi into externals

This commit is contained in:
Prad Nukala committed 2026-10-14 13:40:53 -04:00
1 parent ab29365a3d
commit 954e1e1ae0
216 files changed
+138 -9708

No files matched your search

+2 -2
View File
@@ -165,8 +165,8 @@ See [bash and zsh](/shell) for the rest of those files.
| `e.h` | not defined | `cd ~/.local/share/chezmoi/dot_config/hypr && yazi` |
| `e.k` | `yazi ~/.config/kitty` | `yazi ~/.local/share/chezmoi/dot_config/kitty` |
| `e.n` | `yazi ~/.config/niri` | `yazi ~/.local/share/chezmoi/dot_config/niri` |
| `e.y` | `yazi ~/.config/yazi` | `yazi ~/.local/share/chezmoi/yazi` |
| `e.t` | `nvim ~/.config/tmux/tmux.conf` | `nvim ~/.local/share/chezmoi/dot_config/tmux/tmux.conf` |
| `e.y` | `yazi ~/.config/yazi` | ✓ |
| `e.t` | `nvim ~/.config/tmux/tmux.conf` | ✓ |
| `cdd` | `cd ~/Developer && yazi` | not defined |
| `,,` | not defined | `cd ~/.local/share/chezmoi && yazi` |
| `..` | not defined | `cd ..` |
+42 -6
View File
@@ -31,14 +31,48 @@ Externals are content chezmoi fetches instead of storing in the repo. Every entr
| --- | --- | --- |
| `~/.config/nvim` | [prdlk/nvim](https://github.com/prdlk/nvim) | Neovim config, kept in its own repo |
| `~/.config/bat/syntaxes/sublime-purescript-syntax` | [tellnobody1/sublime-purescript-syntax](https://github.com/tellnobody1/sublime-purescript-syntax) | PureScript syntax for bat, compiled into bat's cache by the [bat cache scripts](/chezmoi/scripts#build-bat-cache) |
| `~/.config/tmux/plugins/tpm` | [tmux-plugins/tpm](https://github.com/tmux-plugins/tpm) | tmux plugin manager, run from the bottom of `tmux.conf` ([tmux](/terminal/tmux)) |
| `~/.config/tmux/plugins/tpm` | [tmux-plugins/tpm](https://github.com/tmux-plugins/tpm) | tmux plugin manager, run from the bottom of `tmux.conf` ([tmux](/terminal/tmux)). Cloned inside the tmux checkout, whose `.gitignore` excludes `plugins/` |
### No refreshPeriod
No entry sets `refreshPeriod`, so it stays at chezmoi's default of never. chezmoi clones each repo on a fresh machine and otherwise leaves it alone: `chezmoi apply` and `chezmoi update` do not pull. The local nvim checkout always wins over the remote, so in-progress Neovim edits and unpushed commits are never disturbed by an apply.
No entry in `.chezmoiexternal.toml` sets `refreshPeriod`, so it stays at chezmoi's default of never. chezmoi clones each repo on a fresh machine and otherwise leaves it alone: `chezmoi apply` and `chezmoi update` do not pull. The local nvim checkout always wins over the remote, so in-progress Neovim edits and unpushed commits are never disturbed by an apply.
To update explicitly, run `chezmoi apply --refresh-externals` (`-R`), which pulls with `git pull --ff-only`. `--ff-only` makes the pull fail instead of creating a merge commit when the local checkout has diverged.
## .chezmoiexternals/ [#app-externals]
Per-app config repos, one file each in `.chezmoiexternals/<app>.toml`. Each is a `git-repo` external with `refreshPeriod = "168h"` and `pull.args = ["--ff-only"]`, so `chezmoi apply` fast-forwards them at most once a week. The repos hold plain config files (no chezmoi prefixes) and are not part of `chezmoi managed` contents.
```toml .chezmoiexternals/tmux.toml
[".config/tmux"]
type = "git-repo"
url = "https://github.com/prdlk/tmux.git"
refreshPeriod = "168h"
[".config/tmux".pull]
args = ["--ff-only"]
```
| File | Target | Repo |
| --- | --- | --- |
| `tmux.toml` | `~/.config/tmux` | [prdlk/tmux](https://github.com/prdlk/tmux) |
| `tmux-palette.toml` | `~/.config/tmux-palette` | [prdlk/tmux-palette](https://github.com/prdlk/tmux-palette) |
| `television.toml` | `~/.config/television` | [prdlk/television](https://github.com/prdlk/television) |
| `yazi.toml` | `~/.config/yazi` | [prdlk/yazi](https://github.com/prdlk/yazi) |
Edit these in place under `~/.config/<app>`, then commit and push from that checkout.
## Submodules [#submodules]
Three source directories are git submodules, listed in `.gitmodules`. They keep chezmoi source naming and are applied in symlink mode like the rest of the tree. `chezmoi init` clones them.
| Source | Target | Repo |
| --- | --- | --- |
| `dot_config/niri` | `~/.config/niri` | [prdlk/niri](https://github.com/prdlk/niri) |
| `dot_config/hypr` | `~/.config/hypr` | [prdlk/hypr](https://github.com/prdlk/hypr) |
| `dot_config/fish` | `~/.config/fish` | [prdlk/fish](https://github.com/prdlk/fish) |
Edit them inside the submodule in the chezmoi source, commit there, then commit the updated submodule pointer in the root repo.
## .chezmoiignore.tmpl [#chezmoiignore]
Patterns match target paths (relative to `$HOME`). Matching entries are neither written nor removed. The file is a template, so the desktop block appears only on machines where it applies. Source entries that start with `.` (`.github/`, `.claude/`, `.crush/`, `.gitignore`) are ignored by chezmoi without needing a rule.
@@ -69,11 +103,12 @@ Files at the source root that would otherwise land in `$HOME` as `~/README.md`,
| `.config/lazygit/.omc/**` | Tool state written inside the lazygit config dir |
| `.config/tmux/plugins/**`, except `!.config/tmux/plugins/tpm` | Plugins tpm installs with `prefix I`; tpm itself is the external above |
| `.config/fish/fish_variables` | fish universal variables, rewritten by fish at runtime |
| `.config/fish/conf.d/secrets.fish` | Plaintext credentials. Local-only, never in git (the fish repo's `.gitignore` also lists it) |
| `.config/nvim/lazy-lock.json` | lazy.nvim lockfile inside the nvim external |
| `.config/nvim/.git`, `.config/nvim/.git/**` | The external's git metadata |
| `.config/nvim/.omc/**`, `.config/nvim/.crush/**`, `.config/nvim/.understand-anything/**` | Agent tool state inside the nvim checkout |
`.gitignore` covers the source side of the same problem: `dot_config/lazygit/dot_omc`, `dot_config/tmux/plugins`, `/yazi/plugins/*` (except the vendored `bunny.yazi`), and `__pycache__/` never get committed even though symlink mode lets tools write into the source tree.
`.gitignore` covers the source side of the same problem: `dot_config/lazygit/dot_omc` and `__pycache__/` never get committed even though symlink mode lets tools write into the source tree.
### mise
@@ -90,6 +125,8 @@ mise tool versions stay local to each machine and are not managed.
{{ if or (ne .chezmoi.os "linux") (and (ne .role "desktop") (ne .role "laptop")) }}
.config/niri
.config/niri/**
.config/hypr
.config/hypr/**
.config/noctalia
.config/noctalia/**
.config/niri-dynamic-workspaces
@@ -103,11 +140,10 @@ mise tool versions stay local to each machine and are not managed.
.local/bin/niri-launch
.config/fish/auto-Niri.fish
.local/bin/cp-appid
.config/tmux/niri-title.sh
{{ end }}
```
The block is emitted, and these paths skipped, unless the OS is `linux` and the role is `desktop` or `laptop`. `mac` and `server` machines, and any non-Linux machine regardless of role, never receive the niri compositor config (`dot_config/niri/`), fontconfig (`dot_config/fontconfig/fonts.conf`), default-app associations (`dot_config/mimeapps.list`), the fish auto-start hook (`dot_config/fish/auto-Niri.fish`), the tmux window-title helper, the systemd user units (`dot_config/systemd/user/kitty-day-save.service`), or the `niri-launch`, `cp-appid` and `kitty-day-save` scripts. The `noctalia` and `niri-dynamic-workspaces` rules match nothing in the current source tree; they only take effect if those configs are added later.
The block is emitted, and these paths skipped, unless the OS is `linux` and the role is `desktop` or `laptop`. `mac` and `server` machines, and any non-Linux machine regardless of role, never receive the niri and Hyprland configs (`dot_config/niri/`, `dot_config/hypr/`), fontconfig (`dot_config/fontconfig/fonts.conf`), default-app associations (`dot_config/mimeapps.list`), the fish auto-start hook (`dot_config/fish/auto-Niri.fish`), the systemd user units (`dot_config/systemd/user/kitty-day-save.service`), or the `niri-launch`, `cp-appid` and `kitty-day-save` scripts. The `noctalia` and `niri-dynamic-workspaces` rules match nothing in the current source tree; they only take effect if those configs are added later.
| Machine | Desktop layer |
| --- | --- |
@@ -115,7 +151,7 @@ The block is emitted, and these paths skipped, unless the OS is `linux` and the
| Linux, `server` or `mac` | Ignored |
| macOS or other OS, any role | Ignored |
See [Desktop](/desktop/niri) for what the layer contains. Gaps in the gate: the block lists `niri-launch` but not its siblings (`niri-launch-ai`, `niri-launch-browser`, `niri-launch-terminal`, `niri-launch-webapp`), and the Hyprland and waybar configs (`dot_config/hypr/`, `dot_config/waybar/`) are not gated at all, so those apply on every role. `dot_config/niri/scripts/` is covered by `.config/niri/**`.
See [Desktop](/desktop/niri) for what the layer contains. Gaps in the gate: the block lists `niri-launch` but not its siblings (`niri-launch-ai`, `niri-launch-browser`, `niri-launch-terminal`, `niri-launch-webapp`), and the waybar config (`dot_config/waybar/`) is not gated at all, so it applies on every role. `dot_config/niri/scripts/` is covered by `.config/niri/**`.
### Secrets in runtime state
+13 -8
View File
@@ -27,7 +27,13 @@ The repo is a [chezmoi](https://chezmoi.io) source directory. It lives at `~/.lo
- packages.yaml
- skills.yaml
- .chezmoiexternal.toml
- .chezmoiexternals/
- television.toml
- tmux.toml
- tmux-palette.toml
- yazi.toml
- .chezmoiignore.tmpl
- .gitmodules
- .chezmoiscripts/
- run_onchange_before_10-packages.sh.tmpl
- run_onchange_after_20-gh-extensions.sh.tmpl
@@ -59,15 +65,12 @@ The repo is a [chezmoi](https://chezmoi.io) source directory. It lives at `~/.lo
- niri/
- shell/
- starship.toml
- tmux/
- topgrade.toml
- waybar/
- symlink_yazi.tmpl
- zsh/
- dot_local/
- bin/
- dot_leetcode/
- yazi/
- docs/
- public/
- blume.config.ts
@@ -81,11 +84,13 @@ The repo is a [chezmoi](https://chezmoi.io) source directory. It lives at `~/.lo
| --- | --- | --- |
| `.chezmoi.toml.tmpl` | `~/.config/chezmoi/chezmoi.toml` | Config template rendered by `chezmoi init`. See [Config and roles](/chezmoi/config). |
| `.chezmoidata/` | — | YAML merged into template data (`.packages`, `.aliases`, `.skills`). See [Packages and aliases](/chezmoi/data) and [Skills](/ai/skills). |
| `.chezmoiexternal.toml` | — | Git repos cloned into `$HOME` (nvim config, a bat syntax). |
| `.chezmoiexternal.toml` | — | Git repos cloned into `$HOME` (nvim config, a bat syntax, tpm). |
| `.chezmoiexternals/` | — | One `git-repo` external per app: tmux, tmux-palette, television, yazi. Plain config repos cloned into `~/.config/<app>`. See [Externals and ignore rules](/chezmoi/externals-and-ignore#app-externals). |
| `.gitmodules` | — | `dot_config/niri`, `dot_config/hypr`, `dot_config/fish` are git submodules. See [Submodules](/chezmoi/externals-and-ignore#submodules). |
| `.chezmoiignore.tmpl` | — | Target paths chezmoi skips; gates the Linux desktop layer by role. |
| `.chezmoiscripts/`, root `run_*` | — | Install and housekeeping scripts. See [Apply scripts](/chezmoi/scripts). |
| `dot_config/` | `~/.config/` | Per-tool config. Documented under [Shell](/shell), [Terminal](/terminal), [Tools](/tools), [Desktop](/desktop). |
| `dot_local/bin/` | `~/.local/bin/` | 34 standalone scripts shared by every shell. |
| `dot_local/bin/` | `~/.local/bin/` | 39 standalone scripts shared by every shell. |
| `dot_leetcode/` | `~/.leetcode/` | leetcode CLI workspace state. |
| `docs/`, `public/`, `blume.config.ts`, `package.json`, `bun.lock`, `README.md` | — | This docs site and the repo README. Listed in `.chezmoiignore.tmpl`, never applied. |
@@ -99,10 +104,10 @@ chezmoi encodes target names and attributes in source file names. These are the
| --- | --- | --- |
| `dot_` | Target name starts with `.` | `dot_config` → `~/.config`, `dot_zshrc` → `~/.zshrc` |
| `private_` | Target has group/world permissions cleared (`0600`/`0700`) | `dot_config/atuin/private_config.toml`, `dot_config/gh/private_config.yml`, `dot_config/hunk/private_state.json` |
| `executable_` | Target gets the executable bit | 40 files: every script in `dot_local/bin/`, `dot_config/niri/scripts/`, `dot_config/tmux/executable_niri-title.sh` |
| `executable_` | Target gets the executable bit | 44 files: every script in `dot_local/bin/` (including `executable_tmux-niri-title`) and `dot_config/niri/scripts/` |
| `exact_` | Directory is exact: entries in the target that are not in the source are deleted | `dot_config/niri/exact_config.d/` (numbered `10-…kdl` through `95-…kdl` fragments) |
| `empty_` | File is kept even when empty | `dot_config/herdr/empty_dot_plugins.lock` |
| `symlink_` | Target is a symlink; file content is the link destination | `dot_config/kitty/symlink_current-theme.conf` (→ `themes/cyberdream.conf`), `dot_config/symlink_television.tmpl`, `dot_config/symlink_yazi.tmpl` |
| `symlink_` | Target is a symlink; file content is the link destination | `dot_config/kitty/symlink_current-theme.conf` (→ `themes/cyberdream.conf`) |
| `.tmpl` | Rendered with Go templates and chezmoi data | `dot_gitconfig.tmpl`, `dot_config/shell/aliases.sh.tmpl`, all scripts, the config and ignore files |
| `run_once_` / `run_onchange_` + `before_` / `after_` | Script, with run frequency and phase | See [Apply scripts](/chezmoi/scripts) |
@@ -120,7 +125,7 @@ What that means in practice:
- Tools that rewrite their own config write through the symlink into the repo. The runtime state that would otherwise pollute the source (plugin dirs, lock files, `fish_variables`, `__pycache__`) is excluded in `.chezmoiignore.tmpl` and `.gitignore`; see [Externals and ignore rules](/chezmoi/externals-and-ignore).
:::note
Several fish aliases (`e.f`, `e.h`, `e.k`, `e.n`, `e.y`, `e.t`, `,,`) open the chezmoi source paths directly. Symlink mode makes that equivalent to editing the live config.
Several fish aliases (`e.f`, `e.h`, `e.k`, `e.n`, `,,`) open the chezmoi source paths directly. Symlink mode makes that equivalent to editing the live config. `e.y` and `e.t` open the yazi and tmux external checkouts in `~/.config`.
:::
## Daily workflow
+2 -2
View File
@@ -28,7 +28,7 @@ Six scripts run during `chezmoi apply`. Four live in `.chezmoiscripts/`, a direc
| `.chezmoiscripts/run_once_after_30-user-services.sh.tmpl` | after | once | Runs once per distinct rendered content |
| `.chezmoiscripts/run_onchange_after_40-post.sh.tmpl` | after | onchange | Only edits to the script itself (or an OS change) |
| `run_onchange_after_build-bat-cache.sh.tmpl` | after | onchange | sha256 of `dot_config/bat/themes/cyberdream.tmTheme` and `dot_config/bat/config` |
| `run_onchange_after_install-yazi-plugins.sh.tmpl` | after | onchange | sha256 of `yazi/package.toml` |
| `run_onchange_after_install-yazi-plugins.sh.tmpl` | after | onchange | sha256 of `~/.config/yazi/package.toml` (empty when the file is absent) |
`run_onchange_` scripts re-run whenever their rendered content differs from the last successful run. The hash triggers work by writing a checksum of another file into a comment, so editing that file changes the script's content:
@@ -115,4 +115,4 @@ Each step ignores failures (`|| true`). tpm is cloned by [`.chezmoiexternal.toml
## install-yazi-plugins [#install-yazi-plugins]
`run_onchange_after_install-yazi-plugins.sh.tmpl` reinstalls yazi plugins whenever `yazi/package.toml` changes. It exits quietly if `ya` is missing or `${XDG_CONFIG_HOME:-$HOME/.config}/yazi/package.toml` does not exist, and otherwise runs `ya pkg install`. If that fails, it deletes ya's clone cache (`${XDG_CACHE_HOME:-$HOME/.cache}/yazi/packages`), since clones made by an older ya can break a newer one, and retries once. `~/.config/yazi` links to the source dir, so the plugins land in the repo's `yazi/plugins/`, which `.gitignore` excludes apart from the vendored `bunny.yazi`. The plugin list is on the [yazi page](/tools/yazi).
`run_onchange_after_install-yazi-plugins.sh.tmpl` reinstalls yazi plugins whenever `~/.config/yazi/package.toml` changes (the template hashes it via `joinPath .chezmoi.homeDir`, guarded with `stat`). It exits quietly if `ya` is missing or `${XDG_CONFIG_HOME:-$HOME/.config}/yazi/package.toml` does not exist, and otherwise runs `ya pkg install`. If that fails, it deletes ya's clone cache (`${XDG_CACHE_HOME:-$HOME/.cache}/yazi/packages`), since clones made by an older ya can break a newer one, and retries once. `~/.config/yazi` is the [prdlk/yazi](https://github.com/prdlk/yazi) external checkout, so the plugins land in its `plugins/`, which that repo's `.gitignore` excludes apart from the vendored `bunny.yazi`. The plugin list is on the [yazi page](/tools/yazi).
+3 -1
View File
@@ -6,7 +6,9 @@ description: Hyprland Lua config layered on Omarchy — bindings ported from nir
[Hyprland](https://hypr.land) is a dynamic tiling Wayland compositor. This config uses Hyprland's Lua configuration and sits on top of [Omarchy](https://omarchy.org), which provides the defaults, theme, menus, and `omarchy-*` commands. The files here only override. Most bindings are ported from the [niri config](/desktop/niri) so the same keys do the same jobs.
:::note
`~/.config/hypr` and the `omarchy-*` scripts are **not** listed in `.chezmoiignore.tmpl`. chezmoi applies them on every role and OS, including `mac` and `server`. They only take effect where Hyprland and Omarchy are installed.
Linux `desktop` and `laptop` roles only. `.chezmoiignore.tmpl` skips `~/.config/hypr/**` on other roles. The `omarchy-*` scripts are **not** listed there, so chezmoi applies them on every role and OS; they only take effect where Omarchy is installed.
`dot_config/hypr` is a git submodule ([prdlk/hypr](https://github.com/prdlk/hypr)). Edit inside the submodule, commit there, then commit the updated pointer in the chezmoi repo.
:::
## Files
+2 -2
View File
@@ -6,9 +6,9 @@ sidebar:
---
:::note[Role gating]
`.chezmoiignore.tmpl` skips the niri layer unless the machine runs Linux **and** its role is `desktop` or `laptop`. The gated targets are `~/.config/niri`, `~/.config/noctalia`, `~/.config/niri-dynamic-workspaces`, `~/.config/fontconfig`, `~/.config/mimeapps.list`, `~/.config/systemd`, `~/.local/bin/kitty-day-save`, `~/.local/bin/niri-launch`, `~/.local/bin/cp-appid`, `~/.config/fish/auto-Niri.fish`, and `~/.config/tmux/niri-title.sh`. On `mac` and `server` roles these are not applied.
`.chezmoiignore.tmpl` skips the Linux desktop layer unless the machine runs Linux **and** its role is `desktop` or `laptop`. The gated targets are `~/.config/niri`, `~/.config/hypr`, `~/.config/noctalia`, `~/.config/niri-dynamic-workspaces`, `~/.config/fontconfig`, `~/.config/mimeapps.list`, `~/.config/systemd`, `~/.local/bin/kitty-day-save`, `~/.local/bin/niri-launch`, `~/.local/bin/cp-appid`, and `~/.config/fish/auto-Niri.fish`. On `mac` and `server` roles these are not applied.
`~/.config/hypr`, `~/.config/waybar`, the `omarchy-*` scripts, and the `niri-launch-ai` / `-browser` / `-terminal` / `-webapp` wrappers are **not** listed there, so chezmoi applies them on every role and OS. Only the exact path `.local/bin/niri-launch` is ignored, not the wrappers that call it.
`~/.config/waybar`, the `omarchy-*` scripts, the `niri-launch-ai` / `-browser` / `-terminal` / `-webapp` wrappers, and `~/.local/bin/tmux-niri-title` are **not** listed there, so chezmoi applies them on every role and OS. Only the exact path `.local/bin/niri-launch` is ignored, not the wrappers that call it.
:::
Two Wayland compositors are configured side by side. niri is the original setup, paired with the Noctalia shell. Hyprland runs on top of [Omarchy](https://omarchy.org), and its bindings are ported from the niri config: the same keys launch the same apps where both compositors support it. Waybar is the Hyprland bar. Noctalia replaces it under niri.
+2
View File
@@ -7,6 +7,8 @@ description: Scrollable-tiling Wayland compositor config — input, layout, wind
:::note
Linux `desktop` and `laptop` roles only. `.chezmoiignore.tmpl` skips `~/.config/niri/**`, `~/.local/bin/niri-launch`, and `~/.local/bin/cp-appid` on other roles. The `niri-launch-*` wrappers are not in the ignore list and are applied everywhere.
`dot_config/niri` is a git submodule ([prdlk/niri](https://github.com/prdlk/niri)). Edit inside the submodule, commit there, then commit the updated pointer in the chezmoi repo.
:::
## Files
+3 -3
View File
@@ -41,11 +41,11 @@ A ✓ means the alias exists in that shell with the command shown. Where fish us
| `e.k` | `yazi ~/.config/kitty` | `yazi ~/.local/share/chezmoi/dot_config/kitty` |
| `e.n` | `yazi ~/.config/niri` | `yazi ~/.local/share/chezmoi/dot_config/niri` |
| `e.v` | `yazi ~/.config/nvim/lua` | ✓ |
| `e.y` | `yazi ~/.config/yazi` | `yazi ~/.local/share/chezmoi/yazi` |
| `e.t` | `nvim ~/.config/tmux/tmux.conf` | `nvim ~/.local/share/chezmoi/dot_config/tmux/tmux.conf` |
| `e.y` | `yazi ~/.config/yazi` | ✓ |
| `e.t` | `nvim ~/.config/tmux/tmux.conf` | ✓ |
| `hx` | `helix` | ✓ (listed under Tools in fish) |
The fish editor aliases open the chezmoi source tree directly. In symlink mode, `~/.config/<tool>` files are symlinks into that tree, so both versions edit the same files.
The fish `e.f`, `e.h`, `e.k`, and `e.n` aliases open the chezmoi source tree directly. In symlink mode, `~/.config/<tool>` files are symlinks into that tree, so both versions edit the same files. yazi and tmux are external checkouts in `~/.config`, so `e.y` and `e.t` open them there.
### Quick directory jumps
+2 -2
View File
@@ -15,7 +15,7 @@ fish is the primary interactive shell. The config is split into autoloaded files
| `dot_config/fish/fish_plugins` | `~/.config/fish/fish_plugins` |
| `dot_config/fish/auto-Niri.fish` | `~/.config/fish/auto-Niri.fish` (Linux `desktop`/`laptop` only) |
None of these files are templates. chezmoi runs in symlink mode, so each target is a symlink back into the source tree and edits to `~/.config/fish/...` land in the repo directly. `~/.config/fish/fish_variables` (universal variables, including the selected theme) is listed in `.chezmoiignore.tmpl` and stays local to each machine.
`dot_config/fish` is a git submodule ([prdlk/fish](https://github.com/prdlk/fish)). Edit inside the submodule, commit there, then commit the updated pointer in the chezmoi repo. None of these files are templates. chezmoi runs in symlink mode, so each target is a symlink back into the source tree and edits to `~/.config/fish/...` land in the submodule directly. `~/.config/fish/fish_variables` (universal variables, including the selected theme) is listed in `.chezmoiignore.tmpl` and stays local to each machine. `~/.config/fish/conf.d/secrets.fish` is local-only: it is listed in `.chezmoiignore.tmpl` and in the fish repo's `.gitignore`, and never committed.
## Installation
@@ -218,7 +218,7 @@ The pickers run `tv --inline`, which opens on the line below the prompt and leav
`omp-session` (<kbd>ctrl-a</kbd>) does its own `\033[A` when its `omp-sessions` picker is cancelled, so the binding only repaints.
zsh and bash bind <kbd>ctrl-o</kbd>, <kbd>ctrl-e</kbd>, <kbd>ctrl-p</kbd>, <kbd>down</kbd>, and <kbd>ctrl-t</kbd> the same way ([bash and zsh](/shell/bash-zsh)). Inside television, <kbd>ctrl-e</kbd> runs the channel's `edit` action and <kbd>ctrl-h</kbd> its `goto_parent_dir` action (`television/config.toml`). The config and cables are on the [television](/tools/television) page.
zsh and bash bind <kbd>ctrl-o</kbd>, <kbd>ctrl-e</kbd>, <kbd>ctrl-p</kbd>, <kbd>down</kbd>, and <kbd>ctrl-t</kbd> the same way ([bash and zsh](/shell/bash-zsh)). Inside television, <kbd>ctrl-e</kbd> runs the channel's `edit` action and <kbd>ctrl-h</kbd> its `goto_parent_dir` action (`~/.config/television/config.toml`). The config and cables are on the [television](/tools/television) page.
:::note
Under kitty, <kbd>ctrl-g</kbd> (lazygit overlay), <kbd>ctrl-y</kbd> (yazi split), and <kbd>ctrl-h/j/k/l</kbd> (split navigation) are mapped in `kitty.conf` and never reach fish. The fish binds for those keys only apply in other terminals. See [kitty](/terminal/kitty).
+1 -1
View File
@@ -11,7 +11,7 @@ kitty is the primary terminal. It runs in three modes: plain kitty (kitty owns s
| --- | --- | --- |
| [kitty](/terminal/kitty) | `dot_config/kitty/` | Main config, host configs (tmux, herdr, goliath), kittens, custom tab bar |
| [Ghostty](/terminal/ghostty) | `dot_config/ghostty/` | tmux-only terminal: ctrl+shift chords → tmux, themes |
| [tmux](/terminal/tmux) | `dot_config/tmux/` | Prefix, bindings, kitty-style tabs with Nerd Font icons, resurrect/continuum persistence, Niri titles |
| [tmux](/terminal/tmux) | external repo via `.chezmoiexternals/tmux.toml` | Prefix, bindings, kitty-style tabs with Nerd Font icons, resurrect/continuum persistence, Niri titles |
| [herdr](/terminal/herdr) | `dot_config/herdr/`, `dot_config/herdr-nvim/` | Agent-aware multiplexer: keys, theme, plugins, Claude hook |
## Shared conventions
+5 -5
View File
@@ -7,11 +7,11 @@ Terminal multiplexer. [Ghostty](/terminal/ghostty) runs nothing but tmux, and Gh
| | |
| --- | --- |
| Source | `dot_config/tmux/tmux.conf`, `dot_config/tmux/tmux-nerd-font-window-name.yml`, `dot_config/tmux/executable_tab-label.sh`, `dot_config/tmux/executable_niri-title.sh` |
| Source | [prdlk/tmux](https://github.com/prdlk/tmux) via `.chezmoiexternals/tmux.toml`: `tmux.conf`, `tmux-nerd-font-window-name.yml`, `tab-label.sh` |
| Target | `~/.config/tmux/` |
| Install | `tmux` in `.chezmoidata/packages.yaml` (pacman, brew) |
tpm is a `git-repo` external in `.chezmoiexternal.toml`, cloned to `~/.config/tmux/plugins/tpm` when missing. `tmux.conf` ends with `run '~/.config/tmux/plugins/tpm/tpm'`. Plugins installed by tpm (`prefix I`) land next to it and are ignored by chezmoi. `dot_config/tmux-palette/` (→ `~/.config/tmux-palette/`) holds the [palette](#command-palette) config.
`~/.config/tmux` is a `git-repo` external checkout, not chezmoi-managed contents; edit it in place and commit and push from there. tpm is a separate `git-repo` external in `.chezmoiexternal.toml`, cloned to `~/.config/tmux/plugins/tpm` inside that checkout when missing. `tmux.conf` ends with `run '~/.config/tmux/plugins/tpm/tpm'`. Plugins installed by tpm (`prefix I`) land next to it; the tmux repo's `.gitignore` excludes `plugins/` and chezmoi ignores them. [prdlk/tmux-palette](https://github.com/prdlk/tmux-palette) (`.chezmoiexternals/tmux-palette.toml`, → `~/.config/tmux-palette/`) holds the [palette](#command-palette) config.
## Options
@@ -92,7 +92,7 @@ Labels longer than 27 characters end in `…`. The icon comes from tmux-nerd-fon
### Command palette
`ctrl+space` opens tmux-palette, a fuzzy command list in a popup. Its user config lives in `~/.config/tmux-palette/` (source `dot_config/tmux-palette/`):
`ctrl+space` opens tmux-palette, a fuzzy command list in a popup. Its user config lives in `~/.config/tmux-palette/` (the [prdlk/tmux-palette](https://github.com/prdlk/tmux-palette) external):
| File | Contents |
| --- | --- |
@@ -111,9 +111,9 @@ resurrect saves sessions, windows, panes, cwds, pane contents, and a default set
`show-name: false`, because `automatic-rename-format` supplies the label. The icon sits on the left, with a fallback icon and a blank multi-pane icon. Icons are defined for `mprocs`, `mm`, `macmon`, `make`, `zsh`, `nvim`, `devbox`, `psql`, `yazi`, `lazygit`, `gh`, `tv`, `docker`, `bun`, `node`, `npm`, `pnpm`, `go`, `bunx`, `claude`, `omp`, and `gitframe`. The plugin parses the YAML with awk and does not interpret `\U` escapes, so the glyphs are literal characters.
## niri-title.sh
## tmux-niri-title
Installed only on Linux `desktop`/`laptop` roles (gated in `.chezmoiignore.tmpl`). Given the pane command, path, tty, and title, it prints a context segment for the window title read by [Niri](/desktop/niri). It picks the first match:
`dot_local/bin/executable_tmux-niri-title` → `~/.local/bin/tmux-niri-title`. POSIX sh, installed on every OS and role. Given the pane command, path, tty, and title, it prints a context segment for a window title such as the one read by [Niri](/desktop/niri). It picks the first match:
1. `ssh`/`mosh-client`/`autossh`/`et`: the remote target.
2. `nvim`/`vim`: the pane title (current file).
+2 -2
View File
@@ -16,13 +16,13 @@ Packages come from `.chezmoidata/packages.yaml` and are installed by `run_onchan
| [Git](/tools/git) | git, delta, diffnav, git-split-diffs | `dot_gitconfig.tmpl` | delta colors hand-tuned (dark) |
| [GitHub CLI](/tools/github-cli) | gh, gh extensions, gh-dash | `dot_config/gh/`, `dot_config/gh-dash/` | gh-dash defaults |
| [Neovim](/tools/neovim) | nvim (AstroNvim) | external repo via `.chezmoiexternal.toml` | managed in the nvim repo |
| [Yazi](/tools/yazi) | yazi file manager | `yazi/` (symlinked) | cyberdream flavor (ii-auto flavor shipped) |
| [Yazi](/tools/yazi) | yazi file manager | external repo via `.chezmoiexternals/yazi.toml` | cyberdream flavor (ii-auto flavor shipped) |
| [Lazygit](/tools/lazygit) | lazygit | `dot_config/lazygit/` | cyberdream colors (ii theme file shipped) |
| [Lazydocker](/tools/lazydocker) | lazydocker | `dot_config/lazydocker/config.yml` | cyberdream colors |
| [bat](/tools/bat) | bat | `dot_config/bat/` | cyberdream tmTheme |
| [Topgrade](/tools/topgrade) | topgrade | `dot_config/topgrade.toml` | n/a |
| [Hunk](/tools/hunk) | hunk diff viewer | `dot_config/hunk/config.toml` | `auto` |
| [television](/tools/television) | tv fuzzy picker, custom cables | `television/` (symlinked) | `cyberdream-transparent` |
| [television](/tools/television) | tv fuzzy picker, custom cables | external repo via `.chezmoiexternals/television.toml` | `cyberdream-transparent` |
| [LeetCode](/tools/leetcode) | leetcode CLI, `lc-elir` | `dot_leetcode/` | n/a |
<CardGroup cols={2}>
+2 -4
View File
@@ -7,13 +7,11 @@ description: tv config symlinked from the repo, a transparent cyberdream theme,
| | |
| --- | --- |
| Source | `television/config.toml`, `television/cable/*.toml`, `television/themes/cyberdream-transparent.toml` |
| Link | `dot_config/symlink_television.tmpl` → `~/.config/television` is a symlink to `{{ .chezmoi.sourceDir }}/television` |
| Source | [prdlk/television](https://github.com/prdlk/television) via `.chezmoiexternals/television.toml`: `config.toml`, `cable/*.toml`, `themes/cyberdream-transparent.toml` |
| Target | `~/.config/television/` |
| Ignore | `.chezmoiignore.tmpl` lists `television`, so it is not copied to `~/television` |
| Install | Not listed in `.chezmoidata/packages.yaml`; install separately |
The whole directory is a symlink into the source tree, so edits apply without `chezmoi apply`. `cable/` holds tv's stock cables plus the repo's own and overridden ones.
`~/.config/television` is a `git-repo` checkout (pulled `--ff-only` every 168h), so edits apply immediately; commit and push them from there. `cable/` holds tv's stock cables plus the repo's own and overridden ones.
## config.toml
+9 -10
View File
@@ -7,10 +7,8 @@ description: Yazi file manager config — layout, openers, bat previews, keymap,
| | |
| --- | --- |
| Source | `yazi/` |
| Link | `dot_config/symlink_yazi.tmpl` → `~/.config/yazi` is a symlink to `{{ .chezmoi.sourceDir }}/yazi` |
| Target | `~/.config/yazi/` |
| Ignore | `.chezmoiignore.tmpl` lists `yazi`, so it is not copied to `~/yazi` |
| Source | [prdlk/yazi](https://github.com/prdlk/yazi) via `.chezmoiexternals/yazi.toml` (`git-repo`, pulled `--ff-only` every 168h) |
| Target | `~/.config/yazi/` (git checkout; edit in place, commit and push from there) |
| Files | `yazi.toml`, `keymap.toml`, `init.lua`, `package.toml`, `theme.toml`, `vfs.toml`, `flavors/{cyberdream,ii-auto}.yazi/flavor.toml`, `plugins/bunny.yazi/` (vendored) |
| Helper | `dot_local/bin/executable_yazi-nvim-open` → `~/.local/bin/yazi-nvim-open` |
| Packages | `yazi` plus preview backends `ffmpeg`, `ffmpegthumbnailer`, `poppler`, `resvg`, `imagemagick`, `7zip` (`sevenzip` on macOS), `unzip` |
@@ -137,14 +135,15 @@ In the shell opened by <kbd>Shift</kbd>+<kbd>Tab</kbd>, the `q` function (fish,
## Plugins
`package.toml` pins every plugin to a commit and hash. Since `~/.config/yazi` links to the source dir, `ya pkg install` writes plugins into the repo's `yazi/plugins/`, which `.gitignore` excludes (`/yazi/plugins/*`, `!/yazi/plugins/bunny.yazi/`). The post-apply script reinstalls from the manifest:
`package.toml` pins every plugin to a commit and hash. `~/.config/yazi` is the [prdlk/yazi](https://github.com/prdlk/yazi) checkout, so `ya pkg install` writes plugins into its `plugins/`, which that repo's `.gitignore` excludes (`plugins/*`, `!plugins/bunny.yazi/`). The post-apply script reinstalls from the manifest:
```sh run_onchange_after_install-yazi-plugins.sh.tmpl
#!/bin/sh
# Install the yazi plugins pinned in yazi/package.toml whenever it changes.
# ~/.config/yazi links to the source dir, so they land in yazi/plugins/
# (gitignored, except the vendored bunny.yazi).
# package.toml hash: {{ include "yazi/package.toml" | sha256sum }}
# Install the yazi plugins pinned in ~/.config/yazi/package.toml whenever it
# changes. ~/.config/yazi is a git-repo external (prdlk/yazi); plugins land in
# its plugins/ dir (gitignored there, except the vendored bunny.yazi).
{{- $pkg := joinPath .chezmoi.homeDir ".config/yazi/package.toml" }}
# package.toml hash: {{ if stat $pkg }}{{ include $pkg | sha256sum }}{{ end }}
set -eu
command -v ya >/dev/null 2>&1 || exit 0
[ -f "${XDG_CONFIG_HOME:-$HOME/.config}/yazi/package.toml" ] || exit 0
@@ -158,7 +157,7 @@ ya pkg install || {
The embedded hash makes chezmoi re-run the script whenever `package.toml` changes.
bunny is not in `package.toml`: it is vendored at `71b14a3` in `yazi/plugins/bunny.yazi/`, because its repo contains a Git symlink to a directory (`test/plugins/bunny.yazi -> ../..`) that `ya pkg` cannot materialize. To update it, re-copy the files from upstream.
bunny is not in `package.toml`: it is vendored at `71b14a3` in `plugins/bunny.yazi/` of the yazi repo, because its repo contains a Git symlink to a directory (`test/plugins/bunny.yazi -> ../..`) that `ya pkg` cannot materialize. To update it, re-copy the files from upstream.
| Plugin | Rev | Used by |
| --- | --- | --- |