
The chat interface is the primary interaction surface of Memo. It supports real-time streaming, rich content rendering, and deep integration with the local backend.
Messages are delivered token-by-token over Server-Sent Events (SSE). The Go backend streams tokens as they are generated by the inference engine:
// Backend SSE handler pattern
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
for token := range llm.Stream(ctx, prompt) {
fmt.Fprintf(w, "data: %s\n\n", token)
flusher.Flush()
}
The Flutter frontend renders each token immediately via Riverpod state updates, creating the appearance of the model "typing" in real time.
All model responses are parsed as GitHub-Flavored Markdown and rendered with full support for:
| Format | Support |
|---|---|
| Headings | H1–H6 with anchor IDs |
| Code Blocks | Syntax highlighting via highlight.js (Go, Python, JS, Bash, YAML, JSON, Dart) |
| Inline Code | Monospace with bronze accent |
| Tables | Responsive, striped hover rows |
| Lists | Ordered and unordered, nested |
| Blockquotes | Styled callouts ([!NOTE], [!WARNING], [!TIP], [!DANGER]) |
| Links | Auto-linked URLs, internal doc cross-references |
| Images | Rendered inline from markdown image syntax |
Drag and drop files or images directly into the chat input area:
Type / in the chat input to reveal the command palette:
| Command | Action |
|---|---|
/agent |
Activate Agent Mode for tool-calling workflows |
/orchestra |
Start Orchestra Mode with expert roles |
/search |
Search RAG memory with semantic query |
/model |
Switch active model |
/incognito |
Toggle incognito mode |
/clear |
Clear current conversation |
/export |
Export conversation to Markdown |
Speech-to-text runs entirely on-device via whisper.cpp (bundled with the application):
# whisper.cpp runs as a subprocess managed by the Go backend
whisper-cli -m models/ggml-base.bin -f audio.wav -l auto
The globe icon in the chat top bar toggles web search. When it's on, the model gets a web_search tool (DuckDuckGo, no API key needed) via native function-calling, in the same request that produces its reply — it decides per message whether the question actually needs a live search, and picks its own query, rather than every message triggering a search regardless of content. See Agent Mode for the full mechanism, which this toggle shares with Agent Mode's own toolset (just scoped down to this one tool). Turned off entirely under Minimal Mode.
Toggle incognito mode to create ephemeral sessions. In this mode:
Use incognito mode for sensitive discussions, one-off queries, or testing model behavior without polluting your memory store.
marked with deferred syntax highlighting