SwiftTUI — a Terminal UI framework for Swift

Hey everyone — I'd like to introduce SwiftTUI. (tagline: SwiftUI's semantics drawn to terminal cells.)

Terminal apps are having a renaissance. The Rust and Go communities in particular[1] have built a lot of impressive tools, and neat niche apps.

Swift has felt weirdly underrepresented: despite the language being at a perfect level of abstraction, having a powerful package ecosystem, and providing good platform support, Swift-based TUI apps are scarce.

Why SwiftTUI

SwiftTUI aims to make TUI development trivially accessible to the Swift community.

It implements a surprisingly powerful portion of the SwiftUI API you already know, and makes spinning up a TUI a three step process:

  1. swift package init
  2. an spm dependency + import
  3. @main struct MyApp: App { /*…*/ }.

Key Features

  • SwiftUI-faithful API and behavior[2]:
    • State@State, @Environment, @Binding, @Observable,@FocusState, etc.
    • Updatesvar body: some View, .task(id:), .onChange(of:), etc.
    • LayoutV/H/ZStack, ScrollView, GeometryProxy, Shape, overlays, alignment guides, etc.
    • Gestures and keys — click/tap, hover, drag, key commands
    • Animations + transitions — PhaseAnimator, .bouncy,
  • Modern feature support, with graceful fallback behavior. The framework handles terminal negotiation and the ANSI/Xterm/OSC/TTY details.
  • Cross platform: the frameworks supports macOS, Linux, and soon Windows[3]
    • … and builds native[4] GUIs for for Web, iOS, macOS, and Android.
  • Swift 6.3 implementation, open source, with strict concurrency — and as many of SwiftUI's optimizations, tricks, and structural insights as one can find by trawling the public web.[5]

Where to find it

SwiftTUI is a young project — but it's very ready for testing and feedback.
Take a look and and let me know how it goes.

This 'SwiftTUI' is not the first framework to use the name. Shout-out to Rens Breuer, whose earlier SwiftTUI implementation and associated articles on structural diffing and the attribute graph I have learned a lot from — and who now works on the SwiftUI team itself.


  1. Here's one curated index that filters by language https://terminaltrove.com/explore/ ↩︎

  2. There are changes to represent the realities of the terminal — but even the divergences aim to follow the spirit of the API ↩︎

  3. Very soon! It's on main, but not in a tagged release ↩︎

  4. The cells are drawn directly. There's no xterm.js or libghostty. But the cells are still cells. This is a TUI framework after all :) ↩︎

  5. Because without them performance would be awful :). See Rens Breuer's diffing article for an example. ↩︎

35 Likes

Windows support has landed.
SwiftTUI terminal apps now for macOS, Linux, Windows, and WASI.

If you get a chance to take a look:

  • Try cloning the QuickStart swift-tui-counter-demo
  • Or just spin up your own app! SwiftUI syntax should get you there.

If so, let me know! Either just here, or open a GitHub issue on the repo to report anything funky — or just send your first impressions :)

5 Likes

I like the design and reuse the SwiftUI semantics, thanks for sharing

2 Likes

I'm loving this project so much. Looks like some serious work went into it already, thank you!

1 Like

I think text interfaces are an often unappreciated area, and I'm glad the AI coding tools have given them more visibility. The first time i saw Claude Code, I remember thinking that I haven't really seen such an advanced console app. (Not since DOS days at least, but certainly never on a Unix system).

I remember seeing rensbreur's version many years ago and thought it was a great idea. So I think I'm really glad you've taken up the mantle!

Not sure if it's useful, but it looks like there's another similar project that's still actively being developed:

3 Likes

TUIKit is cool. I'm super impressed by the documentation clarity.
It would be fun to collaborate!

In terms of comparing/contrasting the projects beyond platform support: SwiftTUI has a (potentially unreasonable!) emphasis on implementing SwiftUI functionality in the same way SwiftUI itself does. This puts a big performance burden on the framework (SwiftUI takes on a lot of complexity, and it does so in very sophisticated ways).

The potential downsides here are performance, binary size, bugs, etc — but the upside is the ability to re-implementing exciting functionality animations, gestures, etc. (and learning a lot in the process!)

3 Likes

Yeah, pretty cool. I was actually working on something like that too -- BlinkUI -- but man, it got messy fast. So I know the grind involved. Props for pulling it off!

2 Likes

I saw your project a few months ago — I really appreciate that!
SwiftTUI's still very WIP, though. (And I really need to build out a roadmap page somewhere!)

Hit me up if you're interested in collaborating! :)

1 Like

This is such a cool idea!! I love it. I will absolutely use it in one of my future projects.

1 Like

The dedication to matching SwiftUI's exact state management is insane (in a good way!).

I maintain an open source macOS/iOS network auditing engine called NetProof. We rely heavily on @MainActor and SwiftUI to render high frequency diagnostic probes and latency updates in real time.

We’ve been wanting to build a headless/CLI version for server environments, but I always dreaded rewriting the reactive state logic for the terminal. Your project might be exactly what we need.

I'm curious: how does SwiftTUI handle rapid, high frequency state updates (like streaming live ping/jitter metrics)?

If you're looking for a somewhat complex real world codebase to stress test your framework's performance, I’d love to try porting our diagnostic views over. Repo is here if you want to take a look at the UI complexity we are dealing with:

2 Likes

I'm very interested in finding real use cases that stress test SwiftTUI relative to what's possible in SwiftUI — both in performance and state churn terms, and more generally for API usability.

I would love to try to collaborate on, or actively provide framework support for, efforts like this. You can find me in the SwiftTUI Discord if you'd like to talk it over, and in the meantime I'll give your project a spin.

To answer your question directly: SwiftTUI coalesces changes received from @Observable models. I do expect to find (and fix!) new bottlenecks when working with high-frequency updates like what you're describing.

Coalescing @Observable changes makes total sense. That is exactly where I suspect we will hit the ceiling first, since our TestRunnerViewModel pumps out ping and jitter metrics every few hundred milliseconds during a live audit.

I will definitely hop into the Discord later today to chat about how we can approach this port.

When you give the repo a spin, just hit the Run Test button on the main view. It fires off a rapid batch of concurrent probes so you can immediately see the UI state churn we are dealing with. Let's see if we can break SwiftTUI! Catch you in the server.

I've spent the last month bringing SwiftTUI closer to 1.0.0 readiness, including a few notable changes which make the framework genuinely nicer to use:

Features:

  • A full style system; nearly every component now has an associated style protocol (whether SwiftUI exposes one or not)

Improvements and fixes:

  • Animations are much smoother, and evenly sampled to avoid backlog glitching
  • Key press events now bubble like their SwiftUI counterparts
  • Scroll views size and scroll properly when nested

We're still discovering new usability corner cases here and there, and making the occasional breaking change. (Huge thanks to anyone who found the framework here and opened an issue!) It's getting close!

If you've given it a spin I'd love to know! (And if you hit issues I'm in the project's Discord to get you unblocked.)

3 Likes