Leith.Term.Kernel 430.0.0

Leith.Term.Engine

Git: github.com/buchmiet/Leith.Term.Engine — clone as Leith.Term.Engine/ (sibling of Leith.Term.Presentation, Leith.Text, …).

Standalone VT/xterm-class terminal engine extracted from Leith.Term.Presentation.

The main library ships as Leith.Term (NuGet id, assembly, and root namespace).

Contents

  • src/Term/ — public Terminal facade over the kernel
  • src/Kernel/ — terminal kernel (grid, modes, graphics, journal, effects)
  • src/VtParser/ — standalone VT parser the kernel consumes
  • sibling Leith.Imaging — owns the dependency-free PNG, GIF and SIXEL codecs consumed by the engine
  • src/Tests/Tests.Engine/ — engine test suite and corpora
  • src/Tests/Tests.Scenarios/ — scenario runner and acceptance corpus shared by the test projects
  • Benchmarks/Engine.* — decode/parser/SIMD benchmarks
  • tools/kitty-oracle, tools/kitty-keyboard-oracle — Kitty corpus tooling

Build

dotnet build Term.Engine.slnx -c Release
dotnet test --solution Term.Engine.slnx -c Release

The test suites are xunit.v3 4.x, which are self-hosting Microsoft.Testing.Platform applications rather than VSTest assemblies, and global.json opts dotnet test into that runner. Two consequences worth knowing before the first confusing result: the project or solution has to be named with --project / --solution, because a bare positional path is accepted and then quietly runs nothing ("Zero tests ran"); and the reporting switches differ — --report-xunit-trx in place of --logger trx. Each test project is also directly executable, which is the quickest way to run one suite.

Kitty corpus tests may require LEITH_KGP_CORPUS / homelab checkout — see tools/kitty-oracle/README.md.

IIP codecs

Leith.Term decodes OSC 1337 PNG through Leith.Imaging.Png and GIF through Leith.Imaging.Gif. Other IIP formats remain opt-in via TerminalGraphicsOptions.ImageDecoder. JPEG, WebP, TIFF and similar are host business; the engine does not reference ImageSharp.

SIXEL and Jexer gallery tests still use SixLabors.ImageSharp 3.1.x as a test-only PNG reader. That package is not referenced by shipping code and does not gate Leith.Term.slnx on a Six Labors license.

Minimal 0.1.0 host wiring (public API only)

raw PTY bytes
      ↓
Terminal.Process(ReadOnlySpan<byte>)
      ↓
committed terminal state  (Screen, modes, Title, …)
      ↓
TerminalMutationResult.EffectRange
      ↓
Terminal.DrainEffects(range)  →  PtyBytes / HostQuery / WindowOp / Bell

Terminal is not thread-safe: serialize Process, input APIs, DrainEffects, and reads on one lock.

using System.Text;
using Leith.Term;
using Leith.Term.Events;
using Leith.Term.Input;

var options = new TerminalOptions
{
    Columns = 120,
    Rows = 40,
    ScrollbackLines = 10_000,
    WindowPermissions = TerminalWindowPermissions.GetGeometryPixels
        | TerminalWindowPermissions.ManipulateWindow,
};

using var terminal = new Terminal(options);
long renderWatermark = terminal.Screen.GetViewportChangeSet().ChangeSequence;

void OnPtyBytes(ReadOnlySpan<byte> data)
{
    var remaining = data;
    while (remaining.Length > 0)
    {
        var result = terminal.Process(remaining);
        foreach (var effect in terminal.DrainEffects(result.EffectRange).Effects)
        {
            switch (effect.Kind)
            {
                case TerminalEffectKind.PtyBytes:
                    pty.Write(effect.Bytes.Span);
                    break;
                case TerminalEffectKind.HostQuery when effect.HostQuery is { } query:
                    if (TerminalHostQueryReplies.TryEncode(
                            query,
                            new WindowCharDimensionsInfo(host.VisibleRows, host.VisibleColumns),
                            out var wire))
                    {
                        OnPtyBytes(wire.Span);
                    }
                    break;
                case TerminalEffectKind.WindowOp:
                    host.ApplyWindowOp(effect.WindowOp);
                    break;
                case TerminalEffectKind.Bell:
                    host.RingBell();
                    break;
            }
        }

        if (result.Status == ProcessStatus.OutputFull)
        {
            remaining = remaining[result.Consumed..];
            continue;
        }

        if (terminal.Screen.IsFullDamageSince(renderWatermark))
            renderer.InvalidateFull();
        else
            renderer.InvalidateRows(terminal.Screen, renderWatermark);

        renderWatermark = result.ChangeSequence;
        remaining = remaining[result.Consumed..];
    }
}

var key = terminal.SendKey(new TerminalKeyEvent(TerminalKey.FromRune(new Rune('a')))
{
    Modifiers = TerminalKeyModifiers.Control,
});
DrainInputEffects(key);

terminal.SendText("日本語");
terminal.Paste(clipboardText);
terminal.SendMouse(new TerminalMouseEvent(
    TerminalMouseEventType.Down,
    TerminalMouseButton.Left,
    column,
    row));
terminal.SendFocus(true);

var line = terminal.Screen.GetViewportLine(0);
if (line is not null)
{
    var cell = line.GetCell(0);
    Draw(cell);
}

void DrainInputEffects(TerminalMutationResult result)
{
    foreach (var effect in terminal.DrainEffects(result.EffectRange).Effects)
    {
        if (effect.Kind == TerminalEffectKind.PtyBytes)
        {
            pty.Write(effect.Bytes.Span);
        }
    }
}

Accidental public API growth is guarded by PublicApiBaselineTests and the checked-in Leith.Term.PublicApi.baseline.txt snapshot. The public API baseline is enforced (BaselineTestPolicy.Enabled = true). Kitty/sixel oracle snapshots remain research-only; see Docs/BASELINE_TESTS_SUSPENDED.md. Regenerate the tracked public API baseline with UPDATE_PUBLIC_API_BASELINE=1 dotnet test --project src/Tests/Tests.Engine/Tests.Engine.csproj --filter PublicApi_MatchesCheckedInBaseline.

Headless architecture

Docs/HEADLESS_ARCHITECTURE.md is the authoritative model for headless use: Terminal as the engine, Screen vs Terminal.Graphics, explicit time, and the removal of TerminalEngine. Superseded draft: Docs/HEADLESS_ENGINE_API.md. CLI dependency policy (sibling repo): Docs/Leith.Cli_DEPENDENCY_POLICY.md.

History

Git history was extracted from Leith.Term.Presentation with git filter-repo (engine-related paths only). Terminal remains the integration repo for Session, hosts, transport, and rendering.

License

MIT — see LICENSE and THIRD-PARTY-NOTICES.md.

Showing the top 20 packages that depend on Leith.Term.Kernel.

Packages Downloads
Leith.Term
Leith VT/xterm-class terminal engine (.NET 10). See https://github.com/buchmiet/Leith.Term.Engine.
34
Leith.Term
Leith VT/xterm-class terminal engine (.NET 10). See https://github.com/buchmiet/Leith.Term.Engine.
3
Leith.Term
Leith VT/xterm-class terminal engine (.NET 10). See https://github.com/buchmiet/Leith.Term.Engine.
0

.NET 10.0

Version Downloads Last updated
431.0.0 0 09/29/2026
430.0.0 33 09/29/2026