Запустити headless-сервер
Запустіть cc_server на машині, яка працює постійно, а потім підключіться до неї з настільного застосунку, браузера чи телефона. Сервер — це нативний бінарник, написаний суто на Dart, без рушія Flutter, тож він працює headless на macOS, Linux і Windows. Він володіє базою даних, запускає агентів і виконує всі зовнішні виклики API; клієнти лише відображають.
Запуск у Docker (готові образи)
Розділ із назвою «Запуск у Docker (готові образи)»Кожен випуск публікує стек для самостійного розміщення з чотирьох образів GHCR — бекенд, два статичні тонкі клієнти й необов’язкове реле прив’язки — а також окремий образ cc-server-demo для публічного демо-хоста. Для самостійного розміщення не потрібне ні клонування репозиторію. Закріпіть тег версії (ghcr.io/samuelalev/<image>:v0.0.1-rc.1) або використовуйте latest.
| Образ | Що це | Публікує |
|---|---|---|
ghcr.io/samuelalev/cc-server |
Бекенд: база даних, агенти, MCP, вебхуки | -p 9030:9030 |
ghcr.io/samuelalev/cc-webapp |
Вебклієнт (статичний nginx) | -p 8080:8080 |
ghcr.io/samuelalev/cc-remote |
Супровідний телефонний PWA (статичний nginx) | -p 8081:8080 |
ghcr.io/samuelalev/cc-signaling-server |
Реле прив’язки WebRTC (необов’язкове) | -p 8788:8788 |
Увесь стек як файл compose:
services: server: image: ghcr.io/samuelalev/cc-server:latest ports: ["9030:9030"] volumes: ["cc_data:/data"] restart: unless-stopped web: image: ghcr.io/samuelalev/cc-webapp:latest ports: ["8080:8080"] restart: unless-stopped remote: image: ghcr.io/samuelalev/cc-remote:latest ports: ["8081:8080"] restart: unless-stopped signaling: image: ghcr.io/samuelalev/cc-signaling-server:latest ports: ["8788:8788"] restart: unless-stopped
volumes: cc_data:Що варто знати, перш ніж відкривати будь-що з цього поза loopback:
-
Образ
cc-serverпостачається зCC_SERVER_INSECURE=1(він має прив’язуватися до0.0.0.0, щоб приймати трафік опублікованого порту), що безпечно лише за зворотним проксі, який завершує TLS — Caddy, Traefik, nginx або Cloudflare Tunnel — у довіреній мережі. Щоб натомість завершувати TLS у самому процесі, змонтуйте сертифікат і задайтеCC_SERVER_TLS_CERT/CC_SERVER_TLS_KEY(а потім знімітьCC_SERVER_INSECURE). Усе це можна перевизначити черезdocker run -e …або блокenvironment:у compose. -
/data— це єдиний стан. Бази даних SQLite, секрети прив’язаних пристроїв, завантажені моделі та аудіо зустрічей — усе живе в томі: зробіть його резервну копію, і контейнер стане одноразовим. -
Прив’яжіть клієнт зсередини образу до першого підключення — контейнерний відповідник кроку 3:
Вікно термінала docker run --rm -it -v cc_data:/data \--entrypoint /app/bin/cc_server ghcr.io/samuelalev/cc-server:latest pair -
Обидва клієнтські образи — це статичні хости nginx: нічого не треба налаштовувати під час роботи; форма підключення кожного клієнта приймає URL сервера, ідентифікатор пристрою та ключ прив’язки. Реле сигналізації так само потребує лише свого порту (
SIGNALING_HOST/SIGNALING_PORTможна перевизначити); воно безстанове, не зберігає секретів і є запасним шляхом — телефон використовує loopback, локальну мережу, tailnet або прямий шляхwss://, коли якийсь із них доступний, і звертається до реле лише тоді, коли жоден недоступний. Пропустіть його, якщо ваші клієнти завжди дістаються сервера напряму.
Решта цього посібника збирає сервер із вихідного коду; прапорці та поведінка, які він описує, — ті самі, що їх живлять змінні середовища образу.
Передумови
Розділ із назвою «Передумови»- Dart SDK. Цей репозиторій закріплює свій SDK через fvm, тож додавайте
fvmна початок кожної команди. - Клонований цей репозиторій.
- Нативний набір інструментів, потрібний скрипту підготовки — Rust/
cargo, а такожmeson,ninja,pkg-config,gitі компілятор C++. Кожен скрипт збірки повідомляє, чого не знайшов і як це встановити. - Доступний хост: loopback для локального використання або адреса в локальній мережі чи публічна адреса з TLS для віддалених клієнтів.
Крок 1: Підготуйте нативні бібліотеки
Розділ із назвою «Крок 1: Підготуйте нативні бібліотеки»Нативні бібліотеки обов’язкові — режиму з обмеженою функціональністю немає. Зберіть їх із кореня репозиторію перед усім іншим:
scripts/natives/build_natives.shЦе збирає rift, fff, tree-sitter разом з його граматиками, aec, lame, ccpty, cc_watcher, cc_inference і нативну бібліотеку SAML у build/natives/. Хук збірки cc_server переносить усе, що там підготовлено, у пакет, тож пропуск цього кроку або провалює збірку відразу, або — з обхідним шляхом нижче — дає бінарник, чия передперевірка завантаження відмовляється запускатися й називає відсутню бібліотеку.
Крок 2: Зберіть бінарник
Розділ із назвою «Крок 2: Зберіть бінарник»cd apps/cc_serverfvm dart build cliПакет постачає libsqlite3 і підготовлені нативні бібліотеки поряд із бінарником — системний SQLite і рушій Flutter не потрібні. Виконуваний файл опиняється за шляхом ./build/cli/<os_arch>/bundle/bin/cc_server.
Крок 3: Прив’яжіть клієнт до першого запуску
Розділ із назвою «Крок 3: Прив’яжіть клієнт до першого запуску»У свіжому каталозі даних немає прив’язаного пристрою й наперед спільного ключа, тож запит клієнта на ключ прив’язки ще нічим задовольнити. Створіть його підкомандою pair. Вона пише global.db і secrets.json напряму; сервер, який уже обслуговує цей каталог даних, підхоплює новий пристрій без перезапуску:
./build/cli/<os_arch>/bundle/bin/cc_server pair --data-dir ./data --port 9030Вона виводить три значення, які треба вставити у форму підключення клієнта:
Connect a thin client (paste into its connect form): Server ws://localhost:9030/rpc Device id web-client Pairing key <a freshly generated key>Корисні прапорці: --device (типово web-client; ідентифікатор також визначає рівень пристрою — desktop, ios, android, а будь-що інше — вебклієнт), --label (типово назва платформи плюс ім’я хоста цієї машини), --host (хост, який виводиться в URL, адже loopback недоступний з іншої машини) і --client-url. Повторний запуск pair оновлює ключ цього пристрою та розриває його активні сесії. Прив’язка ніколи не створює робочий простір: перший створює й називає початкове налаштування клієнта, який підключається.
З --client-url вона також виводить QR-код для сканування з термінала, який відкриває вебклієнт уже заповненим:
./build/cli/<os_arch>/bundle/bin/cc_server pair --data-dir ./data --port 9030 \ --bind any --host 192.168.1.42 --client-url https://app.usectrl.devОблікові дані, створені cc_server pair, не мають терміну дії; створені в застосунку завжди спливають через 30 днів. Відкликайте пристрій, створений через CLI, у Налаштування → Ви → Ваші пристрої, коли він вам більше не потрібен.
Крок 4: Запустіть сервер
Розділ із назвою «Крок 4: Запустіть сервер»На loopback — типово й цього досить для клієнта на тій самій машині:
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030Щоб дістатися з іншої машини, прив’яжіться до всіх інтерфейсів. Прив’язка не до loopback без TLS відхиляється під час запуску (Refusing to bind non-loopback address … without TLS), тож надайте сертифікат:
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030 \ --bind any --tls-cert /path/fullchain.pem --tls-key /path/privkey.pem \ --public-url wss://server.example:9030/rpcАбо завершуйте TLS у зворотному проксі в довіреній приватній мережі та увімкніть прив’язку незашифрованим текстом за ним:
./build/cli/<os_arch>/bundle/bin/cc_server --data-dir ./data --port 9030 \ --bind any --insecure --public-url wss://server.example/rpc--insecure ігнорується, коли задано і --tls-cert, і --tls-key — TLS завжди перемагає. Сервер повідомляє стан незашифрованого тексту як insecure: true у GET /healthz, і клієнти позначають таке з’єднання як незахищене.
Сервер працює до SIGINT/SIGTERM, а потім чисто завершує роботу.
Крок 5: Підключіть клієнт
Розділ із назвою «Крок 5: Підключіть клієнт»Спрямуйте клієнт на URL сервера та ключ прив’язки з кроку 3:
- Настільний застосунок: на екрані першого запуску (Як має працювати Control Center?) заповніть поля підключення замість Запустити в цій програмі або додайте сервер пізніше в Налаштування → Сервер → Підключення та стан. Див. Під’єднатися до віддаленого сервера.
- Вебклієнт: відкрийте app.usectrl.dev (або власну копію вебзбірки) і введіть URL сервера, ідентифікатор пристрою та ключ прив’язки.
- Телефон: прив’яжіть застосунок Remote із запущеного клієнта — див. Прив’язати пристрій.
Крок 6: Підключіть Google Calendar (необов’язково)
Розділ із назвою «Крок 6: Підключіть Google Calendar (необов’язково)»Щоб синхронізувати календар робочого простору без графічного інтерфейсу, скористайтеся потоком із кодом пристрою:
GOOGLE_OAUTH_CLIENT_ID=<id> GOOGLE_OAUTH_CLIENT_SECRET=<secret> \ ./build/cli/<os_arch>/bundle/bin/cc_server calendar connect \ --data-dir ./data --workspace <workspace-id>Він виводить код і URL для підтвердження на іншому пристрої, зберігає токен оновлення на сервері та завершується. Збірка з вихідного коду не містить клієнта Google, тож змінні середовища з ідентифікатором і секретом обов’язкові — прапорця --google-client-id немає. Див. Підключити Google Calendar.
Конфігурація
Розділ із назвою «Конфігурація»Прапорці, використані вище, — це ті, що потрібні для першого налаштування. Повний набір — 23 пари прапорців і змінних середовища, чотири підкоманди та структура каталогу даних — у довідці CLI cc_server.
Чотири, які найімовірніше вам знадобляться:
| Прапорець | Типово | Значення |
|---|---|---|
--data-dir |
каталог даних застосунку для користувача в ОС | Бази даних, секрети, моделі та кешовані медіа |
--port |
9030 |
Порт TCP (0 = тимчасовий) |
--bind |
loopback |
loopback або any для всіх інтерфейсів (потребує TLS чи --insecure) |
--public-url |
похідний від прив’язки | URL RPC, який повідомляється прив’язаним клієнтам. Задайте його явно за проксі, NAT або тунелем |
Типовий каталог даних — ~/Library/Application Support/control-center на macOS, %APPDATA%\control-center на Windows і $XDG_DATA_HOME/control-center (інакше ~/.local/share/control-center) на решті платформ. Відносний до робочого каталогу .cc_server використовується лише тоді, коли не вдається визначити ні домашній каталог, ні каталог даних застосунку.
Що обслуговує сервер
Розділ із назвою «Що обслуговує сервер»cc_server — це вся поверхня продукту, а не її підмножина: шлях даних repo-RPC і підписки, кінцева точка інструментів MCP за POST /mcp і GET /sse на тому самому порту, вхідні вебхуки, проксі медіа та шрифтів, зворотні виклики єдиного входу, протокол оренди флоту, отримання RSS на боці сервера за 30-хвилинним розкладом і векторний пошук (розширення sqlite_vector зареєстровано як глобальне для процесу автоматичне розширення, що переходить до повнотекстового пошуку лише там, де розширення недоступне).
Диспетчер безстановий: немає прив’язки робочого простору до сесії. Кожен виклик у межах робочого простору несе власний workspace_id, і доступ визначається членством у робочому просторі та роллю того, хто викликає, — а не наявністю ключа прив’язки.
Дві речі, які варто знати, перш ніж відкривати порт поза loopback:
- MCP закривається за замовчуванням поза хостом. Поверхня MCP без токена відповідає лише на loopback. Прив’язка
anyцього не розширює — запит ззовні хоста відхиляється з «MCP requires a bearer token to answer non-loopback clients», доки ви не налаштуєте токен (mcp.setTokenабо Налаштування → Сервер → MCP-сервери). GET /healthzнавмисно не вимагає автентифікації, має CORS із дозволом будь-якого джерела й публікує ідентифікатор, ім’я, відбиток ідентичності та версію збірки сервера. Клієнтам потрібен відбиток, щоб закріпити сервер, тож це свідоме рішення — але воно означає, що будь-який доступнийcc_serverрозкриває стільки кожному, хто запитає.
Пов’язані посібники
Розділ із назвою «Пов’язані посібники»- Під’єднатися до віддаленого сервера
- Прив’язати пристрій
- Запустити воркер флоту
- Підключити Google Calendar