Skip to content

Instantly share code, notes, and snippets.

@Birdie0
Last active October 30, 2026 14:38
Show Gist options
  • Select an option

  • Save Birdie0/c20ae3a92e01c4db348d2f5270255b0b to your computer and use it in GitHub Desktop.

Select an option

Save Birdie0/c20ae3a92e01c4db348d2f5270255b0b to your computer and use it in GitHub Desktop.
Bash / Zsh / fish config files

bash

Shell modes

Login shell

bash -l or bash --login to run as a login shell

if shopt -q login_shell
then
  echo 'login shell'
else
  echo 'non-login shell'
fi

Interactive shell

bash -i to run as interactive shell

if [[ $- == *i* ]]
then
  echo 'interactive shell'
else
  echo 'non-interactive shell'
fi

Startup source order

  • if the shell runs in login mode (the interactive flag is ignored) and --noprofile is not provided (which skips sourcing startup files), the following files will be sourced:
    • /etc/profile, which sources next files:
      • /etc/bash.bashrc
      • /etc/profile.d/*.sh
    • checks the following files in order and sources only the first one found:
      • ~/.bash_profile - usually missing
      • ~/.bash_login - usually missing
      • ~/.profile - present by default, sources next file:
        • ~/.bashrc
    • on shell exit sources ~/.bash_logout
  • if the shell runs in non-login mode:
    • and interactive and --norc is not provided (skips sourcing startup files), next files will be sourced:
      • /etc/bash.bashrc
      • ~/.bashrc
    • and non-interactive:
      • no files are sourced

Reference

fish

Shell modes

Login shell

fish -l or fish --login to run as login shell

if status is-login
    echo 'login shell'
else
    echo 'non-login shell'
end

Interactive shell

fish -i or fish --interactive to run as interactive shell

if status is-interactive
    echo 'interactive shell'
else
    echo 'non-interactive shell'
end

Configuration directories

Fish uses several directories to store its configuration files:

Config Variable Path
user $__fish_config_dir $XDG_CONFIG_HOME/fish => ~/.config/fish
system-wide $__fish_sysconf_dir /etc/fish
software $__fish_user_data_dir $XDG_DATA_HOME/fish => ~/.local/share/fish
vendor $__fish_data_dir /usr/share/fish (varies)

About vendor config

If $XDG_DATA_DIRS is set, loop through it (path variable), otherwise $__fish_data_dir is used:

  • each {path}/fish/vendor_conf.d is appended to $__fish_vendor_confdirs
  • each {path}/fish/vendor_functions.d is appended to $__fish_vendor_functionsdirs
  • each {path}/fish/vendor_completions.d is appended to $__fish_vendor_completionsdirs

Note: updating $XDG_DATA_DIRS won't update *dirs variables retrospectively.

Startup source order

--no-config/-N skips sourcing all config files.

  • /usr/share/fish/config.fish sources the following files. If any have duplicate basenames (/some/path/dir.fish -> dir.fish), only the first will be sourced:
    • $__fish_config_dir/conf.d/*.fish
    • $__fish_sysconf_dir/conf.d/*.fish
    • loop through $__fish_vendor_confdirs paths for *.fish
  • $__fish_sysconf_dir/config.fish
  • $__fish_config_dir/config.fish

Lazy load

In fish, functions and completions are lazily loaded, which means they aren't sourced until they're typed or run. For example, to run a custom function named hello, store it in a file such as $__fish_config_dir/functions/hello.fish. There are two side effects:

  1. If there are two identically named function files, only the first one will be sourced.
  2. If there are additional commands in the function file, or even another function, they will be called once.

New paths can be added by appending them to the fish_function_path and fish_complete_path variables without requiring a reload. If there are multiple identical functions or completions in the path, the first one found takes precedence.

Lookup paths for functions:

  • $__fish_config_dir/functions
  • $__fish_sysconf_dir/functions
  • $__fish_vendor_functionsdirs
  • $__fish_data_dir/functions

Lookup paths for completions:

  • $__fish_config_dir/completions
  • $__fish_sysconf_dir/completions
  • $__fish_vendor_completionsdirs
  • $__fish_data_dir/completions
  • $__fish_user_data_dir/generated_completions - generated by fish_update_completions command

Reference

zsh

Shell modes

Login shell

zsh -l or zsh --login to run as a login shell

if [[ -o login ]]
then
  echo 'login shell'
else
  echo 'non-login shell'
fi

Interactive shell

zsh -i or zsh --interactive to run as interactive shell

if [[ -o interactive ]]
then
  echo 'interactive shell'
else
  echo 'non-interactive shell'
fi

Startup source order

$ZDOTDIR is used as the root of the zsh configuration. If it is not set, $HOME is used instead.

Zsh startup order is more straightforward than in Bash:

Path Comment
/etc/zsh/zshenv always sourced, --no-rcs/-f prevents next files from being sourced
$ZDOTDIR/.zshenv always sourced
/etc/zsh/zprofile login shell
$ZDOTDIR/.zprofile login shell
/etc/zsh/zshrc interactive shell
$ZDOTDIR/.zshrc interactive shell
/etc/zsh/zlogin login shell
$ZDOTDIR/.zlogin login shell
/etc/zsh/zlogout sourced on exit of login shell
$ZDOTDIR/.zlogout sourced on exit of login shell

Reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment