swift-et
July 21, 2026 · View on GitHub
Pure Swift Eternal Terminal (ET) protocol client for Apple platforms.
This library implements the client side of the Eternal Terminal wire protocol (protocol version 6): bootstrap command generation/parsing, encrypted transport, reconnect/resume, terminal I/O, and port forwarding. The server, an SSH implementation, and terminal UI/rendering are intentionally out of scope so consumers can integrate their preferred SSH stack and renderer.
Features
- Wire-compatible with the C++
etserver(verified end-to-end against Eternal Terminal 7.0.0) - Pure Swift XSalsa20-Poly1305, byte-compatible with libsodium
crypto_secretbox— no runtime crypto dependency - Seamless reconnection and process relaunch recovery using sequence-numbered ciphertext checkpoints
- Terminal session API: async/await,
AsyncStreamoutput, keystroke input, window resize - SSH bootstrap adapter with bring-your-own-SSH execution
- Forward and reverse port tunnels, port ranges, Unix sockets, jumphost support
- Split modules:
ETCrypto— pure Swift XSalsa20-Poly1305 and nonce managementETCore— protobuf messages, packets, framing, and reliable catchupETTransport— internal transport abstraction and Network.framework implementationETBootstrap— injectedetterminallaunch command and credential parserETSession— connection lifecycle, terminal API, forwarding, and jumphost support
- Real local
etserverE2E test harness - Release-mode benchmarks with a libsodium baseline
Platforms
- iOS 16+
- macOS 13+
- Swift tools 6.0+
Installation
Add to Package.swift:
dependencies: [
.package(url: "https://github.com/wiedymi/swift-et", from: "0.1.5")
]
Then add ETSession and ETBootstrap to your app target dependencies:
.target(
name: "YourApp",
dependencies: [
.product(name: "ETSession", package: "swift-et"),
.product(name: "ETBootstrap", package: "swift-et")
]
)
Usage
Apps normally import the session and bootstrap surfaces:
import ETBootstrap
import ETSession
You can supply credentials acquired out of band:
let session = try ETTerminalSession(
host: "example.com",
port: 2022,
clientID: clientID,
passkey: passkey
)
try await session.connect()
Task {
for await data in session.output {
renderer.feed(data)
}
}
try await session.send(Data("ls -la\n".utf8))
try await session.resize(
rows: 40,
cols: 120,
pixelWidth: 1440,
pixelHeight: 900
)
Bootstrap
ETBootstrap mirrors the C++ client's etterminal command and IDPASSKEY: parser. The
library never opens SSH itself; inject your existing SSH client:
struct AppSSHExecutor: ETBootstrapExecutor {
let ssh: MySSHClient
func run(command: String) async throws -> String {
try await ssh.run(command, captureOutput: true)
}
}
let session = ETTerminalSession(
host: "example.com",
port: 2022,
bootstrapExecutor: AppSSHExecutor(ssh: ssh),
bootstrapOptions: ETBootstrapOptions(
term: "xterm-256color",
serverFifo: "/tmp/etserver.fifo"
)
)
try await session.connect()
Port forwarding:
let session = try ETTerminalSession(
host: "example.com",
port: 2022,
clientID: clientID,
passkey: passkey,
tunnelSpecification: "8080:8080",
reverseTunnelSpecification: "9090:9090"
)
The full lifecycle (bootstrapping, connecting, connected, disconnected,
reconnecting, and terminal states) is observable via session.stateChanges. If your network
monitor reports a meaningful path change, nudge recovery without waiting for the normal retry:
await session.notifyNetworkPathChanged()
To resume the same server-side session after an app relaunch, persist
ETSessionCheckpoint separately from the passkey, then restore both:
let checkpoint = try await session.prepareForApplicationBackground()
// Persist checkpoint; keep the passkey in Keychain or another credential store.
let restored = try ETTerminalSession(
host: "example.com",
clientID: clientID,
passkey: passkey,
checkpoint: checkpoint
)
try await restored.connect()
If the process remains alive, call resumeFromApplicationBackground() after foregrounding.
Testing
swift test
End-to-end tests against a real etserver (brew install MisterTea/et/et):
ET_INTEGRATION=1 swift test --filter ETIntegrationTests
Benchmarks:
swift run -c release Benchmarks
License
MIT