No description
Find a file
Freydis Mende a53f899f13 fix(setup): comment out oh-my-zsh's own source line in .zshrc
The Oh My Zsh installer's template .zshrc sources oh-my-zsh.sh itself, and the managed block sources it again. The second compinit runs with a different ZSH_CUSTOM/fpath, which invalidates .zcompdump on every start - ~6 s per shell on a Raspberry Pi. setup_zsh_custom now comments out any source line above the managed block, as already done by hand on the Mac.
2026-10-25 16:45:39 +01:00
zsh_custom fix(atuin): install upstream release on Linux and log in during setup 2026-10-25 16:28:31 +01:00
.dircolors-256dark zshrc: add .dircolors-256dark 2016-10-04 16:28:45 +02:00
.gitconfig Add modern CLI tool replacements: eza, fd, delta, dust/duf, zoxide, tealdeer 2026-09-24 15:56:41 +02:00
.gitignore Remove legacy Gentoo/rxvt/vala-era cruft 2026-09-24 15:19:36 +02:00
.lessfilter Fix bat/lesspipe binary naming on Debian/Ubuntu 2026-09-24 15:26:31 +02:00
.vimrc Remove legacy Gentoo/rxvt/vala-era cruft 2026-09-24 15:19:36 +02:00
atuin-config.toml add atuin sync address 2026-10-05 18:02:00 +02:00
bat-config Add atuin, starship, and sd to setup.sh 2026-10-02 09:26:27 +02:00
README.md fix(atuin): install upstream release on Linux and log in during setup 2026-10-25 16:28:31 +01:00
ripgreprc Add atuin, starship, and sd to setup.sh 2026-10-02 09:26:27 +02:00
setup.sh fix(setup): comment out oh-my-zsh's own source line in .zshrc 2026-10-25 16:45:39 +01:00
ssh_config Reorganize personal SSH hosts 2026-09-24 15:20:32 +02:00
starship.toml Add atuin, starship, and sd to setup.sh 2026-10-02 09:26:27 +02:00
tmux.conf Switch from screen to tmux 2026-09-24 15:22:01 +02:00

dotfiles

Personal dotfiles, used on macOS and Debian/Ubuntu.

Quick start

git clone <this repo> ~/git/dotfiles
~/git/dotfiles/setup.sh
exec zsh -l

setup.sh installs the prerequisites below, creates the symlinks, and wires up $ZSH_CUSTOM in ~/.zshrc. It's idempotent - safe to re-run, and backs up (.bak.<timestamp>) rather than overwrites anything already in place at a symlink target. The steps below are what it does and why, for reference or if you'd rather run them by hand.

1. Install prerequisites

