WpfTerminal

May 15, 2026 · View on GitHub

Table of Contents

  1. Architecture
  2. API Reference
  3. Integration Guide — Level 1: Basic Setup
  4. Integration Guide — Level 2: Sessions & Commands
  5. Integration Guide — Level 3: Macros & HxScript
  6. Integration Guide — Level 4: Plugins & Theming
  7. Built-in Commands Reference
  8. Settings Reference

Architecture

Assembly structure

graph TD
    pkg["📦 WpfTerminal.nupkg"]
    t["Terminal.dll\nTerminalPanel UserControl · main entry point"]
    ct["Core.Terminal.dll\ncommand engine · macros · HxScript"]
    ab["SDK.Terminal.Abstractions.dll\nterminal plugin contracts"]
    c["Core.dll\nshared services and infrastructure"]
    ev["Core.Events.dll\ninternal event bus"]
    sdk["SDK.dll\nplugin contracts and interfaces"]

    pkg --> t & ct & ab & c & ev & sdk
    t --> ct & sdk
    ct --> ab & c & ev

Zero external NuGet dependencies. All assemblies are bundled inside the package.

Type ownership

TypeAssemblyPurpose
TerminalPanelTerminalMain UserControl — tabs, output, input bar
TerminalViewModelTerminalMVVM root — owns the session list
TerminalSessionCore.TerminalSingle shell tab — process wrapper + output buffer
CommandEngineCore.TerminalDispatch built-in and plugin commands
MacroRecorderCore.TerminalRecord/replay command sequences
HxScriptEngineCore.Terminal.hxscript interpreter
ITerminalPluginSDK.Terminal.AbstractionsContract for terminal plugin commands

MVVM model

graph TD
    TP["TerminalPanel (View)"]
    TV["TerminalViewModel (ViewModel)"]
    SC["Sessions : ObservableCollection<TerminalSession>"]
    AS["ActiveSession : TerminalSession"]
    CE["CommandEngine"]
    BI["Built-in handlers\n(39 commands)"]
    PI["Plugin handlers\n(ITerminalPlugin)"]
    PR["Process\n(cmd / PowerShell / bash)"]
    BUF["Output StringBuilder\n→ UI via Dispatcher.BeginInvoke"]

    TP --> TV
    TV --> SC & AS & CE
    CE --> BI & PI
    AS --> PR & BUF

Each TerminalSession owns a Process (cmd, PowerShell, bash) and an output StringBuilder. Output lines stream to the UI via Dispatcher.BeginInvoke.


API Reference

TerminalPanel

TerminalViewModel ViewModel { get; }

// Convenience shortcut to active session
TerminalSession? ActiveSession => ViewModel.ActiveSession;

TerminalViewModel

ObservableCollection<TerminalSession> Sessions { get; }
TerminalSession? ActiveSession { get; set; }

// Add a new tab
TerminalSession AddSession(string name, TerminalShellType shell);
// shell: Cmd | PowerShell | Bash | GitBash

// Remove a tab
void RemoveSession(TerminalSession session);

TerminalSession

string Name { get; set; }

// Execute a command
Task ExecuteCommandAsync(string command);

// Output
string FullOutput { get; }
event EventHandler<string>? OutputLineReceived;

// Find in output
void FindNext(string pattern);
void ClearOutput();

// Export
Task ExportToTextAsync(string filePath);
Task ExportToHtmlAsync(string filePath);

// Macro
MacroRecorder Recorder { get; }

MacroRecorder

void StartRecording();
void StopRecording();
void Play();
void Play(Dictionary<string, string> variables);   // variable substitution

IReadOnlyList<string> RecordedCommands { get; }
bool IsRecording { get; }

HxScriptEngine

Task RunScriptAsync(string scriptPath);
Task RunScriptAsync(string scriptContent, bool isLiteral);

event EventHandler<string>? OutputLine;
event EventHandler<Exception>? ScriptError;

Level 1: Basic Setup

1 — Install

dotnet add package WpfTerminal

2 — Add namespace and control

<Window
    xmlns:term="clr-namespace:WpfHexEditor.Terminal;assembly=WpfHexEditor.Terminal">

    <term:TerminalPanel x:Name="Terminal" />

No resource dictionary merge required.

3 — Add a default session

Terminal.ViewModel.AddSession("PowerShell", TerminalShellType.PowerShell);

4 — Execute a command

await Terminal.ViewModel.ActiveSession.ExecuteCommandAsync("Get-Process");

Level 2: Sessions & Commands

Multiple shell tabs

var ps   = Terminal.ViewModel.AddSession("PowerShell", TerminalShellType.PowerShell);
var cmd  = Terminal.ViewModel.AddSession("cmd",        TerminalShellType.Cmd);
var bash = Terminal.ViewModel.AddSession("bash",       TerminalShellType.Bash);

// Switch active tab
Terminal.ViewModel.ActiveSession = ps;

React to output

