Surfus.Shell 2.0.0

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

Surfus.Shell

Surfus.Shell is an SSH client library for .NET.

Features

  • Fully asynchronous API
  • Terminal sessions, command execution, and SCP file transfers
  • Local port forwarding (direct-tcpip)
  • SSH agent authentication
  • Private key authentication
  • Keyboard-interactive authentication
  • Host key verification callback
  • Low-level channel API for custom SSH extensions

Installation

dotnet add package Surfus.Shell

Quick Start

await using var client = new SshClient("192.168.1.1");
await client.ConnectAsync(cancellationToken);
await client.AuthenticateAsync("admin", "password", cancellationToken);

var terminal = await client.CreateTerminalAsync(cancellationToken);
await terminal.StandardInput.WriteAsync("show version\n"u8.ToArray(), cancellationToken);

Examples

Connect and Authenticate

await using var client = new SshClient("host", 22);
await client.ConnectAsync(ct);

// Password authentication
await client.AuthenticateAsync("user", "pass", ct);

// Keyboard-interactive
await client.AuthenticateAsync("user", (prompt, ct) => Task.FromResult("password"), ct);

// SSH agent (via SSH_AUTH_SOCK)
var agent = await SshAgentClient.ConnectAsync(ct);
await client.AuthenticateAsync("user", agent, ct);

// SSH agent over a custom stream
using var agent2 = new SshAgentClient(myAgentStream);
await client.AuthenticateAsync("user", agent2, ct);

// Private key
var key = PrivateKeyAuth.FromFile("/path/to/key");
await client.AuthenticateAsync("user", key, ct);

Terminal Session

var terminal = await client.CreateTerminalAsync(ct);

// Write to stdin
await terminal.StandardInput.WriteAsync("ls -la\n"u8.ToArray(), ct);

// Read from stdout
var buf = new byte[4096];
var n = await terminal.StandardOutput.ReadAsync(buf, ct);
var output = Encoding.UTF8.GetString(buf, 0, n);

Execute a Command

var command = await client.CreateCommandAsync(ct);
await command.StartAsync("echo hello", ct);

var result = new MemoryStream();
await command.StandardOutput.CopyToAsync(result, ct);
// result contains "hello\n"

// Exit code is available after the channel closes
var exitCode = command.ExitCode;

Local Port Forwarding

// Forward local port 8080 through SSH to remote-db:5432
await client.ForwardLocalPortAsync(8080, "remote-db", 5432, ct);

Direct TCP/IP Channel

// Open a single forwarded connection
await using var channel = await client.CreateDirectTcpIpChannelAsync("10.0.0.5", 80, ct);

await channel.StandardInput.WriteAsync("GET / HTTP/1.0\r\n\r\n"u8.ToArray(), ct);
var response = new MemoryStream();
await channel.StandardOutput.CopyToAsync(response, ct);

SCP File Transfer

var scp = new ScpClient(client);

// Upload
await scp.UploadAsync("/local/file.txt", "/remote/file.txt", cancellationToken: ct);

// Download
await scp.DownloadAsync("/remote/file.txt", "/local/file.txt", ct);

Host Key Verification

var client = new SshClient("host")
{
    HostKeyCallback = async (hostKey, ct) =>
    {
        // Verify the host key and return true to accept
        return true;
    }
};
var client = new SshClient("host")
{
    // Called for each line the server sends before its version string (RFC 4253 §4.2)
    OnConnectionBanner = line => Console.WriteLine($"Connection: {line}"),

    // Called when the server sends a banner during authentication (RFC 4252)
    OnAuthenticationBanner = banner => Console.WriteLine($"Auth: {banner}")
};

Low-Level Channel API

For custom channel types or advanced use cases:

// Open a raw session channel
var channel = await client.OpenChannelAsync(new ChannelOpenSession(), ct);

// Send custom requests
await channel.RequestAsync(new ChannelRequestSubsystem(channel.ServerId, true, "sftp"), ct);

// Use the channel streams
await channel.StandardInput.WriteAsync(data, ct);

// Or construct higher-level wrappers manually
var terminal = new SshTerminal(channel, new TerminalOptions { Columns = 120, Rows = 40 });
await terminal.RequestAsync(ct);

Custom Stream Transport

// Use an existing stream (e.g., over a proxy)
await using var client = new SshClient(myStream);

// Or use a factory for reconnectable transports
await using var client = new SshClient(async ct =>
{
    var tcp = new TcpClient();
    await tcp.ConnectAsync("host", 22, ct);
    return (tcp.GetStream(), () => { tcp.Dispose(); return ValueTask.CompletedTask; });
});
Product Compatible and additional computed target framework versions.
.NET 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.
  • net9.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Surfus.Shell:

Package Downloads
Surfus.Shell.Cisco

Surfus.Shell.Cisco provides Cisco Router/Switch/Firewall extensions to Surfus.Shell.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 88 5/20/2026
1.1.0 370 8/27/2023
1.0.94 3,572 7/12/2017
1.0.92 1,324 7/12/2017
1.0.89 1,295 7/12/2017
1.0.86 1,356 7/11/2017
1.0.73 1,870 7/11/2017
1.0.42 1,373 6/25/2017