zdot API Reference

June 23, 2026 · View on GitHub

Complete reference for all public zdot functions, grouped by usage category.

Convention: Functions prefixed with _zdot_ or _ are internal and not documented here. Only the public API that module authors and users should call is covered.


Table of Contents


Initialization

zdot_init

Single entry point for the entire zdot startup sequence. Call this once at the end of your .zshrc, after all zdot_load_module calls.

zdot_init

What it does (in order):

  1. Clones all declared plugin repositories
  2. Runs bundle init functions (OMZ, Prezto)
  3. Resolves group annotations into DAG barrier hooks
  4. Builds or loads the cached execution plan (topological sort)
  5. Executes all eager hooks in dependency order
  6. Kicks off deferred hooks (post-prompt via zsh-defer)
  7. Compiles all modules to .zwc bytecode

Guards against double-invocation. You should never need to call any other orchestration function directly.

Example .zshrc:

source "${XDG_CONFIG_HOME}/zdot/zdot.zsh"

zdot_load_module xdg
zdot_load_module history
zdot_load_module brew
zdot_load_module plugins

zdot_init

Hook Registration

These functions register shell functions as hooks in the dependency-aware execution system. Hooks are topologically sorted and executed in the correct order by zdot_init.

zdot_register_hook

Full-control hook registration with explicit dependency metadata.

zdot_register_hook <function-name> <context...> [flags...]
ParameterDescription
<function-name>Shell function to execute when this hook fires
<context...>One or more of: interactive, noninteractive, login, nonlogin
FlagArgumentDescription
--requires<phase...>Phases that must complete before this hook runs. Hard: if no hook provides the phase in the current context, the plan build aborts
--requires-optional<phase...>Soft requires. When a hook provides the phase it is a full dependency — real ordering edge and force-defer propagation, identical to --requires. When nothing provides it the edge is silently dropped (the hook still runs; the build does not abort). Use when a base/common hook wants to order behind an optional sibling module's phase without depending on it being loaded. Contrast --after (ordering only, does not propagate deferral) and --requires + --optional (skips the whole hook when unmet). See Dependency types
--requires-tool<tool>Sugar for --requires tool:<tool>
--after<target...>Soft ordering: run after each target if present, else no-op (never errors, never skips the hook). Each target resolves as a phase first, else as a hook name. The declarative, soft counterpart to --requires; the per-hook counterpart to zdot_defer_order.
--after-tool<tool>Sugar for --after tool:<tool> — soft-order after whoever --provides-tool <tool>, if any.
--before<target...>Soft ordering mirror of --after: run before each target if present, else no-op (never errors, never skips the hook). Each target resolves as a phase first, else as a hook name. Lets a hook insert itself ahead of another without editing it.
--before-tool<tool>Sugar for --before tool:<tool> — soft-order before whoever --provides-tool <tool>, if any.
--provides<phase>Phase token this hook provides on completion
--provides-tool<tool>Sugar for --provides tool:<tool>
--optionalHook is skipped (not errored) if a required phase has no provider. Safe to combine with --group: a skipped optional member is dropped from its group's end barrier rather than stalling it — see Implementation → Skipped optional members and the end barrier
--name<name>Human-readable label (used by zdot_defer_order and introspection)
--deferredMark for post-prompt deferred execution
--deferred-promptLike --deferred but refreshes the prompt afterward
--group<name>Add to a named group (may repeat). Three names are predefined: bootstrap (runs first), pre-defer (runs as the last eager step, before the deferred phase), and finally (runs last of all, after the deferred drain). See the Module Guide.
--provides-group<name>Run before the named group: the group's begin barrier waits for this hook, so every member runs after it. Mirror image of --requires-group (which waits for the group's end barrier). The provider is not a member
--requires-group<name>Require all members of the named group to complete. Members that are skipped (optional with unmet requires) or variant/context-filtered are dropped from the barrier, not waited on; an empty/all-skipped group is satisfied vacuously
--variant<name>Only run when variant matches (may repeat; empty = all)
--variant-exclude<name>Exclude when variant matches (takes priority over --variant)

Sets REPLY to the generated hook_id on success.

Example:

_my_tool_init() {
  export MY_TOOL_HOME="${XDG_DATA_HOME}/my-tool"
  path=("${MY_TOOL_HOME}/bin" $path)
}

