Customize
Theme tokens, per-tool customization knobs, and recipes for adding aliases, functions, and brew packages.
Everything here is plain text in this repo. Adding your own aliases, functions, package installs, or directory jumps is a one-line edit and a shell reload.
Your local config
Everything machine-specific — your NAS IP, NAS username, git identity, code directory, which optional features you want — lives in one file outside the repo: ~/.config/dotfiles/local.env. It’s mode 0600, gitignored, and written by the wizard on first install. Every script (and every install module) sources it at runtime via bin/lib/dotfiles-config.sh.
All supported keys
| Key | Default | Effect |
|---|---|---|
CODE_DIR | $HOME/Code | Where archive-project scans for repos and the dev alias jumps to |
GIT_USER_NAME / GIT_USER_EMAIL | empty | Written to |
HAS_NAS | false | Master switch. |
NAS_HOST | empty | IP or hostname. Substituted into |
NAS_USER | empty | Your account on the NAS — appears in SMB URLs |
NAS_SHARE_MEDIA | media | Share name for general file storage |
NAS_MOUNT_MEDIA | /Volumes/media | Where it mounts on this Mac |
HAS_TIMEMACHINE_NAS | false | Install the monthly Time Machine LaunchDaemon + helper scripts |
NAS_SHARE_TM | timemachine | Separate share for Time Machine (needs exclusive use) |
TM_SCHEDULE_MONTHLY | true | Replace Apple’s hourly schedule with 1st-of-month-at-03:00 |
ENABLE_SORT_DOWNLOADS | false | Install bin/sort-downloads |
SORT_DOWNLOADS_BACKGROUND | true | Run it via LaunchAgent (vs. manual sort-downloads only) |
ENABLE_ARCHIVE_PROJECT | false | Install bin/archive-project + its man page |
ARCHIVE_AFTER_MONTHS | 1 | Default threshold for “old enough to archive” |
Change a value
./install.sh --reconfigure $EDITOR ~/.config/dotfiles/local.env Both work. The wizard validates inputs (positive integers for thresholds, y/n for booleans) and re-renders the .inetloc Login Item if NAS settings changed. Hand-editing is faster for single-value changes; just run ./install.sh --only=symlinks,launchd afterward if you flipped a feature on/off so the gated modules pick up the change.
Reference
Where things live
| You want to add… | Edit this file |
|---|---|
| A zsh alias | zsh/.zshrc |
| A fish alias or one-liner | fish/config.fish |
| A fish function (takes args) | fish/functions/<name>.fish + entry in install.sh |
| A standalone script | bin/<name> + entry in install.sh (linked into ~/.local/bin) |
| A Homebrew package | Brewfile (or Brewfile.aerospace / Brewfile.omniwm for WM-only) |
| A starship prompt module | starship/starship.toml |
| A ghostty keybinding | ghostty/config |
| An aerospace shortcut | aerospace/laptop.toml and aerospace/docked.toml (keep both in sync) |
zoxide (smart cd) cheat-sheet
cd is rebound to zoxide. The database builds automatically as you navigate — no manual config. After visiting a directory once, you can jump there by any unique substring of its path.
| Command | What it does |
|---|---|
cd /full/path | Works exactly like the builtin — full paths are honoured first |
cd lumo | Fuzzy jump to the highest-scored dir whose path contains “lumo” |
cd code lumo | Multiple substrings — matches paths containing both |
cdi | Interactive fzf picker over your frecency list |
cd - | Previous directory (passes through to builtin) |
zoxide query foo | Show the path cd foo would jump to (no cd) |
zoxide remove <path> | Forget a directory — useful after deleting/moving it |
If you’d rather keep the builtin cd and use a separate command, remove --cmd cd from the zoxide init lines in zsh/.zshrc and fish/config.fish; zoxide then exposes z and zi instead.
Recipes
Step-by-step examples. Jump to: alias · function · brew package · reload.
Add a simple alias
Aliases are textual substitutions — they don’t take arguments. Use them for fixed-shape commands. For anything that needs an arg, use a function (next recipe).
alias serve="python3 -m http.server" alias serve="python3 -m http.server" Add a function (takes arguments)
When the alias needs to receive a port number, a path, or any user input, write a function instead. dev and killport in this repo are functions for exactly this reason.
{`mkcd() {
mkdir -p "$1" && cd "$1"
}`} {`function mkcd --description "mkdir + cd"
mkdir -p $argv[1]; and cd $argv[1]
end`} For the fish version, also add a symlink line to install.sh so a fresh machine picks it up — copy the pattern next to the existing killport.fish entry.
Add a Homebrew package
One line in the Brewfile — install.sh runs brew bundle against it so a fresh machine installs it automatically.
{`brew "ripgrep" # ultra-fast grep
brew "fd" # ultra-fast find`} Reload after edits
source ~/.zshrc exec fish brew bundle --file=Brewfile Fish functions placed under ~/.config/fish/functions/ are autoloaded on next invocation — no reload needed for those.
Useful Commands
SketchyBar
sketchybar --reload brew services restart sketchybar brew services stop sketchybar AeroSpace
aerospace reload-config dock # or undock aerospace list-windows --all Where to go next
- Configuration overview — every key in
local.envand how install modules read it. - Maintenance —
bin/update,clean-node-modules,bigfiles. - NAS workflow · Backup · macOS tweaks.