TUI / JSON Stream Protocol
A production-ready JSON stream spec for terminal renderers, diff-aware patching, and token-level highlighting. Designed to stay deterministic while supporting high-frequency streaming output.
Convert streaming markdown into stable JSON blocks with inline token streams, diff metadata, and predictable patch application.
- Block snapshots for stable layout in terminal UIs.
- Token spans that map directly to ANSI palettes.
- Patch diffs for incremental highlight updates.
{
"protocol": "streammdx",
"schemaVersion": "1.0",
"streamId": "a9f2c0c1-7c9c-4b2b-8c29-f2df20c30f6a",
"event": "patch",
"tx": 42,
"patches": [
{
"op": "appendLines",
"at": ["__root__", 3],
"startIndex": 0,
"lines": ["# Title", "Streaming docs"],
"tokens": [{"spans": [{"t": "# Title", "s": {"fg": "#93c5fd"}}]}]
}
]
}The lifecycle of a stream
StreamMDX emits a predictable sequence of events that keep terminal UIs stable while incremental updates arrive.
Announce schema + theme metadata.
Emit stable block snapshots.
Append lines with tokens + diffs.
Seal the stream + final tx.
Protocol schema
Events are typed, versioned, and replayable. Consumers ignore unknown fields to keep the stream forward-compatible.
{
"protocol": "streammdx",
"schemaVersion": "1.0",
"event": "init",
"capabilities": { "tokens": "v1", "diff": "v1" },
"theme": { "mode": "dual", "dark": "github-dark", "light": "github-light" }
}Token-level highlighting
Token spans carry color and style metadata for terminal renderers. Streaming tokens arrive line by line to minimize flicker.
{
"type": "code-line",
"index": 12,
"text": "const stream = createStream();",
"tokens": {
"spans": [
{ "t": "const", "s": { "fg": "#60a5fa", "fs": 1 } },
{ "t": " stream = ", "s": { "fg": "#e2e8f0" } },
{ "t": "createStream", "s": { "fg": "#f97316" } },
{ "t": "()", "s": { "fg": "#e2e8f0" } }
]
}
}Diffs in terminal
Unified diff semantics are baked into patches so terminals can render additions, removals, and context lines without re-parsing content.
@@ -12,7 +12,8 @@
-export function render() {
+export function render() {
+ const { patches } = stream;
return <Renderer patches={patches} />;
}
Stability & guarantees
Event shapes remain backward compatible. Consumers should ignore unknown fields to stay resilient across minor releases.
Identical inputs yield identical patches. This enables replay testing, diff validation, and deterministic TUI output.
Ready to build something real?
Explore the reference implementation and start streaming into your terminal UI.