zdot_register_hook _my_tool_init interactive noninteractive \
  --requires bootstrap-ready \
  --provides my-tool-ready \
  --provides-tool my-tool \
  --name "my-tool"

zdot_simple_hook

Sugar for the common single-hook module pattern. Derives sensible defaults from a base name.

zdot_simple_hook <name> [flags...]

Auto-derived defaults:

  • Function: _<name>_init
  • Requires: bootstrap-ready
  • Provides: <name>-configured
  • Context: interactive noninteractive
FlagArgumentDescription
--provides<phase>Override provides (default: <name>-configured)
--requires<phase...>Override requires (default: bootstrap-ready)
--no-requiresClear all auto-derived requires
--context<ctx...>Override contexts
--fn<name>Override function name
(others)Passed through to zdot_register_hook

To expose a user-extension group, pass --requires-group <name>-configure directly (it falls through to zdot_register_hook). Users then attach with --group <name>-configure.

Example:

# Registers _rust_init with requires=bootstrap-ready, provides=rust-configured
_rust_init() {
  source "$HOME/.cargo/env" 2>/dev/null
}
zdot_simple_hook rust
# Custom overrides
_my_setup() { ... }
zdot_simple_hook my-thing \
  --fn _my_setup \
  --requires brew-ready \
  --provides-tool mytool

zdot_define_module

Declarative multi-phase module definition. Auto-derives hook names and phase tokens and wires up lifecycle dependencies.

zdot_define_module <basename> [flags...]

Registers up to five lifecycle hooks from a single call:

PhaseTriggered ByDefault ProvidesContext
configure--configure <fn><basename>-configuredeager, all
load--load <fn> or --load-plugins <specs><basename>-loadedeager, all
post-init--post-init <fn><basename>-post-configureddeferred, interactive
interactive-init--interactive-init <fn><basename>-interactive-readydeferred, interactive
noninteractive-init--noninteractive-init <fn><basename>-noninteractive-readyeager, noninteractive
FlagArgumentDescription
--configure<fn>Configure hook function (auto-requires bootstrap-ready)
--load<fn>Custom loader hook function
--load-plugins<specs...>Auto-generate loader from plugin specs
--post-init<fn>Post-init hook function
--interactive-init<fn>Interactive init hook function
--noninteractive-init<fn>Non-interactive init hook function
--context<ctx...>Default contexts for all phases
--provides-tool<tool>Tool provided by the load phase (may repeat)
--requires-tool<tool>Tool required by the load phase (may repeat)
--requires<phase...>Extra requirements for the load phase
--after / --after-tool<target...> / <tool>Soft ordering for the load phase — same semantics as on zdot_register_hook
--before / --before-tool<target...> / <tool>Soft ordering mirror, applied to the load phase
--auto-bundle-depsMatch each --load-plugins spec to a registered plugin-framework bundle handler and auto-wire the generated load hook. Per distinct handler found, injects --group <handler>-plugins and (if the handler declared one) --requires <handler-provided-phase>; always adds --requires plugins-cloned. No-op for specs no handler claims; ignored without --load-plugins. See Module Guide → Bundle integration.
--group<name>Explicit group for the load phase (may repeat)
--auto-configure-groupExpose the <basename>-configure extension group. The --configure fn (or --load fn, if no configure) becomes the CONSUMER (--requires-group), running after all user group hooks. Requires at least one of --configure / --load.
--configure-context<ctx...>Override configure phase context
--load-context<ctx...>Override load phase context
--post-init-requires<phase...>Override post-init requires
--post-init-context<ctx...>Override post-init context
--variant<name>Only activate for this variant (may repeat)
--variant-exclude<name>Exclude for this variant (may repeat)

Example:

_fzf_configure() {
  export FZF_DEFAULT_OPTS="--height 40%"
}

_fzf_post_init() {
  bindkey '^T' fzf-file-widget
}

zdot_define_module fzf \
  --configure _fzf_configure \
  --load-plugins "junegunn/fzf" \
  --post-init _fzf_post_init \
  --provides-tool fzf

With --auto-configure-group (extension point for downstream config):

zdot_define_module brew \
  --configure _brew_defaults \
  --load _brew_load \
  --auto-configure-group

