terminal-mac: полноценный macOS для ИИ-агентов в терминале
📂 Исходный код на GitHubОтдельный рабочий стол macOS для computer-use агентов: виртуальная машина на Apple Virtualization, просмотр и управление из терминала.
terminal-mac — утилита для Mac на Apple Silicon, которая запускает настоящую виртуальную машину с macOS и показывает её экран прямо в окне терминала. ИИ-агент получает внутри этой машины управление компьютером (computer use): он видит экран, двигает курсор, набирает текст и нажимает клавиши. При этом ваш основной рабочий стол, буфер обмена и курсор физического Mac остаются нетронутыми. Проект написан на Swift, распространяется по лицензии MIT и сейчас находится на стадии раннего релиз-кандидата.
Зачем нужен отдельный виртуальный Mac
Современные агенты вроде Claude Code, Cursor или Codex уверенно работают с кодом через файлы и API. Но многие задачи требуют полноценного графического интерфейса: установить и настроить приложение, пройтись по системным настройкам, поработать в браузере. Давать агенту управление своим основным Mac рискованно — он получит доступ к вашим файлам, сессиям и учётным записям.
terminal-mac решает эту проблему: агент работает внутри отдельного виртуального Mac, у которого собственные приложения, файлы, учётные записи и разрешения. Гость не наследует ни запущенные приложения хоста, ни ваши залогиненные сессии. Единственная цена — ВМ потребляет CPU, память и диск основного Mac.
Как это устроено
Архитектура состоит из трёх частей:
- Гость. Apple Virtualization запускает настоящий macOS. Внутри гостя работает вспомогательное приложение
TerminalMacGuest.app: оно захватывает экран через ScreenCaptureKit и отправляет события ввода. - Просмотрщик в терминале. Экран гостя транслируется в терминал через графические протоколы Kitty, Ghostty или iTerm2. Кадры отправляются только при изменении экрана, до 30 кадров в секунду, со сжатием lz4 без потерь. Kitty и Ghostty получают кадры через разделяемую память, а не через pty. Простой рабочий стол не передаёт ничего, поток останавливается через 15 секунд после закрытия просмотрщика.
- Управление. Команды агента идут через тот же гостевой хелпер, поэтому физический курсор и буфер обмена хоста не затрагиваются.
Новые ВМ по умолчанию используют дисплей 2x HiDPI: для стандартных 1280×800 точек это 2560×1600 пикселей, поэтому текст остаётся чётким на Retina-терминалах. Переключить режим можно командой terminal-mac display default --hidpi или --standard на остановленной ВМ.
Требования и установка
Что понадобится:
- Mac на Apple Silicon с macOS 14 или новее;
- интернет при первом запуске — образ macOS скачивается прямо с серверов Apple (или готовый локальный файл
.ipsw); - место под кэш образа и растущий диск ВМ (по умолчанию 64 ГиБ логического объёма);
- терминал Ghostty, Kitty или iTerm2 для встроенного просмотрщика; остальные терминалы получают нативное окно ВМ и CLI.
Для готового релиза инструменты разработчика не нужны. Установка одной командой:
curl -fsSL https://github.com/govijr/terminal-mac/releases/latest/download/get.sh | bash
Установщик скачивает последний релиз, проверяет его SHA-256 и кладёт лаунчер в ~/.local/bin, а рантайм — в ~/.local/lib/terminal-mac. Права администратора не нужны, конфигурацию шелла он не меняет.
Первый запуск terminal-mac up ведёт вас по шагам: скачивает и кэширует подходящий образ восстановления Apple, устанавливает виртуальный Mac, загружает его и проверяет гостевой хелпер. Последующие запуски переиспользуют существующую ВМ и просто подключаются к ней.
Есть и другие варианты запуска:
terminal-mac up work # another virtual Mac
terminal-mac up --ipsw /path/mac.ipsw # use a local image
terminal-mac up --no-view # wait for agent readiness, then return JSON
terminal-mac up --detach # install/boot, return without waiting for guest setup
terminal-mac up --plan # show steps without network access or disk changes
Первая загрузка образа может занять время — скачать и установить macOS за один момент не выйдет. Кэш образа переиспользуется, а недокачанная загрузка возобновляется после сбоя сети.
Настройка гостя (один раз)
Первый запуск открывает окно виртуального Mac. Дальше по шагам:
- Пройдите Setup Assistant macOS и создайте учётную запись гостя.
- Внутри гостя откройте Finder →
/Volumes/My Shared Files/tools→TerminalMacGuest.app. Хелпер установит себя в~/Applicationsгостя и зарегистрируется на будущие входы в систему. - Кнопками хелпера выдайте в госте два разрешения: Screen Recording и Accessibility. Основному Mac они не нужны.
- Держите гостя залогиненным и хелпер запущенным.
После этого CLI автоматически перейдёт к терминальному рабочему столу. Это управляемая настройка, а не безлюдная установка: более новый автоматический механизм из macOS 27 этот сборка пока не использует.
Подключение ИИ-агента
terminal-mac даёт агентам computer use через два интерфейса: MCP-инструменты (screenshot, click, drag, scroll, type, key, status) и skill, который обучает агента циклу observe → act → verify: посмотреть на экран, сделать действие, проверить результат.
Claude Code — всё сразу одним плагином:
/plugin install terminal-mac --marketplace govijr/terminal-mac
Или по отдельности:
claude mcp add terminal-mac -- terminal-mac mcp
terminal-mac skills install # → ~/.claude/skills/terminal-mac/SKILL.md
Другие MCP-клиенты (Cursor, VS Code, Codex, Windsurf…): вставьте вывод команды terminal-mac mcp --config в настройки MCP своего клиента. terminal-mac mcp NAME подключает ВМ с именем, отличным от default.
Любой агент с папкой skills: terminal-mac skills install --dir PATH или npx skills add govijr/terminal-mac --skill terminal-mac. В AGENTS.md достаточно строки вида «Before using the virtual Mac, run terminal-mac skills get» — агент получит инструкции, соответствующие установленной версии.
Инструменты управляют только гостевым хелпером и никогда не трогают ваш рабочий стол. Если гость стоит на экране входа, инструменты об этом сообщают — и агент попросит вас войти в систему.
Управление агентом из CLI
Помимо MCP, гостем можно управлять прямо из командной строки:
./dist/terminal-mac action default screenshot --output /tmp/guest.png
./dist/terminal-mac action default click 640 400
./dist/terminal-mac action default type 'Hello from the agent'
./dist/terminal-mac action default key cmd+space
./dist/terminal-mac action default key return
./dist/terminal-mac action default scroll --dy -300 --x 640 --y 400
Команды возвращают JSON, а при ошибке — ненулевой код выхода. Скриншоты сохраняются в PNG на хосте. Координаты отсчитываются от левого верхнего угла и соответствуют размерам скриншота, поэтому агенту легко сопоставить картинку с точкой клика даже на Retina. Команда snapshot пока что просто псевдоним screenshot, а не снимок accessibility-дерева.
Просмотрщик поддерживает набор текста, одиночные, двойные и тройные клики, перетаскивание, прокрутку и стандартные клавиши. Ctrl+G открывает палитру мак-шорткатов (Spotlight, Mission Control, копирование и вставка) — терминалы держат ⌘ для себя. Ctrl+] выходит из просмотрщика, не останавливая ВМ.
Готовые инструкции для агентов лежат в docs/AGENT.md. Глобальные настройки агентов проект не меняет.
Жизненный цикл и ресурсы
./dist/terminal-mac ls
./dist/terminal-mac status default
./dist/terminal-mac pause default
./dist/terminal-mac resume default
./dist/terminal-mac show default
./dist/terminal-mac stop default # request a normal guest shutdown
./dist/terminal-mac stop default --force # immediate power-off; unsaved guest work can be lost
Новую ВМ можно настроить флагами: --cpus 4 --memory 4 --disk 64 --width 1280 --height 800. Флаг --offline убирает у гостя сетевое устройство — канал управления через общую папку продолжает работать.
Данные ВМ живут в ~/Library/Application Support/terminal-mac/machines/NAME/. Переменная TERMINAL_MAC_HOME меняет корень данных. У каждой ВМ есть эксклюзивная файловая блокировка, динамически растущий диск, аппаратная идентичность, файл machine.json, приватный почтовый ящик управления и журнал runtime.log. Загрузка ВМ идёт отдельным фоновым процессом, поэтому команды жизненного цикла должны использовать тот же TERMINAL_MAC_HOME, что и запустивший её процесс.
Прерванная установка оставляет каталог с меткой installed: false и никогда не перезаписывается молча. Деструктивной команды удаления ВМ пока намеренно нет.
Модель изоляции
Безопасность здесь продумана на уровне транспорта:
- Действия агента не используют API ввода и экрана хоста. Хелпер отказывается работать, если модель устройства (
hw.model) не начинается сVirtualMac. Это защита от случайного запуска на основном Mac, а не аппаратная гарантия. - Гость видит ровно два общих ресурса:
control(чтение и запись: JSON-запросы, ответы, скриншоты) иtools(приложение-хелпер, только чтение). Домашняя папка хоста, проекты, буфер обмена, микрофон и камера не подключены. - Сетевого слушателя удалённого управления нет. «Почтовый ящик» на общей папке проверяет пути (отвергает симлинки, жёсткие ссылки и нестандартные файлы), ограничивает размер сообщений, сверяет идентификаторы запросов и снимает просроченные действия. Хост никогда не исполняет контент, присланный гостем.
- Сеть по умолчанию работает через NAT: у гостя есть интернет, и он может достучаться до сервисов хоста и локальной сети. Это не среда, изолированная по сети, и не песочница для враждебного кода. Флаг
--offlineубирает этот канал. - Разрешения TCC выдаются вручную внутри гостя. Разлогиненный или заблокированный гость, отсутствие хелпера или отказ в разрешениях блокируют управление.
В планах у автора: клонирование ВМ, контрольные точки для отката, accessibility-снимки, полностью безлюдная установка гостя, сплиты терминала и транспорт через tmux.
Сборка из исходников и проверки
bash scripts/build.sh
./dist/terminal-mac doctor
Сборка создаёт dist/TerminalMac.app вместе с гостевым приложением и лаунчером dist/terminal-mac. Виртуализации нужен entitlement com.apple.security.virtualization, поэтому используйте собранный лаунчер, а не сырой бинарник Swift. Стабильная самоподписанная личность подписи («Govijr Code Signing») сохраняет разрешения хелпера между пересборками; ad-hoc подпись требует выдавать их заново. Детали подписи и публикации описаны в RELEASING.md.
Автотесты покрывают обмен сообщениями почтового ящика, истечение и очистку, защиту границ файлов, валидацию имён и опций, фрагментированный UTF-8 и терминальные последовательности ввода. Записанные результаты и живой чек-лист — в docs/VALIDATION.md.
Среди источников, на которые ссылается автор: проект terminal-browser, пример Apple по виртуализации macOS, документация VZVirtualMachineView и ScreenCaptureKit.
Источник: https://github.com/govijr/terminal-mac