Faster than Ghostty, measured.
Parser and terminal-state throughput beat Ghostty on all 14 inputs by median, up to 3.8× on OSC-heavy output. Allocation budgets run in Release.
See the benchmarksA native terminal for Apple platforms
A Swift 6.4 terminal core with libghostty behavioral parity, rendered through Metal and CoreText. Native AppKit on macOS and UIKit on iPhone and iPad, with shells that outlive the window.
mise install && mise run app
macOS 27+ · iOS & iPadOS · visionOS · tvOS
The agent keeps the shell. Windows come and go.
# Every window is a SwiftMux workspace.
❯swmux new -s work
✓swiftmux-agent owns the PTY
✓Pane frames rendered by Metal
✓TERM=swmux-256color
❯swmux attach -t work
Reattached. The shell kept running while no window was open.
iPhone and iPad clients survive network changes.
Illustrative session · inside Swiftty, with the SwiftMux agent installed
Tested against real programs.
Recorded and replayed.
Native APIs. Measured gains.
Darwin PTYs, CoreText and Metal, with no portability layer.
Every improvement is
benchmarked.
Parser and terminal-state throughput beat Ghostty on all 14 inputs by median, up to 3.8× on OSC-heavy output. Allocation budgets run in Release.
See the benchmarksOne serial queue owns the parser and grid; the renderer draws immutable snapshots. Common ASCII, UTF-8, CSI and cell updates make zero steady-state allocations.
Read the architecture
A per-user agent owns shells, PTYs, history and layouts. Quitting detaches; tabs and
splits grow the same workspace. Reattach from the app or swmux.
RST/1 sends complete current screens over QUIC, not a byte log, so iPhone and iPad sessions survive Wi-Fi and cellular changes. No speculative echo.
Set up roamingEvery pane parses OSC 7501 status, shown or not. The toolbar counts Needs you requests; open, snooze or review them, or follow a deep link to the pane.
Open the inbox
config.js ships with typed swiftty.d.ts: output filters,
pane splits, status items, notifications and command, directory and status events. No
Node.js required.
More ways to make it yours
Run it on every Apple screen, configure it in JSONC, bring your own shell, or drive the engine from your own transport.
TerminalSession.receive(_:)
SwifttyEngine is headless; SwifttyCore adds rendering and
sessions. Feed bytes through receive, send input from
onWrite. Shell embeds it through its libghostty API.
-scheme SwifttyMobile
The UIKit frontend runs on iOS and iPadOS and builds for Mac Catalyst, visionOS and tvOS, where the focus engine and hardware keyboards provide input.
Build for mobileswsh -c 'echo $HOME'
swsh brings pipelines, ordered redirects, Darwin job control, functions,
subshells and native programmable completion, with no word splitting surprises.
~/.config/swiftty/config.jsonc
Comments, trailing commas and a published $schema for editor completion.
Settings writes back to the same file; Reload Configuration applies edits.
Settings › SSH Keys
Generate or import Ed25519 keys into the Keychain, device-only by default or opt in to iCloud Keychain. A missing key fails closed and never falls back to a password.
Manage SSH keysswmux new -s work -c ~/code
swmux attaches, lists, detaches and ends the same workspaces the app
shows, with a C-b prefix and up to 32 panes per workspace.
Working on durability? A separate swiftmux-gateway is building toward
sessions that survive app and gateway updates; it is installed explicitly and not yet
registered by the app installer.
Read the durability spec →
Release builds · Apple M5 Max
Same inputs, same machine, alternating runs.
Swift 6.4 against Ghostty built with
Zig ReleaseFast.
Parser and terminal-state throughput, by median.
Versus 18.6–21.3 ms for Ghostty 1.3.1, same display.
120×40 offscreen full redraw on a physical device.
| Input | Ghostty | Swiftty | Swiftty time relative to Ghostty | Relative |
|---|---|---|---|---|
| ascii | 99.0 ms | 93.8 ms | 105.6% | |
| compiler-log | 140.9 ms | 125.1 ms | 112.7% | |
| csi-heavy | 477.5 ms | 357.4 ms | 133.6% | |
| ghostty-osc | 4,104.0 ms | 1,092.8 ms | 375.6% | |
| ghostty-styled | 409.1 ms | 211.9 ms | 193.1% | |
| osc-heavy | 1,111.7 ms | 541.4 ms | 205.3% | |
| scroll | 406.4 ms | 303.9 ms | 133.7% | |
| unicode-joins | 348.2 ms | 258.6 ms | 134.7% | |
| utf8-cjk | 100.6 ms | 92.4 ms | 108.9% |
Medians of 20 alternating runs after two warmups, including startup and file I/O, reading 64 KiB chunks. Relative throughput is Ghostty time divided by Swiftty time.
Mixed-script UTF-8 has little margin (100.2%). The key-to-pixel probe uses synthetic keys and screen capture; physical-keyboard and photon-level latency have not been measured. All measurements →
From checkout to first prompt
Build from source with Xcode and mise, then install the app with its persistent SwiftMux agent.
Read the build guidemacOS 27+ · Xcode 27 · Swift 6.4
# Build and launch the macOS terminal.
git clone https://github.com/chr33s/swiftty.git
cd swiftty
mise install
mise run app
Use Xcode’s Swift 6.4 toolchain; mise.toml pins the other tools.
mise run test-native runs the full unit suite and real PTY sessions
with sh, vim, less, tmux and
top.
Build and test →
mise run install # or: mise run install --roaming
swmux new -s work # inside Swiftty
swmux list
Packages Swiftty.app with the bundled agent, signs it with your first
Developer ID identity (else ad hoc), installs it to /Applications and
registers the agent. --roaming also sets up swifttyd for
roaming clients.
SwiftMux →
Embedded by:
Shell, through its libghostty API. Configuration lives in
~/.config/swiftty/config.jsonc.