# SwiftTerm for native, embedded, and web terminals

> SwiftTerm is a Swift terminal engine with AppKit, UIKit, headless, WebAssembly, and Web frontends. Its UI-independent core suits SSH clients and custom terminal products, but developers still need to supply transport, rendering, and application configuration.

**migueldeicaza/SwiftTerm** — Xterm/VT100 Terminal emulator library in Swift with AppKit, UIKit, WebAssembly, Web, headless frontends.

- Repository: https://github.com/migueldeicaza/SwiftTerm
- Stars: 1,740 · Forks: 517
- Language: Swift
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/migueldeicaza-swiftterm

## SwiftTerm's split between terminal emulation and host UI

SwiftTerm solves a specific problem in Swift application development: it provides a terminal emulator that can run inside an application instead of requiring users to leave it for a standalone terminal. Its intended users include developers of commercial SSH clients, terminal multiplexers, console programs, browser-based terminals, and custom interfaces for Apple platforms. The README names Secure Shellfish, La Terminal, and CodeEdit as applications that have used the library.

The architecture separates a UI-agnostic terminal engine from its frontends. Based on the repository layout, the engine and shared library code are under `Sources/SwiftTerm`, macOS-specific code is under `Mac`, and iOS-specific code is under `iOS`. The AppKit and UIKit views consume the engine instead of implementing independent terminal emulators. A headless frontend is also bundled. TermKit supplies a terminal-over-console frontend, while Pane uses the engine for terminal multiplexing.

That separation matters when comparing SwiftTerm with alternatives. An Apple application can use the supplied platform views, while a server-side or custom frontend can connect its own transport and output model to the engine. It also defines what the library does not own. SwiftTerm is a terminal emulator rather than a complete SSH client. Local-process and SSH connection support are listed as features, but the README qualifies SSH integration as requiring some assembly. An application still needs to decide how it handles credentials, connection negotiation, host-key policy, reconnection, and session lifecycle.

For an existing terminal product, these boundaries should be treated as integration work rather than missing features. The engine interprets terminal input and output, while the containing application remains responsible for the network or process boundary and for the experience around that connection.

## VT100, xterm, Unicode, and BiDi handling

SwiftTerm processes control sequences and display data associated with VT100 and xterm-compatible programs. Its feature list covers ANSI colors, 256-color output, TrueColor, bold, italic, underline, strikethrough, and dim or faint text. It supports mouse events, hyperlinks, remote-controlled resizing, and local resizing. These capabilities matter for interactive terminals because shells, full-screen programs, editors, and command-line utilities regularly change attributes, dimensions, and screen contents.

Text handling extends beyond individual Unicode scalars. The README identifies support for UTF, emoji, combining characters, grapheme clusters, and bidirectional scripts such as Arabic and Hebrew. It says the bidirectional implementation follows the terminal-wg BiDi recommendation and includes Arabic contextual shaping. On Apple platforms, the views use CoreText rendering, which the project associates with its hardened Unicode test suites.

SwiftTerm's history also explains part of its design. The repository history says it began as a Swift port of XtermSharp, which was based on `xterm.js`. Test cases have since been extracted from `xterm.js` and Ghostty, and the project relies extensively on `esctest`. The README states that SwiftTerm handles UTF, Unicode, and grapheme clusters better than XtermSharp and `xterm.js`, but that qualification does not extend to every terminal concern. Selection and accessibility are specifically identified as areas where it remains behind both comparison projects.

The core also recognizes image-oriented terminal protocols, including Sixel, iTerm2-style graphics, and Kitty graphics. Documented payloads include PNG through iTerm2 and Kitty, JPEG through iTerm2, and raw RGB or RGBA through Kitty. These protocols are useful for CLI image viewers, but support depends on the selected build and frontend.

## Full and Embedded targets for Swift deployments

SwiftTerm 2.0 provides an Embedded Swift mode with a narrower compatibility boundary. Selecting the `Embedded` package trait yields a Foundation-free, headless core. According to the README, this build omits Apple views, the local-process host, image decoders, and Kitty Clipboard. Embedded builds require Swift 6.3 or later.

The repository points developers to `Sources/SwiftTerm/Documentation.docc/PortableHosting.md` for portable host APIs and `Docs/embedded-swift.md` for the required trait, compiler, and target settings. This means the Embedded configuration is documented as a distinct build contract rather than an incidental platform fallback. An application cannot assume that every Full API is present merely because the package name is the same.

An Apple application can instead use the bundled AppKit or UIKit frontend. The feature list also identifies optional Metal-accelerated rendering for macOS, iOS, and visionOS. An Embedded Swift host retains terminal-oriented functionality such as input, selection, scrollback, and bracketed paste through its portable APIs, but it lacks the image and clipboard facilities associated with the Full build.

