PowerShell Profile: Create a Custom Profile Script

PowerShell Profile: Create a Custom Profile Script

PowerShell Tips Editor 4 min read
PowerShell Profile: Create a Custom Profile Script

Every time you open PowerShell, you’re starting from scratch — unless you have a profile. Your PowerShell profile is a script that runs automatically at session start, loading your aliases, functions, modules, and custom prompt so your environment is ready the moment the prompt appears. Set it up once and every future session has your tools ready. This post covers all four profile paths, creation, and the most useful things to put in yours.

The Four Profile Paths

PowerShell has four profile files with different scopes. They load in order from broadest to most specific, with later profiles overriding earlier settings.

# View all four profile path variables
$PROFILE.AllUsersAllHosts        # All users, all hosts
$PROFILE.AllUsersCurrentHost     # All users, current host (ISE or pwsh)
$PROFILE.CurrentUserAllHosts     # Current user, all hosts
$PROFILE.CurrentUser             # Current user, current host (most specific)

# Quick reference — show all paths
$PROFILE | Select-Object *
AllUsersAllHosts     : C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
AllUsersCurrentHost  : C:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1
CurrentUserAllHosts  : C:\Users\jsmith\Documents\WindowsPowerShell\profile.ps1
CurrentUser         : C:\Users\jsmith\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

For personal customization, use $PROFILE.CurrentUser — it doesn’t affect other users and survives system updates.

Create Your Profile File

The profile file usually doesn’t exist until you create it. Check first, then create it with the appropriate editor.

# Check if profile exists
Test-Path $PROFILE

# Create the profile file (and any missing parent directories)
if (-not (Test-Path $PROFILE)) {
    New-Item -Path $PROFILE -ItemType File -Force
    Write-Output "Profile created at: $PROFILE"
}

# Open in Notepad for editing
notepad $PROFILE

# Or open in VS Code
code $PROFILE

Add Custom Aliases

Aliases defined in your profile are available every session. Keep them short and intuitive. Remember: Set-Alias maps a name to a cmdlet only — if you need an alias that includes arguments, use a function instead (see below).

# In your $PROFILE file:

# Short aliases for common cmdlets
Set-Alias g   Get-ChildItem
Set-Alias v   Get-Content
Set-Alias his Get-History

# Alias to a function for complex shortcuts (aliases can't carry arguments)
function ll { Get-ChildItem -Force $args }
function touch { New-Item -ItemType File -Name $args[0] }
function .. { Set-Location .. }
function ... { Set-Location ..\.. }

Auto-Import Modules

Modules you use daily should import automatically. Place Import-Module calls in your profile so they’re always ready without a manual import step.

# In your $PROFILE file:

# Import frequently used modules silently
Import-Module -Name PSReadLine -ErrorAction SilentlyContinue
Import-Module -Name Posh-Git   -ErrorAction SilentlyContinue  # Git integration in prompt

# Set PSReadLine options for better history and completion
Set-PSReadLineOption -HistorySearchCursorMovesToEnd
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward

Customize the Prompt Function

The built-in prompt is functional but minimal. Override it with a function prompt in your profile. The function should return a string — whatever you return becomes the prompt displayed before each command.

# In your $PROFILE file:

function prompt {
    $currentPath = (Get-Location).Path
    # Abbreviate home directory as ~
    $currentPath = $currentPath -replace [regex]::Escape($HOME), "~"

    $gitBranch = ""
    if (Test-Path ".git") {
        $branch = git rev-parse --abbrev-ref HEAD 2>$null
        if ($branch) { $gitBranch = " [$branch]" }
    }

    # Blue path + yellow git branch + white PS>
    Write-Host $currentPath -ForegroundColor Blue -NoNewline
    Write-Host $gitBranch   -ForegroundColor Yellow -NoNewline
    return " PS> "
}

Profile Across Windows and PowerShell 7

Windows PowerShell (5.1) and PowerShell 7 use different profile paths. A setting in your Windows PowerShell profile does not automatically apply to PowerShell 7.

# Windows PowerShell 5.1 profile:
# C:\Users\jsmith\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

# PowerShell 7 profile:
# C:\Users\jsmith\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

# To share a profile between both, source the common file from each:
# Add this to both profile files:
. "$env:USERPROFILE\Documents\PowerShell\common-profile.ps1"

Note the directory difference: Windows PowerShell uses WindowsPowerShell; PowerShell 7 uses PowerShell.

Common Errors and Fixes

  • Profile won’t load — execution policy blocks it: If PowerShell shows “File cannot be loaded because running scripts is disabled,” the execution policy is preventing your profile from running. Fix it with: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser. This allows locally created scripts (including your profile) to run while still requiring signatures on downloaded scripts.
  • Wrong profile path for PowerShell 7 vs Windows PowerShell: Changes you make to $PROFILE in a Windows PowerShell session only affect that host. If your aliases and functions aren’t appearing in PowerShell 7, you’re editing the wrong file. Always confirm which host you’re in with $PSVersionTable.PSVersion before editing a profile.

Related Cmdlets / See Also

Wrapping Up

Your PowerShell profile is the highest-leverage customization you can make — one file that pays dividends in every future session. As a next step, add at least the PSReadLine configuration block from above for better command history navigation, then add one new alias or function each week until your profile truly reflects how you work.

Send-Item -To