configs and systems preferences for all the machines i frequent now and in the future.
obviously you want to read the best part... emacs-config.org — and its nvim counterpart: editors/nvim/README.md with the emacs parity keymap doc.
| dir | contents |
|---|---|
editors/ |
emacs config (emacs-config.org), neovim config (editors/nvim), ideavimrc, editorconfig, jetbrains plugins |
shells/ |
zsh + bash profiles/rc files, inputrc, the digitalnomad zsh theme |
utils/ |
gitconfig, tmux.conf, ghostty + karabiner + espanso config, ssh_config, agent skills, T3 Code, Thunderbird, misc tool config and scripts (project-ruby-exec, autogit.sh, ...) |
omarchy/ |
owned omarchy customizations (hypr keymaps/input, omarchy-shell bar config, moom config, ghostty config, omarchy-moom script, plugin patches) — see omarchy/README.md |
scripts/ |
bootstrap-mac.sh, doctor.sh, weekly-update.sh, omarchy-post-update.sh, macos-defaults.sh, links.conf, npm/gem package lists (deploy.sh lives at the repo root, like the Brewfile) |
.github/ |
CI: shellcheck, links.conf lint, and syntax checks run on push/PR |
the bootstrap-mac.sh script is designed to be run once for initial setup, although it should remain safe to re-run if interrupted.
git clone https://github.com/chadhs/dotfiles.git ~/dotfiles
cd ~/dotfiles
sh scripts/bootstrap-mac.shit will:
- wait for Xcode Command Line Tools
- install Homebrew if needed
- install packages from the root
Brewfile(brew bundle) - apply macOS defaults (
scripts/macos-defaults.sh) - run
deploy.shfor symlinks / shell setup - optionally switch your login shell to Homebrew zsh
the Brewfile lives at the repo root (not under scripts/). that matches Homebrew’s usual layout so cd ~/dotfiles && brew bundle works without extra flags, while scripts/weekly-update.sh still passes --file explicitly.
assumes omarchy is already installed. the deploy step covers packages the omarchy image doesn't include, links the shared configs, and offers to switch the login shell to zsh.
git clone https://github.com/chadhs/dotfiles.git ~/dotfiles
cd ~/dotfiles
sh deploy.shnotes on omarchy-managed configs (deliberate split):
- omarchy owns: tmux config (XDG), hyprland look'n'feel,
monitors.lua(machine-generated) — the repo does not manage these on linux. (ghostty is repo-owned on linux too — see the slider caveat in omarchy/README.md.) - the repo owns (linux-scoped in
scripts/links.conf): git config + hooks, ssh config, shells (~/.profile, zsh chain), nvim, emacs, editorconfig, agent skills, and the owned omarchy customizations inomarchy/(hyprbindings.lua/input.lua, shell bar config, moom, Vicinae). SUPER+SPACE is Vicinae (apps, web-search fallbacks, Search Files); SUPER+ALT+SPACE is the Omarchy menu. AUR apps (vicinae-binand the agent desktop tools) are listed inomarchy/aur.packagesand installed bydeploy.sh; see omarchy/README.md. ~/.bashrcstays omarchy's on linux; the repo's minimal bashrc is mac-only.- tmux auto-attach in zsh only fires for SSH sessions now, so desktop terminals aren't swallowed.
the window switcher (switcharoo) and window overview (switchboard) are plugin-manager plugins; switcharoo carries a local patch snapshotted in omarchy/plugins/patches/ — re-apply it after omarchy plugin update — see omarchy/README.md.
- per-project git identity works as on the mac:
~/.gitconfig→~/.gitconfig-local→~/.gitconfig.d/*(includeIfper project dir). gitconfig and ssh_config are small per-OS forks (utils/gitconfig_linux,utils/ssh_config_linux) — keep them in sync with the mac files. - per-project gh tokens flow through direnv: project
.envrcfiles exportGH_TOKEN/GITHUB_TOKEN, and the oh-my-zshdirenvplugin (linux zsh branch) loads them per directory. usedirenv exec <repo-root> gh ...when a token must be guaranteed (see thegit-host-authskill). - git over SSH uses per-account keys via
core.sshCommandin~/.gitconfig.d/*— copy the keys manually to~/.ssh/on a new machine (machine-local, never in the repo), e.g.~/.ssh/chad-mac_rsa. - keep SSH agents from changing the selected Git account: each account file should use
ssh -o IdentitiesOnly=yes -i ~/.ssh/<account-key>forcore.sshCommand. The template includes this flag. These files are copied only once, so update existing local account files manually while retaining their machine-specific key paths. A setup agent should be scoped to its command, e.g.ssh-agent bash -c 'ssh-add "$HOME/.ssh/id_ed25519" && exec your-setup-command', rather than replacing the current shell’s agent. - git over HTTPS has no credential helper on linux by default; if ever needed, set
helper = !gh auth git-credentialin~/.gitconfig-local(it composes with the direnv token flow) — commented recipe inutils/gitconfig-local. - before linking,
deploy.shmoves any real (non-symlink) files at repo-managed targets aside to<target>.bak-omarchy(never overwritten, machine-local) — stock omarchy configs (~/.config/nvim,~/.config/emacs, the owned omarchy files, bin scripts) are preserved and the links take over cleanly.
the deploy.sh script is designed to setup base packages and symlinks; it is also called by the bootstrap script.
sh deploy.sh is idempotent and safe to re-run for symlink maintenance (prefer running it intentionally, not as a login hook).
all managed symlinks and copy-once baseline files are defined in scripts/links.conf — the single source of truth shared by deploy.sh (applies them) and scripts/doctor.sh (verifies them). to manage a new config file, add a line there rather than editing the scripts. run with DOTFILES_LINKS_ONLY=1 sh deploy.sh to apply links without the repo update or package installs.
shared skills live in utils/agents/skills/. after deploy.sh, Codex, Cursor, OpenCode, and Copilot discover them in ~/.agents/skills; Claude uses ~/.claude/skills. T3 threads use their underlying agent's skills. see utils/agents/README.md.
machine-only skills (e.g. company-specific) go in ~/.agents/skills-local/. re-run deploy.sh after adding one so it is linked into the merge dir. a local skill with the same name as a shared skill wins on that machine. deploy also drops skill names from the merge dir that no longer exist in shared or local.
T3 Code (OpenRouter via OpenCode, plus themes) is documented in utils/t3-code/README.md. on omarchy, deploy.sh installs it from omarchy/aur.packages.
scripts/weekly-update.sh is the single full maintenance entry point: brew upgrade, Brewfile reconcile, Mac App Store apps, and global npm/gem packages.
sh scripts/weekly-update.sh (safe to run from any cwd)
for ad-hoc brew/cask/mas updates from a shell, use the aliases: brewup, caskup, masup (npm/gem globals are handled by weekly-update)
sh scripts/doctor.sh verifies this machine still matches what deploy.sh sets up: symlinks intact and pointing at the repo, copy-once baseline files present (warns on drift from the repo version), git identity configured, toolchain present, Brewfile packages installed, and agent skills linked. FAILs mean broken setup (usually re-run deploy.sh); WARNs are informational. safe to run anytime, from any cwd.
the same lint/syntax checks (shellcheck, links.conf validation) also run remotely on every push/PR via .github/workflows/ci.yml.
sh scripts/omarchy-post-update.sh runs after any omarchy update or omarchy plugin update: it re-applies the local switcharoo patch if the plugin update wiped it (restarting omarchy-shell), verifies the switcher chords/shortcuts and switchboard service are live, checks hyprctl configerrors, flags shell.json/hyprland.lua drift against omarchy's current templates, and finishes with a doctor pass. exits non-zero on FAILs; safe to re-run. see omarchy/plugins/patches/README.md for the patch itself.
things that can't be automated from the shell, in rough order:
- 1Password SSH agent — System Settings → 1Password → enable SSH agent (then set
IdentityFile/IdentityAgentin~/.ssh/config.d/ssh_config). this replaces fetching keys from the vault by hand. - sign into 1Password, iCloud, and the App Store —
masandscripts/weekly-update.shneed a signed-in App Store. - Karabiner-Elements permissions — grant the system extension and Input Monitoring when macOS prompts (System Settings → Privacy & Security).
- espanso — grant Accessibility permission, then enable it as a login item.
- Emacs.app first launch — if Gatekeeper complains, right-click → Open (cask builds are signed but not always notarized).
- PopClip / Moom / other cask apps — grant Accessibility permissions as prompted on first launch.
sh scripts/doctor.sh after finishing to confirm everything landed.
MacVim is no longer installed. for occasional GUI/Finder opens, use Neovide (installed via the Brewfile); it shares this repo's init.lua, so colors and plugins match terminal nvim.
- Finder → right click file → Open With → Neovide
- (optional) set as default for a file type via Get Info → Open with → Change All
this repo also contains other utility scripts, editor settings, etc... feel free to use anything you find useful. ^_^
where possible run the latest stable version via homebrew as a base version. if you need a specific version for development use a version manager or docker.
- node@24
- corretto21 (amazon jdk)
- postgresql@17 (lives commented-out in the Brewfile; uncomment it on a machine when you actually need it)
(node@24 and corretto21 are pinned in the Brewfile; keep this list in sync with it.)
create a ~/.box-name to override the host name that is used for display purposes in zsh