Skip to main content

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.

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.3.0.tar.gz (120.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.3.0-py3-none-any.whl (82.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: upivia_tui-0.3.0.tar.gz
  • Upload date:
  • Size: 120.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.3.0.tar.gz
Algorithm Hash digest
SHA256 68be2e6b744c6d3fb1124b4c9a771f9bd957d629d29d7dea37a4017419d9c584
MD5 8af2cf49478979fe61cdd9f5590deb3f
BLAKE2b-256 7ef0e58a9fc464445518288bcd4b20e52f2d64edfeea59ab4a886bb6c6fe585d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: upivia_tui-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 82.5 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.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cf04d85365f997f39ee6555733bf43bff21e3c4021d9d675aa5e92f2d173d031
MD5 ff7eba601055abfe8dab1905bccd8ae3
BLAKE2b-256 411ff9968ed6c409eac23fbc18b4e70e83aca1167d2668d069790a61b47bb79b

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.1

2 files

0.1.0

2 files

Supported by

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