505

I'm looking for guidelines on what one should and should not include in the various startup files for zsh.

I understand the order of sourcing of these files, and the conditions under which they are sourced, but it is still not clear to me what should go in each.

1

3 Answers 3

564

Here is a non-exhaustive list, in execution-order, of what each file tends to contain:

  1. .zshenv is always sourced. It often contains exported variables that should be available to other programs. For example, $PATH, $EDITOR, and $PAGER are often set in .zshenv. Also, you can set $ZDOTDIR in .zshenv to specify an alternative location for the rest of your zsh configuration.
  2. .zprofile is for login shells. It is basically the same as .zlogin except that it's sourced before .zshrc whereas .zlogin is sourced after .zshrc. According to the zsh documentation, ".zprofile is meant as an alternative to .zlogin for ksh fans; the two are not intended to be used together, although this could certainly be done if desired."
  3. .zshrc is for interactive shells. You set options for the interactive shell there with the setopt and unsetopt commands. You can also load shell modules, set your history options, change your prompt, set up zle and completion, et cetera. You also set any variables that are only used in the interactive shell (e.g. $LS_COLORS).
  4. .zlogin is for login shells. It is sourced on the start of a login shell but after .zshrc, if the shell is also interactive. This file is often used to start X using startx. Some systems start X on boot, so this file is not always very useful.
  5. .zlogout is sometimes used to clear and reset the terminal. It is called when exiting, not when opening.

You should go through the configuration files of random Github users to get a better idea of what each file should contain.

7
  • 26
    Be aware when setting $PATH in .zshenv, various other files all are sourced after this file that will override this value. See zsh.org/mla/users/2003/msg00600.html.
    – bcb
    Commented Oct 6, 2015 at 0:19
  • 129
    Just for my own notes / confirmation and to help anybody else, the ultimate order is .zshenv → [.zprofile if login] → [.zshrc if interactive] → [.zlogin if login] → [.zlogout sometimes].
    – Gabriel L.
    Commented May 18, 2016 at 20:48
  • 14
    re: setting $PATH in .zshenv - macOS, as of Big Sur and at least a few versions prior - overwrites any changes to $PATH when /etc/zprofile is executed (after .zshenv). Commented Mar 9, 2021 at 0:19
  • 3
    @BeauBarker should $PATH be located in .zshrc?
    – alper
    Commented May 5, 2021 at 11:06
  • 2
    @alper GitHub user thoughtbot's popular dotfiles do indeed recommend setting the $PATH in .zshrc. Commented May 27, 2022 at 10:19
190

Here a list of what each file should/shouldn't contain, in my opinion:

.zshenv

[Read every time]

This file is always sourced, so it should set environment variables which need to be updated frequently. PATH (or its associated counterpart path) is a good example because you probably don't want to restart your whole session to make it update. By setting it in that file, reopening a terminal emulator will start a new Zsh instance with the PATH value updated.

But be aware that this file is read even when Zsh is launched to run a single command (with the -c option), even by another tool like make. You should be very careful to not modify the default behavior of standard commands because it may break some tools (by setting aliases for example).

.zprofile

[Read at login]

I personally treat that file like .zshenv but for commands and variables which should be set once or which don't need to be updated frequently:

  • environment variables to configure tools (flags for compilation, data folder location, etc.)
  • configuration which execute commands (like SCONSFLAGS="--jobs=$(( $(nproc) - 1 ))") as it may take some time to execute.

If you modify this file, you can apply the configuration updates by running a login shell:

exec zsh --login

.zshrc

[Read when interactive]

I put here everything needed only for interactive usage:

  • prompt,
  • command completion,
  • command correction,
  • command suggestion,
  • command highlighting,
  • output coloring,
  • aliases,
  • key bindings,
  • commands history management,
  • other miscellaneous interactive tools (auto_cd, manydots-magic)...

.zlogin

[Read at login]

This file is like .zprofile, but is read after .zshrc. You can consider the shell to be fully set up at .zlogin execution time

So, I use it to launch external commands which do not modify shell behaviors (e.g. a login manager).

.zlogout

[Read at logout][Within login shell]

Here, you can clear your terminal or any other resource which was setup at login.

How I choose where to put a setting

  • if it is needed by a command run non-interactively: .zshenv
  • if it should be updated on each new shell: .zshenv
  • if it runs a command which may take some time to complete: .zprofile
  • if it is related to interactive usage: .zshrc
  • if it is a command to be run when the shell is fully setup: .zlogin
  • if it releases a resource acquired at login: .zlogout
4
  • .zshenv is read before /etc/zprofile and that script will probably overwrite your PATH setting. I wouldn't use it at all. .zshrc runs for all interactive shells so it will run if you even just type zsh on the command line. That's where I'd put frequently changed things.
    – JeremyP
    Commented Aug 10, 2022 at 15:07
  • @JeremyP My /etc/zsh/zprofile does not set my PATH. And, I would think it would problematic for /etc/zsh/zprofile to assume that it can clobber PATH. Is there actually a distro that does this? Commented Mar 27, 2023 at 5:25
  • where would you put startx then?
    – fedemengo
    Commented May 28, 2023 at 8:20
  • @fedemengo You probably want to start your X server when everything is setup when loging in. The .zlogin file is perfect for that usage. Commented Mar 31 at 18:47
6

For people who came here hoping to find a simple solution that is easy to remember and to maintain, here's the setup I use and recommend (at least for Mac OS users):

enter image description here

  1. Put everything common in .zshenv and .bash_env, the other ones should now be empty and can be deleted (unless shell-specific, see step 4)
  2. Make sure you have the same content in .zshenv and .bash_env
  3. Remove content of .bash_env and put this inside instead so you have everything in a single place
   if [ -f $HOME/.zshenv ]; then
           source $HOME/.zshenv
   fi
  1. Create .zlogin and .bash_login so that you can override the content of .zshenv/.bash_env on a per-shell basis (since they execute after).
  2. (optional) Monitor .zprofile, .bash_profile, .bashrc, .zshrc from time to time, because some installers may create and append content in them automatically.
3
  • 1
    Why not use .zshrc ? I put lots of things in it.
    – Good Pen
    Commented Feb 15, 2023 at 2:04
  • @GoodPen You can, I just love simplicity so I prefer to use .zlogin instead, that executes at the very end of the flow.
    – lapin
    Commented Feb 21, 2023 at 12:49
  • .bashrc or .zshrc are typically used to configure the look and feel of the interactive shell. For example, customizing the prompt, font color, etc. could be done here. See this answer for more insights unix.stackexchange.com/a/324391/297265 Commented Jul 8, 2023 at 8:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .