Skip to main content

Overview

The PowerShell configuration uses a modular, directory-based structure inspired by Unix systems. Instead of one monolithic profile file, configuration is split into numbered modules that load in a specific order.

Entry Point

The main profile file (Microsoft.PowerShell_profile.ps1) is intentionally lean:
Microsoft.PowerShell_profile.ps1
$ConfigRoot = "$HOME\.config\powershell"

# Source all conf.d files in order
$confDir = Join-Path $ConfigRoot "conf.d"
if (Test-Path $confDir) {
    Get-ChildItem -Path $confDir -Filter "*.ps1" | 
        Sort-Object Name | 
        ForEach-Object { 
            . $_.FullName 
        }
}
This approach:
  • Keeps the main profile simple and maintainable
  • Makes it easy to add/remove features
  • Allows for clear organization by category
  • Enables predictable load order through numbering

Configuration Directory Structure

~/.config/powershell/
├── Microsoft.PowerShell_profile.ps1  # Entry point
├── conf.d/                           # Modular configuration
│   ├── 00-init.ps1                  # Core settings
│   ├── 10-environment.ps1           # Environment variables
│   ├── 20-aliases.ps1               # Command aliases
│   ├── 30-tools.ps1                 # Modern CLI tools
│   ├── 40-completions.ps1           # Tab completions
│   ├── 50-functions.ps1             # Function loader
│   ├── 60-prompt.ps1                # Oh My Posh theme
│   └── 99-local.ps1                 # Machine-specific overrides
└── functions/                        # Custom functions
    ├── mkcd.ps1
    ├── rfv.ps1
    ├── backup.ps1
    └── ...

Load Order

Files in conf.d/ are loaded in alphanumeric order using numbered prefixes:
1

00-init.ps1

Core PowerShell settings, PSReadLine configuration, Terminal-Icons
2

10-environment.ps1

Environment variables ($env:EDITOR, $env:PATH), editor fallback chain
3

20-aliases.ps1

Git aliases, lazygit, HTTPie, btop shortcuts
4

30-tools.ps1

Modern tool integrations (bat, eza, zoxide, fzf, ripgrep, delta)
5

40-completions.ps1

Enhanced tab completions for docker, scoop, winget, npm/pnpm/yarn
6

50-functions.ps1

Loads custom functions from functions/ directory, invokes greeting
7

60-prompt.ps1

Oh My Posh prompt theme configuration
8

99-local.ps1

Machine-specific overrides (gitignored for local customization)

Numbered Prefix Convention

The two-digit prefix determines load order:
PrefixPurposeExamples
00-XXCore initializationPSReadLine, encoding, error display
10-XXEnvironment setup$env:EDITOR, $env:PATH
20-XXAliases and shortcutsGit, tool aliases
30-XXExternal tool integrationbat, eza, zoxide, fzf
40-XXCompletionsdocker, scoop, npm
50-XXFunctionsCustom function loader
60-XXPrompt customizationOh My Posh
99-XXLocal overridesMachine-specific config

Adding New Modules

To add a new configuration module:
  1. Create a new .ps1 file in conf.d/
  2. Choose an appropriate numeric prefix based on dependencies
  3. The file will automatically load on next shell start
Example: Adding a 25-docker.ps1 module
# ~/.config/powershell/conf.d/25-docker.ps1
# Docker-specific aliases and functions

if (Get-Command docker -ErrorAction SilentlyContinue) {
    function dps { docker ps $args }
    function dimg { docker images $args }
    function dlog { docker logs -f $args }
}

Local Overrides

The 99-local.ps1 file is gitignored and intended for machine-specific customization:
~/.config/powershell/conf.d/99-local.ps1
# Work proxy settings
$env:HTTP_PROXY = "http://proxy.work.com:8080"
$env:HTTPS_PROXY = "http://proxy.work.com:8080"

# Override editor for this machine
$env:EDITOR = "code"

# Add work tools to PATH
$env:PATH = "C:\work\tools\bin;$env:PATH"

Benefits of This Structure

Modular

Each module has a single responsibility and can be enabled/disabled independently

Predictable

Numbered prefixes ensure consistent load order across machines

Maintainable

Easy to add, remove, or modify specific features without touching other modules

Portable

The entire ~/.config/powershell directory can be versioned and synced

See Also

Build docs developers (and LLMs) love