xcode-select --install # if not already prompted
git clone https://github.com/<you>/dotfiles.git ~/code/dotfiles
cd ~/code/dotfiles
./setup.sh
exec zshsetup.sh is idempotent — re-run it any time. See MIGRATION.md
for the credentials and machine-local state that must be moved by hand.
This repo installs machine-level tooling and config only. Project
dependencies (postgres, redis, docker, cloud CLIs, browser drivers, ...) belong
in each project's own Brewfile — e.g. ~/code/patch/Brewfile — not here.
setup.sh— installs core tooling (via Homebrew +Brewfile) and symlinks configs into your home directory.Brewfile— Homebrew bundle for CLI tools and casks.MIGRATION.md— new-machine checklist for everythingsetup.shcan't automate.git/gitconfig— Git defaults + aliases; includes~/.gitconfig.localfor machine-specific overrides.gitignore_global— global ignores.gitattributes— global attributes (line-ending normalization).
zsh/— Zsh config (zshenv,zshrc,aliases.zsh,functions.zsh).config/— XDG-style app configs (starship.toml,ghostty/config,zed/settings.json).launchd/— user launch agents. Copied (not symlinked) into~/Library/LaunchAgentsand bootstrapped bysetup.sh.
toolchains/— tool/runtime config (mise.toml,default-npm-packages).scripts/— one-off scripts (e.g. macOS defaults).ai/— agent instructions and configs (AGENTS.global.md,codex.config.toml,conductor.settings.toml,opencode.json).- User-level files are symlinked into
$HOMEbysetup.sh(e.g.claude-settings.json→~/.claude/settings.json). - Repo-level files for this repo live here too and are symlinked back to the root:
claude-settings.local.json→.claude/settings.local.json,claude-skills/→.claude/skills/,conductor.settings.local.toml→.conductor/settings.local.toml.
- User-level files are symlinked into
-
Ruby is not pinned globally.
toolchains/mise.tomlpins only Node; each project's.ruby-versiondrives the Ruby version via mise. -
opencodecomes fromanomalyco/tap, which Homebrew treats as untrusted.setup.shtaps and trusts it before runningbrew bundle. -
Global npm packages go in
toolchains/default-npm-packages(symlinked to~/.default-npm-packages) so they survive a Node version change. -
~/.ssh/allowed_signersis generated, not tracked. It is a trust list — it decides which keys git accepts as valid signers — and this repo is public, so it should not be editable by pull request.setup.shrebuilds it from your GitHub-published signing keys (a public, unauthenticated endpoint), falling back to the local key when offline. Old keys keep verifying as long as they stay registered on GitHub; any manually added lines are preserved across regeneration. -
Caps Lock is remapped to Escape by a launch agent (
config/launchd/com.brennan.dotfiles.capslock-escape.plist) rather than System Settings, so it covers external keyboards too.hidutilremaps only last until reboot, hence the agent. To turn it off:launchctl bootout gui/$(id -u)/com.brennan.dotfiles.capslock-escape && hidutil property --set '{"UserKeyMapping":[]}'(and delete~/Library/LaunchAgents/com.brennan.dotfiles.capslock-escape.plistsosetup.shdoesn't reinstate it). -
cmd-dtoggles Do Not Disturb, set inscripts/macos_defaults.shvia macOS's own (normally unassigned) shortcut for it — symbolic hotkey175, the one System Settings > Keyboard > Keyboard Shortcuts > Mission Control writes to. No hotkey daemon or Shortcuts.app detour needed.Because it's a system-wide hotkey it takes precedence over every app's own
cmd-d: Ghostty's split-right, Zed's select-next-match, Chrome's Add Bookmark, Finder's Duplicate, "Don't Save" in save sheets. Change the combo by editingparametersin that script, or drop the binding with:defaults delete com.apple.symbolichotkeys AppleSymbolicHotKeys 175followed by/System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -u.
uq— unquarantine a Homebrew-installed app or binary.- Examples:
uq chromedriveroruq /Applications/SomeApp.app
- Examples: