UIKit & AppKit
TerminalView resolves to UITerminalView on UIKit and AppTerminalView on AppKit. Catalyst follows UIKit.
View setup
import GhosttyTerminal
let terminalView = TerminalView(frame: .zero)
let controller = TerminalController(configuration: .default)
terminalView.controller = controller
terminalView.configuration = TerminalSurfaceOptions(
backend: .inMemory(session)
)
terminalView.delegate = coordinator
The view owns the native input layer and the Metal-backed surface. TerminalController owns Ghostty app lifecycle, configuration resolution, themes, and surface creation.
Delegate callbacks
Adopt the delegate protocols that match your host UI. A single coordinator object can implement multiple protocols.
final class Coordinator:
TerminalSurfaceTitleDelegate,
TerminalSurfaceGridResizeDelegate,
TerminalSurfaceBellDelegate,
TerminalSurfaceLifecycleDelegate
{
func terminalDidChangeTitle(_ title: String) {}
func terminalDidResize(_ size: TerminalGridMetrics) {}
func terminalDidRingBell() {}
func terminalDidAttachSurface(_ surface: TerminalSurface) {}
func terminalDidDetachSurface() {}
}
Programmatic input
Both platform views press keys through sendKey(_:) and paste text through paste(text:). A key press takes libghostty's key path and is encoded the way the terminal asked for; a paste takes the text path and is framed as a paste when the program enabled bracketed paste — so Enter, Tab, and Ctrl chords are keys, never text. sendText(_:) is the deprecated name of paste(text:).
terminalView.paste(text: "ls -la")
terminalView.sendKey(.enter)
terminalView.sendKey(.c, modifiers: .ctrl)
iOS input
UITerminalView conforms to UITextInput. Hardware keys enter through pressesBegan, software keyboard text enters through insertText, and marked text flows through the shared IME handler.
On iOS, the input accessory bar provides Esc, Tab, arrows, symbols, Paste, and sticky Ctrl/Alt/Cmd modifiers. Configure colors through inputAccessoryStyle. The bar and its members exist on iOS only — not on Mac Catalyst, which imports UIKit too — so a target that also builds for Catalyst nests the exclusion inside the UIKit guard.
#if canImport(UIKit)
#if !targetEnvironment(macCatalyst)
terminalView.inputAccessoryStyle = .init(
regularBackground: .secondarySystemBackground,
regularForeground: .label,
activeBackground: .label,
activeForeground: .systemBackground
)
#endif
#endif
Hosts with a custom keyboard bar can hide the bundled accessory and drive sticky modifiers through the public sticky APIs.
#if canImport(UIKit)
#if !targetEnvironment(macCatalyst)
terminalView.inputAccessoryItems = []
#endif
#endif
The default button list is available as TerminalInputAccessoryItem.defaultItems. Hosts can provide a smaller list while keeping the bundled bar styling and key dispatch behavior.
#if canImport(UIKit)
#if !targetEnvironment(macCatalyst)
terminalView.inputAccessoryItems = [
.esc,
.ctrl,
.alt,
.command,
.divider,
.tab,
.arrowLeft,
.arrowRight,
.paste,
]
#endif
#endif