Desktop GUI for the bonsai stack. Tauri 2 + React + TypeScript + Tailwind. A calm, documentation-grade surface, ink on warm paper, serif display type, monospace micro-labels, hairline rules, for chatting, coding and running deep research against a local suiban server. Everything happens on your machine.
A dai (台) is the display stand a bonsai is presented on.
Author: Yağızhan Keskin (github.com/YKesX)
Two surfaces, switched from the sidebar: Chat and Code.
- Chat is streaming conversation with the local 27B orchestrator: markdown, code copy, image attach (vision runs on the 27B; the control disables itself, with a hint, when no 27B is resident), an effort dial (low to max) and an ultra toggle ("orchestrator+agents") that fans a task out to contained sub-agents.
- Deep research runs inline in Chat behind a quiet research switch: sending starts an async job, coarse progress (stage, percent, elapsed, a rough remaining estimate, cancel) renders in the thread and the finished cited report renders right there as markdown. There is no separate research view.
- The model picker is a quiet footnote select in the composer: auto, the resident bonsai models and any external providers you configured (Ollama or an OpenAI-compatible endpoint), grouped under their prefix. External models are honest proxies: chat only, so the research and ultra toggles disable with the caption "external models chat only".
- Code is session-first agentic coding: a task plus a workspace folder, then a visible plan card, file tree, diff previews and a live tool-activity feed. Destructive steps pause on a confirmation card that shows the exact operation, a shell command or a file edit as a unified diff, to approve or decline. A bypass confirmations toggle (marked DANGER, off by default) skips the cards for a run and raises a persistent banner. Follow-up turns continue the same session.
The sidebar holds the Chat | Code switch, session search, New and the archive: Chats and tasks (sessions and research jobs in one list), Projects (per-project sessions plus plain-text knowledge docs), Scheduled (recurring prompts with cadence, run-now and last-error) and Recents fed by the server's auto-generated titles. Chat and Code keep separate recents, since the lists filter by the active segment. System and Settings sit at the bottom.
- System: the live residency state (cold, loading, ready or idle-unloading) with the keep-alive setting, models loaded, VRAM per GPU with quiet usage bars, headroom, analytic-vs-measured budget labels, KV-cache and TurboQuant state, quant family (configured vs effective) and every server notice, verbatim.
- Settings gathers every knob, with secrets write-only:
- Connection: point dai at a local or remote suiban (host:port) with an optional bearer token for a non-loopback bind, checked against the health probe.
- Runtime: the keep-alive control (stay hot or unload after N minutes idle) and a SLAP agent-protocol toggle (Structured Lightweight Agent Protocol, on by default).
- Quantization: family (ternary or 1-bit) with the TurboQuant disclaimer toggle and preset.
- External providers (Ollama or OpenAI-compatible, write-only API keys) and the web search provider for research, each with a test button.
- MCP: the built-in connector catalog with enable toggles, plus custom stdio servers (MCP changes apply on the next loadout restart).
- Skills: a skills creator ("New skill" scaffolds agentskills.io-compatible markdown with live name validation) alongside edit and delete, plus Import skills from a chosen folder.
- Import chats from OpenAI, Claude, Claude Code or generic exports, optionally compressed into a resumable seed; imported sessions land in the archive.
- Gateways: Telegram, plus WhatsApp device linking by QR code (scanned like WhatsApp Web) for research-complete and scheduled-run pings.
- A memory editor (browse, edit, delete; the identity layer is read-only).
- First-run guidance: when suiban is reachable but binaries or model weights are missing, Chat shows a dismissible panel with the exact copy-paste install commands and the one-time download sizes. No fake progress bars.
Keyboard: Ctrl/Cmd+K opens the command palette (navigation, effort, theme);
Enter sends, Shift+Enter breaks the line. Full light and dark themes from a
single token file, system-following with manual override and
prefers-reduced-motion respected throughout.
Two commands from a fresh clone to a built app, then one to run it:
./install.sh # 1-2. npm install, then npm run build (typecheck + vite build -> dist/)
npm run tauri dev # run: the desktop shell (needs the Rust toolchain)./install.sh just runs npm install and npm run build for you and prints the run
commands; run them by hand if you prefer.
- Desktop app.
npm run tauri buildpackages the click-to-launch app and needs the Rust toolchain (rustup).npm run tauri devruns the same shell without packaging. - Web (dev).
npm run devserves the UI in your browser against a bundled mock suiban (contract-shaped fixtures, including error and degraded states), so the GUI develops with no model stack running. SetVITE_DAI_MOCK=0to hit a real server.
dai talks to suiban over the frozen HTTP contract in
suiban/docs/api.md. The
zero-config default is a local suiban at http://127.0.0.1:8686. When suiban is
reachable but binaries or model weights are missing, Chat shows a dismissible first-run
panel with the exact install commands and one-time download sizes; install suiban from its
own repo, then suiban serve.
Local or remote. Settings → Connection sets the suiban server address (host:port) and,
for a non-loopback/remote suiban, a bearer token. Both are persisted locally (never in a
repo) and applied to the API client. This works today in the web/dev build. One honest
caveat for the packaged desktop app: its Tauri Content-Security-Policy currently
allowlists the default 127.0.0.1:8686, so pointing the bundled app at an arbitrary
remote host needs a widened CSP (TODO(v1.1)); until then, the web build (npm run dev)
reaches any server the Connection card is pointed at.
npm run dev # web dev server against the bundled mock suiban (default in dev)
npm run tauri dev # full desktop shell (requires Rust toolchain)
npm run test # vitest
npm run lint # eslintThe mock in src/mocks/ is contract-shaped (including error and degraded-state fixtures),
so the GUI develops without a running model stack.
dai is built with React, Tauri (v2), Tailwind CSS, Vite and TypeScript, tested and linted with Vitest and ESLint. Chat and reports render through marked, sanitized with DOMPurify and highlighted with highlight.js.
The design tokens are measured from DTX-AI with the author's permission; the dark theme is our own derivation from the same token file.
Sibling repos in the bonsai stack: suiban (inference and orchestration core), sentei (CLI) and SLAP (the agent protocol).
Apache-2.0.


