💻 ghostty, zsh, fish, tmux, starship, helix, lazygit, homebrew — my whole world
All shell commands manage globally installed packages (Homebrew, npm, pipx, cargo, mas).
The repo lives at ~/dotfiles/ and uses GNU stow to symlink each package into $HOME — $HOME itself is not a git working tree.
xcode-select --install # one-time, GUI prompt
git clone https://github.com/IvanWng97/dotfiles.git ~/dotfiles
cd ~/dotfiles && make bootstrapmake bootstrap installs Homebrew + stow, backs up any conflicting files in $HOME to ~/.dotfiles-pre-stow-<timestamp>/, stows the dotfile packages, and runs make install. Pass SKIP_INSTALL=1 to skip the package install step.
| Command | What it does |
|---|---|
make bootstrap |
Fresh-machine setup: brew + stow + symlinks + make install. Idempotent. |
make install |
Installs everything from Backup/Brewfile (brew bundle natively covers taps, formulas, casks, mas, vscode, cargo and npm) plus requirements.txt, fisher plugins from the stowed fish_plugins, tpm + plugins, and seeds ~/.claude/settings.json if absent. |
make install-links |
Re-run stow to (re)create symlinks under $HOME. |
make uninstall-links |
Remove the symlinks (configs stay safe in ~/dotfiles/). |
make relink |
uninstall-links then install-links — useful after adding a new file to a package. |
make symlinks-check |
Verify every package file has a matching, correctly-resolved symlink in $HOME; reports orphans too. Exits non-zero on issues. |
make doctor |
Run every health check at once: zsh syntax on each script, symlinks-check, Brewfile parses, git working tree clean. |
make update |
Upgrades brew/npm/pipx/cargo/mas/tmux packages and re-dumps Backup/Brewfile so it matches reality. |
make backup |
Re-dumps Backup/Brewfile + requirements.txt and snapshots ~/.claude/settings.json into Backup/ for committing. |
All six scripts (bootstrap, install, update, backup, check-links, doctor) live in scripts/ and share a small set of helpers (strict mode, colored output, per-tool guards) — update.sh deliberately skips -e so one failing updater doesn't abort the rest.
Each tool gets its own top-level package. All packages stow into $HOME; each one carries the right .config/, .aria2/, etc. structure inside it so stow puts files in the correct XDG location.
~/dotfiles/
alacritty/.config/alacritty/...
fish/.config/fish/...
helix/.config/helix/...
... ← 13 XDG packages
aria2/.aria2/aria2.conf
claude/.claude/CLAUDE.md claude/.claude/RTK.md
bash/.bashrc
czrc/.czrc
vim/.vimrc vim/.ideavimrc
zsh/.zshrc
~/.claude/settings.json is the one config that is not stowed: Claude Code rewrites it in place, which would silently replace the symlink with a real file. Instead make backup snapshots it to Backup/claude-settings.json and make install seeds it on a fresh machine.
The Makefile auto-discovers packages (every top-level dir except scripts/, Backup/, .github/, .git/) and runs a single stow -v -t ~ <packages...> call. Run make print-packages to see the current list.
Scripts under scripts/ are written in zsh (#!/usr/bin/env zsh); the lint workflow runs zsh -n on each to catch syntax errors.
The same checks the CI runs (gitleaks, actionlint, zsh -n, plus trailing-whitespace / EOF / YAML / merge-conflict) are available as pre-commit hooks. Opt-in per clone:
brew install pre-commit
pre-commit installZsh is the daily driver — kept lean, with eza/zoxide/fzf/bat/starship glue.
Starship handles the prompt — see config.toml.
Helix for quick edits; classic Vim config plus .ideavimrc for JetBrains IDEs.
Tmux config lives in tmux.conf. Prefix is C-Space; C-h/j/k/l navigates panes (vim-aware), M-h/j/k/l resizes them. Zellij is configured as an alternative.
Configs for Ghostty, Kitty, and Alacritty — Ghostty is the daily driver.
lazygit, tealdeer, lf, xplr, helix.
Everything is Dracula!
JetBrains Mono Nerd Font — installed via the font-jetbrains-mono-nerd-font cask in Backup/Brewfile.
👤 Ivan — @IvanWng97
MIT — feel free to fork, copy, and rip out whatever's useful.
Give a ⭐️ if this project helped you!
