- Shell 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .gitignore | ||
| aliases.zsh | ||
| completions.zsh | ||
| env.zsh | ||
| functions.zsh | ||
| integrations.zsh | ||
| lib.zsh | ||
| local.zsh.example | ||
| options.zsh | ||
| plugins.txt | ||
| plugins.zsh | ||
| prompt.zsh | ||
| README.md | ||
| theme.toml | ||
| update.zsh | ||
| zshrc | ||
zsh config
A modular, stand-alone zsh setup: small focused files, guard everything
(has_command / alias_if — a missing tool never breaks the shell), only add
PATH entries that exist, and one config for linux + macOS. Windows/WSL is
handled where trivial but not a priority.
Mostly written with LLM assistance; all generated code has been reviewed.
Wiring it up
Everything is sourced through one clear entry file: zshrc. Point your real
~/.zshrc at it. Assuming this folder ends up at ~/.config/zsh:
echo 'source ~/.config/zsh/zshrc' >> ~/.zshrc
The config finds its own directory (${ZSH_CFG_DIR}), so you can put it anywhere
— no paths are hardcoded. Then open a new shell.
What's where
| File | Responsibility |
|---|---|
zshrc |
Entry point. Resolves its own dir, sources the modules in order. |
lib.zsh |
Helpers + OS detection: has_command, alias_if, alias_unless_disabled, path_add, note, IS_LINUX/IS_MACOS/IS_WINDOWS. Also loads the persistent config state (below). |
env.zsh |
Env vars (EDITOR=micro, cargo paths…) + PATH; sources local.zsh if present; Homebrew via brew shellenv (linuxbrew and both macOS arches); jenv's shims ahead of Homebrew on macOS. |
update.zsh |
Rate-limited git pull --ff-only of this config from its remote on interactive shell start; exposes update-config for a manual on-demand run. |
local.zsh |
Per-machine aliases, configs go here (API keys, etc). Gitignored, machine-local — never commit. Copy from local.zsh.example. |
local.zsh.example |
Committed template listing the keys this config expects. |
options.zsh |
setopts, history. |
completions.zsh |
compinit + carapace. |
aliases.zsh |
Modern-tool swaps + editors→micro (all guarded). |
functions.zsh |
clipboard, moodle, list_optional_deps (Arch-only), alias-disable/alias-enable, config. |
integrations.zsh |
thefuck, mcfly, upkg, zoxide, broot, jenv — guarded eval/source hooks. |
prompt.zsh |
oh-my-posh + theme.toml, with a native fallback prompt. |
plugins.zsh |
Antidote bundle (autosuggestions, syntax-highlighting, history-substring-search) + lavender highlight theming. |
plugins.txt |
The antidote plugin list. |
theme.toml |
oh-my-posh theme. |
generated/ |
Auto-created caches & plugin clones. Gitignored — don't commit. |
Dependencies
Nothing is required — missing tools are skipped. To get the full experience, install (all available via Homebrew on linux & macOS, or your distro):
- Prompt/completions:
oh-my-posh,carapace - CLI swaps:
eza,bat,fd,dust,broot,ripgrep(rg),procs,gping,btop,micro - Integrations:
thefuck,mcfly - Plugins:
git(antidote auto-clones the rest on first run)
Per-machine aliases, configs
env.zsh sources local.zsh if it exists, and nothing else depends on it. On
a fresh clone, env.zsh auto-creates local.zsh from local.zsh.example the
first time it's missing, then sources it right away — no manual cp needed.
The copied file nags you (in yellow, on every interactive shell start) to
edit it and reload, until you do:
$EDITOR ~/.config/zsh/local.zsh
source ~/.config/zsh/local.zsh
local.zsh is gitignored; only the .example template is committed.
Managing aliases & settings
Every swap in aliases.zsh is also individually toggleable, independent of
whether its target tool is installed — e.g. you have btop but don't want
htop remapped to it:
alias-disable htop # turn it off (also unaliases it in the current shell)
alias-enable htop # turn it back on (run `exec zsh` to re-apply)
Both validate the name against aliases.zsh's ZSH_CFG_MANAGED_ALIASES list
and print a clear success/failure message. State is a plain-text list of names
in generated/disabled_aliases.conf (gitignored, machine-local, one name per
line, # comments allowed) — lib.zsh reads it at shell start; no file means
no disables.
The some optional tools are missing startup notice (and any other collected
note) can be toggled off:
config notices off # silence the summary
config notices on # (default)
config notices status
This is backed by a small general-purpose key=value store — config set/get/ unset/list <key> [value] — in generated/settings.conf (gitignored,
machine-local), for future shell-behaviour toggles beyond notices.
Auto-update
Every interactive shell start, update.zsh checks (at most once every 3h,
tracked in generated/last_update_check) whether this repo can be
fast-forwarded from its remote, and pulls if so — so a fresh terminal is
usually already on the latest commit. It only ever does git pull --ff-only:
if the working tree is dirty or history has diverged, it skips the pull and
raises a note instead of touching anything. It runs first in the
interactive load order, so a pulled update is picked up by the rest of that
same shell's startup, not just the next one.
Run it on demand, bypassing the rate limit, with:
update-config
Turn it off like any other config toggle:
config auto-update off
config auto-update on # (default)
config auto-update status
Notes
- History lives at
~/.zsh_history— outside this managed dir on purpose, so chezmoi/git ignore it and it can't sync-conflict. - Plugins are managed by antidote,
bootstrapped automatically into
generated/on first launch. Add a plugin by editingplugins.txt; the static bundle rebuilds when that file changes. - Per-OS configs: when you split linux/macOS later, add an
os.$(uname).zshsource line near the end ofzshrc—lib.zshalready exportsIS_LINUX/IS_MACOSfor inline branching in the meantime.