Files
scripts/zsh/README.md
T
jeremy 18af4de0c0 zsh: add github binary fallbacks for bat/zoxide/delta (fixes RHEL/Alma without EPEL/cargo)
On RHEL-family distros without EPEL enabled and without cargo, the PM
loop fails for bat/zoxide/git-delta and there was no fallback, so they
ended up skipped/FAIL. Now, after the PM/cargo attempts fail, download
the latest static release tarball from GitHub instead, matching the
existing pattern for eza/fastfetch/starship/lazydocker.

- Add _gh_latest_tag(): resolve latest release tag from the
  /releases/latest redirect (no GitHub API, no rate limits)
- Add _gh_install_bin(): build the asset URL from a versioned template,
  download, extract, and cp the named binary into ~/.local/bin
- Handle per-repo tag conventions: bat/zoxide tags are 'v0.x' while
  delta tags are bare '0.x'; keep the raw tag for the download path and
  strip the optional 'v' only for asset-filename substitution
- Add target_musl/target_gnu per-arch (x86_64/aarch64/armv7l)
- bat/zoxide use static musl builds (no glibc deps); delta ships gnu-only
- Verbose 'gh installing <bin> (<tag> from <repo>)' / FAIL lines
- Bump ZSHRC_BOOTSTRAP_VERSION 3 -> 4 so existing boxes re-run the
  bootstrap and pick up the new fallbacks

Verified end-to-end: bat 0.26.1, zoxide 0.10.0, delta 0.19.2 all
download, extract, install, and run from a temp HOME.
2026-07-29 12:11:31 -04:00

127 lines
7.2 KiB
Markdown

# 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 `zshrc` drives 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, `zshrc` and `starship.toml` are re-pulled from the repo and applied if changed (downloaded files are validated with `zsh -n` before 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`](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`](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.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.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`:
```bash
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:
```bash
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; `zi` opens the fzf picker. `cd` still works.
- **bat** — `alias cat='bat'`, `BAT_THEME=Monokai Extended`, and `MANPAGER` set so `man` pages are colored and paginated by bat.
- **delta** — `GIT_PAGER=delta` so `git diff`/`log`/`show` render side-by-side with syntax highlighting. (Not aliased to `diff` — delta is a pager reading diff input on stdin, not a `diff a b` replacement.)
## 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:
1. **zshrc** — re-downloaded, validated with `zsh -n`, and applied via `exec zsh` only if it differs from `~/.zshrc`.
2. **starship.toml** — re-downloaded and moved to `~/.config/starship.toml` if changed (applied live on the next prompt render; no shell reload needed).
3. **tmux.conf** — downloaded once on first shell start if `~/.config/tmux/tmux.conf` and `~/.config/byobu/.tmux.conf` are both absent.
4. **bootstrap** — runs (`zshrc-bootstrap.zsh`) when `ZSHRC_BOOTSTRAP_VERSION` in `zshrc` doesn'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` | `4` | 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
```bash
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
```