Skip to content

Repository files navigation

SwiftTUI

SwiftUI semantics, drawn in terminal cells.

Swift 6.3 Status License

SwiftTUI is a Swift framework for building terminal user interfaces on macOS, Linux, and Windows. You write View types with @State, stacks, controls, focus, gestures, and animation — the declarative model SwiftUI has proven at platform scale — and the framework owns layout, input, redraw, and the terminal itself. The result is one fast native binary.

Important

Beta, pre-1.0. The API has stabilized, but breaking changes may still land before 1.0.0.
All changes are documented in the CHANGELOG.
Pin with .upToNextMinor.

counter-demo

Try it first
This is is a real SwiftTUI app, compiled to WebAssembly and running live.
The guided introduction and API reference are at SwiftTUI.sh

The counter

This is the app behind the live demo, without the demo's ripple animation (full source):

import SwiftTUI

struct CounterView: View {
  @State private var count = 0

  var body: some View {
    VStack(spacing: 1) {
      TextFigure("\(count)", font: .future)
        .frame(minWidth: 14, alignment: .center)
      Button("Increment") { count += 1 }
        .buttonStyle(.bordered)
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}

@main
struct CounterApp: App {
  var body: some Scene {
    WindowGroup("Counter") { CounterView() }
  }
}

A frame is a pure function of the view tree and a size proposal, so this is exactly what that view renders at 40 columns (RenderOnce.print(CounterView(), width: 40), color off):

                  ┏━┓
                  ┃┃┃
                  ┗━┛

               ╭─────────╮
               │Increment│
               ╰─────────╯

Space activates the focused button and the figure redraws — only the cells that changed. Ctrl-C quits and restores your shell.

Run it

Any Swift 6.3+ toolchain builds and runs SwiftTUI apps from the command line on macOS 15+, Linux, and Windows 10 1809+ (swiftly, a current Xcode, or the swift.org installer). Add the package, depend on its SwiftTUI product, and swift run:

// Package.swift
.package(url: "https://github.com/SwiftTUI/swift-tui", .upToNextMinor(from: "0.9.11")),
// in your executable target:
.product(name: "SwiftTUI", package: "swift-tui"),

Or clone the demo's repo and run its terminal target:

git clone https://github.com/SwiftTUI/swift-tui-counter-demo
swift run --package-path counter counter

Why SwiftTUI

  • State in, screen out. Views are a pure function of your app's state: change a value and the runtime recomputes layout and rewrites exactly the cells that changed. No draw loop, no buffer diffing, no repaint bookkeeping.
  • The terminal, negotiated for you. Truecolor, Kitty and Sixel images, OSC 8 hyperlinks, and mouse reporting are probed per session and degrade gracefully: one binary is correct in kitty, a bare SSH session, or CI. Every app also ships --accessible, --cursor-follows-focus, --reduce-motion, --no-color, and --ascii. You write views, not escape codes.
  • One compiled binary, testable without a TTY. Swift 6 compiles your interface into a single executable with checked concurrency, and tests render and compare integer-cell frames like the one above with no terminal attached.

Coming from SwiftUI? The shape is the same; the terminal-native differences are deliberate and recorded — read Coming from SwiftUI and the divergence register. Choosing between TUI frameworks? See the comparison on swifttui.sh.

Built with SwiftTUI

GIF Editor csvui
GIF Editor — canvas, layers, a scrubbable timeline, pointer tools, undo, export csvui — a 34,000-row table browsed and edited in place
Terminal Workspace mrkdwn
Terminal Workspace — tabs, splits, and a command palette over embedded terminals mrkdwn — a responsive Markdown reader, shown reading this README

Every example runs from a fresh clone of swift-tui-examples.
Try swift run --package-path gallery gallery-demo for the gallery of SwiftTUI's interactive functionality. (See more in the showcase)

Beyond the terminal

Terminal first, not terminal only. The same App also runs in a browser — launch it with --web to serve it over localhost, or compile it with the SwiftTUIWASI product and ship it as a static bundle with @swifttui/web, which is what the live demo is — and inside native apps through swift-tui-swiftui (macOS, iOS) and swift-tui-android (arm64 preview). The browser paths paint to the DOM with a real accessibility tree; none of them is a terminal emulator. For narrower product graphs — the explicit SwiftTUICLI terminal runner, custom hosts, or one committed frame rendered without a TTY — start from Choosing Modules And Platforms; the full platform-by-product matrix (including the Windows notes) is Hosts And Platforms.

Documentation

Contributing

Small, well-scoped issues and pull requests are easiest to review. The repo uses the pinned Swift 6.3.3 toolchain through swiftly: swiftly run swift test for the unit tests, bun run test for the repo gate. Read CONTRIBUTING.md and AGENTS.md for the build, test, style, and pull-request rules, and open an issue for SwiftUI-style APIs you find missing or anything that gets in your way.

License

SwiftTUI first-party code is licensed under the MIT License (MIT). Vendored third-party code under Vendor/ keeps its own license and provenance notices. See LICENSE.

About

SwiftUI semantics, drawn in terminal cells — macOS/Linux/Windows/WASI

Topics

Resources

Contributing

Security policy

Stars

78 stars

Watchers

3 watching

Forks

Releases

Contributors

Languages