- Lua 58.6%
- Shell 23.7%
- GLSL 16%
- Vim Script 1.2%
- CSS 0.5%
| .chezmoidata | ||
| .chezmoiscripts | ||
| dot_alias | ||
| dot_claude | ||
| dot_config | ||
| dot_local/bin | ||
| dot_oh-my-zsh/custom/themes | ||
| dot_vim/colors | ||
| other-configs | ||
| private_dot_ssh | ||
| .chezmoi.toml.tmpl | ||
| .chezmoiignore | ||
| .gitignore | ||
| CLAUDE.md | ||
| dot_bashrc.tmpl | ||
| dot_vimrc | ||
| dot_zshrc.tmpl | ||
| README.md | ||
dotfiles
Personal dotfiles managed with chezmoi — one repo, macOS and Debian Linux, multiple machines.
Primary remote: https://forgejo.patilla.es/patillacode/dotfiles.git
Mirror: https://github.com/patillacode/dotfiles
Fresh Install
One-liner (new machine)
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply --source ~/dotfiles https://forgejo.patilla.es/patillacode/dotfiles.git
This installs chezmoi, clones the repo, runs the interactive setup, and applies everything.
What the setup wizard asks
When running chezmoi init for the first time you'll be prompted for:
- Machine name — used throughout configs and prompts
- Shell —
zshorbash(Linux only; macOS always uses zsh) - Personal or work machine? — sets
personalorworktrait - Does it have a GUI / screen? — sets
guitrait; skips desktop-only packages on headless machines - Starship theme — choose from 13+ themes (default:
simple) - Git name & email — used in
~/.config/git/config - KeePassXC database path — full path to your
.kdbxfile - Font family & size — used in Ghostty and Zed (GUI machines only)
Answers are saved in ~/.config/chezmoi/chezmoi.toml and reused on subsequent runs.
Migrating from old setups
If the machine currently has the old GNU Stow dotfiles, remove the symlinks first:
# From the old dotfiles directory
cd ~/dotfiles
stow --delete .
# Remove the old repo
cd ~
rm -rf ~/dotfiles
Then proceed with the normal fresh install one-liner above.
If the machine has an older chezmoi setup instead:
chezmoi purge # removes ~/dotfiles source dir and ~/.config/chezmoi config
Then proceed with the fresh install one-liner.
How It Works
The trait system
Each machine selects a set of independent traits. Traits compose — a machine just has whichever apply.
| Trait | Question | Gets |
|---|---|---|
base |
Does this machine exist? | All CLI tools, dev tools, git, SSH, nvim, claude |
gui |
Does it have a screen? | Ghostty, Zed, GUI-only apps |
personal |
Is it mine for fun? | Personal identity, SSH keys, entertainment tools |
work |
Is it for work? | Work git identity, work rules |
personal + gui together also add entertainment: music/tv/twitch aliases, mpv, yt-dlp.
Each trait only lists what it adds — no duplication. The full set is resolved at template time by iterating all active traits.
Files are gated in .chezmoiignore — wrong-trait files are never deployed to disk.
OS differences
chezmoi handles macOS/Linux automatically:
- Packages: brew (+ casks on macOS) vs apt
- Shell: zsh on macOS; bash or zsh on Linux (your choice at init)
- GUI-only packages (casks) are skipped on Linux machines without the
guitrait
Per-machine overrides
To include an alias or config outside your traits without changing trait membership, edit ~/.config/chezmoi/chezmoi.toml:
[data]
include_aliases = ["music"] # pull in music.sh even on a work machine
exclude_aliases = ["tv"] # skip tv.sh
include_configs = ["mpv"] # deploy mpv config on a non-personal machine
exclude_configs = ["zed"] # skip zed config
Then chezmoi apply.
Quick Reference
dotfiles CLI (dt / dots)
# Sync & deploy
dotfiles sync # pull latest changes + apply
dotfiles push [msg] # commit source changes + push to remote
dotfiles apply [--dry-run] # apply configs to $HOME
dotfiles diff # preview what would change
dotfiles edit <file> # edit a managed file (opens in $EDITOR)
# Customization
dotfiles theme # interactive Starship theme picker (fzf)
dotfiles secrets # inject secrets from KeePassXC into ~/.env
# Info
dotfiles status # machine info, traits, managed file count
dotfiles info # active aliases, configs, tools
dotfiles utils # list all utility scripts and fzf functions
dotfiles doctor # run chezmoi diagnostics
# Recovery
dotfiles rollback # restore a previous snapshot (fzf)
chezmoi apply, chezmoi diff, and chezmoi edit ~/.zshrc all work directly too.
How To
Add a new managed file
chezmoi tracks source files, not symlinks — add a file to the source directory and it deploys on apply.
# Copy an existing file into the source dir
chezmoi add ~/.config/tool/config
# Or create it manually in the source dir
# dot_config/tool/config → ~/.config/tool/config
chezmoi apply
Check if a file is tracked
chezmoi status ~/.config/tool/config # shows status code if tracked, nothing if not
chezmoi managed | grep <filename> # search across all tracked files
Status codes: A added · M modified · D deleted · R re-added.
Modify an existing managed file
Edits go to the source directory; apply deploys them.
chezmoi edit ~/.zshrc # opens source file in $EDITOR
chezmoi apply
Or edit the source file directly in ~/dotfiles/ and run chezmoi apply.
Add a package
Packages are auto-installed when the list hash changes on chezmoi apply.
Edit .chezmoidata/packages.yaml — add to the right trait:
trait_packages:
base: # or gui / personal / work
- new-tool
- { name: x, apt: x-dev } # different name on apt
- { name: y, type: cask } # brew cask (macOS only)
- { name: z, type: cask, apt: z-app } # cask on macOS, apt name on Linux
Then chezmoi apply.
Remove a package
The install script only adds — it doesn't uninstall. Remove the line from .chezmoidata/packages.yaml, then uninstall manually with brew remove or apt remove.
Add a new alias file
Alias files live in dot_alias/ and are sourced based on active traits.
- Create
dot_alias/<name>.shin the repo - Add
<name>to the right trait in.chezmoidata/aliases.yamlundertrait_aliases chezmoi apply
Add an alias to an existing file
The alias files are plain shell files — just edit them.
chezmoi edit ~/.alias/git.sh
chezmoi apply
Remove an alias
Delete or comment out the line from the relevant file in dot_alias/, then chezmoi apply. The shell will stop sourcing it on the next session.
Set up a new machine
Run the one-liner from Fresh Install. The wizard asks the right questions and handles everything else.
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply --source ~/dotfiles https://forgejo.patilla.es/patillacode/dotfiles.git
Once packages are installed, run the interactive configuration wizard for a polished setup experience:
dotfiles setup
This reads all current values as defaults (safe to re-run at any time to reconfigure).
Update an existing machine after a repo change
Pull and re-apply — chezmoi diffs against deployed state and only touches what changed.
dotfiles sync
# or
git -C ~/dotfiles pull && chezmoi apply
Yazi keybindings
Press <Space> inside yazi to open a filterable keybinding overlay.
Key highlights:
| Key | Action |
|---|---|
<Space> |
Show all keybindings |
e / E |
Edit in $EDITOR / Zed |
d / D |
Trash / permanent delete |
v / V |
Toggle select / select all |
gg / G |
Top / bottom of list |
<C-u> / <C-d> |
Scroll half-page up/down |
{ / } |
History back/forward |
g. / g/ |
Go to home / root |
gs / gp |
Git status / pull |
<C-t> / q |
New tab / close tab |
[ / ] |
Prev / next tab |
R,G / R,W |
Video → GIF / Audio → FLAC |
R,m / R,j |
Bookmark here / jump to bookmark |
Media toggle: opening an audio or video file uses mpv-yazi — pressing the same file again stops playback; pressing a different file replaces it. Requires socat and jq.
Opener picker: pressing <Enter> on a video shows a picker (play / compress / GIF); on audio (play / FLAC). Single-key shortcuts bypass the picker for speed.
Switch yazi theme
Yazi uses catppuccin themes. Two scripts live in ~/.config/yazi/themes/:
# Download all catppuccin theme variants
~/.config/yazi/themes/download-themes.sh
# Switch to a specific theme (interactive or by name)
~/.config/yazi/themes/switch-theme.sh
These scripts are yazi-specific and not part of the dotfiles CLI.
Switch Starship theme
The prompt theme is set in chezmoi.toml and re-applied by chezmoi.
dotfiles theme # interactive fzf picker
Or manually edit ~/.config/chezmoi/chezmoi.toml:
[data.starship]
theme = "catppuccin"
Then chezmoi apply.
Available themes: simple · minimal · zenful · nerd-font-symbols · gruvbox · catppuccin · dracula · nord · tokyo-night · pastel · tops · totoro · ushuaia
Inject secrets from KeePassXC
Secrets are pulled on demand into ~/.env — they're never part of normal apply.
dotfiles secrets # prompts for master password once, writes ~/.env
Change font (Ghostty + Zed)
Both apps read font settings from chezmoi.toml via templates — one change updates both.
Edit ~/.config/chezmoi/chezmoi.toml:
[data.font]
family = "JetBrainsMono Nerd Font Propo"
size = 16
Then chezmoi apply.
Repository Structure
dotfiles/
├── .chezmoi.toml.tmpl # init wizard (prompts)
├── .chezmoidata/ # split data files:
│ ├── profiles.yaml # trait definitions
│ ├── aliases.yaml # trait_aliases (delta per trait)
│ ├── configs.yaml # trait_configs (delta per trait)
│ └── packages.yaml # unified cross-platform packages
├── .chezmoiignore # per-machine file exclusions (templated)
├── .chezmoiscripts/
│ ├── run_once_before_bootstrap.sh.tmpl
│ ├── run_onchange_install-packages.sh.tmpl # brew / apt
│ ├── run_onchange_install-uv.sh.tmpl # uv on Linux
│ ├── run_onchange_install-oh-my-zsh.sh.tmpl
│ ├── run_onchange_install-python-tools.sh.tmpl
│ ├── run_onchange_install-yazi-plugins.sh.tmpl # ya pkg add
│ └── run_after_apply-snapshot.sh.tmpl
│
├── dot_alias/ # → ~/.alias/
├── dot_claude/ # → ~/.claude/
├── dot_config/
│ ├── git/ # config.tmpl + nordhealth work identity
│ ├── ghostty/ # config.tmpl
│ ├── starship/ # 13 .toml themes
│ ├── zed/ # settings.json.tmpl
│ ├── yazi/
│ │ └── themes/ # catppuccin theme files + executable_download-themes.sh / executable_switch-theme.sh
│ └── atuin/ btop/ gh/ mpv/ nvim/ tmux/ yt-dlp/
├── dot_local/bin/ # → ~/.local/bin/ (all executable)
│ ├── executable_dotfiles # CLI wrapper for chezmoi
│ ├── executable_bak # timestamped file backup
│ ├── executable_extract # universal archive extractor
│ ├── executable_json-fmt # pretty-print JSON (jq wrapper)
│ ├── executable_myip # show public + local IP
│ ├── executable_port-check # check if host:port is open
│ ├── executable_mpv-yazi # toggle-play via mpv IPC (used by yazi)
│ ├── executable_vid-compress # shrink video file size
│ ├── executable_vid-convert # convert video formats
│ ├── executable_vid2gif # convert video to GIF (requires explicit output name)
│ ├── executable_vid2gif-auto # vid2gif wrapper with auto output name (used by yazi)
│ ├── executable_ffmpeg-trim # trim a video clip
│ ├── executable_img-convert # convert image formats
│ ├── executable_screen-cap # screen recording
│ ├── executable_git-clean-branches
│ ├── executable_tg-send # send Telegram messages
│ └── executable_download-urls # batch yt-dlp downloader
├── dot_oh-my-zsh/ # → ~/.oh-my-zsh/ (custom themes)
├── dot_vim/ + dot_vimrc # vim config
├── dot_zshrc.tmpl # → ~/.zshrc
├── dot_bashrc.tmpl # → ~/.bashrc
└── private_dot_ssh/ # → ~/.ssh/ (0700/0600)
Trait Reference
What each trait deploys:
base |
gui |
personal |
work |
|
|---|---|---|---|---|
| aliases | ai, atuin, docker, fzf, git, misc, ssh, system, tmux, utils | ghostty | music, tv, twitch (personal+gui only) |
— |
| configs | atuin, btop, claude, gh, git, nvim, starship, tmux | ghostty, zed | mpv, yt-dlp (personal+gui only) |
— |
| packages | atuin, bat, btop, chezmoi, duf, eza, fastfetch, fd, fzf, gcc, gh, git-delta, git-lfs, glow, gum, jq, n, neovim, prek, ripgrep, rtk, ruff, starship, tmux, uv, wget | ghostty, keepassxc, raycast, rectangle, sf-symbols, stats | cmatrix, ffmpeg, ffmpegthumbnailer, figlet, imagemagick, mpv, ollama, poppler, socat, streamlink, yt-dlp, firefox, jordanbaird-ice, nextcloud, telegram, transmission, vlc, zen | zen |
Secrets
Secrets are injected on demand via dotfiles secrets — never during normal apply/diff/sync. The command prompts for your KeePassXC master password once, then pulls all configured secrets into ~/.env.
Currently managed secrets:
- GitHub token — from
Code/dotfiles/github-pat(Password field) - Telegram bots — auto-discovered from
Code/dotfiles/tg-*entries
Telegram bot setup
- Create a KeePassXC entry
Code/dotfiles/tg-<botname>with the bot token as Password - In the Notes field, define chats (one per line):
chat-family: -1002457345563 chat-personal: 789012345 - Run
dotfiles secretsto inject into~/.env - Send messages:
tg-send <bot> <chat> <message>
Use tg-send --discover <bot> to find chat IDs — send a message to the bot first, then discover will list recent chats with their IDs.
Utility Scripts & Functions
All scripts are in ~/.local/bin/ (on $PATH), available on every machine. Run any script with -h for detailed usage. Run dotfiles utils for a full list.
Files & system
| Command | Description |
|---|---|
bak <file> |
Timestamped backup (file.bak.20260329-110000) |
extract <archive> |
Universal extractor (tar/zip/gz/bz2/xz/7z/rar/zst) |
mkcd <dir> |
Create directory and cd into it (shell function) |
json-fmt [file] |
Pretty-print JSON from file or stdin |
myip |
Show public and local IP addresses |
port-check <host> <port> |
Check if host:port is reachable |
Media
| Command | Description |
|---|---|
mpv-yazi <file> |
Toggle-play via mpv IPC — same file stops, new file replaces |
vid-convert <in> <out> |
Convert video formats (tries stream copy first) |
vid-compress <in> [out] |
Shrink video keeping reasonable quality |
vid2gif [-s width] <in> <out> |
Convert video to GIF (explicit output name required) |
vid2gif-auto <in> |
Convert video to GIF (auto-names output as <in>.gif) |
ffmpeg-trim <in> <start> <end> |
Trim a video clip |
img-convert |
Convert image formats (macOS sips) |
screen-cap |
Screen recording (macOS) |
Messaging & downloads
| Command | Description |
|---|---|
tg-send <bot> <chat> <msg> |
Send Telegram message via named bot and chat |
tg-send --discover <bot> |
List recent chats a bot can see |
download-urls <file> |
Batch download URLs with yt-dlp |
Git & dev
| Command | Description |
|---|---|
git-clean-branches |
Delete all non-protected local branches |
fzf functions
Interactive fzf-powered helpers sourced from ~/.alias/fzf.sh (all machines).
| Function | Description |
|---|---|
fbr |
Switch git branch (sorted by recent, includes remotes) |
flog |
Browse git log with diff preview |
fga |
Stage changed files interactively |
dexec [shell] |
Exec into a running docker container |
dstop |
Stop docker containers (multi-select) |
dlogs |
Tail docker container logs |
drmi |
Remove docker images (multi-select) |
fkill [signal] |
Kill processes (multi-select) |
fcd [dir] |
cd into subdirectories with preview |
fssh |
SSH into a host from ~/.ssh/config |
fenv |
Browse environment variable values |
fedit |
Edit config files in ~/.config/ or ~/.alias/ |