My personal PowerShell profile, shared in case it's useful to others.
- Windows only. The profile assumes Windows paths (
C:\...) and Windows-specific tools (devenv,rider64.exe,winget, Windows Terminal). It will not work as-is on macOS/Linux. - PowerShell 7.1 or later (i.e.
pwsh, not Windows PowerShell 5.1). The profile uses the??null-coalescing operator and the.LinkTargetproperty on symlinks, neither of which exist in Windows PowerShell 5.1. - If you download the repo as a zip instead of
git clone-ing it, Windows may block the.ps1files as coming from the internet - runGet-ChildItem -Recurse *.ps1 | Unblock-Filein the repo folder, and make sure your execution policy allows running local scripts (e.g.RemoteSigned).
- PSReadLine
- Get-ChildItemColor
- Oh-My-Posh (supersedes Posh-Git; no need to also install Posh-Git)
- Remember to install a Nerd Font and use it your shell (I like Windows Terminal), see https://ohmyposh.dev/docs/fonts.
- For the font, I like "FuraCode Nerd Font Mono" (in the bundle "FiraCode Nerd Font"), because it has nordic characters; get it (or other Nerd Fonts) here: https://www.nerdfonts.com/font-downloads
- winget - used for autocomplete and a periodic "upgradeable packages" reminder.
- A few of my own PowerShell utils - which may have evolved to have their own dependencies. Please check notes on usage in that repo.
None of these are hard requirements: each module/tool is imported defensively, so if something isn't installed, the profile prints a warning for that piece and keeps loading the rest.
Either
- clone directly into your PowerShell profile directory, or,
- clone in another directory, and setup a symlink to the path where PowerShell looks for your profile. I.e., in an elevated shell, from the cloned directory, do something like:
New-Item -Path $PROFILE -ItemType SymbolicLink -Value (Get-Item .\Microsoft.PowerShell_profile.ps1).FullNameSince it's just a git repo, pull the latest changes from wherever you cloned it:
git pullMicrosoft.PowerShell_profile.ps1 itself is just a small loader. The actual logic lives in profile.d/, loaded in filename order, one concern per file:
| File | Purpose |
|---|---|
00-helpers.ps1 |
Shared helper functions (safe module import/dot-source, Test-IsElevated, etc.) |
10-options.ps1 |
Config variables - utils path, outdated-check settings |
20-modules.ps1 |
PSReadLine |
30-aliases-and-tools.ps1 |
s, vs/OpenWithVisualStudio, rider/OpenWithRider, winutil |
40-utils-import.ps1 |
Loads scripts from the dontrolle/Powershell utils repo |
50-prompt-and-git.ps1 |
Get-ChildItemColor, l/ls aliases, oh-my-posh prompt |
60-winget.ps1 |
winget tab-completion |
70-banner-and-checks.ps1 |
Startup reminders banner + periodic winget upgradeable check |
90-personal.ps1.example |
Example personal touch (starting directory) - not loaded automatically |
Feel free to add, remove, reorder, or split these files further to fit your own setup.
- Utils path: by default the profile looks for the dontrolle/Powershell utils repo at
$Home\src\Powershell. Override this by setting$env:POWERSHELL_UTILS_PATHbefore the profile loads, or inprofile.local.ps1(see below). profile.local.ps1: an optional, gitignored file in the repo root. If present, it is dot-sourced first, before anything inprofile.d/, so it can pre-set any option variable used inprofile.d/10-options.ps1(e.g.$PowershellUtilsPath) as well as run arbitrary personal tweaks (e.g. a starting directory - seeprofile.d/90-personal.ps1.example) - all without editing tracked files.
The CI GitHub Actions workflow runs PSScriptAnalyzer (and the Pester tests, see Tests below) on every push/PR. Run the lint locally with:
Install-Module -Name PSScriptAnalyzer -Scope CurrentUser
Invoke-ScriptAnalyzer -Path . -Settings .\PSScriptAnalyzerSettings.psd1 -RecurseUnit tests live under Tests/ and use Pester v5. They cover:
Tests/ScriptSyntax.Tests.ps1- a syntax smoke test asserting every*.ps1file parses cleanly.Tests/Helpers.Tests.ps1-_Test-DotSourceTargetfrom00-helpers.ps1.Tests/Aliases.Tests.ps1- the.sln-resolution logic inOpenWithVisualStudiofrom30-aliases-and-tools.ps1(withGet-ChildItem/Start-Processmocked).
Run them locally with:
Install-Module -Name Pester -MinimumVersion 5.0.0 -Scope CurrentUser
Invoke-Pester -Path .\TestsSee LICENSE.