Thank you for considering contributing to this project! This document provides guidelines and instructions for contributing.
⚡ Quick Reference: See DEVELOPER-REFERENCE.md for command cheatsheet, validation scripts, and common fixes.
- Code of Conduct
- Getting Started
- How to Contribute
- Development Setup
- Coding Standards
- Testing
- Pull Request Process
- Be respectful and inclusive
- Welcome newcomers and help them learn
- Focus on constructive feedback
- Respect differing viewpoints and experiences
- Windows 10/11
- PowerShell 7+
- Git
- Code editor (VS Code recommended)
# Fork the repository on GitHub first
# Clone your fork
git clone https://github.com/YOUR-USERNAME/powershell-environment.git
cd powershell-environment
# Add upstream remote
git remote add upstream https://github.com/ORIGINAL-OWNER/powershell-environment.git- Check if the bug is already reported in Issues
- If not, create a new issue with:
- Clear, descriptive title
- Steps to reproduce
- Expected vs actual behavior
- PowerShell version (
$PSVersionTable) - OS version
- Relevant logs or screenshots
- Check existing Issues and Discussions
- Create a new issue or discussion with:
- Clear description of the enhancement
- Why it would be useful
- Possible implementation approach
- Any alternatives considered
Great areas to contribute:
- Bundled Modules - Add new
.psm1files toPowerShell/IncludedModules/(shipped with repo) - Additional Standard Modules - Suggest useful PSGallery modules to include
- Yazi Plugins/Themes - Additional Yazi configurations
- oh-my-posh Themes - New prompt themes
- Documentation - Improvements and examples
- Bug Fixes - Issue resolution
- Performance - Optimization improvements
Adding a new bundled module to the DevKit - add a .psm1 file to PowerShell/IncludedModules/:
# Example: PowerShell/IncludedModules/my-tools.psm1
<#
.SYNOPSIS
My custom PowerShell utilities
#>
function Get-MyCustomTool {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$Name
)
Write-Host "Running custom tool: $Name"
}
# Export only the functions you want to be public
Export-ModuleMember -Function Get-MyCustomToolThat's it! The module will be loaded via the Components system. Add it to the Components.psm1 file to include it in the setup.
Module Loading Rules:
- ✅ Added to
PowerShell/IncludedModules/*.psm1 - ✅ Registered in
Scripts/Components.psm1for static loading - ✅ Loaded during deferred startup (doesn't slow shell initialization)
- ✅ Use
Export-ModuleMemberto control what's public - ✅ Shipped with the repo (tracked in git)
Note for Users: If you want to add your own personal modules (not contributed to the repo), create them in PowerShell/CustomModules/ instead. Those are auto-discovered and never overwritten by updates.
-
Install Dependencies
# Run the setup script .\Scripts\Setup-PowerShellEnvironment.ps1 # Install PSScriptAnalyzer for linting Install-Module -Name PSScriptAnalyzer -Scope CurrentUser
-
Create a Feature Branch
git checkout -b feature/my-new-feature # or git checkout -b fix/bug-description
-
Make Your Changes
- Edit files as needed
- Test your changes
- Follow coding standards (see below)
-
Commit Your Changes
git add . git commit -m "feat: add amazing new feature"
- Use PascalCase for function names
- Use camelCase for variables
- Use approved verbs (Get-Verb for list)
- Add comment-based help to all functions
- Include parameter validation where appropriate
- Use Write-Host for output, Write-Verbose for debug info
- Avoid aliases in scripts (use full cmdlet names)
<#
.SYNOPSIS
Short description
.DESCRIPTION
Detailed description
.PARAMETER ParameterName
Description of parameter
.EXAMPLE
Example usage
#>
function Verb-Noun {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$ParameterName
)
begin {
Write-Verbose "Starting operation"
}
process {
# Main logic here
}
end {
Write-Verbose "Operation complete"
}
}- One function per file (for large modules)
- Group related functions in modules
- Export only public functions
- Keep internal helpers private
- TOML: Use consistent indentation (2 spaces)
- JSON: Use 2-space indentation, validate with linter
- Lua: Follow Lua style guide
- Update README.md if adding new features
- Update README.md if changing setup process
- Add inline comments for complex logic
- Update changelog (if maintained)
Before committing any changes, run our validation script:
# Run comprehensive validation (REQUIRED before commits)
.\Scripts\Validate-Code.ps1
# Quick validation (syntax only)
.\Scripts\Validate-Code.ps1 -Quick
# Show detailed PSScriptAnalyzer results
.\Scripts\Validate-Code.ps1 -DetailedWe use PSScriptAnalyzer to maintain high code quality. All code must pass analysis before being committed.
# Install PSScriptAnalyzer
Install-Module -Name PSScriptAnalyzer -Scope CurrentUser -Force# Use project settings (RECOMMENDED)
Invoke-ScriptAnalyzer -Path . -Recurse -Settings .\PSScriptAnalyzerSettings.psd1
# Check specific file
Invoke-ScriptAnalyzer -Path .\Scripts\Setup.ps1 -Settings .\PSScriptAnalyzerSettings.psd1
# Export results for review
Invoke-ScriptAnalyzer -Path . -Recurse -Settings .\PSScriptAnalyzerSettings.psd1 |
ConvertTo-Json | Out-File "analysis-results.json"- ✅ ERRORS: Must be zero (builds will fail)
⚠️ WARNINGS: Should be minimized (acceptable for merging)- ℹ️ INFORMATION: Informational only
| Rule | Issue | Fix |
|---|---|---|
PSAvoidUsingCmdletAliases |
Using ls instead of Get-ChildItem |
Use full cmdlet names |
PSUseDeclaredVarsMoreThanAssignments |
Unused variables | Remove or use variables |
PSAvoidGlobalVars |
Using $global: scope |
Use parameters or return values |
PSUseCmdletCorrectly |
Incorrect parameter usage | Check parameter sets |
PSAvoidUsingPositionalParameters |
Missing parameter names | Use -ParameterName syntax |
-
✅ Code Analysis
# Must pass with zero errors .\Scripts\Validate-Code.ps1
-
✅ Syntax Validation
# Test all PowerShell files Get-ChildItem -Path . -Include "*.ps1", "*.psm1" -Recurse | ForEach-Object { $errors = $null [void][System.Management.Automation.PSParser]::Tokenize((Get-Content $_.FullName -Raw), [ref]$errors) if ($errors) { Write-Error "Syntax error in $($_.Name): $($errors[0].Message)" } }
-
✅ Functionality Testing
# Test your specific changes .\Scripts\Test.ps1 # For setup script changes, test on clean environment .\Scripts\Setup.ps1 -WhatIf
-
✅ Profile Loading
# Test profile loads without errors powershell -NoProfile -Command ". '$PROFILE'"
-
✅ Module Import
# Test bundled modules import correctly Import-Module .\PowerShell\IncludedModules\utilities.psm1 -Force Import-Module .\PowerShell\IncludedModules\build_functions.psm1 -Force
-
✅ Configuration Validation
# Test Yazi config (if modified) yazi --check-config # Test oh-my-posh theme (if modified) oh-my-posh config validate --config .\Config\oh-my-posh\iterm2.omp.json
# Measure profile load time
Measure-Command { powershell -NoProfile -Command ". '$PROFILE'" }
# Should be under 2 seconds for good performance# Test on PowerShell 5.1 (if available)
powershell.exe -NoProfile -File .\Scripts\YourScript.ps1
# Test on PowerShell 7
pwsh -NoProfile -File .\Scripts\YourScript.ps1For major changes, test on a clean environment:
# Use Windows Sandbox, VM, or container
# Fresh Windows install → Clone repo → Run setup- ✅ Script runs without errors
- ✅ All parameters work as expected
- ✅ Help documentation is accurate
- ✅ No breaking changes to existing functionality
- ✅ Works on Windows 10 and 11
- ✅ Follows existing patterns and style
Set up automatic validation before each commit:
# Cross-platform pre-commit hook setup
$hookDir = Join-Path ".git" "hooks"
$hookFile = Join-Path $hookDir "pre-commit"
# Create hooks directory
New-Item -Path $hookDir -ItemType Directory -Force
# Create cross-platform pre-commit hook
$hookContent = @'
#!/bin/sh
# PowerShell code validation pre-commit hook (cross-platform)
echo "🔍 Running PowerShell code validation..."
# Try pwsh first (PowerShell 7+), fall back to powershell if needed
if command -v pwsh >/dev/null 2>&1; then
pwsh -NoProfile -ExecutionPolicy Bypass -File "Scripts/Validate-Code.ps1" -Quick
elif command -v powershell >/dev/null 2>&1; then
powershell -NoProfile -ExecutionPolicy Bypass -File "Scripts/Validate-Code.ps1" -Quick
else
echo "❌ PowerShell not found. Please install PowerShell 7+ (pwsh)"
exit 1
fi
if [ $? -ne 0 ]; then
echo "❌ Code validation failed. Run './Scripts/Validate-Code.ps1' for details."
echo "💡 Tip: Use 'git commit --no-verify' to skip validation (not recommended)"
exit 1
fi
echo "✅ Code validation passed."
'@
# Write hook file with proper encoding
$hookContent | Out-File $hookFile -Encoding UTF8 -NoNewline
# Make executable on Unix-like systems
if ($IsLinux -or $IsMacOS) {
chmod +x $hookFile
Write-Host "✅ Pre-commit hook installed and made executable" -ForegroundColor Green
} else {
Write-Host "✅ Pre-commit hook installed (Windows)" -ForegroundColor Green
}
Write-Host "🎯 Hook location: $hookFile" -ForegroundColor Cyan# Alternative setup for Linux/macOS/WSL
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
echo "🔍 Running PowerShell code validation..."
pwsh -NoProfile -ExecutionPolicy Bypass -File "Scripts/Validate-Code.ps1" -Quick
if [ $? -ne 0 ]; then
echo "❌ Validation failed. Run './Scripts/Validate-Code.ps1' for details."
exit 1
fi
echo "✅ Validation passed."
EOF
chmod +x .git/hooks/pre-commit-
Update from upstream
git fetch upstream git rebase upstream/main -
🔍 REQUIRED: Run full validation
# This MUST pass before creating PR .\Scripts\Validate-Code.ps1
-
Update documentation if needed
-
Push to your fork:
git push origin feature/my-new-feature
-
Go to GitHub and create a Pull Request
-
Fill in the PR template with:
- Description of changes
- Motivation for the change
- Type of change (bugfix, feature, docs, etc.)
- Testing performed
- Screenshots if UI changes
Use conventional commits format:
feat: add new custom functionfix: resolve yazi plugin installation issuedocs: update READMErefactor: improve module loading performancetest: add validation for custom moduleschore: update dependencies
- Maintainer will review your PR
- Address any feedback or requested changes
- Once approved, PR will be merged
- Your contribution will be credited!
We'd especially love contributions in these areas:
- Cross-platform support - Make scripts work on Linux/macOS
- Additional modules - Useful PowerShell modules everyone should have
- Performance - Speed up profile loading or scripts
- Documentation - More examples, guides, tips
- Themes - Additional oh-my-posh themes
- Yazi configs - More plugin configurations
- Tests - Automated testing improvements
Look for issues labeled:
good first issuehelp wanteddocumentation
- 💬 Start a Discussion
- 📖 Read existing documentation
- 🔍 Search closed issues for similar problems
By contributing, you agree that your contributions will be licensed under the MIT License.
Every PR automatically runs comprehensive validation via GitHub Actions:
- ✅ PSScriptAnalyzer with project settings
- ✅ Syntax validation for all PowerShell files
- ✅ Configuration validation (JSON, TOML, PSD1)
- ✅ Module import testing
- ✅ Cross-platform compatibility checks
Check your PR status:
- 🟢 All checks passed → Ready for review
- 🟡 Some warnings → Review suggested fixes
- 🔴 Failures detected → Must fix before merge
- Go to your PR → "Checks" tab
- Click "Validate PowerShell Scripts"
- Download "pssa-results" artifact for detailed analysis
- Review JSON reports for comprehensive issue details
The Validate-Code.ps1 script uses identical rules to GitHub Actions, so local validation results will match CI results.
All contributors will be:
- Listed in the project README
- Credited in release notes
- Part of building an awesome PowerShell environment!
Thank you for contributing! 🎉
Questions? Feel free to open an issue or discussion!