Skip to content
jaivialPublic

About

A pretty terminal UI for mini-swe-agent: parses and reformats tool calls and outputs, with live /model switching.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

mini-tui

Talk to a bot. It runs the board.

A team of bots that organize your work as a kanban, from the web app, the terminal or a WhatsApp group.
Workers carry the cards out. A card closes only when the evidence is on it.

Landing page · Install guide · Changelog · Latest release


What mini-tui is now

mini-tui started as a terminal UI for the mini-swe-agent coding agent. It is now a different thing: a team of bots that plan and organize, with workers that do. The bot does not write all the code itself. It turns what you ask into cards on a durable task graph, hands them to workers, checks the evidence, and reports back in the thread you started.

Before Now
Who works One agent that types code Bots that write a board, and workers that take cards
Where you talk A terminal prompt The web app, the terminal, or a WhatsApp group per bot
What "done" means The agent says it is done A closure check reads the goal against the diff and the logs
How it looks Panes of transcripts Silver-metal web app: bots in the sidebar, a kanban, a team map
Can it look at a page No Yes, through cu: a real browser, with screenshots in the chat

The board

  • Every request becomes cards with dependencies on a durable task graph. Workers take a lease on a card, a card in flight is not lost when a lane stops, and an expired lease freezes its project instead of dropping work. See docs/task-graph.md.
  • Cards from other bots are visible read-only, through a shared graph layer (docs/bot-graph-rag.md).
  • The sidebar is a tree: window, bots, and the delegates each bot started. The team map draws the same tree as a live graph.

WhatsApp groups, synced with the web

  • Each bot can have its own WhatsApp group. It answers there without a mention, and its avatar becomes the group photo.
  • The thread is mirrored both ways between WhatsApp and the web app, with no echo and an origin marker on each bubble. Images and attachments travel too.
  • Voice notes are transcribed on your machine, and the state is honest when a transcript fails.
  • The bot reacts with 👀 the moment it hears you, shows a typing indicator, and uses semantic reactions when a card closes. /newsession starts a fresh session, and /rename renames the session and the group subject.
  • Pair with a phone code or a QR from Settings, Channels. Details: docs/channel-multichat.md, docs/channel-mirror.md, docs/channel-consumers.md.

Bots that use a browser (cu)

The computer_use tool drives a real browser through a reusable pool of cu daemons and posts screenshots to the chat. A bot can open the page it just changed, look at it, and file what it found as evidence on the card. Logins live in cu's vault, and the bot never sees a password.

Done means proven

A card moves to Done only after a closure check reads the goal against the diff and the logs. The default judge is a model. Point it at Laya, a small self-hosted classifier, and a clean run closes in about a tenth of a second; anything unclear goes to the model judge. A run that the judge keeps rejecting for the same reason ends as a stalemate instead of looping.

export MINI_AGENT_GOAL_ORACLE=laya
export MINI_AGENT_GOAL_ORACLE_URL=http://127.0.0.1:8102/v1/systemone

How it works: docs/goal-closure.md.

Also new

One Docker image for the whole runtime (web, agent, whisper, Python), and provider keys that connect for real — including Kimi for Coding, whose temperature and message-part constraints the connection now handles — with failed connects that say what the provider actually answered. Also: model router with three tiers and a persistent fallback breaker, usage metering per model and provider, generative UI in the chat (forms, tables and charts), a voice-note recorder and player, inline images and attachments, AI session titles, a PWA with cookie login, and a long list of hardening passes on the web server (per-IP rate limits, loopback-only CORS, upload sniffing). Everything is in the changelog.

Quick start

git clone https://github.com/jaivial/mini-tui && cd mini-tui
bun install
(cd agent-rs && cargo build --release)       # one binary, no Python
mkdir -p ~/.local/lib/mini-tui && cp agent-rs/target/release/mini-agent-rs ~/.local/lib/mini-tui/
bun run web                                   # http://127.0.0.1:4317

Or run the whole runtime in Docker — same web on 4317, state in your mounted home, tools baked into the image: see Run it in Docker below.

Then open Settings, Providers, and paste a model key. It is tested with one real request before it is saved, and a refusal names what the provider actually answered. The install guide has the rest, and the terminal UI is still there: run bin/mini-tui.

Run it in Docker

The whole runtime also ships as one image — tools in the image, state in your mounted home:

docker compose up -d                      # the web app on 4317
docker compose --profile channels up -d   # + the WhatsApp consumer daemon
docker compose --profile rag up -d        # + RAG server + graph projection

The container is not a sandbox: gh and ssh work inside exactly like in the terminal outside it (GitHub auth and your ssh keys/config ride the home mount, gh and openssh-client have the image). Agent sessions can open PRs and reach your ssh hosts from the container. See docs/docker.md for the whole tour.

Benchmarks

Historical closure-check result, 19 October 2026. Ten tasks, three repetitions, MiniMax-M3.1-Flash-Preview on both sides, pi and mini interleaved task by task so that API drift hits both alike, mini on the deployed binary and config with Laya as the judge.

pi mini-tui
Tasks passed 30/30 30/30
Sum of per-task medians 145.6 s 112.9 s (0.78x)
Tasks where mini is at least as fast 1/10 9/10
Timeouts 0 0

Limits: ten tasks, three repetitions, one model, one machine. Recovered from the original completed-run readback; its temporary raw directory is no longer available here. This is not a measurement of the 20 October parity changes. The earlier analysis attributed the gain to a judge that closes a clean run in a tenth of a second instead of a model call, with a cap on judge rejections. Before that, 7 of 27 runs with the model judge hit the 900 s timeout. Earlier rounds were a tie and the report keeps them: docs/pi-vs-mini-benchmark.md.

Graphics with separate provenance

The 11 October full dev sweep was 62.5% (10/16). A later targeted composite reached 75% (12/16); it was not a fresh full sweep. The single-run 0.69x speed ratio belongs to another experiment and did not hold in the three round-6 repetitions.

The graphics below keep provenance beside every result. Public leaderboard data uses another corpus and is not a like-for-like ranking of mini.

Release card: v0.43.0, bots that run your board, with the 19 Oct run's figures and their limits

Every mini-vs-pi run as one bar, each with the corpus, model and judge it came from

Historical 19 October closure-on result, with evidence limits

Per-task historical medians, with shared zero-based scales

Terminal and web implementation changes, without a speedup claim

Obsolete, kept for context. docs/img/time-per-task.png (11 October dev sweep) carries the earlier dev-sweep framing and is referenced by nothing in this repo. It is not a like-for-like view of the corpus above and should not be quoted; it is kept only as a historical artifact until someone decides to archive or drop it.


Reference

