macOS dotfiles for JS/Python development.
Reading this as a reference? This is one person's personal setup. The steps below are his, for his machines — don't run them. If you're new to macOS, start with docs/macos-for-windows-devs.md instead. It explains the concepts and points back at the files here as examples.
Shell (bash), git, tmux, and editor configs.
- macOS
- Homebrew
-
brew install stow -
git clone <this repo> ~/.home-directory && cd ~/.home-directory, then set up the filter that keepsautoModeandmodelSettingsout of commits:git config filter.strip-local-settings.clean "jq --indent 2 'del(.autoMode, .modelSettings)'" git config filter.strip-local-settings.required true
autoModein.claude/settings.jsondescribes the environments you work in, and this repo is public. Claude Code rewritesmodelSettingswhenever you change a model's effort level. The filter drops both when the file is staged. Your copy keeps them. A checkout, stash, or reset writes the committed file back without them, so save those blocks first. -
git submodule update --init --recursive -
stow -R --no-folding --adopt -t ~ .Note:--adoptmoves any pre-existing files in~into the repo, overwriting the tracked versions. Checkgit status/git diffafterwards and reset anything you didn't mean to keep. -
Start a new shell (so
.bashrc.dsetsHOMEBREW_BUNDLE_FILE), then runbin/brew-install. -
Switch to Homebrew's bash. The Brewfile installs it, but macOS only accepts a login shell listed in
/etc/shells:echo "$(brew --prefix)/bin/bash" | sudo tee -a /etc/shells chsh -s "$(brew --prefix)/bin/bash"
Open a new terminal window, then check
echo "$SHELL". Apple's/bin/bashis stuck at 3.2 (GPLv3), so this is what gets a current bash. -
Create
~/.gitconfig.localwith your git identities..gitconfigincludes it, and stow doesn't manage it, so a fresh machine has no identity until you write this file. Copy docs/gitconfig-local.example and fill it in. Per-client identities go in real files under~/.config/git/, never in this repo. -
Link Karabiner's config directory by hand:
ln -s ../.home-directory/.config/karabiner ~/.config/karabiner.stow-local-ignoreskips this path, so stow won't do it for you. Karabiner rewriteskarabiner.jsonby renaming a temp file over it. That replaces a file symlink with a real file and strands the repo copy without saying so. Linking the directory keeps the rename inside the repo.
bin/run-tests runs everything. Arguments pass through to node, so
bin/run-tests --watch works.
Call it rather than node --test. Bare node --test skips dot directories
when it looks for tests, so it silently misses every test under .claude and
still reports a green suite. The runner names those paths.
Inspired by https://knowler.dev/blog/maintaining-dotfiles.