Andrey Epifancev 521182d4a4 spec: archive headless-panel change (#4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:59:24 +04:00

97 lines
7.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# panel-service Specification
## Purpose
Определяет, где и как работает сервер панели «Claude»: фоновая служба пользователя, не зависящая
от iTerm2, единственный владелец порта панели, тонкая регистрация в Toolbelt и установка/удаление.
## Requirements
### Requirement: Сервер панели работает без iTerm2
Сервер панели SHALL отдавать страницу, дерево сессий, лимиты и баланс на `127.0.0.1:<port>`
(по умолчанию 8766), пока пользователь вошёл в систему, независимо от того, запущен ли iTerm2.
#### Scenario: iTerm2 не запущен
- **WHEN** пользователь вошёл в систему, iTerm2 не запущен, а сессия Claude Code работает в tmux
- **THEN** `http://127.0.0.1:8766/` отвечает 200 и показывает эту сессию с её субагентами, моделью,
контекстом и worktree, а нижний блок показывает лимиты и баланс
#### Scenario: Имена сессий в tmux
- **WHEN** сессия Claude Code работает в панели tmux
- **THEN** её имя берётся из заголовка панели tmux или из `сессия:окно имя_окна`, как и раньше
### Requirement: Служба стартует при входе и перезапускается при падении
Сервер панели SHALL запускаться автоматически при входе пользователя в систему и SHALL
перезапускаться, если его процесс завершился.
#### Scenario: Вход в систему
- **WHEN** пользователь входит в систему на Mac после перезагрузки
- **THEN** сервер панели запускается без открытия iTerm2 и каких-либо действий пользователя
#### Scenario: Падение процесса
- **WHEN** процесс сервера панели завершился (ошибка, `kill`)
- **THEN** он снова запущен и отвечает на порту в пределах нескольких десятков секунд
### Requirement: Порт панели занимает один процесс
На порту панели SHALL работать ровно один сервер; лимиты и баланс SHALL опрашиваться одним
процессом, чтобы не удваивать запросы к API.
#### Scenario: iTerm2 запускается при работающей службе
- **WHEN** служба уже отвечает на порту и пользователь запускает iTerm2
- **THEN** второй сервер не запускается, в API лимитов идёт один поток запросов, а в Toolbelt
появляется панель «Claude», показывающая ту же страницу
### Requirement: Toolbelt показывает панель фоновой службы
Скрипт панели в iTerm2 SHALL регистрировать web view «Claude» в Toolbelt, указывающий на адрес
фоновой службы, и SHALL NOT поднимать собственный сервер.
#### Scenario: Toolbelt при запущенной службе
- **WHEN** iTerm2 запущен и пользователь выбирает Toolbelt → Claude
- **THEN** панель показывает ту же страницу, что и `http://127.0.0.1:8766/` в браузере
#### Scenario: Служба не отвечает при старте iTerm2
- **WHEN** iTerm2 стартует, а служба на порту не отвечает
- **THEN** скрипт просит launchd запустить службу и всё равно регистрирует web view
### Requirement: Сервер доступен только локально
Сервер панели SHALL слушать только `127.0.0.1`; доступ с других устройств возможен только через
туннель (например, SSH local forward).
#### Scenario: Запрос из локальной сети
- **WHEN** устройство в той же сети обращается к Mac по его LAN-адресу на порт панели
- **THEN** соединение не устанавливается
### Requirement: Действия по клику работают через tmux
Переход к сессии и открытие worktree по клику SHALL выполняться средствами tmux для сессий в tmux,
независимо от iTerm2 и от того, на каком устройстве открыта страница.
#### Scenario: Переход к сессии с iPad
- **WHEN** пользователь с iPad (страница через туннель) нажимает «↗ вкладка» у сессии в tmux
- **THEN** клиент tmux переключается на окно и панель этой сессии
#### Scenario: Открытие worktree с iPad
- **WHEN** пользователь нажимает `⎇ папка` у сессии в tmux
- **THEN** в том же окне tmux открывается новая панель с файловым менеджером в этой папке
### Requirement: Установка и удаление службы
`install.sh` SHALL устанавливать, (пере)запускать службу и останавливать прежний сервер, державший
порт; повторный запуск SHALL быть безопасным. `uninstall.sh` SHALL останавливать и удалять службу.
#### Scenario: Обновление старой установки
- **WHEN** у пользователя стоит прежняя версия (сервер внутри iTerm2) и он запускает `install.sh`
- **THEN** прежний сервер остановлен, служба установлена и отвечает на порту, а iTerm2-скрипт
обновлён до регистратора
#### Scenario: Повторная установка
- **WHEN** `install.sh` запускается второй раз подряд
- **THEN** служба одна, отвечает на порту, записи хуков в `settings.json` не задублированы
#### Scenario: Запуск по SSH
- **WHEN** `install.sh` или `uninstall.sh` запущен из SSH-сессии
- **THEN** скрипт сообщает, что его нужно запускать за самим Mac, и завершается с ненулевым кодом,
ничего не изменив: прежний сервер продолжает работать
#### Scenario: Удаление
- **WHEN** пользователь запускает `uninstall.sh`
- **THEN** служба остановлена, её описание удалено, порт свободен и после повторного входа в систему
служба не запускается