Downstream code hooks into brew-configure to contribute pre-load configuration:

_my_brew_overrides() {
    zstyle ':zdot:brew' verify-tools op fd ripgrep
}
zdot_register_hook _my_brew_overrides interactive noninteractive \
    --group brew-configure

Wiring. --auto-configure-group exposes the <basename>-configure extension group. The module's --configure fn (or --load fn, if no configure is set) becomes the consumer of the group via --requires-group <basename>-configure, so it runs after every user-registered group hook. The DAG is:

bootstrap-ready

  [ _my_brew_overrides  ||  …other user hooks ]   ← group members

  group end-barrier

  _brew_defaults    ← the module's --configure fn (consumer)
      ↓ provides brew-configured
  _brew_load

The module's configure fn (or load fn) is positioned to read state the user hooks set — e.g. zstyle -s ':zdot:brew' verify-tools _tools || _tools=(default fallback). The flag requires at least one of --configure or --load; otherwise it is ignored with a warning.


Hook Orchestration

These functions control hook execution order and behavior. They are typically called in .zshrc before zdot_init.

zdot_allow_defer

Pre-accept a hook as force-deferred, suppressing warnings.

zdot_allow_defer <function-name> [<phase>...]

When a non-deferred hook depends on a phase provided only by a deferred hook, zdot will automatically force-defer it. Call zdot_allow_defer to acknowledge this is intentional.

Example:

zdot_allow_defer _nodejs_init nodejs-configured
zdot_allow_defer _completions_init
zdot_init

zdot_defer_order

Declare ordering constraints between named hooks without coupling them through a shared phase.

zdot_defer_order [--context <ctx>] <name-A> <name-B> [name-C ...]

Generates a full ordering chain: A before B, A before C, B before C, etc.

FlagArgumentDescription
--context<ctx>Only apply in the given context (e.g. interactive)

Example:

# Ensure fzf loads before shell-extras, which loads before autocompletion
zdot_defer_order fzf shell-extras autocompletion

zdot_defer_order vs --after. Both inject the same ordering-only synthetic edge and share the same contradiction/cycle safety. Reach for zdot_defer_order to order two otherwise-unrelated hooks by name from the outside; a missing endpoint warns (it's treated as a probable typo). Reach for --after when a hook itself declares "run me after this capability, if present" — it resolves a phase/tool/hook target, a missing target is a silent no-op, and the constraint lives on the dependent hook. In short: --after is the declarative, soft, dependent-side counterpart; zdot_defer_order is the imperative, warn-on-absence, third-party one.


zdot_build_execution_plan

Builds the topologically-sorted execution plan from all registered hooks.

zdot_build_execution_plan

Note: You typically do not call this directly. zdot_init calls it for you. It is documented here for completeness and advanced use.


zdot_execute_all

Runs every hook in the eager (non-deferred) execution plan.

zdot_execute_all

Note: Called internally by zdot_init. Documented for completeness.


Module Loading

zdot_load_module

Load a module by name.

zdot_load_module <module-name>

Searches the configured module path in order:

  1. User-supplied directories (via zstyle :zdot:modules search-path)
  2. ${XDG_CONFIG_HOME}/zdot-modules (default user dir, if it exists)
  3. Built-in modules/ directory

First match wins. Deduplicates automatically (loading the same module twice is a no-op).

Example:

zdot_load_module xdg
zdot_load_module brew
zdot_load_module history

zdot_before_module

Register a callback to run synchronously before a module is sourced. Useful for setting zstyles or other shell state that the module reads at parse time (see User Extension Points for the two-layer model).

zdot_before_module <module-name> --fn  <function-name>
zdot_before_module <module-name> --cmd <command> [args...]

Exactly one of --fn / --cmd must be given.

FlagDescription
--fn <name>Register an existing function. Deduplicated by name.
--cmd <cmd> [args…]Schedule a single command + args. The framework generates an anonymous function. Not deduplicated.

Callbacks fire in registration order. --fn accepts a name that is not yet defined; missing-at-drain warns and continues. Registering after the module has been loaded warns and the callback does not run. Callbacks for modules that never load silently never fire.

Examples:

# Light: one-shot zstyle override
zdot_before_module brew --cmd zstyle ':zdot:brew' verify-tools op fd ripgrep

# Heavy: multi-statement setup or conditional logic
_my_brew_setup() {
    zstyle ':zdot:brew' verify-tools op fd ripgrep
    is-platform mac && zstyle ':zdot:brew' something-else yes
}
zdot_before_module brew --fn _my_brew_setup

For one-off zstyles, raw zstyle … ; zdot_load_module <name> in .zshrc is lighter and adds no API surface. Reach for zdot_before_module when grouping multiple settings, when setup is conditional, or when per-module config files should self-register.

Cross-module configuration: any module M may register zdot_before_module N … callbacks for another module N, provided M is sourced before zdot_load_module N. Callbacks for modules that never load are silent no-ops. See User Extension Points → Cross-module configuration for the full pattern.


zdot_module_path

Find the filesystem path of a module.

zdot_module_path <module-name>

Sets REPLY to the full path of <name>/<name>.zsh, or returns 1 if not found.


zdot_module_loaded

Check whether a module has been loaded.

zdot_module_loaded <module-name>

Returns 0 if the named module has been loaded via zdot_load_module, 1 otherwise. Useful inside a module's configure/init hooks to vary behaviour based on which sibling modules the user has enabled.

By the time configure and init hooks run, all zdot_load_module calls in .zshrc have completed, so the check reflects the user's full module selection regardless of load order.

Example:

# In modules/history/history.zsh — default the fzf ctrl-r binding on
# only when the user has also enabled the fzf module.
if zdot_module_loaded fzf; then
    zstyle ':contextual-history:*' fzf-bind-ctrl-r true
fi

zdot_module_list

List all loaded modules with their source directories.

zdot_module_list [--before]

Modules from the built-in dir are labelled "(modules)"; user-supplied modules show their directory path. With --before, each module also lists its registered zdot_before_module callbacks — --fn entries with the registering origin, --cmd entries with the command body.


zdot_module_dir

Get the directory of the currently-loading module.

zdot_module_dir

Sets REPLY to the module's directory path. Must be called from within a module file (typically in the module's .zsh file).

