Desktop apps
ClickClack ships one Electron desktop client for macOS, Windows, and Linux. It connects to the hosted service by default and can point at any compatible self-hosted server. The server remains the source of truth; the desktop client adds operating-system behavior around the existing web app and API.
#What becomes native
- Notifications with routing. Incoming channel and DM notifications use the
- Unread state outside the window. macOS/Linux badges, a Windows taskbar
- Background presence. Closing the window can keep the realtime connection
- Quick compose.
Cmd/Ctrl+Shift+Kraises ClickClack and focuses the active - Deep links.
clickclack://app/<workspace>/<target>opens routed workspace, - Native downloads and text editing. Completed downloads reveal themselves
- Remembered workspace. Window bounds, maximized state, selected server,
- Integrated window chrome. ClickClack extends into the native title bar:
operating system notification center. Clicking one opens its ClickClack conversation.
overlay, and the tray menu reflect aggregate channel and DM unread counts.
alive in the tray so notifications still arrive. This behavior is configurable.
channel, DM, or thread composer.
channel, DM, and thread URLs in the desktop client.
in the OS file manager. Text fields gain the platform spellchecker and native edit menu.
tray preference, and optional login launch are stored in the platform user-data directory.
macOS traffic lights and Windows/Linux caption controls share one compact row with the sidebar toggle, the workspace name (click it for workspace settings), the current channel or DM title, and centered message search, all on one continuous chrome surface with the rail and sidebar — the conversation floats on it as a rounded card with no header row of its own. Desktop settings live in the app menu (Cmd/Ctrl+,) and the tray menu, and a "Connecting…" note appears beside the channel title only while the realtime link is down. The browser app keeps these controls in the normal app header. The desktop app checks for this renderer capability before hiding the standard frame, so older self-hosted servers retain usable native window chrome. While the integrated frame is active, non-app pages open in the system browser so the desktop window always keeps its draggable control row.
The desktop shell does not run ClickClack server code, read agent transcripts, or grant web content filesystem or Node.js access.
Servers can configure the workspace home button. With integrated chrome, a default / destination uses /app regardless of the label. Configured non-app HTTP(S) destinations, including same-origin paths such as /portal, open in the system browser through the existing navigation guard. Desktop clients using native window chrome retain their ordinary same-origin navigation behavior.
#Connect a server
Open ClickClack → Settings on macOS or File → Settings on Windows/Linux. Enter the server origin:
https://app.clickclack.chat
https://chat.example.com
http://127.0.0.1:8080
Remote servers must use HTTPS. Plain HTTP is accepted only for localhost, 127.0.0.1, and ::1. Authentication returns to Electron's persistent browser session and remains scoped to the selected origin.
Saving a server takes effect after the settings file is written successfully. Until then, the current server, window, and desktop controls stay active. A failed save leaves that selection intact and can be retried. Concurrent saves are applied in order, including window-state updates made while saving. A successful save dismisses its original Settings window; reopening Settings during a save leaves the new window open.
GitHub sign-in opens in the system browser, where existing GitHub sessions, passkeys, password managers, and two-factor authentication already work. After GitHub approves the login, chat.clickclack.desktop:/auth/callback returns a one-time grant to the running app. The app redeems it against the exact server that initiated the flow, verifies the resulting session through /api/me, and then reloads itself as the signed-in workspace. The app also accepts the legacy clickclack://auth/callback format when connecting to an older server.
Each sign-in belongs to its initiating server and window. Selecting another server, replacing that window, or starting another sign-in prevents the old in-flight attempt from navigating, showing a late error, or clearing the new attempt. Errors from the current attempt still appear normally.
Servers using namespaced cookies require desktop OAuth protocol 2. They return an update-required page before sending an older desktop client to GitHub.
When a server redirects the app to Cloudflare Access, ClickClack opens the Cloudflare Access one-time-PIN page in a small, isolated sign-in window. It shares the selected server's Electron session so Access can set its cookies, but it has no preload bridge, Node access, or popup support. ClickClack accepts only the exact HTTPS Access login URL for the configured host and returns only after the sign-in window has committed a navigation back to that server's /app route. This flow does not support arbitrary external identity providers. If the PIN window is closed or cannot complete, the main window stays on a local connection page; use View → Reload to retry or Settings to check the server URL.
This flow supports the selected ClickClack hostname only. If the Access application covers multiple domains, turn off Eager redirect cookie under Advanced settings → Cookie settings before using desktop sign-in. Cloudflare otherwise redirects through the other protected hostnames to set their cookies, which this isolated window deliberately blocks. With eager redirects off, Access issues each domain's cookie when that domain is visited. See Cloudflare's cookie settings.
#Security model
The app loads the selected ClickClack origin with Electron sandboxing, contextIsolation, webSecurity, and Node integration disabled. The preload bridge exposes only bounded notification, unread-count, navigation, and quick- compose messages. It does not expose arbitrary IPC, shell commands, environment variables, filesystem access, or credentials.
Navigation stays on the configured ClickClack origin. GitHub OAuth and other HTTP(S) and mail links open in the system browser. The callback carries only an opaque, short-lived grant: GitHub access tokens and ClickClack session tokens never appear in the callback URL. Redemption requires the verifier held by the initiating app, is single-use, survives server restart or replica handoff, and expires after five minutes. Permission requests from remote content are denied. The Cloudflare Access sign-in window denies permissions, downloads, custom protocols, and popups; navigation is limited to its Access origin and the configured ClickClack origin (including Access cookie callbacks). Only a committed /app navigation completes the sign-in. Subframe navigation has the same restriction, with https://challenges.cloudflare.com allowed only inside frames for Cloudflare Turnstile challenges. Server configuration is accepted only from the bundled local settings window and is written atomically with user-only permissions.
#Build locally
Install workspace dependencies, then build or run the desktop package:
pnpm install
pnpm build:desktop
pnpm dev:desktop
Create an unpacked app for the current platform:
pnpm --filter @clickclack/desktop run pack
Create installers on their native CI runner:
pnpm --filter @clickclack/desktop run dist:mac
pnpm --filter @clickclack/desktop run dist:win
pnpm --filter @clickclack/desktop run dist:linux
Pull requests run a three-platform desktop workflow and attach explicitly unsigned preview installers for seven days. Official macOS release candidates are built on an authorized maintainer Mac from the exact signed tag, signed inside-out with the OpenClaw Foundation Developer ID identity and hardened runtime, notarized, stapled, and uploaded to a private draft. The release workflow independently verifies their checksums, bundle seals, stable bundle identifier, Foundation team, Gatekeeper assessment, and notarization tickets before publishing them alongside the Windows and Linux installers.
#Icon system
apps/desktop/assets/icon-source.svg is the source of truth: the "Keystroke" mark — two keycaps mid-stroke, one raised in porcelain and one pressed in signal cyan, on the navy Switchboard board. Generated assets include multi-resolution macOS .icns, Windows .ico, Linux PNG, a monochrome macOS tray template, and a Windows unread overlay. Regenerate them from the SVG sources with rsvg-convert (PNGs), iconutil (.icns), and ImageMagick (.ico).