Skip to content

Customization & Output

Repl’s output pipeline is fully composable. The same command graph produces plain text for a CI log, syntax-highlighted JSON for a terminal, and Spectre.Console tables for a rich interactive session — all without touching handler code.

Every command supports output format flags out of the box:

FlagFormat
(none)human — plain text / table
--output:format=json (or --json)JSON
--output:format=xmlXML
--output:format=yamlYAML
--output:format=markdownMarkdown table
--output:format=spectreSpectre.Console rendering
  1. --output:format flag on the command line
  2. ReplOptions.Output.DefaultFormat (configured at startup)
  3. human (built-in default)
app.Options(o =>
{
o.Output.DefaultFormat = "json"; // all commands default to JSON
});

When a command returns a ReplPage<T> or an IReplPageSource<T>, the output format determines how the page is rendered:

FormatRendering
human / spectre (interactive TTY)Table + integrated pager; continues fetching source pages as the user scrolls
human / spectre (redirected stdout)Table for the first source page; pager suppressed; nextCursor hint printed
json / xml / yaml / markdownExplicit page envelope: { "$type": "page", "items": [...], "pageInfo": { ... } }
MCP structured content{ "$type": "page", ... } in StructuredContent; text fallback via PagedResultTextMode

The pager activates only for human and spectre on an interactive TTY. Redirected output and machine formats always receive the raw first page — use --result:cursor to advance.

See Result-Flow Paging for the full source paging model, CLI options, and MCP surface.


Repl detects the terminal’s color capability at startup and chooses rendering accordingly.

Repl detects the terminal’s color capability at startup and chooses rendering accordingly. Detected capability tiers (informational):

Detected tierRendering
No ANSIPlain text, no escape sequences
Basic16 ANSI colors
Extended256 colors
TrueColor24-bit color

Detection chain (first match wins):

  1. NO_COLOR env var → disable ANSI
  2. CLICOLOR_FORCE env var → force ANSI
  3. TERM / COLORTERM heuristics
  4. Platform-specific checks (Windows Console, VS Code terminal, etc.)
  5. Redirection check (piped stdout → no ANSI)

Override programmatically using AnsiMode:

app.Options(o =>
{
o.Output.AnsiMode = AnsiMode.Always; // force ANSI on regardless of detection
// or: Auto (default — let detection decide), Never (force off)
});

In interactive mode with ANSI support, --json output is automatically syntax-highlighted (keys in one color, strings in another, numbers in a third). No configuration required.


Repl uses the terminal width for table column sizing, word wrap, and layout decisions.

Resolution order:

  1. OutputOptions.PreferredWidth (explicit override)
  2. COLUMNS environment variable
  3. Detected console window width
  4. Telnet NAWS / DTTERM resize for hosted sessions
  5. OutputOptions.FallbackWidth (default: 120)
app.Configure<OutputOptions>(o =>
{
o.PreferredWidth = 160;
o.FallbackWidth = 80;
});

Register a transformer for a new format name:

app.Options(o =>
{
o.Output.AddTransformer("csv", new CsvOutputTransformer());
o.Output.AddAlias("spreadsheet", "csv"); // both --output:format=csv and --output:format=spreadsheet work
});

IOutputTransformer receives the handler’s return value and returns a formatted string:

public class CsvOutputTransformer : IOutputTransformer
{
public string Name => "csv";
public ValueTask<string> TransformAsync(object? value, CancellationToken ct)
{
var csv = value is IEnumerable<object> rows ? ToCsv(rows) : value?.ToString() ?? "";
return ValueTask.FromResult(csv);
}
}

The startup banner (shown in interactive mode) can be suppressed:

Terminal window
myapp --no-logo

Or globally:

app.Options(o =>
{
o.Output.BannerEnabled = false;
// or: o.Output.BannerFormats = ["human"] — show only in human format (default)
});

Add Repl.Spectre and register:

app.UseSpectreConsole(); // enables rich prompts and renderables in one call

Return any IRenderable from a handler — Spectre renders it automatically:

app.Map("contacts table", (IContactStore store) =>
{
var table = new Table()
.BorderStyle(Style.Parse("grey"))
.AddColumn("[bold]Id[/]")
.AddColumn("[bold]Name[/]")
.AddColumn("[bold]Email[/]");
foreach (var c in store.All())
table.AddRow(c.Id.ToString(), c.Name, c.Email);
return table;
});

Use Spectre.Console’s full Markup and Style API anywhere an IRenderable is expected:

return new Markup("[green bold]Success![/] Contact added.");
return new Panel(new Markup(content))
.BorderStyle(Style.Parse("blue"))
.Header("[bold]Summary[/]");
TypeDescription
TableGrid with borders, alignment, and markup
PanelBox with optional header and border
TreeHierarchical tree view
BarChartHorizontal bar chart
BreakdownChartProportion chart
CalendarMonthly calendar with highlighted dates
JsonTextSyntax-highlighted JSON
FigletTextLarge ASCII art text
TextPathBreadcrumb path rendering
MarkupInline styled text
Grid / ColumnsFree-form layout
RuleHorizontal divider
Progress / StatusLive progress widgets

Spectre.Console detects terminal capabilities automatically. On terminals without ANSI support, all output degrades gracefully to plain text — no code changes needed.


Help can also be rendered in structured formats:

Terminal window
myapp contacts --help # human-readable
myapp contacts --help --json # machine-readable JSON

The JSON format returns a structured ReplDocumentationModel — useful for tooling, documentation generators, and agents.


Repl.Spectre registers Spectre’s IAnsiConsole in DI, bound to the current session’s output stream. Inject it directly when you need full Spectre control:

app.Map("demo", (IAnsiConsole console) =>
{
console.Write(new FigletText("Repl").Color(Color.Blue));
console.MarkupLine("[bold green]Ready.[/]");
});

This is session-safe in hosted mode — each session gets its own IAnsiConsole bound to its output stream.