Подключение Desktop к нескольким инстансам Hermes
Зарегистрируйте в одном десктопном приложении все свои бэкенды Hermes — локальный runtime, удалённые шлюзы в домашней сети или на VPS, SSH-хосты и инстансы Hermes Cloud — и работайте с агентами на всех них одновременно. Соединения постоянные: каждый зарегистрированный шлюз сам поднимает свои бэкенды и WebSocket-каналы по требованию, а фоновые агенты продолжают стримить, пока вы смотрите на другой шлюз.
Это десктопная часть темы, которую раскрывает страница Запуск нескольких шлюзов одновременно: там речь о том, как разместить несколько шлюзов на одной машине; здесь — о том, как одно десктопное приложение работает с несколькими машинами.
Где это найти
Всё собрано на единой странице Settings → Gateways (в старых сборках были отдельные страницы Gateway и Connections; старые прямые ссылки на Connections теперь ведут туда же). К странице ведут три пути:
- Settings → Gateways — сама страница (Cmd/Ctrl+,, затем Gateways в навигации настроек). Реестр соединений — это раздел этой страницы, расположенный ниже элементов управления режимом подключения уровня машины.
- Панель профилей в сайдбаре — кнопка-разъём в правом конце панели (подсказка: «Connect another Hermes gateway…») ведёт прямо на страницу Gateways. Она видна всегда, даже до того, как вы создали второй профиль или второе соединение.
- Командная палитра — Cmd/Ctrl+K, затем введите Gateways (также подходят connections, add gateway, remote, ssh, instances).
Реестр шлюзов
Раздел Registered gateways на странице Settings → Gateways управляет именованным списком шлюзов Hermes. Его вступление говорит прямо: «Manage this device and every Hermes gateway it can reach through remote, SSH, or Cloud connections». Каждая запись — это соединение:
| Тип | Что это | Аутентификация |
|---|---|---|
| Local | «The Hermes runtime managed by this app» (runtime Hermes, которым управляет само приложение) | автоматически |
| Remote gateway | «A Hermes gateway reachable over HTTP(S) — LAN, Tailscale, or the internet» (шлюз Hermes, доступный по HTTP(S) — локальная сеть, Tailscale или интернет) | токен сессии или OAuth |
| SSH | «A Hermes install reached over SSH» (установка Hermes, доступная по SSH). Приложение само открывает туннель и запускает дашборд | SSH-ключ + принятый токен |
| Hermes Cloud | «A hosted instance discovered through your Hermes Cloud account» (облачный инстанс, обнаруженный через ваш аккаунт Hermes Cloud) | вход через портал |
Что важно знать:
- У каждого соединения должно быть уникальное имя устройства («Homelab», «Work laptop»). Это имя появляется везде, где фигурирует инстанс — в бейджах ростера, хендлах, результатах обновления. Уникальность не зависит от регистра, поэтому
Homelabиhomelabсосуществовать не могут. - Записью local управляет само приложение (у неё значок App-managed), и удалить её нельзя. Удаление любого другого соединения останавливает его живые бэкенды и туннели; сам инстанс при этом не трогается.
- Одно соединение всегда помечено как Primary (значок в его строке): это резервный вариант реестра для мультишлюзовых вызовов, в которых шлюз явно не указан. Кнопка Make primary не переключает текущее рабочее пространство Sessions; при удалении primary-соединения система откатывается на локальную запись.
- Опция At startup, return to Sessions on the last-used gateway определяет, на каком шлюзе откроется Sessions после полного перезапуска приложения. По умолчанию она выключена, поэтому Sessions открывается на Primary. Включите её, чтобы возвращаться на последний шлюз, к которому удалось успешно подключиться. Неудачное переключение никогда не запоминается, а удалённый или недоступный сохранённый шлюз откатывается на Primary.
- Кнопка Test проверяет и HTTP-, и WebSocket-часть соединения, так что успех (тост «Reachable») означает, что чат действительно заработает — а не просто то, что хост откликнулся на пинг.
- Дубликаты отклоняются при сохранении: запись local всегда только одна; записи remote и cloud дедуплицируются по нормализованному URL (обрезанные пробелы, убранные завершающие слэши, приведение к нижнему регистру — причём между обоими типами тоже, так что cloud- и remote-запись не могут указывать на один и тот же URL); записи SSH дедуплицируются по нормализованной паре
user@host:portплюс удалённый профиль. - Cloud-записи обычно появляются через вход/обнаружение Hermes Cloud в верхней части страницы Gateways — тип Hermes Cloud в редакторе добавления соединения как раз направляет туда.
Переключайте шлюзы из сайдбара Sessions. Профили, чаты, сообщения и cron остаются привязаны к этому шлюзу; бэкенд окна, которым управляет само приложение, по-прежнему выбирается элементами управления режимом подключения выше. Primary — это резервный вариант для реестра и не переключает текущее рабочее пространство.
Как упорядочить группы сессий
В меню вида на боковой панели Sessions выберите Gateway & profile, просматривая все
профили. Каждый шлюз получит свою сворачиваемую секцию, а внутри — подсекции профилей с их
сессиями. Два шлюза с профилем default остаются раздельными. Заголовок шлюза начинается с
сохранённого имени соединения, заголовок профиля показывает имя профиля.
В меню секции шлюза или профиля есть Rename group, Reset name, Move up и Move down. Переименование меняет только подпись в боковой панели, но не сам шлюз или профиль. Шлюзы переставляются целыми секциями, а профили — внутри своего шлюза. Переставить секцию можно перетаскиванием её заголовка за любое место (иконку, имя или пустое пространство) либо с клавиатуры: фокус на заголовке, затем Space, стрелки и снова Space. Имена, порядок и свёрнутые секции запоминаются на этом десктопе. Свёртывание шлюза сохраняет состояние свёртки у его профилей по отдельности. Кнопка «новая сессия» у каждого профиля создаёт её именно для этого профиля на его собственном шлюзе.
Панель Hermes Cloud вдобавок перечисляет Saved Cloud gateways, когда вы вышли из портала и обнаружение не работает. Кнопка Use gateway выбирает существующее сохранённое соединение, не меняя шлюз по умолчанию; Active in this window показывает текущий. Новый инстанс добавляется под своим человекочитаемым облачным именем, а имена существующих собственных соединений сохраняются. Сохранённым соединениям всё так же нужна действующая аутентификация на шлюзе; вход настраивается там же, в элементах управления зарегистрированным соединением.
Добавление соединения по шагам
- Откройте Settings → Gateways и прокрутите до реестра соединений (или нажмите на значок разъёма в панели профилей).
- Нажмите Add connection.
- Выберите тип: Local, Hermes Cloud, Remote gateway или SSH. (Local недоступен для выбора, пока существует управляемая приложением локальная запись — а это почти всегда так; Hermes Cloud отправляет вас к описанному выше входу/обнаружению облака.)
- Заполните поля:
- Name — обязательное, уникальное; «имя устройства», которое показывается везде, где появляется этот инстанс (плейсхолдер:
Homelab). Максимум 64 символа. - Только для Remote gateway:
- Gateway URL — базовый URL работающего бэкенда
hermes serve, напримерhttp://homelab.lan:9119. Префиксы пути от reverse-прокси поддерживаются. - Authentication — выберите Session token или OAuth:
- Session token — вставьте токен сессии дашборда с удалённого шлюза. При редактировании: «Leave blank to keep the saved token» (оставьте поле пустым, чтобы сохранить прежний токен).
- OAuth — войдите через браузерный флоу Nous Portal; вставлять токен не нужно.
- Gateway URL — базовый URL работающего бэкенда
- Только для SSH:
- SSH host — одно составное поле в форме
user@host:22(пользователь и порт необязательны). Используется ваш SSH-ключ; приложение само принимает токен дашборда через туннель. Удалённые проверки выполняются под login-shell аккаунта; на login-shellzshсторож проверки не может убить всю группу процессов, так что внуки зависшей проверки могут остаться на удалённой машине (bash/sh их подбирают). - Hermes path (необязательно) — полный путь к исполняемому файлу
hermesна удалённой машине (например,/opt/hermes/bin/hermes). Оставьте пустым для автоопределения. Задайте его, когда у неинтерактивной оболочки удалённой машины нетhermesвPATHи Test сообщает «Hermes is not installed on the remote host»; очистка поля возвращает автоопределение.
- SSH host — одно составное поле в форме
- Name — обязательное, уникальное; «имя устройства», которое показывается везде, где появляется этот инстанс (плейсхолдер:
- Нажмите Save connection (или Cancel).
- Нажмите Test на новой строке и дождитесь статуса «Reachable».
Любую запись, кроме local, можно позже отредактировать кнопкой-карандашом или удалить кнопкой-корзиной — удаление запрашивает подтверждение и напоминает, что «The instance itself is not touched — you can add it again any time» (сам инстанс не затрагивается — его можно добавить снова в любой момент).
hermes serve
Ничего не заработает, если бэкенд на другой машине реально не запущен и не доступен. Десктопное приложение подключается к нему, но не запускает его само (кроме SSH-соединений, где приложение по требованию запускает дашборд через туннель). Настройка бэкенда — провайдеры аутентификации, привязка к адресу, отличному от loopback, и рекомендации по Tailscale — описана на странице Подключение к удалённому бэкенду.
Миграция с настроек единственного соединения
При первом запуске сборки с поддержкой реестра ваши текущие настройки импортируются автоматически: глобальный режим подключения и любые устаревшие переопределения на уровне профиля из Settings → Gateway становятся именованными записями реестра (с дедупликацией по URL/хосту). (В более новых сборках страница настроек Gateways больше не предлагает переопределения на уровне профиля — соединения со шлюзами теперь на уровне машины, а профили обнаруживаются исходя из того, к каким шлюзам вы подключены.)
Файл старых настроек остаётся нетронутым, поэтому более ранние сборки на той же машине продолжают работать. Если перенесённое имя совпало с уже существующим, к нему добавлялся суффикс (Homelab 2).
Агенты на разных шлюзах
Каждый профиль на каждом зарегистрированном соединении — это отдельный агент. Именно объединённый ростер отображают мультишлюзовые поверхности (и встроенный ростер режима бота):
- Когда одно и то же имя профиля существует на нескольких шлюзах, хендлы разграничиваются как
@name-device— профильresearchна вашем Homelab отображается как@research-homelab, а профиль, уникальный среди всех шлюзов, сохраняет своё простое имя. - Перечисление агентов происходит сразу, а сокеты подключаются лениво: приложение получает список агентов по REST, не открывая WebSocket-соединение с каждым шлюзом. Недоступный шлюз просто помечается ошибкой в своей строке, не ломая весь ростер; SSH-соединения остаются в режиме connect-on-demand, пока вы не откроете агента на них впервые (никаких неожиданных туннелей).
- Открытие агента подключается к его собственному шлюзу — чаты, сессии и память живут на той машине, которой принадлежит профиль, точно так же, как если бы вы работали с этим инстансом напрямую.
Каждая пара (соединение, профиль) получает собственный бэкенд и сокет, с тем же пулингом и вытеснением простаивающих соединений, что и у локальных бэкендов на профиль — фоновые агенты продолжают стримить, пока вы смотрите на другой шлюз.
Кнопки подтверждения уходят обратно на тот бэкенд, которому принадлежит сессия, а не на выбранный сейчас профиль. Для локального вторичного профиля десктоп может воспользоваться тем сокетом, который доставил запрос, даже когда закэшированная привязка сессии потерялась. Сохранённое владение сессией всё равно в приоритете, а удаление или переименование такого локального профиля этот временный маршрут снимает, а не переподключает устаревший бэкенд.
Переключение и область видимости
Низ сайдбара следует одной иерархии: шлюз → профиль → сессии. Шлюзы — это машины или хостинговые бэкенды; профили — изолированные агенты Hermes, живущие на одном шлюзе.
- При одном зарегистрированном шлюзе элемент выбора шлюза не добавляется. Desktop только с локальным подключением сохраняет ту же панель профилей и те же клавиатурные сценарии, что и раньше.
- При нескольких шлюзах в сайдбаре появляется один именованный селектор шлюза. Его значок — устройство, облако, сеть или терминал — показывает тип соединения; аватары профилей остаются отдельным элементом управления после разделителя. Один и тот же селектор одинаково работает и для двух шлюзов, и для крупного парка машин, не превращая бэкенды в подобие профильных иконок и не вытесняя действия с профилями из панели.
- Выбор шлюза восстанавливает последний использованный на нём профиль. Кнопка «домой» возвращается к профилю по умолчанию, а кнопка слоёв показывает All profiles on this gateway. Комбинации Cmd/Ctrl+1–9 по-прежнему переключают профили внутри активного шлюза, когда ни у одной панели нет полосы вкладок, которая забрала бы их себе.
- При нескольких шлюзах панель профилей превращается в ленту парка (fleet rail): профили всех зарегистрированных шлюзов лежат на одной полосе, а каждую группу открывает значок типа своего шлюза (устройство, сеть, терминал, облако) — тот же, что использует селектор шлюзов. Квадраты активного шлюза выглядят точно так же, как на Desktop с одним шлюзом; квадраты остальных шлюзов притушены («в покое»). Наведение на притушенный квадрат показывает имя его машины (
omer · This device), так что два одноимённых профиля на разных машинах никогда не выглядят одинаково. - Клик по притушенному квадрату выполняет то же переключение, что и селектор шлюзов, — попадание точно в пару
(шлюз, профиль): пока цель дозванивается, квадрат крутится, предыдущий шлюз остаётся отрисованным до ответа цели, а недоступная цель просто проваливает клик с сообщением об ошибке вместо того, чтобы оставить окно в наполовину переключённом состоянии. Группы сохраняют порядок реестра независимо от того, какой шлюз активен, так что квадрат никогда не сдвигается из-под курсора, которым по нему кликнули. Правый клик по притушенному квадрату открывает Switch to, Color, Rename, Edit SOUL.md и Delete — все действия выполняются на собственном шлюзе этого квадрата; подтверждение удаления называет машину. - Шлюз, до которого не дозвонился последний опрос, сохраняет свои квадраты — на его значке просто появляется янтарная точка: спящая машина всё равно ваша. Две регистрации одного и того же бэкенда схлопываются в одну группу. Когда квадратов по всему парку становится больше тринадцати, лента сворачивается в одно меню с разделами по шлюзам.
- Выбранный шлюз сохраняется после закрытия и перезапуска приложения только если включена опция Settings → Gateways → At startup, return to Sessions on the last-used gateway. Настройка и идентификатор шлюза хранятся в пользовательском реестре данных приложения, так что замена или обновление бандла приложения их не сбрасывает.
- Если на активном шлюзе больше тринадцати профилей, их лента аватаров сворачивается в именованный селектор профилей. Так большие наборы шлюзов и профилей уживаются вместе, не меняя саму модель шлюз → профиль → сессии.
- Этот компьютер остаётся полноценным шлюзом, даже когда primary — удалённое соединение. Он может держать локальные сессии доступными во время сбоя на удалённой стороне, но приложение не называет это «офлайн-режимом»: выбранная модель или инструменты всё равно могут требовать доступа в интернет.
- Список сессий, каналы сообщений, задачи cron, настройки, файлы и память — всё привязано к активной паре
(шлюз, профиль). Переключение с Telegram-шлюза на Signal-шлюз не может оставить в сайдбаре группы каналов или сессии предыдущего шлюза. - Десктоп загружает локальный реестр соединений при запуске, даже когда строка состояния скрыта, и держит его актуальным, когда шлюзы сохраняют или удаляют. Открывать настройки для этого не нужно. В простом режиме лента профилей остаётся доступной, если зарегистрировано больше одного шлюза, даже когда у каждого есть только профиль по умолчанию. Загрузка реестра не подключает все шлюзы разом; периодического опроса всего парка нет.
- Наведение на агента заранее прогревает его бэкенд, чтобы переключение не упиралось в холодный старт. Исключение — SSH-агенты: наведение никогда не поднимает туннель и не запускает удалённый бэкенд, это делает только открытие.
- У страницы Capabilities (Skills / Tools / MCP) та же логика области видимости: её селектор Configuring перечисляет каждого агента
(профиль, устройство)из объединённого ростера, и выбор одного из них читает и пишет навыки, наборы инструментов и MCP-серверы именно этой машины, не переключая рабочее пространство Sessions. Установки из хаба, ключи окружения и настройка MCP — всё это применяется к бэкенду выбранного агента. Кнопка горячей перезагрузки в активную сессию на вкладке MCP появляется только для агентов на том шлюзе, к которому подключено текущее окно; изменения на других машинах применяются при их следующей сессии.
Добавляйте, тестируйте, переименовывайте или удаляйте шлюзы на странице Settings → Gateways. Кнопка разъёма рядом с действиями профиля — это лишь ярлык к тому же единому центру управления, а не отдельный способ добавления.
Sessions и режим бота
Sessions намеренно показывает один активный шлюз за раз: так файлы, инструменты, каналы, cron и история сессий остаются в одном понятном контексте выполнения. Лента парка расширяет только средство выбора — после каждого клика рабочее пространство всё равно остаётся ровно на одной паре (шлюз, профиль). У режима бота другая задача, поэтому он может показывать объединённый ростер, сгруппированный по шлюзам — так пользователь может открыть одного агента на NAS, а другого на VPS с одной и той же поверхности. Открытие бота всё равно активирует его точный маршрут (шлюз, профиль).
Прямые упоминания бота и делегирование по умолчанию остаются локальными для шлюза. Пересечение границы бэкенда меняет файловую систему, учётные данные, инструменты и контекст доверия, поэтому кросс-шлюзовое выполнение должно быть явным мостом, а не случайным побочным эффектом того, что всё это делится одним окном Desktop.
Обновление всех инстансов сразу
Опция Settings → Gateways → Update all instances (появляется, как только зарегистрировано больше одного соединения) параллельно рассылает команду hermes update на все подходящие соединения:
- Local обновляется через собственный конвейер обновлений приложения (тот же путь, что и Settings → Updates).
- Remote и SSH соединениям приходит команда обновиться самим через свой бэкенд — обновление выполняется прямо на той машине.
- Инстансы Hermes Cloud пропускаются с пометкой «Managed by Hermes Cloud»: их версиями управляет сама платформа.
Каждый инстанс отчитывается независимо, поэтому один недоступный узел никогда не блокирует весь пакет. Бэкенды, обновления которых управляются извне (Docker, Nix), вежливо отказываются со своим собственным сообщением — построчно.
Впрочем, кнопка в настройках нужна редко: как только целей обновления становится больше одной, обычные пути обновления в приложении (Update now на панели About, ⌘K Update Hermes, всплывающее уведомление о готовом обновлении) сами запускают ту же веерную рассылку — сперва активный бэкенд, затем все остальные подходящие шлюзы и в самом конце десктопное приложение. См. Обновление в гайде по десктопу.
Заметки по безопасности
- Где хранятся токены. Токены сессий удалённых шлюзов (и токены OAuth для нативного входа, привязанные к базовому URL шлюза) хранятся в пользовательском каталоге данных приложения в виде файлов с правами доступа только для владельца (0600), внутри основного процесса Electron; рендерер и плагины никогда не видят байты токена.
- Опциональное шифрование через связку ключей. По умолчанию токены не проходят через связку ключей ОС — на macOS, в частности,
safeStorageElectron хранит ключ приложения в системном keychain для входа, а заблокированная или повреждённая связка ключей превращается в запрос пароля при каждом запуске. Если нужно шифрование при хранении поверх прав доступа к файлам, включите Settings → Gateway → «Encrypt saved secrets with the OS keychain»; уже сохранённые секреты будут перешифрованы на месте (Keychain на macOS, DPAPI на Windows, бэкенд сессионного keyring на Linux). Выключение опции обратно расшифровывает их. - Файл реестра (
connections.jsonв пользовательском каталоге данных приложения) хранит метки, URL и хосты — секреты появляются в нём только внутри зашифрованных конвертов. - Метод
host.connections()из SDK для плагинов намеренно возвращает только метки, типы и идентификатор primary-соединения — но никогда не сами токены.
Для авторов плагинов
SDK для плагинов в Desktop напрямую открывает доступ к мультишлюзовой поверхности:
host.connections()— список зарегистрированных соединений (метки, типы, primary; байты токенов никогда не возвращаются).host.agents()— объединённый ростер: по одной строке на пару(шлюз, профиль), с уже готовым хендлом@name-device.host.ensureAgent(connectionId, profile)— активировать шлюз агента, чтобы последующие вызовыhost.requestшли к его бэкенду.host.warmAgent(connectionId, profile)— предварительный прогрев сокета без ожидания ответа (по наведению курсора).
Все четыре метода определяются по факту наличия: в более старой сборке Desktop их просто нет, и плагину следует переключиться на одношлюзовый флоу profiles.list. Мультишлюзовый ростер режима бота — эталонный пример такого использования.
Диагностика проблем
- «Connection test failed» — бэкенд недоступен по этому URL с этой машины. Проверьте, что
hermes serveзапущен на удалённом хосте, порт открыт и (для токен-аутентификации) токен актуален. После исправления заново нажмите Test. - Агент отображается, но не открывается — запустите Test на его соединении. Если WebSocket-часть падает, а HTTP проходит, обычно дело в прокси, файрволе или защите auth/origin на шлюзе, блокирующей
/api/ws. - Удалённый шлюз отсутствует в ростере — его бэкенд не работает или недоступен; ростер показывает его среди шлюзов с ошибкой. SSH-соединения показывают статус connect-on-demand до первого использования — это ожидаемое поведение, а не сбой.
- «Update Hermes Desktop to chat with agents on other connections» — приложение старше мультишлюзового стека; обновите само десктопное приложение.
- Дублирующиеся имена устройств — невозможны; уникальность имён проверяется при сохранении. Если перенесённое имя совпало с существующим, к нему добавлялся суффикс (
Homelab 2). - «Could not save the connection» — чаще всего это отсутствующее Name, уже занятое имя или некорректный Gateway URL / SSH host; сообщение об ошибке называет конкретное нарушение.