A portable, cross-platform configuration managed with chezmoi. Optimised for macOS, Arch Linux (CachyOS), and WSL, with Fish as the primary shell and clean fallbacks for Zsh, Bash, and POSIX sh.
On a fresh machine:
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply andycarlbergThis downloads a standalone chezmoi binary, prompts for a few configuration values, then runs all install scripts (Homebrew, packages, shell default, SSH config) autonomously.
| Prompt | Default | Purpose |
|---|---|---|
| — | Git identity | |
| Full name | Andy Carlberg | Git identity |
| Work machine? | false | Enables work-specific SSH config |
| Personal GitHub SSH host | github.com | Host alias for personal key on work machines |
| Install packages and tools? | true | Set false for config-only setup (skips Homebrew, packages, mise) |
| Set fish as default shell? | true | Runs chsh to set fish as login shell |
| Category | Tools |
|---|---|
| Primary shell | Fish |
| Fallback shells | Zsh, Bash, POSIX sh |
| Editor | Helix (hx) |
| Terminal | Ghostty |
| Multiplexer | Zellij |
| File manager | Yazi |
| Prompt | Starship (Fish, Zsh, Bash) |
| Runtime manager | Mise (Node, Python, Go) |
| Package manager | Homebrew (macOS + Linux), Pacman/Paru (Arch), Apt (Debian) |
The core design goal is a single source of truth for configuration that all four shells consume. Fish cannot source POSIX files natively, so there is a defined boundary:
| File | Shared how | Available in |
|---|---|---|
env_vars |
. ~/.shell/env_vars / posix_source |
sh, bash, zsh, fish |
interactive_aliases |
. ~/.shell/interactive / posix_source |
sh, bash, zsh, fish |
interactive_functions |
. ~/.shell/interactive |
sh, bash, zsh |
env |
. ~/.shell/env |
sh, bash, zsh |
common_paths.tmpl |
. ~/.shell/env |
sh, bash, zsh |
Fish paths and Homebrew/Mise activation live in dot_config/fish/conf.d/env.fish since they require fish-native syntax.
The practical rule: command shortcuts go in interactive_aliases (all shells get them); logic goes where it lives (fish functions for fish, POSIX functions for fallback shells).
sh: ~/.profile → ~/.sh/env → ~/.shell/env
$ENV → ~/.sh/interactive → ~/.shell/interactive
bash: ~/.bash_profile → ~/.bash/env → ~/.shell/env
→ ~/.bash/interactive → ~/.shell/interactive
~/.bashrc → ~/.bash/env + ~/.bash/interactive
zsh: ~/.zshenv → ~/.zsh/env → ~/.shell/env
~/.zshrc → ~/.zsh/interactive → ~/.shell/interactive
fish: ~/.config/fish/conf.d/env.fish (paths, brew, mise, posix_source env_vars)
~/.config/fish/conf.d/interactive.fish (posix_source aliases, starship, fzf)
.chezmoi.toml.tmpl— prompts for identity and machine context once per machine usingpromptStringOnce/promptBoolOncedot_shell/common_paths.tmpl— generates PATH entries from thepathslist in.chezmoidata/packages.yamldot_config/mise/config.toml.tmpl— runtime tool versions
On work machines with a custom github_ssh_host, chezmoi manages ~/.ssh/config.d/github.conf with the personal GitHub host alias (e.g. github.com-personal → github.com via a specific SSH key). A run_once_after_ script adds Include ~/.ssh/config.d/* to ~/.ssh/config. The chezmoi repo remote is automatically converted to SSH using the configured host alias.
All install scripts (except fisher) are skipped when install_packages = false.
| Script | Trigger | Purpose |
|---|---|---|
run_once_install-homebrew.sh.tmpl |
Once | Installs Homebrew |
run_onchange_install-packages.sh.tmpl |
packages.yaml changes | Installs OS packages |
run_onchange_after_install-mise-tools.sh.tmpl |
mise config changes | Installs runtime tools |
run_onchange_after_install-fisher.sh.tmpl |
fish_plugins changes | Bootstraps fisher and syncs plugins |
run_once_after_set-default-shell.sh.tmpl |
Once | Sets fish as login shell |
run_once_after_configure-ssh-includes.sh.tmpl |
Once (work machines) | Wires up SSH config.d |
run_after_configure-git-remote.sh.tmpl |
Always | Converts chezmoi remote to SSH |
| File | Purpose |
|---|---|
~/.shell/env_local |
Machine-specific env vars (sourced by all POSIX shells) |
~/.config/fish/local.fish |
Machine-specific fish config |
Personal project — fork or reference freely, use at your own risk.