This distinction prevents a product from adopting desktop assumptions for every target. It also creates a feature decision. If an application treats inline images or Kitty Clipboard as core requirements, it cannot select Embedded and expect those capabilities to appear through an undocumented workaround. The target selection must match the actual product feature set before the application begins integrating the package.

## Installing SwiftTerm and performing a first project check

The README directs SwiftTerm 2.0 users to the API documentation and includes sample applications under `TerminalApp`. It does not provide an install command, package dependency declaration, or complete copy-and-paste first-use example. It would therefore be misleading to invent a Swift Package Manager URL or an exact `Package.swift` entry.

A practical first evaluation starts with the API documentation and the sample that matches the target. The macOS sample is described as having much of the functionality of macOS Terminal.app but no configuration UI. The iOS sample uses an SSH library because iOS has no native shell, and it includes a login interface for configuring the connection. An SSH product developer can inspect that sample to see how an application wraps SwiftTerm around a remote session. A local terminal project can begin with the macOS sample, although it must supply its own settings experience if required.

The repository also contains a Web terminal package under `TerminalApp/WebTerminal`. Its README says the package uses a Hummingbird server, WebSocket transport, and local shell PTY. The top-level README says `TerminalApp/WebTerminal/run.sh` starts it on localhost, but it does not state the invocation syntax or required runtime versions. The build instructions, pinned compiler and SDK pair, API details, limits, and tests are located in `Docs/wasm.md`.

One repository-level check is documented in the `Makefile`. The Unicode-width data can be checked for consistency with its generator:

```bash
make check-unicode-width
```

The target invokes `python3 scripts/regen_unicode_width_data.py --check`. A successful exit indicates that this specific consistency check completed. It does not prove that an application has integrated the engine correctly or that all target configurations compile.

## WebAssembly host responsibilities and deployment limits

The WebAssembly package provides an engine contract rather than a complete hosted terminal. According to the README, its ABI version 1 exposes copied render snapshots, generated reply bytes, and host-event queues. The host must supply a renderer and PTY transport. It is responsible for presenting engine state to the user and for moving terminal data between the browser or Node.js process and a pseudo-terminal.

The TypeScript package can load either a Full or Embedded WASM reactor. Full builds support PNG, Kitty, Sixel, iTerm graphics, and Kitty Clipboard. Embedded builds retain terminal input, selection, scrollback, and bracketed paste while omitting graphics and clipboard support. A Canvas 2D example demonstrates one possible rendering frontend, but it does not turn the engine into a self-contained hosted service.

This design can suit an application that already owns a server connection, session manager, WebSocket service, and canvas renderer. It also shifts several failure modes to that host. A terminal cannot behave correctly if the host stalls input, reports an incorrect size, loses WebSocket messages, or fails to render the snapshots it receives. Those responsibilities need to be tested separately from SwiftTerm's escape-sequence handling.

The documented `TerminalApp/WebTerminal` sample combines Hummingbird, WebSocket transport, and a local shell PTY. Teams adopting a production web terminal would need to replace or secure that local shell arrangement for their deployment model. The README does not document authentication, session isolation, resource limits, or production hardening for that sample, so those subjects should not be inferred from the existence of the package.

## Graphics protocols, testing assets, and emulation boundaries

SwiftTerm's compatibility work is visible in the repository rather than limited to its feature list. The `Makefile` includes targets for building and running a Swift fuzzer, running Ghostty fuzz corpora through `swift test`, fetching `esctest`, and running benchmarks from `Tools/SwiftTermBenchmarks`. The README says test cases were extracted from `xterm.js` and Ghostty and that the project relies extensively on `esctest`.

These assets let adopters investigate terminal edge cases before integration, but they do not establish that every interactive program behaves identically to a native terminal. Selection and accessibility remain documented limitations relative to XtermSharp and `xterm.js`. Software may also use timing behavior, private sequences, or platform assumptions not represented in the included corpora.

Graphics support has a configuration boundary. Full Apple and WebAssembly configurations can handle several image protocols, while the Embedded build omits image decoders and graphics. For iTerm2 images, the Apple views use the system image decoder. PNG and JPEG are identified as the tested formats for the supported image paths, so products expecting another decoder should verify that path against the API documentation.

The README describes `Terminal` instances as thread-safe, which can help an application separate engine access from UI work. Optional Metal rendering is documented for macOS, iOS, and visionOS. Neither feature resolves application-level integration errors such as omitted keyboard input, incorrect terminal dimensions, or incomplete selection behavior.

## Maintenance, 2.0 upgrades, and licensing boundaries

