Appearance
The terminal client
matterwave-tui is a chat client for the terminal: conversation list, transcript, composer, model picker and a status line, over the same /api routes as the web app. Conversations are shared: one started in the terminal is in the web app, and the other way round. It is a client, not an agent: it runs no tools and edits no files.
The package lives at clients/tui (Python 3.11+, Textual, on the Python SDK).
Install
bash
uvx matterwave-tui # run without installing
pipx install matterwave-tui # or install itFrom this repo: cd clients/tui && uv sync && uv run matterwave-tui.
Point it at a deployment with --base-url https://<host> or MATTERWAVE_BASE_URL (default http://localhost:8000).
Sign in
A stored credential lives in the OS keyring (Keychain, Credential Manager, Secret Service), one entry per base URL, never in a dotfile; with no usable keyring, sign-in fails rather than writing a file.
- An API key. Run
matterwave-tui login --keyand paste it once, or setMATTERWAVE_API_KEY=mw_...for one shell (read, not stored). Create one in Settings → API keys; it needschat:readandchat:write. - As yourself, by device code.
matterwave-tui login, or justmatterwave-tuiwith no stored credential, prints a URL and a short code. Open the URL in any browser, sign in, approve the code; the terminal picks the session up. The flow is in device-login.md; the key it issues appears in Settings → API keys and revoking it there signs the terminal out.
Keys
| Key | Where | Does |
|---|---|---|
Ctrl+Enter | anywhere | send (also Ctrl+J / Ctrl+S, for terminals that do not report Ctrl+Enter) |
Esc | composer | to the transcript; cancels an edit; stops a streaming answer |
↑ ↓ / k j | transcript | select a message |
[ / ] | transcript | previous / next sibling branch |
e | transcript | edit the selected user turn |
r | transcript | regenerate the selected answer |
x | transcript | show / hide the messages a summary replaced |
c | transcript | compact the conversation now |
m | transcript | model picker |
n | transcript | new conversation |
/ | transcript | search conversations |
Ctrl+Q | anywhere | quit |
Letter keys apply when focus is not in the composer or the search box; Esc gets you there.
The composer is multiline and keeps a draft per conversation while the app runs. matterwave-tui logout forgets the stored credential.
Branches
Editing a user turn or regenerating an answer writes a sibling; the original stays. [ and ] step through the siblings at the selected turn and move the conversation's active branch (PUT /api/conversations/{id}/active-leaf), so the web app opens on the same branch.
The status line
Model, the context meter (used / window, from the last context frame), the request id of the last error, the wait left on a rate limit, and online / offline. A dropped stream resumes once with Last-Event-ID (the SDK's resume); Esc stops a streaming answer, and what the server had sent is read back as a truncated turn.
When the server compacts a long thread, a divider marks where the summary begins; x expands the covered messages from the tree already loaded. See compaction.md.
Models
The picker shows /api/models, read again when it opens, grouped as on the web (GRT, partner, research preview). A model your plan does not include shows its upgrade path and cannot be selected. The choice is kept on the conversation (PATCH /api/conversations/{id}, its default_model), so the web app opens it on the same model.
Errors
Budget, moderation, upstream and truncated answers get the same wording as the web app, always with the request id, which is what to quote in a support thread. Two states the web app never shows: a key's per-minute limit (429, with the server's Retry-After counted down in the status line) and a model the plan does not include (402), which is not the budget's 402.