Skip to content

Web Chat

Web Chat is AI Butler’s flagship channel. It’s one of two channels marked [ready] in v0.1 (the terminal REPL is the other) — the remaining 10 channels (Telegram, Slack, Discord, WhatsApp, Teams, Google Chat, LINE, IRC, webhook, Nostr) are in beta pending real-world validation. When you run ./aibutler run, you immediately get a production-quality web chat at http://localhost:3377 with no additional configuration.

This page is a full visual tour — every screenshot is live output from a running instance.

Terminal window
./aibutler run

That’s the entire setup. Open http://localhost:3377 and you’re chatting. No API keys, no vault entries, no credentials, no OAuth flow, no external dependencies beyond the model provider you’re already using.

By default it binds to all interfaces on port 3377 so you can reach it from any device on your LAN (phones, tablets, other laptops). For localhost-only, change bind_address in config.yaml — see Configuration below.

AI Butler welcome screen with a top-hat logo, 'What can I help you with?' heading, tagline, and a 6-card grid of starter prompts (Morning briefing, Remember something, Schedule a task, Explore files, What do you know?, What can you do?)

When you first open the web chat, you land on the welcome screen with 6 starter prompt cards. Click any one and it pre-fills the input — or just type your own. The starters cover the core capability areas (memory, scheduling, file exploration, self-introspection) so new users see the breadth immediately without having to read docs.

The header pills at the top right show live state:

  • Butler (blue) — the active persona name
  • $1.61 used (green) — cost spent this period, pulled live from /api/dashboard/costs
  • connected (green) — WebSocket connection status (flips to connecting / offline as the connection state changes)

The sidebar has six panels. Click any one to switch views — the chat panel stays alive in the background so you never lose your conversation.

Standard conversational interface with streaming token-by-token replies, file upload, voice upload, and natural-language prompting. Returns to the welcome screen when the conversation is empty; shows the message thread when you start chatting.

AI Butler Home panel with 4 live tiles (Memories saved, Conversations, Spent this period, Connected apps) and a Quick Actions row with 4 prompt shortcuts (Morning briefing, Set a daily reminder, Summary about me, Show skills)

Four live tiles pulled from /api/dashboard/stats:

  • Memories saved — total count of notes, people, and key facts in the knowledge graph
  • Conversations — how many sessions you’ve had
  • Spent this period — live USD cost from the model API
  • Connected apps — how many messaging channels are active

Plus a Quick Actions row with six pre-written prompts that jump back to the Chat panel with the input pre-filled. Perfect for repeating common tasks (morning briefing, daily reminder setup, summary-about-me, etc.).

3. Memories — browse what Butler knows about you

Section titled “3. Memories — browse what Butler knows about you”

AI Butler Memories panel showing mini-stats (1 note, 6 people & things, 2 key facts) and a list of recent notes with source labels and timestamps, plus a tip hint with a 'Try it' inline link

Shows the memory system’s contents directly:

  • Mini-stats — notes, people & things, key facts
  • Recent notes — cards with source label, timestamp, and content
  • Tip hint — clickable “Try it” link that pre-fills a “remember this” prompt

This is the panel that makes the memory system tangible. Users can see exactly what the agent remembers about them and when it was learned. See Memory & Knowledge for the full architecture.

4. Connected Apps — which channels are active

Section titled “4. Connected Apps — which channels are active”

AI Butler Connected Apps panel with Web Chat shown as active (green border + Connected badge) and 6 Add Another cards for Telegram, WhatsApp, Slack, Discord, Teams, and Custom Webhook linking to per-channel setup docs

The “Active right now” section shows which channels are currently running. In v0.1 only Web Chat is [ready], so you’ll see one active card with a green “Connected” badge.

Below that, an “Add another” grid links to setup guides for the 11 beta channels: Telegram, WhatsApp, Slack, Discord, Teams, and a “Custom Webhook” card for any HTTP-capable platform. Each link opens the relevant docs page.

AI Butler Spending panel with a big gradient card showing $1.61 spent this period, followed by a per-model breakdown list (claude-sonnet-4-6 484.8k tokens $1.61) and a hint about setting budget alerts in Settings

Live per-model cost breakdown that updates every time a model call completes:

  • Big gradient card — total spent this period
  • Per-model list — each model you’ve used, with total tokens and cost
  • Budget hint — pointer to set monthly alerts in Settings

The update is debounced so it doesn’t jitter on every token, but it feels real-time on any practical model call.

AI Butler Settings panel with three sections: Appearance (Theme Auto/Light/Dark, Language EN/AR), Welcome Screen (show again button), and About (Activity stats like '10 conversations · 6 things saved · 1 notes', Version v0.1.0, Docs and GitHub links)

Three grouped sections:

  • Appearance — Auto/Light/Dark theme picker (Auto honors your system preference) and language selector (EN / AR with RTL support; 12 more languages planned)
  • Welcome screen — “Show again” button to reset the welcome-screen dismissal
  • About — Activity summary with consumer-friendly language (“10 conversations · 6 things saved · 1 notes”), version number, and links to docs + GitHub

Everything is persisted in localStorage per-browser, so preferences survive reloads but don’t leak across devices.

AI Butler Home dashboard rendered in dark mode with proper contrast for all tiles, cards, pills, and chat elements

