Skip to content

Navigation Menu

Sign in
Sign up

The Zsh Module System

Gerrrt edited this page Jun 14, 2026 · 1 revision

The Zsh Module System

The zsh configuration is the heart of Core. Rather than one monolithic .zshrc, Core ships a set of focused modules under zsh/, and each OS repo's .zshrc loader sources them in a specific order. That order is load-bearing β€” getting it wrong silently breaks completion, keybindings, or the prompt.

The load order

Each OS repo's .zshrc sources the modules in exactly this sequence:

tools β†’ ui β†’ options β†’ history β†’ aliases β†’ git β†’ functions β†’ fzf β†’
bindings β†’ plugins β†’ op β†’ maint β†’ update β†’ os β†’ local

The last two (os, local) are not in this repo β€” they're the OS repo's own native layer and your machine-local untracked overrides. Everything before them is Core. (dotfiles-Kali inserts an extra offensive stage: ... os offensive local.)

Why the order matters

The dependencies between modules are real, not cosmetic:

  • tools is first because it initializes atuin (which registers its zle widget), sets the HAVE_* detection flags every later module reads, and puts ~/.local/bin on PATH before anything probes for tools.
  • ui loads right after tools because it only defines the _core_* UX helpers (_core_err, _core_warn, _core_confirm, _core_spin, ...) that every later module may call.
  • options runs compinit (the completion system) β€” both fzf-tab and carapace need it to already have run.
  • fzf defines its zle widgets before plugins loads zsh-vi-mode, whose init fires the keybinding hook in bindings.
  • bindings registers the keymap via zsh-vi-mode's zvm_after_init hook, so it must be defined before plugins sources vi-mode.

The canonical order lives in core.manifest.

Module-by-module

tools.zsh β€” detection + single init point (load FIRST)

The one place the modern-CLI stack is detected and the shell-hook tools (zoxide, starship, atuin, mise) are initialized. It:

  • Probes each tool with command -v and sets HAVE_* flags (HAVE_EZA, HAVE_BAT, HAVE_FD, ...) that aliases.zsh, functions.zsh, and fzf.zsh guard on.
  • Resolves binaries that ship under alternate names on some distros β€” Debian/ Ubuntu ship fd as fdfind and bat as batcat, so it sets $FD_BIN and $BAT_BIN to the real name.
  • Caches the four init scripts (zoxide init, starship init, etc.) under $XDG_CACHE_HOME/zsh/*.zsh via _cache_eval, regenerating only when the binary is newer than its cache. This turns an eval-of-subprocess into a plain source, removing per-shell subprocess spawns from the startup hot path.

ui.zsh β€” terminal-UX primitives

Defines Core's voice: _core_err / _core_warn / _core_ok / _core_hint / _core_confirm / _core_spin. These are gum-aware (prettier when gum is installed) and respect NO_COLOR and non-TTY output. _core_confirm declines when there's no TTY, which is what makes functions like extract and please safe to run non-interactively.

options.zsh β€” setopts + completion system

Sets the setopt flags, runs compinit (cached), and configures zstyle completion styling. Because it runs compinit, it must come before fzf-tab and carapace (both in plugins.zsh).

history.zsh β€” history config

HISTFILE / HISTSIZE / SAVEHIST, the history setopts, and a secret-ignore pattern so credentials don't land in history.

aliases.zsh β€” modern-CLI aliases (guarded)

Every alias touching an optional tool is guarded by its HAVE_* flag, so on a bare box you transparently get the classic command. See Tools, Aliases & Functions for the full list.

git.zsh β€” curated git aliases + helpers

A hand-picked subset of the oh-my-zsh git plugin with the framework stripped out β€” naming matches OMZ so muscle memory transfers. Includes git_main_branch and git_current_branch helpers so branch-aware aliases work whether the trunk is main, master, trunk, etc. Two deliberate safety upgrades over OMZ: gpf uses --force-with-lease (raw force is the explicit gpf!).

functions.zsh β€” cross-OS shell functions

mkcd, cdup, extract (with tarbomb + clobber guards), fcd, please, mkbak, serve, plus the discoverability commands core-help / core-doctor / core-version. All POSIX-ish so they behave the same on macOS zsh, Linux zsh, and Alpine's busybox-adjacent environment.

fzf.zsh β€” fzf env + zle widgets

fzf defaults plus the custom zle widgets (Ctrl-F file picker, Ctrl-R history, Alt-Z zoxide jump, Ctrl-G session picker) and the fif / fbr functions. Loads before bindings and plugins so the widgets exist when the keybinding hook fires. Preview commands resolve $BAT_BIN so they don't print "command not found" on Debian where bat is batcat.

bindings.zsh β€” vi-mode keybindings

Registers the keymap via zsh-vi-mode's zvm_after_init hook, because vi-mode resets all bindings on init. Sets cursor shapes per mode and binds the fzf widgets, atuin (Ctrl-E), and autosuggest-toggle (Ctrl-\).

plugins.zsh β€” lightweight plugin loader

No Oh My Zsh, no Zinit. Plugins are auto-cloned on first launch and pinned to specific commits (supply-chain safety β€” these are the only third-party code running in every interactive shell across all nine repos). zsh-defer async-loads the two heaviest plugins (autosuggestions + fast-syntax-highlighting) after the first prompt paints. The pinned set:

Plugin Role
romkatv/zsh-defer async-load the heavy plugins
jeffreytse/zsh-vi-mode vi-mode (loaded synchronously; fires the hook)
zsh-history-substring-search Up/Down history substring match
zsh-autosuggestions inline suggestion from history (deferred)
fast-syntax-highlighting command-line syntax highlighting (deferred)
Aloxaf/fzf-tab fzf-driven tab completion
zsh-you-should-use nudges you toward your aliases

make update-plugins (via scripts/update-plugins.sh) is the only thing that moves a pin β€” the runtime never floats.

op.zsh β€” 1Password CLI helpers

opsecret / openv / optoken / opssh wrappers around the op CLI.

maint.zsh β€” daily-maintenance control surface

maint-install / maint-run / maint-log β€” schedule and inspect the daily safe-update job (the runner itself is maint/dotfiles-maint.sh).

update.zsh β€” the up updater + nudge

The up package-updater and a once-per-day "updates available" nudge.

completions/ β€” autoloaded completions

zsh completion files for Core's own verbs (up, extract, mkcd, core-doctor, ...), added to fpath by options.zsh.

Performance note

Two things keep startup fast: tools.zsh caches the four shell-hook init scripts so they're a plain source rather than a subprocess, and plugins.zsh defers the two heaviest plugins until after the first prompt. Measure Core's contribution with:

hyperfine 'zsh -i -c exit'
# or, from the repo:
make bench

See also

Clone this wiki locally

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /