RemoteViewer.SessionKit 0.9.0

dotnet add package RemoteViewer.SessionKit --version 0.9.0
                    
NuGet\Install-Package RemoteViewer.SessionKit -Version 0.9.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="RemoteViewer.SessionKit" Version="0.9.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RemoteViewer.SessionKit" Version="0.9.0" />
                    
Directory.Packages.props
<PackageReference Include="RemoteViewer.SessionKit" />
                    
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 RemoteViewer.SessionKit --version 0.9.0
                    
#r "nuget: RemoteViewer.SessionKit, 0.9.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 RemoteViewer.SessionKit@0.9.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=RemoteViewer.SessionKit&version=0.9.0
                    
Install as a Cake Addin
#tool nuget:?package=RemoteViewer.SessionKit&version=0.9.0
                    
Install as a Cake Tool

SessionKit

Remote desktop as a library — for .NET. Drop cross-platform screen sharing and remote control into your own application, riding whatever secure channel you already have.

RemoteViewer.SessionKit is the session layer of a remote-desktop stack: it captures a screen, encodes it, streams it, and injects the operator's mouse/keyboard back — plus clipboard, file transfer, and audio — all multiplexed over a single transport-agnostic byte channel (ISessionChannel) that you provide. It does not open sockets, traverse NATs, or run a relay: you bring the pipe (a WebSocket, a raw socket with framing, an SSH tunnel, or ConnectKit for an encrypted NAT-traversing one), and SessionKit is what flows over it.

your app ──▶ SessionHost(channel, screenSource, inputSink)   // device: capture → encode → send, apply input
your app ──▶ ViewerSession(channel)                          // operator: OnFrame(bgra) + SendMouse/SendKey/…

If you're building remote support, an RMM/kiosk/POS tool, an industrial-HMI console, or any .NET app that needs "see and control that machine" — SessionKit is the embeddable core, without bundling a third-party product.

Why SessionKit

  • .NET-native. A single NuGet package (net8.0 / net9.0), one dependency (SkiaSharp). No native SDK to vendor, no C++ interop for you to maintain — it's using RemoteViewer.SessionKit; and go.
  • Transport-agnostic. SessionKit never assumes a network. Anything that can carry a byte message — preserving message boundaries — is a valid channel, so it slots into apps that already have a connection.
  • Cross-platform, both ends. Windows, Linux, and macOS can each be the host (the controlled device) and the viewer (the operator). Capture, input, and codecs are chosen per OS behind stable seams.
  • Hardware H.264, license-clean. Video is JPEG-tile deltas by default, or hardware H.264 via each OS's native codec — Media Foundation (Windows), VideoToolbox (macOS), VA-API (Linux). Using the OS codec means the OS covers the H.264 patent licensing. The codec is negotiated automatically.
  • Composable. Screen source, input sink, clipboard, and channel are all interfaces — swap in your own, or use the built-ins. Pairs with ConnectKit for a batteries-included-but-not-monolithic stack.

Install

dotnet add package RemoteViewer.SessionKit

Requires the .NET 8 or .NET 9 SDK. Sole dependency: SkiaSharp.

30-second example

Host — capture this machine and apply the operator's input:

using RemoteViewer.SessionKit;
using RemoteViewer.SessionKit.Capture;
using RemoteViewer.SessionKit.Input;

var host = new SessionHost(
    channel,                                   // your ISessionChannel
    WindowsScreenCapture.CreateBest(out _),    // DXGI→GDI on Windows; see below for Linux/macOS
    new WindowsInputSink(),                     // applies the viewer's mouse/keyboard
    new HostOptions { MaxWidth = 1920, MaxFps = 15, Quality = 70 });
host.Start();                                   // capture/send loop runs until Dispose()

Viewer — show frames and drive the host:

using RemoteViewer.SessionKit;
using RemoteViewer.SessionKit.Input;

var viewer = new ViewerSession(channel);
viewer.OnFrame += frame =>
{
    // frame.Bgra is tight BGRA8888 (Width*Height*4). Wrap it in your UI's bitmap and blit.
};
viewer.Start();

viewer.SendMouseMove(0.5f, 0.5f);               // coordinates are normalized 0..1 across the frame
viewer.SendMouseButton(MouseButton.Left, down: true);
viewer.SendMouseButton(MouseButton.Left, down: false);
viewer.SendText("hello");

Full walkthrough (including a runnable offline selftest): GETTING-STARTED.md.

What's in the box

Capability Windows Linux macOS
Screen capture DXGI (→ GDI fallback) X11 (XGetImage) CoreGraphics¹
Input inject SendInput XTest (mouse + Unicode text) CGEvent (mouse + Unicode text)
H.264 encode Media Foundation VA-API (Intel/AMD) VideoToolbox
H.264 decode Media Foundation VA-API VideoToolbox
Clipboard Win32 (text + image) X11 via xclip (text + img) (in-memory)²
File transfer ✓ (chunked, hashed)
Audio WASAPI loopback → playback

¹ Needs Screen Recording permission; SessionKit ships preflight/request helpers. ² Native mac clipboard is a planned backend behind the same interface. Everything is multiplexed on one channel by a 1-byte tag.

Video is JPEG-tile deltas (only changed 16×16 tiles, JPEG-compressed) by default — no codec, works everywhere. Supply an IVideoEncoder/IVideoDecoder to opt into H.264 instead; JPEG remains the automatic fallback.

Bring your own channel

public interface ISessionChannel
{
    void Send(ReadOnlySpan<byte> data);   // send one whole message
    event Action<byte[]>? OnData;         // one message received (boundaries preserved)
    event Action? OnClosed;
}

The one rule: one Send must arrive as exactly one OnData. Datagram-like transports (ConnectKit, WebSocket messages) satisfy this directly; over a raw TCP stream, add length-prefix framing in your adapter.

Codec negotiation

Supplying an encoder is always safe. The host doesn't assume the viewer can decode H.264 — on connect the viewer advertises the codecs it can decode, and the host switches to H.264 only when it can also encode it, else it stays on the JPEG-tile baseline every viewer understands. A viewer that can't do H.264 simply keeps getting JPEG.

Interoperable, verified

The H.264 wire format is platform-independent Annex-B. The full 3×3 encode/decode matrix — Media Foundation, VideoToolbox, VA-API — cross-decodes in every direction, verified on real Windows, macOS, and Linux hardware (including colorspace handling and multi-slice pictures). A Linux box captured over X11, encoded on its Intel iGPU, and streamed over TCP to a decoding viewer end-to-end.

Status — 0.9.0

Pre-1.0 but broadly exercised: 50 unit tests, an offline selftest, live two-process sessions on all three OSes, and the cross-OS codec matrix above. The public API (SessionHost / ViewerSession / ISessionChannel and the capture/input/codec seams) is settling toward 1.0; remaining work (native Wayland capture, macOS ScreenCaptureKit) is additive behind the existing interfaces and won't break your code.

Build & test from source

dotnet build SessionKit.slnx -c Release
dotnet test SessionKit.slnx
dotnet run --project samples/SessionKit.Sample -- selftest   # offline host→loopback→viewer

License

Commercial / proprietary — see LICENSE.txt. Installation requires accepting the license terms. For evaluation, pricing, or licensing questions, see the project site.

Part of the RemoteViewer family

Connection = ConnectKit · Session = SessionKit. ConnectKit (RemoteViewer.ConnectKit) gives you the encrypted, NAT-traversing pipe (IConnectChannel); SessionKit is what rides it. They combine through a thin adapter (IConnectChannel → ISessionChannel) shown in the sample — SessionKit itself takes no ConnectKit dependency, so you can pair it with any transport you like.

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 was computed.  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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.9.0 0 8/31/2026