Every panel, tile, pill, chat bubble, and form element has a hand-tuned dark variant. Click the button top-right (or pick Dark in Settings) and the whole UI re-themes. System preference detection is on by default — your OS’s light/dark setting controls the initial choice, and your manual override persists in localStorage.

Drag and drop any file into the chat input — or click the 📎 paperclip icon — and it’s uploaded before the next message sends.

Out-of-the-box support:

  • Images (JPEG, PNG, WebP, GIF) — passed to vision-capable models
  • Documents (PDF, DOCX, TXT, Markdown) — extracted and indexed into memory
  • Audio (MP3, WAV, OGG, M4A) — transcribed via the configured STT provider
  • Spreadsheets (CSV, XLSX) — parsed into structured data
  • Archives (ZIP, TAR) — listed and optionally extractable

The max_upload_size_mb config controls the per-file limit (default 25 MB).

The 🎤 microphone button (appears on the chat panel when available) uses the browser’s MediaRecorder API to capture audio, streams it to the server, and the server transcribes via the configured STT provider (Whisper by default). The transcribed text is processed as a normal text message, so memory capture and tool calls work the same way as text input.

STT provider setup: AI Services → Speech-to-text.

AI Butler mobile view of the welcome screen at 390x844 viewport — header collapses, sidebar becomes a hamburger drawer, starter cards stack vertically

The entire UI is mobile-responsive. On narrow viewports (≤900px) the sidebar collapses into a hamburger drawer that slides in from the left with a backdrop overlay:

AI Butler mobile view with the sidebar drawer open, showing all 6 nav items and the brand header, over a dimmed backdrop of the main chat area

Tap any nav item or the backdrop to close the drawer. All 6 panels work on mobile with the same functionality as desktop — no feature parity loss.

Access it from your phone over LAN at http://your-machine-ip:3377 — mDNS discovery (aibutler.local) is on the v0.1 roadmap. A PWA install is planned for v0.2.

Replies stream token-by-token via WebSocket — no polling, no full-page reloads, no “thinking…” spinners that hide progress. If the connection drops mid-stream:

  • The connection pill flips to orange connecting… and tries to reconnect every 2 seconds
  • If reconnection succeeds, the server’s response buffer is replayed so you don’t lose partial output
  • If reconnection fails, a red offline pill appears and a polite message lands in the chat area

All of this is in internal/webchat/static/chat.js — 409 lines of vanilla JS with no framework. Click “View Source” in your browser to read the entire client-side implementation.

By default Web Chat is open on the configured bind address. For LAN use that’s fine — your LAN is the security boundary. For internet-exposed deployments, enable authentication:

configurations:
auth:
enabled: true
session_timeout: 24h
require_totp: false

Supported methods (all [beta] in v0.1 pending real-world validation):

  • Password — bcrypt-hashed, per-user
  • TOTP 2FA — RFC 6238, any authenticator app
  • OIDC SSO — Auth0, Okta, Keycloak, Authelia, ZITADEL, Google Workspace
  • FIDO2 / WebAuthn — hardware security keys (YubiKey, SoloKey, Apple Touch ID)

Full setup: Authentication.

configurations:
web:
port: 3377 # default; change to any free port
bind_address: 0.0.0.0 # 127.0.0.1 for localhost-only
max_upload_size_mb: 25 # per-file limit in MB
ModeHow
Localhost onlyDefault bind_address: 127.0.0.1 + open http://localhost:3377
LANbind_address: 0.0.0.0 + open http://<your-ip>:3377 from any device on the network
InternetPut behind nginx / Caddy / Traefik with TLS — see VPS deploy guide
Pair from phoneLAN mode + scan the QR code on the terminal / display (planned v0.2)

Page loads but no replies. Check the browser console. WebSocket errors usually mean your reverse proxy isn’t upgrading HTTP connections. For nginx, make sure proxy_http_version 1.1, Upgrade, and Connection headers are set. For Caddy, a simple reverse_proxy localhost:3377 handles WebSocket automatically.

File uploads fail at larger sizes. Increase max_upload_size_mb in config.yaml and restart. If you’re behind a reverse proxy, also bump that proxy’s body size limit (client_max_body_size 30M; in nginx).

Slow first-token latency. Usually model-related, not web chat. Check which provider you configured in Choose Your AI. Ollama on low-end hardware and cloud models during peak hours are the most common causes.

Connection pill stuck on “connecting”? The WebSocket upgrade failed. Check aibutler run output for webchat: listening on — if the server isn’t listening, review configurations.web.port for conflicts.

Dark mode stuck on the wrong theme? Clear localStorage: localStorage.removeItem('theme') in the browser console and reload. Or switch it explicitly in Settings → Appearance.

  • Server: Go net/http for HTTP, coder/websocket for WebSocket streaming
  • Static assets: HTML/CSS/JS embedded via //go:embed static/* — no separate file server, everything ships inside the 18 MB binary
  • Frontend: hand-written vanilla JS + CSS with no framework, no build step, no npm. Total: ~300 lines of HTML, ~350 lines of CSS, ~410 lines of JS
  • Streaming: token-by-token via WebSocket messages; the server buffers the stream so reconnection can replay
  • Dashboard API: 16+ JSON endpoints under /api/dashboard/* for panel data

All of this is in internal/webchat/. The total frontend is small enough to read in one sitting — we deliberately kept it framework-free so it’s easy to fork, modify, or replace.