███╗ ███╗██╗ ██╗ ███████╗██╗ ██╗███████╗██╗ ██╗
████╗ ████║╚██╗ ██╔╝ ██╔════╝██║ ██║██╔════╝██║ ██║
██╔████╔██║ ╚████╔╝█████╗███████╗███████║█████╗ ██║ ██║
██║╚██╔╝██║ ╚██╔╝ ╚════╝╚════██║██╔══██║██╔══╝ ██║ ██║
██║ ╚═╝ ██║ ██║ ███████║██║ ██║███████╗███████╗███████╗
╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝
Personal dotfiles for Bash, Zsh, tmux, and Ghostty — designed to work across macOS, Arch Linux, Ubuntu, Fedora, and NixOS. Uses GNU Stow to symlink files into $HOME and a modular installer that can set up or revert everything in one command.
git clone <repo-url> ~/Projects/my-shell
cd ~/Projects/my-shell
./setup # install everything
./setup -r # revert to backupsThe setup script runs each module in install.d/ in order: create directories, configure Bash, configure Zsh, then stow dotfiles.
| File | Purpose |
|---|---|
shared.envs.sh |
Environment variables shared across shells (paths, Homebrew, Go, NVM, Ollama, libvirt) |
shared.aliases.sh |
Cross-shell aliases (lsd, bat, cls) and package management helpers (pi, pq, pr) |
zsh.rc.sh |
Zsh entrypoint — loads envs, plugins, aliases, and shell integrations |
zsh.plugins.sh |
Zinit plugin manager with fast-syntax-highlighting, autosuggestions, fzf-tab, and completions |
bash.rc.sh |
Bash entrypoint |
| File | Purpose |
|---|---|
tmux.conf |
Main config — vim-style navigation, popup support, mouse, inlined status bar theme |
popup.sh |
Helper for launching floating popup windows |
tpm.sh |
Bootstraps TPM if not installed |
| File | Purpose |
|---|---|
config.ghostty |
Terminal config — padding, keybinds, SSH integration |
auto/theme.ghostty |
Ayu theme (auto-loaded) |
local.ghostty |
Optional machine-local overrides (gitignored) |
Custom slash commands for Claude Code:
| Command | Description |
|---|---|
/cc |
Stage and create a Conventional Commit (with optional issue close) |
/commit |
Create a well-formed conventional commit from staged changes |
/encode |
Encode MakeMKV rips into movies or TV shows using HandBrake presets |
/file-header |
Add an ASCII banner + description header to a file |
/tag |
Create an annotated semantic version tag on HEAD |
/gh-issue |
Create a well-formed GitHub issue via gh |
/gh-pr-merge |
Open a PR from the current branch and squash-merge it |
/rip-disc |
Rip Blu-ray / 4K UHD discs with MakeMKV into ~/Rippy/@imports |
/update-readme |
Sync the README to reflect the current state of the repo |
| Command | Description |
|---|---|
ai-call-ollama |
Call a local or remote Ollama instance with a model, system prompt, and user prompt |
ai-git-commit-msg |
Generate a Conventional Commit message from staged diff using Ollama, then open it in $EDITOR |
backup-calibre.sh |
Archive and sync Calibre library from a remote host to local Dropbox backup |
sys-cache-thumbnail |
Generate and cache thumbnails for media files |
sys-get-os |
Detect the current OS (macos, arch, ubuntu, fedora) |
sys-pkg-install |
Install packages with the right package manager for the current OS |
sys-pkg-check |
Check if a package is already installed |
sys-pkg-uninstall |
Remove packages cross-platform |
tmux-sessionizer |
Fuzzy-find a project directory and open it in a tmux session (inspired by ThePrimeagen) |
xtra-setup-sshd |
Configure sshd |
| Library | Description |
|---|---|
require.sh |
Module loader for Bash — sources scripts by name with dedup guards |
logger.sh |
Colored, leveled logging (debug/info/warn/error/fatal) with style helpers |
Libraries live in .local/share/my/lib/bash/. Source them directly or use require.sh for dedup-safe loading:
PROJECT_ROOT=$(git rev-parse --show-toplevel)
# Direct source
source "$PROJECT_ROOT/.local/share/my/lib/bash/logger.sh"
# Via require.sh (safe to call multiple times — loads each module at most once)
source "$PROJECT_ROOT/.local/share/my/lib/bash/require.sh" loggerrequire.sh resolves modules by name from $MY_LIB_DIR/bash/, or by explicit path if the argument starts with / or ./.
logger.sh provides leveled logging controlled by LOG_LEVEL (default: 1 = ERROR and above):
LOG_LEVEL=8 # enable all levels
export LOG_LEVEL
debug "low-level detail" # level 8
info "status message" # level 4
warn "something is off" # level 2
error "something failed" # level 1
fatal "unrecoverable" # level 0 — also calls exit 1Style helpers are available for ad-hoc output:
bold_green "Done!"
dim "skipping..."
red "uh oh"Colors are auto-disabled when stdout is not a terminal (e.g. when output is captured or piped).
Child scripts (workers, installers, helpers) should write freely to stdout/stderr and exit with meaningful codes. Top-level scripts that interact with the desktop or a user-facing UI own the notification layer — they capture child output and handle it in an EXIT trap.
#!/usr/bin/env bash
on_exit() {
if (( $? > 0 )); then
notify-send "ERROR $(basename "$0")" "An error occurred:\n\n$msg"
error "$msg"
else
notify-send "Success!" "$msg"
fi
}
set -euEo pipefail
trap on_exit EXIT
PROJECT_ROOT=$(git rev-parse --show-toplevel)
source "$PROJECT_ROOT/.local/share/my/lib/bash/logger.sh"
msg="" # initialize before any early exit so the trap is always safe
msg=$("$PROJECT_ROOT/.local/share/my/bin/some-child-script" "$@" 2>&1)Key points:
set -euEo pipefail— exit on any error, unset variable, or pipe failuretrap on_exit EXIT— the handler always runs, success or failuremsg=""— must be initialized before the first command that can fail; otherwiseset -uwill crash the trap if it fires early2>&1— merges stderr into stdout so the full child output (logs + errors) becomes the notification body
The bin/ scripts are standalone and callable from any script once $MY_BIN_DIR is on $PATH (set up by the shell config after install):
# Detect OS
os=$(sys-get-os) # → "arch", "ubuntu", "macos", etc.
# Install packages (skips already-installed)
sys-pkg-install git curl ripgrep
# Check if a package is present
sys-pkg-check fzf && echo "fzf is installed"These scripts talk to an Ollama API endpoint. The target host is controlled by the OLLAMA_HOST environment variable, which defaults to http://localhost:11434.
shared.envs.sh sets OLLAMA_HOST to a remote instance. To override it for a session, or to point at a local Ollama instance instead:
export OLLAMA_HOST="http://localhost:11434"To make the override permanent, add the export to ~/ollama.env.sh (this file is sourced automatically by shared.envs.sh when it exists, and is gitignored):
echo 'export OLLAMA_HOST="http://localhost:11434"' >> ~/ollama.env.shSend a prompt to any Ollama model and print the response:
# Basic usage
ai-call-ollama -m llama3.2 -s "You are a terse assistant." -p "What is a VLAN?"
# Pipe the user prompt from stdin
echo "Explain BGP in one sentence." | ai-call-ollama -m qwen2.5-coder:14b -s "Be concise."
# Stream the raw response as it generates
ai-call-ollama -m mistral -s "You are helpful." -p "Summarize TCP/IP." --stream| Flag | Description |
|---|---|
-m, --model |
Model name (e.g. llama3.1, qwen2.5-coder:14b) |
-s, --system |
System prompt |
-p, --prompt |
User prompt (or pipe via stdin) |
--stream |
Stream raw JSON lines as the model generates |
Requires curl and jq.
Generate a Conventional Commit message from the currently staged diff, open it in $EDITOR for review, then commit:
git add -p # stage your changes
ai-git-commit-msg # generate, edit, and commitThe script uses qwen2.5-coder:14b by default and respects OLLAMA_HOST.
The Zsh config auto-detects and initializes these tools when available:
- Starship — prompt
- fzf — fuzzy finder
- zoxide — smarter
cd - mise — runtime/tool version manager
- ngrok — tunneling
.
├── setup # Main installer entrypoint
├── install.d/ # Installer modules
│ ├── envs.sh # Shared vars and arg parsing
│ ├── mkdirs.sh # Create directory structure
│ ├── bash.sh # Install .bashrc
│ ├── zsh.sh # Install .zshrc
│ └── stow.sh # Symlink dotfiles via GNU Stow
├── .claude/
│ ├── commands/ # Custom Claude Code slash commands
│ └── settings.json # Claude Code project settings
├── .config/
│ ├── 1Password/ssh/ # 1Password SSH agent config
│ ├── ghostty/ # Ghostty terminal config and theme
│ └── tmux/ # Tmux config, theme, and helper scripts
├── .local/share/my/
│ ├── bin/ # CLI utilities (added to $PATH)
│ ├── lib/bash/ # Bash libraries
│ └── shell/ # Shell rc/profile/alias/env files
└── .stow-local-ignore # Files excluded from stow

