Cluely — коммерческий AI-ассистент, который во время созвонов и собеседований «слушает» звук и «смотрит» на экран, подсказывая ответы в окне, скрытом от демонстрации экрана.
OpenCluely — свободная open-source реализация той же идеи по принципу BYOK (свой API-ключ): чат с LLM, real-time транскрипция голоса и «скриншот → вопрос» в лёгком стелс-оверлее для macOS и Windows.
Проект носит демонстрационный характер и создан в образовательных целях. Ответственность за его использование полностью лежит на пользователе.
Главная цель репозитория — презентация опыта разработки полноценного проекта с помощью AI:
- Код написан с использованием Claude Code — от каркаса до упаковки инсталляторов
- Дизайн разработан с использованием Claude Design
Итог: ~150 юнит-тестов + E2E на Playwright, собранные инсталляторы под macOS и Windows, и подробная документация каждого этапа.
- Spotlight-оверлей — компактная строка ввода, разворачивается в чат.
- Невидимость при демонстрации экрана —
setContentProtection(true)на окне (⌘H переключает). - Чат с LLM за абстракцией
ChatProvider— по умолчанию OpenAI (gpt-4o-mini), Gemini (gemini-2.5-flash) как второй провайдер. Ответы — markdown с подсветкой кода и копированием. - Скриншот → вопрос — к сообщению незаметно прикрепляется скриншот экрана (модель «видит» экран); в ленте чата он не показывается.
- Real-time транскрипция голоса (STT) — стриминг по WebSocket (OpenAI realtime,
gpt-4o-transcribe), транскрипт пишется в поле ввода на лету и авто-отправляется в чат. - Глобальные хоткеи — вызвать окно, «паник-скрытие», голос, показ экрана ассистенту.
- Онбординг и Настройки — провайдеры/ключи, микрофон, разрешения, шорткаты.
- Кросс-платформенность — macOS и Windows, инсталляторы через
electron-builder.
| Слой | Технологии |
|---|---|
| Оболочка | Electron 33, electron-vite, electron-builder |
| UI | React 18 + TypeScript, Vite, zustand, react-markdown + remark-gfm + highlight.js |
| LLM / STT | @google/genai (Gemini), openai (chat + realtime STT), ws |
| Аудио | Web Audio API, AudioWorklet (даунсемпл в 16 кГц mono Int16 PCM) |
| Тесты | Vitest (юнит) + Playwright-Electron (E2E) |
| Тулинг | ESLint (flat config), Prettier, tsc --noEmit |
Три процесса Electron с жёстким разделением ответственности
(подробно — в docs/architecture.md):
- main (Node) — единственный доверенный процесс: окно-оверлей и стелс, глобальные хоткеи, сеть к LLM/STT, чтение экрана, файловое хранилище.
- preload — тонкий типизированный мост
window.apiчерезcontextBridge(contextIsolation: true,nodeIntegration: false,sandbox: true). - renderer (React) — только UI и захват медиа браузерными API; аудио-чанки уходят в main по IPC.
Что стоит посмотреть в коде:
safeStorageдля ключей — API-ключи шифруются в покое через OS keychain (src/main/store/settings.store.ts) и живут в открытом виде только в main-процессе; в рендерер они не передаются никогда (settings:getотдаётPublicSettingsбез ключей, только булевы флаги наличия).- Абстракции провайдеров —
ChatProviderиSttProvider(src/main/services/chat,.../stt): SDK изолированы, чистые билдеры запросов тестируются без сети, провайдер меняется флагом. - Стелс-оверлей —
src/main/windows/stealth.ts(applyStealthMeasures+ enforcers,type: 'panel',transparent,frame: false, content protection). - Аудио-конвейер —
src/renderer/src/audio(pcm.worklet.ts, чистый DSP вdsp.ts): микрофон (+ опц. системный звук) → микс → 16 кГц PCM → IPC → STT. - Чистое ядро + тонкие оболочки — вся логика (сборка запросов, DSP, VAD, дисковый формат
настроек, диспетчер шорткатов, гейт онбординга) вынесена в чистые функции с юнит-тестами;
Web-Audio, WebSocket и
safeStorage/fs — тонкие «оболочки».
- Node.js ≥ 20 (проверено на 22.12), npm ≥ 10
- macOS или Windows
npm installnpm run devПриложение работает и без ключа (покажет подсказку при отправке). Чтобы сразу подключить LLM, передайте ключ через переменную окружения (или введите его в Настройках → Провайдеры):
OPENAI_API_KEY=your_key npm run dev # провайдер по умолчанию — openai
# либо, если выбран Gemini:
GEMINI_API_KEY=your_key npm run devSTT (голос) использует тот же
OPENAI_API_KEY. Для демо без сети/ключа:STT_FAKE=1 npm run dev.
| Команда | Что делает |
|---|---|
npm run dev |
Dev-режим с HMR рендерера |
npm run build |
Прод-сборка (main / preload / renderer в out/) |
npm run typecheck |
tsc --noEmit |
npm run lint / npm run format |
ESLint / Prettier |
npm test |
Юнит-тесты (Vitest) |
npm run test:e2e |
Сборка + Playwright-Electron E2E |
npm run pack # быстрая сборка .app без установщика (dist/)
npm run dist:mac # DMG под arm64 и x64
npm run dist:win # Windows NSIS-инсталлятор (.exe)MVP без подписи кода. macOS покажет предупреждение Gatekeeper (первый запуск — правый клик → «Открыть»), Windows — SmartScreen. Как включить подпись/нотаризацию — в
docs/dev-setup.md.
Для полной работы нужны системные разрешения «Микрофон» и «Запись экрана» (System Settings → Privacy & Security). Запрашиваются во вкладке «Разрешения».
| Клавиши (macOS) | Действие |
|---|---|
⌘⇧Space |
Показать окно и поставить курсор в поле ввода |
⌘\ |
Скрыть/показать всё окно (паник-скрытие) |
⌘H |
Режим невидимки (защита контента при записи экрана) |
⌘⇧S |
Прикреплять ли скриншот экрана к сообщениям |
⌘M |
Голосовой ввод (STT) |
Enter · Esc · ⌘R |
Отправить · свернуть · новый чат |
- Подход BYOK — вы используете собственный ключ провайдера.
- Ключи шифруются через
safeStorage(OS keychain) и хранятся только в main-процессе. - В открытый исходный код или в рендерер ключи не попадают; в репозитории их нет.
- Данные (текст, аудио, скриншоты) отправляются только выбранному провайдеру LLM/STT.
Полная документация проекта — в docs/:
архитектура · решения (ADR) ·
roadmap · UI-спека ·
IPC-контракт · dev-setup ·
стелс-оверлей.
MIT © Ramzil