My personal macOS dotfiles, managed with GNU Stow for symlink-based config deployment.
| Component | Tool | Config Location |
|---|---|---|
| Terminal | Kitty | ~/.config/kitty/ |
| Shell | Zsh + Starship | ~/.config/zsh/ |
| Editor | AstroNvim (Neovim) | ~/.config/nvim/ |
| Window Manager | AeroSpace | ~/.config/aerospace/ |
| Status Bar | SketchyBar | ~/.config/sketchybar/ |
| Window Borders | JankyBorders | ~/.config/borders/ |
| Launcher | Leader Key | ~/.config/leader-key/ |
| Mouse Control | Mouseless | GUI (v1.0.0) |
| Keyboard Nav | Homerow | ~/.config/homerow/ |
| Git | delta, lazygit | ~/.config/git/, ~/.config/lazygit/ |
| Search | ripgrep, fzf, zoxide | ~/.config/ripgrep/ |
| Version Manager | mise | ~/.config/mise/ |
| Password Manager | 1Password | — |
| Passwords (CLI) | gcloud SDK | ~/google-cloud-sdk/ |
zsh -c "$(curl -fsSL https://raw.githubusercontent.com/edygar/dotfiles/main/.local/bin/install.sh)"This will:
- Clone the repo to
~/Code/personal/dotfiles - Install Homebrew + all packages from Brewfile (including
stow) - Stow all config files into place via symlinks
- Set macOS system defaults
- Prompt for API keys and work email
- Set up Leader Key, Homerow, default apps, cron jobs, and wallpapers
~/.local/bin/install.shRe-running the same script on an existing machine will:
- Pull latest dotfiles
- Re-stow config files (updating symlinks)
- Refresh Homebrew packages
- Re-apply macOS defaults
- Skip already-configured items (API keys, cron jobs)
- Only download wallpapers if none exist
The install script handles:
- Homebrew + all packages from Brewfile (including
stow) - Stow config files into
~/.config/,~/.local/,~/.hammerspoon/, etc. - macOS system defaults (menu bar autohide, dock, finder, keyboard, trackpad)
- Unsplash API key prompt (for wallpaper rotation)
- Git work identity (
.gitconfig.work) - Leader Key config symlink (to
~/Library/Application Support/Leader Key/) - Raycast extension builds (Chrome, Kitty, QR Code, Notification History)
- Hammerspoon GridTile patch + reload
- Homerow config import
- Default app association for code files (Neovim.app)
- Cron jobs (hourly wallpaper rotation)
- Initial wallpaper download
- Restart kitty (fully quit, not just reload)
- Run
:Lazy syncin nvim - Grant accessibility permissions: System Settings > Privacy & Security
- Mouseless, Homerow, AeroSpace
- Configure Mouseless via GUI (
mouseless://settings) - Add Raycast script commands from
~/.local/bin/raycast-*.zsh - Rebuild neovim:
~/.local/bin/buildnvim.sh(if using local build) - Install SF Pro font:
brew install --cask font-sf-pro(requires sudo)
.zshrc: Main config — mise, starship, zsh-autosuggestions, .nvmrc auto-switching, gcloud SDKenv.zsh: Portable XDG paths, Zsh directory, and executable pathaliases.zsh: Git aliases, navigation, ls/eza with icons, zoxide, functionskey-bindings.zsh: Vi mode (bindkey -v), kitty window close, autosuggestions
~/.zshenv is machine-local and only sources ~/.config/zsh/env.zsh. The tracked environment then optionally sources ~/.env.zsh. Machine-local environment values, managed shell blocks, and credentials belong in ~/.env.zsh, which stays outside the repository and should use mode 600.
- Vi mode in shell (
KEYTIMEOUT=1) .nvmrcauto-switching via mise- Google Cloud SDK in PATH
- SauceCodePro Nerd Font throughout
OpenCode configuration is tracked under ~/.config/opencode/, but installed skills are machine-local. They live in ~/.local/share/opencode/skills, with ~/.config/opencode/skills pointing there. Stow ignores the skills path so private or work-specific skills never enter this repository.
- Font: SauceCodePro Nerd Font
- Colors: Gruvbox dark theme
- Scrollback: Neovim pager (
nvim_open_term) withq/Ctrl-C/Shift+Qto quit - Window nav:
Ctrl+h/j/k/lvia vim-kitty-navigator (IS_VIM user var) - Remote control:
allow_remote_control yes,listen_on unix:/tmp/mykitty - Icon: Alternate
>^_^<cat icon from sodapopcan/kitty-icon - Tab bar: Custom active/inactive colors (
#659DDAactive) - Transparent background: 0.8 opacity, 30 blur
| Key | Action |
|---|---|
Cmd+e |
Open scrollback in nvim |
Cmd+Shift+. |
Open nvim config tab |
Ctrl+h/j/k/l |
Navigate between nvim splits / kitty windows |
- Plugin Manager: lazy.nvim
- Theme: onedarker (with transparent background)
- Picker: Snacks.nvim (files, grep, buffers, explorer, LSP)
- Status bar: Heirline (tabline with tab numbers)
- LSP: vtsls, lua_ls, efm (formatting/linting via mason)
- Completion: blink.cmp
- Syntax: Treesitter with textobjects
- Git: gitsigns, diffview, gitlinker
- Navigation: dropbar (breadcrumbs), hop (jump), syntax-tree-surfer
- Diagnostics: tiny-inline-diagnostic, trouble
- File explorer: Snacks explorer (replaces nvim-tree)
- Search: grug-far (find & replace)
- Testing: neotest (jest)
- DAP: nvim-dap (jest debugging)
- Other: which-key, noice, undotree, oil, auto-save, nvim-surround, mini.indentscope
| Key | Action |
|---|---|
<Leader>ff |
Find files (Snacks) |
<Leader>fg |
Live grep (Snacks) |
<Leader>e |
Toggle explorer (Snacks) |
<Leader>ul |
Toggle line number style (both/relative) |
<Leader>uv |
Toggle inline diagnostics |
<Leader>gb |
Git blame line |
<Leader>gd |
Open diffview |
<Leader>ss |
Find & replace (grug-far) |
<Leader><Leader> |
Hop jump |
<Leader>gw |
Git worktree picker |
.localrc.lua files in project roots provide project-specific keymaps and LSP settings. See after/plugin/localrc.lua for the loader.
- Workspaces: A S D F Z X V Q R T (keyboard layout order)
- Layout: Accordion (default), tiles, floating
- Gaps: 8px inner, 46px top (for sketchybar), 8px others
- Start at login: Yes
- Config version: 2
- JankyBorders: Launched on startup,
#659DDAactive,style=round
| Key | Action |
|---|---|
Alt+letter |
Switch to workspace |
Alt+Shift+letter |
Move window to workspace |
Alt+h/j/k/l |
Focus left/down/up/right |
Alt+Shift+h/j/k/l |
Move window |
Alt+Cmd+Enter |
Toggle tiles layout |
Alt+Shift+Enter |
Toggle accordion layout |
Alt+Esc |
Service mode (reload, reset, fullscreen, floating) |
Alt+- / Alt+= |
Resize |
- Left: AeroSpace workspaces (A-Z) with app icons, focused workspace accented
- Left: Current focused app name with icon
- Right: Calendar, Volume, Battery, CPU usage
- Font: SF Pro (icons), SauceCodePro Nerd Font (space letters)
- Colors: Dark blue bar, accent on focused space only
- Auto-update: On workspace change and focus change via aerospace callbacks
style=round,width=3.0- Active:
#659DDA(matches kitty active tab) - Inactive:
#494d64
Uses the maintained kevintraver/LeaderKey fork, installed from source by ~/.local/bin/install-leader-key.zsh when full Xcode is available.
Config is symlinked from ~/.config/leader-key/config.json to ~/Library/Application Support/Leader Key/config.json, so changes made in Leader Key update the tracked file directly. Custom icons use /Users/Shared/leader-key-icons, a username-independent symlink to ~/.config/leader-key/icons/apps, and point directly at image files. This requires the fork because upstream treats non-.app iconPath values as SF Symbols.
| Key | Group |
|---|---|
g |
Go to (Browser, Slack, WhatsApp, Kitty, Notes, Gmail, Calendar, etc.) |
s |
Search (Browser tabs, Files, Slack, WhatsApp) |
f |
Browse folder (Home, Downloads, Desktop) |
F |
Open folder (Home, Desktop, Downloads) |
r |
Raycast (Screenshots, Notes, Ticket, Snippets) |
w |
Workspace (AeroSpace: A, B, D, F, G, M, O, P, Q, R, S, T, U, V, X, Z) |
a |
AeroSpace (Reset, Floating, Fullscreen, Close, Join) |
c |
Change case |
Shift+R |
Reload (Kitty, AeroSpace, Leader Key, Mouseless, SketchyBar) |
All URLs use raycast-x:// scheme (except script commands which use raycast://).
The install script builds the Chrome, Kitty, QR Code, and Notification History extensions from the source tracked in this repository. The external Store extensions referenced by Leader Key or script commands must be installed manually:
| Extension | Used for | Store |
|---|---|---|
| Google Chrome | Search browser tabs | Install |
| Calendar | Calendar search | Install |
| Change Case | Text case conversions | Install |
| JQ | Parse and query clipboard JSON | Install |
| Script | Description |
|---|---|
raycast-next-wallpaper.zsh |
Switch to next wallpaper |
raycast-previous-wallpaper.zsh |
Switch to previous wallpaper |
raycast-reload-configs.zsh |
Reload all configs (kitty, aerospace, leader key, mouseless, sketchybar) |
raycast-git-quick-commit.zsh |
Stage tracked files, prompt commit message, push |
raycast-dotfiles-commit.zsh |
Show dotfiles diff, select files, nvim commit, push |
| Script | Description |
|---|---|
dotfiles.zsh |
Open dotfiles in nvim (kitty tab) |
nvim-config.zsh |
Open nvim config in kitty tab |
lazygit.zsh |
Open lazygit in kitty tab |
kitty-launcher.zsh |
Launch commands in kitty split panes |
tab_title.zsh |
Generate kitty tab titles with git branch |
| Script | Description |
|---|---|
focus-tab.js |
Focus a Chrome tab (AppleScript) |
focus-url-tab |
Focus or open a tab by URL |
list-tabs.js |
List all Chrome tabs (for Raycast) |
| Script | Description |
|---|---|
macos-defaults.zsh |
Set macOS system preferences |
install_dotfiles.sh |
Full machine setup script |
buildnvim.sh |
Build neovim from source |
open-in-nvim.zsh |
Open files in nearest running nvim (via kitty remote control) |
wallpaper.zsh |
Fetch space/astronomy wallpapers (JWST + NASA APOD + Unsplash) |
organize_windows.sh |
Organize windows with AeroSpace |
toggle-chain-click.zsh |
Toggle Homerow chain clicks |
dismiss-notifications.applescript |
Dismiss macOS notifications |
get-ticket.sh |
Get Jira ticket from clipboard |
shortcut.sh |
Launch app and trigger shortcut |
json.sh |
Parse clipboard as JSON |
sh.sh |
Run shell commands via Raycast |
An app bundle at ~/Applications/Neovim.app (not tracked in git) that:
- Shows up in Finder's "Open with" menu with the Neovim icon
- Opens files in the nearest running nvim instance via kitty remote control
- Is set as default for 50+ code file extensions via
duti
Wallpapers are fetched from three sources (in priority order):
- NASA APOD — Astronomy Picture of the Day (free, high quality processed images)
- JWST API — James Webb Space Telescope raw images (free key at jwstapi.com)
- Unsplash — Space/astronomy themed backup
- Stored in
~/.config/wallpapers/(gitignored) - API keys in
~/.config/wallpapers/.unsplash-keyand.jwst-key(gitignored) - Rotates hourly via cron job
- Next/Previous via Raycast scripts
- Minimum resolution filter (1000x500)
- Main config:
~/.config/git/config(aliases, delta pager, nvim as editor) - Personal identity:
~/.gitconfig.user(edygar@users.noreply.github.com) - Work identity:
~/.gitconfig.work(gitignored, prompted on install) - Conditional includes:
~/Code/work/uses work identity - Lazygit: Custom commands (
ssync,Sforce sync,Kcommit --no-verify,oedit config)
| Font | Usage |
|---|---|
| SauceCodePro Nerd Font | Kitty, Neovim, eza icons, starship |
| SF Pro | SketchyBar icons |
| sketchybar-app-font | SketchyBar app icons |
Set via macos-defaults.zsh:
- Dock: autohide, no delay
- Menu bar: always hide
- Finder: show hidden files, list view, path bar, status bar
- Keyboard: fast key repeat, no auto-correct
- Trackpad: tap to click
- Screenshots: no shadow, save to Desktop
- Windows: minimize on double-click title bar
Personal dotfiles. Use at your own risk.