Everything below is the detailed reference for the terminal UI, the web app, the agents and the configuration.

Features

  • Prompt bar, Claude-Code style. A compact multi-line prompt pinned to the bottom of the screen — long lines wrap to the next row and the box grows with your text (up to 8 rows): type your task (Alt+Enter / Ctrl+J for a hard new line), hit Enter, and keep typing follow-ups while the agent works (or after it submits) — they continue the same conversation.

    prompt bar

  • Command palette. Typing / opens real-time completion over the available commands (/model, /settings, /model <id>): filter as you write, pick with ↑/↓ or a mouse click, fill into the prompt with Enter/Tab (it never sends for you).

    command palette

  • $skill — skills anywhere in the prompt. Type $ at any point of the phrase and a panel lists the skills, filtering as you type on any word of the name, in any order ($body and $body-pr find pr-body); Enter/Tab inserts $name, painted in the skill color. A prompt like follow $good-code, then use $better-ui, $pr-body, and finish with $pr-fix-loop hands mini every referenced skill's instructions, then your prompt verbatim; the transcript shows just what you typed. Unknown $names stay plain text.

  • Skills inherited from Claude Code. mini-tui keeps its own folder, ~/.config/mini-tui/skills/ (override with MINITUI_SKILLS_DIR). At install (bun install runs the sync) and at every startup, each skill in ~/.claude/skills that folder doesn't have yet is copied in, including symlinked skills and the synced/<bucket>/ layout. Copies are never overwritten, and a skill you delete from mini-tui's folder is not re-imported. bun run sync-skills runs the sync by hand.

  • Bundled skills, carried everywhere. mini-tui ships its own skills in skills/: $e2e (how agents write and run mini-agent-rs e2e tests), $e2e-army (how agents write and run TesterArmy e2e tests, npx e2e with e2e.config.ts, whose agent steps run on MiniMax MiniMax-M3.1-Flash-Preview with the key from ~/.env) and $subagents (how an agent splits work across its own subagents). They are installed into the skills folder at install and at every startup of the TUI, -p and the web server; a newer bundled version replaces an unedited copy, while an edited or deleted one is left as you made it. mini-agent-rs e2e skill prints $e2e on hosts with only the binary.

  • The TUI and the web app on the same session. Every UI records the agent it runs for a session. Opening that session elsewhere (the web app, another terminal) follows the same agent live instead of starting a second one: its output streams in as it is written, and a prompt, /model or /compact sent from either UI reaches it. Closing one view leaves the agent to the other. Sessions that a terminal continued while the web app held them are reloaded before the next message, so a conversation never forks.

  • Subagents (/subagents). With the Rust agent, a session can split its work across child agents it owns (details). /subagents lists them with their state, steps and cost; each one is saved as a session, so /resume opens it.

  • /compact. Summarizes the conversation now, with or without a run in flight. While it runs, the transcript shows Compacting... and the status line compacting. Auto-compaction (at 80 % of the context window) shows the same state.

  • Only what you sent. The transcript shows your prompt as typed — never the harness' task template wrapping — the final answer is rendered as proper markdown (bold, code, links), and the redundant exit Submitted echo of it is never shown.

  • One quiet card per bash step (command + its output), shadcn-style: zinc neutrals, rounded surfaces, a single subtle accent and semantic colors used sparingly. A single status line under the prompt carries everything: the animated load state while the agent works (⣾ ▓░░░░ working · 34s), the selected model, the working path and the checked-out git branch. Nothing sits below it.

  • Output display modes — collapsed (just a 1 tool call line), trimmed to 2 lines, or fully expanded. The model's thinking follows the same three states (Thinking... while it works, Thought for {n} seconds when done), and your prompt is echoed into the thread the moment you send it. Pick one in the settings panel (/settings); it persists across runs. e still expands or collapses any block individually. Expanded output is capped at 500 lines with a ... N lines hidden ... marker.

  • Flat memory, always. The transcript is mounted in a viewport-sized sliding window (two viewports, 24–120 items depending on terminal height; g pages older ones in, G returns to the live bottom) and every text block is clipped, so an all-day run keeps a flat footprint instead of growing with the conversation.

  • Six themes — shadcn (zinc, default) plus nord, dracula, gruvbox, tokyo night and catppuccin. Also in /settings (Tab switches group): moving the selection repaints the whole UI live and the choice persists.

    settings panel

  • /resume — saved sessions in SQLite. Every conversation is stored (~/.config/mini-tui/sessions.db) with an AI-generated title (falling back to your prompt, trimmed). /resume opens a modal listing the sessions started in the current folder, paged and searchable by title — pick one to restore its transcript, and your next prompt continues the same conversation with full context (mini --resume, companion patch 3). Not sure which one it was? → (or clicking [→ preview]) shows the selected session's transcript read-only inside the same panel — scroll it with ↑/↓, PgUp/PgDn, g/G; ←/Esc goes back to the list, Enter opens it.

    resume modal

  • /connect — BYOK providers. The whole MiniMax Code catalog — Xiaomi MiMo, DeepSeek, OpenCode Go, Z.AI (GLM coding), MiniMax — plus OpenAI, Anthropic, Moonshot, Zhipu, Groq and OpenRouter. Pick a provider, paste your API key, choose a model and the connection is tested for real (a one-token query through mini's own model layer) before being saved locally. Every catalog model of a connected provider joins the /model picker, and its key is injected into your runs, including runs the agent starts itself (subagents, a model switch mid-run). Every provider runs on its own direct base URL (xiaomi/…, deepseek/…, anthropic/…, …) with a dedicated key/base env slot — no litellm. Saved connections on the generic openai/ slot (OPENAI_API_BASE/OPENAI_API_KEY) keep working for any OpenAI-compatible endpoint.

    connect wizard

  • Select-to-copy. Highlight any text in the UI with the mouse and it lands on your clipboard the moment you release — transcripts, commands, outputs, whatever. It works inside tmux (OSC 52 passthrough + the tmux paste buffer, prefix+]) and falls back to wl-copy/xclip/ xsel/pbcopy when available.

  • Modals, not layout shifts. /model, /settings, /resume, /connect and /help open as floating modals centered over the transcript — the prompt bar and the bottom stack never move, and panels clip to the available area on short terminals.

  • /help lists every command and key in one panel.

    help panel

  • Tool call cards with syntax-highlighted bash commands and a quiet focus marker.

  • Output cards with rc=0 / rc=N badges, exception info, and collapsible bodies (… 220 lines hidden · [e] expand) so huge outputs never blow up the layout.- Live header with model, step count, running cost and a spinner while a step is in flight.

  • /model — switch models mid-conversation. Type /model in the prompt to open the model picker (or /model <id> to jump straight to one). During a live run the agent picks the new model up from its next step — no restart, no lost context. The last model you pick (in any session) is remembered in ~/.config/mini-tui/last-model.json and becomes the default of new mini-tui terminals; windows that are already open keep their own model. -m and $MINITUI_MODEL still take precedence.

    model picker

  • Agent commits are authored by you. Runs export GIT_AUTHOR_* / GIT_COMMITTER_* from the account logged into gh (GitHub noreply email), falling back to git config --global user.* — commits never show up as "claude". MINITUI_GIT_IDENTITY=0 disables it.

  • Plain-text final answers (with the companion patch below): the agent finishes by simply answering instead of shuttling its answer through a temporary markdown file. The answer lands in the green exit banner, and you can type a follow-up to keep going.

    final answer

  • view mode renders any existing trajectory (including ~/.config/mini-swe-agent/last_mini_run.traj.json) with the same renderer.

