The Stack
The headline tools, by role — the shell, terminal, package managers, editor, and
AI tooling this repo provisions, plus the few behavior notes worth knowing. The full
list lives in the Brewfile
and uv_tools.txt.
Shell
fish is the login shell by default;
zsh is a fully-supported, selectable opt-in
(install.sh --shell zsh, persisted for the next run). Both config trees are always
stowed regardless of which one is selected, each wired to the same curated set of
modern replacements.
| Tool | Role |
|---|---|
| fish | The default login shell |
| zsh | Opt-in login shell, Homebrew-managed like fish |
| tide | fish prompt (Fisher-managed) |
| starship | zsh cross-shell prompt |
| zinit | zsh plugin manager (autosuggestions, syntax highlighting) |
| fzf.fish | fzf key bindings for fish |
| atuin | SQLite shell history with search |
| zoxide | Smarter cd that learns your habits |
| eza | Modern ls with a git column and icons |
| bat | cat with syntax highlighting |
| fd | Friendly, fast find |
| ripgrep | Fast recursive grep (rg) |
| sd | Intuitive find-and-replace (sane sed) |
| jq | Command-line JSON processor |
| jless | Interactive collapsible JSON/YAML viewer |
| delta | Syntax-highlighting pager for git |
| difftastic | Structural (AST-aware) diff, used as git difftool |
Behavior notes
- atuin owns ++ctrl+r++ (SQLite history search) in both shells; up-arrow stays normal shell history.
- eza aliases
ls/ll/la/ltin interactive shells. - zoxide is initialized in
config.fish(fish) or.zshrc(zsh) — no longer a Fisher plugin. - fish's Tide prompt and zsh's Starship prompt both fall back to a plain prompt inside VS Code's terminal, which otherwise breaks AI terminal tool output parsing.
- zsh gains inline autosuggestions and command syntax highlighting via zinit-managed plugins — fish has these built in.
Terminal & multiplexer
| Tool | Role |
|---|---|
| iTerm2 | Terminal emulator (macOS only) |
| tmux | Terminal multiplexer |
| TPM | tmux plugin manager |
| extrakto | Fuzzy-extract scrollback text (prefix + Tab) |
| tmux-yank | Copy selections to the system clipboard |
| vim-tmux-navigator | Ctrl-h/j/k/l between panes and vim splits |
| MesloLGS NF | Nerd Font for the iTerm2 profile |
iTerm reads its preferences straight from the tracked iterm2/ folder — macOS only,
skipped on Linux/WSL2. tmux plugins are declared in tmux.conf and installed by TPM
during the bootstrap on every OS.
Package managers
Homebrew
Formulae, GUI casks, and fonts — all declared in the Brewfile, installed with
brew bundle. On Linux/WSL2, install.sh self-bootstraps Homebrew's own Linux build
(/home/linuxbrew/.linuxbrew) the same way; Homebrew's Linux build has no cask support,
so --core (formulae only, casks stripped) is required there, not just preferred.
uv
Python toolchain and CLI tools (uv tool install from uv_tools.txt):
ansible,
ansible-dev-tools (molecule),
checkov,
commitizen,
copier,
jc,
playwright,
prek,
reuse,
rumdl,
serena (self-hosted MCP server, pinned to a commit SHA),
and yq.
Editor
VS Code, with extensions declared in the Brewfile so they install with everything else.
| Extension | Role |
|---|---|
| Ruff | Python lint + format |
| Pylance | Python language server |
| GitLens | Git blame / history / authorship lenses |
| Even Better TOML | TOML support |
| rumdl | Rust Markdown linter/formatter |
| Prettier | Formatter for JSON/YAML/web (Markdown scoped off) |
| ShellCheck | Shell static analysis in the editor |
| hadolint | Dockerfile linter |
| EditorConfig | Apply per-project .editorconfig rules |
rumdl vs Prettier
Both format Markdown, so the split is explicit: rumdl owns .md, Prettier handles
everything else (prettier.disableLanguages: ["markdown"] in the generated settings).
Settings Sync
settings.json is generated at install time from the tracked vscode_settings.json
baseline (see Architecture) — it's no longer a stowed symlink. If
VS Code Settings Sync is also on, a cloud pull wins — pick one source of truth, not both
for the same file.
AI tooling
Claude Code
Installed via the native, self-updating installer (chosen over a brew cask precisely so it
stays current). MCP servers are declared in claude_mcp.json and registered at install
time.
Ollama — a local role fleet for GitLens & Claude offload
The installer provisions a fleet of role models declared in scripts/ollama_models.sh:
- a fast tier (
qwen3:4b-instruct-2507-q4_K_M), which also serves GitLens' AI features entirely offline — no cloud key, no Copilot seat; - a vision tier (
qwen3-vl:4b-instruct); and - on Apple Silicon with >32 GB unified memory (macOS 13+), the big pair:
bulk coding (
qwen3.5:35b-a3b-coding-nvfp4, MLX) and a brainstorm generalist (gemma4:26b).
All pulls are idempotent. The ollm CLI fronts the fleet — it picks the model by role, disables hidden thinking by default (the reasoning models otherwise burn their whole token budget on it), and a SessionStart hook shows Claude Code the live roster so bulk mechanical work gets routed off the paid token budget.