Skip to content
ConsoleMonster

Fleet filter

Filter five hosts as you type while retaining the fleet-wide health summary above the matching rows.

Demos Terminal apps

Use it when an operator needs to search a small inventory without losing the overall health summary.

  • Live
  • 88×24
  • PowerShell 7.4+
  • .NET 8.0+
Fleet filter 88×2424-bitFull

How it's built

The whole program in one file, with its sample data at the top. It drew the recording above; both languages draw the same cells.

PowerShellfleet-filter.ps1View on GitHub
# Explore a small fleet dashboard with an interactive inventory filter.
[CmdletBinding()]
param(
    [switch] $StaticSnapshot,
    [ValidateRange(0, 2)] [int] $Step = 0,
    [hashtable] $AppOptions = @{}
)

Import-Module ConsoleMonster
# All data is synthetic and inline; no services are contacted or changed.
$AppOptions.StaticSnapshot = $StaticSnapshot -or ([Console]::IsInputRedirected -and -not $AppOptions.InputSource)

# Data: fictional inputs kept in memory.
$hosts = @(
    [pscustomobject] @{ Host = 'web-01'; Role = 'Web'; Site = 'North'; Status = 'Pass' }
    [pscustomobject] @{ Host = 'web-02'; Role = 'Web'; Site = 'West'; Status = 'Warn' }
    [pscustomobject] @{ Host = 'sql-01'; Role = 'Database'; Site = 'North'; Status = 'Pass' }
    [pscustomobject] @{ Host = 'sql-02'; Role = 'Database'; Site = 'West'; Status = 'Fail' }
    [pscustomobject] @{ Host = 'job-01'; Role = 'Worker'; Site = 'West'; Status = 'Running' }
)
$query = @('', 'sql', 'missing')[$Step]
# Layout: construct the widgets shown on screen.
Show-ConsoleApp {
    New-ConsoleRows -Gap 1 {
        '[bold]Fleet health[/] [muted]· production inventory[/]'
        New-ConsolePanel -Title 'Fleet summary' {
            '[pass]2 healthy[/]  [warn]1 warning[/]  [fail]1 offline[/]  [accent]1 running[/]'
        }

        New-ConsoleTextInput -Name Query -Label Filter -Value $query -Placeholder 'Host, role, site or status'
        # Live updates: rebuild this section when an input or button changes state.
        New-ConsoleBinding {
            param($State)
            $queryText = [string] $State.Query
            $rows = @($hosts | Where-Object {
                ($_.Host, $_.Role, $_.Site, $_.Status -join ' ').IndexOf($queryText, [StringComparison]::OrdinalIgnoreCase) -ge 0
            })
            "$($rows.Count) of $($hosts.Count) hosts"
            New-ConsoleTable -InputObject $rows -Property Host, Role, Site, Status
            if ($rows.Count -eq 0) { '[muted]No matching hosts. Backspace to broaden the filter.[/]' }
        }
    }
} @AppOptions
C#Program.csView on GitHub
// Explore a small fleet dashboard with an interactive inventory filter.
// All data is synthetic and inline; no services are contacted or changed.
using ConsoleMonster.Interactive;
using ConsoleMonster.Layout;
using ConsoleMonster.Presenters;
using ConsoleMonster.Widgets;

// Data: fictional inputs kept in memory.
var hosts = new[] {
    new { Host = "web-01", Role = "Web", Site = "North", Status = "Pass" },
    new { Host = "web-02", Role = "Web", Site = "West", Status = "Warn" },
    new { Host = "sql-01", Role = "Database", Site = "North", Status = "Pass" },
    new { Host = "sql-02", Role = "Database", Site = "West", Status = "Fail" },
    new { Host = "job-01", Role = "Worker", Site = "West", Status = "Running" }
};
// Run options: redirected input selects a deterministic snapshot.
bool snapshot = args.Contains("--snapshot") || (!args.Contains("--interactive") && Console.IsInputRedirected);
int stepAt = Array.IndexOf(args, "--step");
int step = stepAt < 0 ? 0 : int.Parse(args[stepAt + 1], System.Globalization.CultureInfo.InvariantCulture);
if (step < 0 || step > 2) throw new ArgumentOutOfRangeException(nameof(step));

// Layout: construct the widgets shown on screen.
IWidget Results(string query) {
    var rows = hosts.Where(host => string.Join(" ", host.Host, host.Role, host.Site, host.Status)
        .IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0).ToArray();
    Table table = new Table().AddColumn("Host").AddColumn("Role").AddColumn("Site").AddColumn("Status", column => column.Presenter = CellPresenters.StatusWord);
    foreach (var host in rows) table.AddRow(host.Host, host.Role, host.Site, TableCell.FromValue(host.Status));
    Rows result = new Rows(new TextBlock(rows.Length.ToString(System.Globalization.CultureInfo.InvariantCulture) +
        " of " + hosts.Length.ToString(System.Globalization.CultureInfo.InvariantCulture) + " hosts"), table);
    if (rows.Length == 0) result.Add(new TextBlock("[muted]No matching hosts. Backspace to broaden the filter.[/]"));
    return result;
}
Rows layout = new Rows(
    new TextBlock("[bold]Fleet health[/] [muted]· production inventory[/]"),
    new Panel(new TextBlock("[pass]2 healthy[/]  [warn]1 warning[/]  [fail]1 offline[/]  [accent]1 running[/]"), "Fleet summary"),

    new TextInput("Query", new[] { "", "sql", "missing" }[step]) { Label = "Filter", Placeholder = "Host, role, site or status" },
    new AppBinding(state => Results(state.Get<string>("Query", string.Empty)))) { Gap = 1 };
// Live updates: ConsoleApp handles input and reevaluates AppBinding as state changes.
// Escape exits; snapshot mode prints the selected state without reading keys.
ConsoleApp.Run(layout, options: new ConsoleAppOptions { StaticSnapshot = snapshot });

Run it yourself

Three steps in PowerShell, four in C#. Every command copies with one click.

  1. Install the module

    Once. Windows PowerShell 5.1 or PowerShell 7 on Windows, macOS or Linux.

    Install-Module ConsoleMonster -Scope CurrentUser
  2. Save the program

    Download it, or copy it from above into fleet-filter.ps1.

  3. Run it

    From the folder you saved it in.

    ./fleet-filter.ps1
  1. Create a project

    A plain console app; .NET 8 or later.

    dotnet new console -n Fleetfilter; cd Fleetfilter
  2. Add ConsoleMonster

    The only package the program needs.

    dotnet add package ConsoleMonster
  3. Replace Program.cs

    Download it, or copy the program from above.

  4. Run it

    dotnet run

Or skip the copying. Every demo ships with the module and the project template.

Show-ConsoleDemo fleet-filter
Get-ConsoleDemo fleet-filter -Path ./fleet-filter.ps1
dotnet new install ConsoleMonster.Templates
dotnet new consolemonster --demo fleet-filter -n Fleetfilter

Make it yours

Start with these, then read the rest of the file.

  1. Replace the five sample hosts with your inventory.

  2. Choose the properties your users search.

  3. Change the summary counts and status rules.

More terminal apps

All demos