Tip
☕ Support TUIkit Development
If you enjoy TUIkit and find it useful, consider supporting its development! Your donations help cover ongoing costs like hosting, tooling, and the countless cups of coffee that fuel late-night coding sessions. Every contribution, big or small, is greatly appreciated and keeps this project alive. Thank you! 💙
Important
This project is currently a WORK IN PROGRESS! I strongly advise against using it in a production environment because APIs are subject to change at any time.
A SwiftUI-like framework for building Terminal User Interfaces in Swift: no ncurses, no C dependencies, just pure Swift.
TUIkit lets you build TUI apps using the same declarative syntax you already know from SwiftUI. Define your UI with View, compose views with VStack, HStack, and ZStack, style text with modifiers like .bold() and .foregroundColor(.red), and run it all in your terminal.
import TUIkit
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State var count = 0
var body: some View {
VStack(spacing: 1) {
Text("Hello, TUIkit!")
.bold()
.foregroundStyle(.cyan)
Text("Count: \(count)")
Button("Increment") {
count += 1
}
}
.statusBarItems {
StatusBarItem(shortcut: "q", label: "quit")
}
}
}Viewprotocol: the core building block, mirroring SwiftUI'sView@ViewBuilder: result builder for declarative view composition@State: reactive state management with automatic re-rendering@Environment: dependency injection for theme, focus manager, status barAppprotocol: app lifecycle with signal handling and run loop
- Primitive views:
Text,EmptyView,Spacer,Divider,Image(ASCII art rendering, multiple color modes, async loading) - Layout containers:
VStack,HStack,ZStack,LazyVStack,LazyHStackwith alignment and spacing - Interactive:
Button,ButtonRow,Toggle(default, checkbox, switch styles),Menu,TextField,SecureField,Slider,Stepper,RadioButtonGroupwith keyboard navigation - Data views:
List,Table,Section,ForEach,NavigationSplitView,ContentUnavailableView - Containers:
Alert,Dialog,Panel,Box,Card - Feedback:
ProgressView(5 bar styles),Spinner(animated) StatusBar: context-sensitive keyboard shortcuts with.compactand.borderedstyles
- Text styling: bold, italic, underline, strikethrough, dim, blink, inverted
- Full color support: ANSI colors, 256-color palette, 24-bit RGB, hex values, HSL
- Theming: 6 predefined palettes (Green, Amber, Red, Violet, Blue, White)
- Border styles:
line,rounded,doubleLine,heavy,none - List styles:
PlainListStyle,InsetGroupedListStylewith alternating rows - Badges:
.badge()modifier for counts and labels on list rows
- Toast-style notifications: transient alerts via
.notificationHost()modifier
- 5 languages built-in: English, German, French, Italian, Spanish
- Type-safe string constants: Compile-time verified
LocalizationKeyenum - Persistent language selection: Automatic storage with XDG paths
- Fallback chain: Current language → English → key itself
- Thread-safe operations: Safe language switching at runtime
- Lifecycle modifiers:
.onAppear(),.onDisappear(),.task() - Key handling:
.onKeyPress()with modifier keys (ctrl, alt, shift) and function keys F1–F12 - Storage:
@AppStoragewith JSON file backend (XDG paths) andUserDefaultsbackend - Preferences: bottom-up data flow with
PreferenceKey - Focus system: Tab/Shift+Tab navigation,
.focusSection()for grouped areas - Render caching:
.equatable()for subtree memoization
swift run TUIkitExamplePress q or ESC to exit.
Install the tuikit command and create a new project:
curl -fsSL https://github.com/ghraw/phranck/TUIkit/main/project-template/install.sh | bash
tuikit init MyApp
cd MyApp && swift runSee project-template/README.md for more options (SQLite, Swift Testing).
Add TUIkit to your Package.swift:
dependencies: [
.package(url: "https://github.com/phranck/TUIkit.git", branch: "main")
]Then add it to your target:
.target(
name: "YourApp",
dependencies: ["TUIkit"]
)Tip:
import TUIkitre-exports all sub-modules. For finer control you can import individual modules:TUIkitCore,TUIkitStyling,TUIkitView, orTUIkitImage.
TUIkit includes predefined palettes inspired by classic terminals:
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.palette(SystemPalette(.green)) // Classic green terminal
}
}Available palettes (all via SystemPalette):
.green: Classic P1 phosphor CRT (default).amber: P3 phosphor monochrome.red: IBM 3279 plasma.violet: Retro sci-fi terminal.blue: VFD/LCD displays.white: DEC VT100/VT220 (P4 phosphor)
TUIkit includes comprehensive i18n support with 5 languages and type-safe string constants:
import TUIkit
struct MyView: View {
@Environment(\.localizationService) private var localization
var body: some View {
VStack {
// Type-safe localized strings
Text(localized: LocalizationKey.Button.ok)
LocalizedString(LocalizationKey.Error.notFound)
// Switch language at runtime
Button("Deutsch") {
localization.setLanguage(.german)
}
}
}
}Supported languages: English, Deutsch, Français, Italiano, Español
For complete documentation, see Localization Guide in the DocC documentation.
- Modular package: 5 Swift modules with no native targets (see Project Structure below)
- No singletons for state: All state flows through the Environment system
- Pure ANSI rendering: No ncurses or other C dependencies
- Linux compatible: Works on macOS and Linux (XDG paths supported)
- Value types: Views are structs, just like SwiftUI
Sources/
├── TUIkitCore/ Primitives, key events, frame buffer, concurrency helpers
├── TUIkitStyling/ Color, theme palettes, border styles
├── TUIkitView/ View protocol, ViewBuilder, State, Environment, Renderable
├── TUIkitImage/ ASCII art conversion and bounded pure Swift PNG/JPEG decoding
├── TUIkit/ Main module: App, Views, Modifiers, Focus, StatusBar, Notification
│ ├── App/ App, Scene, WindowGroup
│ ├── Environment/ Environment keys, service configuration
│ ├── Focus/ Focus system and keyboard navigation
│ ├── Localization/ i18n service, type-safe keys, translation files (5 languages)
│ ├── Modifiers/ Border, Frame, Padding, Overlay, Lifecycle, KeyPress
│ ├── Notification/ Toast-style notification system
│ ├── Rendering/ Terminal, ANSIRenderer, ViewRenderer
│ ├── StatusBar/ Context-sensitive keyboard shortcuts
│ └── Views/ Text, Stacks, Button, TextField, Slider, List, Image, ...
└── TUIkitExample/ Example app (executable target)
Tests/
├── TUIkitCoreTests/ Core primitives and input parsing
├── TUIkitStylingTests/ Colors, palettes, and theme behavior
├── TUIkitViewTests/ View infrastructure, state, and rendering caches
├── TUIkitImageTests/ Image data, conversion, loading, and decoding
└── TUIkitTests/ Public API and runtime integration
Test discovery covers 1305 tests across all isolated targets.
- Swift 6.0+ for package consumers; development and CI use exactly Swift 6.0.3
- macOS 14+ or Linux
Image decoding supports static PNG and JPEG input and always produces non-premultiplied 8-bit RGBA pixels. Audited decoder and checksum sources are vendored as namespaced Swift targets; the package graph contains no C, C++, or native decoder target.
- Tests use Swift Testing (
@Test,#expect): run withswift test - Run the complete local macOS/Linux quality gate with
./scripts/test-linux.sh - Generate the deployable DocC archive with
./scripts/generate-documentation.sh - All 1305 tests run through Swift Testing; suites that isolate shared state run serially
- The
Terminalclass handles raw mode and cursor control via POSIXtermios
This repository has been published under the MIT license.