Skip to content

candela-desktop

Candela Desktop is a native application for managing LLM providers, visualizing distributed traces, and orchestrating the candela CLI proxy.

Feature Description
Today View At-a-glance dashboard showing today’s LLM spend, request count, and top models — auto-refreshes every 30s
Provider Dashboard Connect and monitor OpenAI, Google Gemini, Anthropic (Vertex), Ollama, vLLM, LM Studio
Traces Screen Full-screen trace browser with search, filtering, and span-level detail — mirrors the web UI
Embedded Span Search Embedded WebView querying /spans on :8181 for rich, interactive span filtering
Trace Viewer Waterfall view with span hierarchy, timing, token counts, and cost
Config Editor Live YAML editor for ~/.config/candela/config.yaml with validation
Mode Switcher Toggle between Solo, Solo + Cloud, and Team modes
Auto-Start Proxy Starts the candela CLI proxy on launch if installed but not running
CLI Install/Upgrade Detects missing CLI, offers one-click brew install, shows upgrade banners
Self-Update Upgrade Desktop via brew upgrade --cask from the system tray
Dark/Light Mode Adaptive UI with system theme detection
Secure Storage API keys stored in the system’s secure storage (macOS Keychain, Windows DPAPI, or Linux libsecret)
Terminal window
brew install --cask candelahq/tap/candela-desktop

Download the latest release from GitHub Releases.

Platform Format
macOS .dmg
Linux .AppImage
Windows .exe installer

Candela Desktop works best alongside the candela CLI:

Terminal window
brew install candelahq/tap/candela

On launch, Desktop automatically:

  1. Detects whether the candela CLI is installed via Homebrew
  2. Installs it with a one-click banner if missing
  3. Starts the proxy in the background if installed but not running
  4. Checks for updates and shows an upgrade banner when a newer CLI version is available

The Desktop app can upgrade itself from the system tray menu:

  • Tray → Check for Updates — runs brew upgrade --cask candelahq/tap/candela-desktop and relaunches

Candela Desktop supports multiple LLM providers:

  • OpenAI — GPT-4o, GPT-4, GPT-3.5
  • Google Gemini — Gemini 2.5 Pro, Gemini 2.0 Flash
  • Anthropic — Claude Sonnet, Claude Haiku (via Vertex AI)
  • Ollama — Local models (auto-discovered)
  • LM Studio — Local models via OpenAI-compatible API

Each provider is configured with:

  • Display name and endpoint URL
  • API key (securely stored in OS keychain)
  • Model selection and parameters
  • Optional proxy routing through candela or candela-sidecar

The trace viewer displays a waterfall view of distributed traces:

  • Span hierarchy — Nested tree showing parent/child relationships
  • Timing — Start time, duration, and TTFB for each span
  • Token counts — Input and output tokens per LLM call
  • Cost — Estimated cost based on provider pricing
  • Attributes — Full span attributes including model, provider, and custom metadata

Candela Desktop integrates an embedded WebView directly wired to the proxy’s /spans route (http://127.0.0.1:8181/spans). This provides rich interactive span searching, model and latency filtering, and deep token inspection without requiring a separate web dashboard process.

Candela Desktop uses Riverpod 3.x with @riverpod code generation for all state management. The provider hierarchy flows from configuration → services → controllers:

Layer Examples Role
Config Providers candelaHostProvider, configProvider Environment and user settings
Service Providers connectApiServiceProvider, cliServiceProvider RPC clients and system integration
State Controllers DashboardController, TracesNotifier Async state that drives the UI

DashboardController is the central state controller — a class-based @riverpod Notifier that provides:

  • Reactive polling — auto-rebuilds when upstream providers change
  • Immutable state snapshots — all updates use state.copyWith()
  • Disposal guards — prevents state mutation after ref.onDispose()
  • Imperative bridgeonStateChanged() callback for non-widget consumers (e.g., system tray)

All UI screens consume state via ref.watch(dashboardControllerProvider) — no ListenableBuilder or manual listeners.

Desktop communicates with the candela proxy via ConnectRPC. Dart stubs are generated from protobuf definitions hosted on the Buf Schema Registry (BSR):

Terminal window
buf generate # requires buf + BUF_TOKEN

Desktop uses CandelaAuthService for native Application Default Credentials (ADC) authentication:

  • Reads credentials directly from ~/.config/gcloud/application_default_credentials.json
  • Refreshes access tokens against oauth2.googleapis.com
  • No dependency on the gcloud CLI
Terminal window
flutter test # ~855 unit + widget tests
flutter test integration_test/ # E2E (requires macOS runner)
flutter analyze # static analysis + lint

The integration test suite covers app boot, dashboard empty state, onboarding flow, navigation, and settings.

Terminal window
# Upgrade Desktop (macOS)
brew upgrade --cask candelahq/tap/candela-desktop
# Upgrade CLI
brew upgrade candelahq/tap/candela
Terminal window
git clone https://github.com/candelahq/candela-desktop.git
cd candela-desktop
flutter pub get
flutter run -d macos # or linux, windows
  • candela — CLI proxy that Desktop auto-starts and manages
  • candela-server — Cloud backend for team features