Personal dotfiles managed with GNU Stow. Each top-level directory is a stow package that mirrors the structure of $HOME. Running install.sh symlinks everything into place and safely backs up any pre-existing files that would conflict.
| Tool | Purpose |
|---|---|
bash 4+ |
Install and helper scripts |
stow |
Symlink management |
git |
Version control |
find / sort / awk |
Used by install script |
| Tool | Purpose |
|---|---|
| mise | Runtime version manager (replaces nvm, rbenv, etc.) |
| oh-my-posh | Shell prompt |
| neovim | Editor (nvim) |
| lsd | Modern ls replacement |
| bat | Modern cat replacement |
| lazygit | Terminal UI for git |
| delta | Syntax-highlighting pager for git diffs |
| btop | System monitor |
| fastfetch | System info display |
| tmux + tpm | Terminal multiplexer + plugin manager |
| opencode | AI coding assistant (aliased via opentmux) |
| superfile | Terminal file manager (spf) |
| cliamp | Retro terminal music player |
| gh | GitHub CLI |
| gh-dash | GitHub dashboard TUI (gh extension) |
| neofetch | System info display |
| Tool | Purpose |
|---|---|
| LM Studio | Local LLM runner (macOS only; path configured in .zshrc) |
| Java (Temurin 17) | JAVA_HOME configured in .zshrc on macOS |
Run check_deps.sh to verify what is and isn't installed — it can also install missing tools automatically.
# 1. Clone the repo
git clone git@github.com:crueber/dotfiles.git ~/.dotfiles
cd ~/.dotfiles
# 2. (Optional) Check and install dependencies
./check_deps.sh
# or auto-install everything without prompts:
./check_deps.sh --yes
# 3. Stow all packages into $HOME
./install.shinstall.sh is safe to re-run at any time. It will never silently overwrite existing files — conflicts are renamed to <original>.bak.<timestamp> before stowing.
Each top-level directory is a stow package. The directory tree inside it mirrors $HOME, so stow knows exactly where to create symlinks:
dotfiles/
├── bin/
│ └── bin/ → ~/bin/
├── git/
│ ├── .gitconfig → ~/.gitconfig
│ └── .gitignore → ~/.gitignore
├── lsd/
│ └── .config/
│ └── lsd/ → ~/.config/lsd/
├── oh-my-posh/
│ └── .oh-my-posh/ → ~/.oh-my-posh/
├── tmux/
│ ├── .tmux.conf → ~/.tmux.conf
│ └── .tmux/ → ~/.tmux/
└── zsh/
├── .zshrc → ~/.zshrc
└── .aliases → ~/.aliases
Note on
bin/bin/double-nesting: Stow would normally symlink the entirebin/package directory as~/bin. The innerbin/bin/nesting causes stow to instead create~/bin/as a real directory and symlink each script individually inside it. This is intentional — it keeps~/bin/as a real directory that can safely contain non-stow-managed files alongside the symlinked scripts.
The install script does the following:
- Discovers all stow packages dynamically (any top-level directory that isn't
.git,.github,node_modules, etc.) - Runs
stow --dry-runto detect conflicts without making any changes - Parses the dry-run output to find exactly which files would conflict
- Renames only those conflicting files to
<path>.bak.<timestamp> - Runs
stow -R(restow) to apply all packages
Backups are timestamped so re-runs never clobber previous backups. Symlinks that already point into the repo are skipped.
Checks for all required and recommended tools. Detects the available package manager (Homebrew, apt, pacman) and can install anything missing. Accepts --yes to skip confirmation prompts.
./check_deps.sh # interactive
./check_deps.sh --yes # auto-install all missing tools.zshrc— Initializes oh-my-posh with theblue-owl-customtheme, activates mise, setsEDITOR/VISUALto nvim, configures PATH for~/bin, LM Studio, and opencode..aliases— Shell aliases:ls=lsd,vim=nvim,n=nvim,cat=bat,ll="ls -al",..="cd ..",lg=lazygit
Local overrides: Create ~/.zshrc.local for machine-specific settings (tokens, private paths, etc.). It is sourced automatically if it exists and is excluded from git via .gitignore.
.gitconfig— User info, push default (current), useful aliases (aa,ap,ci,co,st,rebase-origin), delta as pager/difftool/mergetool (dark mode default; switch to light viaDELTA_FEATURES=+light), and a commit message template..gitignore— Global ignores:.DS_Store, editor swap files, common Rails and macOS artifacts.
.tmux.conf— Loads tpm, tmux-sensible, and tmux-themepack with thepowerline/default/bluetheme. Mouse support andtmux-256colorterminal are enabled..tmux/plugins/tpm/— TPM is vendored directly in the repo so it's available immediately after stowing without a separate bootstrap step.
After stowing, install tmux plugins by pressing prefix + I inside a tmux session.
Four prompt themes are included. The active theme is set in .zshrc:
| File | Notes |
|---|---|
blue-owl-custom.omp.json |
Active — customized version of blue-owl |
blue-owl.omp.json |
Upstream base theme |
microverse-power.omp.json |
Alternative |
tiwahu.omp.json |
Alternative |
To switch themes, update the --config path in zsh/.zshrc.
config.yaml— Enables color always, sets a custom color theme.colors.yml— 256-color palette for file type coloring.
Scripts symlinked into ~/bin/ and available on $PATH:
| Script | Description |
|---|---|
aaxtractor.sh |
Convert Audible .aax/.aaxc files to .m4b |
align.sh |
Library: right_aligned() helper for terminal output (source, don't execute) |
convert.sh |
Batch convert .aax → .m4b via ffmpeg |
get-gh-repos-for.sh |
Clone or pull all repos for a GitHub user or org |
gh-web.sh |
Open the current repo's GitHub page in Brave Browser |
git-churn.sh |
Show most frequently changed files across all git history |
port-kill.sh |
Kill the process listening on a given TCP port |
port-what.sh |
Show the process listening on a given TCP port |
sync-to-git.sh |
Initialize/auto-commit a Syncthing-managed directory as a git repo |
update-repos.sh |
Pull master or main for every git repo in subdirectories |
xlsx-to-csv.sh |
Convert .xlsx to .csv using Nushell |
aaxclean-clinote: This binary is no longer vendored in the repo. Download the appropriate build for your platform from the aaxclean-cli releases page and place it in~/bin/manually.
- Create a top-level directory named after the package (e.g.,
ssh/) - Inside it, recreate the path structure as it should appear under
$HOME(e.g.,ssh/.ssh/config) - Re-run
./install.sh— the new package is picked up automatically
Never commit secrets or machine-specific configuration. Use ~/.zshrc.local instead:
# ~/.zshrc.local (not tracked in git)
export GH_TOKEN="your-token-here"
export SOME_API_KEY="..."The .gitignore at the repo root excludes zsh/.zshrc.local and .zshrc.local to prevent accidental commits.