feat(install): switch to Homebrew for the CLI toolchain

Ubuntu 24.04's apt versions of fzf/fd/bat/eza/zoxide/ripgrep/tmux/nvim/
lazygit/starship are frozen at April 2024 — and the previous GitHub-
release downloads went stale the moment you stopped re-running the
installer. Homebrew on Linux fixes both: always-latest releases and a
single 'brew upgrade' to update the whole CLI stack.

Two-tier install:
  apt   - zsh + base plumbing + WezTerm (vendor repo) + Brave Beta
          (vendor repo). Vendor repos auto-update via 'apt upgrade'.
  brew  - fzf fd bat eza zoxide ripgrep tmux neovim lazygit starship
          gh zsh-syntax-highlighting zsh-autosuggestions
  nvm   - official installer (pinned NVM_VERSION)
  tpm   - tmux plugin manager clone

New files:
  install/Brewfile - bundle for 'brew bundle'
  install/lib/brew.sh - Homebrew bootstrap + brew bundle
  install/lib/extras.sh - nvm + tpm
  install/install.sh - rewired entry point with --packages-only,
    --dotfiles-only, --help
  install/README.md - new docs for the two-tier strategy

.zshrc:
  - Source brew shellenv first when present, so brew bins win on PATH
  - 'update' alias now: brew upgrade && sudo apt update && sudo apt upgrade
    (previously apt-only; before that pacman-only)

Drops install/lib/packages.sh entries that the now-Brewfile-managed tools
duplicated, and removes the GitHub-release tarball install path.
This commit is contained in:
Claude 2026-06-10 16:54:47 +00:00
parent d1a289d6ce
commit 096c3c8afa
No known key found for this signature in database
8 changed files with 124 additions and 188 deletions

8
.zshrc
View file

@ -1,3 +1,9 @@
# Homebrew (Linux) — must come first so brew-installed tools and plugin
# paths below resolve.
if [ -x /home/linuxbrew/.linuxbrew/bin/brew ]; then
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
fi
# Theme (kanagawa variants: dragon|wave)
export KANAGAWA_THEME="${KANAGAWA_THEME:-wave}"
case "${KANAGAWA_THEME}" in
@ -101,7 +107,7 @@ alias vim="nvim"
alias crq="cargo run -q"
alias sudo="sudo "
alias lg="lazygit"
alias update="sudo apt update && sudo apt upgrade -y"
alias update="brew upgrade && sudo apt update && sudo apt upgrade -y"
if command -v tmux &>/dev/null && [ -z "$TMUX" ]; then
tmux attach -t default 2>/dev/null || tmux new -s default

View file

@ -24,23 +24,18 @@ ln -sfn ~/dotfiles/.gitconfig ~/.gitconfig
## Install
On Pop!_OS / Ubuntu 24.04, run the bundled installer — it sets up apt
packages, third-party apt repos (WezTerm, Brave Beta, GitHub CLI),
GitHub-release binaries (Neovim, Lazygit, Starship), nvm + tpm, and links
every config file:
On Pop!_OS / Ubuntu 24.04, run the bundled installer. It uses **apt** for
the system base + GUI apps (WezTerm, Brave Beta) and **Homebrew** for the
CLI toolchain (fzf, fd, bat, eza, zoxide, ripgrep, tmux, neovim, lazygit,
starship, gh, zsh plugins) so those tools stay current — one
`brew upgrade` updates everything.
```bash
~/dotfiles/install/install.sh
```
See [`install/README.md`](install/README.md) for details, flags, and the
full package list.
If you want to install manually instead, the dotfiles assume: `zsh
zsh-syntax-highlighting zsh-autosuggestions tmux fzf fd-find bat eza zoxide
ripgrep neovim lazygit starship` plus WezTerm and Brave Beta.
Install nvm separately: https://github.com/nvm-sh/nvm
See [`install/README.md`](install/README.md) for flags and the full
package list. The `update` alias runs `brew upgrade && sudo apt upgrade`.
## Theme

14
install/Brewfile Normal file
View file

@ -0,0 +1,14 @@
# CLI toolchain — always latest via `brew upgrade`.
brew "fzf"
brew "fd"
brew "bat"
brew "eza"
brew "zoxide"
brew "ripgrep"
brew "tmux"
brew "neovim"
brew "lazygit"
brew "starship"
brew "gh"
brew "zsh-syntax-highlighting"
brew "zsh-autosuggestions"

View file

@ -1,17 +1,28 @@
# Pop!_OS install
# Pop!_OS / Ubuntu install
Installs the tools these dotfiles assume on a fresh **Pop!_OS 24.04** (or any
Debian/Ubuntu 24.04 derivative) and symlinks the configs into place. No
desktop-environment setup — Pop's Cosmic DE handles that.
A small, idempotent installer that gets a fresh Pop!_OS 24.04 (or any
Ubuntu 24.04 / Debian-derivative) to the state these dotfiles assume.
## Two-tier strategy
| Source | What lives there | Why |
|--------|------------------|-----|
| **apt** | `zsh`, `git`, `curl`, `build-essential`, `wl-clipboard`, `wezterm`, `brave-browser-beta` | System base + GUI vendor apps. Vendor apt repos auto-update Brave/WezTerm with `apt upgrade`. |
| **Homebrew** | `fzf` `fd` `bat` `eza` `zoxide` `ripgrep` `tmux` `neovim` `lazygit` `starship` `gh` `zsh-syntax-highlighting` `zsh-autosuggestions` | CLI toolchain. Ubuntu 24.04's apt versions are frozen at April 2024; brew always has latest. One `brew upgrade` updates all of them. |
| **nvm** | Node.js runtime | The standard nvm one-liner — `.zshrc` already sources `~/.nvm/nvm.sh`. |
| **tpm** | tmux plugin manager | Clone of `tmux-plugins/tpm` so the bundled `tmux.conf` works on first launch. |
GitHub-release-binary downloads (the previous approach for nvim/lazygit/
starship) have been retired — they ran latest at install time then went
stale. Brew solves that.
## Environment required
- **Pop!_OS 24.04** (or Ubuntu 24.04 / Debian-derived). The installer aborts
if `apt-get` isn't present.
- A regular user with **`sudo`** — **not** root.
- Internet (the installer adds third-party apt repos and pulls binary
releases from GitHub).
- No special filesystem or bootloader requirements.
- Pop!_OS 24.04 (or Debian/Ubuntu derivative) — preflight aborts if
`apt-get` is missing.
- A regular user with `sudo`**not** root.
- Outbound HTTPS to `apt.fury.io`, `brave.com`, `cli.github.com`,
`github.com`, `raw.githubusercontent.com`, and Ubuntu mirrors.
## Install
@ -20,75 +31,53 @@ git clone https://github.com/brianpooe/dotfiles.git ~/dotfiles
~/dotfiles/install/install.sh
```
Then open a new shell (or log out + back in) so `zsh` becomes your login
shell. On the first `tmux` launch, hit **Prefix + I** to fetch tpm plugins.
Then open a new terminal (or log out + back in) so the new login shell
takes effect.
### Flags
```bash
install/install.sh # full install
install/install.sh --packages-only # only install tools (no symlinks)
install/install.sh --dotfiles-only # only link dotfiles + tpm/nvm + chsh
install/install.sh --packages-only # apt + brew + nvm + tpm, skip symlinks
install/install.sh --dotfiles-only # symlink + chsh + tpm + nvm, skip packages
install/install.sh --help
```
`--dotfiles-only` is useful for re-syncing configs on a machine that already
has all the tools.
## Keeping current
### Configuration (environment variables)
```bash
update # alias: brew upgrade && sudo apt upgrade
```
| Variable | Default | Purpose |
|----------|---------|---------|
| `DOTFILES_DIR` | repo root (auto-detected) | Source dir for symlinks |
| `NEOVIM_VERSION` | `stable` | Tag from neovim/neovim releases (`stable`, `nightly`, `v0.11.0`, …) |
| `LAZYGIT_VERSION` | _(latest)_ | Specific lazygit version (e.g. `0.44.1`); blank = query GitHub |
| `NVM_VERSION` | `v0.40.1` | Pinned nvm release |
## What gets installed
**apt packages:** `zsh zsh-autosuggestions zsh-syntax-highlighting tmux fzf
fd-find bat eza zoxide ripgrep git curl wget ca-certificates gnupg
build-essential unzip xz-utils wl-clipboard`
**Third-party apt repos (added with signed keyrings):**
- **WezTerm**`apt.fury.io/wez`
- **Brave Beta**`brave-browser-apt-beta.s3.brave.com`
- **GitHub CLI**`cli.github.com/packages`
**GitHub-release binaries (not in apt or too stale in apt):**
- **Neovim**`/opt/nvim/`, symlinked to `/usr/local/bin/nvim`
- **Lazygit**`/usr/local/bin/lazygit`
- **Starship** — official installer (`starship.rs/install.sh`)
**Per-user helpers:**
- **nvm**`~/.nvm/`
- **tpm**`~/.tmux/plugins/tpm/`
**Compatibility shims (Debian package naming):**
- `/usr/local/bin/fd``fdfind`
- `/usr/local/bin/bat``batcat`
So `FZF_DEFAULT_COMMAND="fd ..."` and the `bat`/`fd` references in
`.zshrc`/nvim resolve without aliasing tricks.
**Dotfile symlinks:** `nvim, tmux, starship, lazygit, wezterm, zed →
~/.config/...`; `.config/.ideavimrc → ~/.ideavimrc`; `.zshrc`, `.gitconfig`
`~`. Pre-existing targets are backed up to `*.pre-install.<timestamp>`.
**Login shell:** switched to `zsh`. `.zshrc` auto-attaches `tmux`.
## Theming
Kanagawa via the `KANAGAWA_THEME` env var in `~/.zshrc` (`wave` or `dragon`).
WezTerm, neovim, tmux, and starship all read from that env chain.
The CLI tools come from brew, so they stay on bleeding-edge stable. Brave
and WezTerm come from vendor apt repos so `apt upgrade` always has the
latest of those too.
## Layout
```
install/
install.sh entry point
lib/common.sh helpers (apt, symlink-with-backup, signed repo adder)
lib/packages.sh apt packages + WezTerm/Brave/gh repos
lib/extras.sh Neovim, Lazygit, Starship, nvm, tpm
lib/dotfiles.sh symlinks + chsh zsh
Brewfile CLI toolchain bundle (brew owns these)
lib/common.sh helpers: apt_install, add_apt_repo, backup_and_link
lib/packages.sh apt base + WezTerm + Brave Beta vendor repos
lib/brew.sh install Homebrew + `brew bundle`
lib/extras.sh nvm + tpm
lib/dotfiles.sh symlink dotfiles + chsh zsh
```
## What the installer does, in order
1. **preflight** — verify apt + not-root + sudo + curl.
2. **apt base**`zsh git curl wget ca-certificates gnupg build-essential procps file unzip xz-utils wl-clipboard`.
3. **WezTerm apt repo**`apt install wezterm`.
4. **Brave Beta apt repo**`apt install brave-browser-beta`.
5. **Homebrew install** (NONINTERACTIVE) + `brew bundle` against `Brewfile`.
6. **nvm** (pinned `$NVM_VERSION`, default `v0.40.1`).
7. **tpm** clone to `~/.tmux/plugins/tpm`.
8. **Symlink** `nvim tmux starship lazygit wezterm zed → ~/.config/...`;
`.config/.ideavimrc → ~/.ideavimrc`; `.zshrc`, `.gitconfig → ~`.
9. **chsh** login shell to zsh.
Pre-existing config targets get backed up to `*.pre-install.<timestamp>`,
not deleted.

View file

@ -2,17 +2,18 @@
# Pop!_OS / Ubuntu installer for these dotfiles.
#
# What it does (idempotent — safe to re-run):
# 1. Installs apt packages: zsh + plugins, tmux, fzf, fd-find, bat, eza,
# zoxide, ripgrep, git, curl, build-essential, wl-clipboard.
# 2. Adds third-party apt repos and installs: WezTerm, Brave Beta, GitHub CLI.
# 3. Installs tools not packaged in apt: Neovim (latest), Lazygit, Starship.
# 4. Installs nvm and tmux plugin manager (tpm).
# 1. apt: system base (zsh, git, curl, build-essential, wl-clipboard).
# 2. Vendor apt repos: WezTerm, Brave Beta (GUI apps stay on apt).
# 3. Homebrew + Brewfile: fzf, fd, bat, eza, zoxide, ripgrep, tmux,
# neovim, lazygit, starship, gh, zsh plugins — always latest,
# updated later with a single `brew upgrade`.
# 4. nvm + tmux plugin manager (tpm).
# 5. Symlinks dotfiles into ~ and ~/.config.
# 6. Switches login shell to zsh.
#
# Usage:
# install/install.sh Full install
# install/install.sh --packages-only Only the package + tool install
# install/install.sh --packages-only Only packages/tools (apt + brew)
# install/install.sh --dotfiles-only Only link dotfiles + tpm/nvm + chsh
# install/install.sh --help
@ -21,11 +22,12 @@ set -eEo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib/common.sh"
source "$SCRIPT_DIR/lib/packages.sh"
source "$SCRIPT_DIR/lib/brew.sh"
source "$SCRIPT_DIR/lib/extras.sh"
source "$SCRIPT_DIR/lib/dotfiles.sh"
usage() {
sed -n '2,17p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
sed -n '2,18p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
}
MODE=all
@ -51,6 +53,7 @@ main() {
case $MODE in
packages)
install_all_packages
install_brew_packages
install_all_extras
;;
dotfiles)
@ -61,6 +64,7 @@ main() {
;;
all)
install_all_packages
install_brew_packages
install_all_extras
link_dotfiles
set_zsh_as_shell
@ -69,6 +73,7 @@ main() {
info "Done. Open a new shell (or log out + back in) to pick up the new login shell."
info "First tmux launch: prefix + I to fetch tpm plugins."
info "Keep tools current with: brew upgrade && sudo apt upgrade"
}
main

22
install/lib/brew.sh Normal file
View file

@ -0,0 +1,22 @@
#!/bin/bash
# Homebrew on Linux: install brew itself, then everything in the Brewfile.
# Brew owns the CLI toolchain so `brew upgrade` always gets latest versions.
BREW_PREFIX="/home/linuxbrew/.linuxbrew"
install_homebrew() {
if [[ -x $BREW_PREFIX/bin/brew ]]; then
info "Homebrew already installed"
else
info "Installing Homebrew..."
NONINTERACTIVE=1 bash -c \
"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
eval "$("$BREW_PREFIX/bin/brew" shellenv)"
}
install_brew_packages() {
install_homebrew
info "Installing Brewfile bundle..."
brew bundle --file="$DOTFILES_DIR/install/Brewfile"
}

View file

@ -1,67 +1,8 @@
#!/bin/bash
# Tools not packaged in apt (or where apt has stale versions):
# - Neovim : apt's is too old for this nvim config; install latest release
# - Lazygit : not in apt; install latest release binary
# - Starship : not in apt; use the official install script
# - nvm : official installer
# - tpm : git clone
# Per-user helpers not managed by brew: nvm (official installer) + tpm.
NEOVIM_VERSION="${NEOVIM_VERSION:-stable}" # 'stable', 'nightly', or 'v0.11.0' etc.
LAZYGIT_VERSION="${LAZYGIT_VERSION:-}" # empty -> latest
NVM_VERSION="${NVM_VERSION:-v0.40.1}"
install_neovim() {
if command -v nvim >/dev/null 2>&1 && nvim --version | head -1 | grep -qE 'v0\.(1[0-9]|[2-9][0-9])'; then
info "Neovim 0.10+ already installed: $(nvim --version | head -1)"
return
fi
info "Installing Neovim ($NEOVIM_VERSION) from GitHub release..."
local tmp tarball
tmp="$(mktemp -d)"
tarball="$tmp/nvim.tar.gz"
curl -fsSL --retry 3 \
"https://github.com/neovim/neovim/releases/download/${NEOVIM_VERSION}/nvim-linux-x86_64.tar.gz" \
-o "$tarball"
sudo rm -rf /opt/nvim
sudo mkdir -p /opt
sudo tar -C /opt -xzf "$tarball"
sudo mv /opt/nvim-linux-x86_64 /opt/nvim
sudo ln -sf /opt/nvim/bin/nvim /usr/local/bin/nvim
rm -rf "$tmp"
info "Neovim installed: $(/usr/local/bin/nvim --version | head -1)"
}
install_lazygit() {
if command -v lazygit >/dev/null 2>&1; then
info "lazygit already installed: $(lazygit --version | head -c 80)"
return
fi
info "Installing lazygit from GitHub release..."
local version="$LAZYGIT_VERSION" tmp tarball
if [[ -z $version ]]; then
version="$(curl -fsSL https://api.github.com/repos/jesseduffield/lazygit/releases/latest |
grep -Po '"tag_name":\s*"v\K[^"]*' | head -1)"
fi
[[ -n $version ]] || die "Could not determine latest lazygit version"
tmp="$(mktemp -d)"
tarball="$tmp/lazygit.tgz"
curl -fsSL --retry 3 \
"https://github.com/jesseduffield/lazygit/releases/download/v${version}/lazygit_${version}_Linux_x86_64.tar.gz" \
-o "$tarball"
tar -xzf "$tarball" -C "$tmp" lazygit
sudo install -m 0755 "$tmp/lazygit" /usr/local/bin/lazygit
rm -rf "$tmp"
}
install_starship() {
if command -v starship >/dev/null 2>&1; then
info "starship already installed"
return
fi
info "Installing starship from official installer..."
curl -fsSL https://starship.rs/install.sh | sh -s -- --yes
}
install_nvm() {
if [[ -s $HOME/.nvm/nvm.sh ]]; then
info "nvm already installed"
@ -84,9 +25,6 @@ install_tpm() {
}
install_all_extras() {
install_neovim
install_lazygit
install_starship
install_nvm
install_tpm
}

View file

@ -1,28 +1,20 @@
#!/bin/bash
# apt packages + third-party apt repos (WezTerm, Brave Beta, GitHub CLI).
# apt: system base + GUI apps from vendor repos (WezTerm, Brave Beta).
# All CLI tools come from Homebrew (lib/brew.sh) so they stay current.
APT_PACKAGES=(
# Shell + plugins
# Login shell (system-level so chsh can point at /usr/bin/zsh)
zsh
zsh-autosuggestions
zsh-syntax-highlighting
# Terminal tooling
tmux
fzf
fd-find # binary is fdfind on Debian; we symlink to fd
bat # binary is batcat on Debian; we symlink to bat
eza # available in 24.04 universe
zoxide
ripgrep
# Core
# Core plumbing + Homebrew prerequisites
git
curl
wget
ca-certificates
gnupg
build-essential # nvm node-gyp, cargo builds, etc.
build-essential
procps
file
unzip
xz-utils
@ -34,18 +26,6 @@ install_apt_packages() {
apt_update_once
info "Installing apt packages (${#APT_PACKAGES[@]} packages)..."
apt_install "${APT_PACKAGES[@]}"
# Debian renames fd -> fdfind and bat -> batcat. Make the canonical names
# work so the dotfiles' env vars (FZF_DEFAULT_COMMAND="fd ...") and
# FZF_CTRL_T_OPTS ("bat ...") resolve.
if command -v fdfind >/dev/null 2>&1 && ! command -v fd >/dev/null 2>&1; then
sudo ln -sf "$(command -v fdfind)" /usr/local/bin/fd
info "Linked /usr/local/bin/fd -> fdfind"
fi
if command -v batcat >/dev/null 2>&1 && ! command -v bat >/dev/null 2>&1; then
sudo ln -sf "$(command -v batcat)" /usr/local/bin/bat
info "Linked /usr/local/bin/bat -> batcat"
fi
}
install_wezterm() {
@ -72,21 +52,8 @@ install_brave_beta() {
apt_install brave-browser-beta
}
install_github_cli() {
if command -v gh >/dev/null 2>&1; then
info "GitHub CLI already installed"
return
fi
add_apt_repo githubcli-archive-keyring \
https://cli.github.com/packages/githubcli-archive-keyring.gpg \
"deb [arch=$(dpkg --print-architecture) signed-by=$KEYRINGS_DIR/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main"
apt_update_once
apt_install gh
}
install_all_packages() {
install_apt_packages
install_wezterm
install_brave_beta
install_github_cli
}