Подключение 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 показывает текущий. Новый инстанс добавляется под своим человекочитаемым облачным именем, а имена существующих собственных соединений сохраняются. Сохранённым соединениям всё так же нужна действующая аутентификация на шлюзе; вход настраивается там же, в элементах управления зарегистрированным соединением.

Добавление соединения по шагам

  1. Откройте Settings → Gateways и прокрутите до реестра соединений (или нажмите на значок разъёма в панели профилей).
  2. Нажмите Add connection.
  3. Выберите тип: Local, Hermes Cloud, Remote gateway или SSH. (Local недоступен для выбора, пока существует управляемая приложением локальная запись — а это почти всегда так; Hermes Cloud отправляет вас к описанному выше входу/обнаружению облака.)
  4. Заполните поля:
    • 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; вставлять токен не нужно.
    • Только для SSH:
      • SSH host — одно составное поле в форме user@host:22 (пользователь и порт необязательны). Используется ваш SSH-ключ; приложение само принимает токен дашборда через туннель. Удалённые проверки выполняются под login-shell аккаунта; на login-shell zsh сторож проверки не может убить всю группу процессов, так что внуки зависшей проверки могут остаться на удалённой машине (bash/sh их подбирают).
      • Hermes path (необязательно) — полный путь к исполняемому файлу hermes на удалённой машине (например, /opt/hermes/bin/hermes). Оставьте пустым для автоопределения. Задайте его, когда у неинтерактивной оболочки удалённой машины нет hermes в PATH и Test сообщает «Hermes is not installed on the remote host»; очистка поля возвращает автоопределение.
  5. Нажмите Save connection (или Cancel).
  6. Нажмите 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, в частности, safeStorage Electron хранит ключ приложения в системном 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; сообщение об ошибке называет конкретное нарушение.
перевод и редактура:

обновлено

⌕ ESC