Skip to main content

OpenTUI Python

PyPI version Python License: MIT

A Pythonic port of OpenTUI — build rich terminal UIs in Python with reactive signals, flexbox layout, and a full component library.

OpenTUI is the rendering engine behind OpenCode. This package brings that same engine to Python: the native Zig core handles rendering and layout, while the Python layer provides an idiomatic API with signals, components, hooks, and async rendering.

Disclaimer: This is an independent community project. It is not affiliated with, endorsed by, or connected to OpenTUI, OpenCode, or Anomaly in any way. OpenTUI is developed by the anomalyco/opentui team and is used here under its MIT license.

Features

  • Reactive signals — fine-grained reactivity with Signal, computed, effect, and Expr operators
  • Flexbox layout — powered by Yoga via yoga-python
  • Rich components — Box, Text, Input, Textarea, Select, ScrollBox, Markdown, Code, Diff, and more
  • Native performance — Zig core with nanobind C++ bindings for rendering-critical paths
  • Full input handling — keyboard, mouse, and paste events
  • Image support — Kitty and SIXEL graphics protocols
  • Syntax highlighting — Tree-sitter integration for code blocks
  • 4,700+ tests — comprehensive parity with the OpenTUI core test suite

Installation

pip install opentui

With optional extras:

pip install opentui[images]        # Pillow for image support
pip install opentui[highlighting]  # Tree-sitter syntax highlighting
pip install opentui[dev]           # pytest, ruff, ty

Quick Start

import asyncio
from opentui import render, Box, Text, Signal, component, use_keyboard, use_renderer

count = Signal(0, name="count")

@component
def App():
    return Box(
        Text(lambda: f"Count: {count()}"),
        Text("Press +/- to change, q to quit"),
        padding=2, border=True, gap=1,
    )

def on_key(event):
    if event.name == "q":
        use_renderer().stop()
    elif event.name in ("+", "="):
        count.add(1)
    elif event.name == "-":
        count.add(-1)

async def main():
    use_keyboard(on_key)
    await render(App)

asyncio.run(main())

Reactive Patterns

OpenTUI provides three tiers of reactivity — choose the simplest one that fits:

Direct signal prop — pass a Signal directly to any supported prop for zero-overhead updates:

color = Signal("red", name="color")
Text("Hello", fg=color)  # updates paint when color changes

Lambda / callable — use a lambda for computed or derived values:

count = Signal(0, name="count")
Text(lambda: f"Count: {count()}")

.map() transform — transform a signal's value without a full lambda:

Text(count.map(lambda v: f"Count: {v}"))

Expr operators — signals support arithmetic and comparison operators that return reactive expressions:

doubled = count * 2              # Expr: evaluates to count() * 2
is_high = count > 5              # Expr: evaluates to count() > 5
label = count.if_("yes", "no")   # Conditional: "yes" if truthy, "no" otherwise

Batch updates — group multiple signal writes into a single notification pass:

from opentui import Batch

with Batch():
    x.set(1)
    y.set(2)  # subscribers only fire once, after the block

Control Flow

Conditional and list rendering with Show, Switch, Match, and For:

from opentui import Show, Switch, Match, For, Signal

visible = Signal(True, name="visible")
mode = Signal("home", name="mode")
items = Signal(["a", "b", "c"], name="items")

# Conditional rendering
Show(Text("Visible!"), when=visible)
Show(Text("Visible!"), when=visible, fallback=Text("Hidden"))

# Multi-branch conditional
Switch(
    Match(HomePage(), when=mode.map(lambda m: m == "home")),
    Match(Settings(), when=mode.map(lambda m: m == "settings")),
    fallback=Text("Not found"),
)

# Signal-keyed switch (fast path — no re-subscription on change)
Switch(on=mode, cases={
    "home": HomePage(),
    "settings": Settings(),
})

# List rendering
For(lambda item, i: Text(f"{i}: {item}"), each=items)

Components

Use @component to define reusable components. Each invocation gets its own reactive scope:

from opentui import component, Signal, Box, Text

@component
def Counter(label: str = "Count"):
    count = Signal(0, name="count")
    return Box(
        Text(count.map(lambda v: f"{label}: {v}")),
        border=True,
    )

For lower-level control, use Mount directly:

from opentui import Mount, Signal, Text

counter = Mount(lambda: Text(Signal(0, name="n").map(str)))

Layout

Component Description
Box Flexbox container with border, padding, background
ScrollBox Scrollable container with mouse wheel support

Text

Component Description
Text Styled text with wrapping, selection, and inline modifiers
Bold, Italic, Underline Inline text style modifiers
Span Colored inline text spans
Link Clickable terminal hyperlinks

Input

Component Description
Input Single-line text input
Textarea Multi-line editor with native buffer, undo/redo, and syntax highlighting
Select Dropdown selection list

Advanced

