Configuration Files =================== Zsh has several system-wide and user-local configuration files. Prezto has one user-local configuration file. System-wide configuration files are installation-dependent but are installed in */etc* by default. User-local configuration files have the same name as their global counterparts but are prefixed with a dot (hidden). Zsh looks for these files in the path stored in the `$ZDOTDIR` environment variable. However, if said variable is not defined, Zsh will use the user's home directory. This is found on the config scripts as `${ZDOTDIR:-$HOME}` and is a `zsh` idiomatic way of doing something like this: ```bash if [[ -n $ZDOTDIR ]]; then DOTFILES_PATH=$ZDOTDIR else DOTFILES_PATH=$HOME fi source $DOTFILES_PATH/.zshenv #pro tip! set $ZDOTDIR on /etc/zshenv to ~/.zconf to have all runcoms live there instead of cluttering ~ =) ``` the above is the same as: `source ${ZDOTDIR:-$HOME}/.zshenv` is equivalent to: Sourcing of these confguration files depends mostly on 2 things: 1. Whether you are running a *login shell* 2. Whether the `RCS` and `GLOBAL_RCS` options are set. They are usually set by default File Descriptions ----------------- | always runs | when `GLOBAL_RCS` is set | when `RCS` is set | Purpose | stuff that usually goes there, and notes | |------------------|-----------------------------------------|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `/etc/zshenv` | | | system provided minimal environment | Always runs! should be minimal set ZDOTDIR, minimal environment. system paths | | | `${ZDOTDIR:-$HOME}/.zshenv` | user environment overrides non-interactive, non-login shells (when invoked via shebang in a script or via `zsh -c [script]` or when invoked by `make` | personal environment overrides, such as `MANPATH`, `TERM`, `fpath` *non interactive scripts should have their environment completly set up here* ) | | `/etc/zshprofile` | | system profile for login shells (`zsh -ls zsh - or via _ssh forced command_`) | minimal system paths for remote interaction, site `fpath`, site `$LOCALE`, lang. | | | `${ZDOTDIR:-$HOME}/.zshprofile` | personal preferences for interactive login shells | your preferred `$LOCALE`, `$LANG`, `readlne` config, `cdpath`, session managers, additional `fpath` ) login shells (but non necessarily **ineractive** as when invoked via _ssh remote cmd_ ) will read config up to this point | | `/etc/zshrc` | | system provided startup script, for interactive shells, (local shells that live in an `XTerm`, `URxvt`, `gnome-terminal`) or subshells (like running `xterm` from the command prompt of a _login xterm_, | site login accounting, security monitors, site command logging policy | | | `${ZDOTDIR:-$HOME}/.zshrc` | user customization of their *interactive* environment for terminals | sourcing custom completions (`gcloud.comp.inc`), custom user frameworks (zprezto is invoked here), additional path required by custom software installed in `/opt/*` | | `/etc/zshlogin` | | additional customization for interactive **login** shells, such as those accessed via ssh | tmux attach to existing session | | | `${ZDOTDIR:-$HOME}/.zshlogin` | user script for *login shell startup* (this shell is a session leader, and allocates a `ptty` | aliases, keybindings, personal startup programs, time tracking apps, session managers, quote of the day, fortunes | .. | ... your shell session happens here ... | | | | `${ZDOTDIR:-$HOME}/.zshlogout` | personal cleanup tasks | setting personal `crontabs` or `at` tasks, logging checout to your time tracking software, fortune to say goodbye. | `/etc/zshlogout` | | | site cleanup tasks | site command logging policy stop, login accounting records, security context spindown, etcThe configuration files are read in the following order: Discussion ---------- There are several places to add personal configuration and preferences in the files already provided for startup, it’s just a matter of placing them in the appropriate place. Most of them should probably go in `${ZDOTDIR:-$HOME}/.zshrc` **before** invoking zprezto init, to choose the modules that should get loaded, and using the appropriate `zstyle` calls form preferences (`zstyle` is a kind of _registry_ for shell configuration native to `zsh`) Any tweaks to prezto’s behavior should go **after** invoking zprezto init in `zshrc` or, in `${ZDOTDIR:-$HOME}/.zlogin` . Note however that the `zlogin` (sysem or user) files will be sourced **only for login shells**. That means, when logging in to a remote system via ssh for example or when calling say, `XTerm` or your favorite emulator by specifying you want a **login** shell (by calling `zsh -ls` instead of plain `zsh`). Otherwise, the `zlogin` files are ignored. Also, note that another difference between interactive login shells and plain interactive shells, is that, besides sourcing `zlogin` files, interactive login shells also allocate a pseudo-tty (you can see them when invoking `w`. Login shells have a pty assigned, while interactive non-login shells don't.) Why is this designed this way? because login shells are assumed to be the main point of interaction with a user while non login shells would be spawned as _sub-shells_ of a *login shell* , when executing scripts that call `zsh` as a command interpreter, for example, when the *shebang* is `#!/usr/bin/env zsh` or equivalent. When launching a new terminal within an *X11* session, it is safe to assume that you are *already logged in* so any terminal emulator will launch an *interactive-non-login* shell. Which is, _per specification_ the correct behavior, but not the behavior most users *expect*. There is a reason for this _specified_ behaviour: `zlogin` files should be used for *interaction oriented settings* such as custom completion, keybindings, `tmux` session setup, and most `alias`es. The advantage of grouping all interaction oriented settings in `.zlogin` is that non-interactive shells (executing scripts via `zsh -c [script]`, the *shebang*, subshells or `make` invoked shells, for example) will not be burdened by additional config settings making them faster and more responsive, as _keybindings_ and _aliases_ are not even loaded at startup, after all, an _executable non-interactive script_, should never call on keybindings or aliases (assuming they were properly written to be portable) Finally, it is a common source of frustration amongst graphical environment users, to spend some time adding their customizations to `.zlogin` only to see them ignored when launching a new `XTerm` or `tmux` pane. This can be solved by calling (or aliasing) your terminal emulator with the required option to invoke a *login* shell, for `XTerm`, for example you would call `xterm -e zsh -ls` on tmux you may add one of the following lines to your `.tmux.conf`: ```config #tmux.conf: set -g default-command 'exec /usr/bin/zsh -ls' #this will make zsh a login shell AND a session leader set -g default-shell '/usr/bin/zsh -ls' ``` Here is an examplefor *i3wm* on ubuntu ```bash #i3wm.conf: ... set $XTERM_CMD='xterm -e zsh -ls` bind $mod+x $XTERM_CMD ... ``` if you want to replace your non-login shell on your emulator with a brand-new shiny *login* shell you can issue `exec zsh -ls` at your command prompt. Doing this, however **will not write that terminal’s history to file** unless `INC_APPEND_HISTORY` was set when you strted the shell `INC_APPEND_HISTORY` makes `zsh` append history entries as soon as the command is finished. *zprezto* helpfuly sets `INC_APPEND_HISTORY`, `INC_APPEND_HISTORY_TIME`, and `SHARE_HISTORY` which makes your history available immediately from different terminals on command completion, and records execution time on the history file. Pretty neat, huh?) You could tack-on all interactive customizations on `zshrc` but you will end up with bloated shells on non-interactive environments. Perhaps desktop workstation users will not notice any difference, but in resource-constrained environments it may be significant in terms of execution time and energy consumption (v.gr when running a Raspberry PI on batteries or on a cell phone environment such as `termux`) You may be thinking... why is `zpreztorc` not invoked on `.zlogin` instead of `.zshrc`? I believe it was a wise design decision, in order to eliminate complexity by having the whole of *prezto* configured and launched from a single point, as some of the modules need to be sourced early in the startup process, `editor` and `gnu-utls` come to mind. If invoked later on the startup, such as would be the case in `.zlogin` would makee it easier to conflict with stuff users may add on `zshrc`. Also, it avoids **not being loaded** and causing user frustration if the user launches *non-login shells* from graphical environments, as discussed above. ## Conclusion For customization of your environment, use your `.zshrc` after zprezto has been invoked, or before to remove or activate packages via `zstyle` calls or use `.zshlogin` to override or tweak zprezto behavior. there is also `.zpreztorc` but you may want to leave that one alone. In any case, this question is often brought up by users that use the distributed *runcoms* **as is** which is a terrible idea, since doing `git pull` to update your distribution will clobber your customizations. it’s a better idea to *copy* the distributed *runcoms* to your `$ZDOTDIR` a nd merge any changes an update may bring, if any (they are usually confined to `.zpreztorc`) Troubleshooting --------------- 1. if prezto and some of your settings are loaded, but others are not; make sure you are running an *interactive login shell* (you should have a tty allocated, visible on the `w` list) and the `$TTY` variable should be set, if that is not the case, check the above discussion, you can 'replace' your shell _in situ_ by issuing the command `exec zsh -l` 2. if you notice that none of your settings are loaded, check that `/etc/zshenv` does not disable them. In any case ```bash setopt global_rcs setopt rcs ``` in `/etc/zshenv` should set them both. This issue would be extremely rare. Authors ------- *The authors of these files should be contacted via the [issue tracker][4].* - [Sorin Ionescu](https://github.com/sorin-ionescu) [1]: http://www.kornshell.com [2]: http://en.wikipedia.org/wiki/Fortune_(Unix) [3]: http://www.manpagez.com/man/1/msgs [4]: https://github.com/sorin-ionescu/prezto/issues