Desktop App
ClawDesk ships a native desktop application built with Tauri 2.0. The app runs the full Rust gateway in-process—no separate server needed. It provides a system tray icon, native notifications, global shortcuts, and a polished UI for managing channels, conversations, and settings.
Architecture
Key Design Decisions
| Aspect | Choice | Rationale |
|---|---|---|
| Framework | Tauri 2.0 | Native performance, small binary, cross-platform |
| Core | In-process Rust | No IPC overhead, shared memory, single binary |
| UI | WebView (React) | Rich UI capabilities, familiar development |
| Tray | Native system tray | Always accessible, minimal footprint |
| Updates | Sparkle/WinSparkle | Auto-update support |
Supported Platforms
| Platform | Status | Min Version | Notes |
|---|---|---|---|
| macOS | ✅ | 11.0 (Big Sur) | Universal binary (Intel + Apple Silicon) |
| Linux | ✅ | Ubuntu 20.04+ | AppImage, .deb, .rpm |
| Windows | ✅ | Windows 10+ | MSI installer, portable .exe |
| iOS | 🧪 Beta | iOS 16+ | Via Tauri 2.0 mobile support |
| Android | 🧪 Beta | Android 8.0+ | Via Tauri 2.0 mobile support |
Installation
macOS
# Download the latest release
curl -L https://github.com/clawdesk/clawdesk/releases/latest/download/ClawDesk_aarch64.dmg -o ClawDesk.dmg
# Or install via Homebrew
brew install --cask clawdesk
Open the .dmg and drag ClawDesk to Applications. On first launch, you may need to approve the app in System Preferences → Privacy & Security.
Linux
# AppImage (universal)
curl -L https://github.com/clawdesk/clawdesk/releases/latest/download/ClawDesk_amd64.AppImage -o ClawDesk.AppImage
chmod +x ClawDesk.AppImage
./ClawDesk.AppImage
# Debian/Ubuntu
sudo dpkg -i ClawDesk_amd64.deb
# Fedora/RHEL
sudo rpm -i ClawDesk_x86_64.rpm
Windows
Download the MSI installer from the releases page and run it. Windows SmartScreen may show a warning on first run—click "More info" → "Run anyway".
Building from Source
# Prerequisites
# - Rust 1.75+
# - Node.js 18+
# - Platform-specific deps (see Tauri docs)
# Clone the repository
git clone https://github.com/clawdesk/clawdesk.git
cd clawdesk
# Install frontend dependencies
cd crates/ui && npm install && cd ../..
# Build and run in development mode
cd crates/clawdesk-tauri
cargo tauri dev
# Build release binary
cargo tauri build
On macOS, if you get code signing errors during development, use:
cargo tauri dev -- -- --no-sandbox
First Launch
On first launch, ClawDesk opens a setup wizard:
- Welcome: Overview and terms
- Provider Setup: Enter API keys for your preferred providers
- Model Selection: Choose default model
- Channel Setup: Connect your first channel (or skip)
- Security: Set allowlist mode and admin identity
- Ready: Launch the gateway
You can revisit any of these settings later in Settings (⌘,).
User Interface
Main Window
The main window has four primary areas:
┌─────────────────────────────────────────────────────────┐
│ ClawDesk ─ □ ✕ │
├──────────┬──────────────────────────────┬───────────────┤
│ │ │ │
│ Sidebar │ Conversation View │ Detail Panel │
│ │ │ │
│ • Chats │ ┌────────────────────────┐ │ • Session │
│ • Chan- │ │ User: Hello! │ │ Info │
│ nels │ │ │ │ • Tools │
│ • Tools │ │ Agent: Hi! How can I │ │ Used │
│ • Cron │ │ help you today? │ │ • Provider │
│ • Logs │ │ │ │ Stats │
│ │ │ User: What's the │ │ • Memory │
│ │ │ weather like? │ │ Context │
│ │ │ │ │ │
│ │ │ Agent: Let me check... │ │ │
│ │ └────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ Type a message... ⏎ │ │ │
│ │ └────────────────────────┘ │ │
└──────────┴──────────────────────────────┴───────────────┘
Sidebar Sections
| Section | Description |
|---|---|
| Chats | Active conversations across all channels |
| Channels | Connected channels with status indicators |
| Tools | Available tools and their enable/disable toggles |
| Cron | Scheduled tasks with next-run times |
| Logs | Real-time gateway logs with filtering |
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
⌘/Ctrl + N | New conversation |
⌘/Ctrl + K | Quick command palette |
⌘/Ctrl + , | Open settings |
⌘/Ctrl + L | Clear conversation |
⌘/Ctrl + Shift + T | Toggle system tray mode |
⌘/Ctrl + 1-9 | Switch between sidebar sections |
⌘/Ctrl + Enter | Send message |
⌘/Ctrl + Shift + Enter | Send with specific model |
Esc | Close current panel |
System Tray
ClawDesk runs as a system tray application. The tray icon provides quick access to common functions:
┌───────────────────────────┐
│ 🤖 ClawDesk │
├───────────────────────────┤
│ ✅ Gateway Running │
│ 📡 3 Channels Active │
│ 💬 12 Active Sessions │
├───────────────────────────┤
│ Quick Message... ⌘M │
│ Open Dashboard ⌘D │
│ Pause All Channels ⌘P │
├───────────────────────────┤
│ Settings... ⌘, │
│ Check for Updates... │
│ Quit ClawDesk ⌘Q │
└───────────────────────────┘
Tray Icon States
| Icon State | Meaning |
|---|---|
| 🟢 Green dot | Gateway running, all channels connected |
| 🟡 Yellow dot | Gateway running, some channels have warnings |
| 🔴 Red dot | Gateway running, critical errors present |
| ⚪ Gray dot | Gateway stopped |
Minimize to Tray
[desktop]
close_to_tray = true # minimize to tray on window close
start_minimized = false # start in tray without showing window
show_notifications = true # show native notifications for messages
Notifications
ClawDesk sends native OS notifications for important events:
[desktop.notifications]
enabled = true
# Notification types
[desktop.notifications.types]
new_message = true # new messages from channels
channel_error = true # channel disconnection/errors
cron_complete = true # cron task completion
cron_error = true # cron task failures
provider_error = true # provider failures
security_alert = true # security-related events
update_available = true # new version available
# Quiet hours
[desktop.notifications.quiet_hours]
enabled = false
start = "22:00"
end = "08:00"
timezone = "America/New_York"
On macOS, ClawDesk uses UNUserNotificationCenter for native notifications. On Linux, it uses libnotify. On Windows, it uses Windows Toast notifications. Grant notification permissions when prompted on first launch.
Settings
The Settings panel (⌘,) provides a GUI for all configuration options:
General
| Setting | Description |
|---|---|
| Launch at Login | Start ClawDesk when you log in |
| Close to Tray | Minimize to tray instead of quitting |
| Start Minimized | Launch directly to the system tray |
| Theme | Light / Dark / System |
| Language | UI language (English, 中文, 日本語, ...) |
Providers
Add, edit, and test provider configurations through the UI. API keys are stored encrypted in the system keychain.
Channels
Visual channel management with status indicators, test buttons, and log viewers.
Security
Configure allowlists, ACLs, and scanning rules through a guided interface.
Advanced
Direct TOML config editor with syntax highlighting and validation.
In-Process Gateway
The desktop app runs the ClawDesk gateway in-process. This means:
- No separate server to start or manage
- Shared memory between the UI and the gateway
- Lower latency for local interactions
- Single binary distribution
The gateway starts automatically when the app launches and stops when it quits.
// Simplified Tauri setup
fn main() {
tauri::Builder::default()
.setup(|app| {
// Start the gateway in-process
let config = load_config()?;
let gateway = Gateway::new(config)?;
tauri::async_runtime::spawn(async move {
gateway.start().await.expect("Gateway failed to start");
});
Ok(())
})
.invoke_handler(tauri::generate_handler![
send_message,
list_channels,
get_sessions,
get_config,
update_config,
])
.system_tray(build_tray())
.run(tauri::generate_context!())
.expect("error while running application");
}
Tauri Commands
The frontend communicates with the Rust backend through Tauri commands:
#[tauri::command]
async fn send_message(
state: State<'_, AppState>,
message: String,
session_id: Option<String>,
provider: Option<String>,
model: Option<String>,
) -> Result<MessageResponse, String> {
let runner = state.agent_runner.lock().await;
let response = runner.handle_message(/* ... */).await
.map_err(|e| e.to_string())?;
Ok(response.into())
}
#[tauri::command]
async fn list_channels(
state: State<'_, AppState>,
) -> Result<Vec<ChannelStatus>, String> {
let registry = state.channel_registry.lock().await;
Ok(registry.list_with_status().await)
}
Frontend usage (TypeScript):
import { invoke } from '@tauri-apps/api/core';
// Send a message
const response = await invoke('send_message', {
message: 'Hello!',
provider: 'anthropic',
model: 'claude-sonnet-4-20250514',
});
// List channels
const channels = await invoke('list_channels');
Gateway API Access
Even when running as a desktop app, the gateway's HTTP API is available on localhost:
[desktop.gateway]
expose_api = true
port = 1420 # local API port
bind = "127.0.0.1" # only localhost by default
This allows external tools and scripts to interact with the running desktop instance:
# Send a message via the local API
curl -X POST http://localhost:1420/api/v1/message \
-H "Content-Type: application/json" \
-d '{"text": "Hello from curl!"}'
# Check health
curl http://localhost:1420/api/v1/health
The gateway API is bound to 127.0.0.1 by default, making it accessible only from the local machine. Changing this to 0.0.0.0 exposes the API to the network—only do this in trusted environments with proper security configuration.
Auto-Updates
ClawDesk checks for updates automatically (configurable):
[desktop.updates]
auto_check = true
check_interval_hours = 24
auto_install = false # if true, installs without prompting
channel = "stable" # "stable" | "beta" | "nightly"
Update channels:
| Channel | Description |
|---|---|
stable | Stable releases, recommended for most users |
beta | Pre-release versions with new features |
nightly | Bleeding edge, built from main branch |
Data Locations
| Platform | Config | Data | Logs |
|---|---|---|---|
| macOS | ~/Library/Application Support/com.clawdesk.app/config.toml | ~/Library/Application Support/com.clawdesk.app/data/ | ~/Library/Logs/com.clawdesk.app/ |
| Linux | ~/.config/clawdesk/config.toml | ~/.local/share/clawdesk/data/ | ~/.local/share/clawdesk/logs/ |
| Windows | %APPDATA%\ClawDesk\config.toml | %APPDATA%\ClawDesk\data\ | %APPDATA%\ClawDesk\logs\ |
Performance
Resource Usage
| Metric | Idle | Active (1 channel) | Active (5 channels) |
|---|---|---|---|
| Memory | ~60 MB | ~120 MB | ~200 MB |
| CPU | <1% | 2-5% | 5-10% |
| Disk | ~30 MB (app) | +50 MB (data) | +100 MB (data) |
Optimization Tips
[desktop.performance]
# Reduce memory usage
max_cached_sessions = 50 # default: 100
max_session_history = 100 # messages per session in memory
# Reduce CPU usage
ui_refresh_rate_ms = 100 # default: 50
log_buffer_size = 500 # default: 1000
# Reduce disk usage
auto_compact_sessions = true
compact_after_messages = 200
Troubleshooting
Common Issues
| Problem | Solution |
|---|---|
| App won't start | Check logs in the data directory, try --log-level debug |
| Blank window | WebView issue — update your OS, check GPU drivers |
| High CPU usage | Check for reconnection loops in channels, reduce refresh rate |
| Notifications not showing | Check OS notification permissions |
| Tray icon missing | Restart the app, check OS tray settings |
| Build fails | Ensure Tauri 2.0 prerequisites are installed |
| Apple Silicon performance | Ensure you're using the aarch64 build, not Rosetta |
Debug Mode
# Launch with debug logging
CLAWDESK_LOG=debug /Applications/ClawDesk.app/Contents/MacOS/ClawDesk
# Or on Linux
CLAWDESK_LOG=debug /usr/bin/clawdesk
# Or on Windows (PowerShell)
$env:CLAWDESK_LOG="debug"; .\ClawDesk.exe
Reset to Defaults
# macOS
rm -rf ~/Library/Application\ Support/com.clawdesk.app/
# Linux
rm -rf ~/.config/clawdesk/ ~/.local/share/clawdesk/
# Windows (PowerShell)
Remove-Item -Recurse "$env:APPDATA\ClawDesk"
Resetting deletes all configuration, conversation history, memory data, and plugins. Export your config first with clawdesk config export.