How it works
Source layout, naming conventions, symlink mode, and the day-to-day chezmoi workflow for this repo.
The repo is a chezmoi source directory. It lives at ~/.local/share/chezmoi and its remote is prdlk/dotfiles. chezmoi apply renders it into $HOME. The Installation page covers first-time setup.
Pages in this section
| Page | Covers |
|---|---|
| Config and roles | .chezmoi.toml.tmpl: prompts, machine role, symlink mode, age encryption, template data |
| Packages and aliases | .chezmoidata/packages.yaml and .chezmoidata/aliases.yaml, and how they render |
| Apply scripts | Every run_* script: when it runs, what triggers it, what it does per OS and role |
| Externals and ignore rules | .chezmoiexternal.toml git clones and every .chezmoiignore.tmpl rule |
Source layout
- .chezmoi.toml.tmpl
- .chezmoidata/
- aliases.yaml
- packages.yaml
- .chezmoiexternal.toml
- .chezmoiignore.tmpl
- .chezmoiscripts/
- run_onchange_before_10-packages.sh.tmpl
- run_onchange_after_20-gh-extensions.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/
- fish/
- fontconfig/
- gh/
- gh-dash/
- ghostty/
- herdr/
- herdr-nvim/
- hunk/
- hypr/
- kitty/
- lazydocker/
- lazygit/
- mimeapps.list
- niri/
- shell/
- starship.toml
- tmux/
- topgrade.toml
- waybar/
- yazi/
- zsh/
- dot_local/
- bin/
- dot_claude/
- commands/
- hooks/
- skills/
- settings.json
- empty_CLAUDE.md
- dot_agents/
- skills/
- dot_skill-lock.json
- dot_omp/
- loops/
- private_agent/
- dot_leetcode/
- docs/
- public/
- blume.config.ts
- package.json
- bun.lock
- README.md
| Path | Target | Purpose |
|---|---|---|
.chezmoi.toml.tmpl |
~/.config/chezmoi/chezmoi.toml |
Config template rendered by chezmoi init. See Config and roles. |
.chezmoidata/ |
— | YAML merged into template data (.packages, .aliases). See Packages and aliases. |
.chezmoiexternal.toml |
— | Git repos cloned into $HOME (nvim config, a bat syntax). |
.chezmoiignore.tmpl |
— | Target paths chezmoi skips; gates the Linux desktop layer by role. |
.chezmoiscripts/, root run_* |
— | Install and housekeeping scripts. See Apply scripts. |
dot_config/ |
~/.config/ |
Per-tool config. Documented under Shell, Terminal, Tools, Desktop. |
dot_local/bin/ |
~/.local/bin/ |
33 standalone scripts shared by every shell. |
dot_claude/ |
~/.claude/ |
Claude Code settings, commands, hooks, and skill symlinks. See AI agents. |
dot_agents/ |
~/.agents/ |
The shared agent skill library the ~/.claude/skills symlinks resolve against. |
dot_omp/ |
~/.omp/ |
omp agent config and loops. |
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. |
Entries whose source name starts with . (.github/, .claude/, .crush/, .gitignore) are ignored by chezmoi automatically and stay repo-only. .github/workflows/docs.yml builds this site.
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, dot_skill-lock.json → .skill-lock.json |
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, dot_omp/private_agent/, dot_omp/loops/*/private_loop.md |
executable_ |
Target gets the executable bit | 49 files: every script in dot_local/bin/, dot_config/niri/scripts/, dot_config/tmux/executable_niri-title.sh, Claude hooks, skill helper 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_claude/empty_CLAUDE.md, dot_config/herdr/empty_dot_plugins.lock |
symlink_ |
Target is a symlink; file content is the link destination | 67 entries in dot_claude/skills/ (each → ../../.agents/skills/<name>), dot_config/kitty/symlink_current-theme.conf (→ themes/noctalia.conf) |
.tmpl |
Rendered with Go templates and chezmoi data | dot_gitconfig.tmpl, dot_config/shell/aliases.sh.tmpl, dot_config/yazi/yazi.toml.tmpl, all scripts, the config and ignore files |
run_once_ / run_onchange_ + before_ / after_ |
Script, with run frequency and phase | See Apply scripts |
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/kitty/kitty.conf) edits~/.local/share/chezmoi/dot_config/kitty/kitty.confdirectly. The change is live and shows up ingit statusof the repo with nochezmoi addstep. - Templates are rendered copies. Editing
~/.gitconfigor~/.config/shell/aliases.shchanges only the copy; the nextchezmoi applyoverwrites it. Edit the.tmplsource (chezmoi edit ~/.gitconfig) instead. private_andexecutable_targets are real files too. After editing one in place, runchezmoi 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.tmpland.gitignore; see Externals and ignore rules.
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 ~/.local/share/chezmoi 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@github.com:prdlk/dotfiles.git).