Skip to main content

Upivia Textual TUI — chat with Yupi, watch multi-agent delegation, reuse the platform's governed orchestration.

Project description

upivia-tui

The Upivia terminal — a Textual TUI and the canonical CLI for Upivia (it replaced the older Node/OpenTUI CLI). It is a thin presentation layer over the platform's governed chat-turn pipeline — all orchestration, budgets, approvals, memory, and multi-agent delegation happen server-side.

What it does

  • renders messages as bordered cards (OpenCode-style)
  • renders markdown with Textual's native widget (clean tables/code/bold/italic)
  • visualises multi-agent delegation in a live Team panel (+ worker detail view)
  • lets the agent read/write/edit/run files in your launch directory, with per-session command permissions and inline +/- diff cards
  • syncs in realtime with the web app over WebSocket, and can run headless (--background) so the web app edits files on this machine

Install & authenticate

uv tool install upivia-tui        # or: pipx install upivia-tui  (Python 3.10+)
upivia-tui init                   # authenticate (writes ~/.upivia/config.json)
upivia-tui                        # launch

Keyboard & commands

Key Action
Ctrl+P Command palette (fuzzy)
Ctrl+O Switch model (curated + full OpenRouter catalog)
Ctrl+T Switch agent
Ctrl+B Switch session (loads history)
Ctrl+G Toggle Build / Plan mode
Ctrl+L New / clear session
Ctrl+Y Copy (selection, or last reply) — also drag-to-copy
Ctrl+C / Ctrl+Q Quit

All shortcuts work even while typing in the composer (priority bindings). Ctrl+S is intentionally avoided (it triggers terminal flow-control on many terminals).

Slash commands: /models /model <id> /agent /sessions /session /new /rename <title> /delete /mode /autonomy /requests /worker /export /compact /clear /help. The model picker and command palette mirror the Node CLI; selecting a new model or agent starts a fresh session so history stays consistent.

Autocomplete & worker detail

  • Type @ in the composer to autocomplete project files (Tab/Enter to accept); mentioned files are read by the agent first.
  • Type / to autocomplete slash commands from a fuzzy dropdown.
  • Click a worker in the Team panel (or run /worker) to open its full activity stream — every thinking step, tool call, file write, and result.
  • The agent can navigate large codebases with local_code_graph (Graphify); install with uv tool install graphifyy. It falls back to local_search when graphify isn't present.

Copy & select

Textual runs in mouse-tracking mode, so the app handles selection itself:

  • Drag with the mouse to select text — it auto-copies on release (via OSC 52, so it works over SSH and writes the system clipboard where available). This is the reliable path and needs no key.
  • Ctrl+Y copies the current selection, or the last assistant reply if nothing is selected.
  • Ctrl+Shift+C also works where the terminal forwards it — but many terminals intercept it for their own copy, which is why drag-to-copy and Ctrl+Y are the primary paths.
  • Your terminal's native selection still works too: hold Shift (most terminals) or Option/Alt (iTerm2/macOS) while dragging.

Local file editing

When the agent calls a local tool, the server pauses the turn with local_tools_pending; this client executes it on disk and resumes. Supported tools: local_read_file, local_write_file, local_edit_file, local_list_dir, local_search, local_run_command.

  • Sandbox: every path resolves under the directory you launched upivia-tui from and can never escape it.
  • Command gating: the first time the agent wants to run a shell command, you're asked once which categories it may use (shell / install / servers / git / delete); the choice is enforced for the rest of the session.
  • Diffs: writes and edits render a colorised +/- diff card inline.

Local browser automation

The TUI ships with built-in Playwright browser tools — install the TUI and the agent can pilot a real local Chromium with zero manual setup. On the very first browser call, the Chromium engine is auto-installed (one-time, python -m playwright install chromium, with a "Installing local browser engine (one-time setup)…" status line); after that it's instant. One persistent headless browser/page is kept alive across tool calls for the session.

Tools: local_browser_open, local_browser_snapshot, local_browser_click, local_browser_type, local_browser_press, local_browser_select, local_browser_wait, local_browser_extract, local_browser_screenshot, local_browser_close, local_browser_health.

Ref-based interaction contract: the agent calls local_browser_snapshot first (or reads the snapshot embedded in open/click/type results), which tags interactive elements with stable refs like e12 and returns them in an LLM-friendly digest (role, name, text, visibility, links, forms, console errors). Clicks/typing then target those refs, with visible-text and CSS selectors as fallbacks. Refs refresh automatically after every action, so they never go stale silently.

Safety notes:

  • no tool ever returns cookies, localStorage, or other secrets
  • downloads are disabled (accept_downloads=False)
  • screenshots are saved as PNG files under .upivia-screenshots/ in your project directory — only the file path is returned, never inline image data
  • navigating to banking/payment-looking hosts attaches a warning to the result
  • every failure returns a structured error with suggestions (valid refs, repair hints) instead of crashing the turn

Auth

It reads the same ~/.upivia/config.json that upivia init (the Node CLI) writes. If you've authenticated the Node CLI, you're authenticated here.

Override for dev:

export UPIVIA_BASE_URL=http://localhost:3000
export UPIVIA_PAT=upivia_pat_...

Run

cd packages/upivia-tui
uv run upivia-tui              # full TUI in the current directory
uv run upivia-tui --dir PATH  # full TUI rooted at PATH
uv run upivia-tui --background # headless device daemon (no UI)
uv run upivia-tui --browser-headful # show the built-in browser window

Built-in local browser: headless vs headful

The local_browser_* tools drive a local Chromium that is headless by default. To watch the agent work (or complete a login/captcha yourself), opt in to a visible window with any of:

  • --browser-headful CLI flag
  • UPIVIA_BROWSER_HEADFUL=1 environment variable
  • "browserHeadful": true in ~/.upivia/config.json

Realtime sync + machine-wide device

The TUI connects to the platform's WebSocket companion (wss://…/ws) and registers as a live device:

  • Chat turns flow over WS, so the web app and the TUI share one live session — messages and tool calls appear in both in real time (SSE fallback if the socket can't connect).
  • While the TUI is open or upivia-tui --background is running, any web session attached to this device can read/write/edit/run files on this machine through the governed local_tools_pending → execute → tool_result loop. Attach a device from the web app's Sessions view.
  • The TopBar shows ● live (WS connected / device online) or ○ local.

Set the working directory from the web app

When a device is live, the web Sessions header shows a subtle folder chip. Click it to browse the device's directories and cd into one — type a path (Tab completes against available sub-directories, Enter applies) or click a listed folder. This rebases the directory the agent reads/writes/runs in, sandboxed to the chosen root.

How it talks to the platform

REST + SSE go through the official Python SDK (upivia, packages/sdk-py): upivia_tui/client.py is a thin adapter over upivia.AsyncUpiviaClient (PAT auth). The realtime WebSocket device link (upivia_tui/wsclient.py) speaks to the WS companion directly.

Action Endpoint
List agents GET /api/v1/agents
Balance GET /api/v1/balance
Create session POST /api/v1/chat/sessions
Stream a turn POST /api/v1/chat/turn (SSE)

Delegation is driven by the delegation_started and agent_event SSE events emitted by the chat route when Yupi spawns/delegates to worker agents.

Yupi delegates by default

The orchestration system prompt in app/api/v1/chat/turn/route.ts instructs Yupi to delegate any non-trivial or multi-step work to specialist agents, only working solo for genuinely trivial single-step actions.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

upivia_tui-0.1.0.tar.gz (103.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

upivia_tui-0.1.0-py3-none-any.whl (68.1 kB view details)

Uploaded Python 3

File details

Details for the file upivia_tui-0.1.0.tar.gz.

File metadata

  • Download URL: upivia_tui-0.1.0.tar.gz
  • Upload date:
  • Size: 103.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for upivia_tui-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a49a04b21e06bdbd13d2f8379541ba217a2dc7f8f68d606ea66192e81cd9baf2
MD5 3ba03120d33bc19e0ceeac50a50d5cf1
BLAKE2b-256 9bfaef5faf5f2e18667b3aa9d11b8f03ab72c161a458e6cce8da7de1e413d58e

See more details on using hashes here.

File details

Details for the file upivia_tui-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: upivia_tui-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 68.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.13 {"installer":{"name":"uv","version":"0.11.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for upivia_tui-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9ab75dc04a5644e121d1433c523245272aeea7b3e8192e934f5c0b33510f282d
MD5 04305385ec26ceba69f60be0799ff986
BLAKE2b-256 2025172428d88b9de394f5211fb486bceb6d6b91b4e890854fba32e4f3c1a39e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page