Component Description
Code Syntax-highlighted code block via Tree-sitter
Diff Side-by-side and unified diff viewer
Markdown Rendered markdown with headings, lists, tables, code blocks
LineNumberRenderable Line number gutter (pairs with Code or Textarea)
Slider Numeric value slider
TabSelect Tab selection bar
TextTable Tabular text layout with borders

Control Flow

Component Description
For Keyed list rendering with efficient reconciliation
Show Conditional rendering
Switch / Match Multi-branch conditional rendering
Lazy Deferred child construction (built on first render)
Portal Render children into a different mount point
Dynamic / MemoBlock Dynamic node selection and memoized subtrees

Signals

from opentui import Signal, computed, effect

name = Signal("world", name="name")
greeting = computed(lambda: f"Hello, {name()}!")

effect(lambda: print(greeting()))  # prints "Hello, world!"
name.set("Python")                 # prints "Hello, Python!"

Hooks

from opentui import use_keyboard, use_mouse, use_paste, use_on_resize, use_timeline

use_keyboard(lambda event: print(event.name))
use_mouse(lambda event: print(event.type, event.x, event.y))
use_paste(lambda event: print(event.text))
use_on_resize(lambda cols, rows: print(f"{cols}x{rows}"))

timeline = use_timeline()
timeline.add(target, {"opacity": 1.0}, duration=300)

Development

git clone https://github.com/banditburai/opentui-python.git
cd opentui-python
uv sync --all-extras

# Run tests
uv run pytest tests/ -v

# Lint & type checking
uv run ruff check
uv run ruff format --check
uv run ty check

Test coverage

The test suite includes 4,700+ tests: a comprehensive 1:1 port of the OpenTUI core test suite plus Python-specific tests for signals, FFI bindings, and the reconciler.

Architecture

The package is a hybrid: the OpenTUI Zig core handles rendering, text buffers, and layout at native speed, while the Python layer implements the component model, signals runtime, reconciler, and public API. Performance-critical paths are additionally accelerated with nanobind C++ extensions.

OpenTUI Core (Zig) → libopentui.so/dylib
    ↓
nanobind C++ bindings (opentui_bindings)
    ↓
Python API (opentui)
    ├── signals       — Signal, computed, effect, Expr operators
    ├── components/   — Box, Text, Input, ScrollBox, Code, Diff, ...
    ├── hooks         — use_keyboard, use_mouse, use_paste, use_on_resize
    ├── renderer      — CliRenderer, Buffer, TerminalCapabilities
    ├── reconciler    — Component tree diffing (idiomorph-inspired)
    └── layout        — Yoga flexbox integration via yoga-python

What's native vs. Python:

  • Native (Zig via nanobind): text buffers, edit buffers, editor views, hit testing, graphics encoding, buffer rendering, syntax styling
  • C++ extensions: signal→prop bindings, reconciler patching, render tree dispatch
  • Python: signals runtime, component tree, event loop, input parsing, all public API

Pre-built wheels are provided for Linux (x86_64, aarch64), macOS (x86_64, arm64), and Windows (x64) on Python 3.12+.

License

MIT — see LICENSE.

OpenTUI core is also MIT licensed. yoga-python is MIT licensed.

Metadata

Release files for opentui 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for opentui 0.1.2
File Size Uploaded
opentui-0.1.2.tar.gz 804.4 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for opentui 0.1.2
File
opentui-0.1.2-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
opentui-0.1.2-cp313-cp313-manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64 Details
opentui-0.1.2-cp313-cp313-manylinux_2_28_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ ARM64 Details
opentui-0.1.2-cp313-cp313-macosx_13_0_x86_64.whl CPython 3.13 CPython 3.13 macOS 13.0+ x86-64 Details
opentui-0.1.2-cp313-cp313-macosx_13_0_arm64.whl CPython 3.13 CPython 3.13 macOS 13.0+ ARM64 Details
opentui-0.1.2-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
opentui-0.1.2-cp312-cp312-manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64 Details
opentui-0.1.2-cp312-cp312-manylinux_2_28_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ ARM64 Details
opentui-0.1.2-cp312-cp312-macosx_13_0_x86_64.whl CPython 3.12 CPython 3.12 macOS 13.0+ x86-64 Details
opentui-0.1.2-cp312-cp312-macosx_13_0_arm64.whl CPython 3.12 CPython 3.12 macOS 13.0+ ARM64 Details

Total release size: 17.4 MB

Release files / opentui-0.1.2.tar.gz

Download URL opentui-0.1.2.tar.gz
Size 804.4 kB
Tags Source
SHA-256 checksum
How to use checksums
7f3035dabf92b115c62b4a5e53806af1cf528a172406035c7344ab69656ed0ac
BLAKE2b-256 checksum
How to use checksums
dc98c061d65ce35b48ce4e72a064bca29beb361a39d1a1dd47c56d8ef0297f1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp313-cp313-win_amd64.whl

