Configurations for Neovim, kitty, git, and other various developer tools.
This repo includes a pnpm + Vite+ monorepo for TypeScript tools.
tools/scripts # Standalone TS scripts (linear-edit)
tests/e2e # Terminal e2e tests (kitty, nvim)
vp install # install dependencies
vp check # format + lint + typecheck
vp test # run tests
vp run build -r # build all packagesxcode-select --installgit clone https://github.com/pattobrien/dotfiles.git ~/dev/pattobrien/dotfilesNOTE: dotbot is a utility app that
supports syncing the settings of various applications to dotfiles (e.g. kitty,
skhd).
# symlink dotfiles into ~ and create ~/dev
sh ~/dev/pattobrien/dotfiles/install
# essential installs and setups
sh ~/dev/pattobrien/dotfiles/install homebrew
sh ~/dev/pattobrien/dotfiles/install essentials
sh ~/dev/pattobrien/dotfiles/install 1password
sh ~/dev/pattobrien/dotfiles/install macos
sh ~/dev/pattobrien/dotfiles/install mise
sh ~/dev/pattobrien/dotfiles/install xcode
# optional installs (personal, work, runner, server)
sh ~/dev/pattobrien/dotfiles/install personal
# VS Code extensions (run after essentials/personal so the `code` CLI exists)
sh ~/dev/pattobrien/dotfiles/install vscodeNote: Some macOS settings (e.g. mouse/trackpad scaling, key repeat) only take effect after a logout or restart once the
install macosstep has run.
Sets permissions for required files (only required once on the system)
chmod +x ~/.local/scripts/tmux-sessionizerSettings snapshots from the previous MacBook live in two places:
In this repo — .config/macos-defaults/exports/ has macos-defaults YAML
dumps for Raycast, Shottr, superwhisper, FluidVoice, and eul. Apply each with:
macos-defaults apply ~/.config/macos-defaults/exports/<app>.yamlThen restart the app (or log out/in). Also copy the FluidVoice custom vocabulary into place:
mkdir -p ~/Library/Application\ Support/FluidVoice
cp ~/dev/pattobrien/dotfiles/.config/fluidvoice/parakeet_custom_vocabulary.json \
~/Library/Application\ Support/FluidVoice/A full snapshot of everything that was installed on the old machine (beyond
the curated personal/work profiles) is in brew/all/Brewfile:
brew bundle --file=~/dev/pattobrien/dotfiles/brew/all/BrewfileIn the private repo —
pattobrien/machine-backup
holds anything too sensitive or personal for this public repo:
raycast/*.rayconfig— the official Raycast export (extensions, snippets, quicklinks, hotkeys, extension tokens). Import via Raycast Settings → Advanced → Import. Prefer this over the raycast.yaml defaults dump.shottr/shottr-full.yaml— unredacted Shottr defaults including the license key (kc-license), which is stripped from the public export. Apply this one instead ofexports/shottr.yamlon a trusted machine.chrome/— Bookmarks, Preferences, and extension ID lists for all three profiles, in case Chrome profile sign-in sync misses anything.superwhisper/— defaults plist plus agent/database dirs (models re-download on first launch).zsh_history— shell history from the old machine.
SSH keys are intentionally absent: auth goes through the 1Password SSH agent, so signing into 1Password (step 3) restores SSH access.
Switch between Claude Code accounts with cswap switch.
Dumps a snapshot of all brew-installed applications. VS Code extensions live in
their own Brewfile (brew/vscode/Brewfile), so they are dumped separately.
# personal profile (formulae/casks/mas — excludes VS Code extensions)
brew bundle dump --force --describe --no-vscode --file=~/dev/pattobrien/dotfiles/brew/personal/Brewfile
# VS Code extensions
brew bundle dump --force --vscode --file=~/dev/pattobrien/dotfiles/brew/vscode/Brewfile
scripts/maintainruns both dumps for you (and preserves the vscode Brewfile comment header).
Shortcuts are split across layers, each scoped to a specific context.
- Terminal Cmd+key — high-frequency multiplexer actions (tabs, panes,
agents, popups, clear)
- Defined in: Kitty (
kitty.conf), Ghostty (config), Herdr (.config/herdr/config.toml), tmux (.tmux.conf), zsh (zshrc) - Flow: terminal sends an F-key escape sequence → whichever multiplexer is
running (Herdr day-to-day, or tmux) intercepts it → runs the equivalent
action. Herdr only recognizes F1–F12 plus modified F-keys
(
CSI <code>;<mod>~) and CSI-u chords — bare F13+ sequences (CSI 25~+) are invisible to it, so overflow slots useshift+F5-style encodings. - Herdr highlights:
Cmd+A/Cmd+N/Cmd+Lopen-or-create claude / nvim /pnpm devtab layouts (same roles as the old tmux bindings, via the herdr-ensure-tab plugin; layouts in.config/herdr/plugins/config/herdr-ensure-tab/layouts.toml, also in the herdr-plus quick-actions picker as Open Agent / Open Neovim / Dev Server),Cmd+[/Cmd+]cycle agents,Cmd+Shift+[/]cycle tabs,Cmd+1..9tab N,Cmd+T/Wnew/close,Cmd+;last pane,Cmd+Shift+D/Cmd+Shift+Njump to the dotfiles / notes workspaces,Cmd+Shift+;back to the last project workspace (scripts/herdr-workspace-jump),Cmd+Eworktrees,Cmd+Dhunk diff of the working tree in a split (herdr-plugin-hunk; staged/branch variants in the palettes, also onprefix+d),Ctrl+Alt+H/J/K/Lpane focus (direct, no relay). Displaced to prefix mode:prefix+ojump to agent needing attention,prefix+shift+nnew workspace,prefix+btoggle sidebar - Avoid overriding:
- Cmd+Q/H/M/W/N (macOS window mgmt)
- Cmd+C/V/X/Z (clipboard)
- Cmd+Space/Tab (Raycast, app switcher)
- Cmd+, (preferences)
- Defined in: Kitty (
- Clicked
file://URLs — open in the Neovim of the workspace that owns the file, at its line and column, instead of in Cursor- Defined in:
shed/tools/herdr-open-file(Herdr[[link_handlers]], linked withherdr plugin link), and.config/kitty/open-actions.confpointing at the same script Ctrl+clickis the Herdr gesture (captured mouse reports can't tell Cmd-click from a plain click);Ctrl+Shift+clickis the one kitty keeps for itself even while Herdr has the mouse. Herdr only seesfile://through OSC 8 metadata; kitty also detects it as plain text
- Defined in:
- Terminal Cmd+Shift+key — less frequent or destructive terminal actions
- Defined in: same as above (Kitty, Ghostty, tmux)
- Same F-key relay pattern as Cmd+key
- Hammerflow (F18 leader) — system-wide app switching and cross-app
workflows
- Defined in:
hammerflow.toml - F18 is mapped from Right Cmd via Karabiner
- Defined in:
- Hammerspoon direct hotkeys — system-wide shortcuts that need scripting
logic
- Defined in:
hammerspoon/init.lua
- Defined in:
- Karabiner — hardware-level key remaps (Caps Lock → Esc/Ctrl, Right Cmd →
F18)
- Defined in:
karabiner/karabiner.json
- Defined in:
- Neovim — editor keymaps (leader = Space)
- Defined in:
nvim/lua/pattobrien/remap.lua,nvim/after/plugin/*.lua
- Defined in:
On macOS Sequoia, apps can get stuck in a limbo permission state
(auth_value=5) in the TCC database, causing the "would like to access data
from other apps" dialog to reappear on every restart.
Before running the fix: quit the affected apps and dismiss any pending "access data from other apps" dialog first. While a prompt is on screen (or the app is running), macOS keeps re-writing the entry back to the
5limbo state, which clobbers theUPDATEbelow. If an entry reverts to5right after you fix it, a live prompt/app is the cause — close it and re-run.
Check for stuck entries:
sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db \
"SELECT client, auth_value FROM access WHERE service = 'kTCCServiceSystemPolicyAppData' AND auth_value = 5;"Fix all stuck entries:
sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db \
"UPDATE access SET auth_value = 2 WHERE service = 'kTCCServiceSystemPolicyAppData' AND auth_value = 5;"This sets the permission to "allowed" (2) directly, which persists across
reboots. Using tccutil reset does not work — it deletes the entry, causing
macOS to re-create it in the same broken state.
- Add zsh config
- Add Brewfile
- Add NVIM config
- Add tmux config
- Add kitty config
- Separate brew packages into separate files
- Clean up outdated /scripts/ folder
- BUG: tmux requirement in .zshrc causes terminal crash when tmux is not yet installed
- Add VSCode config
- Steps for initializing TMUX plugins
- setup 1password in case passwords are needed for app installations
- can
xcode-select --installbe run from the install script? - does asdf have a zsh autocomplete plugin?
- Raycast settings import script (Cloud Sync is premium; the exported
.config/macos-defaults/exports/raycast.yamlis currently never applied)
- existing real dotfiles (e.g. a stock
~/.zshenv) are backed up to<file>.bakbefore linking, so the firstinstallno longer fails on a fresh/migrated Mac — seescripts/backup_dotfiles.zsh - error: zshrc sourced oh-my-zsh.sh before it existed —
setup_omz.zshnow installs Oh My Zsh first
/Users/fern/.zshrc:source:97: no such file or directory: /Users/fern/.oh-my-zsh/oh-my-zsh.sh
- brew: too many apps were installed
- should maintain a
workset of apps
- should maintain a
- mac settings
- mouse/trackpad
- window / desktop transition
- finder settings
- apple account signed in? (should this just be a part of the get started guide?)
- accessibility/privacy settings per-app (e.g. Zoom needs screen-share access)
- settings for apps that open on startup
- BetterTouchTool
- RayCast
- 1Password
- eul
- auto-hide dock
- allow holding down
hjklkeys (I think this was a keyboard config?) - raycast did not override command+K
- dock apps
- apps that require settings sync
- eul (
exports/eul.yaml) - raycast (
exports/raycast.yaml+.rayconfigin machine-backup) - shottr (
exports/shottr.yaml; license in machine-backup) - Messages (disable notification sounds)
- [ ]
- eul (
- vscode settings / profile (synced via
stow_vscode.sh; extensions via brew) - manual app setup steps:
- 1password sign-in
- github sign-in
- make
/devdefault directory - chrome settings
- 1password extensions (and others)
- bookmarks?
- install default sdks (migrated asdf → mise;
mise installbootstraps from config)- e.g.
fvm install stable && fvm install beta && fvm install master - sdks to install:
- flutter (fvm)
- node (asdf)
- ts (asdf)
- go (asdf)
- typescript (via
npm i -g)
- e.g.
asdf plugin add golang && asdf plugin add nodejs && asdf plugin add deno
asdf install golang latest && asdf install nodejs latest && asdf plugin install deno latest
asdf global golang latest && asdf global nodejs latest && asdf global deno latest- automatically accept xcode license (
xcodebuild -license accept) - needed to comment out
1passwordzsh plugin in.zshrc, becauseopdoesnt have the proper permissions (now re-enabled) - xcode select tools:
- update to latest version (using
softwareupdate?) - approve terms (using
softwareupdate?)
- update to latest version (using
Using Claude Code + computer_use/browser_use plugins to authorize apps using the credentials stored in 1password (without the agent needing to copy/paste credentials into it's session).
- web apps:
- chrome profile login
- google apps (e.g. gmail)
- github
- claude
- reddit (personal)
- vercel
- expo
- neon DB
- cursor
- vs-code
- youtube (personal account, which has YT red/premium)
- figma (personal)
- linear (personal)
- spotify
- raycast
- desktop apps (most use web-based oauth):
- claude desktop
- cursor
- spotify
- linear
- vscode
- codex app
- figma
- raycast
- chatgpt
- slack
- discord
- zoom
- loom
- docker-desktop
- expo-orbit
- brave-browser
- android-studio
- obsidian
- shottr (license setup)
- desktop apps (no auth needed, just need to be opened to initialize)
- karabiner elements
- macOS permissions (grant via System Settings → Privacy & Security)
- script to check each app's granted permissions (query TCC.db)
- hammerspoon (Accessibility)
- kitty (Full Disk Access)
- cli apps (most use web-based oauth):
- claude-code
- gh
- vercel
- expo
- linear
- neonctl
- doctl
- flyctl
- railway
- mas