Cosmo Docs
Desktop App

Renderer Process

React app structure, contexts, components, and hooks

The renderer is a React 19 single-page application built with Vite and Tailwind. It communicates with the main process exclusively via window.cosmoDesktop (the preload bridge). Source lives in packages/desktop/src/renderer/src/.

Entry Point (main.tsx)

Before React mounts, main.tsx reads localStorage for cosmo-theme and cosmo-preset and applies them to document.documentElement. This prevents a flash of unstyled content on load.

PostHog is initialised here with the app's analytics key.

If VITE_CLERK_PUBLISHABLE_KEY is set, the app renders AuthProvider → App. Otherwise it renders DevApp (development bypass mode).

Contexts

AuthContext (context/AuthContext.tsx)

Manages authentication state for the entire app.

ValueTypeDescription
isLoadedbooleanAuth state has been fetched from main
isSignedInbooleanUser is authenticated
tokenstring?Cosmo JWT
userAuthUser?{ id, email, name, avatarUrl }
orgAuthOrg?{ id, name, slug }
rolestring?OWNER / ADMIN / MEMBER
planstring?Active billing plan
onboardingCompletedbooleanWhether onboarding is done
login()fnCalls window.cosmoDesktop.auth.login()
logout()fnCalls window.cosmoDesktop.auth.logout()
getToken()() => stringReturns the current token

On mount it calls window.cosmoDesktop.auth.get() and subscribes to auth:changed events (fired after deep-link login).

Hook: useDesktopAuth()

ChatContext (context/ChatContext.tsx)

The most complex context — manages sessions, streaming, and model selection.

Session state:

ValueTypeDescription
sessionsSessionInfo[]All chat sessions
activeSessionIdstring?Currently open session
messagesDisplayMessage[]Messages for active session
isStreamingbooleanA response is in flight
streamingTextstringAccumulated text so far
streamSegmentsStreamSegment[]Typed segments (thinking, text, tool, advisory)
contextUsage{ usedTokens, maxTokens, percentage }Token meter
activeModelModelInfo?Selected model
availableModelsModelInfo[]All available models
onboardingSessionIdstring?Special onboarding session

Methods:

MethodDescription
createSession(opts?)Create and switch to a new session
switchSession(id)Load a different session
deleteSession(id)Delete and switch to another
sendMessage(content)Send and stream response
stopGeneration()Abort the active stream
switchModel(modelId)Change active model

Stream segments are built incrementally as chat:event IPC events arrive:

Segment typeDescription
thinkingExtended thinking content (shown collapsed)
textPlain assistant text (Markdown rendered)
tool_callTool invocation display
tool_resultTool execution result
tool_confirmAwaiting user approval
advisory:next_actionsSuggested next steps
advisory:heads_upWarning or notice card
advisory:connector_requiredPrompt to add a connector

When the final text contains [ONBOARDING_COMPLETE], the context strips the sentinel and calls onboarding.handleComplete(sessionId).

Hook: useChatContext()

AppModeContext (context/AppModeContext.tsx)

Provides { isClerkMode, orgId, userId } throughout the app. Set once at startup from AuthContext.

Hook: useAppMode()

ThemeContext (context/ThemeContext.tsx)

Manages visual theme:

ValueDescription
theme'light' / 'dark'
preset'chalk' / 'paper' / 'dusk' / 'ledger' / 'atelier' / 'mono'
setTheme(t)Update and persist theme
setPreset(p)Update and persist preset

Applies classes to document.documentElement and syncs values to PostHog person properties.

Hook: useTheme()

Pages

HomePage (pages/HomePage.tsx)

The main authenticated layout. Three panes:

┌──────────────────────────────────────────────────────┐
│  Titlebar  (hamburger + window controls)             │
├──────────┬──────────────────────┬───────────────────┤
│          │                      │                   │
│ Sidebar  │     ChatPanel        │     HubPanel      │
│ (52–256px│                      │   (resizable)     │
│ toggle)  │                      │                   │
└──────────┴──────────────────────┴───────────────────┘
  • Sidebar collapses to icon-only mode (52 px) on toggle.
  • The ResizeHandle between Chat and Hub lets users drag to adjust the Hub width (default 60% of remaining space, min 280 px).
  • Switching to 'customize' view hides ChatPanel and shows CustomizePage.
  • Listens for cosmo:open-integrations custom DOM event to jump directly to the Integrations tab.

LoginPage (pages/LoginPage.tsx)

Shown when isSignedIn is false. Shows the Cosmo logo and a Sign in with browser button that calls window.cosmoDesktop.auth.login().

In dev mode (DevApp), shows a mock form for local testing.

Key Components

ChatPanel (components/chat/ChatPanel.tsx)

  • Renders DisplayMessage list with Markdown support.
  • Shows thinking blocks (collapsible), tool calls, tool confirmation dialogs, and advisory cards.
  • Auto-scrolls to the latest message.
  • Textarea with auto-resize (max 160 px height), Shift+Enter for newline, Enter to send.
  • Context meter at the bottom shows token usage percentage.
  • Model selector (hidden when VITE_HIDE_MODEL_SELECTOR is set).
  • Stop button during streaming.
  • Filters system role messages from display.
  • New session button at the top.
  • Session search input.
  • Sessions grouped by time: Today / Yesterday / Older.
  • Delete button on session hover.
  • Customize toggle button.
  • User menu (bottom): profile, usage modal, manage org (opens web), reset onboarding (dev only), sign out.
  • Trial reminder card + Upgrade button if on free or trial plan.
  • Update card when a new version is available.

HubPanel (components/hub/HubPanel.tsx)

The right-side panel with multiple views:

ViewDescription
DashboardStat cards (Open Tasks, Due Today, Completed, Workspaces), focus task list, status breakdown chart
TasksFull task list with filters (All / Mine / Unassigned), show/hide completed
Team HubWorkspaces list, team tasks, member roster
Artifact viewerEmbedded <iframe> rendering the HTML artifact
ConnectorsBrowse and add integrations grouped by category

Auto-navigates to Artifact view when artifacts:created is received.

CustomizePage (components/customize/CustomizePage.tsx)

Two tabs:

  • Integrations — Add/remove MCP connectors, see connection status.
  • Appearance — Theme (dark/light) + preset picker (chalk, paper, dusk, ledger, atelier, mono).

Hooks

useOnboardingChat (hooks/useOnboardingChat.ts)

Controls the onboarding session lifecycle.

Value / MethodDescription
needsOnboardingtrue if user is incomplete, or admin and org is incomplete
initOnboarding(api)Creates onboarding session, sends [SYSTEM: BEGIN_ONBOARDING] trigger
handleComplete(sessionId)Extracts memory, marks user/org complete, seeds org data
skipOnboarding()Mark complete without memory extraction

The onboarding session ID is persisted to localStorage so the same session is resumed on restart.

useOnboardingStatus (hooks/useOnboardingStatus.ts)

Loads UserProfile and OrgOnboarding from the main process.

HookReturns
useUserOnboarding(userId){ isLoading, isComplete, profile, refetch }
useOrgOnboarding(orgId){ isLoading, isComplete, data, refetch }

Onboarding Prompt (lib/onboardingPrompt.ts)

Builds the AI system prompt used in the onboarding session. The prompt:

  • Greets the user by name.
  • Steps through: welcome → user background → org info (admin only) → pain points → preferences → wrap-up.
  • Uses a different flow for org creators vs. invited members.
  • Terminates with [ONBOARDING_COMPLETE] sentinel when complete.
  • Allows the user to skip at any point.