Download URL opentui-0.1.2-cp313-cp313-win_amd64.whl
Size 827.5 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
c9ec59c0e8b0c49401b816f4fa7d9e9f6389f5c575b61643b01b98c013deb7a8
BLAKE2b-256 checksum
How to use checksums
9a6d49d985d413b319e7fffcc655764f781c5701aaab5cd4be1f57cd29dcfd33
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp313-cp313-manylinux_2_28_x86_64.whl

Download URL opentui-0.1.2-cp313-cp313-manylinux_2_28_x86_64.whl
Size 3.0 MB
Tags CPython 3.13 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
b2b74edce084d0decd430f7c7ab3f0b8d2869ff2afe64ac177dc63daf91463ad
BLAKE2b-256 checksum
How to use checksums
4455f31ec925663dcffc4c303acbd29c2ba80055f6870ec1b24091f00f08f336
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp313-cp313-manylinux_2_28_aarch64.whl

Download URL opentui-0.1.2-cp313-cp313-manylinux_2_28_aarch64.whl
Size 2.9 MB
Tags CPython 3.13 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
4a32829220e450316b3bfca2a08c5752c3d24fc02df8e2866e49bc6e2909eb74
BLAKE2b-256 checksum
How to use checksums
b8001a22b74143f4a9475dffae35ffa3313ddaeefd0eecf33e7b22d07c375e1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp313-cp313-macosx_13_0_x86_64.whl

Download URL opentui-0.1.2-cp313-cp313-macosx_13_0_x86_64.whl
Size 781.9 kB
Tags CPython 3.13 macOS 13.0+ x86-64
SHA-256 checksum
How to use checksums
b922add2291067eb9c6c08c1bfc05a1a86b93c7ff1de110cd4a56bed647410ce
BLAKE2b-256 checksum
How to use checksums
fb998a61e75fe193620d3eb7cfc47377f8c1392cc68e98720ccc3d8292a0f0a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp313-cp313-macosx_13_0_arm64.whl

Download URL opentui-0.1.2-cp313-cp313-macosx_13_0_arm64.whl
Size 756.6 kB
Tags CPython 3.13 macOS 13.0+ ARM64
SHA-256 checksum
How to use checksums
769e92eba6d21dda77eb048577bd8a36882e4af090ae0bfeceda7b53cbbfbb04
BLAKE2b-256 checksum
How to use checksums
ad6333c1ef02c01e0dd535644bdd503049c1d7d7015ace1fad0bbec434c6a30d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp312-cp312-win_amd64.whl

Download URL opentui-0.1.2-cp312-cp312-win_amd64.whl
Size 827.5 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
40dbcf11a28ad40d8de69e98a1c6527b501e8f43d1e9a2dd14705b51bc0d94d1
BLAKE2b-256 checksum
How to use checksums
98c5691929f908dcc5e064c77779794c6afd2de2b43a88279db51bb6cadb39a5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp312-cp312-manylinux_2_28_x86_64.whl

Download URL opentui-0.1.2-cp312-cp312-manylinux_2_28_x86_64.whl
Size 3.0 MB
Tags CPython 3.12 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
f844fe714a166a9c712634c1de363a69ffdf9a407890f7a5330dbc3bbaaaebda
BLAKE2b-256 checksum
How to use checksums
0aea82ab48bd93250d5ee8266bac5f437dd4ad08f4e5b9230cb5321ab521563b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp312-cp312-manylinux_2_28_aarch64.whl

Download URL opentui-0.1.2-cp312-cp312-manylinux_2_28_aarch64.whl
Size 2.9 MB
Tags CPython 3.12 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
24d726d0ba359ad95587519f02fccc33f8d1d376fac02741dd58f89f9e971d5a
BLAKE2b-256 checksum
How to use checksums
0538f8a4f23d96bd4d5ecdc9fcfb904844e5c46950a6e2b388e1a5b210fd37d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp312-cp312-macosx_13_0_x86_64.whl

Download URL opentui-0.1.2-cp312-cp312-macosx_13_0_x86_64.whl
Size 782.0 kB
Tags CPython 3.12 macOS 13.0+ x86-64
SHA-256 checksum
How to use checksums
ac96ed80ddcceff2d50c70096194df46c096837bcda84c31b2d8779259281842
BLAKE2b-256 checksum
How to use checksums
ab4016b06e058fd53e85921b5fa771bf354f507d24be31384ab0ce24541892c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release files / opentui-0.1.2-cp312-cp312-macosx_13_0_arm64.whl

Download URL opentui-0.1.2-cp312-cp312-macosx_13_0_arm64.whl
Size 756.7 kB
Tags CPython 3.12 macOS 13.0+ ARM64
SHA-256 checksum
How to use checksums
a738a9b10b7842645daad32a4e0d60a3cda1aec9cbb4021f86c5a6e541b246c0
BLAKE2b-256 checksum
How to use checksums
b511e79227d5dd7053e5a8c9948e43caedb7156471e84f27808fd97c38545754
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.2 This release

11 release files

0.1.1

11 release files

0.1.0

9 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page