Skip to content

dotfiles

Opinionated macOS dotfiles managed with chezmoi.

macOS only. Assumes Homebrew, Apple Silicon paths (/opt/homebrew), and macOS-specific tools (pbcopy, mac-cleanup, etc.). Not tested on Linux.

What's included

Config Description
~/.zshrc Zsh entrypoint — modular, deferred, fast
~/.zsh/env.zsh Exports, PATH, editor
~/.zsh/aliases.zsh Shell aliases (eza, k8s, git, maintenance, etc.)
~/.zsh/functions.zsh Functions: mnt, pkg-add, pkg-cats, brewsync, comp-add, and more
~/.config/sheldon/plugins.toml Zsh plugin manager config
~/.config/starship.toml Prompt
~/.config/ghostty/ Terminal (config; Catppuccin via native dark/light theme switching)
~/.config/git/config Git: delta pager, diff3 merge style
~/.config/bat/ bat config + Catppuccin themes
~/.config/eza/ eza color theme (Catppuccin symlink)
~/.config/lazygit/ lazygit config + Catppuccin theme
~/.config/atuin/ Shell history config + Catppuccin themes
~/.config/opencode/opencode.json OmniRoute wired as opencode's default provider (omniroute/auto)
~/.hammerspoon/ Auto-reload config; theme sync on macOS appearance change; darkmode.lua auto light/dark by local sunrise/sunset
~/.local/share/navi/cheats/custom.cheat Custom navi cheatsheets (macOS, docker, kubernetes)

Runtime version management

Language runtimes are managed by mise rather than Homebrew, so versions can be pinned per project via .mise.toml:

Runtime Global version
node LTS
uv latest
ruff latest

Ruby is not pinned globally — add it per-project with mise use ruby@3.4 inside a project directory.

Install

On a fresh machine (installs Homebrew and chezmoi if needed, then applies dotfiles):

bash <(curl -fsSL https://raw.githubusercontent.com/drumandbytes/dotfiles/main/install.sh)

If Homebrew is installed but chezmoi isn't:

brew install chezmoi && chezmoi init --apply drumandbytes/dotfiles

If Homebrew and chezmoi are already installed:

chezmoi init --apply drumandbytes/dotfiles

Forking? Replace drumandbytes with your GitHub username. See Forking below.

After the initial apply, run the machine profile wizard to select packages and features:

dots-setup

dots-setup is an interactive fzf wizard that lets you choose a starting profile (work, personal, minimal, full) and then fine-tune individual packages. It writes ~/.config/chezmoi/chezmoi.toml and runs chezmoi apply.

Profile Included categories
work alt_tools, docker, kubernetes, dev_apps, macos_utils, macos_media
personal alt_tools, macos_utils, macos_cosmetic, macos_media, productivity, peripherals
minimal alt_tools only
full Everything

Package categories you can toggle:

Category What it installs
alt_tools Modern CLI replacements: bat, eza, fd, ripgrep, dust, duf, navi, xh…
onepassword 1Password app + op CLI (SSH agent + shell plugins wired in env.zsh) — opt-in, in no profile by default
docker Colima + Docker + Buildx + Compose (whole stack, no sub-toggles)
kubernetes kubectl + kubecolor always; helm, kubectx, k9s, kubeconform, mintoolkit, stern, kustomize, gcloud CLI, awscli individually toggleable
macos_utils Raycast, Hammerspoon, AltTab, logi-options+, NordVPN, UTM…
macos_cosmetic AirBattery, BoringNotch, Cork
macos_media Brave, Slack, Spotify, Telegram, IINA
dev_apps VSCodium, JetBrains Toolbox, opencode, DBeaver, GIMP, PHP + Composer, GitHub/GitLab CLI, Cloudflared, hcloud…
touchbar BetterTouchTool (TouchBar Macs only)
gaming Steam, Discord
productivity Notion, Obsidian, Grammarly, Calibre, Flux Markdown
peripherals 8BitDo, QMK Toolbox, BalenaEtcher, F3

On first apply, chezmoi automatically:

  1. Runs brew bundle --global to install all selected Homebrew packages
  2. Runs mise install to set up language runtimes and global npm tools
  3. Generates static init files and completions (~/.zsh/*_init.zsh, ~/.zsh/completions/)
  4. Seeds a Colima config (~/.colima/default/colima.yaml) optimised for Apple Silicon
  5. Generates personal.cheat for navi; fetches external assets (community cheats, editor/tool themes) via .chezmoiexternal

Forking

To use this as a base for your own dotfiles:

  1. Fork this repo on GitHub and clone your fork locally.

  2. Customise the package registry — dot_local/bin/executable_dots-setup is the central source of truth. CAT_ORDER, CAT_DESC, and CAT_PKGS define what the wizard shows:

    • pkg-cats — list all current categories and their packages
    • pkg-add <category> <package> — add a package to an existing category
    • pkg-group-add <category> <description> — create a new category
  3. Push your changes to your fork.

  4. Install on any machine — pass your GitHub username to install.sh (a bare username expands to username/dotfiles; a username/repo slug or full URL also works):

    bash <(curl -fsSL https://raw.githubusercontent.com/drumandbytes/dotfiles/main/install.sh) \
      yourusername

After the initial install, dots-push / chezmoi update sync against your fork.

Shell architecture

Startup is optimised for speed using zsh-defer and pre-generated static files:

.zshrc
├── env.zsh            # immediate — sets PATH, exports
│   └── ~/.zsh/local.zsh   # optional — machine-local secrets/overrides, untracked
├── functions.zsh      # immediate — defines functions
├── aliases.zsh        # immediate — defines aliases
├── sheldon.zsh        # immediate — pre-rendered plugin source (sheldon source)
└── *_init.zsh         # deferred  — tool hooks (atuin, zoxide, mise, …)

Tool inits (atuin, zoxide, direnv, navi, etc.) are pre-generated once rather than evaluated on every shell start. Regenerate them with mnt (full maintenance) or by running chezmoi apply after touching run_onchange_generate-tool-inits.sh.tmpl.

env.zsh sources ~/.zsh/local.zsh if it exists — an untracked, machine-local file for per-host shell overrides (extra PATH entries, additional op:// references, host-specific settings) that don't belong in the repo. Keep resolved secrets out of it; see Optional: 1Password for the reference + op run pattern.

Key functions & aliases

Command Description
mnt Full maintenance: sync dotfiles, brew upgrade, sheldon update, regenerate inits & completions, recompile, backup, reload
brew-up Homebrew update + upgrade + cleanup + tldr update, then refresh the static tool-init caches
pkg-cats List all package categories with their descriptions and package lists
brewsync Interactively promote untracked brew packages into the chezmoi-managed Brewfile
comp-add <tool> Auto-detect and add zsh completions for a new tool; persists to chezmoi source
uv-add <package> Install a global uv tool and persist it to run_onchange_uv-tools.sh
sh-add <user/repo> Add a deferred sheldon plugin; persists to sheldon config
pkg-add <category> <pkg> Add a package to a Brewfile category + dots-setup registry, commit included
pkg-rm <pkg> Remove a package from the Brewfile and dots-setup registry, commit included
tap-add <category> <tap> <pkg> Register a Homebrew tap and add a tap-qualified package in one step
pkg-group-add <category> <desc> Create a new package group across Brewfile, dots-setup, and chezmoi config
mise-add <tool> [version] Add a runtime to the global mise config and persist to chezmoi
help-cmd fzf search over all aliases and functions
fkill fzf process killer
fgb fzf git-branch checkout (previews each branch's log)
zsh-bak Zip backup of zsh config to ~/Backups/zsh/

dots-* aliases

Alias Command
dots-setup Run the machine profile wizard
dots-apply chezmoi apply
dots-diff chezmoi diff
dots-status chezmoi status
dots-edit chezmoi edit <file>
dots-add chezmoi add <file>
dots-push Push chezmoi source to remote
dots-log Last 20 commits in chezmoi source

Optional: Touch ID for sudo

When Touch ID for sudo is enabled, a one-time script writes /etc/pam.d/sudo_local — a macOS 14+ (Sonoma) file that survives OS updates. To re-run it:

chezmoi state delete-bucket --bucket=scriptState
dots-apply

Optional: 1Password

Enable the onepassword category in dots-setup to install the 1Password app and op CLI. When enabled, env.zsh wires up (each guarded, so it's a no-op if the file/socket is missing):

  • SSH agent — SSH_AUTH_SOCK points at 1Password's agent socket
  • Shell plugins — sources ~/.config/op/plugins.sh (run op plugin init <tool> to add one)
  • Secret references — if dots-setup says Claude is API-key billed and you choose to source it from 1Password, ANTHROPIC_API_KEY is set to its op://… reference, not the secret. Subscription (Pro/Max) users get nothing exported, so claude always uses subscription login.

Nothing resolved touches disk. Resolve a reference into a real value for one command with op run -- <cmd> (e.g. op run -- opencode to use the real Anthropic key for a session instead of OmniRoute).

Optional: OmniRoute

opencode is wired to OmniRoute as its default provider (omniroute/auto, see ~/.config/opencode/opencode.json), a local AI gateway that routes across whatever provider tokens/subscriptions you connect. Its settings live in OmniRoute's own local state (~/.omniroute/), not in this repo, so a fresh install or a new machine won't carry them over. Worth checking in the dashboard (localhost:20128/dashboard) after installing:

  • Cloud tunnel — "Cloud OmniRoute" relays the local gateway to the internet by default. Disable it (Home → Tunnels) unless you actually want remote access; opencode only needs localhost:20128.
  • DeepSeek Web provider — under Providers → Web Cookie Providers, "DeepSeek Web" is a scraped browser session against DeepSeek's consumer chat site, not a real API. It's known to leak raw DSML tool-call markup as garbled text instead of executing tools (also filed upstream against opencode: anomalyco/opencode#14050). If tool calls start showing up as visible junk text, disable this specific provider rather than "auto" mode as a whole — everything else keeps working. If it happens in an existing opencode session, start a fresh one (/new) too, since the model can imitate a leaked tool-call it already saw in that session's history.
  • OAuth-based providers (Amazon Q, Antigravity, Devin CLI, GitHub Copilot, etc.) route traffic through those tools' own subscription logins rather than real API keys — likely against those services' ToS, at risk to the linked account. Enable deliberately, not by default.

Optional: automatic dark mode

When macos_utils (Hammerspoon) is enabled, ~/.hammerspoon/darkmode.lua switches macOS between light and dark at local sunrise/sunset — computed offline from coordinates. dots-setup prompts for a city (fzf pick from world capitals, or custom coordinates) and two switch offsets, given in minutes relative to the event (negative = before, positive = after) — e.g. -30 sunset = go dark 30 min before sunset. Re-run dots-setup to change them.

History

Shell history is managed by atuin with sqlite backend and optional sync. Import existing history with:

atuin import auto
atuin sync

Day-to-day workflow

dots-apply              # apply pending changes
dots-diff               # preview what would change
dots-status             # show which files are out of sync
dots-edit ~/.zshrc      # edit a managed file and apply
dots-push               # push source changes to remote
chezmoi update          # pull latest from remote and apply

To add a new file to chezmoi management:

dots-add ~/.config/something

Adding packages and tools

dots-setup              # re-run wizard to change profile or toggle packages
pkg-cats                # list all categories and their packages
brewsync                # detect untracked brew packages and add them to the Brewfile interactively
pkg-add <cat> <pkg>     # add a package to a Brewfile category and the dots-setup registry
pkg-rm <pkg>            # remove a package from the Brewfile and dots-setup registry
tap-add <cat> <tap> <pkg>  # register a tap and add a tap-qualified package in one step
pkg-group-add <cat> <desc> # create a new package group (Brewfile + dots-setup + chezmoi flag)
mise-add <tool> [ver]   # add a runtime to the global mise config and persist it
comp-add <toolname>     # add a zsh completion; auto-detects syntax, persists to chezmoi source
uv-add <package>        # install a global uv tool and persist it to run_onchange_uv-tools.sh
sh-add <user/repo>      # add a deferred sheldon plugin and persist it to plugins.toml

To remove a package permanently: pkg-rm <package> — removes it from the Brewfile and dots-setup registry and commits. Then brew uninstall <package> locally and dots-apply to sync.

Navi

navi is a command-line cheatsheet tool. Press Ctrl+G mid-command to search cheatsheets and insert a command into the prompt. Or run navi to browse interactively.

On first chezmoi apply, run_onchange_navi-cheats.sh.tmpl generates ~/.local/share/navi/cheats/personal.cheat from your aliases and functions (regenerated whenever aliases.zsh or functions.zsh changes). The community cheat repos are fetched and refreshed weekly by chezmoi via .chezmoiexternal.toml.tmpl.

Source What it covers
personal.cheat All your aliases and functions, auto-generated
custom.cheat macOS system/network/defaults, docker/colima, kubectl/helm
denisidoro/cheats General shell cheatsheets
denisidoro/navi-tldr-pages tldr pages in navi format (~2000 commands)
tg-z/navi-cheats macOS-focused: brew, defaults, network tools
tsologub/navi-cheats kubectl, helm, docker (kubernetes only)

Theme

Catppuccin across ghostty, bat, delta, btop, and k9s — Macchiato (dark) / Latte (light).

Tool Theme location
ghostty ~/.config/ghostty/config (theme = dark:…,light:… — switches natively with macOS appearance)
bat ~/.config/bat/themes/ (Macchiato + Latte, loaded automatically)
delta inherits bat theme via ~/.config/git/config
eza ~/.config/eza/theme.yml (symlink: Macchiato or Latte) (alt_tools only)
lazygit ~/.config/lazygit/theme.yml (symlink: Macchiato or Latte)
atuin ~/.config/atuin/themes/ (Macchiato + Latte)
starship palette set in ~/.config/starship.toml (Macchiato or Latte)
zsh-syntax-highlighting ~/.zsh/catppuccin_*.zsh (sourced from env.zsh based on appearance)
btop ~/.config/btop/themes/ (all four flavours: latte, frappé, macchiato, mocha)
k9s ~/.config/k9s/skins/ (all flavours; follows macOS appearance via sync-theme) (kubernetes only)

Theme files (bat/btop/fresh .tmTheme/.theme/.json, k9s skins) are fetched and refreshed by chezmoi via .chezmoiexternal.toml.tmpl.

sync-theme (~/.local/bin/sync-theme) switches delta, starship, atuin, eza, lazygit, and k9s between Latte and Macchiato. It is called by Hammerspoon (~/.hammerspoon/init.lua) which watches AppleInterfaceThemeChangedNotification — so all tools switch instantly when you toggle macOS appearance. ghostty is not part of sync-theme; it follows the appearance natively.

Override manually with theme dark or theme light.

Troubleshooting

chezmoi update fails with merge conflicts or "git: exit status 1"

src=$(chezmoi source-path)
git -C "$src" fetch origin main
git -C "$src" checkout -B main origin/main
dots-apply

Or run mnt — it calls _chezmoi_sync as its first step which handles wrong branch, missing tracking, and diverged commits.

chezmoi apply shows an unexpected diff

Use dots-diff to review it, then overwrite to apply the source or skip to keep the current file. To pull the current state back into source: chezmoi re-add ~/.config/....

Re-run a one-time script (e.g. Colima config)

chezmoi state delete-bucket --bucket=scriptState
dots-apply

About

Personal macOS dotfiles managed with chezmoi — shell, Homebrew and app configuration, reproducible on a fresh machine.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages