A PowerShell module for building interactive, scrollable CLI menus with nested sub-menus, multi-select lists, and a live display area in the footer.
- Scrollable menus for large item lists
- Declarative menu construction
- Built-in sub-menu navigation (back / main / exit)
- Multi-select list menus
- A configurable footer display area to surface state to the user
- Size-aware — adapts to the given dimensions
Import-Module -Name CliScrollMenu
Set-MenuOption -Heading "My Tool" -SubHeading "v1.0" -MenuFillChar "#" -MenuFillColor DarkYellow
Set-MenuOption -HeadingColor DarkCyan -MenuNameColor DarkGray -SubHeadingColor Green
$width = (Get-Host).UI.RawUI.WindowSize.Width
$height = (Get-Host).UI.RawUI.WindowSize.Height
Set-MenuOption -MaxWidth $width -MaxHeight $height
New-Menu -Name Main -DisplayName "Main Menu" | Out-Null
Add-BuiltInMenuItem -MenuName Main -Item Exit
New-MenuItem -Name "Hello" -DisplayName "Say hello" -DisableConfirm -Action {
Write-Output "Hello, world!"
} | Add-MenuItem -Menu Main
Clear-Host
Show-SubMenu -MenuName MainSets visual and layout options. Only the parameters you pass are updated — call it multiple times to set different groups.
| Parameter | Type | Description |
|---|---|---|
-Heading |
string | Title shown at the top of every menu |
-HeadingColor |
ConsoleColor | Colour of the heading |
-SubHeading |
string | Subtitle shown below the heading |
-SubHeadingColor |
ConsoleColor | Colour of the sub-heading |
-MenuFillChar |
string | Character used to draw the border (e.g. #, *) |
-MenuFillColor |
ConsoleColor | Colour of the border |
-MenuItemColor |
ConsoleColor | Colour of unselected menu items |
-MenuNameColor |
ConsoleColor | Colour of the menu display name |
-FooterTextColor |
ConsoleColor | Colour of footer display area text |
-MaxWidth |
int | Maximum menu width in columns |
-MaxHeight |
int | Maximum menu height in rows |
Set-MenuOption -Heading "Helpdesk" -SubHeading "Contoso" -MenuFillChar "#" -MenuFillColor DarkYellow
Set-MenuOption -HeadingColor DarkCyan -MenuNameColor DarkGray -SubHeadingColor Green -FooterTextColor DarkGray
Set-MenuOption -MaxWidth $width -MaxHeight $heightCreates a new menu. The first menu created becomes the main menu.
$mainMenu = New-Menu -Name "Main" -DisplayName "* * * Main Menu * * *"
$subMenu = New-Menu -Name "SubMenu" -DisplayName "* * * Sub Menu * * *"Returns the menu object, which can be piped to New-MenuItem.
Creates a menu item and optionally adds it to a menu.
| Parameter | Description |
|---|---|
-Name |
Unique identifier for the item |
-DisplayName |
Label shown to the user |
-Action |
ScriptBlock to run when selected |
-DisableConfirm |
Skip the "are you sure?" prompt |
-DisableMultiSelect |
Prevent this item from being toggled in multi-select mode |
-MenuName |
Add directly to this named menu |
-MenuObject |
Add directly to this menu object (pipeline) |
# Create and add in one line via pipeline
New-Menu -Name Main -DisplayName "Main Menu" | New-MenuItem -Name "Go" -DisplayName "Go somewhere" -DisableConfirm -Action { Write-Output "Going!" }
# Create then add separately
$item = New-MenuItem -Name "Greet" -DisplayName "Say hello" -DisableConfirm -Action { Write-Output "Hello!" }
$item | Add-MenuItem -Menu MainAdds an existing menu item to a named menu.
$item | Add-MenuItem -Menu MainAdds a pre-built navigation or utility item to a menu.
| Item key | Display name | Behaviour |
|---|---|---|
Exit |
Exit | Exits all menus |
GoToParent |
Go Back | Returns to the parent menu |
GoToMainMenu |
Go to Main Menu | Jumps to the top-level menu |
Timestamp |
Show current date/time | Prints the current timestamp |
PSVersion |
Show PowerShell version | Prints the PS version |
Add-BuiltInMenuItem -MenuName Main -Item Exit
Add-BuiltInMenuItem -MenuName SubMenu -Item GoToParent
Add-BuiltInMenuItem -MenuName SubMenu -Item GoToMainMenu
Add-BuiltInMenuItem -MenuName SubMenu -Item ExitUse Get-BuiltInMenuItems to list all available keys.
Displays a named menu and keeps it running until the user navigates away. This is the normal way to show any menu — main or sub.
Navigation is fully automatic: GoToParent returns to the caller, GoToMainMenu unwinds to the top, and Exit exits the process.
# Entry point — show the main menu
Show-SubMenu -MenuName Main
# From inside a menu item's Action block — open a sub-menu and wait
$goToSub = @{
Name = "GoToSub"
DisplayName = "Open Sub Menu"
Action = { Show-SubMenu -MenuName SubMenu }
}Show-SubMenu passes the last action result back to the menu so it is visible on screen between selections.
Lower-level function that renders a single menu frame and returns one selection. Use Show-SubMenu for most cases. Use Show-Menu directly when you need to control the loop yourself or invoke a specific item programmatically. When -Multi is present all selected items will be invoked and the results returned as an array.
| Parameter | Description |
|---|---|
-MenuName |
The menu to display |
-InvokeItem |
Index of item to invoke directly (no UI) |
-Force |
Skip confirmation prompts |
-Multi |
Enable multi-select mode (Space to toggle, Enter to confirm) |
-LastResult |
Result from the previous action, shown on screen |
Displays a temporary, one-shot selection menu built from an array of objects. Cleans itself up after the user makes a selection.
Each entry in -MenuItems is a [pscustomobject] with:
| Property | Description |
|---|---|
DisplayName |
Label shown to the user |
Value |
The object returned when this item is selected |
DisableMultiSelect |
Prevent toggling in -Multi mode |
$items = @(
[pscustomobject]@{ DisplayName = "Option 1"; Value = 1; },
[pscustomobject]@{ DisplayName = "Option 2"; Value = 2; },
[pscustomobject]@{ DisplayName = "Option 3"; Value = 3; },
[pscustomobject]@{ DisplayName = "Cancel"; Value = $null; DisableMultiSelect = $true }
)
# Single selection
$choice = Show-ListMenu -MenuItems $items -MenuName "Pick one"
# Multi-select — Space to toggle, Enter to confirm
$choices = Show-ListMenu -MenuItems $items -MenuName "Pick many" -MultiReturns the Value of the selected item (or an array of values when using -Multi).
| Key | Action |
|---|---|
| Up arrow | Move selection up |
| Down arrow | Move selection down |
| Left arrow | Page up (½ screen) |
| Right arrow | Page down (½ screen) |
| Enter | Confirm selection |
| Space | Toggle item (multi-select mode only) |
The $global:Display hashtable is rendered in the footer of every menu frame. Add or update keys to surface live state to the user — selected files, current settings, or any status you want visible at all times.
$global:Display = @{
Selected = "No item selected"
}
# Update from inside an action
$global:Display.Selected = $selectedFile.FullNameLong display strings are wrapped automatically. If the content exceeds half the available height it is truncated to prevent menu items from being pushed off screen.
See Scripts/Example.ps1 for a complete working demo that includes:
- A three-level menu hierarchy (Main → Sub → SubSub)
- A file browser built with
Show-ListMenu - Multi-select demo
$global:Displayfooter showing the currently selected item- All five built-in menu items
Remove-Module -Name CliScrollMenu -ErrorAction SilentlyContinue
Import-Module -Name .\CliScrollMenu.psd1 -Force
$global:Display = @{ Selected = "No item selected" }
$width = (Get-Host).UI.RawUI.WindowSize.Width
$height = (Get-Host).UI.RawUI.WindowSize.Height
Set-MenuOption -Heading "kinda bad file browser" -SubHeading "K.B.F.B" -MenuFillChar "#" -MenuFillColor DarkYellow
Set-MenuOption -HeadingColor DarkCyan -MenuNameColor DarkGray -SubHeadingColor Green -FooterTextColor DarkGray
Set-MenuOption -MaxWidth $width -MaxHeight $height
New-Menu -Name Main -DisplayName "* * * M a i n M e n u * * *" | Out-Null
New-Menu -Name SubMenu -DisplayName "* * * S u b M e n u * * *" | Out-Null
# ... add items ...
$goToSubItem = @{
Name = "GoToSub"
DisplayName = "Go to Sub Menu (demo of submenu navigation)"
Action = { Show-SubMenu -MenuName SubMenu}
}
New-MenuItem @goToSubItem -DisableConfirm | AddMenuItem -Menu Main
Add-BuiltInMenuItem -MenuName Main -Item Exit
Add-BuiltInMenuItem -MenuName SubMenu -Item GoToParent
Add-BuiltInMenuItem -MenuName SubMenu -Item GoToMainMenu
Add-BuiltInMenuItem -MenuName SubMenu -Item Exit
Clear-Host
Show-SubMenu -MenuName MainBig thank you to the original creators, go check it out.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