Web app

The same agent, in a browser, with every session running at once in panes and windows:

  • split the screen like tmux, up to 12 panes in a window;
  • group panes into as many windows as you like, each with a working, done or idle dot per pane in the sidebar;
  • move any pane to another window from its menu, rearrange the panes of a window (a menu step in each direction, a row / column / grid layout, or drag one onto another to swap them);
  • resize the notes of a session freely inside its pane, the width kept per pane;
  • keep the same layout on every device (it lives on the server).

Each session streams over its own WebSocket, and a remote mode keeps the agent headless on a server over SSH while the UI stays on your machine.

mini-tui web app: four sessions side by side in a window called Backend, three of them working; the sidebar lists the Backend, Frontend and Release windows with a status dot per pane

A pane's menu, offering to move the pane to the Frontend or Release window or to a new one The same windows in the sidebar of a phone
Move a pane to another window, or to a new one. The same windows on a phone.

mini-tui web app: a running session with a thinking receipt, a command and its result, and the answer

bun run web          # build the UI and serve everything on http://127.0.0.1:4317
bun run web:dev      # Vite dev server, hot reload

Sessions started in the browser land in the same ~/.config/mini-tui/sessions.db the terminal UI's /resume reads, so both front ends see each other. A session running in a terminal opens live in the browser: the web app follows that terminal's agent (its output streams in, your prompts go to it) instead of showing a frozen copy or starting a second agent, and the terminal does the same for a session the browser runs. Opening a session never fails because a terminal is saving at that moment: the database runs in WAL mode, so readers never wait for a writer. /resume works in the browser too, even from a new chat with nothing running: it lists every saved session, searchable, and sending a message continues the one you pick.

What the web app does:

  • History in the sidebar, by recency or grouped by folder.
  • A folder picker for new chats that also browses remote hosts.
  • Prompt memory with ↑/↓.
  • A toast when a session finishes, with a View button that jumps to it.
  • Panes like tmux (Ctrl+\), up to 12 in a window, and as many windows as you like: the sidebar lists them with a pane count and a New window button, and any pane can move to another window or to a new one from its pane menu.
  • A side panel in every pane, with two tabs:
    • Notes, saved as you type.
    • Terminal, a real shell in the session's folder (over SSH for a remote session) that survives hiding the panel and reloading the page. Open it with Ctrl+` or /terminal.
  • Settings with an interface size and a separate text size.
  • Subagents above the transcript. A session whose agent started subagents shows them in a strip under its header, each with a status dot, its steps and its cost. Click one to follow it live in the pane (and message it like any session); its own strip links back to the parent. /subagents [name] lists them or opens one.

One workspace on every device: the windows, panes and sidebar are kept on the server, so a phone, a laptop and a second tab all show the same thing, and a change on one appears on the others live.

Notes, the terminal, the shared workspace and prompt memory all travel over one hub WebSocket per tab, with no REST polling. A server restart (a deploy) does not lose your panes: sessions reopen from the saved history when the page reconnects.

The terminal is a shell as the user the server runs as, so keep the server behind authentication, or turn the terminal off with MINITUI_WEB_TERMINAL=0. Remote runs need mini-tui on the server; the hosts panel has a Test button that checks reachability and agent presence.

To run it as a service, deploy/mini-tui-web.service is a systemd unit. Agents and the terminal can use sudo there just as in the terminal UI, limited by the account's own sudoers rules. Do not add NoNewPrivileges=true: it makes every sudo fail.

A new chat is a draft. /new shows an empty chat and creates nothing; the first message creates the session on the model and host you picked.

new chat

