A PowerShell module for organizing scripts, executables, and CLI tools using command proxies. Stop cluttering your PATH - organize your tools into logical namespaces and access them through a single entry point.
As your collection of PowerShell scripts and CLI tools grows, you face a common challenge:
- Scripts scattered across multiple directories
- Adding every folder to PATH becomes unmanageable
- No logical organization for related tools
- Difficult to remember where each tool lives
PowerStub creates command proxies (called "stubs") that serve as namespaced entry points to your organized tools:
# Instead of remembering paths or adding to PATH:
C:\Tools\DevOps\Scripts\Deployment\deploy-app.ps1 -Environment prod
# Use a simple, organized command:
pstb DevOps deploy-app -Environment prod- Namespace Organization: Group related tools under logical stub names
- Tab Completion: Full IntelliSense for stub names, commands, and parameters
- Dynamic Parameters: Automatically inherits parameters from target commands
- Multi-format Support: Works with
.ps1scripts and.exeexecutables - Lifecycle Prefixes: Built-in support for
alpha.*andbeta.*command stages - Zero PATH Pollution: Single alias (
pstb) provides access to all your tools - Built-in Commands: Search across stubs and get help for any command
- Direct Aliases: Create shortcut aliases for frequently used stubs
- Git Integration: Automatic detection and updates for Git-based stub repositories
The easiest way to install PowerStub:
# Install from PowerShell Gallery
Install-Module -Name PowerStub -Scope CurrentUser
# Import the module
Import-Module PowerStub
# Add to your PowerShell profile for persistent use
Add-Content $PROFILE "`nImport-Module PowerStub"Download a specific release from GitHub Releases:
- Download the latest release
.zipfile - Extract to a folder (e.g.,
C:\Modules\PowerStub) - Import the module:
# Import from extracted location
Import-Module C:\Modules\PowerStub\PowerStub.psd1
# Add to your PowerShell profile for persistent use
Add-Content $PROFILE "`nImport-Module 'C:\Modules\PowerStub\PowerStub.psd1'"Clone the repository for development or to get the latest changes:
# Clone the repository
git clone https://github.com/DevPossible/power-stub.git
# Import the module from source
Import-Module ./power-stub/PowerStub/PowerStub.psm1
# Add to your PowerShell profile for persistent use
Add-Content $PROFILE "`nImport-Module 'C:\path\to\power-stub\PowerStub\PowerStub.psm1'"After installing the module, you need to add it to your PowerShell profile so it loads automatically. If you haven't already done so during installation:
# Add PowerStub to your profile (PSGallery install)
Add-Content -Path $PROFILE -Value "`nImport-Module PowerStub"
# Or for a custom path (GitHub/Source install)
Add-Content -Path $PROFILE -Value "`nImport-Module 'C:\path\to\PowerStub\PowerStub.psd1'"Then reload your profile to apply the changes without restarting PowerShell:
. $PROFILEVerify the module is loaded and the pstb alias is available:
pstbYou should see the PowerStub overview with any registered stubs and built-in commands.
Note: If
$PROFILEdoesn't exist yet, create it first with:New-Item -Path $PROFILE -ItemType File -Force
# Register a stub for your DevOps tools
New-PowerStub -Name "DevOps" -Path "C:\Tools\DevOps"This creates the following folder structure:
C:\Tools\DevOps\
├── Commands\ # Your commands go here
└── .tests\ # Test files
Place your scripts or executables in the Commands folder:
# C:\Tools\DevOps\Commands\deploy-app.ps1
param(
[Parameter(Mandatory)]
[string]$Environment,
[string]$Version = "latest"
)
Write-Host "Deploying to $Environment with version $Version"For commands that need helper scripts, data files, or executables, create a subfolder with the command name. Only the file matching the folder name is exposed as a command:
Commands/
├── simple-task.ps1 # Exposed as "simple-task"
├── quick-deploy.exe # Exposed as "quick-deploy"
└── complex-deploy/ # Subfolder for complex command
├── complex-deploy.ps1 # Exposed as "complex-deploy"
├── deploy-helper.ps1 # NOT exposed (helper script)
├── config.json # NOT exposed (data file)
└── validator.exe # NOT exposed (helper executable)
This prevents helper scripts from appearing in tab completion or being accidentally invoked as commands.
# Tab completion works for stub names
pstb Dev<TAB> # Completes to "DevOps"
# Tab completion works for commands
pstb DevOps dep<TAB> # Completes to "deploy-app"
# Tab completion works for parameters
pstb DevOps deploy-app -Env<TAB> # Completes to "-Environment"
# Execute the command
pstb DevOps deploy-app -Environment prod -Version 2.0.1| Command | Description |
|---|---|
New-PowerStub -Name <name> -Path <path> |
Register a new stub and create folder structure |
Remove-PowerStub -Name <name> |
Unregister a stub (files remain) |
Get-PowerStubs |
List all registered stubs |
Get-PowerStubCommand -Stub <name> -Command <cmd> |
Get command object details |
| Command | Alias | Description |
|---|---|---|
Invoke-PowerStubCommand -Stub <name> -Command <cmd> |
pstb |
Execute a command from a stub |
pstb (no args) |
Show overview with stubs and built-in commands | |
pstb <stub> (no command) |
List commands in the stub |
These virtual commands work across all stubs without needing script files:
| Command | Description |
|---|---|
pstb search <query> |
Search commands by name or help text across all stubs |
pstb help <stub> <command> |
Display PowerShell help for a specific command |
pstb update [stub] |
Update Git repositories for stubs |
# Find all commands related to "deploy"
pstb search "deploy"
# Get detailed help for a command
pstb help DevOps deploy-app
# Update all Git-tracked stubs
pstb update
# Update a specific stub's Git repository
pstb update DevOpsCreate shortcut aliases for frequently used stubs:
| Command | Description |
|---|---|
New-PowerStubDirectAlias -AliasName <alias> -Stub <stub> |
Create a direct alias for a stub |
Remove-PowerStubDirectAlias -AliasName <alias> |
Remove a direct alias |
# Create a short alias for your DevOps stub
New-PowerStubDirectAlias -AliasName "do" -Stub "DevOps"
# Now use the shorter syntax
do deploy-app -Environment prod # Same as: pstb DevOps deploy-app -Environment prod
do # List commands in DevOps
# Remove the alias when no longer needed
Remove-PowerStubDirectAlias -AliasName "do"Direct aliases are persisted and automatically restored when the module loads.
| Command | Description |
|---|---|
Get-PowerStubConfiguration |
View current configuration |
Import-PowerStubConfiguration |
Reload configuration from file |
Import-PowerStubConfiguration -Reset |
Reset to defaults |
| Command | Description |
|---|---|
Enable-PowerStubAlphaCommands |
Show alpha.* prefixed commands |
Disable-PowerStubAlphaCommands |
Hide alpha commands |
Enable-PowerStubBetaCommands |
Show beta.* prefixed commands |
Disable-PowerStubBetaCommands |
Hide beta commands |
Set-PowerStubCommandVisibility -Stub <s> -Command <c> -Visibility <v> |
Change command lifecycle stage |
# Promote a command from production to alpha (work-in-progress)
Set-PowerStubCommandVisibility -Stub DevOps -Command deploy -Visibility Alpha
# Promote to beta testing
Set-PowerStubCommandVisibility -Stub DevOps -Command deploy -Visibility Beta
# Release to production
Set-PowerStubCommandVisibility -Stub DevOps -Command deploy -Visibility ProductionPowerStub stores its configuration in PowerStub.json, located in the module directory (alongside PowerStub.psm1):
{
"Stubs": {
"DevOps": "C:\\Tools\\DevOps\\",
"Database": "C:\\Tools\\Database\\"
},
"InvokeAlias": "pstb",
"EnablePrefix:Alpha": false,
"EnablePrefix:Beta": false
}| Key | Type | Default | Description |
|---|---|---|---|
Stubs |
Object | {} |
Map of stub names to root paths (or config objects with GitRepoUrl) |
InvokeAlias |
String | pstb |
Alias for Invoke-PowerStubCommand |
EnablePrefix:Alpha |
Boolean | false |
Include alpha.* prefixed commands |
EnablePrefix:Beta |
Boolean | false |
Include beta.* prefixed commands |
GitEnabled |
Boolean | true |
Enable Git integration (auto-detected on load) |
PowerStub supports organizing commands by development stage using filename prefixes:
YourStub/Commands/
├── alpha.new-feature.ps1 # Work in progress (Enable-PowerStubAlphaCommands)
├── beta.deploy-v2.ps1 # Beta testing (Enable-PowerStubBetaCommands)
├── deploy.ps1 # Production-ready (always visible)
└── complex-task/ # Subfolder for complex command
├── alpha.complex-task.ps1 # Alpha version (file matches folder name)
└── complex-task.ps1 # Production version
Prefix conventions:
alpha.*- Work-in-progress commands (developer mode)beta.*- Beta/experimental commands (tester mode)- No prefix - Production-ready commands
Workflow:
- Create new commands with
alpha.prefix (e.g.,alpha.my-feature.ps1) - Rename to
beta.prefix when ready for testing - Remove prefix for production use
Resolution precedence: alpha.* → beta.* → production (no prefix)
When multiple versions exist (e.g., alpha.deploy.ps1, beta.deploy.ps1, deploy.ps1),
the command resolves in precedence order based on enabled modes. This applies to both direct files and files in subfolders.
PowerStub integrates with Git to help you keep your stub repositories up to date.
When you register a new stub with New-PowerStub, PowerStub automatically detects if the path is part of a Git repository and saves the remote URL in the configuration.
# If C:\Tools\DevOps is a Git repo, the remote URL is saved automatically
New-PowerStub -Name "DevOps" -Path "C:\Tools\DevOps"When the PowerStub module loads, it checks each Git-tracked stub to see if it's behind the remote repository:
Stub 'DevOps' is 5 commit(s) behind the remote repo. Run 'pstb update DevOps' to update.
Use the update command to pull the latest changes:
# Update all Git-tracked stubs
pstb update
# Update a specific stub
pstb update DevOpsGit integration is enabled by default when Git is available. You can disable it:
# Disable Git integration
Set-PowerStubConfigurationKey 'GitEnabled' $false
# Re-enable Git integration
Set-PowerStubConfigurationKey 'GitEnabled' $trueNew-PowerStub -Name "DevOps" -Path "C:\Tools\DevOps"
New-PowerStub -Name "Database" -Path "C:\Tools\Database"
New-PowerStub -Name "Azure" -Path "C:\Tools\Azure"
# View all stubs
Get-PowerStubs
# Output:
# Name Value
# ---- -----
# DevOps C:\Tools\DevOps\
# Database C:\Tools\Database\
# Azure C:\Tools\Azure\# Enable alpha visibility
Enable-PowerStubAlphaCommands
# Now alpha.* prefixed commands appear in completion
pstb DevOps <TAB> # Shows both production and alpha commands
# Run an alpha command (no need to type the prefix)
pstb DevOps my-feature # Executes alpha.my-feature.ps1
# Disable when done developing
Disable-PowerStubAlphaCommandsPowerStub works with .exe files too:
# Place terraform.exe in your stub folder
# C:\Tools\DevOps\Commands\terraform.exe
# Use it through PowerStub
pstb DevOps terraform init
pstb DevOps terraform plan -out=tfplanPowerStub/ # Repository root
├── PowerStub/ # Module folder (publishable to PSGallery)
│ ├── Public/functions/ # Exported user-facing functions (17)
│ ├── Private/functions/ # Internal helper functions (11)
│ ├── Templates/ # Command templates
│ ├── PowerStub.psm1 # Module loader
│ ├── PowerStub.psd1 # Module manifest
│ └── PowerStub.json # Runtime configuration
├── tests/ # Pester test files
│ ├── PowerStub.tests.ps1 # Main test suite (97 tests)
│ └── sample_stub_root/ # Sample stub for integration tests
├── dev-reload.ps1 # Reload module for local testing
├── dev-test.ps1 # Run Pester test suite
├── README.md
├── CLAUDE.md # Development guide for Claude Code
└── LICENSE.txt # Apache 2.0
This section covers local development and testing of the PowerStub module.
- PowerShell 5.1 or later
- Pester v5.x or later for running tests
# Install Pester if not already installed
Install-Module Pester -Force -SkipPublisherCheckgit clone https://github.com/DevPossible/power-stub.git
cd power-stubUse the dev-reload.ps1 script to import the module from source:
# Load/reload the module
.\dev-reload.ps1
# Load and reset configuration to defaults
.\dev-reload.ps1 -ResetThis script:
- Removes any existing PowerStub module from the session
- Imports the module from local source (
PowerStub/PowerStub.psm1) - Shows module info and current configuration
Edit files in the PowerStub/ folder:
- Public functions:
PowerStub/Public/functions/- Exported to users - Private functions:
PowerStub/Private/functions/- Internal helpers
After making changes, reload the module to test:
.\dev-reload.ps1Use the dev-test.ps1 script to run the Pester test suite:
# Run all tests with detailed output
.\dev-test.ps1
# Run specific tests by name filter
.\dev-test.ps1 -Filter "*Alpha*"
# Run with minimal output
.\dev-test.ps1 -Output Normal
# Skip module reload (if already loaded)
.\dev-test.ps1 -SkipReloadTest your changes interactively using the sample stub:
# Reload module
.\dev-reload.ps1 -Reset
# Register the sample stub from tests
New-PowerStub -Name "Sample" -Path ".\tests\sample_stub_root" -Force
# Test command discovery
Get-PowerStubCommand -Stub "Sample" -Command "deploy"
# Test command execution
pstb Sample deploy -Environment "test"
# Test alpha/beta features
Enable-PowerStubAlphaCommands
pstb Sample new-feature -Name "MyFeature"
Disable-PowerStubAlphaCommandsTests are located in tests/PowerStub.tests.ps1 and cover:
| Area | Description |
|---|---|
| Module Loading | Exports, aliases, private function isolation |
| Configuration | Get/set/reset configuration values |
| Stub Management | Register, remove, list stubs |
| Command Discovery | Direct files, subfolders, helper isolation |
| Alpha/Beta Prefixes | Enable/disable, precedence order |
| Command Execution | Parameter passing, output capture |
| Direct Aliases | Create, remove, tab completion for aliases |
| Virtual Verbs | Search and help built-in commands |
The tests/sample_stub_root/ folder contains a pre-configured stub with various command types for integration testing.
- New public function: Create in
PowerStub/Public/functions/Verb-PowerStub*.ps1 - New private function: Create in
PowerStub/Private/functions/*.ps1 - Add tests: Update
tests/PowerStub.tests.ps1 - Update documentation: Update README.md and CLAUDE.md
Functions are automatically loaded by the module - no manifest changes needed.
- Use approved PowerShell verbs (
Get-,Set-,New-, etc.) - Prefix public functions with
PowerStub - Include
[CmdletBinding()]on all functions - Use
$Script:scope for module-level variables
- PowerShell 5.1 or later
- Windows (primary support)
Apache License 2.0 - See LICENSE.txt
DevPossible LLC
Contributions are welcome! Please feel free to submit issues and pull requests.
See the Development section above for local setup, testing, and code style guidelines.