A lightweight ZSH framework. Sensible defaults, 356 plugins, fast startup.
Built-in themes match upstream Oh My ZSH (Unicode and Powerline where
applicable). Prompt-facing plugins under plugins/ are normalized to plain
ASCII by tools/ascii_cleanup.sh so they behave well on minimal terminals.
git clone <this-repo> /tmp/leanzsh
cp /tmp/leanzsh/zshrc ~/.zshrc
cp -r /tmp/leanzsh/zshconfig ~/.zshconfig~/.zshrc # Your shell config (edit this)
~/.zshconfig/ # Framework root ($ZSH)
customzsh.sh # Core loader
lib/ # Built-in libraries (git, history, completion, etc.)
plugins/ # 356 plugins
themes/ # Prompt themes (robbyrussell, agnoster)
Edit ~/.zshrc:
ZSH_THEME="robbyrussell" # default, minimal
ZSH_THEME="agnoster" # Powerline-style segments (needs a patched font)Edit the plugins array in ~/.zshrc:
plugins=(git docker kubectl fzf)List available plugins:
ls ~/.zshconfig/plugins/These go in ~/.zshrc before the source $ZSH/customzsh.sh line:
CASE_SENSITIVE="true" # Case-sensitive completion
HYPHEN_INSENSITIVE="true" # _ and - interchangeable in completion
DISABLE_AUTO_TITLE="true" # Don't auto-set terminal title
ENABLE_CORRECTION="true" # Command auto-correction
COMPLETION_WAITING_DOTS="true" # Show dots during completion
HIST_STAMPS="yyyy-mm-dd" # Timestamp format in historyPlace your own plugins or lib overrides under $ZSH/custom/
(or set ZSH_CUSTOM to a different path):
~/.zshconfig/custom/
plugins/my-plugin/my-plugin.plugin.zsh
lib/git.zsh # overrides the built-in lib/git.zsh
themes/my.zsh-theme # custom theme
Disable git prompt features on large repos:
cd /path/to/huge-repo
git config leanzsh.hide-status 1 # hide dirty/clean status
git config leanzsh.hide-dirty 1 # skip dirty check only
git config leanzsh.hide-info 1 # hide git info entirelyUpstream agnoster reads oh-my-zsh.hide-status; the copy shipped here uses leanzsh.hide-status so the same commands above apply.
Plugins that accept options use the :leanzsh: zstyle namespace.
Add these to ~/.zshrc:
zstyle ':leanzsh:plugins:nvm' lazy yes
zstyle ':leanzsh:plugins:ssh-agent' agent-forwarding yes
zstyle ':leanzsh:plugins:docker' legacy-completion yesOne command does everything -- sync, rebrand, strip emoji, and test:
./tools/update.shOptions:
./tools/update.sh --dry-run # preview all changes, modify nothing
./tools/update.sh --skip-sync # skip upstream sync (no network needed)
./tools/update.sh --skip-test # skip the test suite at the endupdate.sh runs four scripts in order. Here is exactly what each step
does and why it is needed.
Keeps the local plugin set in lockstep with ohmyzsh/ohmyzsh.
- Sparse-clone the upstream repo (plugins directory only, depth 1) into a temporary directory.
- Compare the upstream and local plugin lists with
comm. - Add any plugins that exist upstream but not locally (new plugins).
- Update any existing plugins whose content has changed upstream
(detected via
diff -r). The local copy is replaced with the upstream version. - Remove any plugins that no longer exist upstream (deprecated).
- Optionally run the rebrand pass (skipped when called from
update.sh, which runs rebrand as its own step).
Flags: --dry-run (preview only), --no-rebrand (skip branding pass).
Replaces all Oh My ZSH identifiers with leanzsh equivalents so the codebase is self-consistent. Themes are never modified (they stay byte-identical to upstream).
- Replace
:omz:zstyle namespaces with:leanzsh:. - Replace
oh-my-zsh.*git config keys withleanzsh.*. - Replace internal
_omz_/_OMZ_function and variable prefixes with_leanzsh_/_LEANZSH_. - Replace
[oh-my-zsh]user-facing message prefixes with[leanzsh]. - Replace public function names (
omz_urlencodeetc.) with theirleanzsh_equivalents, preserving backward-compat wrappers. - Replace branding in comments and documentation text.
- Run a catch-all pass for any remaining
_omz_and_OMZ_prefixes, skipping backward-compat wrapper lines.
GitHub URLs (github.com/ohmyzsh/...) are preserved. The script is
idempotent -- running it on an already-rebranded codebase produces no
changes.
Flags: --dry-run (preview only).
Replaces emoji and Unicode symbols with plain ASCII equivalents in
plugins/ only. This ensures prompts render correctly on minimal
terminals.
- Replace git-status glyphs (
✚→+,●→*, etc.). - Replace arrow symbols used for ahead/behind indicators (
↑→^). - Replace special symbols (lightning, gear, flag, star, etc.).
- Replace Powerline Private Use Area glyphs with pipe/at characters.
- Replace Kubernetes and other domain-specific Unicode escapes.
- Replace emoji in user-facing messages (lock, folder, skull, fire).
lib/ and themes/ are not touched. The script is idempotent.
Flags: --dry-run (preview only).
Validates the entire codebase after the above steps. Exits non-zero if any test fails.
- Core structure — required files (
customzsh.sh, all libs, themes) exist. - No OMZ references — no
:omz:,oh-my-zsh.*,_omz_,_OMZ_, orOh My Zshbranding in functional code (excluding themes and backward-compat wrappers). Also checkszshrcandplugins/. - Correct identifiers — leanzsh config keys, function names, zstyle namespaces, and async handlers are all present.
- Backward compatibility —
omz_urlencode,omz_urldecode, andomz_historyaliases still work. - Dead code removal — OMZ-only functions (
uninstall_oh_my_zsh,upgrade_oh_my_zsh) are gone. - Config defaults —
ZSH_CUSTOMandZSH_COMPDUMPhave defaults. - Cross-reference consistency — functions that are called are actually defined, plugin-specific rebrands are verified.
- Plugin inventory — count is >= 350, deprecated plugins removed, new plugins present, every plugin dir has an entry-point file.
- ASCII safety —
lib/is fully ASCII; all plugin.zsh/.shfiles are ASCII-clean. - README sanity — documents leanzsh namespaces and migration.
- Rebrand idempotency — re-running
rebrand.shproduces no changes.
| Script | What it does |
|---|---|
tools/sync_upstream.sh |
Pull new / update changed / remove deprecated plugins from OMZ |
tools/rebrand.sh |
Replace OMZ branding with leanzsh (does not edit themes/) |
tools/ascii_cleanup.sh |
Replace emoji/Unicode with ASCII in plugins/ only |
tools/test_leanzsh.sh |
94-assertion test suite covering structure, branding, ASCII, inventory |
The default zshrc sets these aliases. Add your own below them:
alias grep='grep --color=auto --exclude-dir={.bzr,CVS,.git,.hg,.svn,.idea,.tox}'If you previously used Oh My ZSH:
| Old | New |
|---|---|
:omz:plugins:* zstyle |
:leanzsh:plugins:* |
oh-my-zsh.* git config |
leanzsh.* |
omz_urlencode |
leanzsh_urlencode (alias kept) |
omz_urldecode |
leanzsh_urldecode (alias kept) |
omz_history |
leanzsh_history (alias kept) |
Backward-compat aliases are provided so existing scripts continue to work.