SwiftUI
SwiftUI integration starts with TerminalViewState. It owns the controller, exposes observable terminal state, and tracks the current TerminalSurface after a platform view attaches.
State
import SwiftUI
import GhosttyTerminal
struct TerminalScreen: View {
@StateObject private var terminal = TerminalViewState()
var body: some View {
TerminalSurfaceView(context: terminal)
.navigationTitle(terminal.title)
}
}
Observable properties include title, surfaceSize, isFocused, bellCount, lastBellAt, desktop notification metadata, workingDirectory, and command-finished metadata.
View
TerminalSurfaceView embeds the platform terminal view and adopts the current SwiftUI color scheme. This wrapper requires iOS 15, macOS 13, Mac Catalyst 15, or visionOS 1.
TerminalSurfaceView(context: terminal)
.onAppear {
terminal.configuration = TerminalSurfaceOptions(
backend: .inMemory(session),
fontSize: 13,
workingDirectory: "/"
)
}
Input
Input takes two paths, and they are not interchangeable. sendKey(_:) presses a key: the event takes libghostty's key path, so the terminal's key encoding applies (legacy, modifyOtherKeys, kitty). paste(text:) is the text path: a program that enabled bracketed paste receives it framed as a paste, so a \r in it lands in the shell's edit line instead of running the command. Both return true when Ghostty accepts the input; call them after the surface attaches.
@discardableResult
func run(_ command: String) -> Bool {
terminal.paste(text: command) && terminal.sendKey(.enter)
}
terminal.sendKey(.c, modifiers: .ctrl) // interrupt
terminal.sendKey(.tab, modifiers: .shift) // back-tab
terminal.sendKey(TerminalKeyPress(typing: "~")!) // Shift+backquote on a US layout
TerminalKey covers libghostty's full key set and uses the W3C UI Events code names. Keys with no macOS keycode (media keys, numpad extras) report hasPlatformKeycode == false and are rejected. send(_:) is the deprecated name of paste(text:).
Configuration
Use fluent configuration for common Ghostty settings, and custom(_:_:) for additional Ghostty config keys.
let config = TerminalConfiguration.default
.fontFamily("SF Mono")
.fontSize(13)
.windowPaddingX(8)
.windowPaddingY(6)
.custom("shell-integration", "detect")
terminal.setTerminalConfiguration(config)