From 5c3c56ac219881409ca6241f29cd4e8323a07118 Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 27 Jan 2026 22:35:31 -0500 Subject: [PATCH] Migrate to GNU Stow for symlink management Replace custom deploy.sh with stow-based install.sh and update.sh. Each app gets its own package directory with files structured as they should appear relative to ~. Co-Authored-By: Claude Opus 4.5 --- Brewfile | 1 + README.md | 10 ++--- claude/{ => .claude}/CLAUDE.md | 0 deploy.sh | 44 ------------------- {exts => git/.exts}/git.sh | 0 gitconfig => git/.gitconfig | 0 gitignore => git/.gitignore | 0 git/.stow-local-ignore | 3 ++ install.sh | 32 ++++++++++++++ iterm/{ => .iterm}/0x96.itermcolors | 0 iterm/{ => .iterm}/clutchski.itermcolors | 0 {config => mise/.config}/mise/config.toml | 0 .../custom}/themes/clutchski.zsh-theme | 0 pythonrc => python/.pythonrc | 0 screenrc => screen/.screenrc | 0 bash_aliases => shell/.bash_aliases | 0 exports.sh => shell/.exports.sh | 0 {exts => shell/.exts}/blackhole.sh | 0 {exts => shell/.exts}/wt.sh | 0 functions.sh => shell/.functions.sh | 0 zshrc => shell/.zshrc | 0 ssh/{ => .ssh}/config | 0 ssh/{ => .ssh}/sockets/.gitkeep | 0 tool-versions | 4 -- update.sh | 12 +++++ vim/{ => .vim}/tmp/.gitkeep | 0 vimrc => vim/.vimrc | 0 .../.config}/worktrunk/config.toml | 0 28 files changed, 52 insertions(+), 54 deletions(-) rename claude/{ => .claude}/CLAUDE.md (100%) delete mode 100755 deploy.sh rename {exts => git/.exts}/git.sh (100%) rename gitconfig => git/.gitconfig (100%) rename gitignore => git/.gitignore (100%) create mode 100644 git/.stow-local-ignore create mode 100755 install.sh rename iterm/{ => .iterm}/0x96.itermcolors (100%) rename iterm/{ => .iterm}/clutchski.itermcolors (100%) rename {config => mise/.config}/mise/config.toml (100%) rename oh-my-zsh/{ => .oh-my-zsh/custom}/themes/clutchski.zsh-theme (100%) rename pythonrc => python/.pythonrc (100%) rename screenrc => screen/.screenrc (100%) rename bash_aliases => shell/.bash_aliases (100%) rename exports.sh => shell/.exports.sh (100%) rename {exts => shell/.exts}/blackhole.sh (100%) rename {exts => shell/.exts}/wt.sh (100%) rename functions.sh => shell/.functions.sh (100%) rename zshrc => shell/.zshrc (100%) rename ssh/{ => .ssh}/config (100%) rename ssh/{ => .ssh}/sockets/.gitkeep (100%) delete mode 100644 tool-versions create mode 100755 update.sh rename vim/{ => .vim}/tmp/.gitkeep (100%) rename vimrc => vim/.vimrc (100%) rename {config => worktrunk/.config}/worktrunk/config.toml (100%) diff --git a/Brewfile b/Brewfile index 9fe119b..47e8105 100644 --- a/Brewfile +++ b/Brewfile @@ -1,5 +1,6 @@ tap "max-sixty/worktrunk" +brew "stow" brew "htop" brew "ripgrep" brew "wget" diff --git a/README.md b/README.md index 9d05832..1675d69 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,13 @@ dotfiles ======== ``` -git clone https://github.com/clutchski/dotfiles +git clone git@github.com:clutchski/dotfiles.git cd dotfiles -./deploy.sh +./install.sh ``` -or +After changes: ``` -git clone git@github.com:clutchski/dotfiles.git -cd dotfiles -./deploy.sh +./update.sh ``` diff --git a/claude/CLAUDE.md b/claude/.claude/CLAUDE.md similarity index 100% rename from claude/CLAUDE.md rename to claude/.claude/CLAUDE.md diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index 34bb6eb..0000000 --- a/deploy.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -set -e - -# First install oh-my-zsh -if [ ! -d ~/.oh-my-zsh ]; then - echo "Cloning oh-myzsh" - git clone https://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh -fi - -# Deploy each app config file. -for f in `ls . ` -do - if [[ $f == "README.md" ]] || [[ $f == "deploy.sh" ]] || [[ $f == "Brewfile" ]]; then - continue - fi - - if [ -d $f ]; then - ln -sfn "$(pwd)/${f}" ~/.${f} - else - ln -sf "$(pwd)/${f}" ~/.${f} - fi -done - -# Check if the Brewfile needs to be applied -if ! brew bundle check > /dev/null ; then - echo "📦 Installing missing packages from Brewfile..." - brew bundle -fi - -# Setup vim. -if [ ! -f ~/.vim/autoload/plug.vim ]; then - echo "Installing vim-plug..." - curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ - https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim -fi -vim +'PlugInstall --sync' +qa - -# Set up git. -git config --global core.excludesfile ~/.gitignore - -if [[ "$(hostname)" == bt* ]]; then - git config --global user.email "matt@braintrustdata.com" -fi diff --git a/exts/git.sh b/git/.exts/git.sh similarity index 100% rename from exts/git.sh rename to git/.exts/git.sh diff --git a/gitconfig b/git/.gitconfig similarity index 100% rename from gitconfig rename to git/.gitconfig diff --git a/gitignore b/git/.gitignore similarity index 100% rename from gitignore rename to git/.gitignore diff --git a/git/.stow-local-ignore b/git/.stow-local-ignore new file mode 100644 index 0000000..fed2008 --- /dev/null +++ b/git/.stow-local-ignore @@ -0,0 +1,3 @@ +# Override stow's default ignores to allow .gitignore +\.git +\.gitmodules diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..9b460ab --- /dev/null +++ b/install.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +DOTFILES_DIR="$(cd "$(dirname "$0")" && pwd)" + +# Install Homebrew packages (includes stow) +if ! brew bundle check --file="$DOTFILES_DIR/Brewfile" > /dev/null 2>&1; then + brew bundle --file="$DOTFILES_DIR/Brewfile" +fi + +# Install oh-my-zsh if needed +if [ ! -d ~/.oh-my-zsh ]; then + git clone https://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh +fi + +# Stow all packages +"$DOTFILES_DIR/update.sh" + +# Install vim-plug +if [ ! -f ~/.vim/autoload/plug.vim ]; then + curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ + https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim +fi +vim +'PlugInstall --sync' +qa + +# Configure git +git config --global core.excludesfile ~/.gitignore + +if [[ "$(hostname)" == bt* ]]; then + git config --global user.email "matt@braintrustdata.com" +fi diff --git a/iterm/0x96.itermcolors b/iterm/.iterm/0x96.itermcolors similarity index 100% rename from iterm/0x96.itermcolors rename to iterm/.iterm/0x96.itermcolors diff --git a/iterm/clutchski.itermcolors b/iterm/.iterm/clutchski.itermcolors similarity index 100% rename from iterm/clutchski.itermcolors rename to iterm/.iterm/clutchski.itermcolors diff --git a/config/mise/config.toml b/mise/.config/mise/config.toml similarity index 100% rename from config/mise/config.toml rename to mise/.config/mise/config.toml diff --git a/oh-my-zsh/themes/clutchski.zsh-theme b/oh-my-zsh/.oh-my-zsh/custom/themes/clutchski.zsh-theme similarity index 100% rename from oh-my-zsh/themes/clutchski.zsh-theme rename to oh-my-zsh/.oh-my-zsh/custom/themes/clutchski.zsh-theme diff --git a/pythonrc b/python/.pythonrc similarity index 100% rename from pythonrc rename to python/.pythonrc diff --git a/screenrc b/screen/.screenrc similarity index 100% rename from screenrc rename to screen/.screenrc diff --git a/bash_aliases b/shell/.bash_aliases similarity index 100% rename from bash_aliases rename to shell/.bash_aliases diff --git a/exports.sh b/shell/.exports.sh similarity index 100% rename from exports.sh rename to shell/.exports.sh diff --git a/exts/blackhole.sh b/shell/.exts/blackhole.sh similarity index 100% rename from exts/blackhole.sh rename to shell/.exts/blackhole.sh diff --git a/exts/wt.sh b/shell/.exts/wt.sh similarity index 100% rename from exts/wt.sh rename to shell/.exts/wt.sh diff --git a/functions.sh b/shell/.functions.sh similarity index 100% rename from functions.sh rename to shell/.functions.sh diff --git a/zshrc b/shell/.zshrc similarity index 100% rename from zshrc rename to shell/.zshrc diff --git a/ssh/config b/ssh/.ssh/config similarity index 100% rename from ssh/config rename to ssh/.ssh/config diff --git a/ssh/sockets/.gitkeep b/ssh/.ssh/sockets/.gitkeep similarity index 100% rename from ssh/sockets/.gitkeep rename to ssh/.ssh/sockets/.gitkeep diff --git a/tool-versions b/tool-versions deleted file mode 100644 index 63c7ca0..0000000 --- a/tool-versions +++ /dev/null @@ -1,4 +0,0 @@ -python 3.13 -go 1.24 -node 22.15.0 -rust 1.88 diff --git a/update.sh b/update.sh new file mode 100755 index 0000000..ceeb774 --- /dev/null +++ b/update.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +DOTFILES_DIR="$(cd "$(dirname "$0")" && pwd)" +PACKAGES=(shell git vim ssh python screen mise worktrunk iterm oh-my-zsh claude) + +cd "$DOTFILES_DIR" + +for pkg in "${PACKAGES[@]}"; do + stow -t ~ -R "$pkg" +done diff --git a/vim/tmp/.gitkeep b/vim/.vim/tmp/.gitkeep similarity index 100% rename from vim/tmp/.gitkeep rename to vim/.vim/tmp/.gitkeep diff --git a/vimrc b/vim/.vimrc similarity index 100% rename from vimrc rename to vim/.vimrc diff --git a/config/worktrunk/config.toml b/worktrunk/.config/worktrunk/config.toml similarity index 100% rename from config/worktrunk/config.toml rename to worktrunk/.config/worktrunk/config.toml