Personal, portable developer environment — shell startup, XDG app configs, editors, terminals, and CI-backed quality checks. Designed to symlink or vend across machines (including nested submodule layouts) without one-off paths baked into the tree.
Automation can copy or symlink entire trees without per-file mapping:
config/— XDG-style application configs (Neovim, Ghostty, Zellij, Alacritty, Kitty, Oh My Posh themes, etc.). Paths inside these files avoid machine-specific locations where possible (e.g. Neovim usesstdpath()for cache/state; Alacritty theme imports use$HOME/.config/...).home/— Dotfiles meant for the home directory (e.g..zshrc,.bashrc,.tmux.conf,.vimrc). OS-specific zsh snippets live underhome/zsh/and are sourced fromhome/.zshrcafter resolving the repo root. Tmux 3.1+ can use~/.config/tmux/tmux.conf; this repo still ships~/.tmux.conffor broad compatibility.
home/.zshrc sets DOTFILES to the repository root by:
- Reading
~/.dotfiles_pathif it exists and still points at a tree that containshome/zsh/, or - Searching a few common locations once, then writing the result to
~/.dotfiles_pathso the next login avoids repeated filesystem checks.
Override DOTFILES in ~/.local_extras if your clone lives somewhere
else.
home/.zshrc exports standard defaults when unset (XDG Base Directory spec):
| Variable | Default |
|---|---|
XDG_CONFIG_HOME |
$HOME/.config |
XDG_DATA_HOME |
$HOME/.local/share |
XDG_CACHE_HOME |
$HOME/.cache |
XDG_STATE_HOME |
$HOME/.local/state |
Tools that respect these (including many terminals and Neovim) can find configs
under ~/.config without littering $HOME.
From the repository root:
-
./setup.sh— verifiesconfig/andhome/, runs git submodule helpers when.gitmodulesexists (safe to rerun), then runs optional headless Neovim Lazy/Tree-sitter steps whennvimis onPATH. -
./setup.sh --link-xdg-config— symlinks everyconfig/<app>/tree to$XDG_CONFIG_HOME/<app>/(default~/.config/<app>/). If you already have a real directory there, it is renamed to*.dotfiles-bak-<timestamp>first.
After linking: Ghostty, Kitty, Neovim, tmux module layout, etc.
resolve against ~/.config. home/.tmux.conf assumes
~/.config/tmux/includes/base.conf exists.
Some projects ship this repo under a nested path (for example
src/dotfiles/ in macOS-setup-scripts). In that layout, keep these in mind:
-
DOTFILESis the dotfiles checkout root, not the parent repository. Your shell resolves it via~/.dotfiles_path(often written by parent provisioning scripts), auto-discovery under~/Projects/dotfiles, orexport DOTFILES=…in~/.local_extras. If you move from a submodule path to a standalone clone, refresh~/.dotfiles_pathorDOTFILES. -
Two Git histories: Changes land in this repository first. The parent then records the new submodule commit with
git add <submodule-path>and its own commit.git submodule update --init(or--remote) only fetches what the parent has pinned. -
Parent scripts may copy a subset of
config/. For example, one phase might install terminals and another Neovim; that is not always the fullconfig/tree. To mirror everything under~/.config/<app>/, run from this repo (submodule directory is fine):./setup.sh --link-xdg-config
That is especially relevant if
home/.tmux.confuses the modular loader (source-file ~/.config/tmux/...) — you needconfig/tmux/present under~/.config/tmux(symlink or copy). Older inline-onlyhome/.tmux.conffiles self-contained without~/.config/tmuxare an exception. -
Node tooling for this repo (Prettier, markdownlint, etc.) uses
package.jsonhere. A parent project’snpm ciat its own root does not replace(cd path/to/dotfiles && npm ci)when you lint or develop inside the dotfiles tree.
Pull requests run reusable workflows for linting / formatting (StyLua,
ShellCheck, Prettier, and the rest of the shared quality matrix) and security
(Semgrep, TruffleHog). Dependabot keeps GitHub Actions references current.
Contribution and automation notes for agents live in AGENTS.md.
- Alacritty —
config/alacritty/ - Ghostty —
config/ghostty/ - Kitty —
config/kitty/ - Zellij —
config/zellij/ - Oh My Posh — Prompt themes (
config/oh-my-posh/)
- Neovim —
config/nvim/; plugins via lazy.nvim. Options live inlua/config/lazy.lua(install.missing = true,change_detection.enabled = falsefor non-interrupting installs and automation).lazy-lock.jsonis committed so plugin revisions match across machines. Example headless sync:XDG_CONFIG_HOME=/path/to/this/repo/config nvim --headless "+Lazy! sync" +qa - VS Code —
vs-code/
- Taskwarrior —
taskwarrior/(includes a themes submodule)
These are my personal configurations. Feel free to browse and adapt them for your
own use. Machine-specific settings can live in ~/.local_extras, which is sourced
from home/.zshrc and home/.bashrc when present.
MIT License — see LICENSE for details.