Claude Code

Статус сессии

Как purplemux превращает активность Claude Code в бейдж из четырёх состояний — и почему он обновляется почти мгновенно.

Каждая сессия в боковой панели несёт цветную точку, по которой с первого взгляда понятно, чем сейчас занят Claude. Эта страница объясняет, откуда берутся эти четыре состояния и как они остаются синхронизированными без вашего обращения к терминалу.

Четыре состояния

Состояние Индикатор Что значит
Idle нет / серый Claude ждёт следующего промпта.
Busy фиолетовый спиннер Claude обрабатывает — читает, редактирует, запускает инструменты.
Needs input янтарный пульс Запрос разрешения или вопрос ждёт вашего ответа.
Review фиолетовый пульс Claude закончил, и есть что проверить.

Пятое значение — unknown — кратко появляется для вкладок, которые были busy в момент перезапуска сервера. Оно само разрешается, как только purplemux может перепроверить сессию.

Источник истины — хуки

purplemux устанавливает конфигурацию хуков Claude Code в ~/.purplemux/hooks.json и крошечный shell-скрипт в ~/.purplemux/status-hook.sh. Скрипт зарегистрирован на пять событий хуков Claude Code и POST'ит каждое на локальный сервер с CLI-токеном:

Хук Claude Code Получаемое состояние
SessionStart idle
UserPromptSubmit busy
Notification (только разрешения) needs-input
Stop / StopFailure review
PreCompact / PostCompact показывает индикатор сжатия (состояние не меняется)

Поскольку хуки срабатывают в момент перехода Claude Code, боковая панель обновляется раньше, чем вы заметили бы в терминале.

Только уведомления о разрешениях
Хук `Notification` Claude срабатывает по разным причинам. purplemux переключает в **needs-input**, только если уведомление имеет тип `permission_prompt` или `worker_permission_prompt`. Idle-напоминания и прочие типы уведомлений бейдж не активируют.

Определение процесса работает параллельно

То, действительно ли запущен Claude CLI, отслеживается отдельно от рабочего состояния. Сотрудничают два пути:

  • Изменения заголовка tmux — каждая панель сообщает pane_current_command|pane_current_path в качестве заголовка. xterm.js доставляет изменение через onTitleChange, и purplemux пингует /api/check-claude для подтверждения.
  • Обход дерева процессов — на сервере detectActiveSession смотрит на shell PID панели, обходит его потомков и сопоставляет с PID-файлами, которые Claude пишет в ~/.claude/sessions/.

Если каталога нет, UI показывает экран «Claude не установлен» вместо точки статуса.

JSONL-watcher закрывает пробелы

Claude Code пишет JSONL-транскрипт каждой сессии в ~/.claude/projects/. Пока вкладка в состоянии busy, needs-input, unknown или ready-for-review, purplemux наблюдает за этим файлом через fs.watch по двум причинам:

  • Метаданные — текущий инструмент, последний фрагмент ассистента, счётчики токенов. Это перетекает в таймлайн и боковую панель, не меняя состояния.
  • Синтетический interrupt — когда вы нажимаете Esc посреди потока, Claude пишет [Request interrupted by user] в JSONL, но не вызывает хук. Watcher замечает эту строку и синтезирует событие interrupt, чтобы вкладка вернулась в idle вместо застревания в busy.

Поллинг — это страховка, а не движок

Поллинг метаданных запускается каждые 30–60 секунд в зависимости от количества вкладок. Он не определяет состояние — это строго путь хуков. Поллинг существует, чтобы:

  • Обнаруживать новые tmux-панели
  • Восстанавливать любую сессию, висящую в busy дольше 10 минут с мёртвым процессом Claude
  • Обновлять информацию о процессах, портах и заголовках

Это и есть «5–15-секундный fallback poll», упомянутый на главной, — замедленный и сужённый после того, как хуки доказали свою надёжность.

Восстановление после перезапуска сервера

Хуки не могут срабатывать, пока purplemux выключен, так что любое состояние «в полёте» может устареть. Правило восстановления консервативное:

  • Сохранённый busy становится unknown и перепроверяется: если Claude больше не запущен, вкладка тихо переходит в idle; если JSONL аккуратно завершился — становится review.
  • Все остальные состояния — idle, needs-input, ready-for-review — мяч на вашей стороне поля, поэтому они сохраняются нетронутыми.

Никакие автоматические смены состояний при восстановлении не отправляют push-уведомлений. Пинг приходит только когда новая работа переходит в needs-input или review.

Где видно состояние

  • Точка в строке сессии в боковой панели
  • Точка в строке вкладок каждой панели
  • Точка рабочего пространства (наивысший приоритет состояния по всему рабочему пространству)
  • Счётчик иконки колокольчика и шторка уведомлений
  • Заголовок вкладки браузера (считает требующие внимания пункты)
  • Web Push и десктопные уведомления для needs-input и ready-for-review

Что дальше