Дизайн компактного режима: конкурентный анализ и оптимизация
Переключение компактного/подробного режима Ctrl+O — конкурентный анализ с Claude Code, обзор текущей реализации и рекомендации по оптимизации.
Документация пользователя: Настройки — ui.compactMode.
1. Резюме
Qwen Code и Claude Code предоставляют комбинацию Ctrl+O для переключения между компактным и подробным отображением вывода инструментов, однако философия дизайна, состояние по умолчанию и модель взаимодействия принципиально различаются. Этот документ содержит глубокое сравнение на уровне исходного кода, выявляет UX-пробелы и предлагает оптимизации для Qwen Code.
| Измерение | Claude Code | Qwen Code |
|---|---|---|
| Режим по умолчанию | Компактный (verbose=false) | Подробный (compactMode=false) |
| Семантика переключателя | Временный просмотр деталей | Постоянное переключение предпочтений |
| Сохранение | Только на сессию, сбрасывается при перезапуске | Сохраняется в settings.json |
| Область действия | Глобальное переключение экрана (prompt ↔ transcript) | Переключение отрисовки отдельных компонентов |
| Замороженный снимок | Нет (нет такой концепции) | Нет (удалено) |
| Подсказка развернуть для инструмента | Да («ctrl+o to expand») | Да («Нажмите Ctrl+O, чтобы показать полный вывод инструмента») |
2. Анализ реализации Claude Code
2.1 Архитектура
Claude Code использует подход на основе экрана, а не переключения отрисовки на уровне компонентов:
┌──────────────────────────────────┐
│ AppState (Zustand) │
│ verbose: boolean (default: false)│
│ screen: 'prompt' | 'transcript' │
└──────────┬───────────────────────┘
│
┌─────┴──────┐
│ Ctrl+O │ переключает режим экрана,
│ Handler │ а НЕ флаг отрисовки
└─────┬──────┘
│
┌─────▼──────────────┐
│ REPL.tsx │
│ screen='prompt' → компактный вид (по умолчанию)
│ screen='transcript'→ подробный вид
└────────────────────┘2.2 Ключевые исходные файлы
| Компонент | Файл | Ключевая логика |
|---|---|---|
| Обработчик переключения | src/hooks/useGlobalKeybindings.tsx:90-132 | Переключает screen между 'prompt' и 'transcript' |
| Горячая клавиша | src/keybindings/defaultBindings.ts:44 | app:toggleTranscript |
| Определение состояния | src/state/AppStateStore.ts:472 | verbose: false (только на сессию) |
| Подсказка развернуть | src/components/CtrlOToExpand.tsx:29-46 | Текст “(ctrl+o to expand)” для каждого инструмента |
| Фильтр сообщений | src/components/Messages.tsx:93-151 | filterForBriefTool() для компактного вида |
| Разрешения | src/components/permissions/PermissionRequest.tsx | Отрисовывается в слое наложения, никогда не скрывается |
2.3 Дизайнерские решения
- Компактный режим по умолчанию. Пользователи видят чистый интерфейс «из коробки»; детализация — опциональна.
- Ограничено сессией.
verboseсбрасывается вfalseпри каждом новом сеансе — Claude Code предполагает, что пользователи обычно предпочитают компактный вид и нуждаются в деталях лишь временно. - Переключение на уровне экрана. Ctrl+O не изменяет то, как компоненты отрисовываются; он переключает весь дисплей между экраном «prompt» (компактный) и экраном «transcript» (подробный).
- Нет замороженных снимков. Концепция заморозки снимков отсутствует. При переключении отображение обновляется сразу с текущим состоянием.
- Диалоги разрешений отделены. Подтверждения инструментов отрисовываются в выделенном слое наложения, который никогда не затрагивается переключателем verbose/compact.
- Подсказка для каждого инструмента. Компонент
CtrlOToExpandпоказывает контекстную подсказку на отдельных инструментах, когда они выдают большой вывод; подавляется в под-агентах.
2.4 Пользовательский поток
Начало сессии → компактный режим (по умолчанию)
│
├─ Выводы инструментов сведены в одну строку
├─ Большой вывод инструмента показывает подсказку «(ctrl+o to expand)»
│
├─ Пользователь нажимает Ctrl+O
│ └─→ Экран переключается на transcript (подробный вид)
│ └─ Пользователь видит весь вывод инструментов, мысли и т.д.
│
├─ Пользователь снова нажимает Ctrl+O
│ └─→ Экран переключается обратно на prompt (компактный)
│
└─ Сессия заканчивается → verbose сбрасывается в false3. Анализ реализации Qwen Code
3.1 Архитектура
Qwen Code использует флаг отрисовки на уровне компонентов, который каждый UI-компонент читает из контекста:
┌─────────────────────────────────────┐
│ CompactModeContext │
│ compactMode: boolean (default: false)│
│ setCompactMode: (v) => void │
└──────────┬──────────────────────────┘
│
┌─────┴──────┐
│ Ctrl+O │ переключает compactMode
│ Handler │ сохраняет в настройки
└─────┬──────┘
│
┌─────▼──────────────────┐
│ Каждый компонент │
│ читает compactMode │
│ и решает, как │
│ отрисовываться │
└────────────────────────┘
│
┌─────▼──────────────────────────────┐
│ ToolGroupMessage │
│ showCompact = compactMode │
│ && !hasConfirmingTool │
│ && !hasErrorTool │
│ && !isEmbeddedShellFocused │
│ && !isUserInitiated │
└────────────────────────────────────┘3.2 Ключевые исходные файлы
| Компонент | Файл | Ключевая логика |
|---|---|---|
| Обработчик переключения | AppContainer.tsx:1684-1690 | Переключает compactMode, сохраняет в настройки |
| Контекст | CompactModeContext.tsx | compactMode, setCompactMode |
| Группа инструментов | ToolGroupMessage.tsx:105-110 | showCompact с 4 условиями принудительного разворачивания |
| Сообщение инструмента | ToolMessage.tsx:346-350 | Скрывает displayRenderer в компактном режиме |
| Компактное отображение | CompactToolGroupDisplay.tsx:49-108 | Однострочная сводка со статусом и подсказкой |
| Подтверждение | ToolConfirmationMessage.tsx:113-147 | Упрощённое компактное подтверждение с 3 опциями |
| Подсказки | Tips.tsx:14-29 | Ротация стартовых подсказок включает подсказку о компактном режиме |
| Синхронизация с настройками | SettingsDialog.tsx:189-193 | Синхронизация с CompactModeContext + refreshStatic |
| MainContent | MainContent.tsx:60-76 | Отрисовывает живые pendingHistoryItems |
| Мышление | HistoryItemDisplay.tsx:123-133 | Скрывает gemini_thought в компактном режиме |
3.3 Дизайнерские решения
- Подробный режим по умолчанию. Пользователи видят весь вывод инструментов и мысли по умолчанию.
- Постоянное предпочтение.
compactModeсохраняется вsettings.jsonи переживает сессии. - Отрисовка на уровне компонентов. Каждый компонент читает
compactModeиз контекста и адаптирует собственную отрисовку. - Защита принудительного разворачивания. Четыре условия переопределяют компактный режим, чтобы гарантировать видимость критических элементов интерфейса (подтверждения, ошибки, оболочка, инициированные пользователем).
- Нет замороженных снимков. Переключатель всегда показывает живой вывод — никаких замороженных снимков.
- Синхронизация с диалогом настроек. Переключение компактного режима из настроек мгновенно обновляет состояние React через
setCompactMode. - Ненавязчивое обнаружение. Компактный режим представляется через ротацию стартовых подсказок, а не постоянный индикатор в футере, чтобы избежать загромождения интерфейса.
3.4 Пользовательский поток
Начало сессии → подробный режим (по умолчанию)
│
├─ Весь вывод инструментов, мысли, детали видны
│
├─ Пользователь нажимает Ctrl+O (или переключает в Настройках)
│ └─→ compactMode = true, сохранено
│ ├─ Группы инструментов показывают однострочную сводку
│ ├─ Содержимое мыслей/размышлений скрыто
│ └─ Подтверждения, ошибки, оболочка всё ещё развёрнуты
│
├─ Пользователь снова нажимает Ctrl+O
│ └─→ compactMode = false, сохранено
│ └─ Все детали снова видны
│
└─ Следующая сессия → тот же режим, что и в прошлый раз4. Глубокое сравнение ключевых различий
4.1 Философия режима по умолчанию
| Аспект | Claude Code (компактный по умолчанию) | Qwen Code (подробный по умолчанию) |
|---|---|---|
| Первое впечатление | Чисто, минималистично — профессиональное ощущение | Богато информацией — полная прозрачность |
| Кривая обучения | Пользователь должен выучить Ctrl+O, чтобы увидеть детали | Пользователь сразу может видеть всё |
| Целевая аудитория | Опытные пользователи, доверяющие инструменту | Пользователи, желающие понимать происходящее |
| Информационная перегрузка | Избегается по умолчанию | Возможна для новых пользователей |
| Обнаружение | Подсказки «(ctrl+o to expand)» на инструментах | Ротация стартовых подсказок + ? ярлыки + /help |
Анализ: Компактный режим по умолчанию у Claude Code работает, потому что его пользовательская база — в основном опытные разработчики, которые доверяют инструменту и не нуждаются в просмотре каждого вызова инструмента. Подробный режим по умолчанию у Qwen Code уместен на ранней стадии, когда построение доверия пользователей через прозрачность важно.
4.2 Модель сохранения
| Аспект | Claude Code | Qwen Code |
|---|---|---|
| Сохраняется? | Нет — только на сессию | Да — в settings.json |
| Обоснование | Подробный режим — временный просмотр | Режим — предпочтение пользователя |
| Поведение при перезапуске | Всегда запускается в компактном | Запускается с последним использованным режимом |
Анализ: Claude Code рассматривает просмотр деталей как сиюминутную потребность — вы посмотрели и вернулись. Qwen Code рассматривает это как стабильное предпочтение — некоторым пользователям всегда нужны детали, другим всегда компактный вид. Оба подхода валидны; подход Qwen Code более гибкий.
4.3 Защита подтверждений
| Аспект | Claude Code | Qwen Code |
|---|---|---|
| Механизм | Слой наложения/модальное окно (структурно отделён) | Условия принудительного разворачивания в showCompact |
| Охват | Полный — одобрения никогда не могут быть скрыты | Полный — 4 условия покрывают все интерактивные состояния |
| Компактный UI подтверждения | Н/Д (наложение всегда полноразмерное) | Упрощённый RadioButtonSelect с 3 опциями |
Анализ: Архитектурное разделение Claude Code (слой наложения) более надёжно. Подход Qwen Code с принудительным разворачиванием эффективен, но требует явного добавления каждого нового интерактивного состояния в список условий.
4.4 Подход к отрисовке
| Аспект | Claude Code | Qwen Code |
|---|---|---|
| Область переключения | Уровень экрана (prompt ↔ transcript) | Уровень компонентов (каждый компонент решает) |
| Детализация | Всё или ничего | Тонко настраиваемая для каждого компонента |
| Гибкость | Низкая — глобальный переключатель | Высокая — компоненты могут переопределять |
| Согласованность | Гарантирована | Зависит от реализации каждого компонента |
Анализ: Подход Qwen Code на уровне компонентов более гибок (например, принудительное разворачивание для определённых условий), но требует большей дисциплины для поддержания согласованности. Подход Claude Code на уровне экрана проще и гарантирует единообразное поведение.
5. Рекомендации по оптимизации
5.1 [P0] Оставить подробный режим по умолчанию — изменений не требуется
Подробный режим по умолчанию у Qwen Code — правильный выбор для текущего этапа. Новым пользователям нужна прозрачность для построения доверия. По мере взросления продукта можно рассмотреть переход на компактный режим по умолчанию (как в Claude Code).
5.2 [P1] Разворачивание отдельных инструментов при большом выводе
Claude Code показывает «(ctrl+o to expand)» на отдельных инструментах, которые выдают большой вывод. Qwen Code в настоящее время имеет только глобальный переключатель. Рассмотреть:
- Когда один инструмент выдаёт вывод, превышающий N строк, показывать подсказку «развернуть» для этого инструмента в компактном режиме.
- Область: улучшение в будущем, не текущий приоритет.
5.3 [P2] Рассмотреть временное переопределение на сессию
Некоторым пользователям может быть удобен компактный режим по умолчанию, но иногда нужен подробный для конкретной сессии. Рассмотреть поддержку обоих:
settings.json→ постоянное значение по умолчанию (текущее поведение)- Ctrl+O во время сессии → временное переопределение только для текущей сессии (поведение Claude Code)
- При перезапуске сессии → вернуться к значению из settings.json
Это даст пользователям лучшее из обоих миров. Реализация потребует разделения состояния «настройка по умолчанию» и «переопределение в сессии».
5.4 [P2] Структурное разделение для подтверждений
В настоящее время защита подтверждений основана на условиях showCompact в ToolGroupMessage. Рассмотреть более надёжный подход:
- Отрисовывать подтверждения в отдельном слое (как подход Claude Code с наложением).
- Это сделает архитектурно невозможным влияние компактного режима на подтверждения.
- Более низкий приоритет, так как текущий подход с принудительным разворачиванием работает корректно.
6. Текущее состояние реализации
После изменений в ветке feat/compact-mode-optimization:
| Функция | Статус | Примечания |
|---|---|---|
| Подсказка в стартовых советах | Готово | Подсказка о компактном режиме в ротации Tips (ненавязчиво) |
| Ctrl+O в клавиатурных сокращениях (?) | Готово | Добавлено в компонент KeyboardShortcuts |
| Ctrl+O в /help | Готово | Добавлено в компонент Help |
| Синхронизация с диалогом настроек | Готово | Синхронизирует compactMode с CompactModeContext |
| Нет замороженных снимков | Готово | Переключатель всегда показывает живой вывод |
| Защита подтверждений | Готово | Принудительное разворачивание + защита WaitingForConfirmation |
| Защита оболочки | Готово | Принудительное разворачивание через !isEmbeddedShellFocused |
| Защита ошибок | Готово | Принудительное разворачивание через !hasErrorTool |
| Обновлена пользовательская документация | Готово | settings.md, keyboard-shortcuts.md |
7. Справочник файлов
Qwen Code
| Файл | Назначение |
|---|---|
packages/cli/src/ui/AppContainer.tsx | Обработчик переключения, инициализация состояния, провайдер контекста |
packages/cli/src/ui/contexts/CompactModeContext.tsx | Определение контекста |
packages/cli/src/ui/components/messages/ToolGroupMessage.tsx | Логика принудительного разворачивания |
packages/cli/src/ui/components/messages/ToolMessage.tsx | Скрытие вывода отдельного инструмента |
packages/cli/src/ui/components/messages/CompactToolGroupDisplay.tsx | Отрисовка компактного вида |
packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx | Компактный UI подтверждения |
packages/cli/src/ui/components/MainContent.tsx | Отрисовка ожидающих элементов истории |
packages/cli/src/ui/components/Tips.tsx | Стартовая подсказка с упоминанием компактного режима |
packages/cli/src/ui/components/Help.tsx | Запись ярлыка в /help |
packages/cli/src/ui/components/KeyboardShortcuts.tsx | Запись ярлыка в ? |
packages/cli/src/ui/components/SettingsDialog.tsx | Синхронизация с настройками |
packages/cli/src/ui/components/HistoryItemDisplay.tsx | Скрытие содержимого мыслей |
packages/cli/src/config/settingsSchema.ts | Определение настройки |
packages/cli/src/config/keyBindings.ts | Привязка Ctrl+O |
Claude Code (справочно)
| Файл | Назначение |
|---|---|
src/hooks/useGlobalKeybindings.tsx | Обработчик переключения |
src/state/AppStateStore.ts | Определение состояния (verbose: false) |
src/components/CtrlOToExpand.tsx | Подсказка развернуть для инструмента |
src/components/Messages.tsx | Фильтр кратких сообщений |
src/screens/REPL.tsx | Переключение режима на уровне экрана |
src/components/permissions/PermissionRequest.tsx | Подтверждение на основе наложения |