A Diagram is nodes, links, groups and use cases, written in C#, with the fluent builder or with PowerShell commands. The core package draws it as a tree and needs nothing else. Add ConsoleMonster.Graphics and register it, and the same diagram is drawn with the ChartForgeX layout: boxes with status, routed connections with arrows, dashed groups and a legend, the same picture ChartForgeX renders as SVG, PNG or an HTML player.
dotnet add package ConsoleMonster.Graphics
DiagramRendererProvider.Register() turns on the Graphics drawing once per process; Diagram.Load(path) then reads a ChartForgeX architecture file, as the demo below does.
Architecture diagrams that play in the terminal
An AD replication diagram from a ChartForgeX architecture file: two sites, four domain controllers and a use case whose steps light up on the diagram, with the payload of each step under it.
Active Directory replication ╭╌ Site: HQ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ ╭╌ Site: Warsaw ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ ╎ ╎ ╎ ╎ ┌────────────┐ ╎ ┌──────────────┐ ┌────────────┐ ╎ ╎ ┏━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━┓ ╎ │ Admin │ ╎ │ DC01 │ RPC │ DC02 │ ╎ ╎ ┃ DC03 ▴┃ RPC ┃ DC04 ┃ ╎ │ │─ LDAP ──▶│ PDC emulator │──────▶│ Bridgehead │─── Site link ──▶┃ Bridgehead ┃━━━━━━▶┃ Branch DC ┃ ╎ └────────────┘ ╎ │ │ │ │ ╎ ╎ ┃ ┃ ┃ ┃ ╎ ╎ └──────────────┘ └────────────┘ ╎ ╎ ┗━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━┛ ╎ ╎ ╎ ╎ ╎ ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ Replicate a change (1/2) · step 8 of 8 ↑ 1 earlier 2. DC01 → Admin response Success 3. DC01 → DC02 message Change notification 4. DC02 → DC01 request DRSGetNCChanges 5. DC01 → DC02 response 1 object 6. DC03 → DC02 request Scheduled pull 7. DC02 → DC03 response Changes ▶ 8. DC03 → DC04 message Change notification p play/pause n/→ next b/← back r/Home restart e/End last x clear step s/Tab next use case Shift+Tab previous use case ↑/↓ focus d details ▴ Warn Needs attention ▴ DC03 Bridgehead esc quit
dotnet new console -n Topology
cd Topology
dotnet add package ConsoleMonster.Graphics# Open the diagram: Space plays the use case, Left and Right step, Tab switches use case, Esc quits.
Show-ConsoleDiagram -Path ./ad-replication.cfx
# One step as text, for a log or a ticket.
Show-ConsoleDiagram -Path ./ad-replication.cfx -Scenario sitelink -Step 4 -Width 120 -AsStringFull program
Import-Module ConsoleMonster
# Open the diagram: Space plays the use case, Left and Right step, Tab switches use case, Esc quits.
Show-ConsoleDiagram -Path ./ad-replication.cfx
# One step as text, for a log or a ticket.
Show-ConsoleDiagram -Path ./ad-replication.cfx -Scenario sitelink -Step 4 -Width 120 -AsStringRun: ./Run.ps1
PowerShell launches the same .NET project after Program.cs is saved from either C# tab. The generic host and ILogger provider have no separate cmdlet implementation.
dotnet new console -n Topology
cd Topology
dotnet add package ConsoleMonster.Graphics// ConsoleMonster.Graphics draws diagrams with the ChartForgeX layout; without it a diagram prints as a tree.
DiagramRendererProvider.Register();
// The same architecture file ChartForgeX draws as SVG, PNG or an HTML player.
bool capture = args.Contains("--capture");
Diagram diagram = Diagram.Load(Path.Combine(
capture ? Environment.CurrentDirectory : AppContext.BaseDirectory, "ad-replication.cfx"));
// Play the first use case; Left and Right step, Tab switches use case, Up and Down focus a node, Esc quits.
diagram.Play();
if (!capture) { diagram.Run(); return; }
// Recording uses the same app and playback with explicit logical checkpoints, independent of repaint scheduling.
InteractiveOptions interactive = InteractiveOptions.Default.Clone();
interactive.Mode = InteractionMode.Rich;
interactive.NonInteractive = false;
interactive.Input = new ScriptedInput(string.Empty) { EndsQuietly = true };
var recording = interactive.Target as RecordingTarget
?? throw new InvalidOperationException("A recording target is required.");
int checkpoints = 0;
diagram.Run(new ConsoleAppOptions {
Interactive = interactive,
Mouse = false,
ProcessEvents = state => {
if (checkpoints == 8) { state.RequestExit(); return; }
LiveSession session = LiveSession.Current
?? throw new InvalidOperationException("The app has no live session.");
session.Delay(TimeSpan.FromMilliseconds(900));
recording.Screens.Hold(TimeSpan.FromMilliseconds(900));
checkpoints++;
}
});
if (checkpoints != 8 || diagram.StepIndex != 7)
throw new InvalidOperationException("The recording did not reach the eighth playback step.");Full program
using ConsoleMonster.Graphics;
using ConsoleMonster.Input;
using ConsoleMonster.Interactive;
using ConsoleMonster.Live;
using ConsoleMonster.Output;
using ConsoleMonster.Widgets;
// ConsoleMonster.Graphics draws diagrams with the ChartForgeX layout; without it a diagram prints as a tree.
DiagramRendererProvider.Register();
// The same architecture file ChartForgeX draws as SVG, PNG or an HTML player.
bool capture = args.Contains("--capture");
Diagram diagram = Diagram.Load(Path.Combine(
capture ? Environment.CurrentDirectory : AppContext.BaseDirectory, "ad-replication.cfx"));
// Play the first use case; Left and Right step, Tab switches use case, Up and Down focus a node, Esc quits.
diagram.Play();
if (!capture) { diagram.Run(); return; }
// Recording uses the same app and playback with explicit logical checkpoints, independent of repaint scheduling.
InteractiveOptions interactive = InteractiveOptions.Default.Clone();
interactive.Mode = InteractionMode.Rich;
interactive.NonInteractive = false;
interactive.Input = new ScriptedInput(string.Empty) { EndsQuietly = true };
var recording = interactive.Target as RecordingTarget
?? throw new InvalidOperationException("A recording target is required.");
int checkpoints = 0;
diagram.Run(new ConsoleAppOptions {
Interactive = interactive,
Mouse = false,
ProcessEvents = state => {
if (checkpoints == 8) { state.RequestExit(); return; }
LiveSession session = LiveSession.Current
?? throw new InvalidOperationException("The app has no live session.");
session.Delay(TimeSpan.FromMilliseconds(900));
recording.Screens.Hold(TimeSpan.FromMilliseconds(900));
checkpoints++;
}
});
if (checkpoints != 8 || diagram.StepIndex != 7)
throw new InvalidOperationException("The recording did not reach the eighth playback step.");Run: dotnet run · Save ad-replication.cfx beside Program.cs. Esc quits.
dotnet new console -n Topology
cd Topology
dotnet add package ConsoleMonster.Graphics// ConsoleMonster.Graphics draws diagrams with the ChartForgeX layout; without it a diagram prints as a tree.
DiagramRendererProvider.Register();
// The same architecture file ChartForgeX draws as SVG, PNG or an HTML player.
bool capture = args.Contains("--capture");
Diagram diagram = Diagram.Load(Path.Combine(
capture ? Environment.CurrentDirectory : AppContext.BaseDirectory, "ad-replication.cfx"));
// Play the first use case; Left and Right step, Tab switches use case, Up and Down focus a node, Esc quits.
diagram.Play();
if (!capture)
{
diagram.Run();
return;
}
// Recording uses the same app and playback with explicit logical checkpoints, independent of repaint scheduling.
InteractiveOptions interactive = InteractiveOptions.Default.Clone()
.Mode(InteractionMode.Rich)
.NonInteractive(false)
.Input(new ScriptedInput(string.Empty) { EndsQuietly = true });
var recording = interactive.Target as RecordingTarget
?? throw new InvalidOperationException("A recording target is required.");
int checkpoints = 0;
diagram.Run(new ConsoleAppOptions()
.Interactive(interactive)
.Mouse(false)
.Configure(configured => configured.ProcessEvents = state =>
{
if (checkpoints == 8)
{
state.RequestExit();
return;
}
LiveSession session = LiveSession.Current
?? throw new InvalidOperationException("The app has no live session.");
session.Delay(TimeSpan.FromMilliseconds(900));
recording.Screens.Hold(TimeSpan.FromMilliseconds(900));
checkpoints++;
}));
if (checkpoints != 8 || diagram.StepIndex != 7)
throw new InvalidOperationException("The recording did not reach the eighth playback step.");
Full program
using ConsoleMonster.Graphics;
using ConsoleMonster.Input;
using ConsoleMonster.Interactive;
using ConsoleMonster.Live;
using ConsoleMonster.Output;
using ConsoleMonster.Widgets;
// ConsoleMonster.Graphics draws diagrams with the ChartForgeX layout; without it a diagram prints as a tree.
DiagramRendererProvider.Register();
// The same architecture file ChartForgeX draws as SVG, PNG or an HTML player.
bool capture = args.Contains("--capture");
Diagram diagram = Diagram.Load(Path.Combine(
capture ? Environment.CurrentDirectory : AppContext.BaseDirectory, "ad-replication.cfx"));
// Play the first use case; Left and Right step, Tab switches use case, Up and Down focus a node, Esc quits.
diagram.Play();
if (!capture)
{
diagram.Run();
return;
}
// Recording uses the same app and playback with explicit logical checkpoints, independent of repaint scheduling.
InteractiveOptions interactive = InteractiveOptions.Default.Clone()
.Mode(InteractionMode.Rich)
.NonInteractive(false)
.Input(new ScriptedInput(string.Empty) { EndsQuietly = true });
var recording = interactive.Target as RecordingTarget
?? throw new InvalidOperationException("A recording target is required.");
int checkpoints = 0;
diagram.Run(new ConsoleAppOptions()
.Interactive(interactive)
.Mouse(false)
.Configure(configured => configured.ProcessEvents = state =>
{
if (checkpoints == 8)
{
state.RequestExit();
return;
}
LiveSession session = LiveSession.Current
?? throw new InvalidOperationException("The app has no live session.");
session.Delay(TimeSpan.FromMilliseconds(900));
recording.Screens.Hold(TimeSpan.FromMilliseconds(900));
checkpoints++;
}));
if (checkpoints != 8 || diagram.StepIndex != 7)
throw new InvalidOperationException("The recording did not reach the eighth playback step.");
Run: dotnet run · Save ad-replication.cfx beside Program.cs. Esc quits.
See also: Architecture diagrams
Write one
Nodes, links, groups and use cases are the same model in C#, the fluent builder and PowerShell. Without Graphics registered, the core draws this as a tree:
using ConsoleMonster;
using ConsoleMonster.Widgets;
var diagram = Ui.Diagram("Home network")
.Node("Laptop", n => n.Kind(DiagramNodeKind.Workstation))
.Node("Router", n => n.Kind(DiagramNodeKind.Gateway)
.Subtitle("192.168.1.1").Value("1 ms"))
.Link("Laptop", "Router", l => l.Label("Wi-Fi"));
Terminal.Write(diagram);
The PowerShell module bundles Graphics and registers it for the diagram commands:
Import-Module ConsoleMonster
New-ConsoleDiagram -Title 'Home network' {
New-ConsoleDiagramNode 'Laptop' -Kind Workstation
New-ConsoleDiagramNode 'Router' -Kind Gateway -Subtitle '192.168.1.1' -Value '1 ms'
New-ConsoleDiagramLink 'Laptop' 'Router' -Label 'Wi-Fi'
} | Show-ConsoleDiagram -StaticSnapshot
Use cases
A use case is an ordered list of steps over the diagram: a request, its answer, a message nobody waits for, or a call that fails. The panel under the diagram lists the steps, the active one lights up on the diagram (answers point back, failures are red) and its payload is shown. In an interactive console:
| Key | Does |
|---|---|
| Space or P | Play or pause |
| Right or N, Left or B | Next and previous step |
| Home or R, End or E | First and last step |
| X | Clear the active step |
| Tab or S | Next use case |
| Up and Down | Move the focus between nodes |
| D | Details of the focused node |
Playback follows the session clock, so a resize or a slow frame never skips steps.
From PowerShell
Show-ConsoleDiagram reads a Markdown file with ChartForgeX visual fences, or a plain architecture file. In an interactive console it opens the same view; in CI, redirected output or with -StaticSnapshot it prints one step and returns.
Show-ConsoleDiagram -Path ./ad-replication.cfx
Show-ConsoleDiagram -Path ./ad-replication.cfx -Scenario sitelink -Step 4 -StaticSnapshot
Show-ConsoleDiagram -Path ./ad-replication.cfx -Scenario sitelink -Step 4 -Width 120 -AsString
Markup errors stop the command with the file, line and diagnostic code, for example ad-replication.cfx:20:1 CFXA002 ....
Live values
A diagram can be a live dashboard. Values and statuses change, the layout stays put, and nodes keep room for a short value; longer text shows in the focused node's details.
using var session = new LiveSession(diagram, new LiveSessionOptions());
session.Start();
DiagramHandle handle = diagram.Handle(session);
handle.Value("dc03", "lag 42 min", StatusKind.Fail);
In PowerShell, give the diagram a -WidgetId and update it with Update-Console -WidgetId <id> -Key dc03 -Value 'lag 42 min' -Status Fail.
Glyphs and width
The Full glyph set uses rounded and dashed boxes and heavy lines for the active step; Basic maps them to WGL4 box drawing; ASCII stays plain ASCII. A small diagram keeps its natural size in a wide terminal. In a terminal narrower than the full text, subtitles go first, then labels are shortened, then connection labels are dropped until it fits.