Skip to content

Getting started

Install

virtufin-tui is published to a private index at pypi.haenerconsulting.com, not public PyPI -- every install method below needs credentials for it first. Use a Gitea personal access token (scope read:packages) as the password.

One-off (inline credentials)

Simplest for a single machine / CI job -- embed credentials directly in the index URL:

export VIRTUFIN_REGISTRY_USER=<your-gitea-username>
export VIRTUFIN_REGISTRY_TOKEN=<your-gitea-token>
INDEX="https://${VIRTUFIN_REGISTRY_USER}:${VIRTUFIN_REGISTRY_TOKEN}@pypi.haenerconsulting.com/api/packages/virtufin/pypi/simple/"

# Recommended: use uvx (no install needed)
uvx --index "$INDEX" --from virtufin-tui virtufin-tui

# Or install via pip
pip install virtufin-tui --index-url "$INDEX" --extra-index-url https://pypi.org/simple
virtufin-tui

# Or install via uv into a project
uv add virtufin-tui --index "$INDEX"

Persistent (no credentials in shell history / process list)

pip, via ~/.netrc:

cat >> ~/.netrc <<EOF
machine pypi.haenerconsulting.com
login <your-gitea-username>
password <your-gitea-token>
EOF
chmod 600 ~/.netrc

pip install virtufin-tui \
  --index-url https://pypi.haenerconsulting.com/api/packages/virtufin/pypi/simple/ \
  --extra-index-url https://pypi.org/simple

uv, via the UV_INDEX env var (add to your shell profile):

export UV_INDEX="https://<your-gitea-username>:<your-gitea-token>@pypi.haenerconsulting.com/api/packages/virtufin/pypi/simple/"

uvx --from virtufin-tui virtufin-tui
uv add virtufin-tui   # inside a project

Either way, public dependencies (textual, grpcio, pydantic, tomlkit, etc.) still resolve from pypi.org as usual -- the private index is additive, not a replacement for it.

First run

On first run, if ~/.config/virtufin/api/contexts.toml (or ~/.config/virtufin/tui/config.toml) doesn't exist yet, it's seeded from the shipped defaults (a single local context pointing at localhost:5002) -- edit the copy under ~/.config to add other environments. A fuller template lives at contexts.toml.example in the repo root. Example contexts.toml:

[[contexts]]
name = "local"
api_host = "localhost"
api_port = 5002
description = "Local dev virtufin-api"

[[contexts]]
name = "staging"
api_host = "staging.virtufin.com"
api_port = 5002
tls = true
description = "Staging cluster"
default_worker_topic = "workmanager.lifecycle"

[[contexts]]
name = "kubernetes"
api_host = "api.virtufin.com"
api_port = 443
tls = true
worker_api_host = "api.virtufin.svc.cluster.local"
worker_api_port = 5002
description = "k3s cluster via ingress; workers dial the in-cluster Service directly"

The active context itself isn't set here -- it's state, not config; see Contexts.

Configuration

Field Type Default Description
name string required Display name (must be unique within [[contexts]])
api_host string required Hostname of the virtufin-api gRPC endpoint
api_port int (1-65535) required Port of the gRPC endpoint (typically 5002)
tls bool false Use TLS for the gRPC channel
api_key string unset (falls back to VIRTUFIN_API_KEY env var) Sent as x-api-key metadata on every call; required when the endpoint enforces API-key auth. See Contexts for the env-var fallback and error reporting.
worker_api_host string unset (falls back to api_host) Address a spawned worker process dials for its own Gateway callback; set for contexts where the worker runs somewhere api_host isn't reachable from (e.g. cluster-internal)
worker_api_port int (1-65535) unset (falls back to api_port) Port for worker_api_host
default_worker_topic string unset Subscribe to this topic on start (typically workmanager.lifecycle)
description string "" Free-form label shown in the Config page's contexts table

Environment variables override file values:

Env var Overrides
VIRTUFIN_TUI_API_HOST api_host of the active context
VIRTUFIN_TUI_API_PORT api_port of the active context
VIRTUFIN_TUI_CONTEXT the active context (see Persistence in Contexts)

Config file location: $XDG_CONFIG_HOME/virtufin/api/contexts.toml if $XDG_CONFIG_HOME is set, otherwise ~/.config/virtufin/api/contexts.toml on every OS (there's no platform-specific path like macOS's "Application Support" or Windows's %APPDATA% -- the same ~/.config/... layout is used everywhere). Runtime state (active context, active World/Scenario, subscribed event topics) lives separately under $XDG_STATE_HOME (default ~/.local/state), not in this file. The TUI's own log file (tui.log, everything logged during a session -- see Architecture) lives alongside that runtime state at $XDG_STATE_HOME/virtufin/tui/tui.log, for the same reason: it's generated output, not something you hand-author.

Switch context inside the TUI

Go to the Config tab (Infra → Config by default), highlight a row in the contexts table, and press Enter. Switching closes the current gRPC channel and opens a new one to the selected endpoint; the dashboard refreshes within 1 second.

Development

git clone https://gitea.haenerconsulting.com/virtufin/virtufin-tui
cd virtufin-tui
uv sync
uv run virtufin-tui --context local
uv run pytest tests/
uv run ruff check src/ tests/

See Architecture for the data flow and Keybindings for the full keybinding table.