Skip to main content

Documentation Index

Fetch the complete documentation index at: https://simplellmfunc.cn/llms.txt

Use this file to discover all available pages before exploring further.

TUI

The @tui decorator wraps a @llm_chat agent into a full Textual terminal UI with streaming output, tool visualization, and input handling.

Basic Usage

from SimpleLLMFunc import llm_chat, OpenAICompatible
from SimpleLLMFunc.utils.tui import tui

models = OpenAICompatible.load_from_json_file("provider.json")
llm = models["openrouter"]["openai/gpt-4o"]


@tui
@llm_chat(llm_interface=llm, toolkit=[...], stream=True)
async def agent(message: str, history: list | None = None, _abort_signal=None):
    """A helpful assistant."""
    pass


if __name__ == "__main__":
    agent()
Run it and you get a full chat interface in the terminal.

Features

  • Streaming display — Model responses appear character-by-character
  • Tool call cards — Each tool call gets a visual card showing name, arguments, and result
  • Specialized cardsexecute_code, read_file, grep, sed, echo_into have custom rendering
  • AbortCtrl+C cancels the current response
  • CopyCtrl+Y copies the full transcript to clipboard
  • Multi-column forks — When using SelfRef forks, child agents get their own columns

Slash Commands

CommandAction
/exit, /quit, /qQuit the TUI
/copy, /copyallCopy transcript to clipboard
/chat <msg>Send a message (bypasses tool-input mode)

Custom Event Hooks

Handle custom events (e.g., PyRepl streaming output) with hooks:
from SimpleLLMFunc.hooks.events import CustomEvent
from SimpleLLMFunc.utils.tui import ToolRenderSnapshot


def my_event_hook(event: CustomEvent, snapshot: ToolRenderSnapshot):
    """Process custom events for display."""
    if event.event_name == "kernel_stdout":
        # Handle PyRepl stdout streaming
        pass
    return None


@tui(custom_event_hook=[my_event_hook])
@llm_chat(llm_interface=llm, toolkit=repl.toolset, stream=True)
async def agent(message: str, history: list | None = None, _abort_signal=None):
    """My agent."""
    pass

Decorator Parameters

ParameterTypeDescription
custom_event_hookList[Callable]Custom event handler functions
titlestrWindow title

ToolRenderSnapshot

Passed to event hooks with context about the current tool card:
@dataclass
class ToolRenderSnapshot:
    tool_name: str
    tool_call_id: str
    status: str          # "running", "completed", "error"
    arguments: dict

Keyboard Shortcuts

KeyAction
Ctrl+CAbort current response
Ctrl+QQuit
Ctrl+YCopy transcript
EnterSend message

When to Use @tui vs Custom UI

Use @tui when:
  • You want a working chat interface quickly
  • The built-in tool cards are sufficient
  • You don’t need custom widgets or layouts
Build custom when:
  • You need confirmation modals for dangerous actions
  • You want a status bar with custom metrics
  • You need non-chat UI elements (file trees, progress bars)
  • You’re building a product, not a tool
For custom UIs, consume the ReactOutput stream directly and render with Textual or any other framework.