Сделал для себя ssh‑commander: терминал, файловый менеджер, управление Docker и AI‑агент в одном окне. Можно работать с сервером руками, а когда нужна помощь, передать вывод агенту или поставить ему задачу. Он сам смотрит файлы и логи, предлагает команды, а изменения выполняет после подтверждения.
Приложение запускается локально через Docker, интерфейс открывается в браузере. К серверам подключается по SSH. Код открыт под MIT, подписки нет. Для агента нужен свой API‑ключ; без него ручные инструменты тоже работают.

Зачем я это сделал
Несколько моих веб‑проектов нужно было перевезти на новый сервер. Чтобы ничего не забыть, я запустил AI‑агента на старом сервере и попросил изучить конфигурацию и собрать документ для переноса. Где лежат проекты, как запускаются сервисы, какие конфиги нужно забрать.
Потом подумал: если агент может все это изучить, почему бы не поручить ему и настройку? При этом хотелось видеть, что он собирается делать, и иметь возможность проверить результат самому.
Так появился ssh‑commander. Слева выбираешь сервер, сверху переключаешься между терминалом, файлами и другими разделами. Справа остается чат с агентом. Можно открыть лог, отправить нужный фрагмент в чат и продолжить разбираться в том же окне.
Запускать агента прямо на сервере тоже можно, с этого я и начал. Мне оказалось удобнее собрать подключения и ручные инструменты в одной панели.
Что есть в приложении
Терминал. Несколько вкладок на сервер, история команд, восстановление сессии после перезагрузки страницы. Выделение или последний вывод можно отправить агенту одним кликом.
Файлы по SFTP. Загрузка и скачивание, редактор с подсветкой, поиск, просмотр растущих логов. Есть анализатор занятого места: можно пройти от большого каталога до конкретных файлов.
Docker. Контейнеры, образы, логи, запуск и остановка, Compose, терминал внутри контейнера.
Еще есть разделы для PostgreSQL и MySQL, Nginx, systemd, портов и cron. Полный перечень возможностей есть в README.

У агента есть память для каждого сервера: локальный файл MEMORY.md, который подгружается в начале следующей сессии. Туда можно записать, где лежат проекты и как они запускаются. Запись требует подтверждения. В один диалог можно подключить несколько серверов; у каждой команды видно, на какой машине она выполняется.
Пример из использования: PDF, свободное место и сломанный бэкап
Когда приложение уже работало, на одном из серверов закончилось место. Агент нашел дубли больших PDF и предложил освободить почти 1,5 ГБ. Заодно предложил перевести работу с PDF на Yandex S3.
Мы убрали дубли, потом настроили работу с S3 и перенесли туда документы. Когда понадобилось удалить с диска PDF, которые уже были перенесены, выяснилось, что нет актуального бэкапа всех медиафайлов в S3. Хотя резервное копирование было настроено раньше.
Агент быстро выяснил причину. Синхронизация сломалась, когда мы удалили дубли PDF: процесс бэкапа попытался удалить соответствующие файлы в S3, но у сервисного аккаунта не хватало прав на удаление. Операция падала, и бэкап перестал обновляться.
То есть перед очисткой оставшихся локальных файлов нашлась проблема с резервным копированием. Агент связал ее с нашим предыдущим действием и нашел недостающие права.
Что агент делает сам, а что нужно подтверждать
Агент может сам прочитать обычный файл, посмотреть логи, список контейнеров или свободное место. Для записи файла, перезапуска контейнера и произвольной shell‑команды нужно подтверждение. Внизу чата появляется плашка: можно раскрыть команду целиком, затем подтвердить или отклонить ее.

Для команд чтения есть отдельный инструмент exec_readonly с разрешающим списком. Изначально я использовал запрещающий список, но при проверке обнаружились обходы: например, /bin/rm и \rm не совпадали с проверяемым именем. Поэтому теперь автоматически проходит только ограниченный набор команд. У них отдельно проверяются флаги, а конвейеры, перенаправления и подстановки запрещены.
Команда | Пройдет без подтверждения |
|---|---|
| Да |
| Да |
| Нет: удаление файлов |
| Нет: запись в файл |
Интерпретаторов и сетевых клиентов в этом списке нет. Сложную команду агент может предложить через обычный exec, с подтверждением. Иногда так приходится подтверждать и безобидный запрос. Для своего инструмента я считаю этот компромисс приемлемым. Вот фильтр и его тесты.
Для больших задач есть режим планирования. Модель составляет план по уже собранным сведениям, без вызова инструментов. Если нужна свежая информация, ее нужно получить до перехода в этот режим. Одобрение плана запускает работу, но не отменяет подтверждения отдельных изменений.
Ограничения
Агент может предложить неправильную команду. Перед подтверждением ее нужно прочитать, а после выполнения проверить результат. Бэкапы по‑прежнему нужны.
При работе с внешним AI‑провайдером прочитанные файлы и логи передаются ему. Чтение путей, похожих на файлы секретов, например .env или приватных ключей, требует подтверждения. В выводе инструментов скрываются распознанные секреты. Это проверки по шаблонам: они могут что‑то пропустить и не обезличивают логи.
Prompt injection тоже остается проблемой: в файле или логе может оказаться текст с посторонними инструкциями для модели. Проверки команд и подтверждения при этом сохраняются, но гарантировать правильность предложений агента они не могут.
Панель рассчитана на одного пользователя, по умолчанию доступна только на 127.0.0.1 и защищена паролем. SSH‑пароли, пароли БД и API‑ключ хранятся локально открытым текстом; пароль панели хранится как хеш. Каталоги data/ и keys/ вместе с резервными копиями нужно защищать от чужого доступа.
Как попробовать
Нужны Docker с Compose v2 на вашем компьютере и SSH‑доступ к Linux‑серверу. В Linux или macOS готовый образ версии 0.1.1 запускается так:
mkdir ssh-commander cd ssh-commander curl --fail --location https://raw.githubusercontent.com/lexuss1979/ssh-commander/v0.1.1/docker-compose.release.yml --output compose.yaml docker compose up -d
Откройте http://localhost:8080, задайте пароль панели и добавьте сервер. В поле адреса укажите IP или hostname VPS. localhost здесь будет адресом самого контейнера.
Для агента добавьте API‑ключ в настройках. Есть пресеты провайдеров и настройка собственного OpenAI‑совместимого API с поддержкой вызова инструментов. Расходы идут по тарифу провайдера, в приложении есть учет токенов и оценка стоимости по диалогам. На скриншотах используется deepseek-v4-flash. И сам я использую именно эту модель — это очень быстро и недорого.
Установка, в том числе на Windows и первое подключение описаны отдельно. Если хочется посмотреть код: TypeScript, Node.js и ssh2 на бэкенде, React и xterm.js во фронтенде. Есть описание архитектуры.
Репозиторий: lexuss1979/ssh‑commander. Если попробуете, напишите, что получилось и чего не хватило. Ошибки и предложения можно оставлять в issues.