Example:

# Inside modules/fzf/fzf.zsh
zdot_module_dir
local my_dir="$REPLY"
source "${my_dir}/helpers.zsh"

zdot_module_source

Source a file relative to the calling module.

zdot_module_source <relative-path>

Compiles to .zwc if caching is enabled. Uses zdot_module_dir to resolve the base directory.

Example:

# Inside a module file
zdot_module_source "extra-config.zsh"

zdot_module_autoload_funcs

Autoload functions from the calling module's functions/ directory.

zdot_module_autoload_funcs [function-names...]

If no names are given, autoloads all files in the module's functions/ directory (excluding _* completion functions, which are discovered by compinit via fpath). Adds the directory to fpath and compiles files if caching is enabled.

Example:

# Autoload all functions in this module's functions/ dir
zdot_module_autoload_funcs

# Autoload specific functions only
zdot_module_autoload_funcs fzf_fd fzf_rg

zdot_autoload_global_funcs

Autoload functions from the global functions directory (${XDG_CONFIG_HOME}/zsh/functions).

zdot_autoload_global_funcs [function-names...]

Same behavior as zdot_module_autoload_funcs but uses the global functions directory.


Plugin Management

zdot_use_plugin

Declare a plugin and optionally register a load hook.

zdot_use_plugin <spec> [subcommand] [flags...]
ParameterDescription
<spec>Plugin spec: user/repo, user/repo@version, or bundle prefix like omz:plugins/git, pz:modules/git

Subcommands:

SubcommandDescription
hookRegister an eager hook to load this plugin
deferRegister a deferred hook to load this plugin
defer-promptRegister a deferred hook with prompt refresh

All flags valid with defer are equally valid with defer-prompt — the two differ only in the prompt refresh after loading.

