Automating PowerShell Code Formatting with Pre-Commit Hooks #
The Problem #
If you’re working on a PowerShell project with multiple developers, you’ve probably experienced the pain of inconsistent code formatting. One developer uses tabs, another uses spaces. Braces are sometimes on the same line, sometimes on a new line. It’s a mess, and code reviews become debates about formatting instead of logic.
VS Code’s PowerShell extension has a great “Format Document” feature, but let’s be honest—developers forget to use it.
The Solution #
Enter pre-commit hooks combined with a PowerShell formatter. In this post, I’ll show you how to set up automatic PowerShell code formatting that:
- Runs automatically on every commit
- Uses PSScriptAnalyzer (the same tool VS Code uses)
- Maintains consistent formatting across your team
- Works in CI/CD pipelines
Prerequisites #
You’ll need:
- Git
- Python 3.12+
- PowerShell 5.1 or later
- The
pre-commitframework
Step 1: Install Pre-Commit Framework #
Pre-commit is a framework for managing git hooks. Install it with pip:
pip install pre-commit
Verify the installation:
pre-commit --version
Step 2: Set Up the PowerShell Formatter #
We’ll use a fantastic script from nathan815’s PowerShell-Formatter that wraps PSScriptAnalyzer.
Create the pre-commit folder structure #
mkdir pre-commit
Download the formatter script #
Invoke-RestMethod -Uri "https://raw.githubusercontent.com/nathan815/PowerShell-Formatter/main/FormatCode.ps1" -OutFile "pre-commit/FormatCode.ps1"
Install PSScriptAnalyzer #
The formatter requires PSScriptAnalyzer module:
Install-Module -Name PSScriptAnalyzer -Scope CurrentUser -Force -RequiredVersion 1.23.0
Or use the built-in installation option:
.\pre-commit\FormatCode.ps1 -InstallDependencies
Step 3: Configure Formatting Rules #
Create pre-commit/PSScriptAnalyzerSettings.psd1 to define your formatting rules:
@{
IncludeRules = @(
"PSPlaceOpenBrace",
"PSPlaceCloseBrace",
"PSUseConsistentIndentation",
"PSUseConsistentWhitespace",
"PSAlignAssignmentStatement",
"PSUseCorrectCasing"
)
Rules = @{
PSPlaceOpenBrace = @{
Enable = $true
OnSameLine = $true
NewLineAfter = $true
IgnoreOneLineBlock = $true
}
PSPlaceCloseBrace = @{
Enable = $true
NewLineAfter = $true
IgnoreOneLineBlock = $true
NoEmptyLineBefore = $false
}
PSUseConsistentIndentation = @{
Enable = $true
IndentationSize = 4
PipelineIndentation = 'IncreaseIndentationForFirstPipeline'
Kind = 'space'
}
PSUseConsistentWhitespace = @{
Enable = $true
CheckInnerBrace = $true
CheckOpenBrace = $true
CheckOpenParen = $true
CheckOperator = $true
CheckPipe = $true
CheckPipeForRedundantWhitespace = $true
CheckSeparator = $true
CheckParameter = $false
}
PSAlignAssignmentStatement = @{
Enable = $true
CheckHashtable = $true
}
PSUseCorrectCasing = @{
Enable = $true
}
}
}
These rules match VS Code’s PowerShell extension defaults: 4-space indentation, braces on the same line, consistent whitespace, and proper cmdlet casing.
Step 4: Configure Pre-Commit #
Create .pre-commit-config.yaml in your repository root:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: fix-byte-order-marker
- repo: local
hooks:
- id: powershell-formatter
name: PowerShell Code Formatter
entry: powershell.exe -NoProfile -ExecutionPolicy Bypass -File pre-commit/FormatCode.ps1 -File
language: system
types: [powershell]
pass_filenames: true
default_language_version:
python: python3
The key part is the local repo hook that runs the PowerShell formatter on all .ps1 and .psm1 files.
Step 5: Install the Git Hooks #
Install pre-commit in your repository:
pre-commit install
This creates the actual git hook file in .git/hooks/pre-commit.
Step 6: Test It Out #
Create a test file with intentionally bad formatting:
# test-format.ps1
function Test-Formatting{
param($name,$value)
if($name -eq "test"){
Write-Host "Hello $name"
}
$result=Get-Process|Where-Object{$_.Name -eq "powershell"}
return $result
}
Stage and commit it:
git add test-format.ps1
git commit -m "test: formatting"
You’ll see the formatter run and fix the formatting! The commit will initially fail because files were modified. This is intentional—it lets you review the changes:
# Review the formatted changes
git diff test-format.ps1
# Stage the formatted version
git add test-format.ps1
# Commit again - will succeed this time
git commit -m "test: formatting"
The formatted file will look like this:
# test-format.ps1
function Test-Formatting {
param($name, $value)
if ($name -eq "test") {
Write-Host "Hello $name"
}
$result = Get-Process | Where-Object { $_.Name -eq "powershell" }
return $result
}
Beautiful! Proper spacing, consistent indentation, and clean formatting.
Manual Formatting #
You can also run the formatter manually:
# Format all PowerShell files
.\pre-commit\FormatCode.ps1
# Format a specific directory
.\pre-commit\FormatCode.ps1 -Directory ".\src"
# Format a single file
.\pre-commit\FormatCode.ps1 -File ".\src\MyModule.psm1"
# Check formatting without modifying (for CI)
.\pre-commit\FormatCode.ps1 -CheckOnly
CI/CD Integration #
Add this to your GitLab CI or GitHub Actions workflow to ensure all code is formatted:
# GitLab CI example
format-check:
script:
- pwsh -File pre-commit/FormatCode.ps1 -CheckOnly
The -CheckOnly flag makes the script exit with code 1 if any files need reformatting, perfect for CI validation.
Workflow Benefits #
Once set up, the workflow is seamless:
- Write code in your normal style
- Commit → formatter automatically fixes formatting
- Review the changes (if any)
- Stage and commit again → passes
Your team gets:
- ✅ Consistent code style across the entire codebase
- ✅ No more formatting debates in code reviews
- ✅ Automatic enforcement via pre-commit hooks
- ✅ CI validation to catch any bypasses
- ✅ Zero manual effort after initial setup
Customization #
Don’t like the default rules? Customize PSScriptAnalyzerSettings.psd1:
- Change indentation size
- Move braces to new lines
- Adjust whitespace rules
- Enable/disable specific formatting rules
See the PSScriptAnalyzer rules reference for all available options.
Troubleshooting #
Hook doesn’t run on commit #
Make sure you installed it:
pre-commit install
PSScriptAnalyzer not found #
Install the module:
.\pre-commit\FormatCode.ps1 -InstallDependencies
Need to bypass the hook temporarily #
Use --no-verify (not recommended):
git commit --no-verify -m "skip formatting"
Final Thoughts #
Automating PowerShell code formatting with pre-commit hooks has been a game-changer for our team. No more inconsistent indentation, no more whitespace debates, and code reviews focus on what matters—the logic.
The setup takes about 10 minutes, and the benefits last forever. If you’re working on any PowerShell project with multiple developers, I highly recommend giving this a try.