KronuZSH

July 31, 2026 · View on GitHub

KronuZSH is a thin, prezto-free zsh setup: my prompt, four plugins, and a small amount of config, with no framework underneath. It replaces a 7-years-behind prezto fork with something I maintain end to end.

KronuZSH prompt showing host, Git and virtualenv context above the time, working directory, and caret.

KronuZSH is an opinionated, complete Zsh configuration—not a plugin intended to be sourced into an existing framework. It installs the standard Zsh runcoms and owns the shell options, history, completion, keybindings, plugins, and prompt they load.

It is deliberately small. The prompt is one file. Everything Prezto used to give me that I actually use is now maintained here or supplied by a standalone plugin:

  • prompt (lib/prompt.zsh) the Kronuz prompt, evolved from the theme I maintained in Prezto and incorporating ideas and code from Prezto prompt themes. Git status comes from gitstatus; the venv, vi/emacs keymap indicator, and pwd are tiny native replacements for prezto's python-info, editor-info, and prompt-pwd. Past prompts collapse to a compact, configurable path ❯ line (the transient prompt); a slow or failed command is immediately visible in the live prompt, while terminals with OSC 133 support retain its historical status and running time.
  • plugins (git submodules under plugins/): fast-syntax-highlighting, zsh-autosuggestions, zsh-history-substring-search, and gitstatus.
  • config (in lib/): options.zsh, history.zsh, colors.zsh, completion.zsh, keybindings.zsh, aliases.zsh, functions.zsh, python.zsh, terminal.zsh — one named file per concern.

