Cosmo Docs
Desktop App

Main Process (index.ts)

Window management, IPC handlers, auth lifecycle, and deep linking

packages/desktop/src/main/index.ts is the Electron main-process entry point. It owns the OS window, the IPC bus, and coordinates all managers.

Window Creation

createWindow() creates the application BrowserWindow:

  • macOS — native titlebar with traffic-light buttons; titleBarStyle: 'hiddenInset'.
  • Windows / Linux — frameless window; the renderer draws custom titlebar controls.
  • Minimum size: 1024 × 700 px.
  • Loads the renderer via a local HTTP server (needed for Clerk cookie support — file:// URLs cannot hold cookies).

Local HTTP Server

startLocalServer(staticDir) binds to a random available port and serves the renderer's built static files. The BrowserWindow navigates to http://localhost:{port}.

Auth Lifecycle

Auth state is persisted to userData/auth.json as a JSON object with fields:

FieldTypeDescription
tokenstringCosmo JWT
userIdstringInternal user ID
orgIdstringActive org ID
userEmailstringUser email
userNamestringDisplay name
orgNamestringOrg display name
orgSlugstringURL-safe org slug
rolestringOWNER / ADMIN / MEMBER
planstring?Active billing plan
onboardingCompletedboolean?Whether onboarding is done

validateStoredAuth(auth) makes a live call to GET /api/v1/auth/me. If the server returns non-OK, tryRefreshToken is called. On network error (offline), auth is trusted.

tryRefreshToken(auth) calls POST /api/v1/auth/refresh to obtain a new token.

wipeAppData() clears auth state, the chat-sessions file, the cosmo-data directory, and browser session/cache. It does not call app.relaunch() or app.exit() — the renderer receives an auth:changed: null event and navigates to the login screen.

Deep Linking

The app registers as a handler for the cosmo:// custom URL scheme. handleDeepLink(url) parses incoming cosmo:// URLs:

URLAction
cosmo://auth?token=...Stores the token from web auth flow

After a successful deep link, auth:changed is emitted to the renderer so AuthContext can update immediately.

IPC Handlers

All IPC handlers are registered in main/index.ts using ipcMain.handle. The renderer calls them via the preload bridge.

Window Controls

ChannelHandler
window:minimizeMinimise the window
window:maximizeToggle maximise
window:closeClose the window
window:is-maximizedReturns boolean

Auth

ChannelHandler
auth:getReturns stored AuthState or null
auth:loginOpens browser to web sign-in page
auth:logoutCalls wipeAppData()

Chat

ChannelHandler
chat:list-sessionsReturns sessions from ChatManager
chat:create-sessionCreates a new session
chat:get-messagesReturns messages for a session
chat:delete-sessionDeletes a session
chat:send-messageStreams a response (events via chat:event)
chat:stopAborts in-flight generation
chat:available-modelsReturns model list from server
chat:confirm-toolResolves a pending tool confirmation
chat:extract-onboardingExtracts memory from onboarding session

Onboarding

ChannelHandler
onboarding:get-user-profileReturns stored user profile
onboarding:save-user-profileSaves user profile + cloud push
onboarding:get-org-statusReturns org onboarding data
onboarding:save-orgSaves org data + cloud push
onboarding:resetWipes all onboarding data
onboarding:save-assetStores brand asset file
onboarding:resolve-asset-urlResolves asset:// ref to file:// URL
onboarding:seed-onboardingCalls POST /api/v1/auth/seed-onboarding
onboarding:get-sample-tasksCalls GET /api/v1/tasks to return org tasks

Connectors

ChannelHandler
connectors:availableFetches provider catalog from server
connectors:listLists installed connector instances
connectors:addStarts OAuth or API-key flow, saves instance
connectors:removeDeletes a connector instance

Updates

ChannelHandler
updates:get-statusReturns current UpdateStatus
updates:checkTriggers an immediate update check
updates:downloadStarts downloading an available update
updates:installQuits and installs the downloaded update

Tasks, Workspaces, Teams, Artifacts

Thin wrappers that forward calls to SyncClient:

ChannelEndpoint
workspaces:listGET /api/v1/workspaces
workspaces:getGET /api/v1/workspaces/:id
teams:listGET /api/v1/teams
teams:getGET /api/v1/teams/:id
teams:list-membersGET /api/v1/teams/:id/members
artifacts:listArtifactManager.list()
artifacts:getArtifactManager.read()

Billing

ChannelHandler
billing:open-manageOpens web billing portal in browser
billing:get-usageGET /api/v1/metering/user
billing:get-subscriptionGET /api/v1/billing/subscription
billing:open-portalPOST /api/v1/billing/portal → opens URL

Utility

ChannelHandler
get-app-versionReturns app.getVersion()
open-externalOpens URL in system browser
open-web-pageOpens app web URL in browser

platform is not an IPC channel — it is exposed as window.cosmoDesktop.platform (a direct process.platform property on the preload object).

Events Emitted to Renderer

The main process pushes events to the renderer window using webContents.send:

ChannelPayloadTrigger
auth:changedStoredAuth | nullDeep link login / logout
chat:eventChatEventEach streaming chunk
tasks:changedorgId: stringTask created/updated/deleted
teams:changedorgId: stringTeam membership changed
workspaces:changedorgId: stringWorkspace created/deleted
artifacts:changedorgId, workspaceIdArtifact updated
artifacts:createdorgId, workspaceId, artifactId, titleNew artifact created by AI
updates:statusUpdateStatusUpdate state change
sync:remote-changeChangeEventSSE change from cloud pushed to renderer
posthog:capture-feedbackFeedbackCaptureDataAI feedback submission
window:maximized-changedbooleanWindow resize