The bootstrap silently installs tools for ~30s+ on a version bump or first login, which looked like an unexplained hang. Now prints a banner explaining what is happening, that it may take a minute, and that subsequent runs are a no-op. The box is built dynamically so the right edge stays aligned regardless of the version string length. Also clarifies the trigger comment in zshrc.
Zsh Config
A reproducible, self-configuring Zsh setup managed from a remote git repo. The zshrc auto-updates itself and the Starship prompt config on every interactive shell start, and a versioned bootstrap script installs all missing dependencies across distros. Drop ~/.zshrc in place once and every machine stays in sync automatically.
Design
- Reproducible — one
zshrcdrives an identical environment across every machine and distro. - Self-configuring — tool integrations are guarded by
command -v, so the shell works degraded-but-fine when a tool is absent, and lights up automatically once the bootstrap installs it. - Self-updating — on each interactive shell start,
zshrcandstarship.tomlare re-pulled from the repo and applied if changed (downloaded files are validated withzsh -nbefore replacing anything, so a 502 error page or corrupted content can't break the shell). - Network-resilient — all remote calls use
--fail+--connect-timeout/--max-time, so an unreachable server silently no-ops instead of hanging the shell.
Files
| File | Description |
|---|---|
zshrc |
Main config. Path setup, history options, oh-my-zsh + plugins, eza theme, tool integrations, aliases, and the auto-update logic. Sources ~/.zshrc.local at the end for per-machine overrides. |
zshrc-bootstrap.zsh |
One-shot setup script run by zshrc when the bootstrap version changes. Installs all dependencies across distros and clones oh-my-zsh + custom plugins. |
starship.toml |
Starship prompt config — two-line prompt with directory, git status, command duration, Nerd Font symbols, and an error indicator. Synced to ~/.config/starship.toml by the auto-update logic. |
tmux.conf |
Tmux config with GitHub Dark theming, Vim-style pane navigation (h/j/k/l), TPM plugin manager, Nerd Font auto-install, and a built-in cheatsheet (prefix + ?). Installed to ~/.config/tmux/tmux.conf on first shell start. |
Getting Started
Point ~/.zshrc at the remote zshrc:
curl -fsSL https://git.jeremymcclure.com/jeremy/scripts/raw/branch/master/zsh/zshrc -o ~/.zshrc && exec zsh
On first start, zshrc bootstraps missing dependencies (oh-my-zsh, plugins, and all CLI tools below) over the next shell starts. To force a re-bootstrap (e.g., after adding new tool installs to the bootstrap script), the bootstrap version is bumped in zshrc and every machine re-runs it automatically — or run manually:
BOOTSTRAP=true exec zsh
Dependencies
All installed automatically by the bootstrap across brew / apt / dnf / pacman / cargo:
| Tool | Purpose |
|---|---|
| starship | Prompt (configured via starship.toml) |
| fzf | Fuzzy finder — powers fzf-tab completion and zi |
| eza | ls replacement with icons, git status, hyperlinks |
| bat | cat replacement + colored man pages |
| zoxide | Frecency directory jumping (z, zi) |
| git-delta | Pretty git diff/log/show pager |
| fastfetch | System info on shell start |
| lazydocker | TUI for Docker |
| rsync / tmux / git | Core utilities |
Debian/Ubuntu renames handled: batcat→bat, fdfind→fd (symlinked into ~/.local/bin).
Oh-My-Zsh Plugins
git, sudo, extract, eza, history, kitty, docker, docker-compose, archlinux, encode64, universalarchive, zsh-autosuggestions, fast-syntax-highlighting, fzf, fzf-tab, systemd, vscode, rsync, starship.
Tool Integrations
Each is enabled only when the binary is present (command -v):
- zoxide —
z <substring>jumps to frecency-ranked dirs;ziopens the fzf picker.cdstill works. - bat —
alias cat='bat',BAT_THEME=Monokai Extended, andMANPAGERset somanpages are colored and paginated by bat. - delta —
GIT_PAGER=deltasogit diff/log/showrender side-by-side with syntax highlighting. (Not aliased todiff— delta is a pager reading diff input on stdin, not adiff a breplacement.)
History & Shell Options
SHARE_HISTORY, HIST_IGNORE_DUPS, HIST_IGNORE_ALL_DUPS, HIST_REDUCE_BLANKS, HIST_FCNTL_LOCK, HIST_VERIFY, EXTENDED_HISTORY, AUTO_CD, AUTO_LIST, INTERACTIVE_COMMENTS, AUTO_PUSHD, PUSHD_IGNORE_DUPS, PUSHD_SILENT.
AUTO_PUSHD maintains an automatic directory stack, so cd -<TAB> and dirs let you navigate recent locations without pushd/popd muscle memory.
Aliases
| Alias | Action |
|---|---|
c |
clear |
q |
exit |
open-ports |
ss -tulpn | grep LISTEN |
nbstat |
Netbird peer status as a TSV table |
yeet |
yay -Rcs (remove + deps + config on Arch) |
Keybindings
| Shortcut | Action |
|---|---|
Ctrl+R |
fzf history search (via fzf plugin) |
Ctrl+T |
fzf file finder |
Alt+C |
fzf cd |
Tab |
fzf-tab completion menu |
Esc twice |
Toggle sudo prefix (via sudo plugin) |
Eza Hyperlinks — Implementation Note
zshrc does not set the oh-my-zsh eza plugin's hyperlink zstyle. The plugin emits a bare --hyperlink flag, which eza (clap) treats as taking the next token as its optional value — so la / fails with invalid value '/'. Instead, after oh-my-zsh loads, the aliases are rewritten to append the glued --hyperlink=always form, which can't eat a following path argument. Hyperlinks stay on and paths keep working.
Auto-Update Behavior
On every interactive shell start:
- zshrc — re-downloaded, validated with
zsh -n, and applied viaexec zshonly if it differs from~/.zshrc. - starship.toml — re-downloaded and moved to
~/.config/starship.tomlif changed (applied live on the next prompt render; no shell reload needed). - tmux.conf — downloaded once on first shell start if
~/.config/tmux/tmux.confand~/.config/byobu/.tmux.confare both absent. - bootstrap — runs (
zshrc-bootstrap.zsh) whenZSHRC_BOOTSTRAP_VERSIONinzshrcdoesn't match~/.config/zsh/.bootstrapped.
All downloads use --fail so a 502/HTML error page is never written over a working config, and --connect-timeout/--max-time so an unreachable server never hangs startup.
Per-Machine Overrides
~/.zshrc.local is sourced at the very end of zshrc (created empty if missing). Put machine-specific aliases, env vars, or PATH additions there — they survive repo updates since zshrc doesn't manage that file.
Environment Variables
| Variable | Default | Purpose |
|---|---|---|
ZSHRC_GIT |
.../scripts/raw/branch/master/zsh/ |
Base URL for all remote config files |
ZSHRC_BOOTSTRAP_VERSION |
3 |
Bump to force a re-bootstrap on all machines |
FFENABLED |
(unset → enabled) | Set to false to disable the fastfetch system info on shell start |
BAT_THEME |
Monokai Extended |
Override before the bat block to use a different bat theme |
GIT_PAGER |
delta (when installed) |
Override to use a different git pager |
Helper Functions
update_zshrc # Manually re-pull and reload the zshrc
fix_btopbg # Disable btop theme_background (workaround for transparency)
install_opencode # Install the opencode CLI
BOOTSTRAP=true exec zsh # Force a re-bootstrap