Initial import: chezmoi source for Omarchy (Hyprland)
Imported from prdlk/dotfiles master (efdd827), which supersedes the omarchy branch (3031416). Drops the Umbriel, Noctalia, niri, CachyOS, macOS, and Blume docs-site layers; docs/ is plain Markdown.
This commit is contained in:
commit
b18729f4a0
163 files changed
+12685
No files matched your search
@@ -0,0 +1,142 @@
|
||||
# How it works
|
||||
|
||||
Source layout, naming conventions, symlink mode, and the day-to-day chezmoi workflow for this repo.
|
||||
|
||||
The repo is a [chezmoi](https://chezmoi.io) source directory. It lives at `~/Code/prad.codes/env/omarchy` and chezmoi uses it as its source, either through `chezmoi init --source ~/Code/prad.codes/env/omarchy` or by cloning it into `~/.local/share/chezmoi`; both are the same checkout model chezmoi expects. Its remote is [env/omarchy](https://prad.codes/env/omarchy) (branch `main`). `chezmoi apply` renders it into `$HOME`. The [Installation](../installation.md) page covers first-time setup.
|
||||
|
||||
## Pages in this section
|
||||
|
||||
| Page | Covers |
|
||||
| --- | --- |
|
||||
| [Config and roles](config.md) | `.chezmoi.toml.tmpl`: prompts, machine role, symlink mode, age encryption, template data |
|
||||
| [Packages and aliases](data.md) | `.chezmoidata/packages.yaml` and `.chezmoidata/aliases.yaml`, and how they render |
|
||||
| [Apply scripts](scripts.md) | Every `run_*` script: when it runs, what triggers it, what it does per role |
|
||||
| [Externals and ignore rules](externals-and-ignore.md) | `.chezmoiexternal.toml` git clones and every `.chezmoiignore.tmpl` rule |
|
||||
|
||||
## Source layout
|
||||
|
||||
```text
|
||||
.chezmoi.toml.tmpl
|
||||
.chezmoidata/
|
||||
aliases.yaml
|
||||
packages.yaml
|
||||
skills.yaml
|
||||
.chezmoiexternal.toml
|
||||
.chezmoiexternals/
|
||||
agent-root.toml
|
||||
ghostty.toml
|
||||
herdr.toml
|
||||
kitty.toml
|
||||
omarchy.toml
|
||||
omp.toml
|
||||
television.toml
|
||||
tmux.toml
|
||||
tmux-palette.toml
|
||||
yazi.toml
|
||||
.chezmoiignore.tmpl
|
||||
.gitmodules
|
||||
.chezmoiscripts/
|
||||
run_onchange_before_10-packages.sh.tmpl
|
||||
run_onchange_after_15-tools.sh.tmpl
|
||||
run_onchange_after_20-gh-extensions.sh.tmpl
|
||||
run_onchange_after_25-skills.sh.tmpl
|
||||
run_once_after_30-user-services.sh.tmpl
|
||||
run_onchange_after_40-post.sh.tmpl
|
||||
run_onchange_after_build-bat-cache.sh.tmpl
|
||||
run_onchange_after_install-yazi-plugins.sh.tmpl
|
||||
dot_bashrc
|
||||
dot_zshrc
|
||||
dot_gitconfig.tmpl
|
||||
dot_config/
|
||||
atuin/
|
||||
bash/
|
||||
bat/
|
||||
drydock/
|
||||
fish/
|
||||
fontconfig/
|
||||
gh/
|
||||
gh-dash/
|
||||
go/
|
||||
herdr-nvim/
|
||||
hunk/
|
||||
hypr/
|
||||
lazydocker/
|
||||
lazygit/
|
||||
mimeapps.list
|
||||
shell/
|
||||
starship.toml
|
||||
systemd/
|
||||
topgrade.toml
|
||||
uwsm/
|
||||
waybar/
|
||||
xdg-terminals.list
|
||||
yazi.toml.tmpl
|
||||
zsh/
|
||||
dot_local/
|
||||
bin/
|
||||
dot_leetcode/
|
||||
docs/
|
||||
AGENTS.md
|
||||
README.md
|
||||
```
|
||||
|
||||
| Path | Target | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `.chezmoi.toml.tmpl` | `~/.config/chezmoi/chezmoi.toml` | Config template rendered by `chezmoi init`. See [Config and roles](config.md). |
|
||||
| `.chezmoidata/` | — | YAML merged into template data (`.packages`, `.aliases`, `.skills`). See [Packages and aliases](data.md) and [Skills](../ai/skills.md). |
|
||||
| `.chezmoiexternal.toml` | — | Git repos cloned into `$HOME` (nvim config, a bat syntax, tpm). |
|
||||
| `.chezmoiexternals/` | — | One external per app or tool: agent-root, ghostty, herdr, kitty, omarchy, omp, television, tmux, tmux-palette, yazi. Plain config repos cloned into `~/.config/<app>`. See [Externals and ignore rules](externals-and-ignore.md#chezmoiexternals). |
|
||||
| `.gitmodules` | — | `dot_config/hypr` and `dot_config/fish` are git submodules. See [Submodules](externals-and-ignore.md#submodules). |
|
||||
| `.chezmoiignore.tmpl` | — | Target paths chezmoi skips; gates the Linux desktop layer by role. |
|
||||
| `.chezmoiscripts/`, root `run_*` | — | Install and housekeeping scripts. See [Apply scripts](scripts.md). |
|
||||
| `dot_config/` | `~/.config/` | Per-tool config. Documented under [Shell](../shell/README.md), [Terminal](../terminal/README.md), [Tools](../tools/README.md), [Desktop](../desktop/README.md). |
|
||||
| `dot_local/bin/` | `~/.local/bin/` | 37 standalone scripts shared by every shell, plus the `omarchy-*` helpers. |
|
||||
| `dot_leetcode/` | `~/.leetcode/` | leetcode CLI workspace state. |
|
||||
| `docs/`, `AGENTS.md`, `README.md` | — | These docs, the repo agent rules, and the repo README. Listed in `.chezmoiignore.tmpl`, never applied. |
|
||||
|
||||
Entries whose source name starts with `.` (`.claude/`, `.gitignore`) are ignored by chezmoi automatically and stay repo-only.
|
||||
|
||||
## Naming conventions
|
||||
|
||||
chezmoi encodes target names and attributes in source file names. These are the prefixes and suffixes the repo uses:
|
||||
|
||||
| Source form | Meaning | Examples here |
|
||||
| --- | --- | --- |
|
||||
| `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 | Every script in `dot_local/bin/` |
|
||||
| `empty_` | File is kept even when empty | None currently |
|
||||
| `symlink_` | Target is a symlink; file content is the link destination | None currently |
|
||||
| `.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](scripts.md) |
|
||||
|
||||
Prefixes stack in chezmoi's fixed order, e.g. `private_dot_foo`, `executable_dot_bar`. No source file currently uses `encrypted_`, even though age encryption is configured.
|
||||
|
||||
## Symlink mode
|
||||
|
||||
`.chezmoi.toml.tmpl` sets `mode = "symlink"`. `chezmoi apply` then makes each managed dotfile a symlink into the source tree instead of a copy, as long as the file is a plain regular file. Files that are templates, `private_`, `executable_`, or encrypted are still written as real files.
|
||||
|
||||
What that means in practice:
|
||||
|
||||
- Editing a plain file in `$HOME` (for example `~/.config/waybar/config.jsonc`) edits the matching file in the source tree directly. The change is live and shows up in `git status` of the repo with no `chezmoi add` step.
|
||||
- Templates are rendered copies. Editing `~/.gitconfig` or `~/.config/shell/aliases.sh` changes only the copy; the next `chezmoi apply` overwrites it. Edit the `.tmpl` source (`chezmoi edit ~/.gitconfig`) instead.
|
||||
- `private_` and `executable_` targets are real files too. After editing one in place, run `chezmoi re-add <path>` to copy it back into the source.
|
||||
- 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](externals-and-ignore.md).
|
||||
|
||||
> [!NOTE]
|
||||
> Several fish aliases (`e.f`, `e.h`, `e.k`, `,,`) 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
|
||||
|
||||
| Command | What it does here |
|
||||
| --- | --- |
|
||||
| `chezmoi apply` | Runs `before_` scripts (package install), writes symlinks/files/templates into `$HOME`, clones missing externals, then runs `after_` scripts. |
|
||||
| `chezmoi update` | `git pull` in the source directory, then `apply`. |
|
||||
| `chezmoi diff` | Shows what `apply` would change, including rendered templates and scripts that would run. |
|
||||
| `chezmoi add <path>` | Moves a new file into the source tree under the right name. In symlink mode the target becomes a symlink on the next apply. Use `--template` or `--encrypt` for templated or secret files. |
|
||||
| `chezmoi re-add <path>` | Copies edits made to non-symlinked targets (private, executable) back into the source. |
|
||||
| `chezmoi edit <path>` | Opens the source file for a target, the right way to change templates. |
|
||||
| `chezmoi cd` | Opens a shell in the source directory for git work. The fish alias `,,` opens yazi there instead. |
|
||||
| `chezmoi init --prompt` | Re-asks name, email, and role and regenerates `~/.config/chezmoi/chezmoi.toml`. |
|
||||
|
||||
Commit and push from the source directory with plain git; the remote pushes over SSH (`git@prad.codes:env/omarchy.git`).
|
||||
@@ -0,0 +1,97 @@
|
||||
# Config and roles
|
||||
|
||||
The .chezmoi.toml.tmpl config template, its three prompts, symlink mode, age encryption, and where the resulting data is used.
|
||||
|
||||
`.chezmoi.toml.tmpl` is rendered once by `chezmoi init` into `~/.config/chezmoi/chezmoi.toml`. It asks three questions, turns on symlink mode and age encryption, and stores the answers as template data for every other `.tmpl` file.
|
||||
|
||||
## Source
|
||||
|
||||
**.chezmoi.toml.tmpl**
|
||||
|
||||
```toml
|
||||
{{- $name := promptStringOnce . "name" "Full name" "Prad Nukala" -}}
|
||||
{{- $email := promptStringOnce . "email" "Email" "prad@sonr.io" -}}
|
||||
{{- $roleDefault := "desktop" -}}
|
||||
{{- $role := promptChoiceOnce . "role" "Machine role" (list "desktop" "laptop" "server") $roleDefault -}}
|
||||
|
||||
mode = "symlink"
|
||||
encryption = "age"
|
||||
|
||||
[age]
|
||||
identity = "~/.config/chezmoi/key.txt"
|
||||
recipient = "age19tdqgavaekhvgqsd75n8a09vvshen2ykzy8kw6tenczz73449anqc3l7a6"
|
||||
useBuiltin = true
|
||||
|
||||
[data]
|
||||
name = {{ $name | quote }}
|
||||
email = {{ $email | quote }}
|
||||
role = {{ $role | quote }}
|
||||
```
|
||||
|
||||
## Prompts
|
||||
|
||||
| Key | Prompt | Type | Default |
|
||||
| --- | --- | --- | --- |
|
||||
| `name` | `Full name` | `promptStringOnce` | `Prad Nukala` |
|
||||
| `email` | `Email` | `promptStringOnce` | `prad@sonr.io` |
|
||||
| `role` | `Machine role` | `promptChoiceOnce` from `desktop`, `laptop`, `server` | `desktop` |
|
||||
|
||||
The `*Once` functions only prompt when the key is missing from the existing config, so re-running `chezmoi init` keeps earlier answers. `chezmoi init --prompt` forces all three prompts again. Changing the role changes the rendered ignore file and package script, so the next `chezmoi apply` adds or drops the desktop layer and re-runs the package install.
|
||||
|
||||
### Machine roles
|
||||
|
||||
| Role | Intended platform | Linux desktop layer | Desktop packages (`packages.arch.desktop`) |
|
||||
| --- | --- | --- | --- |
|
||||
| `desktop` | Arch Linux | Applied | Installed |
|
||||
| `laptop` | Arch Linux | Applied | Installed |
|
||||
| `server` | Omarchy/Arch Linux, headless | Skipped | Skipped |
|
||||
|
||||
`desktop` and `laptop` behave identically in the current templates; nothing branches on one without the other. The desktop layer is also skipped whenever the OS is not Linux, whatever the role. See [the ignore rules](externals-and-ignore.md#chezmoiignoretmpl) for the exact list of gated paths.
|
||||
|
||||
## Mode
|
||||
|
||||
`mode = "symlink"` makes `chezmoi apply` link plain files in `$HOME` back to the source tree. Templates, `private_`, `executable_`, and encrypted files are still written as real files. The [overview](README.md#symlink-mode) covers the editing consequences.
|
||||
|
||||
## Age encryption
|
||||
|
||||
| Setting | Value | Effect |
|
||||
| --- | --- | --- |
|
||||
| `encryption` | `"age"` | `chezmoi add --encrypt` and `encrypted_` source files use age. |
|
||||
| `age.identity` | `~/.config/chezmoi/key.txt` | Private key used to decrypt. Distributed by hand between machines, never committed. |
|
||||
| `age.recipient` | `age19tdqgavaekhvgqsd75n8a09vvshen2ykzy8kw6tenczz73449anqc3l7a6` | Public key files are encrypted to. Safe to publish. |
|
||||
| `age.useBuiltin` | `true` | Uses chezmoi's built-in age implementation; the `age` binary is not required. |
|
||||
|
||||
No source file currently carries the `encrypted_` attribute, so the key is only exercised when a secret is added with `chezmoi add --encrypt`. The [Installation](../installation.md) page still asks for the key to be copied into place before the first apply:
|
||||
|
||||
```sh
|
||||
mkdir -p ~/.config/chezmoi
|
||||
scp <existing-machine>:.config/chezmoi/key.txt ~/.config/chezmoi/key.txt
|
||||
chmod 600 ~/.config/chezmoi/key.txt
|
||||
```
|
||||
|
||||
## Template data
|
||||
|
||||
The `[data]` table exposes `.name`, `.email`, and `.role` to every template. chezmoi also merges `.chezmoidata/*.yaml` into the same namespace (`.packages`, `.aliases`; see [Packages and aliases](data.md)) and provides built-ins such as `.chezmoi.os`.
|
||||
|
||||
| Variable | Consumed by | Use |
|
||||
| --- | --- | --- |
|
||||
| `.name` | `dot_gitconfig.tmpl` | `[user] name` in `~/.gitconfig` |
|
||||
| `.email` | `dot_gitconfig.tmpl` | `[user] email` in `~/.gitconfig` |
|
||||
| `.role` | `.chezmoiignore.tmpl` | Skips the Linux desktop layer unless role is `desktop` or `laptop` |
|
||||
| `.role` | `.chezmoiscripts/run_onchange_before_10-packages.sh.tmpl` | Adds the `arch.desktop` pacman and AUR packages for `desktop`/`laptop` |
|
||||
| `.chezmoi.os` | `.chezmoi.toml.tmpl` | Role default (`desktop`) |
|
||||
| `.chezmoi.os` | `.chezmoiignore.tmpl` | Desktop layer requires `linux` |
|
||||
| `.chezmoi.os` | `run_onchange_before_10-packages.sh.tmpl` | pacman/yay on `linux` |
|
||||
| `.chezmoi.os` | `run_once_after_30-user-services.sh.tmpl` | systemd user units on `linux` only |
|
||||
| `.chezmoi.os` | `run_onchange_after_40-post.sh.tmpl` | `fc-cache` on `linux` only |
|
||||
| `.chezmoi.os`, `.role` | `run_onchange_after_15-tools.sh.tmpl` | strata install on `linux` with role `desktop`/`laptop` |
|
||||
|
||||
**dot_gitconfig.tmpl**
|
||||
|
||||
```ini
|
||||
[user]
|
||||
email = {{ .email }}
|
||||
name = {{ .name }}
|
||||
```
|
||||
|
||||
The rest of `~/.gitconfig` is covered under [Tools](../tools/README.md).
|
||||
@@ -0,0 +1,182 @@
|
||||
# Packages and aliases
|
||||
|
||||
The .chezmoidata YAML files that declare every installed package and every shared shell alias, and how they render.
|
||||
|
||||
Files in `.chezmoidata/` are merged into chezmoi's template data on every run. Nothing in the directory is written to `$HOME`; the data only reaches the machine through templates and scripts.
|
||||
|
||||
| File | Data key | Consumed by |
|
||||
| --- | --- | --- |
|
||||
| `.chezmoidata/packages.yaml` | `.packages` | [`run_onchange_before_10-packages.sh.tmpl`](scripts.md#10-packages), [`run_onchange_after_15-tools.sh.tmpl`](scripts.md#15-tools), [`run_onchange_after_20-gh-extensions.sh.tmpl`](scripts.md#20-gh-extensions) |
|
||||
| `.chezmoidata/aliases.yaml` | `.aliases` | `dot_config/shell/aliases.sh.tmpl` (bash and zsh) |
|
||||
| `.chezmoidata/skills.yaml` | `.skills` | [`run_onchange_after_25-skills.sh.tmpl`](scripts.md#25-skills) |
|
||||
|
||||
## packages.yaml
|
||||
|
||||
One manifest for Arch, plus a `shared` block. Any edit to the file changes the hash embedded in the package script, so the next `chezmoi apply` re-runs the install. Installs are idempotent (`pacman --needed`, `yay`/`paru --needed`). The lists are derived from what the configs actually invoke: tmux-palette items, television cable `requirements`, fish functions, `~/.local/bin` scripts, and compositor bindings.
|
||||
|
||||
### Arch
|
||||
|
||||
`packages.arch.pacman`, installed on every Linux machine with `pacman -S --needed --noconfirm`:
|
||||
|
||||
| Group | Packages |
|
||||
| --- | --- |
|
||||
| Shell and editors | `fish`, `neovim`, `helix`, `micro`, `tmux` |
|
||||
| Terminals | `ghostty` (default), `kitty` |
|
||||
| TUI tools (tmux-palette, television cables) | `yazi`, `lazygit`, `lazydocker`, `docker`, `docker-compose`, `btop`, `fastfetch`, `onefetch`, `television`, `serie`, `tig`, `gitui`, `tldr`, `navi`, `mdfried` |
|
||||
| VCS and forge | `git`, `github-cli`, `git-delta`, `diffnav`, `tea` |
|
||||
| Search and files | `fzf`, `fd`, `ripgrep`, `zoxide`, `eza`, `bat`, `jq`, `duf` |
|
||||
| Media and preview (yazi and tv deps) | `ffmpeg`, `ffmpegthumbnailer`, `poppler`, `resvg`, `imagemagick`, `chafa`, `7zip`, `unzip` |
|
||||
| Remote | `mosh`, `sshfs`, `tailscale` |
|
||||
| Misc CLI | `mise`, `gum`, `glow`, `atuin`, `wget`, `starship`, `zsh-syntax-highlighting` |
|
||||
| Fonts | `ttf-victor-mono-nerd` |
|
||||
|
||||
`packages.arch.aur`, installed with `yay -S --needed --noconfirm` (or `paru`) on every Linux machine: `topgrade`, `portop`. Names some installed package already provides are skipped, and yay is bootstrapped when no helper exists ([10-packages](scripts.md#10-packages)).
|
||||
|
||||
`packages.arch.desktop`, added only for roles `desktop` and `laptop`:
|
||||
|
||||
| Source | Packages |
|
||||
| --- | --- |
|
||||
| pacman | `uwsm`, `xdg-user-dirs`; Wayland utilities `wl-clipboard`, `cliphist`, `wtype`, `ydotool`, `grim`, `slurp`, `hyprpicker`, `pamixer`, `brightnessctl`, `libnotify`; apps `nautilus`, `imv`, `mpv`, `evince`, `chromium`, `obsidian`; strata runtime deps `bubblewrap`, `desktop-file-utils`, `fontconfig`, `gstreamer`, `gst-libav`, `gst-plugins-base`, `gst-plugins-good`, `gtk4`, `gtksourceview5`, `gvfs`, `poppler-glib`, `xdg-utils` |
|
||||
| AUR (or a sync repo with the same name) | `tldraw-offline-bin`; desktop apps `beeper-bin`, `fastmail`, `1password`, `brave-origin-bin`, `claude-desktop`, `spotify` |
|
||||
| `[omarchy]` repo (`packages.arch.desktop.omarchy`, only when `pacman-conf -l` lists that repo) | `herdr`, `flea`, `voxtype-bin`, `xdg-terminal-exec`, `hyprland-preview-share-picker` |
|
||||
|
||||
Hyprland, Waybar and the `omarchy-*` commands come with the Omarchy install and are not declared. strata (the folder handler) has no package; [15-tools](scripts.md#15-tools) runs its installer.
|
||||
|
||||
### Shared
|
||||
|
||||
`packages.shared.gh_extensions`, installed by the gh-extensions script:
|
||||
|
||||
| Extension | Purpose |
|
||||
| --- | --- |
|
||||
| `davidraviv/gh-clean-branches` | `gh clean-branches`: delete local branches whose upstream is gone |
|
||||
| `prdlk/gh-commit` | `gh commit` |
|
||||
| `dlvhdr/gh-dash` | `gh dash`: PR and issue dashboard |
|
||||
| `meiji163/gh-notify` | `gh notify`: notifications in the terminal |
|
||||
|
||||
`packages.shared.cargo` lists `suvadu`, `mandible` (the tmux-palette "mandible" item runs `~/.local/bin/mandible-pick`), and `worktrunk` (`wt`, git worktree management for parallel agent work). [`run_onchange_after_15-tools.sh.tmpl`](scripts.md#15-tools) installs rustup when `cargo` is missing, then any crate `cargo install --list` lacks.
|
||||
|
||||
`packages.shared.mise` lists the global mise tools: `ghq`, `bun`, `node`, `uv`, `opencode`, `crush`, and omp as `github:can1357/oh-my-pi` (omp is not in the mise registry, so it uses the GitHub-releases backend, which installs the release binary as `omp`). The same script runs `mise use -g` for each one not yet in the global config (`~/.config/mise/config.toml`, local per machine), then `mise install` on the list. A tool already there keeps its pinned version. topgrade's mise step (`mise upgrade`) updates them.
|
||||
|
||||
> [!NOTE]
|
||||
> AUR packages need `yay` or `paru`. The package script bootstraps `yay` when neither exists; only when that is impossible (running as root with no repo shipping yay) does it print a warning listing the skipped AUR packages and continue.
|
||||
|
||||
## aliases.yaml
|
||||
|
||||
The single source for aliases shared across shells. Each entry has a `section` and a list of `{ name, cmd }` items.
|
||||
|
||||
### Editors / file managers
|
||||
|
||||
| Alias | Command |
|
||||
| --- | --- |
|
||||
| `e` | `nvim` |
|
||||
| `e.d` | `cd ~/.config/dotstate/storage/Rogz/.config && yazi` |
|
||||
| `e.f` | `cd ~/.config/fish && yazi` |
|
||||
| `e.k` | `yazi ~/.config/kitty` |
|
||||
| `e.v` | `yazi ~/.config/nvim/lua` |
|
||||
| `e.y` | `yazi ~/.config/yazi` |
|
||||
| `e.t` | `nvim ~/.config/tmux/tmux.conf` |
|
||||
| `hx` | `helix` |
|
||||
|
||||
### Quick directory jumps
|
||||
|
||||
| Alias | Command |
|
||||
| --- | --- |
|
||||
| `cdc` | `cd ~/.config && yazi` |
|
||||
| `cdd` | `cd ~/Developer && yazi` |
|
||||
| `cdk` | `cd ~/Documents/Knowledge && obsidian` |
|
||||
| `cdl` | `cd ~/.local && yazi` |
|
||||
| `cds` | `cd ~/.local/share/services && ls` |
|
||||
| `cdw` | `cd ~/Downloads && yazi` |
|
||||
|
||||
### Tools
|
||||
|
||||
| Alias | Command |
|
||||
| --- | --- |
|
||||
| `dd` | `lazydocker` |
|
||||
| `gg` | `lazygit` |
|
||||
| `ff` | `exec fish` |
|
||||
| `npx` | `bunx` |
|
||||
| `sm` | `sudo micro` |
|
||||
| `sd` | `ssh prad@<lan-host>` |
|
||||
| `oc` | `opencode` |
|
||||
| `dss` | `dotstate sync` |
|
||||
| `fabric` | `fabric-ai` |
|
||||
| `bk` | `bead-kanban` |
|
||||
| `lc` | `leetcode` |
|
||||
| `tk` | `task` |
|
||||
|
||||
`dd` shadows coreutils `dd` in interactive shells.
|
||||
|
||||
## How aliases render
|
||||
|
||||
### bash and zsh
|
||||
|
||||
`dot_config/shell/aliases.sh.tmpl` renders to `~/.config/shell/aliases.sh`. Because it is a template it is written as a real file, not a symlink; edit the YAML and run `chezmoi apply` to regenerate it.
|
||||
|
||||
**dot_config/shell/aliases.sh.tmpl**
|
||||
|
||||
```sh
|
||||
{{- range .aliases }}
|
||||
|
||||
# {{ .section }}
|
||||
{{- range .items }}
|
||||
alias {{ .name }}='{{ .cmd }}'
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
After the generated block the file adds shell-specific pieces that are not in the YAML:
|
||||
|
||||
| Name | Definition |
|
||||
| --- | --- |
|
||||
| `cpy` / `pst` | `wl-copy` / `wl-paste` when `wl-copy` exists |
|
||||
| `q` | Function: if `$YAZI_ID` is set and `ya` exists, runs `ya emit quit` so the parent yazi also exits, then `exit` |
|
||||
| `celar`, `claer` | Typo guards for `clear` |
|
||||
| `ls` | `eza --icons`, when `eza` is installed |
|
||||
|
||||
`~/.bashrc` and `~/.zshrc` source it for interactive shells:
|
||||
|
||||
**dot_bashrc**
|
||||
|
||||
```sh
|
||||
[ -f "$HOME/.config/shell/aliases.sh" ] && . "$HOME/.config/shell/aliases.sh"
|
||||
```
|
||||
|
||||
See [bash and zsh](../shell/README.md) for the rest of those files.
|
||||
|
||||
### fish
|
||||
|
||||
`dot_config/fish/conf.d/20-aliases.fish` is not a template. It is a hand-maintained plain file (symlinked into `~/.config/fish/conf.d/`) whose header says it is generated from the YAML; the YAML header likewise names a `20-aliases.fish.tmpl` that does not exist. The fish file has drifted from `aliases.yaml`:
|
||||
|
||||
| Alias | aliases.yaml (bash/zsh) | fish |
|
||||
| --- | --- | --- |
|
||||
| `e.d` | `cd ~/.config/dotstate/storage/Rogz/.config && yazi` | not defined |
|
||||
| `e.f` | `cd ~/.config/fish && yazi` | `cd ~/.local/share/chezmoi/dot_config/fish && yazi` |
|
||||
| `e.h` | not defined | `cd ~/.local/share/chezmoi/dot_config/hypr && yazi` |
|
||||
| `e.k` | `yazi ~/.config/kitty` | ✓ |
|
||||
| `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 ..` |
|
||||
|
||||
fish-only Bun aliases:
|
||||
|
||||
| Alias | Command |
|
||||
| --- | --- |
|
||||
| `br` | `bun run` |
|
||||
| `br.d` | `bun run dev` |
|
||||
| `br.b` | `bun run build` |
|
||||
| `br.t` | `bun run test` |
|
||||
| `bi` | `bun install` |
|
||||
| `bg` | `bun install -g` (shadows fish's `bg` job-control builtin) |
|
||||
| `bx` | `bunx` |
|
||||
|
||||
Every other YAML alias (`e`, `e.v`, `hx`, `cdc`, `cdk`, `cdl`, `cds`, `cdw`, and the whole Tools section) is defined identically in fish. The file ends with the same extras as the sh version: `cpy`/`pst` clipboard detection, the `q` function, and, in interactive sessions only, `celar`/`claer` and `ls` → `eza --icons`. `clear` itself is an autoloaded function (`functions/clear.fish`), which is why it is not aliased. See [fish](../shell/fish.md).
|
||||
|
||||
> [!TIP]
|
||||
> To add an alias for every shell, add it to `aliases.yaml` for bash/zsh and to `20-aliases.fish` by hand for fish.
|
||||
|
||||
## skills.yaml
|
||||
|
||||
Declares the agent skills installed by the Skills CLI. `skills.cli` is the pinned CLI (`skills@1.7.0`, run with `npx -y`), `skills.agents` the default install targets (`[universal, claude-code]`), and `skills.sources` a list of `{ source, skills, agents? }` entries: 110 skills across 42 entries. The full list, pinned sources, and add/remove workflow are on the [Skills](../ai/skills.md) page.
|
||||
@@ -0,0 +1,176 @@
|
||||
# Externals and ignore rules
|
||||
|
||||
The git repos chezmoi clones into $HOME and every rule in .chezmoiignore.tmpl, including the role gate for the Linux desktop layer.
|
||||
|
||||
## .chezmoiexternal.toml
|
||||
|
||||
Externals are content chezmoi fetches instead of storing in the repo. Every entry is a `git-repo` external: chezmoi runs `git clone` when the target directory is missing. Because they are real git checkouts, they are never symlinked into the source tree.
|
||||
|
||||
**.chezmoiexternal.toml**
|
||||
|
||||
```toml
|
||||
[".config/nvim"]
|
||||
type = "git-repo"
|
||||
url = "https://github.com/prdlk/nvim.git"
|
||||
[".config/nvim".pull]
|
||||
args = ["--ff-only"]
|
||||
|
||||
[".config/bat/syntaxes/sublime-purescript-syntax"]
|
||||
type = "git-repo"
|
||||
url = "https://github.com/tellnobody1/sublime-purescript-syntax.git"
|
||||
[".config/bat/syntaxes/sublime-purescript-syntax".pull]
|
||||
args = ["--ff-only"]
|
||||
|
||||
[".config/tmux/plugins/tpm"]
|
||||
type = "git-repo"
|
||||
url = "https://github.com/tmux-plugins/tpm.git"
|
||||
[".config/tmux/plugins/tpm".pull]
|
||||
args = ["--ff-only"]
|
||||
```
|
||||
|
||||
| Target | Repo | Used by |
|
||||
| --- | --- | --- |
|
||||
| `~/.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](scripts.md#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.md)). Cloned inside the tmux checkout, whose `.gitignore` excludes `plugins/` |
|
||||
|
||||
### No refreshPeriod
|
||||
|
||||
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/
|
||||
|
||||
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. The exception is [`agent-root.toml`](#agent-root), a single downloaded script.
|
||||
|
||||
**.chezmoiexternals/tmux.toml**
|
||||
|
||||
```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) |
|
||||
| `kitty.toml` | `~/.config/kitty` | [prdlk/kitty](https://github.com/prdlk/kitty) |
|
||||
| `ghostty.toml` | `~/.config/ghostty` | [prdlk/ghostty](https://github.com/prdlk/ghostty) |
|
||||
| `herdr.toml` | `~/.config/herdr` | [prdlk/herdr](https://github.com/prdlk/herdr) — `plugins/github/` (runtime plugin checkouts) is gitignored there |
|
||||
| `omarchy.toml` | `~/.config/omarchy` | [prdlk/omarchy](https://github.com/prdlk/omarchy) — `shell.json`, hooks, menu extensions, themed templates; git-installed themes/plugins are gitignored there and restored by its `install-extras` script, `calendars.json` is never committed |
|
||||
| `omp.toml` | `~/.omp` | [prdlk/omp](https://github.com/prdlk/omp) — omp agent config and the global agent instructions |
|
||||
|
||||
Edit these in place under `~/.config/<app>`, then commit and push from that checkout.
|
||||
|
||||
### agent-root
|
||||
|
||||
`agent-root.toml` is the one `file` external: chezmoi downloads [jankeesvw/agent-root](https://github.com/jankeesvw/agent-root)'s single bash script to `~/.local/bin/agent-root` (mode `0755`) and re-fetches it at most once a week (`refreshPeriod = "168h"`). Coding agents run `agent-root "<why>" <command>` instead of `sudo`; it wraps `pkexec` (`polkit`) so the session's polkit agent shows the command, and `notify-send` (`libnotify`) shows the reason. Exit 126 means the dialog was dismissed. The usage rules agents follow live in the global omp instructions, `~/.omp/agent/AGENTS.md` ([prdlk/omp](https://github.com/prdlk/omp)). Linux desktop/laptop roles only ([role gate](#chezmoiignoretmpl)), since there is no polkit agent elsewhere.
|
||||
|
||||
**.chezmoiexternals/agent-root.toml**
|
||||
|
||||
```toml
|
||||
[".local/bin/agent-root"]
|
||||
type = "file"
|
||||
url = "https://raw.githubusercontent.com/jankeesvw/agent-root/main/agent-root"
|
||||
executable = true
|
||||
refreshPeriod = "168h"
|
||||
```
|
||||
|
||||
## Submodules
|
||||
|
||||
Two 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/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
|
||||
|
||||
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 `.` (`.claude/`, `.gitignore`) are ignored by chezmoi without needing a rule.
|
||||
|
||||
### Repo docs
|
||||
|
||||
```txt
|
||||
README.md
|
||||
CLAUDE.md
|
||||
AGENTS.md
|
||||
docs
|
||||
```
|
||||
|
||||
Files at the source root that would otherwise land in `$HOME` as `~/README.md` or `~/docs`. This covers the repo README, the agent instruction files, and these docs.
|
||||
|
||||
### Compositor hook from the fish submodule
|
||||
|
||||
```txt
|
||||
.config/fish/auto-Niri.fish
|
||||
```
|
||||
|
||||
The shared fish submodule ships a compositor auto-start hook this repo never uses. It is ignored on every machine, outside the role gate.
|
||||
|
||||
### Runtime and plugin state inside managed trees
|
||||
|
||||
| Pattern | Why |
|
||||
| --- | --- |
|
||||
| `.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` and `__pycache__/` never get committed even though symlink mode lets tools write into the source tree.
|
||||
|
||||
### mise
|
||||
|
||||
```txt
|
||||
.config/mise
|
||||
.config/mise/**
|
||||
```
|
||||
|
||||
mise tool versions stay local to each machine and are not managed.
|
||||
|
||||
### Linux desktop layer (role-gated)
|
||||
|
||||
**.chezmoiignore.tmpl**
|
||||
|
||||
```txt
|
||||
{{ if or (ne .chezmoi.os "linux") (and (ne .role "desktop") (ne .role "laptop")) }}
|
||||
.config/hypr
|
||||
.config/hypr/**
|
||||
.config/waybar
|
||||
.config/waybar/**
|
||||
.config/uwsm
|
||||
.config/uwsm/**
|
||||
.local/bin/agent-root
|
||||
.config/fontconfig
|
||||
.config/fontconfig/**
|
||||
.config/mimeapps.list
|
||||
.config/xdg-terminals.list
|
||||
.config/systemd
|
||||
.config/systemd/**
|
||||
.local/bin/kitty-day-save
|
||||
.local/bin/cp-appid
|
||||
.local/bin/projects-sync
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
The block is emitted, and these paths skipped, unless the OS is `linux` and the role is `desktop` or `laptop`. `server` machines, and any non-Linux machine regardless of role, never receive the Hyprland config (`dot_config/hypr/`), the Waybar config (`dot_config/waybar/`), the uwsm environment (`dot_config/uwsm/`), fontconfig (`dot_config/fontconfig/fonts.conf`), default-app associations (`dot_config/mimeapps.list`, `dot_config/xdg-terminals.list`), the systemd user units (`dot_config/systemd/user/kitty-day-save.service`, `projects-sync.service`, `projects-sync.timer`), or the `agent-root`, `cp-appid`, `kitty-day-save` and `projects-sync` scripts.
|
||||
|
||||
| Machine | Desktop layer |
|
||||
| --- | --- |
|
||||
| Linux, `desktop` or `laptop` | Applied |
|
||||
| Linux, `server` | Ignored |
|
||||
| Other OS, any role | Ignored |
|
||||
|
||||
See [Desktop](../desktop/README.md) for what the layer contains. The `omarchy-*` scripts in `dot_local/bin/` are not in the block, so they apply on every role.
|
||||
@@ -0,0 +1,146 @@
|
||||
# Apply scripts
|
||||
|
||||
Every run_ script chezmoi executes during apply, when each one fires, and what it does on each OS and role.
|
||||
|
||||
Seven scripts run during `chezmoi apply`. Five live in `.chezmoiscripts/`, a directory whose scripts run as if they sat at the source root without creating a matching target directory. Two sit at the repo root. All seven are templates; `20-gh-extensions` is a fish script, the rest use `#!/bin/sh` with `set -eu` (except `25-skills`, which uses `set -u`).
|
||||
|
||||
## Execution order
|
||||
|
||||
`before_` scripts run before any file is written; `after_` scripts run after every file, symlink, and external is in place. Within a phase chezmoi runs scripts in ASCII order of their target names, so the numeric prefixes come first.
|
||||
|
||||
1. **10-packages (before, onchange)**
|
||||
|
||||
Install system packages from `packages.yaml`.
|
||||
|
||||
2. **Files, symlinks, externals**
|
||||
|
||||
chezmoi writes the target state.
|
||||
|
||||
3. **15-tools (after, onchange)**
|
||||
|
||||
rustup and cargo crates, omp, global mise tools, strata on Linux desktops.
|
||||
|
||||
4. **20-gh-extensions (after, onchange)**
|
||||
|
||||
Install gh extensions from a fish session.
|
||||
|
||||
5. **25-skills (after, onchange)**
|
||||
|
||||
Install and prune agent skills.
|
||||
|
||||
6. **30-user-services (after, once)**
|
||||
|
||||
Enable systemd user units (kitty-day-save, projects-sync.timer).
|
||||
|
||||
7. **40-post (after, onchange)**
|
||||
|
||||
bat cache, font cache.
|
||||
|
||||
8. **build-bat-cache (after, onchange)**
|
||||
|
||||
Rebuild bat cache when its theme or config changes.
|
||||
|
||||
9. **install-yazi-plugins (after, onchange)**
|
||||
|
||||
Reinstall yazi plugins when the manifest changes.
|
||||
|
||||
| Script | Phase | Frequency | Re-run trigger |
|
||||
| --- | --- | --- | --- |
|
||||
| `.chezmoiscripts/run_onchange_before_10-packages.sh.tmpl` | before | onchange | sha256 of `.chezmoidata/packages.yaml`; also the role and OS, which change the rendered package list |
|
||||
| `.chezmoiscripts/run_onchange_after_15-tools.sh.tmpl` | after | onchange | sha256 of `packages.shared.cargo` and `packages.shared.mise` as JSON; also the OS and role, which add the strata step |
|
||||
| `.chezmoiscripts/run_onchange_after_20-gh-extensions.sh.tmpl` | after | onchange | sha256 of `packages.shared.gh_extensions` as JSON |
|
||||
| `.chezmoiscripts/run_onchange_after_25-skills.sh.tmpl` | after | onchange | sha256 of `.skills` as JSON |
|
||||
| `.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 | 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 `~/.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:
|
||||
|
||||
```sh
|
||||
# packages.yaml hash: {{ include ".chezmoidata/packages.yaml" | sha256sum }}
|
||||
```
|
||||
|
||||
`run_once_` scripts run once per unique rendered content and again only if that content changes or the previous run failed.
|
||||
|
||||
## 10-packages
|
||||
|
||||
`.chezmoiscripts/run_onchange_before_10-packages.sh.tmpl` installs everything in [`packages.yaml`](data.md#packagesyaml). It runs before files are applied so the tools exist when configs land. On a non-Linux OS it renders to just the shebang and does nothing.
|
||||
|
||||
### Steps
|
||||
|
||||
1. Uses `pacman` directly when running as root, otherwise `sudo pacman`.
|
||||
2. `pacman -T` filters each list down to names no installed package provides (so `mise-bin` satisfies `mise`, `yazi-git` satisfies `yazi`), then `pacman -S --needed --noconfirm` installs the rest of `packages.arch.pacman`.
|
||||
3. For roles `desktop` and `laptop`, the same for `packages.arch.desktop.pacman`, and for `packages.arch.desktop.omarchy` when `pacman-conf -l` lists an `omarchy` repo.
|
||||
4. Builds the AUR list: `packages.arch.desktop.aur` plus `packages.arch.aur` for `desktop`/`laptop`, only `packages.arch.aur` for other roles, then drops every name `pacman -T` says is already provided. Desktop apps already installed from a sync repo (`[omarchy]`) are therefore neither rebuilt nor replaced.
|
||||
5. If anything is left and neither `yay` nor `paru` is installed, bootstraps `yay`: from a sync repo when `pacman -Si yay` finds one, otherwise by building `yay-bin` from the AUR with `makepkg -si` (installs `git` and `base-devel` first; skipped as root, since makepkg refuses root). Omarchy ships `yay`, so this is normally a no-op.
|
||||
6. Runs `yay -S --needed --noconfirm` on the remaining names, falling back to `paru`. yay prefers a sync repo over the AUR when both have the name. If no helper could be bootstrapped it prints `warning: no yay/paru and none could be bootstrapped — skipping AUR packages: …` and continues.
|
||||
|
||||
## 15-tools
|
||||
|
||||
`.chezmoiscripts/run_onchange_after_15-tools.sh.tmpl` installs the tools that do not come from pacman. It prepends `~/.cargo/bin` to `PATH`, since chezmoi's environment can predate the shell config that adds it. Any failing step aborts the script, so chezmoi keeps the old hash and retries on the next apply.
|
||||
|
||||
| Step | Condition | Action |
|
||||
| --- | --- | --- |
|
||||
| rustup | `cargo` not on `PATH` | `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \| sh -s -- -y --no-modify-path`. `-y` because there is no prompt under chezmoi; `--no-modify-path` because the shell rc files are symlinks into this repo and already source `~/.cargo/env` |
|
||||
| cargo crates | every OS | `cargo install --locked <crate>` for each `packages.shared.cargo` entry missing from `cargo install --list` |
|
||||
| mise tools | `mise` installed (warning otherwise) | `mise use -g <tools…>` for each `packages.shared.mise` entry absent from `mise ls --global --json`, then `mise install <tools…>`. A tool already in the global config keeps its pinned version. omp and opencode come from here |
|
||||
| old omp binary | `~/.local/bin/omp` is a regular file and `mise which omp` resolves | Deletes it: a copy from omp's own installer (`omp.sh/install`) sits ahead of mise's shims on `PATH` |
|
||||
| strata | Linux, roles `desktop`/`laptop`, no `~/.local/bin/strata` | `curl -fsSL https://raw.githubusercontent.com/lgse/strata/main/install.sh \| bash -s -- --with-desktop-entry --with-file-manager` |
|
||||
| strata file chooser | Linux, roles `desktop`/`laptop`, `~/.local/bin/strata` exists and `~/.local/share/xdg-desktop-portal/portals/strata.portal` does not | `strata --install-portal` |
|
||||
|
||||
The strata flags install the binary, `~/.local/share/applications/io.github.lgse.Strata.desktop`, and the `org.freedesktop.FileManager1` D-Bus service in `~/.local/share/dbus-1/services` ("Open file location" from other apps). The folder default (`inode/directory`) comes from the managed `~/.config/mimeapps.list` instead of `--with-folder-association`, because `xdg-mime default` would replace that symlink with a plain file. The installer's own dependency step runs `sudo -n pacman`, which fails without cached credentials, so its runtime packages are declared in `packages.arch.desktop.pacman` and are already present when it runs.
|
||||
|
||||
`strata --install-portal` makes strata the system file chooser for portal-aware apps (browsers, GTK file dialogs). It writes `strata.portal` and the `org.freedesktop.impl.portal.desktop.strata` D-Bus service under `~/.local/share`, prepends `strata;` to the `org.freedesktop.impl.portal.FileChooser` line of `~/.config/xdg-desktop-portal/<desktop>-portals.conf` (`hyprland-portals.conf`, copied from `/usr/share/xdg-desktop-portal/` when absent, so the compositor's backends stay as fallbacks), marks the in-app offer answered (`~/.config/strata/portal-opt-in-v1`), and restarts `xdg-desktop-portal.service`. That config file is strata's, not chezmoi's: `strata --uninstall-portal` restores it. Check: `gdbus call --session --dest org.freedesktop.impl.portal.desktop.strata --object-path /org/freedesktop/portal/desktop --method org.freedesktop.DBus.Properties.Get org.freedesktop.impl.portal.FileChooser version` prints `uint32 4`. Apps that draw their own picker instead of calling the portal are unchanged.
|
||||
|
||||
## 20-gh-extensions
|
||||
|
||||
`.chezmoiscripts/run_onchange_after_20-gh-extensions.sh.tmpl` installs each `packages.shared.gh_extensions` entry. It is a fish script (`#!/usr/bin/env fish`), so fish sources `~/.config/fish` first: `PATH` (mise, `~/.local/bin`, `~/.cargo/bin`) and `GITHUB_TOKEN` (from `gh auth token` in `conf.d/10-env.fish`) are those of a fish session. It runs after every file is applied and after [15-tools](#15-tools), so the fish config and `~/.cargo/env.fish` exist.
|
||||
|
||||
- Exits 0 with `warning: gh not installed — skipping extensions` if `gh` is missing.
|
||||
- Exits 0 with `warning: gh not authenticated — run 'gh auth login', then 'chezmoi apply' again` if `gh auth status` fails.
|
||||
- Reads `gh extension list`, then runs `gh extension install <repo>` only for extensions not already present.
|
||||
- Exits 1 listing the failed extensions if any install failed, so the next apply retries.
|
||||
|
||||
> [!WARNING]
|
||||
> A skipped run still exits 0, so chezmoi records this content as done and a plain re-apply does not retry it, despite what the warning text says. After `gh auth login`, either run `gh extension install` for each entry by hand, or clear chezmoi's onchange state with `chezmoi state delete-bucket --bucket=entryState` and apply again (this re-runs every `run_onchange_` script).
|
||||
|
||||
## 25-skills
|
||||
|
||||
`.chezmoiscripts/run_onchange_after_25-skills.sh.tmpl` installs the agent skills declared in [`skills.yaml`](data.md#skillsyaml) with the Skills CLI (`npx -y skills@1.7.0`). See [Skills](../ai/skills.md).
|
||||
|
||||
- Exits 0 with a warning if `npx` is missing.
|
||||
- One-time migration: deletes any directory in `~/.agents/skills` or `~/.claude/skills` that contains symlinks into the chezmoi source directory (the old vendored layout), and removes `~/.agents/.skill-lock.json` if it is a symlink into the source directory.
|
||||
- Removes skills listed in `${XDG_STATE_HOME:-~/.local/state}/chezmoi/skills.txt` that are no longer declared, with `skills remove -g -y`.
|
||||
- Runs one `skills add <source> -g -y -a <agents> --skill <names…>` per source entry. Output is captured; on failure the last 8 lines are printed.
|
||||
- Writes the declared names to `skills.txt`. Claude-only installs are not in the CLI's lock, so the script keeps its own record.
|
||||
- Exits 1 if any source failed, so chezmoi keeps the old hash and retries on the next apply.
|
||||
|
||||
## 30-user-services
|
||||
|
||||
`.chezmoiscripts/run_once_after_30-user-services.sh.tmpl` enables session-critical systemd user units on Linux.
|
||||
|
||||
- Same check for `~/.config/systemd/user/kitty-day-save.service` (from `dot_config/systemd/user/`, so Linux desktop/laptop roles only), then `systemctl --user enable --now kitty-day-save.service`. See [kitty-day-save](../shell/scripts.md#kitty-day-save).
|
||||
- Same check for `~/.config/systemd/user/projects-sync.timer`, then `systemctl --user enable --now projects-sync.timer`. See [projects-sync](../shell/scripts.md#projects-sync).
|
||||
- On non-Linux systems it renders to `#!/bin/sh` / `exit 0`.
|
||||
|
||||
Other personal automation units (brain-lens, omp-loop, rclone, hermes, voxtype) are deliberately not enabled; the script comment says to enable them by hand per machine. Their unit files are not in the repo, so they have to exist on the machine already.
|
||||
|
||||
## 40-post
|
||||
|
||||
`.chezmoiscripts/run_onchange_after_40-post.sh.tmpl` is post-apply housekeeping. It re-runs when the script is edited.
|
||||
|
||||
| Step | Condition | Action |
|
||||
| --- | --- | --- |
|
||||
| bat cache | `bat` installed | `bat cache --build` |
|
||||
| Font cache | Linux, `fc-cache` installed | `fc-cache -f` |
|
||||
|
||||
Each step ignores failures (`|| true`). tpm is cloned by [`.chezmoiexternal.toml`](externals-and-ignore.md#chezmoiexternaltoml), not here.
|
||||
|
||||
## build-bat-cache
|
||||
|
||||
`run_onchange_after_build-bat-cache.sh.tmpl` rebuilds bat's syntax and theme cache when the managed inputs change. It hashes `dot_config/bat/themes/cyberdream.tmTheme` and `dot_config/bat/config`, exits quietly if `bat` is missing, and otherwise runs `bat cache --build`. This registers the cyberdream theme and the PureScript syntax cloned by [`.chezmoiexternal.toml`](externals-and-ignore.md#chezmoiexternaltoml).
|
||||
|
||||
## install-yazi-plugins
|
||||
|
||||
`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.md).
|
||||
Reference in new issue
Block a user