CodeVetter · Repo Unpack · Extension points
ohmyzsh/ohmyzsh
Oh My Zsh is built to be extended without editing upstream files: $ZSH_CUSTOM shadows every lib file, plugin, and theme; new plugins are just directories with a <name>.plugin.zsh or _<name> completion; new themes are *.zsh-theme files; behavior is tuned via zstyle contexts and env-var flags; and the `omz` CLI dispatches to _omz::<cmd> functions. Theme authors integrate through prompt-info functions and ZSH_THEME_* variables.
- $ZSH_CUSTOM is the primary extension root: files in $ZSH_CUSTOM/*.zsh load last (after lib and plugins), and $ZSH_CUSTOM/<path> shadows $ZSH/<path> inside _omz_source, letting users override any lib file or plugin without touching the repo.
- A plugin is any directory under plugins/ or $ZSH_CUSTOM/plugins/ containing <name>.plugin.zsh (sourced at load) or _<name> (a compinit completion); is_plugin() is the registry check and simply enabling the name in plugins=(...) wires it in.
- A theme is a *.zsh-theme file found in $ZSH_CUSTOM/, $ZSH_CUSTOM/themes/, or $ZSH/themes/ (search order); it typically sets PROMPT/RPROMPT and consumes ZSH_THEME_* styling variables plus *_prompt_info functions.
- zstyle contexts form a typed config API: ':omz:update' mode/frequency/cooldown/verbose, ':omz:lib:theme-and-appearance' gnu-ls, ':omz:alpha:lib:git' async-prompt, and ':omz:lib:<n>'/':omz:plugins:<n>' aliases toggles.
- Env-var feature flags read at startup include DISABLE_MAGIC_FUNCTIONS, DISABLE_LS_COLORS, DISABLE_AUTO_TITLE, ENABLE_CORRECTION, CASE_SENSITIVE, HYPHEN_INSENSITIVE, COMPLETION_WAITING_DOTS, DISABLE_UNTRACKED_FILES_DIRTY, HIST_STAMPS, ZSH_DISABLE_COMPFIX — all documented in the zshrc template.
- Theme-facing integration contract: themes call git_prompt_info/git_prompt_status/ruby_prompt_info/nvm_prompt_info etc.; lib/prompt_info_functions.zsh predefines no-op stubs (chruby, rbenv, hg, pyenv, svn, vi_mode, virtualenv, jenv, azure, tf, conda, go) so themes don't error when plugins are absent.
- Prompt-status symbols are themselves a plugin/theme API: ZSH_THEME_GIT_PROMPT_{PREFIX,SUFFIX,DIRTY,CLEAN,UNTRACKED,ADDED,MODIFIED,RENAMED,DELETED,UNMERGED,AHEAD,BEHIND,DIVERGED,STASHED} map parsed statuses to glyphs.
- Async prompt extension: any function can be registered with _omz_register_handler and its output surfaced via $_OMZ_ASYNC_OUTPUT[handler] inside a stub prompt function — documented in the file header as the intended (but unstable) API.
- The `omz` CLI is open for new subcommands: `omz foo` dispatches to _omz::foo if the function exists, and the _omz completer's cmds/subcmds arrays are the registry to extend; plugin/theme/pr use $0::subcommand namespacing.
- Random-theme selection is extensible via ZSH_THEME_RANDOM_CANDIDATES and ZSH_THEME_RANDOM_IGNORED arrays; the themes plugin additionally provides `theme`/`lstheme` for ad-hoc switching.
- Vendored upstream completions are an extension surface managed declaratively: adding an entry to .github/dependencies.yml (repo, branch, version, pre/postcopy hooks) lets the weekly updater pull new upstream completion sources into plugins/.
- add-zsh-hook (precmd/preexec) is the sanctioned way libs hook the prompt lifecycle — termsupport registers omz_termsupport_precmd/preexec/cwd, async_prompt registers _omz_async_request, and git.zsh prepends _defer_async_git_register to precmd_functions.
- Plugin README convention: `omz plugin info <name>` looks for $ZSH_CUSTOM/plugins/<name>/README.md then $ZSH/plugins/<name>/README.md and pages it through glow/bat/less — each plugin is expected to ship a README documenting its aliases.