Commands and skills. / opens commands, $ opens skills (the terminal's own matching). A pick becomes a chip and is joined to your text only when you send.

slash commands

Model switcher. Searchable and grouped by provider, fully keyboard-driven, and it opens from the prompt bar. A model missing from the list can be typed.

model picker

Settings and providers. Test a key with a real request before it is saved. Keys never come back out of the server: reads carry a masked hint.

providers

The prompt bar is one line when empty and grows a line at a time up to five, then scrolls. Chips keep the field a plain textarea, so IME, autocorrect and paste all keep working.

mini-tui web app on a phone: the session transcript and the prompt bar mini-tui web app in light mode

Built for touch as well as a keyboard: 44px targets on a finger, bottom-sheet dialogs, safe-area insets and dvh layout. Light and dark, six accent palettes. Full details: web/README.md.

Landing page and docs

site/ is the project's landing page and documentation: SvelteKit prerendered to static HTML (every route is a real .html file, readable with JavaScript off), Tailwind 4 with shadcn-svelte components, and scroll-reveal motion that only ever hides content it is about to animate in.

cd site && bun install
bun run dev         # http://127.0.0.1:4320
bun run build       # prerender every route to site/build
bun run seo         # audit the built pages: titles, descriptions, canonicals, JSON-LD, alt text, links, sitemap
bun run browse      # real-browser check at desktop / tablet / phone
bun run layout      # width audit: no sideways scroll, no squeezed column, at 320 to 1440 px

The canonical origin comes from VITE_SITE_URL, and the base path is derived from it, so links, canonical tags and the sitemap cannot disagree. .github/workflows/site.yml runs the audits and publishes to GitHub Pages on every push to main that touches the site. Docs are markdown in site/src/content/docs/.

Themes

Six palettes — pick one in /settings (Tab to the theme group): moving the selection repaints the whole UI live and the choice persists.

shadcn (default) nord dracula
shadcn nord dracula
gruvbox tokyo night catppuccin
gruvbox tokyo night catppuccin

Requirements

  • Bun ≥ 1.3 (OpenTUI ships a native Zig renderer; Node ≥ 26.4 also works)

  • An agent, one of:

    • Python ≥ 3.10 with the bundled agent installed (pip install -e ./agent), or any mini on your PATH;
    • the Rust agent: no Python needed, either a release binary or cargo build --release in agent-rs/.

    ~/.config/mini-swe-agent/.env is honored either way.

Install

git clone https://github.com/jaivial/mini-tui && cd mini-tui
bun install
python3 -m pip install -e ./agent   # bundled mini-swe-agent → `mini` + `mini-swe-agent-tui`

# optional: make `mini-tui` available everywhere
cp bin/mini-tui ~/.local/bin/mini-tui && chmod +x ~/.local/bin/mini-tui

Without Python, download the static Rust agent instead of the pip install step. mini-tui finds it there on its own:

mkdir -p ~/.local/lib/mini-tui
curl -Lo ~/.local/lib/mini-tui/mini-agent-rs https://github.com/jaivial/mini-tui/releases/latest/download/mini-agent-rs-x86_64-linux-musl
chmod +x ~/.local/lib/mini-tui/mini-agent-rs

Usage

# Just start it: the prompt bar is ready (like `mini -y -m <model>`, but pretty)
mini-tui
mini-tui -m xiaomi/mimo-v2.6-flash

# Or start immediately with a task
mini-tui run "Fix the failing test in test_utils.py" -m xiaomi/mimo-v2.6-flash

# Render an existing trajectory (add --follow to keep watching it)
mini-tui view ~/.config/mini-swe-agent/last_mini_run.traj.json

# Include the system prompt in the transcript
mini-tui run ... --show-system

Headless: mini-tui -p (no TUI)

-p / --print runs a session with no UI, like claude -p, opencode run or pi -p: the same integrated agent (tools, $skills, /connect providers, follow-up context) runs one turn, the answer goes to stdout, and the process exits with the run's status. Scripts, CI jobs, cron and other agents can drive mini-tui this way.

# Only the final answer on stdout (quiet by default)
mini-tui -p "Fix the failing test in test_utils.py" -m xiaomi/mimo-v2.6-flash

# Verbose: every step (commands, outputs, notices) streams to stderr, the answer to stdout
mini-tui -p "why is the build red?" -v

# Machine-readable: one JSON result, or JSON lines as the run happens
mini-tui -p "list the TODOs" --json | jq -r .result
mini-tui -p "refactor utils.py" -o stream-json | jq -c 'select(.type=="tool_call")'

# Pipe context in (stdin is appended to the prompt, or is the prompt)
git diff | mini-tui -p "review this diff"

# Sessions continue exactly like /resume in the TUI
mini-tui -p "now add tests" --continue          # latest session of this folder
mini-tui -p "and the docs" --resume s-mugx      # any session, id or unique prefix
mini-tui -p --compact --continue                # /compact from the shell

# Guard rails for unattended runs
mini-tui -p "..." --max-steps 30 --cost-limit 1 --timeout 900 --cwd ~/repo --no-session
Option Meaning
-m, --model <id> model of this run (default: $MINITUI_MODEL, the resumed session's model, else the last /model pick)
-o, --output-format text (default) · json · stream-json (--json = -o json)
-v, --verbose stream every step: text → stderr; json → adds events; stream-json → thinking and full outputs
-q, --quiet the answer only: no error tail on stderr
-C, --continue / -r, --resume <id> follow up in the latest / a given saved session
--compact compact a --continue/--resume session instead of sending a prompt
--no-session don't save the run to the /resume history
--cwd <dir> working directory of the run
--max-steps, --cost-limit, --timeout agent.step_limit, agent.cost_limit, agent.wall_time_limit_seconds
-c, --config <spec> extra mini config (key=value specs merge into the default config)

Exit codes: 0 submitted, 1 the run failed or hit a limit, 2 usage error, 130 interrupted (Ctrl+C / SIGINT once interrupts the agent, twice kills it).

The json result (also the last stream-json line) carries result, subtype (success/error/interrupted), is_error, exit_status, session_id, model, cwd, num_steps, api_calls, cost_usd, duration_ms, trajectory_path, log_path and, on failure, error. stream-json starts with an init line (session id, model, runner, paths), then one line per transcript event (task, assistant, tool_call, observation, notice, exit, and thinking with -v).

Scripting commands

Everything the TUI's slash commands do also works from a shell (add --json to any of them):

mini-tui sessions [--all] [-n 20] [-s text]   # /resume history (this folder, or all)
mini-tui sessions show <id>                   # print a transcript
mini-tui sessions rm <id>                     # delete a session
mini-tui models                               # /model catalog + /connect providers (* = default)
mini-tui model [<id>]                         # print / set the default model (what /model saves)
mini-tui skills                               # $skills
mini-tui settings [output-mode|theme <value>] # /settings
mini-tui --version

Run artifacts live under ~/.config/mini-tui/runs/<timestamp>-<slug>/ (traj.json + its append-only traj.jsonl journal, mini.log, pid, control). mini-tui never touches ~/.config/mini-swe-agent/last_mini_run.traj.json — it always passes its own -o.

Keys

Key Action
Enter send the prompt (starts a task, or continues the running conversation)
Alt+Enter / Ctrl+J insert a newline in the prompt (Shift+Enter too where the terminal reports it)
/ opens the command palette: ↑/↓ or click to select · Enter/Tab fills the prompt (never sends)
$ anywhere in the prompt: opens the skills panel (filters as you type) · Enter/Tab inserts $name
/compact summarize the conversation now (frees context)
/subagents list the subagents this session started (each is a session: /resume opens it)
↑ / ↓ (in the prompt) browse the prompts sent in this session · ↓ past the newest restores your draft
Esc close the palette / leave the prompt · double Esc interrupts the run
ctrl+c clear the prompt · press it twice (within 1.5 s) to close
ctrl+\ show / hide the error console (Esc closes it)
/quit · /exit close mini-tui
/help commands and keys
/model open the model picker (or /model <id> for a direct switch)
/settings output display (collapsed / trimmed / expanded)
/new start a fresh session in place (stops the current run; model and settings stay)
/resume browse sessions saved in this folder (search + pages, → previews a transcript read-only)
/connect connect a BYOK provider (key → model → tested connection)
j / k (or ↓ / ↑) (navigation mode) move between tool call blocks
e expand / collapse the focused output block
PgUp / PgDn scroll half a screen · mouse wheel scrolls 3–5× (burst-accelerated)
g / G load older steps (viewport-sized pages) / back to the live bottom

How it works

mini-tui run
  ├─ src/mini/spawn.ts   starts `mini-swe-agent-tui` (or falls back to `mini`)
  │                      raw stdout/stderr → <session>/mini.log
  ├─ src/traj/watch.ts   polls <session>/traj.json every 200 ms (rewritten by the harness per step)
  ├─ src/traj/parse.ts   pure parser: messages → RunEvent[] (tools, outputs, notices, exit)
  └─ src/ui/             OpenTUI + React renderer (cards, badges, banners, prompt, /model picker)

The parser tolerates mid-write reads (the harness rewrites the file non-atomically after every step), unknown message shapes, and multimodal content in any of the message formats mini produces.

Follow-ups and /model under the hood

mini-tui appends MESSAGE <text> / MODEL <id> lines to the run's control file (<session>/control, exported to mini as MSWEA_CONTROL_FILE). The companion harness patch:

  • injects MESSAGE lines as UserNewTask prompts — from the agent's next step mid-run, and after a submission via an exit hold (the run stays open so one conversation can span many turns);
  • applies MODEL switches from the next step.

One agent, several UIs

Each UI that starts an agent records it in the live_runs table of sessions.db (session, trajectory, control file, pid). Another UI opening that session checks that the pid still runs that trajectory, then follows it the same way: it reads the same journal and writes to the same control file. So the web app, the terminal and a subagent's parent all drive one process, and whichever UI started it decides when it ends.

The Rust agent (optional)

agent-rs/ is a Rust port of the bundled agent's runner. It uses the same command line, configs, trajectory, journal and control file, packaged as one self-contained binary.

Python agent Rust agent
Start a run ~190 ms ~2 ms
A session waiting for your next message ~36 MB ~4 MB
Needs Python ≥ 3.10 + the agent's packages nothing (static build: any x86-64 Linux)
cd agent-rs && cargo build --release      # or: --target x86_64-unknown-linux-musl (static)
mini-tui                                  # uses it: Rust is the default once the binary is there
MINITUI_AGENT=python mini-tui             # the Python agent instead

Prebuilt binaries (mini-agent-rs-x86_64-linux-musl, …-linux-gnu, SHA256SUMS) are attached to every release.

Does the Rust agent use more tool calls, or take longer? No. Both agents send the model byte-identical prompts, so the model batches commands into replies exactly the same way and neither one makes it do more work. Two parity scenarios lock that in: turns (a model that batches several commands per reply must produce the same turns, tool calls and trajectory on both) and batch-calls (the same over the wire, with every request body compared byte for byte). The Rust agent also gets to its first model request sooner (~7 ms vs ~173 ms). If two runs of the same task really do differ, the difference is on the model side — sampling and context pressure decide how much a model batches per reply — and not in the runner.

Rust is the default for the terminal UI, mini-tui -p and the web app, whenever the binary is found: MINITUI_AGENT_BIN, else agent-rs/target/release/mini-agent-rs, else ~/.local/lib/mini-tui/mini-agent-rs, else mini-agent-rs on PATH. The binary also generates session titles and runs the providers panel's connection tests, so nothing runs through Python. Without a binary, mini-tui uses the Python agent as before; MINITUI_AGENT=python chooses it on purpose, and MINITUI_AGENT=rust says so when the binary is missing. mini-tui points the binary at the bundled YAML configs (MINI_AGENT_CONFIG_DIR), so a copy installed outside the checkout works too.

It covers everything mini-tui uses:

  • The loop: limits, follow-ups, /model, /compact and automatic compaction, --resume, interrupts.
  • Models: cli-proxy, Rosetta, DeepSeek, Xiaomi, OpenAI, Anthropic, the provider registry and OpenCode Go.
  • Environments: local and docker.

agent-rs/tests/parity/run_all.sh runs both agents on the same scripted tasks and scripted HTTP servers: 31 scenarios plus 8 helper cases. It checks that they write identical trajectories, exit the same way and send identical requests. See agent-rs/README.md for what is and is not ported.

Subagents

A session on the Rust agent can split its work across subagents it owns. The model drives them from its bash tool, and the bundled $subagents skill teaches it how:

mini-agent-rs agent spawn api "write the API tests" --cwd ~/repo --max-steps 60
mini-agent-rs agent send api "also cover the 404 path"   # mid-run, or continue a finished one
mini-agent-rs agent resources              # free memory, avg child cost, how many more may start
mini-agent-rs agent ls | wait | result | tail | model | stop
mini-agent-rs agent ask "which branch?"                   # inside a subagent: ask the parent
  • One process per subagent. It keeps its whole context between turns, so a follow-up is a single message, not a new run replaying the history. A message sent mid-run lands before its next step. One that exited continues from its saved conversation under the same name.
  • It reports back by itself. When a subagent finishes, fails, stalls or asks something, the parent reads a [subagent <name>] … message before its next step. A parent that already ended its turn is woken by it, so the orchestrator never spends steps polling.
  • Owned by the session. Subagents stop with it, count toward its cost limit, and run on its current model unless told otherwise. Up to 100 run at once per hub, with resource admission guards. Recursive depth has no fixed default cap; set MINI_AGENT_MAX_DEPTH=N for an explicit cap (0 means uncapped). Depth alone does not bypass memory, concurrency, cancellation or provider limits.
  • It never OOMs the box. Before you fan out, agent resources reports the free memory, the measured average memory of the running subagents, and max fan-out now: min((free - 10 GiB reserve) / average child, CPU headroom, 100 - live). Every spawn runs the same calculation at the gate, so a child that would not fit is refused — the session, and every other child, keeps running.
  • Visible everywhere. Each subagent is saved as a session under its parent: the web app shows them above the transcript, the TUI lists them with /subagents, and any of them opens live.
  • Your connected models, no extra key. A subagent on another model (-m minimax/...) gets that model's key from your /connect providers (~/.config/mini-tui/providers.json), like a run you start yourself. Nothing has to be exported first. A variable you did set still wins.
  • The parent reviews before it accepts. A subagent's summary is a claim. The $subagents skill has the parent check the diff, the build and the tests itself. When something is missing or wrong, the parent sends the review back to that same subagent (agent send <name> "<review>"): each finding with its file and line, and the check to rerun. The subagent fixes the work with all its context, and the parent reviews again until nothing is left. After 3 rounds stuck on one finding it moves that subagent to a stronger model (agent model).

A run that starts no subagent behaves exactly like the Python agent: the parity suite still compares every scenario byte for byte. $orchestration's orch forwards its commands to the session's subagents when it runs inside a Rust session. Its detached headless runs remain for your own terminal and the Python agent. Full reference: agent-rs/README.md.

Agents (delegation, handoffs, fan-out)

With the Rust agent, mini-tui gives the model five native tools on top of bash: agent_define (a named specialist: description, when to use it, its system prompt, its model), agent_route (which agent fits a task), agent_delegate (one task, or tasks to fan out), agent_message (to the parent, a sibling or a subagent) and agent_handoff (finish your part and pass the work to the next agent). A general-purpose agent, general, is built in; definitions the model creates live in ~/.config/mini-tui/agents/.

  • Every agent is a session. It starts as a byte-for-byte copy of the session that started it (the delegating one, or for a handoff the agent handing over) with the model switched to its own, plus its task appended after the copy. The copy is the prefix the provider has cached: on the same model the source's last call already wrote it; on another model the hub first warms that model's cache with the copy (one call, max_tokens 1) and starts the agents once it is written. Each agent's first-call cached tokens are measured and shown.
  • Background, never blocking. Delegating returns at once; the session keeps working and is told when an agent finishes. Messages land before the recipient's next step, or wake it.
  • Chains between peers. translator hands off to reviewer; the reviewer messages the translator its corrections and waits; the translator's answer goes back to the reviewer (not to the parent); the reviewer hands off to deployer. The parent is woken when the chain ends.
  • Recursive fan-out. An agent can delegate to subagents of its own (login -> backend + frontend); its turn end while they work is a wait, not a report.
  • Agents panel (web). The side panel's Agents tab draws the tree (parent -> children -> grandchildren) with live state, model, steps, cost and cache reuse, and the timeline of delegations, handoffs, corrections, replies and fan-outs. Any agent opens as its own session.

a translation chain: translator -> reviewer (corrections, second review) -> deployer

a recursive fan-out: login delegates backend and frontend, running in parallel

The shared context (ContextStore)

A subagent that re-reads what the orchestrator already read is the single biggest cost in a fan-out. Measured on a real orchestration (6 subagents, 2 repos, 2026-10-07): 122,039 of 184,342 tokens (66%) were discovery, 28 files were re-read that the parent had already read, and 3 integration failures were found by the parent reading diffs, not by any subagent.

So the exploration is paid for once and handed over, in the run tree's context/ folder, with a schema instead of a social contract:

# The orchestrator fills it, after exploring and before delegating:
mini-agent-rs agent state put findings.md  --prompt-file f.md   # symbols, files, lines found
mini-agent-rs agent state put contracts.md --prompt-file c.md   # the contract + producers/consumers
mini-agent-rs agent state put decisions.md --prompt-file d.md   # what was decided and why
mini-agent-rs agent state put surface.backend.md --prompt-file s.md   # callers, types, payloads

mini-agent-rs agent spawn api-worker --cwd ~/repo/backend --repo backend "add the field"
  • Handed over by default. A child receives the documents that name the repos it works in, scoped: a backend child gets surface.backend.md and the ## backend sections of findings.md / contracts.md, and is not billed for the frontend's. It happens whether or not the parent remembered --context-file — --repo R names the repos explicitly, otherwise they are read from the child's own --cwd. MINI_AGENT_CONTEXT=0 turns it off.

  • Cheap to consult. mini-agent-rs agent surface <symbol> answers "who calls this and which contract does it carry" out of what is already indexed, in one call, instead of grepping the tree again. agent surface ls lists what is indexed.

  • The handshake goes back. When a child's turn ends the hub parses its own final answer into three lines — what it touched and who calls it, what contract field it emitted or read, and anything that contradicted the brief — and stores it as <child>.md for the next child. In a live run, that surprise line is how a subagent reported that the backend emitted group_menu_enabled while the frontend struct expected groupMenuEnabled, with no mapping layer: a real integration failure, caught at the child's own turn instead of by the parent reading diffs.

  • Checked mechanically, not by reminder. mini-agent-rs agent contract-check --repo R runs by itself when a child's turn ends: every file it claims to touch exists and is under the repo, every field the contract names for that repo appears where it should, and a no <invariant> clause is checked literally against the touched files. No model in the loop. A claim that does not hold fails loudly instead of reaching the parent as a summary. There is a fourth check, coverage, for the failure mode that matters most here: a check that examined nothing must never be able to say pass. If no file was claimed and no clause of the contract names the repo, it fails and says "This is NOT a pass". Five separate ways to get a green check over an empty corpus were found by running real orchestrations — a child's prose without a surface: tag, a comma inside a sentence inventing a file name, the word There read as a field name, --repo parsed into a key the arm never read, and a child's worktree directory mistaken for its repo. All five are fixed; the shape they share is that a mechanical check was parsing free text with a rule free text does not obey.

    Two more defects in the same arm came out of the same probing (fixed in 0.38.2): --prompt-file was ignored (so a control was answered about a different child's text), and the positional handshake was dropped whenever --repo was given. All three invocation forms are now verified to examine the text they are handed.

    The best proof that it works came from an agent, not from a test: an orchestrator received 4/4 pass, did not trust it, copied the tree to /tmp, deleted the wire field, re-ran the check, got 4/4 pass again — and reported its own integration check as toothless. That negative test is how the last defect was found.

Measured on a real orchestration driven in the web UI with subagents (same task, 2 repos, orchestrator + 2 children), against the run without the store:

without with
child discovery tokens ~3,197 ~1,456 (-54%)
orchestrator tokens ~26,699 ~12,093 (-55%)
integration bugs caught by a subagent 0 1 (a snake_case/camelCase mismatch)

Duplicate reads do not go down, and that is expected: a child still reads the file it has to edit. What the store removes is the orientation work around it.

The clearest measurement of the fix, same 6-file two-repo task, orchestrator exploring once:

before after
discovery tokens per subagent ~1,962 ~0
subagent steps 40 28

Fewer steps for more work. The honest caveat: the orchestrator pays for the exploration up front, so on a repo this small its own cost still roughly matches what a child would have spent, and total tokens went up. It amortises with more children or a bigger repo — which is exactly the shape the baseline measurement (66% of tokens spent rediscovering) came from.

Two delivery paths, one message. The store is not the only context a child gets at launch: the local graph RAG (MINI_AGENT_GRAPH_RAG_URL, docs/semantic-delegation.md) adds retrieved historical evidence in a <graph-context> block right after the <context> blocks. They are independent switches — MINI_AGENT_CONTEXT=0 turns off only the store, unsetting the URL turns off only the retrieval — and since 2026-10-21 they are deduplicated at the launch point: a hit whose text is already in the delivered blocks/brief/task is dropped instead of delivered twice (dedup_skipped in the graph_retrieval event audit, and no empty <graph-context> block when every hit was already there).

The RLM harness (mini-agent-rs rlm)

The Rust binary also carries a small RLM (Recursive Language Model) harness in pure Rust — experimental, behind its own opt-in subcommand (nothing else in the binary couples to it): an execution framework that treats long-horizon context as program variables and sub-agents as function calls, inside a persistent REPL. A script (or the rlm> prompt) binds what matters with let, and call runs a whole sub-agent to completion and hands its answer back as a value — recursively, up to a depth cap:

mini-agent-rs rlm                       # interactive; variables and functions auto-persist
mini-agent-rs rlm script.rlm            # or run a script (exit 1 on the first error)
let repo = mini-tui              # context is variables; {{repo}} interpolates (strict Jinja)
def worker(q)                    # a sub-agent is a function call
let r = ask {{q}}                #   one turn: model + bash tool until it answers
return {{r}}                     #   the answer is the call's value
end
let out = call worker(check the tool)

ask is one model turn on the current conversation, run is shell, set writes globals from inside a function, and the state (rlm.json) survives restarts. No Python, no framework: the same model layer the agent uses. Full reference: agent-rs/README.md.

Bundled mini-swe-agent

agent/ vendors mini-swe-agent (v2.4.6 base via git subtree --squash) together with everything mini-tui's nicest behaviors need, so pip install -e ./agent is one install that carries:

  1. Integrated runner — mini-swe-agent-tui shares the public CLI's config merge, model loop, journal, resume format, and MSWEA_CONTROL_FILE protocol, but skips Typer, Rich, prompt interaction, and the interactive-agent module on the normal yolo path. mini-tui probes for it once; MINITUI_EMBEDDED_AGENT=0 forces the compatible mini CLI fallback.
  2. Plain-text final answer — a response with text and no tool calls is the submission (no more cat > /tmp/final_answer.md round-trips).
  3. Control file — MODEL <id> switches the running agent's model from its next step; MESSAGE <text> continues the conversation mid-run or at the exit hold (both no-ops when MSWEA_CONTROL_FILE is unset).
  4. --resume — reloads a previous conversation's message history as context and treats the new task as a follow-up (what /resume + prompt uses).
  5. Custom model providers — xiaomi (MiMo), rosetta, cliproxy, deepseek, opencode_go and openai model classes, with mini extra <provider>-models to list their catalogs.
  6. Append-only trajectory journal — <traj>.jsonl gets one line per message (O(1) per step, never torn) and the full traj.json export is compact, atomic and throttled; mini-tui reads the journal and parses only the new bytes per tick.
  7. Slim default install — the direct HTTP clients do not need the openai SDK; benchmark datasets live behind the benchmarks extra (mini-swe-agent[full] includes it).

Upstream sync: git subtree pull --prefix=agent --squash <upstream> <ref>. The original patch descriptions (kept for upstreaming) live in docs/mini-swe-agent-patches.md.

Performance

Trajectory persistence, measured on a synthetic 300-step run (the agent saves after every step):

full rewrite per step (old) append-only journal + throttled export (now)
Bytes written 235.4 MB 4.3 MB (55× less)
Persistence time 0.99 s 0.12 s (8× faster)

The TUI itself is bounded and lean: the transcript mounts a viewport-sized sliding window (two viewports, 24–120 items depending on terminal height), so memory stays flat no matter how long a run gets; g pages older items in and G returns to the live bottom. The 0.3.0 render pass then cut the measured footprint by ~30 % across the board — on the standard 400-step repro: 18.6 s → 13.1 s CPU and peak RSS 323 → 228 MB. In 0.5.0 blocks got 3.6× leaner (plain text unless the text really has markdown — measured 0.33 → 0.09 MB per block): the same repro now settles at 205 MB, and a plain-prose run at 152 MB. Agent-side, prompt_toolkit loads lazily (35 → 20 MB import). In 0.7.0 the local/subscription gateways (cliproxy/, rosetta/, xiaomi/) talk to their OpenAI-compatible endpoint directly instead of through litellm: a real claude-opus-5-5 run peaks at 40 MB instead of 214 MB and answers ~2.3 s sooner. Since 0.9.0 every provider (DeepSeek, OpenAI, Anthropic, OpenCode Go included) talks to its base URL directly and litellm is an optional extra (docs/PLAN-litellm-detach.md).

pi-parity speed work (docs/pi-speed-analysis.md): the loop's own overhead is 0.027 s/step (median, measured on 28 headless runs) while 83 % of wall time is the model. Three of the remaining losses are now closed: retries honour Retry-After / retry-after-ms first and use pi's min(0.5 × 2^i, 8) s shape for throttles (measured corpus: 392 s of waiting → ~136 s); a step's independent commands run overlapped (up to MINI_AGENT_PARALLEL_ACTIONS, default 2) instead of strictly serially, results kept in input order; and the journal no longer clones the whole conversation per step (serialize_info + the unjournaled tail, max(20, len/10) messages or 60 s between full exports).

0.13.0 integrated-runner benchmark (scripts/benchmark-runtime.py, seven fresh Python 3.10 processes, deterministic one-step run, no network): public mini ~205–212 ms / ~39 MiB peak RSS; bundled mini-swe-agent-tui ~160–170 ms / ~34 MiB — about 20% faster and roughly 5 MiB less resident memory. The measurement excludes the TUI process itself; it covers the agent startup/run path that the TUI launches. Run python3 scripts/benchmark-runtime.py --runs 7 to reproduce.

The TUI ingestion path has its own terminal-free benchmark: bun run benchmark:tui -- 5000 appends 10,002 realistic trajectory messages and measures only the incremental parser (about 11–12 ms on the current machine). The randomized item-index tests cover tool/observation pairing fallbacks and prefix replacement, so long-run CPU growth is measurable without opening a TTY.

See docs/PLAN-ram-reduction.md for the plan and numbers.

Development

bun test          # parser fixtures + in-memory OpenTUI render tests (no TTY, no network)
bun run typecheck
bun run screenshots   # regenerates docs/screenshots/*.png from scripted scenes
bun run benchmark:tui -- 5000   # terminal-free long-run parser + item-index benchmark
MINITUI_AGENT=python bun test   # the same suite on the Python agent (Rust when its binary is built)

cd web && bun run e2e           # the web app in a real browser (see web/README.md for the others)
cd web && bun run build && bun scripts/bundle-report.mjs   # chunk sizes, and what a cold visit downloads
cd agent-rs && cargo test --release && sh tests/parity/run_all.sh   # Rust agent: unit + parity

Notes and known limits

  • Yolo only: runs use the integrated agent entry (or the compatible mini -y --exit-immediately fallback) — the UI visualizes and forwards prompts, it never confirms or rejects commands.
  • No token streaming in the terminal UI: the transcript updates once per step, so the spinner covers model calls and command execution. The web app shows the reply as it streams. Follow-ups sent mid-step are picked up at the next step.
  • After a submission the run stays open ("type to continue") while the TUI is attached; quitting the TUI ends it.
  • The code highlighter degrades to plain text when a tree-sitter grammar is unavailable.
  • If the TUI is killed hard, the agent child may survive: check <session>/pid and pgrep -af "minisweagent.run.tui|mini-agent-rs|mini -y --exit-immediately".

Native visual reads (Rust)

With MINITUI_AGENT_TOOLS=1, read recognizes PNG, JPEG, GIF and WebP by their byte signatures. It attaches the original image as a bounded (8 MB) data URL, with a separate user visual block after the tool result. Chat, Responses and Messages wire shapes preserve the image; an empty multimodal_regex does not disable this route. Images do not accept text pagination. Code-mode text reads reject raster bytes rather than returning broken pixel text.

The provider and chosen model must still support images. Vendor support and wire preservation do not prove that a specific endpoint has interpreted an image correctly. This does not change a running benchmark's binary or tool gate.

Native tool filesystem scope

Host-native read, write, edit and Rhai code are available only for the local environment. Other environments fail closed with a tool error and a bash fallback, so container paths cannot accidentally read or change host files. Docker still executes bash in the container working directory. A native container bridge is not implemented by this guard. STOP is checked before each inline native action in a concurrent batch.

Queue goal versions and durable events

Queue edits remain limited to pending tasks; each put increments goal_version and clears old results. Claims carry the version. Both managed workers and direct finish calls require positive closure evidence bound to task ID, current fence and goal version, with a trajectory reference. Plain done is refused. This is recorded evidence, not an independent proof that a judge is correct.

queue events --db PATH --after SEQ --limit 100 returns a durable sequence cursor for created, goal_updated and state_changed events. Consumers deduplicate by seq and resume after their last persisted cursor. Heartbeats do not emit state events. SQLite triggers write events in the same transaction as task changes. Existing tasks are not given invented historical events. Running-goal amendment and live worker notifications remain a separate integration step.

Read-only queue event API

GET /api/task-events?after=SEQ returns up to 100 durable queue events and a resume cursor. /api/task-events/stream uses SSE event task, with id set to seq. Resume with Last-Event-ID or after; store/deduplicate seq on the client. The server reads without schema migration or worker/model calls, at most once per 5 seconds per stream, limits streams to16 and closes with queue-error on unavailable data. Same-origin protection, 5-second child timeout and cursor validation apply. This is an API, not yet a task-board UI or a verified main-chat delivery path.

Context evidence limits

Contract checks now read indexed files from the current contained tree instead of counting index labels as code. Index reads are capped at256 files,512KB per file and4MB corpus, with missing coverage reported. All named identifiers in a positive clause must be present as code tokens; one matching word is insufficient. Coverage requires actual file contents. Prose invariants are flagged for semantic review, never declared safe by an absent/present token. Mechanical checks do not certify types, caller/producer-consumer mappings or complete repository coverage.

Rhai code-mode limits

The existing Rhai code tool is a batching alternative, not JavaScript/QuickJS parity with current Pi. It now respects STOP during interpreter progress, caps a single print and the entire returned observation at60KB without splitting UTF-8, and limits reads to8 concurrent file-reader threads. Pure-script time/operation bounds remain; registered host tools still perform real actions. This does not add async JS, non-LLM image classifiers or a result store.

Explicit queue follow-ups and cancellation

queue amend --id ID --goal-version N --goal-file FILE appends a follow-up only to the explicitly named task at the expected version. It clears stale vector/results. Running tasks are fenced and interrupted; managed workers check their lease/version once a second and stop on revocation. Reconcile the stopped process before retrying with the updated goal. This avoids an old goal closing a new request; it is a safe restart route, not live in-place delivery. Ambiguous similarity never edits a task.

queue cancel --id ID --goal-version N cancels pending/blocked tasks. A running task stays interrupted (blocking conflicting claims) until its worker is stopped and reconciled. Cancellation-request status is not a claim that all external effects were undone.

After verifying the previous worker is stopped, queue cancel-reconcile --id ID --goal-version N --reconciled yes converts interrupted to cancelled and releases ownership. The operator assertion is explicit; the CLI does not pretend to inspect an arbitrary external worker.

Channel inbox preparation

Transport-neutral ChannelInbox stores explicitly bound Gmail/WhatsApp/Apple-Messages routes with session/project and approved sender handles. Ingestion is transactional, bounded, deduplicated by account/thread/message ID and ordered by arrival cursor while retaining provider time/reply-to. A conflicting duplicate is refused. Evo normalizes messages.upsert data only after transport authentication, using the account supplied by trusted configuration rather than the webhook claim; self echoes and ambiguous sender direction are refused. Group messages require participant identity. Media references are not fetched automatically. Audio transcription attaches to the original audio with pending/complete/uncertain/failed state, never a second task.

This is internal adapter/storage preparation. No HTTP receiver, account connection, webhook configuration, Gmail/Apple transport, external send, task launcher or bot identity is enabled by importing it. Bindings are operator configuration, not grants from message content. Transport authentication and owner permission must be checked before calling accept; incoming words cannot authorize arbitrary external effects. Real channel end-to-end and multi-chat work remain open.

Queue from the mini-tui CLI

mini-tui queue <action> forwards to the selected Rust task-graph binary without taking over the TUI. It preserves queue arguments and stdout/stderr, defaults to MINITUI_TASK_GRAPH_DB, and passes SIGINT/SIGTERM to the queue lifecycle. Non-worker calls have a10-second timeout; output is bounded to4MB per stream. Mutations are attempted once. A timeout/interruption may follow a committed write, so inspect current state before retrying. This shared bridge is ready for main/web clients, but importing it does not launch a worker or prove that main conversation routing is integrated.

Context coverage snapshots

Every contract-check records a coverage..json manifest with contained paths and SHA1 content digests of the exact bounded files examined, unread exclusions, scope/root and check time. SHA1 is a freshness fingerprint, not a security guarantee. Changes since the previous check fail the snapshot check and request refreshed findings/contracts. Manifests explicitly state partial repository coverage and unverified semantic contracts. A new snapshot does not automatically repair an index, prove full coverage or check a Git revision.

Queue event client preparation

QueueEventsClient shares a read-only SSE subscription among watchers, deduplicates durable seq, refreshes the graph after events, reconnects after5 seconds and retries failed snapshots without losing the pending event. It guards stale fetches after all watchers leave and removes timers/streams. No mutations or model polling. This is a client building block; the task panel has not yet been wired to it or visually verified.

About

A pretty terminal UI for mini-swe-agent: parses and reformats tool calls and outputs, with live /model switching.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages