Personal macOS dotfiles and bootstrap scripts.
Brewfile- Homebrew packages, casks, npm/go/uv tools, and VSCode extensions.claude/- Claude Code settings, custom skills, the globalCLAUDE.md, and hooks.hooks/dotfiles-guard.shreminds agents to put machine settings into the repo: right after a command that changes the system (defaults write,brew install,pmset, ...), and on session exit if the repo has uncommitted or unpushed work.git/- tracked Git config; local-only values are included from~/.gitconfig.localif that file exists.deltais the pager, so every diff,git show,git log -p,git blameandgit add -pcome out syntax-highlighted, with file names and line numbers asvscode://links. Branch review happens inmerl --review(themrfzf script it replaced is gone). The selected model and effort level (model,effortLevel,modelSettings) never reach the repo: a clean filter from.gitattributesstrips them ongit add, so switching models in the UI does not make the repo dirty.install.shenables the filter.hammerspoon/- Hammerspoon config (Shift+Tab toggles plan/bypass mode in Claude).init.luaalso loads~/.hammerspoon/local.luawhen it exists: machine-local config that stays out of the repo.ghostty/- Ghostty terminal config, symlinked to~/.config/ghostty/config.iterm/- exported iTerm profile JSON for manual import.mailctl/-mailctl, an IMAP client for agents and for hand use; symlinked into~/.local/bin. Mailboxes are described in~/.config/mailctl/accounts.toml(not tracked), passwords live in the Keychain under themailctlservice.kimi/-kimi-task, Claude's way to hand one task to Kimi Code (kimi -pin the current directory), symlinked into~/.local/bin.guard.tomlis a hook the script appends to~/.kimi-code/config.tomlon first run: underkimi-taskKimi cannot commit, push, stash or switch branches.macos/-defaults.shfor appearance, menu bar, Finder, keyboard and input sources, screenshots, sound, Dock, and Mission Control.power.shfor sleep timers and the lock screen; it is separate because it needssudoand the login password.vscode/- VSCode settings and keybindings.zsh/- zsh startup config (.zshrc,.zprofile) and aliases.
Preview actions without changing the system:
./install.sh --dry-runInstall everything from the Brewfile, back up existing config files, and create symlinks:
./install.shApply macOS defaults as well:
./install.sh --macosSleep timers and the lock screen are behind their own flag, because that step is interactive - pmset asks for sudo and sysadminctl asks for the login password:
./install.sh --powerThe installer backs up existing files into ~/.dotfiles-backups/<timestamp>/ before replacing them with symlinks. This includes .zshrc and .zprofile.
It also installs oh-my-zsh when ~/.oh-my-zsh is missing - the tracked .zshrc sources it, and Homebrew does not ship it.
xcode-select --install- Install Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - Clone this repo:
git clone https://github.com/Maksim-Burtsev/dotfiles.git ~/open-source/dotfiles - Adopt any app that is already installed outside of brew, otherwise
brew bundleaborts on "There is already an App at ...":brew install --cask --adopt <name>
- Preview, then install with macOS defaults:
Then apply the power settings - kept separate because they prompt for passwords:
cd ~/open-source/dotfiles && ./install.sh --dry-run && ./install.sh --macos
./install.sh --power
- Optional:
$(brew --prefix)/opt/fzf/install --key-bindings --completion --no-update-rc- creates the~/.fzf.zshthat.zshrcsources. - Create
~/.zshrc.localwith machine-local values (see Local Values below). - iTerm: Settings → Profiles → Other Actions → Import JSON Profiles →
iterm/profile.json. - Grant Hammerspoon Accessibility permission in System Settings → Privacy & Security → Accessibility. Without it
hs.eventtapsilently does nothing and Shift+Tab will not switch Claude modes. - Run
claudeand sign in. Plugins are restored fromenabledPluginsin the tracked settings. - VSCode extensions are already installed by
brew bundle- no extra step.
./sync.shRegenerates the Brewfile from the current machine, restores the ~/.claude/settings.json symlink if Claude Code overwrote it, and scans for secrets. Everything else is symlinked, so it needs no syncing. Run before committing.
This repository stores public configuration only. Keep machine-local or sensitive values outside the repo:
~/.zshrc.local- sourced last by the tracked.zshrc. Machine-local exports andPATHentries go here.~/.gitconfig.local- included by the tracked.gitconfigwhen it exists. The installer copies an existing untracked~/.gitconfighere, with mode 600.- local
.envfiles
A gitleaks pre-commit hook scans staged content and blocks the commit if it finds a secret. It is enabled by install.sh via core.hooksPath - hooks are not carried over by git clone, so a fresh clone needs the installer to run once. The .gitignore only filters filenames; the hook is what actually inspects file contents.