# Claude Desktop — Projekt-Kontext Native Tauri-2.0-Desktop-App die Claude Code/Agent SDK als Backend nutzt. Schneller und maechtiger als Codium + Claude Code Extension. **Stand: 22.04.2026 — Alle Roadmap-Phasen (3-6) abgeschlossen.** Detail-Uebersicht: [README.md](README.md) | Phasen-Status: [ROADMAP.md](ROADMAP.md) | Aenderungen: [CHANGELOG.md](CHANGELOG.md) ## Tech-Stack - **Backend**: Rust 2021, Tauri 2 (`tray-icon`), tokio, mysql_async, rusqlite, reqwest, libc - **Frontend**: SvelteKit 2, Svelte 5 (Runes: $state/$derived/$effect), TypeScript, Vite 5, paneforge - **AI**: `@anthropic-ai/claude-agent-sdk` (query-Funktion), Ollama (optional, lokal) - **Sprache**: whisper-cli (STT, lokal), piper-tts (TTS, lokal, 5 deutsche Stimmen) - **DB**: MySQL (claude-db, 192.168.155.11) fuer Wissensbasis, SQLite lokal fuer Sessions/Settings/Queue - **IPC**: Unix Domain Socket (bevorzugt) oder stdio JSON-Lines - **Build**: NixOS shell.nix, Forgejo Actions → AppImage ## Wichtige Pfade | Was | Pfad | |-----|------| | Rust-Module (18) | `src-tauri/src/` | | UI-Komponenten (27) | `src/lib/components/` | | Stores | `src/lib/stores/` (app.ts, events.ts) | | Bridge | `scripts/claude-bridge.js` (~1100 Zeilen) | | Hauptlayout | `src/routes/+page.svelte` | | Chat-Fenster | `src/routes/chat-window/+page.svelte` | | Praesentation | `src/routes/presentation/+page.svelte` | | CI/CD | `.forgejo/workflows/build-appimage.yml` | | Dev-Shell | `shell.nix` | ## Architektur-Kurzreferenz ### Kommunikationskette ``` User → ChatPanel.svelte → invoke('send_message') → claude.rs → Bridge (UDS/stdio) → query() → Claude API → Events zurueck → claude.rs handle_bridge_message() → emit() → events.ts → UI ``` ### Bridge-Daemon (Phase 3) - **Socket**: `/tmp/claude-bridge.sock` - **PID-File**: `/tmp/claude-bridge.pid` - Start: `node claude-bridge.js --socket /tmp/claude-bridge.sock` - Rust verbindet sich per `UnixStream::connect()` - Auto-Reconnect bei Verbindungsverlust (3 Versuche) - Fallback auf stdio wenn UDS fehlschlaegt ### ClaudeState (claude.rs) ```rust pub struct ClaudeState { pub connection: Option, // Stdio oder Uds pub request_counter: u64, pub agents: Vec, } ``` ### Agent-Modi (claude-bridge.js) | Modus | Beschreibung | Prompt | |-------|-------------|--------| | `solo` | Claude arbeitet direkt | Kein Orchestrator | | `handlanger` | Haupt-Agent delegiert an Haiku-Worker | ORCHESTRATOR_PROMPTS.handlanger | | `experten` | 4 Experten: Research/Implement/Test/Review | ORCHESTRATOR_PROMPTS.experten | | `auto` | Heuristik waehlt Modus nach Nachrichtenlaenge/-inhalt | chooseAutoMode() | ### MCP-Hub (Phase 4) - 6 Server aus `~/.claude.json` → beim Bridge-Start per `set-mcp-servers` injiziert - Tauri-Commands: `list_mcp_servers`, `add_mcp_server`, `remove_mcp_server` - Bridge: `queryOptions.mcpServers = mcpServerConfigs` ### Offline-Queue (Phase 5) - SQLite-Tabelle `offline_queue` - Commands: `queue_message`, `list_queued_messages`, `flush_offline_queue`, `clear_offline_queue`, `queue_count` ## Build & Deploy ```bash # Dev (Hot-Reload) CARGO_TARGET_DIR=/tmp/claude-desktop-target nix-shell --run "npx tauri dev" # Produktion CARGO_TARGET_DIR=/tmp/claude-desktop-target nix-shell --run "npx tauri build -- --bundles appimage" # CI: Commit mit [appimage] → Forgejo baut automatisch # WICHTIG: CARGO_TARGET_DIR nie auf SMB-Mount! ``` ### CI-Eigenheiten - Runner: `16-Forgejo-Runner-AppImage` (Debian Bookworm) - AppImage-Filename mit Leerzeichen → `tr ' ' '-'` vor Upload - DELETE vor PUT (Forgejo 409 Conflict) - Custom-AppRun muss `apprun-hooks/linuxdeploy-plugin-gtk.sh` sourcen (KB #384) - Ntfy-Notifications auf Topic `vk-builds` ## NixOS-Spezialfall AppImage hat WebKit2GTK/Mesa ABI-Konflikt auf NixOS → **immer nativ bauen** via `shell.nix`. Auf Debian/Ubuntu/Fedora/Arch funktioniert das AppImage problemlos. ## Konventionen - **Sprache**: Deutsch in Code-Kommentaren, README, Commits, UI - **Svelte 5**: Runes (`$state`, `$derived`, `$effect`), `onclick` statt `on:click` - **Guard-Rails**: Alle System-Aktionen ueber `guard.rs` klassifizieren - **Audit**: Jede Tool-Ausfuehrung im Audit-Log - **Sessions**: Persistent in SQLite, nach Projekt gefiltert - **PaneForge**: `{#key}` verwenden wenn Panes dynamisch ein-/ausgeblendet werden ## Haeufige Probleme & Loesungen | Problem | Loesung | |---------|---------| | Rusqlite Borrow-Lifetime | `let result = stmt.query_map(...)?.collect(); result` | | UTF-8 Panic bei Truncation | `char_indices().take_while()` statt `&s[..n]` | | PaneForge Resize nach Detach | `{#key $chatDetached}` um PaneGroup | | Piper-TTS nicht gefunden | `nix-env -f '' -iA piper-tts`, Modelle in `~/.local/share/claude-desktop/models/` | | Bridge-Nachricht nicht parsbar | `match serde_json::from_str()` statt `if let Ok()` | | Unhandled Promise Rejection | Global Handler in Bridge (uncaughtException + unhandledRejection) | ## Wissensbasis-Referenzen | KB-ID | Thema | |-------|-------| | #248 | Tauri + SvelteKit shell.nix | | #311 | CI/CD Pipeline | | #371 | Debian Forgejo-Runner | | #381 | NixOS WebKit-EGL-Crash | | #382 | Cargo auf SMB | | #384 | Custom-AppRun |