Skip to content

Getting Started

RoyalTerminal is a modular terminal stack, not a single UI control package. The smallest successful setup depends on whether you want:

  • a managed Avalonia terminal with no native VT dependency
  • an Avalonia terminal that can use the official Ghostty VT engine
  • lower-level transport, rendering, or profile infrastructure without the demo app

Choose the package set

ScenarioRequired packages
Avalonia terminal with managed VT fallbackRoyalApps.RoyalTerminal.Avalonia
Avalonia terminal with native Ghostty VT availableRoyalApps.RoyalTerminal.Avalonia, RoyalApps.RoyalTerminal.Terminal.Vt.Ghostty; restore or publish with your target RID so NuGet selects the matching native asset package
Avalonia settings surfaceadd RoyalApps.RoyalTerminal.Avalonia.Settings
SSH agent auth for the SSH.NET transportadd RoyalApps.RoyalTerminal.Terminal.Transport.Ssh.SshNet.Agent

Native asset packages selected by runtime.json:

  • macOS: RoyalApps.RoyalTerminal.GhosttySharp.Native.OSX
  • Windows: RoyalApps.RoyalTerminal.GhosttySharp.Native.Win64
  • Linux: RoyalApps.RoyalTerminal.GhosttySharp.Native.Linux64

Install the packages

Managed-only Avalonia setup:

bash
dotnet add package RoyalApps.RoyalTerminal.Avalonia

Avalonia plus native Ghostty VT:

bash
dotnet add package RoyalApps.RoyalTerminal.Avalonia
dotnet add package RoyalApps.RoyalTerminal.Terminal.Vt.Ghostty
dotnet publish -r osx-arm64

Replace osx-arm64 with the RID you publish or restore for, such as win-x64, win-arm64, linux-x64, linux-arm64, or osx-x64. Direct native package references are only needed when you intentionally want to force a specific native asset package.

Add a TerminalControl

In XAML, host TerminalControl like any other Avalonia control:

xml
<Window
    xmlns="https://github.com/avaloniaui"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:rt="clr-namespace:RoyalTerminal.Avalonia.Controls;assembly=RoyalTerminal.Avalonia">
  <rt:TerminalControl
      x:Name="Terminal"
      Columns="120"
      Rows="36"
      ScrollbackLimit="10000"
      TerminalFontSize="14" />
</Window>

Start a local PTY session

StartSessionAsync(...) is the preferred entry point. It routes through the transport abstraction and keeps the control aligned with the shared session-service pipeline.

csharp
using RoyalTerminal.Avalonia.Controls;
using RoyalTerminal.Terminal;

public static async Task StartAsync(TerminalControl terminal)
{
    TerminalSessionDimensions dimensions = new(
        Columns: 120,
        Rows: 36,
        WidthPixels: 1200,
        HeightPixels: 800);

    PtyTransportOptions options = new(
        Command: null,
        WorkingDirectory: Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
        Environment: null,
        Dimensions: dimensions);

    await terminal.StartSessionAsync(options);
}

StartPty(...) still exists for compatibility, but new integrations should prefer StartSessionAsync(...) or the typed helpers such as StartSshAsync(...).

Start an SSH session

The SSH transport uses the same session pipeline and option model:

csharp
using RoyalTerminal.Avalonia.Controls;
using RoyalTerminal.Terminal;

TerminalControl terminal = new();

SshTransportOptions options = new(
    Endpoint: new SshEndpointOptions("example.com", 22, "alice"),
    RequestPty: true,
    TerminalType: "xterm-256color",
    InitialCommand: null,
    Authentication: new SshAuthenticationOptions(
        UsePassword: true,
        PasswordSecretId: "demo-password",
        PrivateKeySecretIds: Array.Empty<string>(),
        UseAgent: false),
    Dimensions: new TerminalSessionDimensions(120, 40, 1200, 800))
{
    ExpectedHostKeyFingerprintSha256 = "SHA256:BASE64_FINGERPRINT",
};

await terminal.StartSshAsync(options);

If ExpectedHostKeyFingerprintSha256 is not set, the default trust path falls back to KnownHostsSshHostKeyValidator and OpenSSH known_hosts.

Enable native VT explicitly

If you want strict native-VT behavior instead of automatic fallback, set VtProcessorPreference to Native and add the Ghostty VT provider package plus native runtime assets:

csharp
using RoyalTerminal.Avalonia.Controls;
using RoyalTerminal.Avalonia.Services;
using RoyalTerminal.Terminal;
using RoyalTerminal.Terminal.Services;

TerminalControl terminal = new(
    new TerminalSessionService(),
    new DefaultTerminalInputAdapter(),
    new DefaultTerminalSelectionService(),
    new DefaultTerminalScrollService(),
    new DefaultVtProcessorFactory([new GhosttyVtProcessorProvider()]),
    new DefaultPtyFactory())
{
    VtProcessorPreference = VtProcessorPreference.Native,
};

Use Auto when you want the native processor when available and the managed processor otherwise.

Where to go next

MIT Licensed