Icod.Terminal 0.14.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Icod.Terminal --version 0.14.0
                    
NuGet\Install-Package Icod.Terminal -Version 0.14.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Icod.Terminal" Version="0.14.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Icod.Terminal" Version="0.14.0" />
                    
Directory.Packages.props
<PackageReference Include="Icod.Terminal" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Icod.Terminal --version 0.14.0
                    
#r "nuget: Icod.Terminal, 0.14.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Icod.Terminal@0.14.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Icod.Terminal&version=0.14.0
                    
Install as a Cake Addin
#tool nuget:?package=Icod.Terminal&version=0.14.0
                    
Install as a Cake Tool

Icod.Terminal

Icod TUI Toolchain

Icod.Terminal is the managed, cross-platform live-terminal layer for the Icod library family. It sits between Icod.TermInfo and higher-level consumers such as Icod.DCurses, terminal-aware command-line tools, monitors, editors, pagers, and REPLs.

Status

0.14.0 adds lifecycle-safe scoped ownership and exact restoration for the terminal colors introduced in 0.13.

The stable color surface includes:

  • OSC 4 indexed-palette set/query and lifecycle-safe scoped ownership;
  • OSC 104 indexed-palette terminal-policy reset;
  • OSC 10 / 110 default foreground;
  • OSC 11 / 111 default background;
  • OSC 12 / 112 text cursor;
  • OSC 13 / 113 mouse foreground;
  • OSC 14 / 114 mouse background;
  • OSC 17 / 117 highlight background;
  • OSC 19 / 119 highlight foreground;
  • lifecycle-safe scoped ownership for all seven selected dynamic-color identities.

OSC 15/16/18 and resets 115/116/118 remain deliberately excluded as Tektronix-specific dynamic colors.

Installation

dotnet add package Icod.Terminal --version 0.14.0

The package targets net8.0, net9.0, and net10.0 and depends on Icod.TermInfo 1.10.0 and Icod.Timing 1.0.0.

Architecture

Icod.TermInfo
      ^
      |
Icod.Terminal
      ^
      |
Icod.DCurses
      ^
      |
watch / slabtop / top

Icod.TermInfo remains the immutable terminal-capability authority. Icod.Terminal owns live endpoint observation, terminal modes, input, dimensions, lifecycle, terminal identity, output setup, active terminal-query routing, and semantic terminal-output operations. Icod.DCurses owns cells, windows, virtual-screen state, and refresh/diff policy.

Quick start — lifecycle-safe colors

using Icod.Terminal;

await using TerminalSession session = await TerminalSession.OpenAsync(
	new TerminalSessionOptions {
		InputMode = TerminalInputMode.CBreak,
		EchoInput = false
	}
);

TimeSpan timeout = TimeSpan.FromMilliseconds( 750 );

await using TerminalPaletteColorLease palette =
	await session.AcquirePaletteColorAsync(
		1,
		TerminalColor.FromRgb8( 255, 64, 64 ),
		timeout
	);

await using TerminalDynamicColorLease cursor =
	await session.AcquireDynamicColorAsync(
		TerminalDynamicColor.TextCursor,
		TerminalColor.FromRgb8( 64, 255, 64 ),
		timeout
	);

The first owner queries the real external color before mutation. Final release explicitly replays that observed value. Reset sequences are not used as restoration.

TerminalColor preserves normalized 16-bit RGB channels:

TerminalColor color = new(
	0x1234,
	0x5678,
	0x9abc
);

TerminalColor fromBytes = TerminalColor.FromRgb8(
	0x12,
	0x34,
	0x56
);

FromRgb8(...) expands bytes by multiplication by 257, so 0x12 becomes 0x1212.

Scoped ownership contract

Both ownership APIs are query-before-mutate:

ValueTask<TerminalPaletteColorLease> AcquirePaletteColorAsync(
	byte index,
	TerminalColor color,
	TimeSpan queryTimeout,
	CancellationToken cancellationToken = default
);

ValueTask<TerminalDynamicColorLease> AcquireDynamicColorAsync(
	TerminalDynamicColor kind,
	TerminalColor color,
	TimeSpan queryTimeout,
	CancellationToken cancellationToken = default
);