The repository is not archived, and its last push was on 2026-10-15. Recent tags include `v1.99.0` on 2026-10-08, described as a preview before 2.0, plus `v1.20.0` and `v1.19.0` from 2026-08-18. The default branch, README, and API documentation describe the 2.0 API, while the README says developers who need the old API should use the `v1.x` branch or a tagged 1.x release.

An existing SwiftTerm 1.x integration therefore faces an explicit migration decision rather than only a routine version update. The README links a migration guide for moving from 1.0 to 2.0. That guide is the appropriate starting point when an application depends on the earlier API. Before changing versions, a developer should also compare the current target configuration with the Full or Embedded features required by the product.

The repository's maintenance assets include tests, fuzz targets, benchmark directories, Unicode-width regeneration scripts, and compatibility corpora. Those files impose additional review work when adopting a new revision. Protocol changes, platform support, generated data, and API migration can affect an application even when its visible terminal interface appears unchanged.

SwiftTerm uses the MIT license. That permits use, modification, distribution, and sublicensing subject to its conditions, including preservation of the copyright and license notice. The library license does not determine the terms of separate SSH libraries, host applications, sample dependencies, or platform components used alongside SwiftTerm.

## SwiftTerm, xterm.js, and full terminal applications compared

The closest documented comparison is `xterm.js`, which also forms part of SwiftTerm's lineage. SwiftTerm began as a Swift port of XtermSharp, and XtermSharp was based on `xterm.js`. The README attributes stronger Unicode and grapheme handling and more complete emulation coverage to SwiftTerm, while explicitly identifying selection and accessibility as exceptions. For a Swift team sharing terminal behavior across macOS, iOS, and WebAssembly, that distinction can favor one emulation engine across several frontends.

 SwiftTerm's WebAssembly package delegates rendering and PTY transport to the host, requiring a Swift-to-WebAssembly integration and TypeScript package. A team with an established JavaScript terminal, canvas renderer, and WebSocket PTY may have less reason to introduce WebAssembly. A Swift-heavy application may prefer SwiftTerm because its native frontends and engine share the same language.

A complete SSH application is another alternative. SwiftTermApp is described as a proof of concept with a proper configuration UI, while SwiftTerm itself is a library. Pane is relevant when terminal multiplexing is the product rather than an embedded application feature. Tecolot is described as a macOS Terminal.app replacement. The correct choice follows the missing responsibility: use an application when configuration and session UX dominate, `xterm.js` when browser integration dominates, Pane for multiplexing, and SwiftTerm when a reusable Swift emulation engine is central.

## Conclusion

SwiftTerm is appropriate for Swift developers who need a terminal engine inside an SSH client, embedded application, multiplexer, or browser terminal. It is a poor fit for teams seeking a turnkey terminal application, a complete SSH implementation, or a hosted web terminal, since SwiftTerm does not remove those responsibilities. Before adoption, inspect the SwiftTerm 2.0 API documentation, choose the correct Full or Embedded configuration for the target, and verify that the required graphics protocols, image formats, and host transport match the product.

## FAQ

### Does SwiftTerm include a complete SSH client?

SwiftTerm supports local-process and SSH connections, but the README says SSH integration requires some assembly. The project is principally a terminal emulator rather than a complete SSH product.

### Can SwiftTerm run in Embedded Swift?

Yes. The `Embedded` package trait selects a Foundation-free, headless core requiring Swift 6.3 or later. It omits Apple views, local-process hosting, image decoders, and Kitty Clipboard.

### Does SwiftTerm work with WebAssembly and Node.js?

The project supplies browser and Node.js engines with ABI version 1. Their host must provide a renderer and PTY transport, and the TypeScript package can load either a Full or Embedded WASM reactor.

### Does the Embedded build support terminal images?

No. Embedded builds omit graphics and clipboard support. Full builds support PNG, Kitty, Sixel, iTerm graphics, and Kitty Clipboard, subject to the selected frontend.

### How should a SwiftTerm 1.x integration move to 2.0?

The README documents the 2.0 API and links a migration guide for projects using 1.0. Applications that must remain on the old API should use the `v1.x` branch or a tagged 1.x release.

## Sources

- [Issues](https://github.com/migueldeicaza/SwiftTerm/issues)
- [License: MIT](https://github.com/migueldeicaza/SwiftTerm/blob/main/LICENSE)
- [migueldeicaza/SwiftTerm on GitHub](https://github.com/migueldeicaza/SwiftTerm)
- [README](https://github.com/migueldeicaza/SwiftTerm/blob/main/README.md)
- [Releases](https://github.com/migueldeicaza/SwiftTerm/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/migueldeicaza-swiftterm
