Spectre.Console
A library for creating beautiful console applications for .NET. Provides rich tables, charts, and prompts.
GitHub Overview
spectreconsole/spectre.console
A .NET library that makes it easier to create beautiful console applications.
Topics
Star History
Framework
Spectre.Console
Overview
Spectre.Console is a library for creating beautiful console applications for .NET. It provides rich tables, charts, and prompts, and is rapidly growing in popularity due to beautiful CLI output and interactive features. Widely adopted in modern .NET applications, it dramatically improves traditional monotonous console output.
Details
Spectre.Console is a modern library that brings rich visual experiences to console applications. It provides diverse UI elements such as text styling, tables, progress bars, charts, and interactive prompts. Available for .NET 5+, .NET Framework, and .NET Standard with cross-platform support.
Key Features
- Rich Text Styling: Various styles including colors, bold, italic, underline
- Table Display: Beautiful and organized table display functionality
- Progress Bars: Single and multiple progress bar displays
- Interactive Prompts: User interaction with selection, input, confirmation
- Charts: Bar charts, breakdown charts, etc.
- Layout: Layout features like panels, grids, columns
- Live Display: Real-time display updates
- Markup Notation: HTML-like markup for styling
- Color Support: Rich color support and automatic color adjustment
Pros and Cons
Pros
- Beautiful Output: Professional and visually appealing console output
- Rich UI Elements: Various elements like tables, charts, prompts
- Easy-to-use API: Intuitive and learnable API design
- Cross-platform: Works on Windows, Linux, macOS
- Performance: Fast and efficient rendering engine
- Extensibility: Custom renderers and styles can be created
- Active Development: Continuous feature additions and bug fixes
Cons
- Learning Curve: Takes time to master due to rich features
- Dependencies: Adds dependency on external libraries
- Terminal Dependency: Some parts depend on terminal capabilities
- Overhead: May be excessive for simple applications
Key Links
Usage Examples
Basic Text Styling
using Spectre.Console;
class Program
{
static void Main(string[] args)
{
// Basic text styling
AnsiConsole.WriteLine("Normal text");
AnsiConsole.MarkupLine("[red]Red text[/]");
AnsiConsole.MarkupLine("[bold blue]Bold blue text[/]");
AnsiConsole.MarkupLine("[italic green]Italic green text[/]");
AnsiConsole.MarkupLine("[underline yellow]Underlined yellow text[/]");
// With background color
AnsiConsole.MarkupLine("[white on red]White text on red background[/]");
// Combined styles
AnsiConsole.MarkupLine("[bold italic underline red]All styles applied[/]");
// Rule for separator
AnsiConsole.Write(new Rule("[green]Section Separator[/]"));
// Panel for box display
AnsiConsole.Write(
new Panel("[yellow]This is text inside a panel[/]")
.Header("Information Panel")
.Border(BoxBorder.Rounded)
.BorderColor(Color.Blue));
}
}
Table Display
using Spectre.Console;
class Program
{
static void Main(string[] args)
{
// Basic table
var table = new Table();
// Add columns
table.AddColumn("Name");
table.AddColumn(new TableColumn("Age").Centered());
table.AddColumn(new TableColumn("Department").RightAligned());
// Add rows
table.AddRow("John Doe", "30", "Development");
table.AddRow("Jane Smith", "25", "Sales");
table.AddRow("Bob Johnson", "35", "Planning");
// Set styles
table.Border(TableBorder.Rounded);
table.BorderColor(Color.Blue);
table.Title("Employee List");
table.Caption("2024 Data");
AnsiConsole.Write(table);
AnsiConsole.WriteLine();
// More advanced table
var advancedTable = new Table()
.Border(TableBorder.Square)
.BorderColor(Color.Red)
.Title("[yellow]Project Progress[/]");
advancedTable.AddColumn("[green]Project Name[/]");
advancedTable.AddColumn(new TableColumn("[blue]Progress[/]").Centered());
advancedTable.AddColumn(new TableColumn("[red]Status[/]").RightAligned());
advancedTable.AddColumn("[purple]Assignee[/]");
// Apply styles conditionally
advancedTable.AddRow(
"Website Renewal",
"[green]85%[/]",
"[green]In Progress[/]",
"John");
advancedTable.AddRow(
"Mobile App",
"[yellow]60%[/]",
"[yellow]Delayed[/]",
"Jane");
advancedTable.AddRow(
"API Development",
"[red]30%[/]",
"[red]At Risk[/]",
"Bob");
AnsiConsole.Write(advancedTable);
}
}
Progress Bars
using Spectre.Console;
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// Single progress bar
await AnsiConsole.Progress()
.StartAsync(async context =>
{
var task = context.AddTask("[green]Downloading file...[/]");
while (!task.IsFinished)
{
await Task.Delay(100);
task.Increment(2);
}
});
AnsiConsole.MarkupLine("[green]Download complete![/]");
AnsiConsole.WriteLine();
// Multiple progress bars
await AnsiConsole.Progress()
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(), // Task description
new ProgressBarColumn(), // Progress bar
new PercentageColumn(), // Percentage
new RemainingTimeColumn(), // Remaining time
new SpinnerColumn(), // Spinner
})
.StartAsync(async context =>
{
var downloadTask = context.AddTask("[blue]File Download[/]", maxValue: 100);
var processTask = context.AddTask("[yellow]Data Processing[/]", maxValue: 50);
var uploadTask = context.AddTask("[green]Upload[/]", maxValue: 30);
// Simulate parallel processing
var tasks = new[]
{
SimulateWork(downloadTask, 50),
SimulateWork(processTask, 80),
SimulateWork(uploadTask, 120)
};
await Task.WhenAll(tasks);
});
AnsiConsole.MarkupLine("[green]All processing completed![/]");
}
static async Task SimulateWork(ProgressTask task, int delay)
{
while (!task.IsFinished)
{
await Task.Delay(delay);
task.Increment(1);
}
}
}
Interactive Prompts
using Spectre.Console;
using System;
using System.ComponentModel.DataAnnotations;
class Program
{
static void Main(string[] args)
{
AnsiConsole.MarkupLine("[bold blue]User Information Input[/]");
AnsiConsole.WriteLine();
// Text input
var name = AnsiConsole.Ask<string>("Please enter your name:");
// Password input (masked)
var password = AnsiConsole.Prompt(
new TextPrompt<string>("Please enter password:")
.PromptStyle("red")
.Secret());
// Numeric input (with validation)
var age = AnsiConsole.Prompt(
new TextPrompt<int>("Please enter your age:")
.PromptStyle("green")
.ValidationErrorMessage("[red]Please enter a valid number[/]")
.Validate(age =>
{
return age switch
{
<= 0 => ValidationResult.Error("[red]Age must be a positive number[/]"),
>= 150 => ValidationResult.Error("[red]Age is unrealistic[/]"),
_ => ValidationResult.Success(),
};
}));
// Selection prompt
var department = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("Please select your department:")
.PageSize(10)
.MoreChoicesText("[grey](Use arrow keys to navigate, Enter to select)[/]")
.AddChoices(new[] {
"Development", "Sales", "Planning", "HR", "Accounting", "Administration"
}));
// Multi-selection prompt
var skills = AnsiConsole.Prompt(
new MultiSelectionPrompt<string>()
.Title("Please select your skills (multiple selection):")
.NotRequired() // Not required
.PageSize(10)
.MoreChoicesText("[grey](Space to select/deselect, Enter to confirm)[/]")
.InstructionsText(
"[grey](Space to select, arrow keys to navigate, Enter to confirm)[/]")
.AddChoices(new[] {
"C#", "JavaScript", "Python", "Java", "Go",
"React", "Vue.js", "Angular", "Docker", "Kubernetes"
}));
// Confirmation prompt
var confirm = AnsiConsole.Confirm("Do you want to save the input?");
// Display results
AnsiConsole.WriteLine();
var panel = new Panel(
$"[bold]Name:[/] {name}\n" +
$"[bold]Age:[/] {age}\n" +
$"[bold]Department:[/] {department}\n" +
$"[bold]Skills:[/] {string.Join(", ", skills)}\n" +
$"[bold]Save:[/] {(confirm ? "[green]Yes[/]" : "[red]No[/]")}")
.Header("Input Results")
.Border(BoxBorder.Rounded)
.BorderColor(Color.Green);
AnsiConsole.Write(panel);
if (confirm)
{
// Simulate save process
AnsiConsole.Status()
.Start("Saving data...", ctx =>
{
ctx.Spinner(Spinner.Known.Star);
ctx.SpinnerStyle(Style.Parse("green"));
System.Threading.Thread.Sleep(2000);
});
AnsiConsole.MarkupLine("[green]Data saved successfully![/]");
}
}
}
Charts and Live Display
using Spectre.Console;
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
// Bar chart
AnsiConsole.Write(
new BarChart()
.Width(60)
.Label("[green bold underline]Sales Performance[/]")
.CenterLabel()
.AddItem("Jan", 12.5, Color.Yellow)
.AddItem("Feb", 15.8, Color.Green)
.AddItem("Mar", 10.2, Color.Red)
.AddItem("Apr", 18.9, Color.Blue)
.AddItem("May", 22.1, Color.Purple));
AnsiConsole.WriteLine();
// Breakdown chart
AnsiConsole.Write(
new BreakdownChart()
.Width(100)
.AddItem("Development", 45, Color.Red)
.AddItem("Testing", 25, Color.Green)
.AddItem("Design", 20, Color.Blue)
.AddItem("Other", 10, Color.Yellow));
AnsiConsole.WriteLine();
// Live display example
await AnsiConsole.Live(CreateStatusDisplay())
.StartAsync(async context =>
{
for (int i = 0; i <= 100; i += 5)
{
// Update display
context.UpdateTarget(CreateStatusDisplay(i));
await Task.Delay(200);
}
});
AnsiConsole.MarkupLine("[green]Processing complete![/]");
}
static Panel CreateStatusDisplay(int progress = 0)
{
var grid = new Grid()
.AddColumn()
.AddColumn();
grid.AddRow(
new Panel("[bold]System Status[/]")
.BorderColor(Color.Blue),
new Panel($"[bold]Progress: {progress}%[/]")
.BorderColor(Color.Green));
// Add progress bar
if (progress > 0)
{
var progressBar = new ProgressBar()
.Value(progress)
.MaxValue(100);
grid.AddRow(
new Panel(progressBar)
.Header("Processing")
.BorderColor(Color.Yellow),
new Panel($"[bold]Remaining: {(100-progress)/5}s[/]")
.BorderColor(Color.Purple));
}
return new Panel(grid)
.Header("[bold yellow]Dashboard[/]")
.Border(BoxBorder.Double)
.BorderColor(Color.Cyan1);
}
}
Project File Example
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Spectre.Console" Version="0.47.0" />
<PackageReference Include="System.Text.Json" Version="6.0.0" />
</ItemGroup>
</Project>