FlagArgumentValid WithDescription
--name<n>hook, deferNames the generated loader (_zdot_autoload_<n>), which is also the hook's effective label
--provides<p>hook, deferPhase provided on load
--config<fn>hook, deferConfig function called before loading
--context<ctx...>hook, deferContexts (default: interactive noninteractive)
--requires<r>deferRequired phase (hard dependency — gates the load)
--after<t...>hook, deferSoft ordering: load after each target if present in context, else no-op (never gates). Same semantics as zdot_register_hook --after. Composes flexibly with absent/disabled plugins
--before<t...>hook, deferSoft ordering mirror: load before each target if present, else no-op (never gates)
--group<g>hook, deferAdd hook to a named group (may repeat)
--requires-group<g>hook, deferRequire all hooks in the named group
--provides-group<g>hook, deferProvide into the named group

Examples:

# Eager load with a dependency
zdot_use_plugin "zsh-users/zsh-completions" hook \
  --requires plugins-cloned \
  --provides zsh-completions-loaded

# Deferred load
zdot_use_plugin "zsh-users/zsh-autosuggestions" defer \
  --name autosuggestions

# OMZ plugin
zdot_use_plugin "omz:plugins/git" defer

# Soft ordering for a recommended-but-not-mandatory load sequence
# (fzf-tab -> abbr -> autosuggest). --after never gates: if fzf-tab is
# disabled, abbr still loads — only the ordering edge drops out.
zdot_use_plugin "olets/zsh-abbr" defer \
  --requires autocomplete-loaded \
  --after fzf-tab-loaded
zdot_use_plugin "zsh-users/zsh-autosuggestions" defer \
  --requires autocomplete-loaded \
  --after abbr-ready fzf-tab-loaded \
  --context interactive

# Prezto module (shorthand)
zdot_use_pz git

--after/--before vs --requires. Use --requires only for a genuine hard dependency (the plugin is broken without the target). For a preferred order — "load me after X if X is around" — use --after/--before: a missing or disabled target is a silent no-op, so independent modules can each contribute ordering edges that compose into one partial order without hard gates or cycles.


zdot_use_pz

Convenience wrapper to declare a Prezto module.

zdot_use_pz <module>

Equivalent to zdot_use_plugin "pz:modules/<module>".


zdot_use_bundle

Register a repository as a bundle dependency (not a user plugin).

zdot_use_bundle <repo>

Prevents zdot_clean_plugins from treating it as orphaned.


zdot_register_bundle

Register a custom bundle handler.

zdot_register_bundle <name> [--init-fn <fn>] [--provides <phase>]

The handler must implement zdot_bundle_<name>_match, _path, _clone, and _load functions.


zdot_plugin_clone

Clone a single plugin repository.

zdot_plugin_clone <spec>

Clones from GitHub. Supports version pinning via @version. Delegates to bundle handlers if applicable. Skips if already cloned.


zdot_plugins_clone_all

Clone all declared plugin repositories.

zdot_plugins_clone_all

Uses a sentinel-file fast path: if specs haven't changed and all directories exist, returns immediately.


zdot_load_plugin

Load a plugin by sourcing its *.plugin.zsh file.

zdot_load_plugin <spec> [provides-phase]

Handles deduplication, bundle handler delegation, fpath addition for functions/ subdirectories, and optional bytecode compilation. The optional second (positional) argument names a phase to provide once the plugin has loaded.


zdot_plugin_path

Resolve a plugin spec to its filesystem path.

zdot_plugin_path <spec>

Sets REPLY to the on-disk path (the subdirectory for bundle sub-specs like omz:plugins/git, the repo root for plain user/repo specs). Any @version pin is stripped — it is a git ref, never part of the path. Dispatches to the owning bundle handler's _path hook when a bundle claims the spec.


zdot_plugin_repo

Resolve a plugin spec to the git working directory used for fetch/pull.

zdot_plugin_repo <spec>

Sets REPLY to the repo directory. For bundle-owned specs this is the bundle's shared clone (e.g. the single OMZ repo for every omz: spec). Returns 1 if the owning bundle exposes no _repo hook.


zdot_plugin_url

Resolve a plugin spec to its upstream clone URL.

zdot_plugin_url <spec>

