{"id":50086459,"url":"https://github.com/unbalancedparentheses/stoa","last_synced_at":"2026-05-22T20:07:19.071Z","repository":{"id":339666513,"uuid":"1162075298","full_name":"unbalancedparentheses/stoa","owner":"unbalancedparentheses","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-28T21:22:38.000Z","size":231,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-01T00:41:48.858Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unbalancedparentheses.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-19T21:02:02.000Z","updated_at":"2026-02-28T21:22:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/unbalancedparentheses/stoa","commit_stats":null,"previous_names":["unbalancedparentheses/stoa"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/unbalancedparentheses/stoa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbalancedparentheses%2Fstoa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbalancedparentheses%2Fstoa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbalancedparentheses%2Fstoa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbalancedparentheses%2Fstoa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unbalancedparentheses","download_url":"https://codeload.github.com/unbalancedparentheses/stoa/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unbalancedparentheses%2Fstoa/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33364341,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-21T12:23:38.849Z","status":"online","status_checked_at":"2026-05-22T02:00:06.671Z","response_time":265,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-22T20:07:18.504Z","updated_at":"2026-05-22T20:07:19.065Z","avatar_url":"https://github.com/unbalancedparentheses.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stoa\n\nA native AI research platform built with Rust. Send the same prompt to multiple models simultaneously, compare responses side-by-side, diff where they agree or disagree, and track costs — all from a single keyboard-driven interface. Zero Electron, zero JavaScript.\n\n## Why Stoa?\n\nMost AI chat apps let you talk to one model at a time. Stoa lets you **interrogate multiple models in parallel** and see where they converge or diverge. Built for researchers, engineers, and anyone who wants to think harder with AI.\n\n- **Native performance** — Pure Rust + GPU rendering via [iced](https://github.com/iced-rs/iced). Starts instantly, uses minimal resources.\n- **Local-first** — All data stays on your machine. SQLite database, no cloud sync, no telemetry.\n- **Keyboard-driven** — Quick Switcher, Command Palette, and shortcuts for everything.\n\n## Features\n\n### Multi-Model Research\n- **Parallel streaming** — Send to 2-7+ models at once, watch all responses stream simultaneously\n- **Side-by-side comparison** — Toggle comparison mode to view responses in columns\n- **Response diffing** — Word-level diff highlights agreements vs. differences with percentage\n- **Per-conversation system prompts** — Different personas for different research threads\n- **Conversation forking** — Branch at any message to explore alternative directions\n\n### Model Support\n- **OpenAI** — GPT-5, GPT-4.1, o3, o4-mini\n- **Anthropic** — Claude Opus, Sonnet, Haiku\n- **Ollama** — Auto-discovers locally installed models. No API key needed.\n- **OpenRouter** — 200+ models via a single API key (Gemini, Llama, Mistral, DeepSeek, Qwen, and more)\n\n### Analytics \u0026 Cost\n- **Cost tracking** — Estimated token counts and USD cost per message, conversation, and session\n- **Response ratings** — Thumbs up/down on any response, tracked per model\n- **Analytics dashboard** — Per-model stats: response count, tokens, cost, latency, approval rate\n\n### Organization\n- **Tags \u0026 Pins** — Tag conversations, pin important ones to the top\n- **Quick Switcher (Cmd+K)** — Fuzzy search across all conversations\n- **Command Palette (Cmd+P)** — Every action in one searchable list\n- **Full-text search** — FTS5-powered search across titles and message content\n- **Markdown / HTML / JSON export** — Copy any conversation to clipboard in multiple formats\n- **Auto-titling** — AI generates meaningful titles after your first exchange\n- **ChatGPT import** — Import your full ChatGPT history from `conversations.json`\n\n### Multimodal \u0026 Web\n- **Image/Vision** — Attach images and send them to vision-capable models\n- **Text file attachment** — Native file dialog for code, text, and config files\n- **Web search** — Inject DuckDuckGo search context into your prompt\n\n### Security\n- **OS keychain** — API keys stored in macOS Keychain / Linux Secret Service / Windows Credential Manager\n- **No telemetry** — Zero data collection, all conversations stored locally in SQLite\n\n## Keyboard Shortcuts\n\n| Shortcut | Action |\n|----------|--------|\n| `Enter` | Send to primary model |\n| `Cmd/Ctrl+Shift+Enter` | Send to all models |\n| `Cmd/Ctrl+K` | Quick Switcher |\n| `Cmd/Ctrl+P` | Command Palette |\n| `Cmd/Ctrl+E` | Export as Markdown |\n| `Cmd/Ctrl+N` | New conversation |\n| `Cmd/Ctrl+,` | Settings |\n| `Esc` | Dismiss overlays |\n\nAll keybindings are configurable in **Settings**.\n\n## Installation\n\n### Prerequisites\n\n- **Rust** (2024 edition) — [rustup.rs](https://rustup.rs/)\n- **GPU-capable system** — iced uses wgpu for rendering\n- **Ollama** (optional) — [ollama.com](https://ollama.com/) for local models\n\n### Build \u0026 Run\n\n```sh\ngit clone https://github.com/unbalancedparentheses/stoa\ncd stoa\ncargo run --release\n```\n\n### Ollama Setup (Optional)\n\n```sh\n# Install Ollama\ncurl -fsSL https://ollama.com/install.sh | sh\n\n# Pull a model\nollama pull llama3.2\n\n# Stoa auto-discovers local models on startup\n```\n\n## Usage\n\n### Single Model\nType a message, press Enter. Goes to the model shown in the picker chip.\n\n### Parallel Multi-Model\n1. Click the model chip to open the picker\n2. Check multiple models\n3. Type your prompt, click **Run N** (or `Cmd+Shift+Enter` for all)\n4. All responses stream in simultaneously\n\n### Comparison Mode\n1. Send to multiple models\n2. Click **Compare** in the chat header\n3. Responses appear side-by-side in columns\n4. Click **Show Diff** to see word-level differences\n\n### Research Workflow\n- Set a per-conversation system prompt via the **Sys** button\n- **Fork** at any message to branch the conversation\n- **Rate** responses with thumbs up/down to track model quality\n- View aggregated stats in the **Analytics** tab\n- **Tag** conversations for organization, **pin** important ones\n\n## Configuration\n\nConfig path: `~/.config/stoa/config.json`\nData path: `~/.config/stoa/chat.db`\n\n| Setting | Description |\n|---------|-------------|\n| API Keys | Stored in OS keychain (falls back to config file) |\n| Ollama URL | Defaults to `http://localhost:11434/v1/chat/completions` |\n| System Prompt | Global default (overridden by per-conversation prompts) |\n| Temperature | Generation temperature (default 0.7) |\n| Max Tokens | Max output tokens (default 4096) |\n| Keybindings | All shortcuts are remappable |\n\nEnable `RUST_LOG=info` (or `debug`) to see structured log output.\n\n## Comparison\n\n| Feature | **Stoa** | BoltAI | msty | Cherry Studio | Jan | AnythingLLM | MindMac | TypingMind | Open WebUI | LibreChat | Chatbox AI |\n|---|---|---|---|---|---|---|---|---|---|---|---|\n| Platform | Rust/GPU native | macOS | All | All | All | All | macOS | Web | Web | Web | All |\n| Open source | Yes (MIT) | No | No | AGPL | AGPL | MIT | No | No | Custom | MIT | GPLv3 |\n| Multi-model parallel | **Yes** | No | Yes | Yes | No | No | No | Yes | Yes | No | No |\n| Side-by-side comparison | **Yes** | No | Yes | Yes | No | No | No | Yes | Yes | No | No |\n| Response diffing | **Yes** | No | No | No | No | No | No | No | No | No | No |\n| Local LLMs (Ollama) | **Yes** | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |\n| Cloud providers | 4+ (200+ via OR) | 6+ | 10+ | 50+ | 5+ | 3+ | 7+ | Many | OAI-compat | 8+ | Many |\n| Cost tracking | **Yes** | No | Yes | No | No | Partial | Yes | Partial | Yes | Yes | No |\n| Command palette | **Yes** | No | No | No | No | No | No | No | No | No | No |\n| Quick switcher | **Yes** | No | No | No | No | No | No | No | No | No | No |\n| Conversation forking | **Yes** | Yes | Yes | No | No | No | No | Yes | Partial | Yes | No |\n| Image/Vision | **Yes** | Yes | ? | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes |\n| Web search | **Yes** | Yes | Yes | ? | ? | ? | Yes | Yes | Yes | Yes | ? |\n| ChatGPT import | **Yes** | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |\n| OS keychain | **Yes** | ? | ? | No | No | No | ? | N/A | N/A | N/A | ? |\n| FTS5 search | **Yes** | ? | ? | ? | ? | Yes | ? | ? | Yes | Yes | ? |\n| Analytics/Stats | **Yes** | No | Yes | No | No | Partial | Yes | No | Yes | Partial | No |\n| Response ratings | **Yes** | No | No | No | No | No | No | No | Yes | No | No |\n| RAG / Knowledge base | No | No | Yes | Yes | No | **Yes** | No | Yes | **Yes** | No | Yes |\n| AI Agents / MCP | No | Yes | Yes | Yes | Yes | **Yes** | No | Yes | **Yes** | **Yes** | Yes |\n| Plugins | No | Yes | Yes | Yes | Yes | **Yes** | No | Yes | **Yes** | **Yes** | Yes |\n\n### Stoa's Unique Advantages\n\n- **Response diffing** — Word-level LCS diff with agreement percentage. No competitor has this.\n- **Command palette + Quick switcher** — Obsidian-style keyboard-driven navigation.\n- **Native Rust/GPU** — Not Electron, not Tauri, not web. Pure Rust + wgpu rendering.\n- **OS keychain** — API keys in your system's secure credential store, not plaintext config files.\n\n## Architecture\n\n```\nsrc/\n  main.rs              Entry point\n  lib.rs               Library root\n  app.rs               State, Message enum, update loop, view\n  model.rs             Conversation, ChatMessage, Provider\n  config.rs            AppConfig, model routing, keychain integration\n  db.rs                SQLite + FTS5 persistence, migrations, search\n  cost.rs              Pricing table, token estimation\n  diff.rs              Word-level LCS diff\n  export.rs            Markdown / HTML / JSON export\n  import.rs            ChatGPT import parser\n  shortcuts.rs         Shortcut specs + key matching\n  commands.rs          Command palette entries\n  web_search.rs        DuckDuckGo search integration\n  theme.rs             Color palette\n  handlers/\n    streaming.rs       Stream lifecycle, auto-titling\n    send.rs            Message sending, retry, review, analyze\n  api/\n    mod.rs             LlmEvent, stream dispatch, shared HTTP client\n    openai.rs          OpenAI + Ollama + OpenRouter streaming\n    anthropic.rs       Anthropic streaming\n    ollama.rs          Model discovery via /api/tags\n  ui/\n    chat_view.rs       Messages, comparison mode, diff panel\n    input_bar.rs       Input, model picker, file/image attach\n    sidebar.rs         Nav, search, history, tags, pins\n    right_panel.rs     Streams, system info, cost, shortcuts\n    analytics.rs       Per-model stats dashboard\n    settings.rs        Provider config, keybindings\n    quick_switcher.rs  Cmd+K overlay\n    command_palette.rs Cmd+P overlay\n    shortcut_help.rs   Shortcut cheat sheet\n    markdown.rs        Markdown renderer (pulldown-cmark)\n    diagnostics.rs     Debug diagnostics view\n    bottom_bar.rs      Status bar\n```\n\n## Roadmap\n\n- [ ] MCP tool support\n- [ ] RAG / Knowledge base\n- [ ] PDF/DOCX file attachment\n- [ ] Conversation folders\n- [ ] Plugin system\n- [ ] Voice input/output\n- [ ] Cross-platform testing (Windows, Linux)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funbalancedparentheses%2Fstoa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funbalancedparentheses%2Fstoa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funbalancedparentheses%2Fstoa/lists"}