Opening A Client
Start the SFTP subsystem and inspect the negotiated version and extensions.
Open The Client
The public SFTP entry point is SSHConnection.openSFTP(clientVersion:).
import Traversio
@available(macOS 26.0, iOS 26.0, *)
func openSFTP(configuration: SSHClientConfiguration) async throws {
try await SSHClient.withConnection(configuration: configuration) { connection in
let sftp = try await connection.openSFTP()
let exchange = try await sftp.currentVersionExchange()
print(exchange.clientVersion)
print(exchange.serverVersion)
}
}The default client version is 3, which matches the current implementation focus.
Inspect Extensions
SSHSFTPVersionExchange exposes the extensions advertised by the server:
let exchange = try await sftp.currentVersionExchange()
print(exchange.extensions.map(\.name))
print(exchange.supportsExtension(named: "[email protected]", minimumVersion: 1))Traversio automatically prefers [email protected] when the server advertises version 1 or later. Otherwise it uses standard SSH_FXP_RENAME.
Close The Client
SFTPClient.close() closes the subsystem channel explicitly:
let connection = try await SSHClient.connect(configuration: configuration)
let sftp = try await connection.openSFTP()
let exchange = try await sftp.currentVersionExchange()
print(exchange.serverVersion)
try await sftp.close()
await connection.close()If you opened the client inside SSHClient.withConnection(...), the enclosing connection scope invalidates the SFTP client automatically. Explicit close() is useful when you manage a long-lived SSHConnection and want to release the subsystem channel early.
Behavior And Limits
Opening the client:
- opens a subsystem channel
- requests
sftp - performs the initial version exchange
- keeps the resulting actor scoped to the enclosing connection lifetime
The current surface focuses on the subsystem lifecycle and version negotiation. Larger transfer features remain outside this page:
- handle-level stream-style upload/download helpers, which are documented on Transfers
- resumable whole-file upload/download helpers, whole-file transfer progress callbacks, and bounded concurrency controls, which are documented on Transfers
- automatic reconnect behavior
- a separate long-lived lifecycle outside
withConnection