# Design: панель без iTerm2 + фон на клиенте Issue: #4. Ветка: `feat/4-headless-panel`. ## Намерение Пользователь смотрит панель с iPad: Termius держит SSH local forward `8766 → 127.0.0.1:8766` на Mac, страница открыта в Safari рядом с Termius (Split View). Все сессии Claude Code — в обычном tmux, который работает сам по себе. Сейчас страница пропадает, если на Mac не запущен iTerm2, потому что сервер поднимает скрипт AutoLaunch iTerm2. Переключение сессий с iPad уже работает — через tmux. Нужно: страница доступна всегда, пока Mac включён и пользователь вошёл; фон меняется прямо на странице, потому что тема по умолчанию в Safari раздражает. Успех: iTerm2 закрыт → в Safari на iPad видно дерево сессий, лимиты и баланс; клики переключают tmux; фон выставлен под тему Termius и держится между перезагрузками. ## Цели - Фоновый сервер панели, независимый от iTerm2, автозапуск при входе, перезапуск при падении. - Один владелец порта 8766; iTerm2-скрипт только регистрирует web view в Toolbelt. - Шестерёнка ⚙ внизу панели (вариант A из мокапов): образцы фона, «свой цвет», «сброс»; выбор хранится на устройстве; текст подстраивается под яркость фона. - `install.sh`/`uninstall.sh` управляют службой; обновление старой установки без ручных шагов. ## Не цели - Досыл названий вкладок iTerm2 и цветов профиля в фоновый сервер (решено пользователем: в tmux имена и так из tmux; цвет — шестерёнкой, в Toolbelt тоже). - Доступ к странице из сети напрямую (только через туннель). - Мод Claude Code / TUI-версия панели (обсуждались, отложены). - Запуск службы без входа пользователя в систему на самом Mac (см. «Открытые вопросы»). ## Анти-цели (провал, даже если «работает») - Два сервера одновременно или удвоенный опрос лимитов (эндпоинт отвечает 429). - Порт открыт наружу: в панели видны тексты сообщений сессий. - Мелькание темы по умолчанию при каждой автоперезагрузке страницы (раз в минуту) после выбора фона. - Установщик ломает чужие хуки/настройки или требует ручных шагов при обновлении. ## Ограничения - Python 3.8+, только стандартная библиотека; модуль `iterm2` — только в режиме регистратора. - macOS, `launchctl`; LaunchAgent в сессии пользователя (Aqua). - В LaunchAgent минимальный `PATH`: путь к `python3` фиксируется установщиком абсолютным; поиск `tmux`/`ps` уже идёт через `EXTRA_PATH` в коде. - Токен лимитов — из Keychain через `security`; служба должна работать в GUI-сессии пользователя, где Keychain разблокирован. - Сервер слушает только `127.0.0.1`. ## Решения, принятые с пользователем - Вариант 0 (SSH-туннель + Safari) — основной сценарий, мод/TUI не делаем. - Фоновая служба через LaunchAgent; один сервер на порту; iTerm2-скрипт — регистратор. - Цвет профиля iTerm2 не досылать и не читать (вариант 3): в Toolbelt фон тоже ставится шестерёнкой. - Место настройки фона — шестерёнка в нижней строке (вариант A). - Перезагрузка Mac без GUI-входа — не решаем сейчас, запоминаем на будущее. - `install.sh` / `uninstall.sh` запускаются только за самим Mac (не по SSH). При запуске из SSH-сессии (`SSH_CONNECTION`/`SSH_TTY` заданы) установщик предупреждает и завершается, ничего не меняя; в README — строка об этом. ## Как устроено (то, что решено) ### Режимы `claude_agents.py` Один исходный файл, два режима: - **Фоновый сервер** (`--headless`, запускает launchd системным `python3`): `asyncio.start_server` на `127.0.0.1:PORT`, `refresher(None)`, `usage_poller`, `balance_poller`; без `iterm2`, без `theme_poller`, без регистрации web view. `live=None` → `build_tree` уже судит о сессиях по PID и tmux. Блок `__main__` запускает этот режим при флаге независимо от наличия `iterm2`. - **Регистратор** (запуск iTerm2 из AutoLaunch, без флага): проверяет, отвечает ли порт; если нет — `launchctl kickstart gui//