The guiding rule: keep only the genuinely useful parts, lean and easy to find, and prefer zsh-native over a vendored module (e.g. bracketed paste is built in, so there's no safe-paste). No cryptic framework magic; if you want to change something, the file it lives in is obvious.

For the story behind the move away from Prezto—and the small conveniences I only noticed after removing it—read "Molting Zsh: Down to the core".

Contents

Fonts (Nerd Font)

The prompt uses Nerd Font glyphs: the OS logo by the hostname, the git segment (branch/tag/commit, stash, ahead/behind, staged/modified/ conflicted/untracked), the venv segment, and the vi/emacs indicators. Install any Nerd Font and point your terminal at it — e.g. MesloLGS Nerd Font:

  • macOS: brew install --cask font-meslo-lg-nerd-font, then set it as your terminal font.
  • iTerm2 gotcha: also set it (or uncheck) under Settings → Profiles → Text → "Use a different font for non-ASCII text" — otherwise the glyphs show as boxes even with the right main font.

Without a Nerd Font, flip the whole prompt to plain-Unicode glyphs that render in a normal font: set KZ_PROMPT_NERD_FONT=0 (also accepts no/off/false) in ~/.zshrc.local. You can also retune individual glyphs (in either mode) via KZ_PROMPT_GLYPH_<NAME> — set one to a character of your choice, or to '' to hide it (e.g. KZ_PROMPT_GLYPH_MODIFIED='*'). See the glyph table in prompt.md for the full list of names and both default sets.

Color is handled automatically: a dumb/unknown terminal (Emacs M-x shell, some CI) or NO_COLOR=1 (no-color.org) renders the full layout with no color escapes (and dumb also forces the plain glyphs). It's re-checked every prompt, so export TERM=dumb / NO_COLOR=1 (and back) take effect live.

For a longer, opinionated (and surely incomplete) rundown of good coding fonts, see nerd_fonts.md.

Install

Requirements

  • Zsh 5.9 is tested in CI on macOS and Linux. Older Zsh 5.x releases may work, but are not currently guaranteed.
  • Git is required to clone and initialize the four plugin submodules.
  • Bash is used by install.sh; the installed interactive configuration is Zsh.
  • A Nerd Font is optional. Plain-Unicode glyphs are available when one is not installed.
  • The external tools described below are optional. In particular, the prompt falls back to direct git calls when gitstatusd cannot run.
git clone --recursive https://github.com/Kronuz/KronuZSH.git ~/.local/share/KronuZSH
cd ~/.local/share/KronuZSH && ./install.sh
exec zsh

install.sh uses the conventional default-install plus --dry-run, --force, --uninstall, and --help interface. It symlinks the runcoms (~/.zshenv, ~/.zshrc, ~/.zprofile, ~/.zlogin, ~/.zlogout) at this repo's runcoms/, backing up anything it replaces, and inits the plugin submodules. It's idempotent; ./install.sh --uninstall restores the backups. Symlinks mean editing ~/.zshrc edits the tracked runcoms/zshrc directly, and $KRONUZSH self-resolves through them.

The installer also compiles the startup modules, plugins, integrations, and skins into adjacent .zwc wordcode. Zsh selects a current compiled file itself and falls back to text whenever the source is newer or the cache is invalid. The generated fzf and zoxide initialization is cached before compilation, which removes two process launches from every new interactive shell. Re-run ./install.sh after updating KronuZSH or either tool to refresh the caches immediately.

Backups live under ${XDG_STATE_HOME:-$HOME/.local/state}/kronuzsh/backups/<timestamp>/home/ instead of beside active configuration, so backup directories cannot be mistaken for live plugins or settings. Uninstall also recognizes the older adjacent *.kronuzsh.bak convention.

Use ./install.sh --dry-run to preview the complete setup without changing user files, Git configuration, caches, or submodules. Add --force to that preview to show which optional integration prompts force would accept.

Use ./install.sh --force to apply the Kronuz theme over conflicting tool preferences without prompting, --hints for optional usage and maintenance notes, or --files to list integration-managed files and their backups. --no-backup suppresses recovery copies when replacing user files; use it only when those files are versioned.

Machine-local config

Two tiers, by language:

  • ~/.profile — cross-shell env (PATH, exports) in POSIX sh, shared by bash, sh, and zsh; runcoms/zprofile sources it for zsh login shells. Put anything that puts a tool on PATH (cargo, ~/.local/bin, ...) here, so it's set before .zshrc runs and integrations/init.zsh can detect the tool.

  • ~/.zshrc.local — zsh-only interactive machine tweaks (the KZ_PROMPT_COLOR_HOST and other KZ_PROMPT_* overrides, zstyles, tool hooks not already covered by KronuZSH). Sourced after the core prompt setup and before the initial automatic .venv scan, if present. Copy the template and edit:

    cp ~/.config/KronuZSH/zshrc.local.example ~/.zshrc.local
    

/etc/profile is left to the system.

Automatic Python virtualenvs

When a directory or one of its parents contains .venv/bin/activate, KronuZSH activates the nearest .venv. It keeps that environment active throughout the project tree, switches when a closer .venv is found, and restores the shell when you leave.

The hook tracks ownership: an environment activated manually or by another tool is never replaced or deactivated. The existing venv prompt segment shows the active environment. Set KZ_AUTO_VENV=0 in ~/.zshrc.local to disable automatic activation.

KronuZSH disables virtualenv's stock (.venv) prefix because the prompt already has its own venv segment. Set VIRTUAL_ENV_DISABLE_PROMPT='' in ~/.zshrc.local if you want both.

Shell conveniences

The small built-in command set stays deliberately conventional: d prints the automatic directory stack, 19 jump through it, and - returns to the previous directory. mkdcd <directory> creates one directory (including parents) and enters it. http-serve starts Python 3's HTTP server when python3 is installed.

help <command> is the normal help entry point: local shell functions show their source (syntax-highlighted and paged by bat when available, otherwise through $PAGER), while builtins, aliases, reserved words, and external commands go through zsh's context-aware run-help. Transparent integration wrappers do the same, so help cat opens the native cat manual even when interactive file viewing is powered by bat. Native run-help remains available directly, including its Git, ip, OpenSSL, and sudo helpers; minimal installations fall back to man.

The completion menu matches case and ., _, or - boundaries flexibly, keeps private functions out of normal results, and includes the directory stack for cd.

gitstatusd (the git prompt engine)

gitstatus needs a small daemon, gitstatusd. It is downloaded, not compiled. On the first new shell, the plugin fetches a prebuilt binary for your platform into ~/.cache/gitstatus/ (from GitHub releases). Nothing is committed here.

  • macOS / a machine with open network: just works, no action needed.

  • A locked-down host (e.g. behind a corp proxy) where the download is blocked: build it once locally (needs cmake + a C++ compiler), or copy the cached binary from a machine that could download it:

    ~/.config/KronuZSH/plugins/gitstatus/build -w   # compile gitstatusd locally
    # or: scp host:~/.cache/gitstatus/gitstatusd-linux-x86_64 ~/.cache/gitstatus/
    
  • Either way the prompt still works: if gitstatusd isn't up, the git segment falls back to direct git calls (slower on huge repos) and shows a warning icon before the branch until the daemon answers again.

External tools

KronuZSH wires in a set of modern CLI tools when they're installed, and silently skips them when they aren't, so the same config works on your laptop, a fresh box, or a server with none of them. The wired set (fzf, fd, zoxide, bat, ripgrep, git-delta, eza, yazi) gets key bindings, aliases, env, or git config; a longer list of "just run them" tools (lazygit, jq, dust, btop, ...) is worth having too.

See integrations.md for the full catalog — what each tool does, the classic command it replaces, the per-platform install matrix, and the shared Kronuz theming. The quick install:

# macOS
brew install fd bat fzf zoxide ripgrep git-delta eza yazi

# Debian / Ubuntu  (fd installs as `fdfind`, bat as `batcat`; init.zsh detects both)
sudo apt install fd-find bat fzf zoxide ripgrep git-delta

# Fedora
sudo dnf install fd-find bat fzf zoxide ripgrep git-delta

On a minimal or locked-down distro that lacks them, install via Rust (cargo install --locked fd-find bat zoxide git-delta eza) and grab fzf's prebuilt Go binary; the exact commands are in integrations.md.

The colored tools (eza, bat, delta, fzf) share one Kronuz look, bundled under integrations/ (eza/theme.yml, themes/Kronuz.tmTheme, and fzf's --color). The syntax theme is generated from one source of truth (KronuzTheme), identical to the VS Code and Sublime (kronuz-theme-sublime) editions. The wiring is in integrations/init.zsh (per-shell) and integrations/setup.sh (one-time: bat's theme cache + delta's gitconfig).

Layout

install.sh         idempotent symlink installer (--uninstall restores backups)
zcompile.zsh       validates and refreshes install-time zsh wordcode
runcoms/
  zshenv           environment, all shells   (~/.zshenv)
  zprofile         login: sources ~/.profile (~/.zprofile)
  zshrc            interactive entry point   (~/.zshrc)
  zlogin           login: bg-compiles the completion dump
  zlogout          logout (stub)
lib/               modules sourced by zshrc, one per concern
  options.zsh        shell options
  history.zsh        history (HISTSIZE 10M)
  colors.zsh         canonical $LS_COLORS (sourced before completion, which reads it)
  completion.zsh     cached, case-flexible completion (including the directory stack)
  keybindings.zsh    key bindings (emacs; word nav, Ctrl-W to last slash)
  aliases.zsh        the useful aliases (ls colors, ll, mkdir -p, ...)
  functions.zsh      small, generally useful shell functions
  terminal.zsh       window/tab title
  plugins.zsh        plugin loader
  prompt.zsh         the Kronuz prompt (OS glyph, gitstatus, ...; see prompt.md)
integrations/      optional external tools, one self-contained dir per tool (see integrations.md)
  init.zsh           loader: sources each <tool>/init.zsh at shell start
  setup.sh           loader: sources each <tool>/setup.sh at install time
  <tool>/init.zsh    per-shell wiring (fd, bat, fzf, zoxide, eza, yazi, ...)
  bat/setup.sh       builds bat's theme cache from themes/Kronuz.tmTheme
  themes/            shared Kronuz .tmTheme files (bat, delta, yazi); generated
  delta/setup.sh     wires git-delta into the global gitconfig
  eza/theme.yml      Kronuz color theme for eza (loaded via $EZA_CONFIG_DIR)
  vim/colors/        Kronuz vim/nvim colorscheme (linked into ~/.vim/colors by setup.sh)
zshrc.local.example  machine-local template (copy to ~/.zshrc.local)
plugins/           vendored plugins (git submodules)

The startup changes and rejected deferral experiment are measured in dev/startup-performance.md.

Topic docs: prompt.md (the full prompt manual: every segment and option), integrations.md (the external-tool catalog) and nerd_fonts.md (font rankings + setup).

Contributions are welcome within the project's deliberately narrow scope; see CONTRIBUTING.md for file placement, checks, and attribution notes.

License

KronuZSH is released under the MIT License. Portions adapted from Prezto retain its copyright notices. The plugins under plugins/ are git submodules and remain under their respective upstream licenses.