Tool macOS Debian/Ubuntu Why
Homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" — Used to install most of the tools below. If it's not available and there's no sudo either (e.g. a locked-down work Mac), setup.sh bootstraps pixi instead - installs entirely under $HOME, no admin rights needed
Oh My Zsh sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" same Framework that loads everything in zsh_custom/
nvm brew install nvm see nvm's install instructions for the current install script URL Node version manager. zsh_custom/08-nvm.zsh auto-installs and pins the global default version (NVM_DEFAULT_NODE_VERSION) on first shell start
uv curl -LsSf https://astral.sh/uv/install.sh | sh same Python version/package manager. zsh_custom/12-uv.zsh auto-installs and pins the global default version (UV_DEFAULT_PYTHON_VERSION) on first shell start, and blocks bare pip/pip3 outside a venv
pnpm corepack enable pnpm (bundled with Node via nvm above) same JS package manager. zsh_custom/10-pnpm.zsh sets PNPM_HOME; zsh_custom/03-command_not_found.zsh falls back to pnpm bin for unresolved commands (also covers nx, since no separate Angular/nx CLI is installed)
Neovim brew install neovim sudo apt install neovim zsh_custom/11-settings.zsh aliases vim/vi to nvim and sets it as $EDITOR/$VISUAL when present, falls back to vim otherwise
iTerm2 download + install, then Preferences → General → Install Shell Integration — Picked up automatically by zsh_custom/05-iterm2.zsh if ~/.iterm2_shell_integration.zsh exists
Meslo Nerd Font (macOS only) brew install --cask font-meslo-lg-nerd-font — Provides the icon glyphs eza --icons (zsh_custom/02-cli.zsh) and the starship prompt (starship.toml) need - without it they render as tofu boxes. No Homebrew? setup.sh downloads the same release straight into ~/Library/Fonts instead. Pick "MesloLGS Nerd Font Mono" in your terminal's font setting after install
OrbStack (personal machines) installed by setup.sh — zsh_custom/04-containers.zsh wires up OrbStack's completions, bundled at a fixed app path
Podman (work machine only) not installed by setup.sh - install by hand Not installed by setup.sh - only needed on the work machine, install by hand there. On macOS, podman's own docs recommend the signed installer from its GitHub releases over Homebrew, since running containers needs a VM backed by admin-gated permissions either way. zsh_custom/04-containers.zsh wires up its completions (podman completion zsh) if present
bat brew install bat sudo apt install bat Used by .lessfilter for syntax-highlighted less output. Direct invocations pick up theme/style from bat-config, symlinked to ~/.config/bat/config
lesspipe brew install lesspipe already bundled with less Invokes .lessfilter. zsh_custom/06-less.zsh sets $LESSOPEN to wire it up if found on $PATH (checks both lesspipe.sh and Debian's lesspipe binary name)
tmux brew install tmux sudo apt install tmux Terminal multiplexer, config in tmux.conf
eza brew install eza sudo apt install eza Modern ls. zsh_custom/02-cli.zsh points ll/la at it if present, falls back to plain ls otherwise
ripgrep brew install ripgrep sudo apt install ripgrep Modern recursive grep (rg). Not aliased over grep - flag semantics differ enough (e.g. -r means "replace" in rg) that it'd be a footgun. Default flags (--smart-case, search hidden files, skip .git/) come from ripgreprc, pointed to via $RIPGREP_CONFIG_PATH in zsh_custom/02-cli.zsh
fd brew install fd sudo apt install fd-find Modern find. Debian/Ubuntu installs it as fdfind; zsh_custom/02-cli.zsh aliases fd to it if the plain fd binary isn't present
delta brew install git-delta sudo apt install git-delta Syntax-highlighting pager for git diff/show/blame, wired up as core.pager in .gitconfig
dust/duf brew install dust duf sudo apt install du-dust duf Modern du (dust) and df (duf)
zoxide brew install zoxide sudo apt install zoxide Modern cd with frecency-based fuzzy jumping. zsh_custom/02-cli.zsh initializes it as a transparent cd replacement (--cmd cd) if present
tealdeer brew install tealdeer sudo apt install tealdeer Fast tldr client - example-driven cheat sheets instead of full man pages
btop brew install btop sudo apt install btop Modern htop - graphs, mouse support, per-core CPU. Not aliased over anything, just run btop directly
starship brew install starship sudo apt install starship Cross-shell prompt. Owns $PROMPT instead of oh-my-zsh - zsh_custom/11-settings.zsh sets ZSH_THEME="" and initializes it; config lives in starship.toml, symlinked to ~/.config/starship.toml
atuin brew install atuin upstream installer into ~/.atuin/bin (setup.sh does this and removes the apt package - Debian's is too old to sync with newer clients) Shell history backed by a searchable SQLite database, synced via sync_address. zsh_custom/02-cli.zsh initializes it, binding ctrl-r to its fuzzy search UI (up-arrow keeps the default history behavior); config (compact inline UI, global search scope, no update check, sync server) in atuin-config.toml, symlinked to ~/.config/atuin/config.toml. When run from a terminal, setup.sh also runs atuin login (needs the key from atuin key on another machine), imports ~/.zsh_history once and syncs
sd brew install sd sudo apt install sd Modern sed for find & replace (e.g. sd 'foo' 'bar' file.txt). Not aliased over sed - same reasoning as ripgrep/grep, syntax differs enough to be a footgun
GNU coreutils (macOS only) brew install coreutils already the default on Linux macOS ships BSD coreutils, which differ from GNU's (e.g. date -d, sed -i without a backup-suffix arg). Installed g-prefixed (gls, gsed, gdate, ...) same as Homebrew's own default, so nothing on $PATH gets silently shadowed - use explicitly by name when a script needs GNU-specific behavior. No Homebrew? setup.sh installs conda-forge's gnu-coreutils, not its plain coreutils package - that one installs unprefixed and would shadow the BSD tools
watch (macOS only) brew install watch already the default on Linux (procps) Periodically re-runs a command, showing live output - macOS doesn't ship it

Everything above is optional except Oh My Zsh — the rest is auto-detected/guarded and simply no-ops if missing.

2. Clone the repo

git clone <this repo> ~/git/dotfiles

(any path works, just update the symlink targets below accordingly)

Repo path Symlink target Command
.vimrc ~/.vimrc ln -s ~/git/dotfiles/.vimrc ~/.vimrc
.gitconfig ~/.gitconfig ln -s ~/git/dotfiles/.gitconfig ~/.gitconfig
.lessfilter ~/.lessfilter ln -s ~/git/dotfiles/.lessfilter ~/.lessfilter
tmux.conf ~/.tmux.conf ln -s ~/git/dotfiles/tmux.conf ~/.tmux.conf
starship.toml ~/.config/starship.toml mkdir -p ~/.config && ln -s ~/git/dotfiles/starship.toml ~/.config/starship.toml
bat-config ~/.config/bat/config mkdir -p ~/.config/bat && ln -s ~/git/dotfiles/bat-config ~/.config/bat/config
atuin-config.toml ~/.config/atuin/config.toml mkdir -p ~/.config/atuin && ln -s ~/git/dotfiles/atuin-config.toml ~/.config/atuin/config.toml

Not directly symlinked:

  • ssh_config — your real ~/.ssh/config already has its own Host blocks and an Include config.d/* line. Instead, drop this file into that include path: mkdir -p ~/.ssh/config.d && ln -s ~/git/dotfiles/ssh_config ~/.ssh/config.d/dotfiles.
  • .dircolors-256dark — not symlinked anywhere; zsh_custom/07-linux.zsh sources it directly from the repo via a relative path on Linux.
  • ripgreprc — not symlinked either; ripgrep doesn't look for a config file by path, only via $RIPGREP_CONFIG_PATH, which zsh_custom/02-cli.zsh points straight at this file.
  • zsh_custom/ — not symlinked either; see step 4.

4. Wire up zsh_custom

Oh My Zsh loads every *.zsh file in $ZSH_CUSTOM automatically, so instead of symlinking individual files, point $ZSH_CUSTOM at this repo. Your local ~/.zshrc (not tracked in this repo) needs:

export ZSH="$HOME/.oh-my-zsh"
ZSH_CUSTOM="$HOME/git/dotfiles/zsh_custom"
source $ZSH/oh-my-zsh.sh

ZSH_THEME and Oh My Zsh's update mode are set from within zsh_custom/11-settings.zsh, so they don't need to be set here. ZSH_THEME is set to "" there - the prompt itself comes from starship (also initialized in that file), not an oh-my-zsh theme.

5. Restart your shell

exec zsh -l

First start after a fresh clone will be slower than usual — nvm.zsh and uv.zsh will detect their pinned Node/Python versions aren't installed yet and install them automatically. Every start after that is fast.