gpui_tea
[!WARNING] The public API is intended to be stable for real use, but future releases may still refine interfaces or introduce compatibility-affecting changes where needed.
TEA-style runtime primitives for Rust developers building desktop applications with GPUI.
gpui_tea is a Rust library for building Elm Architecture applications on top of
GPUI. You use it when you want a
mounted program with explicit state transitions, message-driven updates, and rendering that stays
inside GPUI's application model.
The crate is aimed at developers building desktop user interfaces with GPUI who want a structured
way to express initialization, synchronous updates, asynchronous effects, and long-lived event
sources. The public surface centers on Model, Program, Command, and Subscription, with
support for nested models through ChildScope and the Composite derive macro.
Table of Contents
Features
- TEA-style runtime for GPUI with a
Modeltrait that separatesinit,update,view, andsubscriptions. - Command system for immediate messages, foreground effects, background effects, batching, and keyed latest-wins work whose stale completions are ignored.
- Declarative subscriptions that are retained, rebuilt, or removed by stable
Keyvalues. - Nested model support through
ModelContext,ChildScope, and#[derive(Composite)]. - Runtime observability through
ProgramConfig,RuntimeEvent, andTelemetryEvent, with optional adapters fortracingandmetrics.
Requirements
- Rust stable toolchain. The repository pins the
stablechannel inrust-toolchain.toml. - A Cargo toolchain that supports Rust 2024 edition crates. The manifest does not declare a
separate
rust-version. - For local development in this repository:
clippy,rustfmt, andtypos. - For running the interactive examples: a desktop environment capable of opening GPUI windows.
The repository does not document additional external services such as databases, brokers, or servers.
Installation
Add the crate from crates.io:
Enable optional telemetry integrations as needed:
To depend on the current repository state instead of a crates.io release, use a Git dependency:
[]
= { = "https://github.com/inkwadra/gpui-tea" }
To build the workspace test suite from source:
To run the repository's full validation gate, use:
Configuration
gpui_tea does not use configuration files or required environment variables for normal library
use.
Cargo Features
| Feature | Default | Description |
|---|---|---|
metrics |
No | Enables observe_metrics_telemetry. |
tracing |
No | Enables observe_tracing_telemetry and the telemetry example. |
Runtime Configuration
Use ProgramConfig when you need queue controls or observability hooks:
queue_policy(QueuePolicy)selects unbounded, reject-new, drop-newest, or drop-oldest backpressure behavior. Under drop policies,dispatch()may still returnOk(())even when a message is discarded or an older queued message is displaced.queue_warning_threshold(usize)emits queue warning events whenever the current queue depth is greater than the threshold.observer(...)receives high-levelRuntimeEventvalues.telemetry_observer(...)receives structuredTelemetryEnvelopevalues.describe_message(...),describe_key(...), anddescribe_program(...)attach readable descriptions to observability output.
The only environment variable referenced in repository examples is RUST_LOG=debug, which is used
when running the telemetry example.
Usage
The usual flow is:
- Define a message enum for your model.
- Implement
Modelfor your state type. - Return
Commandvalues frominitorupdatefor follow-up work. - Mount the model with
Program::mount(...)orModelExt::into_program(...).
The smallest working shape looks like this:
use ;
use *;
use ;
Common Patterns
- Bootstrap state with
Model::init()and returnCommand::emit(...)or an async command. - Schedule asynchronous work with
Command::foreground(...)orCommand::background(...). - Replace in-flight work by key with
Command::foreground_keyed(...)orCommand::background_keyed(...). Older tasks may still finish, but the runtime ignores stale completions. - Cancel tracked keyed work with
Command::cancel_key(...). - Declare long-lived external event sources in
subscriptions()withSubscription::new(...). - Compose child models with
ModelContext::scope(...)or#[derive(Composite)].
API Reference
Model
Signature:
- Parameters:
msgis your domain message,cxis the GPUI application context,scopecontains the current child path, anddispatchersends messages back into the mounted program. - Return type:
Command<Self::Msg>frominitandupdate,Viewfromview,Subscriptions<Self::Msg>fromsubscriptions.
Example:
Program::mount And Program::mount_with
Signatures:
;
;
- Parameters:
modelis the initial state,configcustomizes queue and observability behavior, andcxis the GPUI application context. - Behavior: mounting immediately calls
Model::init(), executes its returned command, and performs the initial subscription reconciliation before returning. - Return type:
Entity<Program<M>>.
Example:
let config = new.queue_warning_threshold;
let entity = mount_with;
Command
Representative constructors:
;
;
;
;
;
;
;
;
;
- Parameters: commands take either a concrete message, an async effect closure, or a stable
Keyused for deduplication and cancellation. - Keyed commands are latest-wins: scheduling a newer keyed command replaces the tracked task for that key, and any later completion from the older task is ignored rather than aborted.
- Return type:
Command<Msg>orCommand<NewMsg>formap.
Example:
background_keyed
.label
Subscription And Subscriptions
Signatures:
;
;
;
- Parameters:
keyis stable subscription identity, andbuilderreceives aSubscriptionContext<'_, Msg>with access toAppand the programDispatcher. - Constraint: keys must be unique within a
Subscriptionsset.Subscriptions::batch(...)andpush(...)returnError::DuplicateSubscriptionKeywhen duplicates are declared. - Return type:
Subscription<Msg>orSubscriptions<Msg>.
Example:
one
#[derive(Composite)]
Syntax:
- Parameters:
messagedeclares the parent message type; eachchildattribute defines the child path, the lift function, and the extractor used to route parent messages back to the child. - Generated helpers: the macro adds hidden aggregate methods
__composite_init,__composite_update, and__composite_subscriptions, plus one hidden<field>_viewhelper per child field. - Caveat: child subscriptions must still resolve to unique scoped keys. The generated composite subscription helper panics if two child subscriptions collide after scoping.
Example:
Examples
Run the packaged examples from the workspace root:
RUST_LOG=debug
Each example focuses on one runtime behavior:
counter: minimal mounted program and message dispatch from the view.init_command: bootstrap work triggered byModel::init().keyed_effect: latest-wins async work on a stable key.nested_models:Compositecomposition and child path scoping.subscriptions: declarative subscription reconciliation by key.observability:RuntimeEventhooks with readable labels.telemetry: structured tracing output for queue activity, keyed replacement, and cancellation.
For repository development, the Justfile mirrors CI:
License
Licensed under Apache-2.0.