ps.OutputLineReceived += (_, line) =>
{
    if (line.Contains("ERROR"))
        Dispatcher.BeginInvoke(() => StatusBar.Text = $"Error: {line}");
};

Search output

// Find next match in the output panel (highlights and scrolls)
ps.FindNext("Exception");

Export output

await ps.ExportToTextAsync(@"C:\logs\session.txt");
await ps.ExportToHtmlAsync(@"C:\logs\session.html");

Close a session

Terminal.ViewModel.RemoveSession(cmd);

Level 3: Macros & HxScript

Record a macro

var session = Terminal.ViewModel.ActiveSession;

session.Recorder.StartRecording();

await session.ExecuteCommandAsync("cd C:\\Projects");
await session.ExecuteCommandAsync("git status");
await session.ExecuteCommandAsync("dotnet build");

session.Recorder.StopRecording();

Replay the macro

session.Recorder.Play();

Replay with variable substitution

// Command recorded as: "cd {ROOT}"
session.Recorder.Play(new Dictionary<string, string>
{
    ["ROOT"] = @"C:\Projects\MyApp"
});

HxScript

.hxscript files are lightweight automation scripts executed by HxScriptEngine.

// build-and-test.hxscript
cd {PROJECT}
dotnet build --configuration Release
dotnet test --no-build
var engine = new HxScriptEngine();
engine.OutputLine  += (_, line) => Console.WriteLine(line);
engine.ScriptError += (_, ex)   => Console.Error.WriteLine(ex.Message);

await engine.RunScriptAsync(@"C:\scripts\build-and-test.hxscript");

Level 4: Plugins & Theming

Implement a terminal plugin

using WpfHexEditor.SDK.Terminal.Abstractions;

public class HexDumpPlugin : ITerminalPlugin
{
    public string CommandName => "hexdump";
    public string Description => "Dump file as hex to terminal output";

    public async Task<string?> ExecuteAsync(string[] args, ITerminalContext context)
    {
        if (args.Length == 0) return "Usage: hexdump <file>";

        var bytes = await File.ReadAllBytesAsync(args[0]);
        return string.Join(" ", bytes.Select(b => b.ToString("X2")));
    }
}

Register a plugin

Terminal.ViewModel.CommandEngine.RegisterPlugin(new HexDumpPlugin());

Theme

The terminal uses DynamicResource keys. Override in your ResourceDictionary:

<SolidColorBrush x:Key="TERM_Background"       Color="#1E1E1E" />
<SolidColorBrush x:Key="TERM_Foreground"       Color="#D4D4D4" />
<SolidColorBrush x:Key="TERM_SelectionBrush"   Color="#264F78" />
<SolidColorBrush x:Key="TERM_InputBackground"  Color="#252526" />
<SolidColorBrush x:Key="TERM_TabActive"        Color="#1E1E1E" />
<SolidColorBrush x:Key="TERM_TabInactive"      Color="#2D2D2D" />
<SolidColorBrush x:Key="TERM_ErrorForeground"  Color="#F44747" />
<SolidColorBrush x:Key="TERM_WarningForeground" Color="#CCA700" />

Built-in Commands Reference

CommandDescription
cd <path>Change working directory
ls / dirList files in current directory
cat <file>Display file content
find <pattern> [path]Search for pattern in files
grep <pattern> <file>Search for pattern in file content
clearClear terminal output
echo <text>Print text to output
set <var> <value>Set environment variable
envList environment variables
pwdPrint working directory
mkdir <path>Create directory
rm <path>Remove file or empty directory
cp <src> <dst>Copy file
mv <src> <dst>Move or rename file
historyShow command history
macro recordStart recording a macro
macro stopStop recording
macro playReplay last recorded macro
macro listList saved macros
macro save <name>Save current recording as named macro
macro load <name>Load and replay a named macro
script <file>Run an .hxscript file
hex <file>Open file in hex editor
inspect <offset>Inspect bytes at offset in open hex file
export text <file>Export session output to text
export html <file>Export session output to HTML
plugin listList registered terminal plugins
plugin run <name>Execute a plugin command
solution open <path>Open solution in IDE host
solution buildBuild active solution
solution cleanClean build output
diagShow diagnostic information
theme darkSwitch to dark theme
theme lightSwitch to light theme
font-size <n>Change terminal font size
find-in-output <pattern>Highlight pattern in output
session new <name>Add a new terminal tab
session closeClose active tab
session listList open sessions
help [command]Show help for all or specific command

Settings Reference

PropertyTypeDefaultDescription
FontSizedouble13Terminal font size
FontFamilyFontFamilyCascadia CodeTerminal font
ShowLineNumbersboolfalseShow line numbers in output
MaxOutputLinesint10000Maximum buffered output lines
ShowTimestampboolfalsePrefix each output line with timestamp
HistorySizeint500Per-session command history depth
AutoScrollToEndbooltrueAuto-scroll output on new line
WordWrapboolfalseWrap long output lines