Documentation
SwiftTUI documentation
Organized by what you're doing: your first hour, then the reference guides for views, state, and focus, charts, and what lies beyond the terminal. The module-by-module API reference is at the end.
Your first hour
Read these in order. Each one picks up where the last left off, from an empty package to an app that handles state, focus, and the terminal's own rules.
- 01
Add it to your app
Pick a toolchain, add the package, paste the counter, swift run.
- 02
Authoring Views
Compose containers, local state, focused controls, and modifiers around a body-driven tree.
- 03
State, Environment, and Focus
State, observation, environment, and focus share one runtime invalidation path.
- 04
Running Apps
The @main entry point, the standard flags, exit keys, and rendering one frame without a TTY.
- 05
Coming from SwiftUI
What transfers unchanged, which reflexes need retraining, and what is not here yet.
Setup / Swift 6.4
A toolchain and an executable package.
You can build from the command line on macOS, Linux, or Windows. Choose a Swift 6.4 toolchain before you begin.
macOS or Linux
Install Swift with swiftly. On macOS, an Xcode installation with Swift 6.4 also works.
Windows
Follow the Swift installation guide for the toolchain and its required build tools.
- Run
swift --versionto check your active toolchain. - In a new
MyTerminalAppdirectory, runswift package init --type executable. - Replace
Package.swiftwith the manifest below. - Replace the generated executable source with the complete counter example. Save it as
Sources/MyTerminalApp/CounterApp.swiftand remove the generated entry-point file, so only the counter’s@mainremains. - Run
swift run. Your app is ready for the next guide.
// swift-tools-version: 6.4
import PackageDescription
let package = Package(
name: "MyTerminalApp",
platforms: [.macOS(.v15)],
dependencies: [
.package(
url: "https://github.com/SwiftTUI/swift-tui",
.upToNextMinor(from: "0.15.1")
),
],
targets: [
.executableTarget(
name: "MyTerminalApp",
dependencies: [
.product(name: "SwiftTUI", package: "swift-tui"),
]
),
]
)Then read Authoring Views, or run the maintained counter directly.
Build your interface
Views, controls, drawing, and animated images. Read the guides as you need them.
Forms and Controls
Compose buttons, pickers, toggles, sliders, and text entry into a working form.
Commands and Key Input
Focus-scoped arrows and Escape, keyboard shortcuts, submit actions, and command palettes.
Scrolling
Finite viewports, compositional lazy stacks, nested wheel routing, indicators, and scrolling from code.
Animating Views
State animation, default fades, numeric text, nested matched geometry, keyframes, and reduced motion.
Navigation and Tabs
Typed navigation paths, destinations, tab selection, and view lifetime.
Animated Images and GIFs
Decode and author frames, control finite or continuous playback, and preserve GIF loop metadata on export.
The Style System
All 28 open style families in one place: built-ins, scoping, custom conformances, routes, theming, diagnostics, and tests.
Styling and Theming
Colors, semantic roles, gradients, the theme model, and your first custom button style.
Authoring Styles
The contract every style family shares: body-producing and presentation-value styles, route wrappers, and what a style may change.
Testing Styles
Exercise custom styles with fixture configurations, snapshots, and runtime route checks.
Understanding Focus
The runtime focus model for input routing, state control, and context export.
Lists and Tables
Collections with authored row content, selection, and viewport-backed data sources.
Geometry and Preferences
Anchor preferences let a subtree publish geometry that other views resolve after layout.
Shapes
Arcs and angles, fills and strokes, shape clipping, and compatible-topology path animation.
Aspect-correct shapes
Cell pixel metrics keep circles circular across terminal fonts and hosts.
Pointer and Canvas
One continuous cell coordinate space for gestures, hover, and drawing.
Accessibility
Semantic metadata for terminal screen readers, browser ARIA trees, VoiceOver, and TalkBack.
Custom Dynamic Properties
Build your own property wrappers on the DynamicProperty extension point.
State Keying
How @State storage is keyed across evaluations, and where owners survive lazy seams.
Dormant Tab State
What happens to a tab's persistent state while the tab is not selected.
Dismissal Is Data
Presentations are driven by Boolean bindings and identifiable items, not hidden stacks.
Charts
Sparklines, bar and line charts, heatmaps, meters, and calendar views
ship separately as swift-tui-charts, composed on the same view surface.
At run time
What a running terminal app reads and can do, from the SwiftTUIRuntime catalog.
Performance for App Authors
Stable identity, certified memo reuse, lazy content, and a measurement-led profiling workflow.
Logging and Diagnostics
Safe logging while the app owns the screen, runtime issues, traces, and debug bundles.
Testing Your App
Render deterministic frames without a TTY and test state, layout, and interaction.
Distributing Your App
Package a native executable, standard flags, shell completions, and platform requirements.
Environment Variables
Every SWIFTTUI_* environment variable the framework reads, grouped by subsystem.
Terminal Handoffs
Temporarily hand the interactive terminal back to the user's shell mid-run.
Terminal Embedding
Host external terminal programs with SwiftTUITerminalView from the separate terminal-view package.
Beyond the terminal
Terminal first, not terminal only. The same app runs in a browser, inside native SwiftUI windows, and on Android; these guides own that path and its platform notes.
Adapting an Interface to Its Host
One shared tree with touch targets, keyboard access, navigation, and scrolling suited to its host.
Deploying to the Browser
Serve a local app with --web or publish a static WASI bundle with the browser host packages.
Embedding in SwiftUI
Native macOS and iOS hosting, touch panning, text input, and optional keyboard controls.
Hosts and Platforms
The browser (--web and static WASI bundles), native SwiftUI windows, and Android, with the support matrix.
Runner and Host Integration
How apps launch through runner products or live inside host products.
Choosing Modules and Platforms
One dependency and one import for most apps, plus the product matrix when you need a narrower build.
Concepts and background
What You Can Build
Drawing, animation, scrolling workspaces, and interaction, with examples and links into the guides.
Public Module Map
Generated product ownership, supported direct imports, and transitive re-exports from source.
Differences from SwiftUI
The primer: what transfers, and the deliberate terminal-native rereadings.
Under the hood
An interactive walkthrough of the frame pipeline, from body to terminal cells.
Runtime Render Pipeline
The developer-level reference for the same pipeline: phases, products, and commit policy.
About SwiftTUI
Why the framework exists and what it optimizes for.
Divergences and gaps
The public register of API departures from SwiftUI and known gaps at HEAD.
API reference by module
The combined DocC archive documents each module. Most app code touches only the first row.
What you import
- SwiftTUI — the batteries-included app product
- SwiftTUIViews — views, controls, layout, state, focus
- SwiftTUIRuntime — scenes, run loop, host integration
- SwiftTUICharts — charts and compact metrics
- SwiftTUITerminalView — embedded terminal program panes
Hosts and opt-in products
- SwiftTUICLI — terminal-only runner
- SwiftTUIWebHostCLI — terminal runner with --web
- SwiftTUIArguments — SwiftTUIOptions and command parsing
- SwiftTUIWebHost — localhost browser host
- SwiftTUIWASI — WASI and browser builds
- SwiftTUIAndroidHost — Android embedding
- SwiftTUIAnimatedImage — animated GIF and image views
- SwiftTUIProfiling — opt-in profiling and diagnostics
- SwiftUIHost — native SwiftUI embedding (separate package)
The last group declares types that reach app code through re-export: CellSize, Alignment, PreferenceKey, SwiftTUIOptions. Their pages document symbols you use, behind imports you never write.