Skip to content

Repository files navigation

ChatGPT Desktop Companion

A lightweight AI sidebar for your desktop. One keystroke summons a docked, frameless window holding your AI assistants: ChatGPT, Claude, Gemini, Perplexity, or any https app you add yourself. Switching providers is instant and never loses a half typed prompt, because every provider stays alive in its own cached view.

npm install
npm start

What it does

  • Always one keystroke away. Ctrl+Shift+Space (Cmd+Shift+Space on macOS) toggles the sidebar from anywhere. Closing hides to the tray; the app keeps running.
  • Instant provider switching that preserves state. Each enabled provider is a live, cached web view. A draft typed in Claude survives a detour into ChatGPT, and a streaming answer keeps streaming in the background.
  • Isolated logins. Every provider gets its own persistent session partition, so accounts never cross contaminate.
  • Keyboard first. Inside the window: Ctrl/Cmd+1..9 switch by tab order, Ctrl+Tab and Ctrl+Shift+Tab cycle, Ctrl/Cmd+= - 0 zoom, Ctrl/Cmd+R reload.
  • One piece of chrome. A 28px strip at the top is the drag handle and the provider tabs. That is all the UI, by design; everything else lives in the tray menu.
  • Tray menu. Switch and enable providers, dock left or right, always on top, start at login, reload page, open the current page in your browser, edit and reload the config file, quit.
  • Secure by default. Sandboxed renderers, context isolation, no node integration in web content, a strict navigation policy (OAuth popups allowlisted, other links open in your default browser), and a minimal permission policy.

Configuration

Settings live in a JSON file at userData/config.json (the tray item "Edit Config" opens it; "Reload Config" applies changes without restarting):

{
  "activeProvider": "chatgpt",
  "enabledProviders": ["chatgpt", "claude"],
  "customProviders": [
    { "name": "Kagi Assistant", "url": "https://kagi.com/assistant" }
  ],
  "hotkey": "CommandOrControl+Shift+Space",
  "alwaysOnTop": false,
  "hideOnBlur": false,
  "dockWidthFraction": 0.25,
  "windowBounds": null
}

Custom providers must be https. Invalid fields fall back to their defaults with a warning in the console, never a crash.

Honest caveats

  • Google sign in may refuse embedded browsers. Gemini ships in the catalog but disabled by default: Google can reject sign in inside any Electron shell no matter what the user agent says. "Open in Browser" in the tray is the escape hatch.
  • Upgrading from v1 signs you out once. v2 moves each provider into its own session partition, which abandons the old shared cookies. Your v1 window bounds, always on top setting, and custom URL migrate automatically.
  • Memory scales with enabled providers. Each live provider view is a renderer process (roughly like one browser tab). Views are created lazily and only for enabled providers.

Development

Everything with an if statement lives in pure modules under src/lib and is tested with the built in node test runner; main.js and src/app are thin Electron wiring.

main.js            composition root: lifecycle, wiring, dispatch
src/app/views.js   cached WebContentsView per provider, policy wiring
src/app/tray.js    tray glue over the pure menu template
src/lib/*.js       providers, config, store, layout, keymap, policy, ua, zoom, tray-template
chrome/            the 28px strip (html, css, js, preload)
test/              node:test suites, one per lib module, plus a style guard
npm test           # pure node, no electron needed
npm run build      # package for the current platform via electron-builder
npm run build:win  # or build:mac, build:linux

The dispatch loop in one glance:

tray click / strip click / hotkey / keymap chord
        -> action string ("switch-provider:claude", "dock:left", ...)
        -> dispatch() in main.js
        -> config change + view manager + save + refresh ui

Changelog

2.0.0

  • Multi provider: ChatGPT, Claude, Gemini, Perplexity, plus custom https providers from the config file
  • Cached per provider views with instant, state preserving switching
  • Per provider session partitions (breaking: one time re login after upgrade)
  • Global toggle hotkey, in app keyboard switching, cycling, zoom
  • Draggable provider strip; v1 windows could not be moved with the mouse at all
  • Dock left and right, display aware bounds restore, start at login
  • Hardened Electron security: sandbox, context isolation, navigation and permission policy
  • Zero runtime dependencies; config is a plain JSON file you can edit from the tray
  • Test suite on the node 22 built in runner with CI

1.0.2 (2023-02-24)

  • "Change URL" option for future proofing

1.0.1 (2023-02-23)

  • Remembers the last window size and state
  • Tray menu: always on top, restart, quit

1.0.0 (2023-02-23)

  • Initial release: resizable chromeless window, minimize and close to tray

Screenshot

v1 shown; v2 adds the provider tab strip at the top.

Screenshot

Built on Electron.

About

Allows you to parallelly run ChatGPT as a sidebar desktop app (Win/Mac/Linux) when working on your computer

Topics

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages