Cosmo Docs
Desktop App

Desktop App Overview

Architecture and structure of the Cosmo Electron desktop application

The Cosmo desktop app is an Electron + React application that provides the full Cosmo workspace experience as a native desktop client on macOS and Windows. It is located at packages/desktop.

Technology Stack

LayerTechnology
ShellElectron
RendererReact 19 + Vite
StylingTailwind CSS + Shadcn
AuthClerk (cloud) with dev-mode bypass
AnalyticsPostHog
Buildelectron-vite

Multi-Process Architecture

Electron splits work across two processes:

Main Process (src/main/)

The Node.js process that owns the OS window, IPC bus, file system, and all network calls. It initialises six managers on startup:

ManagerFileResponsibility
ChatManagerchat-manager.tsLLM sessions, streaming, tool execution
ConnectorManagerconnector-manager.tsOAuth flows, MCP connector instances
ArtifactManagerartifact-manager.tsLocal HTML artifact persistence
OnboardingManageronboarding-manager.tsUser profile + org data storage
SyncManagersync-manager.tsCloud pull/push + SSE change feed
UpdateManagerupdate-manager.tsAuto-update polling and installation

Preload (src/preload/index.ts)

A context-bridge script that exposes a typed CosmoDesktopAPI to the renderer. Nothing from Node.js bleeds into the renderer directly — all communication goes through this bridge.

Renderer Process (src/renderer/src/)

A React single-page app that runs in a sandboxed Chromium context. It reads and writes state only through the preload bridge.

Application Layout

packages/desktop/
├── src/
│   ├── main/
│   │   ├── index.ts              ← Entry: window, IPC handlers, auth
│   │   ├── chat-manager.ts       ← Chat sessions & LLM engine
│   │   ├── artifact-manager.ts   ← Local artifact storage
│   │   ├── connector-manager.ts  ← MCP OAuth + instance management
│   │   ├── sync-manager.ts       ← Cloud sync (pull/push/SSE)
│   │   ├── sync-client.ts        ← HTTP wrapper for server API
│   │   ├── onboarding-manager.ts ← Profile + memory file storage
│   │   ├── update-manager.ts     ← Auto-update lifecycle
│   │   ├── error-tracker.ts      ← PostHog uncaught exception capture
│   │   └── oauth-callback-server.ts ← Local HTTP for OAuth redirects
│   ├── preload/
│   │   └── index.ts              ← IPC context bridge
│   └── renderer/src/
│       ├── main.tsx              ← React entry, theme bootstrap
│       ├── App.tsx               ← Auth gate → home or login
│       ├── DevApp.tsx            ← Dev-mode bypass (no Clerk)
│       ├── pages/
│       │   ├── HomePage.tsx      ← Three-pane layout
│       │   └── LoginPage.tsx     ← Sign-in UI
│       ├── context/
│       │   ├── AuthContext.tsx   ← Auth state + token
│       │   ├── ChatContext.tsx   ← Sessions, streaming, model
│       │   ├── AppModeContext.tsx ← orgId + userId
│       │   └── ThemeContext.tsx  ← Dark/light + preset
│       ├── components/
│       │   ├── chat/             ← ChatPanel, ModelSelector, ContextMeter
│       │   ├── sidebar/          ← Session list, user menu
│       │   ├── hub/              ← HubPanel: tasks, workspaces, artifacts
│       │   └── customize/        ← Integrations + Appearance settings
│       └── hooks/
│           ├── useOnboardingChat.ts
│           └── useOnboardingStatus.ts
├── electron.vite.config.ts
└── package.json

Startup Sequence

  1. Electron launches; main/index.ts creates a BrowserWindow.
  2. A local HTTP server starts on a random port to serve the renderer (required for Clerk cookies — file:// cannot hold cookies).
  3. Stored auth (userData/auth.json) is loaded and validated. If the token is expired but within the 7-day grace window, it is refreshed automatically.
  4. ChatManager, ConnectorManager, ArtifactManager, OnboardingManager, SyncManager, and UpdateManager are initialised.
  5. SyncManager.pull() pulls the latest user profile, org onboarding data, and memory files from the cloud.
  6. The renderer loads and React mounts. The AuthContext fetches stored auth via the IPC bridge.
  7. If signed in, HomePage renders the three-pane layout (Sidebar | Chat | Hub).

Auth Flow (Production)

  1. User clicks Sign in with browser on LoginPage.
  2. Main process opens https://getcosmo.app/auth/desktop in the system browser.
  3. User authenticates via Clerk on the web.
  4. The web app deep-links back to the desktop: cosmo://auth?token=...
  5. Main process handles the cosmo:// protocol, extracts the token, stores it to userData/auth.json, and emits auth:changed to the renderer.

Dev Mode

When VITE_CLERK_PUBLISHABLE_KEY is absent, the app renders DevApp instead of App. Dev mode uses fixed orgId='dev-org' and userId='dev-user' — no Clerk dependency required for local development.