The ownership model is identity-aware and ordered:

  • the first owner captures the exact external baseline;
  • later owners for the same identity nest without re-querying merely because of nesting;
  • owners may be disposed out of order;
  • releasing the controlling owner reapplies the next active owner;
  • releasing the final owner restores the external baseline explicitly;
  • different palette indices and dynamic-color identities remain independent;
  • failed restoration retains logical cleanup responsibility so disposal can be retried.

TerminalSession.InvalidateState() marks physical color state uncertain without discarding logical ownership or the current lifecycle-epoch baseline.

Before managed suspend, active scoped colors restore their external baselines. After resume, old observations are no longer treated as authoritative: retained owners use the session's internal observation phase to establish fresh external baselines before owned colors are reapplied.

Session disposal is the final cleanup owner. Active color leases do not need to be disposed first, and late lease disposal after successful session cleanup is a no-op.

Indexed palette — OSC 4 / 104

Unscoped set and observation remain available:

await session.SetPaletteColorAsync(
	1,
	TerminalColor.FromRgb8( 255, 64, 64 )
);

TerminalColor color = await session.QueryPaletteColorAsync(
	1,
	TimeSpan.FromMilliseconds( 750 )
);

Bounded multi-entry mutation remains available through SetPaletteColorsAsync(...).

Terminal-policy reset remains explicit:

await session.ResetPaletteColorAsync( 1 );
await session.ResetPaletteColorsAsync( [ 1, 2, 3 ] );
await session.ResetPaletteAsync();

The scoped-ownership exclusion is manager-family-wide: while any palette-color lease is active, every unscoped palette set/reset operation is rejected, including operations targeting other indices and reset-all. This prevents an unscoped writer from silently invalidating the exact-restoration contract. Explicit palette observation remains allowed.

Dynamic colors — OSC 10–14, 17, 19

The semantic identities are:

TerminalDynamicColor.DefaultForeground
TerminalDynamicColor.DefaultBackground
TerminalDynamicColor.TextCursor
TerminalDynamicColor.MouseForeground
TerminalDynamicColor.MouseBackground
TerminalDynamicColor.HighlightBackground
TerminalDynamicColor.HighlightForeground

The common/core interoperability tier is OSC 10/11/12. OSC 13/14/17/19 are the extended xterm tier and may have lower support across terminal implementations.

The scoped-ownership exclusion is also manager-family-wide for dynamic colors: while any dynamic-color lease is active, every unscoped dynamic set/reset operation is rejected, including operations targeting another dynamic-color identity. Explicit dynamic-color observation remains allowed.

Reset is not restoration

OSC 104 and OSC 110–119 request terminal policy/defaults. They do not mean “restore the value that existed before this application changed it.”

0.14 scoped leases restore by explicit set-form replay:

palette: OSC 4 ; index ; observed-color ST
dynamic: OSC Ps ; observed-color ST

This distinction is part of the stable 0.14 contract.

Query semantics

Color observation and baseline acquisition reuse the existing session-owned active-query transaction/router.

  • opening a session performs no automatic global color probing;
  • no second response reader is introduced;
  • each query has an explicit finite timeout;
  • caller cancellation remains distinct from timeout;
  • correlated malformed color replies fail with FormatException;
  • timeout is not converted into permanent unsupported state;
  • unrelated application input remains on the normal session path.

Canonical outbound colors use rgb:rrrr/gggg/bbbb with four lowercase hexadecimal digits per channel. Inbound observations accept the documented strict rgb: and hash forms while rejecting unrelated color syntaxes.

Downstream Icod.DCurses acceptance

The T146 downstream acceptance proves that Icod.DCurses 0.1.0 can operate over a TerminalSession with active scoped palette/dynamic-color ownership, consume those owned colors through its normal RGB style path, render normally, and trigger exact baseline restoration when it disposes the TerminalSession it owns.

Current Icod.DCurses uses 8-bit CursesColor.Rgb, so downstream precision adaptation is explicit. Icod.Terminal itself preserves 16-bit channels.

