SSHKit

Swift package for libssh on Apple platforms. Async/await, callback, and Objective-C APIs over a single libssh-per-connection worker.

Capabilities

Install

Add the package to Package.swift:

dependencies: [
    .package(url: "https://github.com/Lakr233/SSHKit.git", from: "0.1.5"),
],
targets: [
    .target(name: "App", dependencies: [
        .product(name: "SSHKit", package: "SSHKit"),
    ]),
]

For Xcode projects, add the same URL through File → Add Package Dependencies… and link the SSHKit product. SSHKit, SSHKitObjC, and CLibSSH ship as dynamic libraries to keep the libssh LGPL boundary explicit.

Platforms

PlatformFloor
iOS13.0
macOS10.15
Mac Catalyst13.0
tvOS13.0
visionOS1.0

watchOS is outside the supported set.

Quick start

import SSHKit

let configuration = SSHClient.Configuration(
    host: "example.com",
    username: "deploy",
    authentication: .password("secret"),
    hostKeyPolicy: .knownHostsFile(
        ("~/.ssh/known_hosts" as NSString).expandingTildeInPath
    )
)

let output = try await SSHClient.withConnection(configuration) { connection in
    try await connection.execute("uname -a")
}

print(String(data: output.standardOutput, encoding: .utf8) ?? "")
print("exit:", output.exitStatus)

withConnection opens a session, runs the body, and closes the connection on both success and failure. Non-zero exit status is part of SSHCommandResult, not a thrown error — inspect output.exitStatus after the call. For long-lived trust, use SSHClient.discoverHostKey to capture the server’s fingerprint, save it to a Keychain trust store, then switch hostKeyPolicy to .trustStore(...). The host-trust guide walks through the four steps.

Ownership rules at a glance

The full model is in Architecture; the type catalog is in API.

License

SSHKit project code is MIT-licensed. The vendored libssh source under Vendor/libssh remains under its upstream GNU LGPL terms (see Vendor/libssh/COPYING in the repository). Linking SSHKit dynamically preserves the LGPL boundary.