Forge Mobile Dev Station
Путь: /home/claude/forge/
Сервис: forge.service (systemd —user), порт 3000 (fastify + ws), процесс bot.js
Стек: fastify, better-sqlite3 (forge.db), telegraf (Telegram-бот), ws (WebSocketServer), Vite miniapp (miniapp/)
Отдельный проект от claudeclaw (у claudeclaw свой модуль src/forge.ts для управления тасками — не путать с этим сервисом).
Архитектура
bot.js— Telegram-бот, точка входа, спавнит Claude Code сессии на задачиserver.js— HTTP API (/api/tasks*,/api/projects) + WS-сервер на том же порту 3000supervisor.js—buildPlan/executeTask/killTask/mergeAndClean(PLAN-GATE workflow)db.js+forge.db— sqlite, таблицыtasks,forge_eventsevents.js— EventEmitter, мост между supervisor-событиями и WS-рассылкойminiapp/— Telegram Mini App (Vite), фронтенд для просмотра задач
WebSocket endpoint
ws://<host>:3000/ws/tasks/:id — по одному подключению на задачу.
- При коннекте сервер сразу шлёт
{type:'init', events:[...], status:...}(вся история событий таска) - Далее пушит новые события через
taskEvents.on('task:<id>', ...)—status_changeи т.п. - Входящие сообщения от клиента не обрабатываются —
ws.on('message', ...)вserver.jsне зарегистрирован. Это read-only канал сервер→клиент. - Нет пути
pathфильтра на уровнеWebSocketServer— роутинг вручную через regex наreq.url
Тест WS (2026-07-01)
Тестировали на живой задаче id=34 (“WS test task” — эта же сессия себя тестировала).
Результат:
- ✅ Подключение к
ws://127.0.0.1:3000/ws/tasks/34— успешно,initс историей событий пришёл сразу - ✅ Отправка сообщения клиент→сервер — принята без ошибок (сервер её просто игнорирует, ожидаемо — обработчика нет)
- ✅ Разрыв соединения (
close(1000)) и повторное подключение — переподключение работает,initснова приходит корректно - ⚠️ Логов нет вообще:
fastify({logger:false}), WS-подключения/отключения/ошибки нигде не пишутся в journalctl. Если WS сломается в проде — узнать об этом можно будет только по симптомам в miniapp, не по логам - ⚠️ Ненормальный shutdown: при каждом рестарте
forge.serviceвиденstop-sigterm timed out→SIGKILL(см.journalctl --user -u forge.service). Это значит открытые WS-соединения рвутся без close-фрейма (клиент получит1006, а не штатный1000/1005). Стоит разобраться, что вbot.js/server.jsблокирует грациозный шатдаун (скорее всего висящий Claude Code child process в supervisor).
Незакрытые задачи
- Добавить логирование WS-событий (connect/disconnect/error) хотя бы на
logger: trueили явный console.log - Разобраться с graceful shutdown — что не даёт процессу завершиться по SIGTERM за 90 сек