How to Configure Zsh Aliases and Functions in the dotfiles Repository

The dotfiles repository organizes Zsh customizations through a three-layer architecture using Zgen for plugin management, followed by automatic sourcing of all *.zsh files in zsh/config and zsh/aliases, plus an optional local override file.

This guide walks through the configuration system in the issmirnov/dotfiles repository, showing exactly where to place aliases and functions, how the loading mechanism works, and how to extend the setup without breaking existing conventions.

Overview of the Three-Layer Architecture

The zsh/zshrc file implements a strict loading order that separates concerns between external plugins and custom code:

  1. Plugin Manager (Zgen) – Loads Oh-My-Zsh, plugins, and syntax highlighting first (lines 20–48)
  2. Custom Configuration – Sources every *.zsh file from zsh/config and zsh/aliases directories in alphabetical order (lines 52–58)
  3. Local Overrides – Sources ~/.zshrc.local last for machine-specific tweaks without version control (line 66)

This structure ensures that your custom aliases in zsh/aliases/ always override plugin defaults, while maintaining a clean separation between shared and private configuration.

Where Aliases Live

All alias definitions reside in the zsh/aliases/ directory as plain Zsh statements. The repository ships with several categorized files:

Utility Aliases

The zsh/aliases/utilities.zsh file contains general-purpose shortcuts:

alias o='open'
alias gurl='curl --compressed'
alias week='date +%V'
alias zsh-reload='source ~/.zshrc'

System-Specific Aliases

Platform-aware definitions live in zsh/aliases/system.zsh and platform-specific files like ubuntu.zsh or osx.zsh:

alias sudo='sudo '
alias ll='ls -lha --color'
alias open='xdg-open'

Suffix Aliases

Special "suffix aliases" defined in zsh/aliases/suffixes.zsh automatically invoke commands based on file extensions:

alias -s pdf='open'
alias -s html='open'

When you type report.pdf, Zsh automatically expands it to open report.pdf.

Where Functions Live

Reusable shell functions are defined alongside aliases, primarily in zsh/aliases/utilities.zsh. These are automatically available because the zshrc loader sources every *.zsh file found in the directories.

Example functions from the source:

function to {
    if [[ -z "$1" ]]; then
        echo "Usage: to <file name>"
    else
        echo "Now writing out to $1. Type ^D to finish."
        cat >| "$1"
    fi
}

function pdfsearch() {
    [ -z "$1" ] && echo "Error: No search term supplied" && exit 1
    find . -name '*.pdf' | xargs -I {} sh -c "pdftotext \"{}\" - | grep --with-filename --label=\"{}\" --color $1"
}

Adding New Aliases and Functions

To extend the configuration, create or edit files in the zsh/aliases/ directory:

  1. Create a new file (e.g., zsh/aliases/docker.zsh) or edit an existing one like utilities.zsh
  2. Add your definitions using standard Zsh syntax:

# zsh/aliases/git_custom.zsh

alias gco='git checkout'
alias gl='git log --oneline --graph'

function mkcd() {
    mkdir -p "$1" && cd "$1"
}
  1. Reload the shell using the provided alias:
zsh-reload

Or source a specific file directly:

source ~/.dotfiles/zsh/aliases/git_custom.zsh

Understanding the Loading Order

The sourcing mechanism in zsh/zshrc (lines 52–58) uses a deterministic alphabetical loading strategy:

find ~/.dotfiles/zsh/config ~/.dotfiles/zsh/aliases -type f -name '*.zsh' -print0 |
  sort -z |
  while IFS= read -r -d $'\0' line; do
      source "$line"
  done

Key implementation details:

  • Alphabetical ordering – sort -z ensures files load predictably regardless of filesystem order
  • Null-terminated strings – -print0 and -d $'\0' handle filenames with spaces safely
  • Sourcing scope – Each file executes in the current shell context via source, making aliases and functions immediately available

Because this block executes after Zgen initializes plugins, any definitions in zsh/aliases/ automatically override plugin defaults of the same name.

Best Practices for Organizing Zsh Configuration

When extending the dotfiles repository, follow these patterns established in the source code:

  • Group logically – Create separate files for different concerns (e.g., docker.zsh, kubernetes.zsh) rather than dumping everything into utilities.zsh
  • Use descriptive filenames – The alphabetical sort means 10-utils.zsh loads before 99-local.zsh if you need explicit ordering
  • Check for collisions – Run alias | grep 'your-alias' before adding new shortcuts to avoid unexpected overwrites
  • Prefer functions for complexity – When logic requires conditionals or loops, defined a function in utilities.zsh rather than a complex alias
  • Leverage suffix aliases – For file types you frequently open, use alias -s ext='command' syntax in zsh/aliases/suffixes.zsh

Summary

  • The three-layer architecture loads plugins first, then custom *.zsh files from zsh/config and zsh/aliases, finally ~/.zshrc.local
  • Aliases belong in zsh/aliases/*.zsh files, categorized by purpose (utilities, system, suffixes)
  • Functions are defined in the same *.zsh files and sourced automatically by the find loop in zsh/zshrc
  • The loading mechanism uses alphabetical sorting (sort -z) to ensure deterministic behavior
  • Use zsh-reload to refresh configuration after making changes

Frequently Asked Questions

How do I override a plugin alias with my own definition?

Add the conflicting alias to any file in zsh/aliases/ (such as system.zsh). Because these files source after Zgen loads Oh-My-Zsh and plugins, your definition wins. For example, if a plugin defines alias ll='ls -l', add alias ll='ls -lha --color' to override it.

Can I organize aliases into subdirectories within zsh/aliases?

The current find command in zsh/zshrc searches only for *.zsh files within the top-level directories zsh/config and zsh/aliases. While find traverses subdirectories, keep aliases in the root of zsh/aliases/ to ensure predictable loading order and prevent naming collisions.

What is the difference between zsh/config and zsh/aliases?

zsh/config/ contains environment settings, prompt configuration, bindkeys, and tool integrations (like fzf). zsh/aliases/ contains command shortcuts, suffix aliases, and function definitions. Both directories are sourced identically, but the separation helps maintain organization as the configuration grows.

How do I temporarily disable an alias without deleting the file?

Add an unalias command to your ~/.zshrc.local file, which sources last. For example, unalias ll removes the alias for that session. Alternatively, prepend the command with \ (backslash) to bypass alias expansion for a single execution: \ll runs the original binary regardless of aliases.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →