Skip to content
This repository was archived by the owner on Oct 7, 2026. It is now read-only.
maketryukPublic archive

About

Native macOS workspace manager for developers: projects, terminal sessions, AI CLI agents, dev services, Docker and SSH in one dark, keyboard-driven window. Sessions run in a background daemon and survive quitting the app.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Relay

Нативный workspace manager для macOS: проекты, терминальные сессии и AI CLI-агенты (Claude Code, Codex) в одном тёмном интерфейсе. Без Electron — Swift 6 + SwiftUI.


Требования

macOS 14 Sonoma или новее. Больше ничего.

Отдельно ставить Claude Code, Codex, Docker и прочее не нужно — Relay запускает то, что уже стоит в системе.


Установка

Скачайте последнюю сборку со страницы Releases — .dmg, если он приложен, иначе .app.zip — и перетащите Relay.app в /Applications до первого запуска.

Этот шаг обязателен, а не косметический: macOS запускает скачанное приложение из временной копии, пока его не переместили, и в ней оно не находит части самого себя. Перетащили — карантин снят, копии нет.

Дальше Relay обновляет себя сам: он спрашивает GitHub о новых релизах и предлагает поставить их одной кнопкой.

Сборка из исходников нужна только для разработки самого Relay — она описана в разделе Разработка.


Запуск

Из Finder — двойной клик по Relay.app. Или из терминала:

open /Applications/Relay.app

При первом запуске macOS может спросить доступ к папкам (Documents, Desktop) — это нужно, чтобы Relay мог открывать в них проекты.

Первые шаги

  1. Нажмите + внизу левой полосы и выберите папку проекта.
  2. Проект появится иконкой в левой полосе (Project Rail).
  3. Нажмите Claude, Codex или Shell — откроется терминальная сессия в корне проекта.
  4. Закройте приложение и откройте снова — сессии будут на месте, вместе с историей вывода.

Возможности

Sessions — Terminal, Claude, Codex, Gemini, OpenCode, SSH, произвольная команда. Несколько сессий на проект, история, восстановление после перезапуска приложения.

Сессия называет себя сама: агенты и шеллы сообщают, чем заняты, через заголовок терминала, и Relay показывает именно его — «refactoring the parser» вместо «Claude 2». Переименовать вручную можно двойным кликом по названию в списке; после этого ваше имя больше не перезаписывается.

Новая сессия — кнопка + в секции Sessions. Там пресеты: каждый со своей иконкой, названием и видимой командой. Агенты по умолчанию запускаются в режиме автоодобрения (claude --permission-mode auto, codex --approve-for-me, gemini --approval-mode auto_edit), рядом лежит вариант «ask first» с подтверждениями. Свою команду можно сохранить пресетом прямо оттуда, список — в Settings → General.

Services — долгоживущие процессы проекта (pnpm dev, API, worker). Start, Stop, Restart, логи, автоопределение порта и кнопка Open URL. Dev-команда подхватывается из package.json при добавлении проекта.

Ports — кнопка в левой рельсе (или ⌘\, или Command Palette) открывает отдельное окно со всеми портами, которые слушает машина: node, Docker, что угодно. То, что запустил Relay, помечено и подписано именем сессии. Есть поиск, открытие в браузере и копирование URL.

Браузер и design mode — вкладка браузера открывается там же, где сессии: пункт Browser в меню + или ⇧⌘B. Вкладок у проекта может быть сколько угодно, они видны в сайдбаре под сессиями. Это Chromium, тот же движок, под который пишется страница. Если dev-сервис проекта запущен, новая вкладка открывается сразу на нём. Адрес из Services, окна портов или Command Palette открывается во вкладке, которая уже смотрит на этот сервер, а если такой нет — в новой. ⇧⌘E включает design mode: наведите на элемент и кликните. В промпт агента попадёт его разметка, вычисленные стили, компонент, который его отрисовал, и файл со строкой, где этот компонент написан (React, Vue и Svelte в dev-сборке), а ещё скриншот элемента и строка о том, что нужно поменять. Текст только вводится, но не отправляется. После этого можно сразу кликнуть снова и проверить, что агент поменял. ⌘R перезагружает страницу, ⌥⌘I открывает инспектор Chromium.

Docker — если в проекте найден compose-файл, доступны Up / Down / Restart / Logs, список контейнеров с их состоянием и опубликованными портами.

SSH — хосты читаются из ~/.ssh/config вместе с директивами Include. Подключение одним кликом, нужные хосты можно закрепить за проектом.

Notifications — macOS-уведомления только о том, что действительно требует внимания: агент ждёт ответа, процесс упал, задача завершена. Отключается глобально, по проекту и по типу события.

Settings (⌘,) — общие настройки, переназначение всех хоткеев с проверкой конфликтов, управление уведомлениями.


Горячие клавиши

Все сочетания переназначаются в Settings → Shortcuts (⌘,). Там же видно, если два действия конфликтуют.

Сочетание Действие
⌘P Command Palette (⌘K тоже работает)
⌘, Настройки
⌘\ Панель портов
⌘T Новый Shell
⇧⌘C Новая сессия Claude
⇧⌘X Новая сессия Codex
⌘W Убрать панель с экрана
⇧⌘R Переименовать сессию
⇧⌘] / ⇧⌘[ Следующая / предыдущая сессия
⌘1…⌘9 Перейти к сессии по номеру
⌘↩ Фокус в терминал
⇧⌘B Новая вкладка браузера
⇧⌘E Design mode
⌘R Перезагрузить страницу в браузере
⌥⌘I Инспектор Chromium
⌥⌘R Перезапустить dev-сервис
⌥⌘↓ / ⌥⌘↑ Следующий / предыдущий проект
⌥⌘1…⌥⌘9 Перейти к проекту по номеру
⇧⌘N Добавить проект
⇧⌘O Открыть проект в Finder
⇧⌘, Настройки проекта

⌘W и крестик в шапке панели убирают её с экрана, а не закрывают окно: Relay — однооконное приложение. Сессия при этом продолжает работать и остаётся в сайдбаре, откуда её можно открыть снова. Завершается она только из сайдбара — крестиком в её строке или пунктом «Закрыть» в её меню.

При наведении на иконочные кнопки появляется подсказка с названием действия и его сочетанием.


Индикаторы статуса

Знак на иконке проекта — агрегированное состояние всех его сессий. Состояние видно по форме знака, цвет его только подтверждает. Приоритет сверху вниз: если хотя бы одна сессия ждёт вас, весь проект показывает вопрос.

Знак Состояние Значение
вопрос в жёлтом круге Waiting for you агент задал вопрос и ждёт ответа
красная точка Error процесс завершился с ошибкой
синее кольцо, вращается Working, Starting агент работает
галочка в зелёном круге Finished задача выполнена
серая точка Idle сессия жива, но ничего не происходит

Кольца вращаются в такт друг другу. С включённым «Уменьшить движение» кольцо замыкается и стоит на месте.

Знак есть только у агентов. У обычного терминала его нет: шелл, сборка или редактор в нём — не новость для иконки проекта. Исключение — терминал, в котором вы сами запустили claude или codex: пока агент в нём работает, у терминала есть и знак.

Статус агента — то, что сообщает сам агент. При запуске Relay добавляет свой хук в настройки Claude Code и Codex (~/.claude/settings.json, ~/.codex/hooks.json) рядом с чужими. Через него агент сообщает о каждом промпте, вызове инструмента, запросе разрешения и конце хода. Вне терминала Relay этот хук ничего не делает. Если хука нет, Relay читает знак, который агент ставит в заголовок терминала, а для шеллов и всего остального — активность терминала. К API Claude и OpenAI Relay не обращается: всё работает локально.

Субагенты, которых запускает Claude Code, видны строкой под своей сессией: их задача, тип и тот же знак состояния. Субагент, которому Claude Code выделил отдельный worktree, показан под заголовком этого worktree. Клик по строке открывает сессию, которая его запустила. Пока фоновые субагенты работают, их сессия тоже считается работающей, даже если сам агент уже закончил ход.


Команда relay

В каждом терминале, который запускает Relay, есть команда relay. Ею агент — или вы — работает с worktrees проекта, в котором открыт терминал, причём руками самого приложения: что сделала команда, сразу видно в сайдбаре.

relay worktree list        # worktrees проекта; * — тот, в котором вы сейчас
relay worktree current     # тот, в котором вы сейчас
relay worktree create fix-login --agent claude --prompt "Почини редирект после входа"
relay worktree rm fix-login                  # с незакоммиченными изменениями — только с --force
relay worktree set --status in-review --comment "Готово, тесты проходят"
relay help                 # справка; у каждой команды есть --help

create называет ветку и выбирает папку так же, как окно New Worktree, и передаёт промпт агенту, когда тот готов его принять; --agent — это пресет сессии: claude, codex или имя пресета. rm удаляет и ветку, если её создал Relay и в ней нет неслитых коммитов, и никогда не трогает папку самого проекта. Без имени команда берёт worktree, в котором запущена. С --json ответ приходит в JSON, ошибки тоже. Код выхода: 0 — сделано, 1 — отказ или ошибка, 2 — такой команды нет.

Команда лежит в бандле, Relay.app/Contents/Helpers/relay. Терминал Relay добавляет эту папку в PATH и кладёт полный путь в RELAY_CLI. Терминал Relay Dev говорит с Relay Dev; вне терминалов Relay команда обращается к обычному Relay, а с RELAY_FLAVOUR=dev — к Relay Dev. Если приложение не запущено, она так и отвечает и выходит с кодом 1.


Демон сессий

relay-daemon — фоновый процесс, владеющий всеми PTY. GUI запускает его автоматически и является лишь клиентом.

# Запущен ли демон
pgrep -lf relay-daemon

# Логи
tail -f ~/.relay/Logs/daemon.log

# Остановить демон вместе со всеми сессиями
pkill -f relay-daemon

Демон сам завершается через 30 минут после того, как не осталось ни клиентов, ни сессий.

Где что лежит

Путь Содержимое
~/.relay/workspace.json проекты и настройки
~/.relay/Logs/daemon.log лог демона
~/.relay/chat рабочая папка сессий вне проекта
~/.relay/worktrees/<репозиторий>/<ветка> worktrees, созданные в Relay
/tmp/relay-<uid>.sock сокет связи GUI ↔ демон
/tmp/relay-<uid>-hooks.sock куда хуки агентов сообщают демону свой статус
/tmp/relay-<uid>-control.sock через него команда relay говорит с приложением
~/.claude/settings.json, ~/.codex/hooks.json хук Relay рядом с остальными; вне терминала Relay он ничего не делает

Секреты не сохраняются: SSH-ключи, пароли и содержимое окружения на диск не пишутся.


Разработка

Нужен Xcode 15 или новее — Relay собирается компилятором Swift 6. Если xcode-select -p ничего не выводит, доставьте инструменты командной строки через xcode-select --install.

git clone <репозиторий> relay
cd relay
./Scripts/build-app.sh   # первая сборка 1–3 минуты, дальше секунды
./Scripts/install.sh     # кладёт бандл в /Applications и регистрирует его

Первая сборка бандла один раз скачивает Chromium для панели браузера (130 МБ) в ~/Library/Caches/com.maketryuk.relay/chromium; swift build и swift test обходятся без него.

install.sh снимает карантин и регистрирует бандл в Launch Services — без этого Spotlight, Raycast и Dock приложение не найдут: лаунчеры индексируют только стандартные каталоги, а не вашу папку сборки.

swift test                        # 236 тестов, ~15 секунд
swift build                       # собрать всё
swift build --product Relay       # только GUI
swift build --product relay-daemon # только демон
./Scripts/build-app.sh debug      # .app из debug-сборки

# запустить GUI из исходников, указав свой демон
RELAY_DAEMON_PATH=$(swift build --show-bin-path)/relay-daemon \
  $(swift build --show-bin-path)/Relay

Структура

Sources/
  RelayProtocol/     общие типы и формат IPC (GUI и демон)
  RelayDaemonCore/   PTY, реестр сессий, scrollback, статусы, порты, Docker
  relay-daemon/      исполняемый демон
  relay-cli/         команда relay: разбор аргументов, справка, вывод
  RelayUI/           тема и UI-компоненты
  RelayAppKit/       модель, представления, клиент демона, панель браузера
  CChromium/         C API Chromium (CEF): заголовки и тонкий слой над ними
  relay-browser-helper/ процесс, в котором Chromium запускает рендереры
  RelayApp/          точка входа (одна строка)
Tests/
  RelayProtocolTests/    формат сообщений и совместимость версий
  RelayDaemonCoreTests/  PTY, сквозные тесты демона, парсеры
  RelayCLITests/         разбор командной строки relay
  RelayAppKitTests/      конфигурация, SSH, сервисы, уведомления
docs/
  SPEC.md            техническое задание
  ARCHITECTURE.md    архитектурные решения

Тесты не используют моки там, где можно проверить реальное поведение: сквозные тесты поднимают настоящий демон на временном сокете и запускают настоящие процессы в настоящих PTY.


Если что-то не работает

Сборка падает на SwiftTerm — проверьте сеть и очистите кеш: rm -rf .build && swift build

«relay-daemon executable not found» — приложение запущено не из бандла. Соберите через ./Scripts/build-app.sh или задайте RELAY_DAEMON_PATH.

Сессия зависла на «Starting», терминал пустой — почти всегда macOS показывает диалог доступа к файлам, а он ждёт ответа за другим окном. Ответьте на него. Relay запускает сессии через ваш логин-шелл, и пока его стартовые файлы заблокированы, сессия не начнётся. Через 8 секунд приложение само покажет эту подсказку поверх терминала. Если диалога нет — проверьте ~/.zshrc на команду, которая не завершается.

Сессия не стартует — посмотрите daemon.log. Вторая по частоте причина: команда (claude, codex) не найдена в PATH. Проверьте, что она работает в обычном терминале.

Порты не находятся — Relay обходит дерево процессов проекта через ps и lsof. Если dev-сервер запущен вне Relay, его портов в списке не будет.

Docker-секция пишет «unavailable» — сообщение приходит от самого docker. Чаще всего движок просто не запущен.

Raycast или Spotlight не находят Relay — приложение должно лежать в /Applications. Запустите ./Scripts/install.sh. Если лаунчер всё ещё не видит его, перезапустите лаунчер: он кеширует список приложений.

Приложение не открывается, Gatekeeper ругается — релизы подписаны Developer ID и заверены Apple, так что это про сборку, сделанную самостоятельно: правый клик по Relay.app → Open → Open.

About

Native macOS workspace manager for developers: projects, terminal sessions, AI CLI agents, dev services, Docker and SSH in one dark, keyboard-driven window. Sessions run in a background daemon and survive quitting the app.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages