Dotfiles: Workstation Bootstrap with GNU Stow

Terminal, editor, and macOS window-manager config managed via GNU Stow + Homebrew Bundle — clone, run one script, machine ready.

dotfiles stow homebrew macos neovim tmux ghostty aerospace zsh
View Source

A single repository that pins every piece of my macOS workstation config: terminal, editor, window manager, Homebrew packages, and system preferences. Bootstrapping a fresh machine to a ready-to-work environment takes one curl | bash.

Philosophy

Each tool gets one directory in the repo. GNU Stow symlinks that directory into the actual config location under $HOME or ~/.config. The practical consequences:

  • Single source of truth. Edit config in the repo, the change is live on the system instantly.
  • No copy-paste. No “copy this file to ~/.config/...” step that’s easy to forget on updates.
  • Reversible. stow -D unlinks cleanly without leaving residue.

Repo Layout

Diagram symlink GNU Stow dari direktori repo ke lokasi config di home directory

dotfiles/
├── aerospace/        # tiling window manager for macOS
├── alacritty/        # GPU terminal (pre-Ghostty)
├── ghostty/          # active terminal
├── nvim/             # Neovim — primary IDE
├── vim/              # Vim fallback
├── tmux/             # terminal multiplexer
├── zsh/              # shell + prompt
├── sketchybar/       # macOS status bar
├── borders/          # macOS window borders
├── git/              # gitconfig + global gitignore
├── ssh/              # ssh client config
├── mise/             # version manager (Node/Go/Python)
├── nix/              # nix-darwin config
├── joshuto/          # TUI file manager
├── yazi/             # alternate TUI file manager
├── fonts/            # locally installed fonts
├── Brewfile          # 39 brew formulas + 11 casks
├── __scripts__/      # plugin installers (zsh, version manager)
├── __macos__/        # macOS system defaults scripts
└── install.sh        # bootstrap entrypoint

Bootstrap

Flow bootstrap satu perintah: stow, brew bundle, plugin shell, defaults macOS

One command from a fresh machine:

bash -c "$(curl -fsSL https://raw.githubusercontent.com/arisros/dotfiles/main/install.sh)"

The script in order:

  1. Creates target directories under ~/.config/...
  2. Runs stow -t <target> <package> for each tool — symlinks materialize
  3. Runs brew bundle --file=Brewfile (optional, commented by default) to install ~50 packages
  4. Calls __scripts__/install_zsh_plugins.sh for shell plugins
  5. Executes __macos__/defaults.sh for macOS system preferences

Tooling

LayerToolNotes
WMAerospacei3-style tiling for macOS
Status barSketchyBarreplaces the default macOS menubar
Window borderJankyBordersfocus indicator for tiling
TerminalGhosttyGPU-accelerated, default since 2025
Multiplexertmuxsession persistence + split panes
ShellZshprompt + plugins via __scripts__/install_zsh_plugins.sh
EditorNeovimLua config, see nvim/.config/nvim/
File managerYazi / JoshutoTUI, keyboard-fast navigation
Version managermisereplaces asdf/nvm/pyenv
Package managerHomebrewBrewfile pins 56 packages

Brewfile

Brewfile is the package manifest — tracked in git so installs are reproducible:

tap "felixkratz/formulae"     # for sketchybar
tap "nikitabobko/tap"          # for aerospace
tap "leoafarias/fvm"
tap "kardolus/chatgpt-cli"

brew "[email protected]"
brew "ffmpeg"
brew "neovim"
brew "tmux"
...

cask "ghostty"
cask "raycast"
cask "rectangle-pro"
...

brew bundle dump regenerates this file from currently-installed packages — so the machine state can always be snapshotted back into the repo.

Update Workflow

Updating config:

# Edit directly in the repo (symlinks make changes immediately live)
nvim ~/dotfiles/nvim/.config/nvim/lua/plugins/lsp.lua

# Commit + push
cd ~/dotfiles && git add . && git commit -m "nvim: ..." && git push

Updating Brewfile:

brew bundle dump --force --file=~/dotfiles/Brewfile
cd ~/dotfiles && git add Brewfile && git commit -m "brew: snapshot" && git push

Status

Active repo — used daily, updated whenever new tools land. Goal: from fresh Mac to “ready to work” in <10 minutes, without touching keys one by one.