Sets REPLY to the URL (https://github.com/<spec> for plain specs). Returns 1 if the owning bundle exposes no _url hook.


zdot_plugin_name

Resolve a plugin spec to a human-readable label suitable for output.

zdot_plugin_name <spec>

Sets REPLY to the label: the bundle handler's name (or its _name hook result) for bundle specs, the spec itself for plain user/repo specs.


zdot_plugin_compile

Compile a plugin's .zsh files to .zwc bytecode.

zdot_plugin_compile <spec>

zdot_plugin_compile_extra

Register extra files to compile alongside a plugin.

zdot_plugin_compile_extra <spec> <file> [<file> ...]

Example:

zdot_plugin_compile_extra "lukechilds/zsh-nvm" "${NVM_DIR}/nvm.sh"

zdot_compile_plugins

Compile all declared plugins.

zdot_compile_plugins

zdot_plugins_have_changed

Check if any git-sourced plugin has a new HEAD.

zdot_plugins_have_changed

Returns 0 if changed, 1 if unchanged.


Deferred Execution

These functions schedule commands to run after shell startup via zsh-defer. When defer is disabled, commands execute immediately.

zdot_defer

Schedule a command for post-startup execution.

zdot_defer [flags] <command...>
FlagDescription
-q / --quietSuppress precmd hooks and zle reset-prompt
-p / --promptEnable prompt refresh after the command
--label <text>Human-readable label (visible in zdot show defer-queue)

Example:

zdot_defer eval "$(pyenv init -)"
zdot_defer --label "rbenv init" eval "$(rbenv init -)"

zdot_defer_until

Schedule a command with a configurable delay.

zdot_defer_until [flags] <delay> <command...>
ParameterDescription
<delay>Delay in seconds

Flags are the same as zdot_defer.

Example:

zdot_defer_until 2 zdot_cache_compile_all

Platform & Context

zdot_is_macos

Returns 0 on macOS, 1 otherwise.

if zdot_is_macos; then
  # macOS-specific setup
fi

zdot_is_debian

Returns 0 on Debian or Debian-derived distros, 1 otherwise.

if zdot_is_debian; then
  zdot_load_module apt
fi

zdot_is_platform

Test against one or more platform names or $OSTYPE globs.

zdot_is_platform <name...>

Friendly aliases: mac -> darwin*, linux -> linux*, debian -> Debian check. Raw globs also accepted (e.g. darwin*, linux-gnu*).

Example:

if zdot_is_platform mac; then
  # macOS
elif zdot_is_platform debian; then
  # Debian/Ubuntu
fi

zdot_interactive

Returns 0 if the current shell is interactive.

zdot_interactive && echo "Interactive shell"

zdot_login

Returns 0 if the current shell is a login shell.

zdot_login && echo "Login shell"

zdot_has_tty

Returns 0 if stdout is attached to a TTY.

zdot_has_tty && echo "Has TTY"

Note: Distinct from zdot_interactive. A shell can be interactive without a PTY (e.g. zsh -i -c ...).


zdot_variant

Print the active variant name.

local v="$(zdot_variant)"

zdot_is_variant

Test if the active variant matches a name.

zdot_is_variant <name>

Example:

if zdot_is_variant work; then
  zdot_load_module corporate-proxy
fi

zdot_resolve_variant

Resolve the active variant. Priority: (1) $ZDOT_VARIANT env var, (2) zstyle :zdot:variant name, (3) user-supplied zdot_detect_variant() function.

zdot_resolve_variant

Note: Called automatically by zdot_init. Documented for completeness.


zdot_build_context

Build the full shell context string (interactive/login/variant).

zdot_build_context

Note: Called automatically by zdot_init. Documented for completeness.


Logging

All logging functions accept one or more message arguments. Messages are printed to stdout unless noted otherwise.

Output Functions

FunctionColorStreamSuppressed in Quiet Mode?Requires Flag?
zdot_info <msg>defaultstdoutYes--
zdot_info_nonl <msg>defaultstdoutYes--
zdot_success <msg>greenstdoutYes--
zdot_report <msg>cyanstdoutYes--
zdot_action <msg>bluestdoutYes--
zdot_error <msg>redstderrNo (always shown)--
zdot_warn <msg>yellowstderrNo (always shown)--
zdot_verbose <msg>cyanstdout--$ZDOT_VERBOSE or $ZDOT_DEBUG
zdot_debug <msg>magentastderr--$ZDOT_DEBUG
zdot_log_debug <msg>magentastdout--$ZDOT_DEBUG

Quiet mode is enabled via:

zstyle ':zdot:logging' quiet true

Verbose/debug mode is enabled via environment variables:

ZDOT_VERBOSE=1 zsh     # verbose + normal output
ZDOT_DEBUG=1 zsh       # debug + verbose + normal output

zdot_info_nonl prints without a trailing newline (for progress indicators). In deferred context, it falls back to a normal line to avoid dropped output.


Utility Functions

FunctionDescription
zdot_show_deferred_logReplay accumulated deferred log messages
zdot_cleanup_loggingUnset all logging variables and functions (teardown)

Cache

zdot implements a two-tier cache:

  • Tier 1: .zwc bytecode compilation (co-located alongside source files)
  • Tier 2: Execution plan serialization (context-specific cache files)

zdot_cache_init

Initialize the cache system.

zdot_cache_init

Reads configuration from zstyle:

zstyle ':zdot:cache' enabled true             # default: true
zstyle ':zdot:cache' directory "$XDG_CACHE_HOME/zdot"  # default

Note: Called automatically during zdot bootstrap. Documented for completeness.


zdot_cache_is_enabled

Returns 0 if caching is enabled.

if zdot_cache_is_enabled; then
  zdot_cache_compile_file "$my_file"
fi

zdot_cache_compile_file

Compile a single zsh file to .zwc bytecode.

zdot_cache_compile_file <source-file>

Creates the .zwc file alongside the source. Skips if already up to date.


zdot_cache_compile_all

Compile all core modules and loaded modules to bytecode.

zdot_cache_compile_all

zdot_cache_compile_functions

Compile all files in a function directory.

zdot_cache_compile_functions <func-dir> [glob-pattern]
ParameterDescription
<func-dir>Directory containing function files
[glob-pattern]Pattern for files to compile (default: *)

zdot_cache_save_plan

Serialize the current execution plan to a cache file.

zdot_cache_save_plan

Note: Called automatically by zdot_init. Documented for completeness.


zdot_cache_invalidate

Invalidate all caches (execution plans, .zwc files, compdump metadata, plugin stamps).

zdot_cache_invalidate

Also available via CLI: zdot cache invalidate.


zdot_cache_stats

Display cache statistics.

zdot_cache_stats

Also available via CLI: zdot cache status.


zdot_cache_create_dirs

Create the cache directory structure.

zdot_cache_create_dirs

Completions

zdot_register_completion_file

Register a completion to be generated by refresh_completions.

zdot_register_completion_file <command> <generate-command> [dest-dir]
ParameterDescription
<command>Command name (e.g. gh)
<generate-command>Shell command that produces the completion script
[dest-dir]Destination directory (default: $XDG_CACHE_HOME/zdot/completions)

Example:

zdot_register_completion_file gh "gh completion -s zsh"
zdot_register_completion_file docker "docker completion zsh"

Calling this from inside a hook? If the registration runs in a hook body (rather than at module-source time), register that hook into the completions-producers group (--group completions-producers) so completion generation waits for it. See Modules → the completions-producers group.


zdot_register_completion_live

Register a function to run live during init for completion setup. Same grouping rule as zdot_register_completion_file: if called from a hook body, register that hook with --group completions-producers.

zdot_register_completion_live <function-name>

zdot_get_completions_dir

Print the completions directory path to stdout.

local dir="$(zdot_get_completions_dir)"

Utilities

zdot_add_fpath

Add a directory to fpath.

zdot_add_fpath <dir> [--glob <pattern>]

Prepends <dir> to fpath. If caching is enabled, compiles files matching the glob pattern to .zwc.

Example:

zdot_add_fpath "${ZDOT_DIR}/my-completions" --glob "*.zsh"

zdot_include_source

Source a file or directory, compiling first if caching is enabled.

zdot_include_source <path> [--glob <pattern>]

If <path> is a file, compiles and sources it. If a directory, compiles and sources all files matching the glob (default: *.zsh).

Example:

zdot_include_source "${my_module_dir}/extras"
zdot_include_source "${my_module_dir}/init.zsh"

zdot_verify_tools

Runtime check that tools are available on PATH.

zdot_verify_tools <tool1> [tool2 ...]

Emits a warning for each tool not found. Does not affect scheduling.

Example:

zdot_verify_tools git curl jq

zdot_verify_tools_zstyle

Read a tool list from zstyle and verify each exists.

zdot_verify_tools_zstyle <zstyle-context> <default-tool...>

Falls back to the default list if the zstyle is unset.


zdot_provides_tool_args

Build --provides-tool arguments from a zstyle tool list.

zdot_provides_tool_args <zstyle-context> <default-tool...>

Sets reply array with --provides-tool <tool> pairs, suitable for splatting into zdot_register_hook or zdot_simple_hook.

Example:

zdot_provides_tool_args ':zdot:module:brew' brew
zdot_simple_hook brew "${reply[@]}"

zdot_zstyle_default

Seed a zstyle default only when the style isn't already set for the context.

zdot_zstyle_default [-e] <context> <style> <value> [<value>...]

Lets a module define backstop defaults that any user-set value transparently overrides — whether set in .zshrc, a zdot_before_module callback (parse-time), or a *-configure group hook (DAG-time). If the user already set the style, the default is skipped; otherwise it's applied.

Presence is tested with zstyle -g, so it works regardless of how the style is later read (-s/-a/-b/-t) and for array and -e (evaluated) styles alike. Mirrors the zstyle setting syntax: pass -e for an evaluated default, and any number of values after <style> for multi-valued styles.

Example:

zdot_zstyle_default ':zsh-ai:*'        endpoint 'http://localhost:11434/v1'
zdot_zstyle_default ':zsh-ai:scratch'  enabled  yes
zdot_zstyle_default ':zsh-ai:scratch'  keybind  '^Xa'
zdot_zstyle_default -e ':completion:*' hosts    'reply=($myhosts)'

Note on -e: this is zstyle's evaluated-style flag, forwarded to the underlying zstyle set — the default value is shell code re-run on each lookup (populating reply), not a literal. It is unrelated to the presence check, which uses -g. There is no "exists vs blank" flag: any prior set (even to empty) counts as present, so an explicit empty user value still wins.


zdot_zstyle_get

Seed a backstop default (if unset) and read the style into a variable in one call — the common zdot_zstyle_default + zstyle -s/-a/-b two-step.

zdot_zstyle_get [-s|-a|-b] [-e] <context> <style> <var> [<default>...]

The retrieval flag selects how the stored value is interpreted (zstyle styles have no type — the reader decides):

flagreads asinto <var>
-sscalar (first value) — defaultstring
-aarray (all values)array
-bboolean (yes/no)string; return code reflects truthiness

Pass -e to mark the default as evaluated, exactly as with zdot_zstyle_default. Values after <var> are the default(s) applied when the style is unset — pass several for -a, or yes/no for -b. The return code is that of the underlying read (found-or-not for -s/-a, true/false for -b), so -b composes directly in a conditional.

Example:

# scalar (default mode) — replaces the two-line default+read pattern
zdot_zstyle_get    ':zdot:update-nag' plugin  spec 'georgeharker/zsh-pkg-update-nag'

# array
zdot_zstyle_get -a ':my:ctx'          paths   dirs /a /b /c

# boolean, used as a conditional
if zdot_zstyle_get -b ':zdot:foo' enabled is_on yes; then
    # is_on == "yes" and the branch is taken
fi

zdot_is_newer_or_missing

Check if a source file is newer than a destination (or the destination is missing).

zdot_is_newer_or_missing <source> <dest>

Returns 0 if the source is newer or the destination does not exist.


zdot_init_short_host

Initialize the $SHORT_HOST global variable.

zdot_init_short_host

On macOS uses scutil --get LocalHostName; elsewhere uses ${HOST/.*/}.

Note: Runs automatically at source time.


CLI

zdot provides an interactive CLI using a <noun> <verb> pattern:

zdot <noun> <verb> [args...]
NounVerbsDescription
cachestatus, invalidate, compileCache management
hooklist, plan, status, defer-queue, graphHook introspection
phaselistPhase introspection
pluginlist, update, check-updates, clean, reclonePlugin management
modulelist, cloneModule introspection
completionrefreshCompletion management
secretrefresh1Password secrets
updatecheck-updates, applySelf-update
infoEnvironment info
debugDebug diagnostics
benchStartup benchmark
profilezprof startup profile
helpShow help

Tab completion is available (via the _zdot completion function).

The CLI reference in commands.md is the authoritative per-command documentation; this table is just the map.