# Meow - Rust Terminal AI Chat Client A high-performance terminal UI (TUI) AI chat client written in Rust, supporting custom OpenAI-compatible providers (DeepSeek, Kimi, etc.). ## Overview Meow is a pure-text terminal chat application. It features: - OpenAI-compatible provider abstraction layer - Real-time streaming (SSE) chat output - Markdown rendering with syntax highlighting - Persistent chat history in JSON Lines format - Mouse scroll support for message history ## Tech Stack | Component | Crate | |-----------|-------| | Async Runtime | `tokio` | | HTTP Client | `reqwest` (with streaming/SSE) | | TUI Framework | `ratatui` + `crossterm` | | Markdown Parser | `pulldown-cmark` | | Syntax Highlighting | `syntect` (fancy-regex backend) | | Serialization | `serde` + `serde_json` + `toml` | | Configuration Path | `dirs` (cross-platform home dir) | ## Architecture ### Layered Design ``` TUI Layer (ratatui widgets) ├── chat.rs (implicit in app.rs) ├── model_select.rs (popup) ├── provider_config.rs (form) ├── input.rs (multi-line text area) └── markdown.rs (rendering pipeline) App Layer (state machine) └── app.rs - coordinates all modules, event loop, async stream handling Provider Layer ├── providers/mod.rs - Provider trait └── providers/openai.rs - OpenAI-compatible implementation Storage Layer ├── config.rs - ~/.meow/config.toml ├── storage.rs - ~/.meow/data/sessions/*.jsonl └── message.rs - core data types ``` ### Data Flow 1. User types message in input box 2. `Enter` triggers `App::send_message()` 3. User message is saved to disk via `Storage::append_message()` 4. A tokio task spawns to call `Provider::chat_stream()` 5. SSE chunks flow back through `tokio::sync::mpsc::UnboundedChannel` 6. Main event loop polls channel via `App::poll_stream()` and redraws 7. When stream ends (`__STREAM_END__`), the full assistant message is persisted ## Project Structure ``` src/ ├── main.rs # Entry point: initializes tokio, Tui, App, event loop ├── app.rs # App state machine: Chat / ModelSelect / ProviderConfig ├── config.rs # Config & ProviderConfig structs, load/save to ~/.meow/config.toml ├── message.rs # Role enum, Message, ChatSession ├── storage.rs # JSON Lines persistence for chat sessions ├── providers/ │ ├── mod.rs # Provider trait, Model struct, ProviderError │ └── openai.rs # OpenAICompatibleProvider: /v1/models, /v1/chat/completions SSE └── tui/ ├── mod.rs # Tui struct: terminal init/restore, raw mode, panic hooks ├── input.rs # InputState: multi-line editor with cursor movement └── markdown.rs # MarkdownRenderer: pulldown-cmark -> ratatui Lines + syntect highlighting ``` ## Configuration Config is stored at `~/.meow/config.toml` (cross-platform via `dirs::home_dir()`). Example: ```toml [[providers]] name = "DeepSeek" base_url = "https://api.deepseek.com" api_key = "sk-..." default_model = "deepseek-chat" ``` Chat sessions are stored as JSON Lines at `~/.meow/data/sessions/.jsonl`. ## Keybindings | Key | Action | |-----|--------| | `Enter` | Send message | | `Shift+Enter` | Newline in input | | `Ctrl+P` | Open model selector | | `Ctrl+S` | Open provider config | | `Ctrl+N` | Start new chat session | | `Ctrl+B` | Toggle sidebar | | `Ctrl+R` | Reset current chat | | `Ctrl+C` | Stop streaming (while AI is typing) | | `Ctrl+Q` | Quit | | `Mouse Scroll` | Scroll message history | ## Provider Protocol The `Provider` trait (`async_trait`) defines: - `name() -> &str` - `config() -> &ProviderConfig` - `list_models() -> Result>` - `chat_stream(model, messages) -> Result>>` `OpenAICompatibleProvider` implements this for any OpenAI API-compatible endpoint. ## Markdown Support Rendered elements: - **Bold** / *Italic* - `Inline code` (dark background) - Code blocks with syntax highlighting (syntect themes) - Bullet / numbered lists - Blockquotes (│ prefix) - Horizontal rules ## First-Time Setup On first run, if no providers exist, the app automatically enters the **Add Provider** form. Fill in name, base URL, and API key to get started. ## Build ```bash cargo build --release ``` The binary will be at `target/release/meow.exe` (Windows) or `target/release/meow` (Unix).