The stable public contract is recorded in docs/Public-API-Baseline-0.14.md. T146 composition/downstream acceptance is recorded in docs/T146-Composition-and-DCurses-Scoped-Color-Acceptance.md.

Previous release highlights

  • 0.13 — observable OSC 4/104 and selected OSC 10–19 terminal colors. See docs/Public-API-Baseline-0.13.md.
  • 0.12 — OSC 133 semantic prompt/command-region markers.
  • 0.11 — OSC 22 pointer shape.
  • 0.10 — OSC 9;4 progress.
  • 0.9 — DEC private mode 2026 synchronized output.
  • 0.8 — DECSCUSR cursor style with observation/scoped restoration.
  • 0.7 — OSC 52 clipboard/selections.
  • 0.6 — OSC 8 hyperlinks.
  • 0.5 — OSC 7 current location.
  • 0.4 — OSC 0/1/2 title operations.

Samples

Focused samples include:

  • Icod.Terminal.Color.Sample — observable colors plus lifecycle-safe scoped ownership;
  • semantic prompt, pointer shape, progress, synchronized output, cursor style, clipboard, hyperlink, location, title, active-query, rich-input, and minimal live-session samples.

See samples/README.md for run instructions.

Build and validation

On Windows:

build.cmd

On POSIX hosts:

sh build.sh

Distribution validation builds/tests the solution, runs real downstream Icod.DCurses acceptance, packs the NuGet artifact, verifies package structure/XML documentation, and runs fresh package-only consumers.

The retained 0.8–0.13 package contracts and the new 0.14 lifecycle-safe color ownership contract run from the freshly produced NuGet artifact on net8.0, net9.0, and net10.0.

Release process

Publishing 0.14.0 requires:

  1. exact stable PR-head validation green on Windows, Linux, and macOS;
  2. exact Staging package verification green;
  3. all real downstream Icod.DCurses acceptance gates green;
  4. retained 0.8–0.13 plus new 0.14 XML/package-only smoke gates green on all supported TFMs;
  5. merge to main;
  6. Release validation green on the resulting exact main commit;
  7. only then create tag v0.14.0.

The tagged workflow reruns build/tests, downstream acceptance, exact package selection, historical package contracts, and the 0.14 ownership package contract before publication to NuGet.org and GitHub Packages.

Development roadmap

The 0.14 milestone is documented in Icod.Terminal-0.14.0-Development-Roadmap.md, with tranche records T140–T147 under docs/.

License

Icod.Terminal is licensed under LGPL-3.0-or-later. See LICENSE.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Icod.Terminal:

Package Downloads
Icod.DCurses

Managed, cross-platform curses-like terminal UI library for .NET, built on Icod.TermInfo and Icod.Terminal.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.16.0 0 9/6/2026
0.15.0 0 9/6/2026
0.14.0 0 9/6/2026
0.13.0 36 9/6/2026
0.12.0 37 9/5/2026
0.11.0 40 9/5/2026
0.10.0 42 9/5/2026
0.9.0 39 9/5/2026
0.8.0 51 9/5/2026
0.7.0 39 9/5/2026
0.6.1 40 9/4/2026
0.6.0 34 9/4/2026
0.5.0 37 9/4/2026
0.4.0 39 9/4/2026
0.3.0 3,173 8/29/2026
0.3.0-alpha.8 69 8/28/2026
0.2.0 88 8/28/2026
0.2.0-alpha.6 87 8/27/2026
0.1.0 85 8/27/2026
0.1.0-alpha.13 56 8/27/2026
Loading failed

0.14.0 adds lifecycle-safe terminal color ownership: query-before-mutate palette and dynamic-color leases; exact observed 16-bit baseline replay; identity-aware nested and out-of-order ownership; invalidation recovery; suspend baseline restoration and post-resume re-observation before retained-state reapply; restoration retry semantics; session-disposal cleanup; concurrency/failure hardening; and downstream Icod.DCurses scoped-color acceptance. OSC 104 and OSC 110-119 remain terminal-policy resets and are never substituted for exact lease restoration.