From 3377a25a10c76d553651db2f31376dd0be459bf9 Mon Sep 17 00:00:00 2001 From: Sal Date: Fri, 28 Aug 2026 03:22:26 +0100 Subject: [PATCH 1/2] docs(customization): clarify loader-owned defaults The customization table lists every ZI[...] field without saying which entry point assigns it, so readers could not tell that the loader sets some values before zi.zsh runs, or that ZI[HOME_DIR] resolves differently depending on whether the loader is used. - Note which fields the loader owns and that the rest are derived by zi.zsh from those values. - Record the deliberate ZI[HOME_DIR] divergence: the loader defaults to the XDG data path while zi.zsh's own fallback for an unset value is ${HOME}/.zi. - Document ZI[LOADER_HISTORY], the loader-only toggle that suppresses the HISTFILE, SAVEHIST, and HISTSIZE defaults. Pairs with the loader changes in z-shell/src. --- docs/guides/02_customization.mdx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/guides/02_customization.mdx b/docs/guides/02_customization.mdx index be7f9379..fd3fd429 100644 --- a/docs/guides/02_customization.mdx +++ b/docs/guides/02_customization.mdx @@ -55,6 +55,30 @@ source "${ZI[BIN_DIR]}/zi.zsh" ``` +:::info Loader defaults + +If you install with the [loader](/docs/getting_started/installation#loader), +`init.zsh` sets `ZI[REPOSITORY]`, `ZI[STREAM]`, `ZI[HOME_DIR]`, and +`ZI[BIN_DIR]` before Zi is cloned, because those four decide what to fetch and +where. Every other field in this table is owned by `zi.zsh` and derived from +them. + +`ZI[HOME_DIR]` differs by entry point. The loader defaults to +`${XDG_DATA_HOME:-$HOME/.local/share}/zi`, while `zi.zsh`'s current fallback +for an unset value is `${HOME}/.zi`. The loader always assigns the value before +`zi.zsh` runs, so a single session is always consistent, but sourcing `zi.zsh` +directly without the loader uses the other layout. Set `ZI[HOME_DIR]` yourself +if you want both entry points to agree. + +Zi is adopting XDG-first path resolution. When that lands, these entry points +converge on the XDG locations the loader already uses, and this table is +updated with it. + +To override any field, assign it in your `.zshrc` **before** sourcing the +loader or `zi.zsh`. + +::: + ### Modify settings {/* #modify-settings */} ```mdx-code-block @@ -67,6 +91,7 @@ source "${ZI[BIN_DIR]}/zi.zsh" | `ZI[COMPINIT_OPTS]` | `undefined` | Options for `compinit` call (e.g: done by `zicompinit`), commonly used with `-C` to speed up loading | | `ZI[MUTE_WARNINGS]` | `undefined` | If set to `1`, mutes some warnings, specifically the `plugin already registered` warning | | `ZI[PKG_OWNER]` | `z-shell` | Owner of the [packages][] (`zi pack …`) | +| `ZI[LOADER_HISTORY]` | `1` | Loader only. Set to `0` before sourcing `init.zsh` to leave `HISTFILE`, `SAVEHIST`, and `HISTSIZE` entirely to your own configuration | ```mdx-code-block From f1d7dfdffebb13891006c89e40eaae25ad8d6e26 Mon Sep 17 00:00:00 2001 From: Sal Date: Fri, 28 Aug 2026 04:41:45 +0100 Subject: [PATCH 2/2] docs(paths): document XDG-first defaults --- .../03_zsh_plugin_standard.mdx | 4 +- docs/getting_started/01_installation.mdx | 31 ++++++--- docs/guides/02_customization.mdx | 63 ++++++++++++++----- docs/guides/syntax/01_standard.mdx | 2 +- ecosystem/annexes/1_bin_gem_node.mdx | 6 +- ecosystem/plugins/zi_console.mdx | 2 +- 6 files changed, 76 insertions(+), 32 deletions(-) diff --git a/community/00_contributing/03_zsh_plugin_standard.mdx b/community/00_contributing/03_zsh_plugin_standard.mdx index 1a148a3a..6f84aad3 100644 --- a/community/00_contributing/03_zsh_plugin_standard.mdx +++ b/community/00_contributing/03_zsh_plugin_standard.mdx @@ -517,7 +517,7 @@ Plugin managers may export the parameter `$ZPFX`, holding a path to a directory dedicated to user-land software, giving `$ZPFX/bin`, `$ZPFX/lib`, `$ZPFX/share`, and so on. The suggested directory name is `polaris`. Zi uses that name and places the directory at -`${XDG_DATA_HOME:-$HOME/.local/share}/zi/polaris` by default. +`${ZI[HOME_DIR]}/polaris` by default. Users can then configure hooks to invoke, for example, `make PREFIX=$ZPFX install` on clone and update, to install software such as @@ -529,7 +529,7 @@ across accounts and machines. Facts related to `$ZPFX`: 1. `export ZPFX="$HOME/polaris"`, or - `${XDG_DATA_HOME:-$HOME/.local/share}/zi/polaris` + `${ZI[HOME_DIR]}/polaris` 2. `make PREFIX=$ZPFX install` diff --git a/docs/getting_started/01_installation.mdx b/docs/getting_started/01_installation.mdx index bf4d5d5b..a9f450d8 100644 --- a/docs/getting_started/01_installation.mdx +++ b/docs/getting_started/01_installation.mdx @@ -46,9 +46,15 @@ sh -c "$(curl -fsSL get.zshell.dev)" -- -a loader The installer will download the loader and add the snippet below to the .zshrc file. ```zsh showLineNumbers -if [[ -r "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" ]]; then - source "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" && zzinit +if [[ -n ${XDG_CONFIG_HOME:-} && $XDG_CONFIG_HOME == /* ]]; then + ZI_LOADER_CONFIG_HOME="$XDG_CONFIG_HOME/zi" +else + ZI_LOADER_CONFIG_HOME="$HOME/.config/zi" fi +if [[ -r "$ZI_LOADER_CONFIG_HOME/init.zsh" ]]; then + source "$ZI_LOADER_CONFIG_HOME/init.zsh" && zzinit +fi +unset ZI_LOADER_CONFIG_HOME ``` Then reload the shell with: `exec zsh`. All done! @@ -95,11 +101,20 @@ sh -c "$(curl -fsSL get.zshell.dev)" -- -a zunit Set up the install location and create a directory: +The assignment below explicitly selects a fresh XDG-style home. It does not +migrate an existing `$HOME/.zi` installation. For automatic legacy detection, +use the loader above or source your existing Zi checkout without overriding +`ZI[HOME_DIR]`. + ```zsh showLineNumbers typeset -Ag ZI -typeset -gx ZI[HOME_DIR]="${XDG_DATA_HOME:-${HOME}/.local/share}/zi" -typeset -gx ZI[BIN_DIR]="${ZI[HOME_DIR]}/bin" -command mkdir -p "$ZI[BIN_DIR]" +if [[ -n ${XDG_DATA_HOME:-} && $XDG_DATA_HOME == /* ]]; then + ZI[HOME_DIR]="$XDG_DATA_HOME/zi" +else + ZI[HOME_DIR]="$HOME/.local/share/zi" +fi +ZI[BIN_DIR]="${ZI[HOME_DIR]}/bin" +command mkdir -p -- "${ZI[BIN_DIR]}" ``` For security reasons run function compaudit to check if the [completion system][completion-system] would use files owned by root or by the current user, or files in directories that are world or group-writable. @@ -107,9 +122,9 @@ For security reasons run function compaudit to check if the [completi If failed, then set the current user as the owner of directories, then remove group/others write permissions, and clone the repository: ```zsh showLineNumbers -compaudit | xargs chown -R "$(whoami)" "$ZI[HOME_DIR]" -compaudit | xargs chmod -R go-w "$ZI[HOME_DIR]" -command git clone https://github.com/z-shell/zi.git "$ZI[BIN_DIR]" +compaudit | xargs chown -R "$(whoami)" "${ZI[HOME_DIR]}" +compaudit | xargs chmod -R go-w "${ZI[HOME_DIR]}" +command git clone https://github.com/z-shell/zi.git "${ZI[BIN_DIR]}" ``` ### Enable {/* #i-classfas-fa-spinner-fa-spini-enable */} diff --git a/docs/guides/02_customization.mdx b/docs/guides/02_customization.mdx index fd3fd429..19f006f6 100644 --- a/docs/guides/02_customization.mdx +++ b/docs/guides/02_customization.mdx @@ -38,11 +38,11 @@ source "${ZI[BIN_DIR]}/zi.zsh" | Hash Field | Default | Description | | ------------------------------------ | ----------------------------- | ---------------------------------------------- | -| `ZI[HOME_DIR]` | `${XDG_DATA_HOME:-$HOME/.local/share}/zi` | Where Zi should create all working directories | +| `ZI[HOME_DIR]` | Legacy `$HOME/.zi`, otherwise XDG data `zi` | Where Zi should create all working directories | | `ZI[BIN_DIR]` | `$ZI[HOME_DIR]/bin` | Directory where Zi code resides | | `ZI[COMPLETIONS_DIR]` | `$ZI[HOME_DIR]/completions` | Completion working directory | -| `ZI[CACHE_DIR]` | `$HOME/.cache/zi` | Cache directory | -| `ZI[CONFIG_DIR]` | `$HOME/.config/zi` | Directory for configuration files | +| `ZI[CACHE_DIR]` | `${XDG_CACHE_HOME:-$HOME/.cache}/zi` | Cache directory | +| `ZI[CONFIG_DIR]` | `${XDG_CONFIG_HOME:-$HOME/.config}/zi` | Directory for configuration files | | `ZI[MAN_DIR]` | `$ZPFX/man` | Directory to store manpages | | `ZI[LOG_DIR]` | `$ZI[CACHE_DIR]/log` | Directory to store log files | | `ZI[PLUGINS_DIR]` | `$ZI[HOME_DIR]/plugins` | Plugins working directory | @@ -60,25 +60,54 @@ source "${ZI[BIN_DIR]}/zi.zsh" If you install with the [loader](/docs/getting_started/installation#loader), `init.zsh` sets `ZI[REPOSITORY]`, `ZI[STREAM]`, `ZI[HOME_DIR]`, and `ZI[BIN_DIR]` before Zi is cloned, because those four decide what to fetch and -where. Every other field in this table is owned by `zi.zsh` and derived from -them. - -`ZI[HOME_DIR]` differs by entry point. The loader defaults to -`${XDG_DATA_HOME:-$HOME/.local/share}/zi`, while `zi.zsh`'s current fallback -for an unset value is `${HOME}/.zi`. The loader always assigns the value before -`zi.zsh` runs, so a single session is always consistent, but sourcing `zi.zsh` -directly without the loader uses the other layout. Set `ZI[HOME_DIR]` yourself -if you want both entry points to agree. - -Zi is adopting XDG-first path resolution. When that lands, these entry points -converge on the XDG locations the loader already uses, and this table is -updated with it. +where. It mirrors the core home resolver. Every other field in this table, +including cache and configuration, is owned by `zi.zsh`. To override any field, assign it in your `.zshrc` **before** sourcing the loader or `zi.zsh`. ::: +#### Path precedence and XDG validity + +Zi resolves paths in this order: + +1. A non-empty explicit `ZI[...]` path, or explicit `ZPFX`, wins. +2. For `ZI[HOME_DIR]`, a recognized legacy `$HOME/.zi` installation remains + active so code, plugins, snippets, completions, and modules are not split. +3. Otherwise Zi uses the matching XDG base when its value is an absolute path. +4. An unset, empty, or relative XDG value uses the specification fallback: + `$HOME/.local/share`, `$HOME/.cache`, or `$HOME/.config`. + +Zi does not use `ZDOTDIR` for application data, cache, or configuration. It is +the home for Zsh startup files, not a Zi storage base. XDG destinations do not +need to exist in advance; Zi creates its new application roots privately and +does not change permissions on a pre-existing base directory. + +`XDG_ZI_HOME`, `XDG_ZI_CACHE`, and `XDG_ZI_CONFIG` are exported compatibility +outputs derived from the resolved `ZI[...]` values. They are not configuration +inputs. Set `ZI[HOME_DIR]`, `ZI[CACHE_DIR]`, or `ZI[CONFIG_DIR]` instead. + +#### Legacy and both-present homes + +Zi never moves, merges, deletes, or overwrites an installation merely because +an XDG location is available. If only a recognized `$HOME/.zi` installation +exists, Zi keeps using it and `zi zstatus` displays a migration hint outside +the shell startup path. + +If both legacy and XDG homes contain Zi data, Zi uses an explicit configuration +or the sourced `ZI[BIN_DIR]` identity. An external checkout without either +identity conservatively selects the legacy home. `zi zstatus` reports the +ambiguity and selected root. To resolve it, set `ZI[HOME_DIR]` before sourcing +the loader or `zi.zsh`; do not combine roots manually while shells are using +them. + +An automatic migration command is not part of path resolution. Follow +[z-shell/zi#429](https://github.com/z-shell/zi/issues/429) for the planned +explicit, recoverable migration workflow. Until it is released, keep a backup +and treat changing `ZI[HOME_DIR]` as selecting another root, not as moving the +existing one. + ### Modify settings {/* #modify-settings */} ```mdx-code-block @@ -128,7 +157,7 @@ zi as'null' wait'1' lucid for \ tj/git-extras ``` -The target directory for installed files is `$ZPFX` - `${XDG_DATA_HOME:-$HOME/.local/share}/zi/polaris` by default. +The target directory for installed files is `$ZPFX` - `${ZI[HOME_DIR]}/polaris` by default. With [meta-plugins][z-shell/z-a-meta-plugins] consisting of: diff --git a/docs/guides/syntax/01_standard.mdx b/docs/guides/syntax/01_standard.mdx index 465cac88..d7108d81 100644 --- a/docs/guides/syntax/01_standard.mdx +++ b/docs/guides/syntax/01_standard.mdx @@ -130,7 +130,7 @@ The `make'…'` ice could also be: `make"install PREFIX=$ZPFX"`, if "install" wo :::info -[$ZPFX][global-parameter-with-prefix] is provided by Zi, it is set to `${XDG_DATA_HOME:-$HOME/.local/share}/zi/polaris` by default. However, it can be changed by specifying the `$ZPFX=` target. +[$ZPFX][global-parameter-with-prefix] is provided by Zi, it is set to `${ZI[HOME_DIR]}/polaris` by default. However, it can be changed by specifying the `$ZPFX=` target. ::: diff --git a/ecosystem/annexes/1_bin_gem_node.mdx b/ecosystem/annexes/1_bin_gem_node.mdx index e08c4df6..0d094635 100644 --- a/ecosystem/annexes/1_bin_gem_node.mdx +++ b/ecosystem/annexes/1_bin_gem_node.mdx @@ -52,7 +52,7 @@ zi ice as'program' from'gh-r' sbin'fzf' zi load junegunn/fzf ``` -The `$PATH` will remain unchanged and a forwarder-script of `fzf` shim will be created in `$ZPFX/bin` (`${XDG_DATA_HOME:-$HOME/.local/share}/zi/polaris/bin` by default), which is being already added to the `$PATH` by Zi when it is being sourced: +The `$PATH` will remain unchanged and a forwarder-script of `fzf` shim will be created in `$ZPFX/bin` (`${ZI[HOME_DIR]}/polaris/bin` by default), which is being already added to the `$PATH` by Zi when it is being sourced: ```zsh title="cat $ZPFX/bin/fzf" showLineNumbers #!/usr/bin/env zsh @@ -117,7 +117,7 @@ View all currently registered: sbin'[{g|n|c|N|E|O}:]{path-to-binary}[ -> {name-of-the-script}]; …' ``` -Creates the so-called `shim` known from `rbenv` – a wrapper script that forwards the call to the actual binary. The script is created always under the same, standard, and single `$PATH` entry: `$ZPFX/bin` (which is `${XDG_DATA_HOME:-$HOME/.local/share}/zi/polaris/bin` by default). The flags have the same meaning as with `fbin'…'` ice. +Creates the so-called `shim` known from `rbenv` – a wrapper script that forwards the call to the actual binary. The script is created always under the same, standard, and single `$PATH` entry: `$ZPFX/bin` (which is `${ZI[HOME_DIR]}/polaris/bin` by default). The flags have the same meaning as with `fbin'…'` ice.