Why Traversio
Why Traversio exists, how it is positioned, and what kind of SSH client API it is trying to provide.
Traversio exists to make SSH feel like a native Swift library for Apple apps.
The library is not a thin wrapper around a C SSH engine, and it is not a low-level protocol pipeline that expects application code to assemble its own client behavior. Traversio starts from the shape most Apple apps need:
- describe a server, auth method, host-trust policy, and transport policy
- open one authenticated SSH connection with
async/await - run commands, open shells, transfer files, or forward traffic
- receive typed failures and redacted diagnostics when something goes wrong
- keep reconnect, credential storage, trust-store persistence, and rollout policy in the application layer
The Public Boundary
The main boundary is SSHClientConfiguration -> SSHConnection -> child work.
import Traversio
func uname() async throws -> String {
let configuration = SSHClientConfiguration(
host: "example.com",
username: "deploy",
authentication: .password("secret"),
hostKeyPolicy: .knownHostsFile("/Users/me/.ssh/known_hosts")
)
let result = try await SSHClient.withConnection(configuration: configuration) { connection in
try await connection.execute("uname -a")
}
return String(decoding: result.standardOutput, as: UTF8.self)
}That example is small, but it shows the main API properties:
- connection setup is explicit and asynchronous
- host-key trust is required by configuration
- the connection owns sessions, SFTP clients, and forwarding wrappers
- failures are surfaced through Swift errors rather than hidden process state
- closure-scoped and explicit long-lived ownership both use the same connection path
Why A Native Swift SSH Client
SSH clients for Apple apps often need to run inside UI-driven, long-lived, cancellation-aware applications. That is a different environment from a command-line tool that owns the whole process and exits when the operation ends.
Traversio is built around that app shape:
async/awaitfor operations that suspend- actors for shared mutable protocol state
AsyncSequencefor session, shell, and forwarding event streams- explicit timeout, keepalive, rekey, compression, proxy, and ProxyJump settings
- app-owned host-trust persistence instead of a mandatory built-in database
- structured logging and support-report helpers with default redaction
The goal is not to hide SSH. The goal is to put SSH concepts behind public Swift types with clear lifetime rules.
Why The Transport Layer Matters
SSH needs a reliable byte stream. Traversio keeps the SSH protocol core behind a byte-stream abstraction and selects an Apple networking backend at runtime.
The public package floor is broad enough for existing Apple apps. On Apple platform release 26 and later, Traversio automatically prefers the newer Network.framework backend. Older supported releases use compatibility transport and listener backends behind the same public API surface.
That keeps two boundaries clear:
- the SSH wire, auth, channel, SFTP, and forwarding layers do not depend on socket-specific APIs
- Apple-specific transport behavior stays below the public SSH client model
This matters for IPv6, path changes, proxy routes, laptop and mobile network transitions, and apps that need one library surface across supported Apple releases.
What Traversio Provides Today
Traversio 1.0.x is a usable public release line, not just a research shape.
The current public API includes:
- connection setup, explicit close, state snapshots, and state event streams
- password, password-change, keyboard-interactive, public-key, callback-backed, and SSH-agent authentication
- OpenSSH private-key metadata inspection, loading, OpenSSL-style PEM loading, and key generation for the supported key families
- host-key policies for pinning, trusted key sets, first-seen trust, callbacks, and OpenSSH
known_hosts - exec, streamed exec, named subsystem startup, PTY shells, environment requests, PTY resize, signals, and exit-signal reporting
- SFTP metadata, file handles, listing, reads, writes, mutations, recursive transfers, resumable transfers, progress callbacks, and selected OpenSSH extensions
- single-file SCP compatibility helpers
- raw
direct-tcpip, local forwarding, dynamic SOCKS forwarding, remote TCP forwarding, streamlocal forwarding, connection proxies, and ProxyJump - structured errors, operation diagnostics, log handlers, OSLog adapters, and route-aware SSH port latency measurement
The current release line is still explicit about limits. Traversio does not own automatic reconnect, session restoration, credential-store policy, a mandatory trust database, X11 forwarding, auth-agent forwarding, hostbased auth, security-key auth, or every legacy algorithm family.
How This Differs From Wrapper-Oriented APIs
A wrapper around an existing SSH engine can be useful, especially when the application wants proven behavior from that engine and is comfortable adapting to its lifecycle model.
The tradeoff is that thin wrappers often inherit the engine's shape:
- session handles
- channel handles
- blocking or retry-oriented control flow
- state transitions that are not expressed as Swift ownership
- transport assumptions that come from the wrapped engine
Traversio chooses a different shape. The public API starts with Swift ownership and app-facing workflows, then the implementation maps those workflows onto SSH protocol layers.
That is why callers normally work with:
SSHClientConfigurationSSHConnectionSSHSessionSFTPClient- raw forwarding channel wrappers
- closure-scoped forwarding helpers
- typed diagnostics and support-report surfaces
Raw packet choreography stays inside the library unless a public expert API exposes a lower-level channel.
Relationship To SwiftNIO SSH
swift-nio-ssh is a serious native Swift SSH implementation with a different boundary.
Use swift-nio-ssh when your application is already built around SwiftNIO event loops, channels, handlers, and protocol pipelines, or when you want SSH as a lower-level building block inside a broader NIO system.
Use Traversio when you want:
- an Apple-first SSH client library
async/awaitas the primary public style- host trust, auth, sessions, SFTP, forwarding, proxies, and diagnostics as client-level APIs
- Network.framework-backed transport selection below the public surface
- a package that keeps app recovery policy above the SSH connection instead of hiding it inside the library
The difference is less about whether the code is Swift and more about the level of abstraction the caller works with.
Design Priorities
Traversio is optimized for:
- Native Swift public APIs.
- Apple-first transport behavior.
- Structured concurrency and explicit lifetime ownership.
- Testable protocol layering.
- Clear security boundaries for host trust, legacy RSA, compression, and unsupported auth modes.
- Practical app workflows: commands, shells, SFTP, SCP, forwarding, proxy routes, and diagnostics.
That is why Traversio exists.