diff --git a/docs/media/tui-lock-v2/120x40/btw.png b/docs/media/tui-lock-v2/120x40/btw.png new file mode 100644 index 0000000..7341f86 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/btw.png differ diff --git a/docs/media/tui-lock-v2/120x40/clear-confirm.png b/docs/media/tui-lock-v2/120x40/clear-confirm.png new file mode 100644 index 0000000..f9e88c2 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/clear-confirm.png differ diff --git a/docs/media/tui-lock-v2/120x40/cloud-handoff.png b/docs/media/tui-lock-v2/120x40/cloud-handoff.png new file mode 100644 index 0000000..c38b743 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/cloud-handoff.png differ diff --git a/docs/media/tui-lock-v2/120x40/code-fence.png b/docs/media/tui-lock-v2/120x40/code-fence.png new file mode 100644 index 0000000..dd5fff5 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/code-fence.png differ diff --git a/docs/media/tui-lock-v2/120x40/compact-chat.png b/docs/media/tui-lock-v2/120x40/compact-chat.png new file mode 100644 index 0000000..50577fb Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/compact-chat.png differ diff --git a/docs/media/tui-lock-v2/120x40/composer-empty.png b/docs/media/tui-lock-v2/120x40/composer-empty.png new file mode 100644 index 0000000..7136166 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/composer-empty.png differ diff --git a/docs/media/tui-lock-v2/120x40/composer-hover.png b/docs/media/tui-lock-v2/120x40/composer-hover.png new file mode 100644 index 0000000..33dc149 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/composer-hover.png differ diff --git a/docs/media/tui-lock-v2/120x40/composer-multiline.png b/docs/media/tui-lock-v2/120x40/composer-multiline.png new file mode 100644 index 0000000..3291039 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/composer-multiline.png differ diff --git a/docs/media/tui-lock-v2/120x40/composer-typing-blink.png b/docs/media/tui-lock-v2/120x40/composer-typing-blink.png new file mode 100644 index 0000000..44e1182 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/composer-typing-blink.png differ diff --git a/docs/media/tui-lock-v2/120x40/composer-typing.png b/docs/media/tui-lock-v2/120x40/composer-typing.png new file mode 100644 index 0000000..a4a8f68 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/composer-typing.png differ diff --git a/docs/media/tui-lock-v2/120x40/config-tree.png b/docs/media/tui-lock-v2/120x40/config-tree.png new file mode 100644 index 0000000..ba3dc6c Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/config-tree.png differ diff --git a/docs/media/tui-lock-v2/120x40/diagnostics.png b/docs/media/tui-lock-v2/120x40/diagnostics.png new file mode 100644 index 0000000..b7d1bc6 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/diagnostics.png differ diff --git a/docs/media/tui-lock-v2/120x40/diff-hunk.png b/docs/media/tui-lock-v2/120x40/diff-hunk.png new file mode 100644 index 0000000..0ac434a Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/diff-hunk.png differ diff --git a/docs/media/tui-lock-v2/120x40/edit-collapsed.png b/docs/media/tui-lock-v2/120x40/edit-collapsed.png new file mode 100644 index 0000000..55ac980 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/edit-collapsed.png differ diff --git a/docs/media/tui-lock-v2/120x40/error-unavailable.png b/docs/media/tui-lock-v2/120x40/error-unavailable.png new file mode 100644 index 0000000..6be42b8 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/error-unavailable.png differ diff --git a/docs/media/tui-lock-v2/120x40/files-picker.png b/docs/media/tui-lock-v2/120x40/files-picker.png new file mode 100644 index 0000000..b1b9823 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/files-picker.png differ diff --git a/docs/media/tui-lock-v2/120x40/first-run-tips.png b/docs/media/tui-lock-v2/120x40/first-run-tips.png new file mode 100644 index 0000000..c8b28e8 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/first-run-tips.png differ diff --git a/docs/media/tui-lock-v2/120x40/footer-hover.png b/docs/media/tui-lock-v2/120x40/footer-hover.png new file mode 100644 index 0000000..a9af11d Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/footer-hover.png differ diff --git a/docs/media/tui-lock-v2/120x40/footer-shortcuts.png b/docs/media/tui-lock-v2/120x40/footer-shortcuts.png new file mode 100644 index 0000000..8100bfb Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/footer-shortcuts.png differ diff --git a/docs/media/tui-lock-v2/120x40/interrupt-stopped.png b/docs/media/tui-lock-v2/120x40/interrupt-stopped.png new file mode 100644 index 0000000..047b01b Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/interrupt-stopped.png differ diff --git a/docs/media/tui-lock-v2/120x40/jobs.png b/docs/media/tui-lock-v2/120x40/jobs.png new file mode 100644 index 0000000..517246e Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/jobs.png differ diff --git a/docs/media/tui-lock-v2/120x40/login-error.png b/docs/media/tui-lock-v2/120x40/login-error.png new file mode 100644 index 0000000..ace3154 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/login-error.png differ diff --git a/docs/media/tui-lock-v2/120x40/login-success.png b/docs/media/tui-lock-v2/120x40/login-success.png new file mode 100644 index 0000000..df1a12b Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/login-success.png differ diff --git a/docs/media/tui-lock-v2/120x40/login-waiting.png b/docs/media/tui-lock-v2/120x40/login-waiting.png new file mode 100644 index 0000000..65e6384 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/login-waiting.png differ diff --git a/docs/media/tui-lock-v2/120x40/login.png b/docs/media/tui-lock-v2/120x40/login.png new file mode 100644 index 0000000..5d98cba Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/login.png differ diff --git a/docs/media/tui-lock-v2/120x40/mcp-drop.png b/docs/media/tui-lock-v2/120x40/mcp-drop.png new file mode 100644 index 0000000..3a80483 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/mcp-drop.png differ diff --git a/docs/media/tui-lock-v2/120x40/mcp-servers.png b/docs/media/tui-lock-v2/120x40/mcp-servers.png new file mode 100644 index 0000000..bb664e2 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/mcp-servers.png differ diff --git a/docs/media/tui-lock-v2/120x40/md-table.png b/docs/media/tui-lock-v2/120x40/md-table.png new file mode 100644 index 0000000..4638ab4 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/md-table.png differ diff --git a/docs/media/tui-lock-v2/120x40/mode-agent.png b/docs/media/tui-lock-v2/120x40/mode-agent.png new file mode 100644 index 0000000..f301dd1 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/mode-agent.png differ diff --git a/docs/media/tui-lock-v2/120x40/mode-ask.png b/docs/media/tui-lock-v2/120x40/mode-ask.png new file mode 100644 index 0000000..b821155 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/mode-ask.png differ diff --git a/docs/media/tui-lock-v2/120x40/mode-bash.png b/docs/media/tui-lock-v2/120x40/mode-bash.png new file mode 100644 index 0000000..77133b1 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/mode-bash.png differ diff --git a/docs/media/tui-lock-v2/120x40/mode-plan.png b/docs/media/tui-lock-v2/120x40/mode-plan.png new file mode 100644 index 0000000..323cda0 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/mode-plan.png differ diff --git a/docs/media/tui-lock-v2/120x40/model-effort-high.png b/docs/media/tui-lock-v2/120x40/model-effort-high.png new file mode 100644 index 0000000..a37ca46 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/model-effort-high.png differ diff --git a/docs/media/tui-lock-v2/120x40/model-effort-hover.png b/docs/media/tui-lock-v2/120x40/model-effort-hover.png new file mode 100644 index 0000000..2324b7b Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/model-effort-hover.png differ diff --git a/docs/media/tui-lock-v2/120x40/model-effort-low.png b/docs/media/tui-lock-v2/120x40/model-effort-low.png new file mode 100644 index 0000000..29b99a1 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/model-effort-low.png differ diff --git a/docs/media/tui-lock-v2/120x40/model-effort-medium.png b/docs/media/tui-lock-v2/120x40/model-effort-medium.png new file mode 100644 index 0000000..7f3096d Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/model-effort-medium.png differ diff --git a/docs/media/tui-lock-v2/120x40/model-list-hover.png b/docs/media/tui-lock-v2/120x40/model-list-hover.png new file mode 100644 index 0000000..30f57e2 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/model-list-hover.png differ diff --git a/docs/media/tui-lock-v2/120x40/model-list.png b/docs/media/tui-lock-v2/120x40/model-list.png new file mode 100644 index 0000000..c7e4059 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/model-list.png differ diff --git a/docs/media/tui-lock-v2/120x40/permission-prompt-hover.png b/docs/media/tui-lock-v2/120x40/permission-prompt-hover.png new file mode 100644 index 0000000..94a3119 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/permission-prompt-hover.png differ diff --git a/docs/media/tui-lock-v2/120x40/permission-prompt.png b/docs/media/tui-lock-v2/120x40/permission-prompt.png new file mode 100644 index 0000000..a4ce483 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/permission-prompt.png differ diff --git a/docs/media/tui-lock-v2/120x40/permissions-picker.png b/docs/media/tui-lock-v2/120x40/permissions-picker.png new file mode 100644 index 0000000..6f7cb07 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/permissions-picker.png differ diff --git a/docs/media/tui-lock-v2/120x40/plan-confirm.png b/docs/media/tui-lock-v2/120x40/plan-confirm.png new file mode 100644 index 0000000..d212de1 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/plan-confirm.png differ diff --git a/docs/media/tui-lock-v2/120x40/plugins.png b/docs/media/tui-lock-v2/120x40/plugins.png new file mode 100644 index 0000000..29ff0cc Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/plugins.png differ diff --git a/docs/media/tui-lock-v2/120x40/question.png b/docs/media/tui-lock-v2/120x40/question.png new file mode 100644 index 0000000..97d3880 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/question.png differ diff --git a/docs/media/tui-lock-v2/120x40/queue.png b/docs/media/tui-lock-v2/120x40/queue.png new file mode 100644 index 0000000..672a9eb Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/queue.png differ diff --git a/docs/media/tui-lock-v2/120x40/quota-exhausted.png b/docs/media/tui-lock-v2/120x40/quota-exhausted.png new file mode 100644 index 0000000..38f5524 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/quota-exhausted.png differ diff --git a/docs/media/tui-lock-v2/120x40/resume-picker.png b/docs/media/tui-lock-v2/120x40/resume-picker.png new file mode 100644 index 0000000..db69027 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/resume-picker.png differ diff --git a/docs/media/tui-lock-v2/120x40/sandbox-deny.png b/docs/media/tui-lock-v2/120x40/sandbox-deny.png new file mode 100644 index 0000000..c4b9e78 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/sandbox-deny.png differ diff --git a/docs/media/tui-lock-v2/120x40/sandbox.png b/docs/media/tui-lock-v2/120x40/sandbox.png new file mode 100644 index 0000000..6538dd5 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/sandbox.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-assistant.png b/docs/media/tui-lock-v2/120x40/session-assistant.png new file mode 100644 index 0000000..6efd517 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-assistant.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-empty.png b/docs/media/tui-lock-v2/120x40/session-empty.png new file mode 100644 index 0000000..7136166 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-empty.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-optin-hover.png b/docs/media/tui-lock-v2/120x40/session-optin-hover.png new file mode 100644 index 0000000..6b41ab6 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-optin-hover.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-optin.png b/docs/media/tui-lock-v2/120x40/session-optin.png new file mode 100644 index 0000000..d33b8e8 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-optin.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-thinking-live.png b/docs/media/tui-lock-v2/120x40/session-thinking-live.png new file mode 100644 index 0000000..cd6e3cd Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-thinking-live.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-thought-expanded.png b/docs/media/tui-lock-v2/120x40/session-thought-expanded.png new file mode 100644 index 0000000..977ee34 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-thought-expanded.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-thought.png b/docs/media/tui-lock-v2/120x40/session-thought.png new file mode 100644 index 0000000..97ee6a5 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-thought.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-user-bars.png b/docs/media/tui-lock-v2/120x40/session-user-bars.png new file mode 100644 index 0000000..9ceacf1 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-user-bars.png differ diff --git a/docs/media/tui-lock-v2/120x40/session-worked.png b/docs/media/tui-lock-v2/120x40/session-worked.png new file mode 100644 index 0000000..1e169a3 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/session-worked.png differ diff --git a/docs/media/tui-lock-v2/120x40/settings-appearance.png b/docs/media/tui-lock-v2/120x40/settings-appearance.png new file mode 100644 index 0000000..0e29057 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/settings-appearance.png differ diff --git a/docs/media/tui-lock-v2/120x40/settings-mouse.png b/docs/media/tui-lock-v2/120x40/settings-mouse.png new file mode 100644 index 0000000..bc15cc3 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/settings-mouse.png differ diff --git a/docs/media/tui-lock-v2/120x40/settings-row-hover.png b/docs/media/tui-lock-v2/120x40/settings-row-hover.png new file mode 100644 index 0000000..f633f02 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/settings-row-hover.png differ diff --git a/docs/media/tui-lock-v2/120x40/settings-search.png b/docs/media/tui-lock-v2/120x40/settings-search.png new file mode 100644 index 0000000..73cca74 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/settings-search.png differ diff --git a/docs/media/tui-lock-v2/120x40/settings-theme-submenu.png b/docs/media/tui-lock-v2/120x40/settings-theme-submenu.png new file mode 100644 index 0000000..40f70a4 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/settings-theme-submenu.png differ diff --git a/docs/media/tui-lock-v2/120x40/shell-running.png b/docs/media/tui-lock-v2/120x40/shell-running.png new file mode 100644 index 0000000..54930fe Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/shell-running.png differ diff --git a/docs/media/tui-lock-v2/120x40/shortcuts-overlay.png b/docs/media/tui-lock-v2/120x40/shortcuts-overlay.png new file mode 100644 index 0000000..8d239b0 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/shortcuts-overlay.png differ diff --git a/docs/media/tui-lock-v2/120x40/skills.png b/docs/media/tui-lock-v2/120x40/skills.png new file mode 100644 index 0000000..34e7381 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/skills.png differ diff --git a/docs/media/tui-lock-v2/120x40/slash-model-typed.png b/docs/media/tui-lock-v2/120x40/slash-model-typed.png new file mode 100644 index 0000000..ec3eb56 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/slash-model-typed.png differ diff --git a/docs/media/tui-lock-v2/120x40/slash-palette.png b/docs/media/tui-lock-v2/120x40/slash-palette.png new file mode 100644 index 0000000..308bf85 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/slash-palette.png differ diff --git a/docs/media/tui-lock-v2/120x40/sudo.png b/docs/media/tui-lock-v2/120x40/sudo.png new file mode 100644 index 0000000..ab9c8c8 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/sudo.png differ diff --git a/docs/media/tui-lock-v2/120x40/todos.png b/docs/media/tui-lock-v2/120x40/todos.png new file mode 100644 index 0000000..5f8f730 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/todos.png differ diff --git a/docs/media/tui-lock-v2/120x40/tokens-topright-warn.png b/docs/media/tui-lock-v2/120x40/tokens-topright-warn.png new file mode 100644 index 0000000..b7473c4 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/tokens-topright-warn.png differ diff --git a/docs/media/tui-lock-v2/120x40/tokens-topright.png b/docs/media/tui-lock-v2/120x40/tokens-topright.png new file mode 100644 index 0000000..7196568 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/tokens-topright.png differ diff --git a/docs/media/tui-lock-v2/120x40/tool-tiles-collapsed.png b/docs/media/tui-lock-v2/120x40/tool-tiles-collapsed.png new file mode 100644 index 0000000..7eb8dc9 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/tool-tiles-collapsed.png differ diff --git a/docs/media/tui-lock-v2/120x40/tool-tiles.png b/docs/media/tui-lock-v2/120x40/tool-tiles.png new file mode 100644 index 0000000..3515baf Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/tool-tiles.png differ diff --git a/docs/media/tui-lock-v2/120x40/usage.png b/docs/media/tui-lock-v2/120x40/usage.png new file mode 100644 index 0000000..d969ebb Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/usage.png differ diff --git a/docs/media/tui-lock-v2/120x40/welcome-agent.png b/docs/media/tui-lock-v2/120x40/welcome-agent.png new file mode 100644 index 0000000..9b2fbbd Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/welcome-agent.png differ diff --git a/docs/media/tui-lock-v2/120x40/welcome-cortex.png b/docs/media/tui-lock-v2/120x40/welcome-cortex.png new file mode 100644 index 0000000..b00b531 Binary files /dev/null and b/docs/media/tui-lock-v2/120x40/welcome-cortex.png differ diff --git a/docs/media/tui-lock-v2/40x12/compact-chat.png b/docs/media/tui-lock-v2/40x12/compact-chat.png new file mode 100644 index 0000000..b90c9d6 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/compact-chat.png differ diff --git a/docs/media/tui-lock-v2/40x12/composer-empty.png b/docs/media/tui-lock-v2/40x12/composer-empty.png new file mode 100644 index 0000000..9d8df07 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/composer-empty.png differ diff --git a/docs/media/tui-lock-v2/40x12/composer-hover.png b/docs/media/tui-lock-v2/40x12/composer-hover.png new file mode 100644 index 0000000..8063fe1 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/composer-hover.png differ diff --git a/docs/media/tui-lock-v2/40x12/composer-typing.png b/docs/media/tui-lock-v2/40x12/composer-typing.png new file mode 100644 index 0000000..3d2c426 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/composer-typing.png differ diff --git a/docs/media/tui-lock-v2/40x12/diagnostics.png b/docs/media/tui-lock-v2/40x12/diagnostics.png new file mode 100644 index 0000000..7fa4edc Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/diagnostics.png differ diff --git a/docs/media/tui-lock-v2/40x12/diff-hunk.png b/docs/media/tui-lock-v2/40x12/diff-hunk.png new file mode 100644 index 0000000..890c22d Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/diff-hunk.png differ diff --git a/docs/media/tui-lock-v2/40x12/first-run-tips.png b/docs/media/tui-lock-v2/40x12/first-run-tips.png new file mode 100644 index 0000000..079a879 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/first-run-tips.png differ diff --git a/docs/media/tui-lock-v2/40x12/interrupt-stopped.png b/docs/media/tui-lock-v2/40x12/interrupt-stopped.png new file mode 100644 index 0000000..1c6036b Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/interrupt-stopped.png differ diff --git a/docs/media/tui-lock-v2/40x12/login.png b/docs/media/tui-lock-v2/40x12/login.png new file mode 100644 index 0000000..362371d Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/login.png differ diff --git a/docs/media/tui-lock-v2/40x12/mcp-servers.png b/docs/media/tui-lock-v2/40x12/mcp-servers.png new file mode 100644 index 0000000..cb4043d Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/mcp-servers.png differ diff --git a/docs/media/tui-lock-v2/40x12/mode-ask.png b/docs/media/tui-lock-v2/40x12/mode-ask.png new file mode 100644 index 0000000..6e31ff4 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/mode-ask.png differ diff --git a/docs/media/tui-lock-v2/40x12/mode-plan.png b/docs/media/tui-lock-v2/40x12/mode-plan.png new file mode 100644 index 0000000..5c9d958 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/mode-plan.png differ diff --git a/docs/media/tui-lock-v2/40x12/model-effort-high.png b/docs/media/tui-lock-v2/40x12/model-effort-high.png new file mode 100644 index 0000000..df682c9 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/model-effort-high.png differ diff --git a/docs/media/tui-lock-v2/40x12/model-list.png b/docs/media/tui-lock-v2/40x12/model-list.png new file mode 100644 index 0000000..0242fcf Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/model-list.png differ diff --git a/docs/media/tui-lock-v2/40x12/permission-prompt.png b/docs/media/tui-lock-v2/40x12/permission-prompt.png new file mode 100644 index 0000000..f49a091 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/permission-prompt.png differ diff --git a/docs/media/tui-lock-v2/40x12/session-assistant.png b/docs/media/tui-lock-v2/40x12/session-assistant.png new file mode 100644 index 0000000..43af154 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/session-assistant.png differ diff --git a/docs/media/tui-lock-v2/40x12/session-empty.png b/docs/media/tui-lock-v2/40x12/session-empty.png new file mode 100644 index 0000000..9d8df07 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/session-empty.png differ diff --git a/docs/media/tui-lock-v2/40x12/session-optin.png b/docs/media/tui-lock-v2/40x12/session-optin.png new file mode 100644 index 0000000..58ebe08 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/session-optin.png differ diff --git a/docs/media/tui-lock-v2/40x12/session-thinking-live.png b/docs/media/tui-lock-v2/40x12/session-thinking-live.png new file mode 100644 index 0000000..6f9bebe Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/session-thinking-live.png differ diff --git a/docs/media/tui-lock-v2/40x12/session-user-bars.png b/docs/media/tui-lock-v2/40x12/session-user-bars.png new file mode 100644 index 0000000..2ff56f5 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/session-user-bars.png differ diff --git a/docs/media/tui-lock-v2/40x12/settings-appearance.png b/docs/media/tui-lock-v2/40x12/settings-appearance.png new file mode 100644 index 0000000..b071f8b Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/settings-appearance.png differ diff --git a/docs/media/tui-lock-v2/40x12/settings-mouse.png b/docs/media/tui-lock-v2/40x12/settings-mouse.png new file mode 100644 index 0000000..4827966 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/settings-mouse.png differ diff --git a/docs/media/tui-lock-v2/40x12/settings-row-hover.png b/docs/media/tui-lock-v2/40x12/settings-row-hover.png new file mode 100644 index 0000000..6254201 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/settings-row-hover.png differ diff --git a/docs/media/tui-lock-v2/40x12/settings-theme-submenu.png b/docs/media/tui-lock-v2/40x12/settings-theme-submenu.png new file mode 100644 index 0000000..95d4803 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/settings-theme-submenu.png differ diff --git a/docs/media/tui-lock-v2/40x12/shortcuts-overlay.png b/docs/media/tui-lock-v2/40x12/shortcuts-overlay.png new file mode 100644 index 0000000..05fdd45 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/shortcuts-overlay.png differ diff --git a/docs/media/tui-lock-v2/40x12/slash-model-typed.png b/docs/media/tui-lock-v2/40x12/slash-model-typed.png new file mode 100644 index 0000000..ad98a74 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/slash-model-typed.png differ diff --git a/docs/media/tui-lock-v2/40x12/slash-palette.png b/docs/media/tui-lock-v2/40x12/slash-palette.png new file mode 100644 index 0000000..aa0fc74 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/slash-palette.png differ diff --git a/docs/media/tui-lock-v2/40x12/tokens-topright.png b/docs/media/tui-lock-v2/40x12/tokens-topright.png new file mode 100644 index 0000000..46aa457 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/tokens-topright.png differ diff --git a/docs/media/tui-lock-v2/40x12/usage.png b/docs/media/tui-lock-v2/40x12/usage.png new file mode 100644 index 0000000..42ca4e9 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/usage.png differ diff --git a/docs/media/tui-lock-v2/40x12/welcome-agent.png b/docs/media/tui-lock-v2/40x12/welcome-agent.png new file mode 100644 index 0000000..062e464 Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/welcome-agent.png differ diff --git a/docs/media/tui-lock-v2/40x12/welcome-cortex.png b/docs/media/tui-lock-v2/40x12/welcome-cortex.png new file mode 100644 index 0000000..b5893bd Binary files /dev/null and b/docs/media/tui-lock-v2/40x12/welcome-cortex.png differ diff --git a/docs/media/tui-lock-v2/SPEC.md b/docs/media/tui-lock-v2/SPEC.md new file mode 100644 index 0000000..3b59925 --- /dev/null +++ b/docs/media/tui-lock-v2/SPEC.md @@ -0,0 +1,476 @@ +# Cortex CLI — TUI lock v2 · design spec + +Design-only deliverable for the full TUI redesign. Layout language is taken +1:1 from the reference boards (user prompt bars, `♦ Thought` line, dual-hairline +composer with the model chip in the bottom border, Settings modal with search + +categorised rows + tip/nav footer, slash autocomplete above the composer, effort +radios under `/model`, token counter top-right, footer shortcut strip) and +re-skinned to the Cortex chrome. **No runtime code changes ship with this pack.** + +- Boards: [`index.md`](index.md) — 77 boards at 120×40, 31 of them also at 40×12 (108 PNGs). +- Grids: `txt//.txt` — the exact character grid of every board (diff a + `MockTerminal` capture against these). +- Renderer: `tools/render_lock_v2.py` + `tools/boards.py` (Python 3 + Pillow, IBM Plex Mono + fetched on first run). `python3 tools/render_lock_v2.py --index` regenerates everything. + +Brand rule: the only product name on any pixel or in this document is **Cortex** +(`Cortex CLI`, `Cortex Agent`, `Cortex Cloud`, `Cortex Mini 1`, `Cortex 1`, `Cortex Max 1`, +`Cortex Night`, `Cortex Day`). No competitor names, no provider names. + +--- + +## 1. Tokens + +```json +{ + "color": { + "bg": "#000000", + "text": "#F5F5F5", + "dim": "#6B7280", + "muted": "#4B5563", + "hairline": "#3A3A3A", + "hairline_hover": "#525252", + "panel": "#141414", + "bar_user": "#1C1C1C", + "bar_hover": "#1A1A1A", + "bar_selected": "#262626", + "accent": "#A78BFA", + "success": "#4ADE80", + "warning": "#FFC857", + "error": "#F87171" + }, + "rules": { + "accent": "ONLY on keyboard focus: the focused `>` caret, the focused row marker/label, typed slash-command / fuzzy-matched characters", + "success": "ONLY `✓` and diff `+N` / `+` lines", + "warning": "ONLY warnings: diagnostics `warn`, context counter ≥ 90 %", + "error": "ONLY errors: `×` titles, diagnostics `error`, diff `−N` / `-` lines, failed exit codes, exhausted quota bar", + "hairline": "always gray — never violet, never coloured", + "bg": "inky #000 — the TUI paints the whole alternate screen; no wash, no frame", + "retired": ["thinking gold #C9A95C", "mint #00F5D4", "cyan #7DD3FC", "violet wash #221A38 as a default bar"] + }, + "font": { + "family": "IBM Plex Mono", + "weights": ["Regular", "Bold", "Italic", "BoldItalic"], + "fallback_symbols": "DejaVu Sans Mono (♦ ▸ ▾ ▼ ● ○ ◦ ↵), Cascadia Mono (⠇ spinner)" + } +} +``` + +Board geometry used by the renderer (documentation only — the product renders 1 cell = 1 terminal cell): + +```json +{ "cell_px": [12, 26], "font_px": 20, "baseline_px": 20, "padding_px": 12, + "png_120x40": [1464, 1064], "png_40x12": [504, 336] } +``` + +--- + +## 2. Viewport geometry (alternate screen, always) + +```json +{ + "120x40": { + "header_row": 0, + "transcript_rows": [2, "composer_top - 2"], + "composer_rows": { "top": 35, "input": 36, "bottom": 37, "grows_upward_when_multiline": true }, + "blank_row": 38, + "footer_row": 39, + "left_margin_col": 1, + "right_edge_col_exclusive": 119, + "content_col": 3, + "bar_text_col": 5, + "modal": { "x": 12, "y": 1, "w": 96, "h": 38 } + }, + "40x12": { + "header_row": 0, + "transcript_rows": [1, 6], + "composer_rows": { "top": 7, "input": 8, "bottom": 9 }, + "blank_row": 10, + "footer_row": 11, + "modal": "full screen (0,0,40,12); tip line dropped; legend compressed" + }, + "compact_mode": { "left_margin_col": 0, "right_edge_col_exclusive": "cols", "timestamps": false, + "blank_rows_between_blocks": "only between turns" } +} +``` + +Header-left is intentionally empty on launch. It never paints a shell echo +(`~/…`, `> cortex`). Optional: the session name after `/rename`, dim. + +--- + +## 3. Component recipes + +Legend for recipes: `T` text `#F5F5F5` · `D` dim `#6B7280` · `M` muted `#4B5563` · +`H` hairline `#3A3A3A` · `V` accent `#A78BFA` · `G` success · `A` warning · `R` error. + +### 3.1 Header + +``` + 14K / 500K ← D, right-aligned to col 118 +``` +- Format `{used} / {window}` with K/M suffixes. `0 / 500K` on welcome. +- ≥ 90 % of the window: counter turns `A` and the transcript gets one line + `Context is 92% full — /compact summarizes the thread to free room.` (`A` + `T` + `D`). + +### 3.2 User prompt bar + +``` + > hey 12:49 AM ← bar #1C1C1C, cols 1..118 +``` +- `>` and text `T` (never violet — history is not focus). Timestamp `D`, right-aligned inside the bar. +- 12-hour clock `hh:mm AM`. Hidden when `Show timestamps = off`, in compact mode, and at < 80 cols. +- One blank row after the bar. `&` and `!` and `/btw` prefixes stay as typed. + +### 3.3 Thought line + +``` + ♦ Thought for 0.4s (collapsed — D, glyph D) + ♦ Thought for 3.2s ▾ (expanded: reasoning below, M, indented 2) + ⠇ Thinking · 3s (live — spinner T, label D; footer shows Esc:interrupt) +``` +Gold is retired. One blank row after (none in compact). + +### 3.4 Reply + +- Markdown through the existing renderer, `T` body, `**bold**` = Bold weight, bullets `•` / nested `◦`, + tasks `✓`(G) / `○`(D). First line carries the timestamp `D` right-aligned; the first paragraph + wraps `len(timestamp) + 2` columns short so it never touches it. +- Tables: gray plus-ASCII grid (`+---+`, `|` in `H`), header row Bold. +- Fences: `─ lang ─────` hairline (tag `D`), dim line-number gutter (`M`), Bold keywords, closing hairline. No background wash. +- Diff hunk: `@@` line `M`, old/new gutter `M`, context `T`, `-` lines `R`, `+` lines `G`, word-level colour only on the mutated token. + +### 3.5 Worked line + +``` + Worked for 4.6s ← D + Worked for 12s · 4.1k tokens ← after a stop; tokens optional +``` + +### 3.6 Opt-in banner (`Help improve Cortex`) + +``` + Help improve Cortex [Opt out] [Opt in] + Off by default. Opt in to let Cortex retain coding data — prompts, traces & metrics — to improve the product. + Change anytime in /settings → Privacy. + Read Terms and Privacy Policy. +``` +- Title Bold `T`; body `D`; `Terms` / `Privacy Policy` underlined `D`. +- `[Opt in]` Bold `T` (recommended), `[Opt out]` `D`. Hover: underline + `#1A1A1A` behind the button. + Keyboard focus: `V` label on `#262626`. Shown once per install above the composer; `▼` (D, centred) + sits between the transcript and the banner when more content is below. + +### 3.7 Composer (dual hairline, rounded) + +``` + ╭─ Agent ──────────────────────────────────────────────────────────────────────╮ + │ > ▏Plan, search, build anything │ + ╰──────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ +``` +- Box cols 1..118, hairline `H`. Corners `╭ ╮ ╰ ╯`. +- Mode chip in the **top-left** hairline: `Agent` in `D` (default, quiet) · `Plan · no edits` in `T` · + `Ask · read-only` in `T` · `Bash · runs in your shell` in `T`. +- Model chip in the **bottom-right** hairline, `D`: `{display name} ({effort})`, e.g. + `Cortex Mini 1 (medium)`, `Cortex Max 1 (high)`. Click → `/model`. +- `>` at col 3: `V` when the composer has keyboard focus, `D` otherwise (a modal, picker or prompt owns focus). + Bash mode swaps the sigil to `!`. +- Placeholder `D` at col 5; caret (2 px bar, `T`) sits **before** the first placeholder glyph. + Typing: text `T`, caret after the last glyph, blinks at the terminal's rate (`composer-typing` / `composer-typing-blink`). +- Slash command token in the composer is `V` (`/model`), arguments `T` (` Cortex Mini 1`); inline ghost completion `D` (`/mod` + `el`). +- Alt+Enter adds rows; the box grows upward, chips stay in place. +- Hover: every hairline of the box becomes `#525252`; nothing else changes. +- Placeholders per state: `Plan, search, build anything` (default) · `Describe a task for the agent` (agent entry) · + `Add a follow-up — Enter to queue` (turn running) · `Choose an option above` (prompt open) · + `Add a follow-up — held until quota resets` · `Reply, or ↑ to edit your last message` (after stop) · + `Ask about the codebase — read-only` (Ask) · `Describe what you want — Cortex drafts a plan first` (Plan). + +### 3.8 Footer shortcut strip + +``` + Shift+Tab:mode | Ctrl+x:shortcuts (idle) + Enter:send | Alt+Enter:newline | Shift+Tab:mode | Ctrl+x:shortcuts (text typed) +``` +- Key Bold `T`, `:label` `D`, separators `D`. Contextual sets: + +```json +{ + "idle": [["Shift+Tab","mode"],["Ctrl+x","shortcuts"]], + "typed": [["Enter","send"],["Alt+Enter","newline"],["Shift+Tab","mode"],["Ctrl+x","shortcuts"]], + "typed_narrow": [["Enter","send"],["Ctrl+x","shortcuts"]], + "running": [["Esc","interrupt"],["Enter","queue follow-up"],["Ctrl+x","shortcuts"]], + "queue": [["Enter","queue"],["↑","edit queued"],["Ctrl+c","stop"],["Ctrl+x","shortcuts"]], + "model_list": [["Enter","choose"],["Tab","effort"],["↑↓","select"],["Esc","close"]], + "effort": [["Enter","apply"],["Tab","back to models"],["Esc","close"]], + "approval": [["↑↓","select"],["Enter","confirm"],["e","edit command"],["Esc","cancel"]], + "mcp": [["Enter","details"],["r","reconnect"],["a","add server"],["Esc","close"]], + "plugins": [["Enter","toggle"],["i","install"],["u","update"],["Esc","close"]], + "resume": [["Enter","resume"],["f","favorite"],["d","delete"],["Esc","close"]], + "bash": [["Enter","run"],["Esc","leave bash"],["Ctrl+x","shortcuts"]], + "unavailable": [["Enter","retry"],["Ctrl+x","shortcuts"]] +} +``` +- Hover on a chunk: key underlined, whole chunk `T` on `#1A1A1A`. + +### 3.9 Menu rows (slash palette · model list · effort radios · pickers) + +Stacked directly above the composer's top hairline, newest/first row on top, full-width bars (cols 1..118). + +``` + > /model Choose the model for this session ← focused: bar #262626, `>` V, name T, desc D + /mode Switch between Agent, Plan and Ask ← plain + /permissions Set the approval policy for edits and commands + /plan Draft a plan before writing any code ← hover: bar #1A1A1A, no violet + … 87 more — keep typing to filter ← trailer M +``` +- Marker col 3, name col 5, description at `5 + name_w` where `name_w ≥ longest name + 2`. +- Fuzzy matching highlights **matched characters** in `V` (`/model`, `/mcp-rel**o**a**d**`, `/custo**m**-c**o**mman**d**s`). +- Slash palette shows 8 rows at 120×40 (3 at 40×12) + the `… N more` trailer. +- `/model` rows: `Cortex Mini 1 · Fast default for everyday coding · current`, `Cortex 1 · Deeper reasoning for hard changes`, + `Cortex Max 1 · Longest context — bills by token instead of per request · MAX`. +- Effort rows (Tab from the model list, or Enter on a model): `High Effort`, `Medium Effort`, `Low Effort` with descriptions + `Deepest reasoning — best for hard, multi-file changes` · `Balanced reasoning for everyday coding · default` · + `Fastest responses for quick edits and questions`. Composer reads `/model Cortex Mini 1` while the radios are open. +- Radio pickers (`/permissions`) lead with `●` (current, `T`) / `○` (`D`). Status pickers (`/mcp`, `/plugins`, `/jobs`) lead with + `✓` G · `⠇` spinner · `×` R · `○` D. +- A one-line title sits two rows above the first row: `MCP servers · 2 of 4 connected` (`T` + `D`). + +### 3.10 Inline radios (approval · confirm · question · sandbox deny) + +Rendered **inside the transcript**, directly under their context — never anchored to the composer. + +``` + ● Cortex wants to run + $ npm install ioredis && npm install -D ioredis-mock ← command on #1C1C1C + > 1 Yes, run once ← focused #262626, `>` V, number D + 2 Yes, always allow npm install in this project + 3 Edit command + 4 No — tell Cortex what to do instead +``` +Composer loses focus (`>` `D`, placeholder `Choose an option above`). Hover row `#1A1A1A`. + +### 3.11 Settings modal (F2 · `/settings`) + +``` + ╭─ Settings ──────────────────────────────────────────────────────────────── [x] ─╮ + │ / to search │ + │ ───────────────────────────────────────────────────────────────────────────────│ + │ │ + │ Appearance ──────────────────────────────────────────────────────────────── │ + │ ▸ Compact mode off │ ← focused: bar, ▸ V, label Bold + │ ▸ Default screen mode Fullscreen > │ ← `>` = submenu + │ ▸ Show timestamps on │ + │ … │ + │ Tip · Ask Cortex: "change theme to Cortex Day" or "what does compact mode do?" │ + │ ↑/↓/j/k nav | g/G top/btm | Space toggle | Enter toggle | → expand | / search | d reset │ + │ F2/Esc close │ + ╰─────────────────────────────────────────────────────────────────────────────────╯ +``` +- Values: `on` `T`, `off` `D`, numbers `T`, submenu value `T` + ` >` `D`. Category header `D` + hairline to the right edge. +- Search: `/` focuses the field (`/ ` turns `V`), rows filter live, matched substring `V`, categories without matches disappear. +- Submenu (→ / Enter on a `>` row): breadcrumb `Appearance › Theme`, radio rows `●`/`○`, focused label `V` Bold; legend `Enter select | ← back`. +- Row hover: `#1A1A1A` bar, marker stays `D`. Focus + hover: focus wins. +- Categories and rows (see §7 for which rows are new): + +```json +{ + "Appearance": [["Compact mode","off"],["Default screen mode","Fullscreen >"],["Show timestamps","on"],["Show thinking blocks","on"],["Group tool calls","on"],["Collapsed edit blocks","off"],["Line numbers","on"],["Word wrap","on"],["Syntax highlight","on"],["Animations","on"],["Theme","Cortex Night >"]], + "Mouse": [["Mouse capture","on"],["Scroll lines","3"],["Invert scroll","off"],["Copy on select","off"]], + "Behavior": [["Auto approve","off"],["Sandbox mode","on"],["Streaming","on"],["Auto scroll","on"],["Sound","off"],["Notifications","off"]], + "AI": [["Thinking mode","on"],["Context aware","on"],["Debug mode","off"]], + "Git": [["Co-author","on"],["Auto commit","off"],["Sign commits","off"]], + "Cloud": [["Cloud sync","off"],["Auto save","on"],["Session history","on"]], + "Privacy": [["Telemetry","off"],["Analytics","off"]], + "Theme submenu": [["Cortex Night","Default inky chrome · violet on focus only","current"],["Cortex Day","Light chrome for bright rooms"],["Ocean Dark","Deep blue and cyan accents"],["Monokai","Classic code-editor colors"]] +} +``` + +### 3.12 Shortcuts overlay (Ctrl+x) + +Same modal chrome, 84×14, two columns of `key` (`T`, padded) + `label` (`D`); a hairline, then +`Docs & guides: cortex.foundation/docs · Cortex CLI v0.1.7` (`M`); legend `Ctrl+x/Esc close`. + +### 3.13 Tool tiles + +``` + ● Shell $ cargo test -p cortex-tui · ✓ 0 · 41s ● D · tool Bold T · arg T · meta D · ✓ G / × R + ● Read src/cortex-tui/src/composer.rs · 212 lines + ● Grep "alternate_screen" in src/ · 6 hits in 4 files + ● Edit src/cortex-tui/src/composer.rs · +12 −3 +N G · −N R · `▸ show diff` D when collapsed + ⠇ Shell $ cargo test -p cortex-tui · running · 8s live: spinner T, output lines D indented 2 + ▾ 3 tool calls Read ×2 · Grep ×1 grouped (Group tool calls = on); ▸ when collapsed + ● Diagnostics src/…/composer.rs · 2 + error E0308 mismatched types — … composer.rs:42:9 error R · warn A · location D + × Stopped R, then `Worked for 12s · 4.1k tokens` D + × The coding service is temporarily unavailable R, then `Try again in a moment — …` D + ↑ Handed off to Cortex Cloud T; `agent` / `branch` / `follow` keys D, values T +``` + +### 3.14 Usage / quota + +`Usage · Cortex Pro · renews Oct 1` then rows `label (T) · used/total (D) · 40-cell bar (filled `█` D, empty `█` #262626) · pct (D)`. +Exhausted: `× Agent quota exhausted` R, bar filled R, composer placeholder `Add a follow-up — held until quota resets`. +Narrow: no bars, `used / total pct%`. + +### 3.15 Login (`cortex login`, inline — no alternate screen) + +`Welcome to Cortex CLI!` Bold → `How would you like to log in?` → radios `1 Continue with browser · Opens cortex.foundation/cli/auth`, +`2 Paste an API key · Enter your key to authenticate` → waiting (`⠇ Waiting for browser authentication…`, `Your code WXYZ-1234` Bold) +→ `✓ Signed in as …` (✓ G) or `× Sign-in didn't complete` (R) + product copy. + +--- + +## 4. Hover vs keyboard focus + +```json +{ + "row (settings, slash, model, effort, radios, pickers)": { + "idle": { "bar": "none", "marker": "none / ▸ dim", "label": "text" }, + "hover": { "bar": "#1A1A1A", "marker": "unchanged", "label": "text", "accent": false }, + "focus": { "bar": "#262626", "marker": "> or ▸ in #A78BFA", "label": "text (Bold in settings)", "accent": true }, + "focus+hover": "focus wins" + }, + "composer": { + "idle": { "hairline": "#3A3A3A", "caret_sigil": "#6B7280" }, + "hover": { "hairline": "#525252", "caret_sigil": "unchanged" }, + "focus": { "hairline": "#3A3A3A", "caret_sigil": "#A78BFA", "caret": "2 px bar, blinking" } + }, + "footer chunk / banner button / chip": { + "hover": { "underline": true, "text": "#F5F5F5", "bar": "#1A1A1A" }, + "focus": { "text": "#A78BFA", "bar": "#262626" } + }, + "typed slash match": { "accent": true, "note": "matched characters in the palette and the command token in the composer" } +} +``` + +--- + +## 5. Welcome copy + +```json +{ + "cortex": { + "line1": "Welcome to **Cortex**, the coding agent CLI", + "line2": "v0.1.7 · / commands · @ files · ! shell · & cloud", + "placeholder": "Plan, search, build anything", + "header": "0 / 500K" + }, + "agent": { + "line1": "Welcome to **Cortex Agent** — describe a task, it does the work", + "line2": "v0.1.7 · / commands · @ files · ! shell · & cloud", + "placeholder": "Describe a task for the agent", + "header": "0 / 500K" + }, + "narrow": { "line1": "Welcome to **Cortex**", "line2": "v0.1.7 · / commands · @ files" }, + "first_run_panel": { + "bg": "#141414", + "title": "A few tips to get the most out of this tool:", + "tips": [ + "1. Use /model to switch between models and adjust reasoning effort.", + "2. Add @ files to give Cortex the right context.", + "3. Press Shift+Tab anytime to cycle Agent / Plan / Ask.", + "4. Ctrl+x lists every shortcut · F2 opens settings." + ] + }, + "never_paint": ["~/…", "> cortex", "$ prompt echoes", "ASCII logo"] +} +``` + +--- + +## 6. Reference → Cortex rename table + +| Reference element | Cortex | +|---|---| +| Product / assistant name in replies | **Cortex** | +| Model chip ` (high)` | `Cortex Mini 1 (medium)` · `Cortex 1 (high)` · `Cortex Max 1 (high)` | +| `/model ` argument | `/model Cortex Mini 1` | +| Themes ` Night` / ` Day` | `Cortex Night` / `Cortex Day` (config ids `dark` / `light` unchanged) | +| Settings tip `Ask : "change theme to …"` | `Ask Cortex: "change theme to Cortex Day" or "what does compact mode do?"` | +| `Help improve ` / ` to retain coding data` | `Help improve Cortex` / `let Cortex retain coding data` | +| `/resume-`, `/import-` | not carried over — Cortex has `/resume` (own sessions) only | +| `/compact-mode`, `/vim-mode` | `/compact` (existing); vim keys are a navigation style, no slash command | +| "Thought for Xs" · "Worked for Xs" | kept verbatim (new strings for Cortex) | +| `Shift+Tab:mode | Ctrl+x:shortcuts` | kept verbatim | +| Effort `High Effort / Medium Effort / Low Effort` | kept; descriptions rewritten (see §3.9) | +| Caret `|` before placeholder | 2 px bar caret before the placeholder | +| `~` cwd in the header | removed (header-left empty) | + +--- + +## 7. State checklist + +| Requested state | Board(s) | +|---|---| +| welcome-cortex / welcome-agent / session-empty | `welcome-cortex`, `welcome-agent`, `session-empty` (+ `first-run-tips`) | +| session-user-bars / thought / assistant / worked / optin | `session-user-bars`, `session-thought`, `session-thought-expanded`, `session-thinking-live`, `session-assistant`, `session-worked`, `session-optin`, `session-optin-hover` | +| composer-empty / typing (+blink) / hover | `composer-empty`, `composer-typing`, `composer-typing-blink`, `composer-hover`, `composer-multiline` | +| footer-shortcuts / tokens-topright | `footer-shortcuts`, `footer-hover`, `tokens-topright`, `tokens-topright-warn` | +| slash-palette / slash-model-typed | `slash-palette`, `slash-model-typed` | +| model-effort-low·medium·high / model-list-hover | `model-list`, `model-list-hover`, `model-effort-high`, `model-effort-medium`, `model-effort-low`, `model-effort-hover` | +| settings-appearance / mouse / row-hover / search / theme-submenu | `settings-appearance`, `settings-mouse`, `settings-row-hover`, `settings-search`, `settings-theme-submenu` | +| mode chips (Shift+Tab) | `mode-agent`, `mode-plan`, `mode-ask`, `mode-bash` | +| permissions / mcp / plugins / usage-quota / sandbox / cloud | `permission-prompt`, `permission-prompt-hover`, `permissions-picker`, `mcp-servers`, `mcp-drop`, `plugins`, `usage`, `quota-exhausted`, `sandbox`, `sandbox-deny`, `cloud-handoff` | +| diagnostics red/amber · interrupt/stopped | `diagnostics`, `interrupt-stopped`, `error-unavailable` | +| markdown table · diff hunk · code fence | `md-table`, `diff-hunk`, `edit-collapsed`, `code-fence`, `tool-tiles`, `tool-tiles-collapsed`, `shell-running` | +| login / first-run | `login`, `login-waiting`, `login-success`, `login-error`, `first-run-tips` | +| compact chat (ref 5) | `compact-chat` | +| other product surfaces (not in the brief, kept complete) | `shortcuts-overlay`, `resume-picker`, `clear-confirm`, `plan-confirm`, `queue`, `files-picker`, `jobs`, `skills`, `todos`, `question`, `sudo`, `config-tree`, `btw` | + +Narrow (40×12) set: `welcome-cortex`, `welcome-agent`, `first-run-tips`, `session-empty`, `session-user-bars`, +`session-thinking-live`, `session-assistant`, `session-optin`, `composer-empty`, `composer-typing`, `composer-hover`, +`tokens-topright`, `compact-chat`, `slash-palette`, `slash-model-typed`, `model-list`, `model-effort-high`, +`settings-appearance`, `settings-mouse`, `settings-row-hover`, `settings-theme-submenu`, `mode-plan`, `mode-ask`, +`permission-prompt`, `mcp-servers`, `usage`, `diagnostics`, `interrupt-stopped`, `diff-hunk`, `login`, `shortcuts-overlay`. + +--- + +## 8. Keybinding contract (as drawn) + +```json +{ + "Shift+Tab": "cycle Agent → Plan → Ask (chip in the composer top hairline)", + "Ctrl+x": "shortcuts overlay (was: clear follow-up queue — see flag F2)", + "F2": "settings modal (also /settings)", + "Esc": "interrupt the turn · close modal/picker · leave bash mode", + "Enter": "send · confirm · queue a follow-up while running", + "Alt+Enter": "newline in the composer", + "Tab": "complete slash command · jump between model list and effort radios", + "/": "slash palette (in the composer) · search (in Settings)", + "@": "file picker", "!": "bash mode", "&": "hand off to Cortex Cloud", + "↑": "edit last / edit queued", "Ctrl+c": "stop", "Ctrl+p": "command palette", "Ctrl+r": "search past sessions", + "settings": { "↑/↓/j/k": "nav", "g/G": "top/bottom", "Space/Enter": "toggle", "→": "expand submenu", "←": "back", "d": "reset row", "F2/Esc": "close" } +} +``` + +--- + +## 9. Flags for Mathis (states I could not invent safely) + +```json +[ + {"id":"F1","area":"welcome-agent","flag":"There is no `agent` binary or alias in `src/cortex-cli/Cargo.toml` (only `[[bin]] name = \"Cortex\"`, clap name `cortex`). The board assumes an `agent` entrypoint that launches the same TUI; the only differences drawn are the title line and the placeholder. Confirm the alias exists / is planned and the wording."}, + {"id":"F2","area":"footer","flag":"`Ctrl+x` is drawn as `shortcuts` (1:1 with the reference). In the current runtime `Ctrl+x` clears the follow-up queue. Proposal: queue items are removed with `↑` (edit) then Backspace/`d` on the queued row; the `queue` footer reads `Enter:queue | ↑:edit queued | Ctrl+c:stop | Ctrl+x:shortcuts`. Needs a decision."}, + {"id":"F3","area":"settings › Mouse","flag":"`Mouse capture`, `Scroll lines`, `Invert scroll`, `Copy on select` do not exist in `TuiConfig` (only `animations`, `alternate_screen`, `notifications`, `theme`). Drawn because the brief asks for a Mouse section; new config keys (`tui.mouse.*`) required."}, + {"id":"F4","area":"settings › Appearance","flag":"`Show thinking blocks`, `Group tool calls`, `Collapsed edit blocks`, `Show timestamps`, `Default screen mode` map to: SettingsSnapshot `Thinking Mode` / new / new / `Timestamps` / `tui.alternate_screen` (Fullscreen = true, Inline = false). Group/collapse are new behaviours."}, + {"id":"F5","area":"opt-in banner","flag":"No `Help improve Cortex` banner exists today (telemetry is a Privacy toggle, default off). Copy is a draft; `Terms` / `Privacy Policy` need real URLs and legal sign-off."}, + {"id":"F6","area":"strings","flag":"`♦ Thought for Xs` and `Worked for Xs` replace `Thinking` (gold) and `1m 12s · 8.2k tokens`. Gold `#C9A95C` is retired because amber-ish colour is reserved for warnings."}, + {"id":"F7","area":"themes","flag":"`dark` → `Cortex Night`, `light` → `Cortex Day` are display renames; keep the config ids. `Ocean Dark` / `Monokai` kept as-is. The theme modal description `Default dark theme with green accents` is wrong for this chrome and should read like the submenu board."}, + {"id":"F8","area":"effort order","flag":"Radios are drawn High → Medium → Low (reference order). The current horizontal radios read Low · Medium · High. Pick one; Tab from the model list lands on the current effort."}, + {"id":"F9","area":"timestamps","flag":"12-hour `hh:mm AM` clock as in the reference. Locale-aware 24 h is an open choice."}, + {"id":"F10","area":"plugins","flag":"Plugin names on the `plugins` board (`cortex-review`, `mermaid-preview`, `jira`) are illustrative; the real registry copy is unknown."}, + {"id":"F11","area":"header-left","flag":"Left side of row 0 is empty by design (no cwd echo). Optional session name after `/rename` — not drawn."}, + {"id":"F12","area":"scroll indicator","flag":"`▼` centred above the banner is drawn as in the reference when content continues below; exact trigger (scrolled up vs new output) is an implementation choice."} +] +``` + +--- + +## 10. Implementation notes for the runtime PR (not part of this delivery) + +- Chrome constants live in `src/cortex-core/src/style.rs`; add `bar_hover #1A1A1A`, retire gold, keep the rest of §1. +- Composer: model chip moves from the footer (`Cortex Mini 1 · Agent · 92% context`) into the bottom hairline; mode moves into the + top hairline; context moves to the header. The footer becomes the contextual shortcut strip (§3.8). +- Menus reuse the existing picker rows (`palette_home.rs`, `/model`, `/permissions`, `/mcp`) with the bar/marker recipe of §3.9; + approval / plan / clear / question prompts render inline (§3.10) using the same recipe. +- Settings hub (7 rows) is replaced by the categorised modal (§3.11); `/settings` and F2 open it. +- Every changed surface needs a unit test plus a headless snapshot; the `txt/` grids in this pack are the expected buffers. diff --git a/docs/media/tui-lock-v2/index.md b/docs/media/tui-lock-v2/index.md new file mode 100644 index 0000000..7e0987b --- /dev/null +++ b/docs/media/tui-lock-v2/index.md @@ -0,0 +1,111 @@ +# Cortex CLI — TUI lock v2 · board index + +Design-only pack for the full TUI redesign (reference layout language, Cortex chrome). +Every board exists at **120x40**; boards where density matters also at **40x12**. +Text dumps of each grid live in `txt//.txt`. Spec: [`SPEC.md`](SPEC.md). + +Regenerate: `python3 tools/render_lock_v2.py --index` (fetches IBM Plex Mono on first run). + +## A. Entry / welcome + +| Board | State | Wide | Narrow | +|---|---|---|---| +| `welcome-cortex` | Cold start `cortex` — clean welcome, alternate screen, no shell echoes | [120x40](120x40/welcome-cortex.png) | [40x12](40x12/welcome-cortex.png) | +| `welcome-agent` | Cold start `agent` — same chrome, agent wording + placeholder | [120x40](120x40/welcome-agent.png) | [40x12](40x12/welcome-agent.png) | +| `first-run-tips` | First launch — charcoal tips panel under the welcome | [120x40](120x40/first-run-tips.png) | [40x12](40x12/first-run-tips.png) | +| `session-empty` | Resumed / after first turn — header, composer, footer only | [120x40](120x40/session-empty.png) | [40x12](40x12/session-empty.png) | + +## B. Session + +| Board | State | Wide | Narrow | +|---|---|---|---| +| `session-user-bars` | Two user prompt bars + timestamps, Thought, reply, Worked, ▼ more, opt-in banner | [120x40](120x40/session-user-bars.png) | [40x12](40x12/session-user-bars.png) | +| `session-thought` | `♦ Thought for Xs` collapsed | [120x40](120x40/session-thought.png) | — | +| `session-thought-expanded` | Thought expanded (Show thinking blocks = on) | [120x40](120x40/session-thought-expanded.png) | — | +| `session-thinking-live` | Live `⠇ Thinking · 3s` while the turn runs | [120x40](120x40/session-thinking-live.png) | [40x12](40x12/session-thinking-live.png) | +| `session-assistant` | Plain reply with bold + bullets | [120x40](120x40/session-assistant.png) | [40x12](40x12/session-assistant.png) | +| `session-worked` | `Worked for Xs` after a reply | [120x40](120x40/session-worked.png) | — | +| `session-optin` | `Help improve Cortex` banner — Opt out | Opt in | [120x40](120x40/session-optin.png) | [40x12](40x12/session-optin.png) | +| `session-optin-hover` | Banner with the mouse over `[Opt in]` | [120x40](120x40/session-optin-hover.png) | — | +| `composer-empty` | Empty composer — caret before the placeholder, violet `>` | [120x40](120x40/composer-empty.png) | [40x12](40x12/composer-empty.png) | +| `composer-typing` | Mid-type, caret on | [120x40](120x40/composer-typing.png) | [40x12](40x12/composer-typing.png) | +| `composer-typing-blink` | Mid-type, caret off (blink phase) | [120x40](120x40/composer-typing-blink.png) | — | +| `composer-hover` | Mouse over the composer — hairline lifts to #525252 | [120x40](120x40/composer-hover.png) | [40x12](40x12/composer-hover.png) | +| `composer-multiline` | Alt+Enter newlines — box grows upward | [120x40](120x40/composer-multiline.png) | — | +| `footer-shortcuts` | Footer strip with text typed (4 hints) | [120x40](120x40/footer-shortcuts.png) | — | +| `footer-hover` | Mouse over `Ctrl+x:shortcuts` | [120x40](120x40/footer-hover.png) | — | +| `tokens-topright` | Token counter `142K / 500K` top-right | [120x40](120x40/tokens-topright.png) | [40x12](40x12/tokens-topright.png) | +| `tokens-topright-warn` | Counter ≥ 90 % — amber + /compact hint | [120x40](120x40/tokens-topright-warn.png) | — | +| `compact-chat` | Compact mode — edge-to-edge bars, no timestamps | [120x40](120x40/compact-chat.png) | [40x12](40x12/compact-chat.png) | + +## C. Slash + model + +| Board | State | Wide | Narrow | +|---|---|---|---| +| `slash-palette` | `/` palette — focused row + hover row + `… more` trailer | [120x40](120x40/slash-palette.png) | [40x12](40x12/slash-palette.png) | +| `slash-model-typed` | `/mod` typed — violet matched chars, ghost completion | [120x40](120x40/slash-model-typed.png) | [40x12](40x12/slash-model-typed.png) | +| `model-list` | `/model` — Cortex Mini 1 · Cortex 1 · Cortex Max 1 | [120x40](120x40/model-list.png) | [40x12](40x12/model-list.png) | +| `model-list-hover` | Model list with mouse over row 3 | [120x40](120x40/model-list-hover.png) | — | +| `model-effort-high` | Effort radios — High focused | [120x40](120x40/model-effort-high.png) | [40x12](40x12/model-effort-high.png) | +| `model-effort-medium` | Effort radios — Medium focused | [120x40](120x40/model-effort-medium.png) | — | +| `model-effort-low` | Effort radios — Low focused | [120x40](120x40/model-effort-low.png) | — | +| `model-effort-hover` | Effort radios — Medium focused, mouse over Low | [120x40](120x40/model-effort-hover.png) | — | + +## D. Settings + +| Board | State | Wide | Narrow | +|---|---|---|---| +| `settings-appearance` | Settings modal — Appearance, Compact mode focused | [120x40](120x40/settings-appearance.png) | [40x12](40x12/settings-appearance.png) | +| `settings-mouse` | Settings scrolled to Mouse / Behavior | [120x40](120x40/settings-mouse.png) | [40x12](40x12/settings-mouse.png) | +| `settings-row-hover` | Keyboard focus on Compact mode, mouse over Show timestamps | [120x40](120x40/settings-row-hover.png) | [40x12](40x12/settings-row-hover.png) | +| `settings-search` | `/ scro` search — filtered rows, violet match | [120x40](120x40/settings-search.png) | — | +| `settings-theme-submenu` | Theme submenu — Cortex Night / Cortex Day / Ocean Dark / Monokai | [120x40](120x40/settings-theme-submenu.png) | [40x12](40x12/settings-theme-submenu.png) | + +## E. Modes / tools / errors + +| Board | State | Wide | Narrow | +|---|---|---|---| +| `mode-agent` | Agent mode — dim chip in the composer border | [120x40](120x40/mode-agent.png) | — | +| `mode-plan` | Plan mode — `Plan · no edits` chip, plan reply | [120x40](120x40/mode-plan.png) | [40x12](40x12/mode-plan.png) | +| `mode-ask` | Ask mode — `Ask · read-only` chip | [120x40](120x40/mode-ask.png) | [40x12](40x12/mode-ask.png) | +| `mode-bash` | Bash mode (`!`) — chip + `!` sigil | [120x40](120x40/mode-bash.png) | — | +| `permission-prompt` | Exec approval — command on gray, numbered radios | [120x40](120x40/permission-prompt.png) | [40x12](40x12/permission-prompt.png) | +| `permission-prompt-hover` | Exec approval with mouse over option 2 | [120x40](120x40/permission-prompt-hover.png) | — | +| `permissions-picker` | `/permissions` — Smart / Read-only / Full access | [120x40](120x40/permissions-picker.png) | — | +| `mcp-servers` | `/mcp` — connected ✓, authenticating, failed × | [120x40](120x40/mcp-servers.png) | [40x12](40x12/mcp-servers.png) | +| `mcp-drop` | MCP server dropped mid-turn (error red) | [120x40](120x40/mcp-drop.png) | — | +| `plugins` | `/plugins` — enabled / disabled rows | [120x40](120x40/plugins.png) | — | +| `usage` | `/usage` — plan bars | [120x40](120x40/usage.png) | [40x12](40x12/usage.png) | +| `quota-exhausted` | Agent quota exhausted — red title, held composer | [120x40](120x40/quota-exhausted.png) | — | +| `sandbox` | `/sandbox` — filesystem / network / escalation | [120x40](120x40/sandbox.png) | — | +| `sandbox-deny` | Sandbox blocked a command — red title, radios | [120x40](120x40/sandbox-deny.png) | — | +| `cloud-handoff` | `&` handoff to Cortex Cloud | [120x40](120x40/cloud-handoff.png) | — | +| `diagnostics` | Diagnostics tile — error red, warn amber | [120x40](120x40/diagnostics.png) | [40x12](40x12/diagnostics.png) | +| `interrupt-stopped` | Esc / Ctrl+c — `× Stopped` | [120x40](120x40/interrupt-stopped.png) | [40x12](40x12/interrupt-stopped.png) | +| `error-unavailable` | API down — product-facing error | [120x40](120x40/error-unavailable.png) | — | +| `tool-tiles` | Grouped tool calls expanded — Read / Grep / Shell | [120x40](120x40/tool-tiles.png) | — | +| `tool-tiles-collapsed` | Grouped tool calls collapsed | [120x40](120x40/tool-tiles-collapsed.png) | — | +| `shell-running` | Live Shell tile with output | [120x40](120x40/shell-running.png) | — | +| `diff-hunk` | Edit tile + unified hunk — green +, red − | [120x40](120x40/diff-hunk.png) | [40x12](40x12/diff-hunk.png) | +| `edit-collapsed` | Collapsed edit blocks (setting on) | [120x40](120x40/edit-collapsed.png) | — | +| `md-table` | Markdown table — gray plus-ASCII grid | [120x40](120x40/md-table.png) | — | +| `code-fence` | Fenced code — language tag hairline, gutter, bold keywords | [120x40](120x40/code-fence.png) | — | +| `login` | `cortex login` — inline picker | [120x40](120x40/login.png) | [40x12](40x12/login.png) | +| `login-waiting` | Waiting for browser + device code | [120x40](120x40/login-waiting.png) | — | +| `login-success` | `✓ Signed in` | [120x40](120x40/login-success.png) | — | +| `login-error` | Sign-in failed — product copy | [120x40](120x40/login-error.png) | — | +| `shortcuts-overlay` | Ctrl+x shortcuts overlay | [120x40](120x40/shortcuts-overlay.png) | [40x12](40x12/shortcuts-overlay.png) | +| `resume-picker` | `/resume` — search field + session rows | [120x40](120x40/resume-picker.png) | — | +| `clear-confirm` | `/clear` confirm radios | [120x40](120x40/clear-confirm.png) | — | +| `plan-confirm` | `Implement this plan?` radios | [120x40](120x40/plan-confirm.png) | — | +| `queue` | Follow-up queue while a step runs | [120x40](120x40/queue.png) | — | +| `files-picker` | `@` file picker — violet matched chars, hover row | [120x40](120x40/files-picker.png) | — | +| `jobs` | `/jobs` — cloud agent, subagent, queued | [120x40](120x40/jobs.png) | — | +| `skills` | `/skills` — search field + skill rows | [120x40](120x40/skills.png) | — | +| `todos` | Working 2/5 checklist — ✓ done · › current · ○ pending | [120x40](120x40/todos.png) | — | +| `question` | Clarifying question radios | [120x40](120x40/question.png) | — | +| `sudo` | Elevated Shell — password row on gray | [120x40](120x40/sudo.png) | — | +| `config-tree` | `/config` read-only key tree | [120x40](120x40/config-tree.png) | — | +| `btw` | `/btw` side note during a running turn | [120x40](120x40/btw.png) | — | + +**77** boards at 120x40 · **31** at 40x12 · 108 PNGs. diff --git a/docs/media/tui-lock-v2/tools/.gitignore b/docs/media/tui-lock-v2/tools/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/docs/media/tui-lock-v2/tools/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/docs/media/tui-lock-v2/tools/boards.py b/docs/media/tui-lock-v2/tools/boards.py new file mode 100644 index 0000000..12f7efd --- /dev/null +++ b/docs/media/tui-lock-v2/tools/boards.py @@ -0,0 +1,1838 @@ +"""Board recipes for the Cortex CLI TUI lock v2. + +Every board is a function ``fn(screen, ctx)`` that paints a full viewport +(alternate screen, default launch). The shared chrome helpers at the top are +the component recipes documented in ``../SPEC.md`` — keep them in sync. + +Layout language (from the reference boards, re-skinned to the Cortex chrome): + +* row 0 header — session name (optional, dim) left · token counter right +* rows 2.. transcript — user prompt bars, ``♦ Thought for Xs``, replies, + ``Worked for Xs``, tool tiles, panels +* rows H-5..H-3 composer — rounded hairline box, mode chip in the top border + (left), model chip in the bottom border (right) +* row H-1 footer — shortcut strip ``Key:label | Key:label`` + +Focus vs hover: keyboard focus = ``#262626`` bar + violet marker/caret; +mouse hover = ``#161616`` bar (or ``#525252`` hairline) and *no* violet. +""" + +from __future__ import annotations + +import textwrap +from dataclasses import dataclass + +from render_lock_v2 import ( + AMBER, + BAR_HOV, + BAR_SEL, + BAR_USER, + BG, + DIM, + GREEN, + HAIR, + HAIR_HI, + MUTED, + PANEL, + RED, + S, + S_ACC, + S_BOLD, + S_DIM, + S_ERR, + S_HAIR, + S_MUTED, + S_OK, + S_WARN, + TEXT, + VIOLET, + Cell, + Screen, + St, + clip, +) + +VERSION = "0.1.7" +MODEL_CHIP = "Cortex Mini 1 (medium)" +PLACEHOLDER = "Plan, search, build anything" +TOKENS = "14K / 500K" + + +@dataclass +class Ctx: + cols: int + rows: int + narrow: bool + + @property + def x0(self) -> int: + return 1 + + @property + def x1(self) -> int: # exclusive right edge of bars / boxes + return self.cols - 1 + + @property + def inner_w(self) -> int: + return self.x1 - self.x0 + + +# --------------------------------------------------------------------------- # +# Rich text helpers +# --------------------------------------------------------------------------- # + + +def parse_markup(text: str, base: St = S) -> list: + """``**bold**`` → bold spans, ``__u__`` → underline spans, `` `code` `` → text.""" + parts, buf, i = [], "", 0 + bold, under = False, False + while i < len(text): + if text.startswith("**", i): + if buf: + parts.append((buf, base(b=bold, u=under))) + buf = "" + bold = not bold + i += 2 + elif text.startswith("__", i): + if buf: + parts.append((buf, base(b=bold, u=under))) + buf = "" + under = not under + i += 2 + else: + buf += text[i] + i += 1 + if buf: + parts.append((buf, base(b=bold, u=under))) + return parts + + +def wrap_markup(text: str, width: int, base: St = S) -> list: + """Greedy word-wrap of a markup string; returns a list of span lists.""" + words = [] # (word, style) + for chunk, st in parse_markup(text, base): + pieces = chunk.split(" ") + for k, piece in enumerate(pieces): + if k > 0: + words.append((" ", st)) + if piece: + words.append((piece, st)) + lines, cur, cur_len = [], [], 0 + for word, st in words: + if word == " ": + if cur: + cur.append((word, st)) + cur_len += 1 + continue + if cur_len + len(word) > width and cur: + while cur and cur[-1][0] == " ": + cur.pop() + lines.append(cur) + cur, cur_len = [], 0 + cur.append((word, st)) + cur_len += len(word) + while cur and cur[-1][0] == " ": + cur.pop() + if cur: + lines.append(cur) + return lines or [[]] + + +# --------------------------------------------------------------------------- # +# Chrome recipes +# --------------------------------------------------------------------------- # + + +def header(s: Screen, c: Ctx, tokens: str = TOKENS, left: str | None = None, warn: bool = False): + if left: + s.put(c.x0, 0, clip(left, c.inner_w - len(tokens) - 2), S_DIM) + s.right(0, tokens, c.x1, S_WARN if warn else S_DIM) + + +FOOTER_IDLE = [("Shift+Tab", "mode"), ("Ctrl+x", "shortcuts")] +FOOTER_TYPED = [("Enter", "send"), ("Alt+Enter", "newline"), ("Shift+Tab", "mode"), ("Ctrl+x", "shortcuts")] +FOOTER_TYPED_NARROW = [("Enter", "send"), ("Ctrl+x", "shortcuts")] + + +def footer(s: Screen, c: Ctx, hints=None, hover: str | None = None, y: int | None = None): + hints = hints or FOOTER_IDLE + y = c.rows - 1 if y is None else y + x = c.x0 + for k, (key, label) in enumerate(hints): + if k: + x = s.put(x, y, " | " if not c.narrow else " | ", S_DIM) + chunk = f"{key}:{label}" + if x + len(chunk) > c.x1: + break + if hover == key: + s.fill(x - 1, y, x + len(chunk) + 1, BAR_HOV) + x = s.put(x, y, key, St(fg=TEXT, b=True, u=True, bg=BAR_HOV)) + x = s.put(x, y, ":" + label, St(fg=TEXT, bg=BAR_HOV)) + else: + x = s.put(x, y, key, St(fg=TEXT, b=True)) + x = s.put(x, y, ":" + label, S_DIM) + + +MODE_CHIPS = { + "Agent": (" Agent ", S_DIM), + "Plan": (" Plan · no edits ", S), + "Ask": (" Ask · read-only ", S), + "Bash": (" Bash · runs in your shell ", S), +} + + +def composer( + s: Screen, + c: Ctx, + content=None, + placeholder: str = PLACEHOLDER, + model: str = MODEL_CHIP, + mode: str = "Agent", + focused: bool = True, + hover: bool = False, + caret: bool = True, + extra_lines: int = 0, + sigil: str = ">", + y_bottom: int | None = None, +) -> int: + """Paint the composer box; returns the row of its top border.""" + hair = HAIR_HI if hover else HAIR + bottom = (c.rows - 3) if y_bottom is None else y_bottom + inner_rows = 1 + extra_lines + top = bottom - inner_rows - 1 + s.box(c.x0, top, c.inner_w, inner_rows + 2, fg=hair) + # mode chip, top-left, inside the hairline + chip, chip_st = MODE_CHIPS.get(mode, (f" {mode} ", S)) + if c.narrow and mode == "Agent": + chip = " Agent " + s.put(c.x0 + 2, top, clip(chip, c.inner_w - 6), chip_st) + # model chip, bottom-right, inside the hairline + m = f" {model} " + s.right(bottom, m, c.x1 - 2, S_DIM) + # prompt + y = top + 1 + s.put(c.x0 + 2, y, sigil, S_ACC if focused else S_DIM) + tx = c.x0 + 4 + max_x = c.x1 - 2 + if content: + x = s.spans(tx, y, content, max_x=max_x) + if caret: + s.caret = (min(x, max_x), y) + else: + s.put(tx, y, clip(placeholder, max_x - tx), S_DIM) + if caret: + s.caret = (tx, y) + return top + + +def scroll_indicator(s: Screen, c: Ctx, y: int): + s.center(y, "▼", c.x0, c.x1, S_DIM) + + +def optin_banner(s: Screen, c: Ctx, y: int, hover: str | None = None, focus: str | None = None) -> int: + """`Help improve Cortex` block above the composer. Returns rows used.""" + s.put(c.x0, y, "Help improve Cortex", S_BOLD) + out_st = S_DIM + in_st = S_BOLD + if hover == "in": + in_st = St(fg=TEXT, b=True, u=True, bg=BAR_HOV) + if hover == "out": + out_st = St(fg=TEXT, u=True, bg=BAR_HOV) + if focus == "in": + in_st = St(fg=VIOLET, b=True, bg=BAR_SEL) + if focus == "out": + out_st = St(fg=VIOLET, b=True, bg=BAR_SEL) + s.right_spans(0 + y, [("[Opt out]", out_st), (" ", S), ("[Opt in]", in_st)], c.x1) + if c.narrow: + s.put(c.x0, y + 1, "Off by default · anytime in /settings", S_DIM) + s.spans(c.x0, y + 2, [("Read ", S_DIM), ("Terms", S_DIM(u=True)), (" and ", S_DIM), ("Privacy Policy", S_DIM(u=True)), (".", S_DIM)]) + return 3 + s.put( + c.x0, + y + 1, + clip("Off by default. Opt in to let Cortex retain coding data — prompts, traces & metrics — to improve the product.", c.inner_w), + S_DIM, + ) + s.put(c.x0, y + 2, "Change anytime in /settings → Privacy.", S_DIM) + s.spans(c.x0, y + 3, [("Read ", S_DIM), ("Terms", S_DIM(u=True)), (" and ", S_DIM), ("Privacy Policy", S_DIM(u=True)), (".", S_DIM)]) + return 4 + + +class Flow: + """Sequential transcript painter. ``compact`` drops margins + timestamps.""" + + def __init__(self, s: Screen, c: Ctx, y: int = 2, limit: int | None = None, compact: bool = False): + self.s, self.c, self.y = s, c, y + self.limit = limit if limit is not None else c.rows - 6 + self.compact = compact + self.x0 = 0 if compact else c.x0 + self.x1 = c.cols if compact else c.x1 + self.tx = self.x0 + 2 # content column (`>`/`♦` column) + + def ok(self, n: int = 1) -> bool: + return self.y + n <= self.limit + + def blank(self, n: int = 1): + self.y += n + + def stamp(self, y: int, time: str | None): + if time and not self.compact and not self.c.narrow: + self.s.right(y, time, self.x1 - 1, S_DIM) + + def user(self, text: str, time: str | None = None, sigil: str = ">"): + if not self.ok(): + return + self.s.fill(self.x0, self.y, self.x1, BAR_USER) + bar = St(fg=TEXT, bg=BAR_USER) + self.s.put(self.tx, self.y, sigil, bar) + room = self.x1 - 1 - (self.tx + 2) - (len(time) + 2 if (time and not self.compact and not self.c.narrow) else 0) + self.s.put(self.tx + 2, self.y, clip(text, room), bar) + self.stamp(self.y, time) + self.y += 1 + if not self.compact: + self.y += 1 + + def thought(self, label: str = "Thought for 0.4s", live: bool = False): + if not self.ok(): + return + glyph = "⠇" if live else "♦" + self.s.spans(self.tx, self.y, [(glyph, S_DIM), (" ", S), (label, S_DIM)]) + self.y += 1 + if not self.compact: + self.y += 1 + + def thought_body(self, lines): + for ln in lines: + if not self.ok(): + return + self.s.put(self.tx + 2, self.y, clip(ln, self.x1 - 1 - self.tx - 2), S_MUTED) + self.y += 1 + if not self.compact: + self.y += 1 + + def reply(self, paragraphs, time: str | None = None): + """paragraphs: list of markup strings ('' = blank line, '• ' bullets).""" + width = self.x1 - 1 - self.tx + first = True + for para in paragraphs: + if para == "": + self.y += 1 + continue + # the first paragraph shares its row with the timestamp — keep clear of it + w = width - (len(time) + 2) if (first and time and not self.compact and not self.c.narrow) else width + for line in wrap_markup(para, w): + if not self.ok(): + return + self.s.spans(self.tx, self.y, line, max_x=self.x1 - 1) + if first: + self.stamp(self.y, time) + first = False + self.y += 1 + if not self.compact: + self.y += 1 + + def worked(self, label: str = "Worked for 1.8s"): + if not self.ok(): + return + self.s.put(self.tx, self.y, label, S_DIM) + self.y += 1 + if not self.compact: + self.y += 1 + + def line(self, parts, indent: int = 0): + if not self.ok(): + return + self.s.spans(self.tx + indent, self.y, parts, max_x=self.x1 - 1) + self.y += 1 + + def dim(self, text: str, indent: int = 0): + self.line([(clip(text, self.x1 - 1 - self.tx - indent), S_DIM)], indent) + + def tile(self, tool: str, arg: str, meta: str = "", glyph: str = "●", glyph_st: St = S_DIM, meta_parts=None): + if not self.ok(): + return + x = self.s.spans(self.tx, self.y, [(glyph, glyph_st), (" ", S), (tool, S_BOLD), (" ", S)]) + room = self.x1 - 1 - x - (len(meta) + 3 if meta else 0) + x = self.s.put(x, self.y, clip(arg, room), S) + if meta_parts: + self.s.spans(x, self.y, [(" · ", S_DIM)] + meta_parts, max_x=self.x1 - 1) + elif meta: + self.s.spans(x, self.y, [(" · ", S_DIM), (meta, S_DIM)], max_x=self.x1 - 1) + self.y += 1 + + def command(self, cmd: str): + """A command row on the user-turn gray (approval prompts, sudo).""" + if not self.ok(): + return + self.s.fill(self.x0, self.y, self.x1, BAR_USER) + self.s.put(self.tx, self.y, clip(cmd, self.x1 - 1 - self.tx), St(fg=TEXT, bg=BAR_USER)) + self.y += 1 + + def options(self, opts, focused: int = 0, hover: int | None = None, numbered: bool = True): + """Inline numbered radios: focused = `#262626` bar + violet `>`; hover = `#1A1A1A` bar.""" + for i, label in enumerate(opts): + if not self.ok(): + return + is_focus = i == focused + is_hover = hover is not None and hover == i and not is_focus + bg = BAR_SEL if is_focus else (BAR_HOV if is_hover else None) + if bg: + self.s.fill(self.x0, self.y, self.x1, bg) + self.s.put(self.tx, self.y, ">" if is_focus else " ", St(fg=VIOLET, bg=bg) if is_focus else S) + x = self.tx + 2 + if numbered: + x = self.s.put(x, self.y, f"{i + 1} ", St(fg=DIM, bg=bg) if bg else S_DIM) + self.s.put(x, self.y, clip(label, self.x1 - 1 - x), St(fg=TEXT, bg=bg) if bg else S) + self.y += 1 + + +def menu(s: Screen, c: Ctx, y_bottom: int, rows, focused: int = 0, hover: int | None = None, name_w: int = 18, trailer: str | None = None) -> int: + """Rows stacked directly above ``y_bottom`` (the composer top). Returns top row. + + rows: list of (name_parts, desc) — name_parts is a span list.""" + n = len(rows) + (1 if trailer else 0) + top = y_bottom - n + y = top + longest = max((sum(len(t) for t, _ in parts) for parts, _ in rows), default=0) + name_w = max(name_w, longest + 2) if any(desc for _, desc in rows) else 0 + for idx, (name_parts, desc) in enumerate(rows): + is_focus = idx == focused + is_hover = hover is not None and idx == hover and not is_focus + bg = BAR_SEL if is_focus else (BAR_HOV if is_hover else None) + if bg: + s.fill(c.x0, y, c.x1, bg) + s.put(c.x0 + 2, y, ">" if is_focus else " ", St(fg=VIOLET, bg=bg) if is_focus else S) + x = c.x0 + 4 + for text, st in name_parts: + x = s.put(x, y, text, st(bg=bg) if bg else st, max_x=c.x1 - 1) + dx = c.x0 + 4 + name_w + s.put(dx, y, clip(desc, c.x1 - 1 - dx), St(fg=DIM, bg=bg) if bg else S_DIM) + y += 1 + if trailer: + s.put(c.x0 + 4, y, clip(trailer, c.x1 - 1 - c.x0 - 4), S_MUTED) + return top + + +def modal(s: Screen, c: Ctx, title: str, w: int | None = None, h: int | None = None, close: bool = True): + """Centered rounded modal with the title in the top hairline. Returns (x, y, w, h).""" + if c.narrow: + x, y, w, h = 0, 0, c.cols, c.rows + else: + w = w or min(96, c.cols - 4) + h = h or (c.rows - 2) + x = (c.cols - w) // 2 + y = 1 + s.clear_rect(x, y, x + w, y + h) + s.box(x, y, w, h, fg=HAIR) + s.put(x + 2, y, f" {title} ", S_BOLD) + if close: + s.right(y, " [x] ", x + w - 2, S_DIM) + return x, y, w, h + + +def legend(s: Screen, y: int, x0: int, x1: int, items, sep: str = " | "): + """Centered key legend: key in text colour, label dim.""" + parts = [] + for k, (key, label) in enumerate(items): + if k: + parts.append((sep, S_MUTED)) + parts.append((key, St(fg=TEXT))) + parts.append((" " + label, S_DIM)) + s.center_spans(y, parts, x0, x1) + + +def search_field(s: Screen, x: int, y: int, w: int, typed: str = "", placeholder: str = "/ to search", focused: bool = False): + if typed: + s.spans(x, y, [("/ ", S_ACC if focused else S_DIM), (typed, S)]) + if focused: + s.caret = (x + 2 + len(typed), y) + else: + s.put(x, y, placeholder, S_DIM) + s.hline(y + 1, x, x + w, HAIR) + + +# --------------------------------------------------------------------------- # +# Content +# --------------------------------------------------------------------------- # + +REPLY_ABOUT = [ + "I'm **Cortex**, a coding agent that runs in your terminal.", + "", + "I mostly help you **build and debug software**: code, architecture, debugging, reviews, docs, and a bit of research. " + "Here I run in an interactive terminal, so I can read your files, run commands, and change the project.", + "", + "In practice:", + "• I get straight to the point", + "• I prefer concrete work over long explanations", + "• I can also discuss, explain, or help you plan", + "", + "Tell me what you'd like to do.", +] + +PALETTE_HOME = [ + ("/model", "Choose the model for this session"), + ("/mode", "Switch between Agent, Plan and Ask"), + ("/permissions", "Set the approval policy for edits and commands"), + ("/plan", "Draft a plan before writing any code"), + ("/effort", "Tune reasoning effort for the current model"), + ("/mcp", "View and manage MCP servers"), + ("/sandbox", "Configure sandboxed command execution"), + ("/usage", "Plan usage, quota and limits"), + ("/resume", "Resume a previous session"), + ("/settings", "Open settings panel"), +] + +PALETTE_MOD = [ + ("/model", [0, 1, 2, 3], "Choose the model for this session"), + ("/mode", [0, 1, 2, 3], "Switch between Agent, Plan and Ask"), + ("/mcp-reload", [0, 1, 8, 10], "Reconnect every configured MCP server"), + ("/custom-commands", [0, 6, 9, 14], "Manage custom commands"), +] + +MODELS = [ + ("Cortex Mini 1", "Fast default for everyday coding", "current"), + ("Cortex 1", "Deeper reasoning for hard changes", ""), + ("Cortex Max 1", "Longest context — bills by token instead of per request", "MAX"), +] + +EFFORTS = [ + ("High Effort", "Deepest reasoning — best for hard, multi-file changes"), + ("Medium Effort", "Balanced reasoning for everyday coding · default"), + ("Low Effort", "Fastest responses for quick edits and questions"), +] + +SETTINGS = [ + ( + "Appearance", + [ + ("Compact mode", "off", False), + ("Default screen mode", "Fullscreen", True), + ("Show timestamps", "on", False), + ("Show thinking blocks", "on", False), + ("Group tool calls", "on", False), + ("Collapsed edit blocks", "off", False), + ("Line numbers", "on", False), + ("Word wrap", "on", False), + ("Syntax highlight", "on", False), + ("Animations", "on", False), + ("Theme", "Cortex Night", True), + ], + ), + ( + "Mouse", + [ + ("Mouse capture", "on", False), + ("Scroll lines", "3", False), + ("Invert scroll", "off", False), + ("Copy on select", "off", False), + ], + ), + ( + "Behavior", + [ + ("Auto approve", "off", False), + ("Sandbox mode", "on", False), + ("Streaming", "on", False), + ("Auto scroll", "on", False), + ("Sound", "off", False), + ("Notifications", "off", False), + ], + ), + ("AI", [("Thinking mode", "on", False), ("Context aware", "on", False), ("Debug mode", "off", False)]), + ("Git", [("Co-author", "on", False), ("Auto commit", "off", False), ("Sign commits", "off", False)]), + ("Cloud", [("Cloud sync", "off", False), ("Auto save", "on", False), ("Session history", "on", False)]), + ("Privacy", [("Telemetry", "off", False), ("Analytics", "off", False)]), +] + +THEMES = [ + ("Cortex Night", "Default inky chrome · violet on focus only", True), + ("Cortex Day", "Light chrome for bright rooms", False), + ("Ocean Dark", "Deep blue and cyan accents", False), + ("Monokai", "Classic code-editor colors", False), +] + + +# --------------------------------------------------------------------------- # +# Shared scenes +# --------------------------------------------------------------------------- # + + +def scene_about(s: Screen, c: Ctx, limit: int, compact: bool = False, first_turn: bool = True) -> Flow: + f = Flow(s, c, y=1 if compact else 2, limit=limit, compact=compact) + if first_turn: + f.user("hey", "12:49 AM") + f.thought("Thought for 0.4s") + f.reply(["Hey — what do you want to work on?"], "12:49 AM") + f.worked("Worked for 1.8s") + f.user("tell me about yourself", "12:49 AM") + f.thought("Thought for 0.4s") + f.reply(REPLY_ABOUT, "12:49 AM") + f.worked("Worked for 4.6s") + return f + + +def scene_shell(s: Screen, c: Ctx, limit: int) -> Flow: + f = Flow(s, c, limit=limit) + f.user("run the tui tests and fix whatever fails", "09:14 AM") + f.thought("Thought for 2.1s") + f.tile("Shell", "$ cargo test -p cortex-tui", meta_parts=[("✓ 0", S_OK), (" · 41s", S_DIM)]) + f.tile("Read", "src/cortex-tui/src/composer.rs", "212 lines") + f.tile("Grep", '"alternate_screen" in src/', "6 hits in 4 files") + f.blank() + return f + + +def backdrop_tail(s: Screen, c: Ctx, y_end: int): + """Paint the *tail* of the about-conversation so its last row sits at + ``y_end - 2`` — a picker pushes the transcript up, so the newest rows stay + visible and the oldest scroll off under the header.""" + scratch = Screen(c.cols, 80) + scene_about(scratch, Ctx(c.cols, 80, c.narrow), limit=78) + last = max(y for y in range(80) if any(cell.ch != " " for cell in scratch.cells[y])) + shift = (y_end - 2) - last + for y in range(1, y_end - 1): + src = y - shift + if 2 <= src < 80: + s.cells[y] = [Cell(ch=cl.ch, fg=cl.fg, bg=cl.bg, b=cl.b, i=cl.i, u=cl.u) for cl in scratch.cells[src]] + + +# --------------------------------------------------------------------------- # +# A. Entry / welcome +# --------------------------------------------------------------------------- # + + +def welcome_lines(s: Screen, c: Ctx, title_parts, y: int = 2): + s.spans(c.x0 + 2, y, title_parts, max_x=c.x1) + hints = [("v" + VERSION, S_DIM), (" · ", S_MUTED), ("/", S), (" commands", S_DIM), (" · ", S_MUTED), ("@", S), (" files", S_DIM)] + if not c.narrow: + hints += [(" · ", S_MUTED), ("!", S), (" shell", S_DIM), (" · ", S_MUTED), ("&", S), (" cloud", S_DIM)] + s.spans(c.x0 + 2, y + 1, hints, max_x=c.x1) + + +def board_welcome_cortex(s, c): + header(s, c, "0 / 500K") + title = [("Welcome to ", S), ("Cortex", S_BOLD)] + ([] if c.narrow else [(", the coding agent CLI", S_DIM)]) + welcome_lines(s, c, title) + composer(s, c) + footer(s, c) + + +def board_welcome_agent(s, c): + header(s, c, "0 / 500K") + title = [("Welcome to ", S), ("Cortex Agent", S_BOLD)] + ([] if c.narrow else [(" — describe a task, it does the work", S_DIM)]) + welcome_lines(s, c, title) + composer(s, c, placeholder="Describe a task for the agent") + footer(s, c) + + +def board_first_run(s, c): + header(s, c, "0 / 500K") + title = [("Welcome to ", S), ("Cortex", S_BOLD)] + ([] if c.narrow else [(", the coding agent CLI", S_DIM)]) + welcome_lines(s, c, title) + # charcoal tips panel + y = 5 + if c.narrow: + s.fill_rect(c.x0, y, c.x1, y + 3, PANEL) + s.put(c.x0 + 1, y, "A few tips to get started:", St(fg=TEXT, bg=PANEL, b=True)) + s.spans(c.x0 + 1, y + 1, [("1. ", St(fg=DIM, bg=PANEL)), ("/model", St(fg=TEXT, bg=PANEL)), (" switches model + effort.", St(fg=DIM, bg=PANEL))], max_x=c.x1 - 1) + s.spans(c.x0 + 1, y + 2, [("2. ", St(fg=DIM, bg=PANEL)), ("@", St(fg=TEXT, bg=PANEL)), (" files add context.", St(fg=DIM, bg=PANEL))], max_x=c.x1 - 1) + else: + s.fill_rect(c.x0, y, c.x1, y + 5, PANEL) + p = St(fg=DIM, bg=PANEL) + t = St(fg=TEXT, bg=PANEL) + s.put(c.x0 + 2, y, "A few tips to get the most out of this tool:", St(fg=TEXT, bg=PANEL, b=True)) + s.spans(c.x0 + 2, y + 1, [("1. Use ", p), ("/model", t), (" to switch between models and adjust reasoning effort.", p)]) + s.spans(c.x0 + 2, y + 2, [("2. Add ", p), ("@", t), (" files to give Cortex the right context.", p)]) + s.spans(c.x0 + 2, y + 3, [("3. Press ", p), ("Shift+Tab", t), (" anytime to cycle Agent / Plan / Ask.", p)]) + s.spans(c.x0 + 2, y + 4, [("4. ", p), ("Ctrl+x", t), (" lists every shortcut · ", p), ("F2", t), (" opens settings.", p)]) + composer(s, c) + footer(s, c) + + +def board_session_empty(s, c): + header(s, c) + composer(s, c) + footer(s, c) + + +# --------------------------------------------------------------------------- # +# B. Session +# --------------------------------------------------------------------------- # + + +def board_session_user_bars(s, c): + header(s, c) + top = composer(s, c) + if c.narrow: + f = Flow(s, c, limit=top) + f.user("hey", "12:49 AM") + f.thought("Thought for 0.4s") + f.reply(["Hey — what do you want to work on?"]) + f.worked("Worked for 1.8s") + footer(s, c) + return + banner_rows = 4 + banner_y = top - 1 - banner_rows + scene_about(s, c, limit=banner_y - 2) + scroll_indicator(s, c, banner_y - 2) + optin_banner(s, c, banner_y) + footer(s, c) + + +def board_session_thought(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("why does the composer lose focus after /model?", "10:02 AM") + f.thought("Thought for 3.2s") + f.reply(["The picker steals focus and never hands it back. `close_picker()` returns early when the effort radios are open."], "10:02 AM") + f.worked("Worked for 6.0s") + footer(s, c) + + +def board_session_thought_expanded(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("why does the composer lose focus after /model?", "10:02 AM") + f.thought("Thought for 3.2s ▾") + f.thought_body( + [ + "The user reports focus loss after the model picker closes.", + "Reading composer.rs — close_picker() early-returns when effort is open,", + "so focus_composer() is skipped. That matches the report.", + ] + ) + f.reply(["The picker steals focus and never hands it back. `close_picker()` returns early when the effort radios are open."], "10:02 AM") + footer(s, c) + + +def board_session_thinking_live(s, c): + header(s, c) + top = composer(s, c, placeholder="Add a follow-up — Enter to queue", focused=False, caret=False) + f = Flow(s, c, limit=top - 1) + f.user("why does the composer lose focus after /model?", "10:02 AM") + f.thought("Thinking · 3s", live=True) + footer(s, c, [("Esc", "interrupt"), ("Enter", "queue follow-up"), ("Ctrl+x", "shortcuts")] if not c.narrow else [("Esc", "interrupt"), ("Ctrl+x", "shortcuts")]) + + +def board_session_assistant(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("tell me about yourself", "12:49 AM") + f.thought("Thought for 0.4s") + f.reply(REPLY_ABOUT if not c.narrow else ["I'm **Cortex**, a coding agent in your terminal.", "• straight to the point", "• concrete work first"], "12:49 AM") + footer(s, c) + + +def board_session_worked(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("hey", "12:49 AM") + f.thought("Thought for 0.4s") + f.reply(["Hey — what do you want to work on?"], "12:49 AM") + f.worked("Worked for 1.8s") + footer(s, c) + + +def board_session_optin(s, c): + header(s, c) + top = composer(s, c) + rows = 3 if c.narrow else 4 + banner_y = top - 1 - rows + f = Flow(s, c, limit=banner_y - 1) + f.user("hey", "12:49 AM") + f.thought("Thought for 0.4s") + f.reply(["Hey — what do you want to work on?"], "12:49 AM") + f.worked("Worked for 1.8s") + optin_banner(s, c, banner_y) + footer(s, c) + + +def board_session_optin_hover(s, c): + header(s, c) + top = composer(s, c) + rows = 3 if c.narrow else 4 + banner_y = top - 1 - rows + f = Flow(s, c, limit=banner_y - 1) + f.user("hey", "12:49 AM") + f.thought("Thought for 0.4s") + f.reply(["Hey — what do you want to work on?"], "12:49 AM") + f.worked("Worked for 1.8s") + optin_banner(s, c, banner_y, hover="in") + footer(s, c) + + +def board_composer_empty(s, c): + header(s, c) + composer(s, c) + footer(s, c) + + +def board_composer_typing(s, c): + header(s, c) + composer(s, c, content=[("add retry with backoff to the api client", S)]) + footer(s, c, FOOTER_TYPED_NARROW if c.narrow else FOOTER_TYPED) + + +def board_composer_typing_blink(s, c): + header(s, c) + composer(s, c, content=[("add retry with backoff to the api client", S)], caret=False) + footer(s, c, FOOTER_TYPED_NARROW if c.narrow else FOOTER_TYPED) + + +def board_composer_hover(s, c): + header(s, c) + composer(s, c, hover=True) + footer(s, c) + + +def board_composer_multiline(s, c): + header(s, c) + bottom = c.rows - 3 + top = bottom - 4 + s.box(c.x0, top, c.inner_w, 5) + s.put(c.x0 + 2, top, " Agent ", S_DIM) + s.right(bottom, f" {MODEL_CHIP} ", c.x1 - 2, S_DIM) + s.put(c.x0 + 2, top + 1, ">", S_ACC) + lines = ["add retry with backoff to the api client:", "- max 3 attempts, jitter", "- surface the final error as product copy"] + for i, ln in enumerate(lines): + s.put(c.x0 + 4, top + 1 + i, clip(ln, c.inner_w - 6), S) + s.caret = (c.x0 + 4 + len(lines[-1]), top + 3) + footer(s, c, FOOTER_TYPED_NARROW if c.narrow else FOOTER_TYPED) + + +def board_footer_shortcuts(s, c): + header(s, c) + composer(s, c, content=[("hello", S)]) + footer(s, c, FOOTER_TYPED_NARROW if c.narrow else FOOTER_TYPED) + + +def board_footer_hover(s, c): + header(s, c) + composer(s, c) + footer(s, c, FOOTER_IDLE, hover="Ctrl+x") + + +def board_tokens_topright(s, c): + header(s, c, "142K / 500K") + top = composer(s, c) + scene_shell(s, c, limit=top - 1) + footer(s, c) + + +def board_tokens_topright_warn(s, c): + header(s, c, "462K / 500K", warn=True) + top = composer(s, c) + f = scene_shell(s, c, limit=top - 1) + f.line([("Context is 92% full — ", S_WARN), ("/compact", S), (" summarizes the thread to free room.", S_DIM)]) + footer(s, c) + + +def board_compact_chat(s, c): + header(s, c) + top = composer(s, c) + scene_about(s, c, limit=top, compact=True) + footer(s, c) + + +# --------------------------------------------------------------------------- # +# C. Slash + model +# --------------------------------------------------------------------------- # + + +def slash_rows(entries, typed: str = ""): + rows = [] + for name, desc in entries: + parts = [] + if typed and name.startswith(typed): + parts.append((typed, S_ACC)) + parts.append((name[len(typed) :], S)) + else: + parts.append((name, S)) + rows.append((parts, desc)) + return rows + + +def board_slash_palette(s, c): + header(s, c) + top = composer(s, c, content=[("/", S_ACC)]) + n = 3 if c.narrow else 8 + rows = slash_rows(PALETTE_HOME[:n], "/") + trailer = None if c.narrow else "… 87 more — keep typing to filter" + menu_top = menu(s, c, top, rows, focused=0, hover=3 if not c.narrow else None, name_w=16, trailer=trailer) + backdrop_tail(s, c, menu_top) + footer(s, c, FOOTER_TYPED_NARROW if c.narrow else FOOTER_TYPED) + + +def fuzzy_parts(name: str, idxs) -> list: + parts = [] + for i, ch in enumerate(name): + parts.append((ch, S_ACC if i in idxs else S)) + return parts + + +def board_slash_model_typed(s, c): + header(s, c) + top = composer(s, c, content=[("/mod", S_ACC), ("el", S_DIM)], caret=True) + # caret should sit after the typed part, before the ghost completion + s.caret = (c.x0 + 4 + 4, top + 1) + rows = [(fuzzy_parts(n, i), d) for n, i, d in PALETTE_MOD] + if c.narrow: + rows = rows[:3] + menu_top = menu(s, c, top, rows, focused=0, name_w=18) + backdrop_tail(s, c, menu_top) + footer(s, c, FOOTER_TYPED_NARROW if c.narrow else FOOTER_TYPED) + + +def model_rows(): + rows = [] + for name, desc, meta in MODELS: + d = desc + (f" · {meta}" if meta else "") + rows.append(([(name, S)], d)) + return rows + + +def board_model_list(s, c): + header(s, c) + top = composer(s, c, content=[("/model", S_ACC), (" ", S)]) + menu_top = menu(s, c, top, model_rows(), focused=0, name_w=16) + backdrop_tail(s, c, menu_top) + footer(s, c, [("Enter", "choose"), ("Tab", "effort"), ("Esc", "close")] if c.narrow else [("Enter", "choose"), ("Tab", "effort"), ("↑↓", "select"), ("Esc", "close")]) + + +def board_model_list_hover(s, c): + header(s, c) + top = composer(s, c, content=[("/model", S_ACC), (" ", S)]) + menu_top = menu(s, c, top, model_rows(), focused=0, hover=2, name_w=16) + backdrop_tail(s, c, menu_top) + footer(s, c, [("Enter", "choose"), ("Tab", "effort"), ("Esc", "close")] if c.narrow else [("Enter", "choose"), ("Tab", "effort"), ("↑↓", "select"), ("Esc", "close")]) + + +def effort_board(s, c, focused: int, hover: int | None = None): + header(s, c) + top = composer(s, c, content=[("/model", S_ACC), (" Cortex Mini 1", S)]) + rows = [([(n, S)], d) for n, d in EFFORTS] + menu_top = menu(s, c, top, rows, focused=focused, hover=hover, name_w=15) + backdrop_tail(s, c, menu_top) + footer(s, c, [("Enter", "apply"), ("Tab", "back to models"), ("Esc", "close")] if not c.narrow else [("Enter", "apply"), ("Esc", "close")]) + + +def board_model_effort_high(s, c): + effort_board(s, c, 0) + + +def board_model_effort_medium(s, c): + effort_board(s, c, 1) + + +def board_model_effort_low(s, c): + effort_board(s, c, 2) + + +def board_model_effort_hover(s, c): + effort_board(s, c, 1, hover=2) + + +# --------------------------------------------------------------------------- # +# D. Settings +# --------------------------------------------------------------------------- # + + +def settings_lines(filter_text: str = ""): + """Flatten SETTINGS into ('cat', name) / ('row', label, value, sub) / ('gap',).""" + lines = [] + for k, (cat, rows) in enumerate(SETTINGS): + vis = [r for r in rows if not filter_text or filter_text.lower() in r[0].lower()] + if not vis: + continue + if lines: + lines.append(("gap",)) + lines.append(("cat", cat)) + for label, value, sub in vis: + lines.append(("row", label, value, sub)) + return lines + + +def paint_settings(s: Screen, c: Ctx, focus_label: str, hover_label: str | None = None, scroll: int = 0, search: str = "", search_focused: bool = False): + x, y, w, h = modal(s, c, "Settings") + ix0, ix1 = x + 2, x + w - 2 # inner content columns + search_field(s, ix0, y + 1, ix1 - ix0, typed=search, focused=search_focused) + body_top = y + 3 if c.narrow else y + 4 + if c.narrow: + body_bottom = y + h - 3 + else: + body_bottom = y + h - 5 + lines = settings_lines(search)[scroll:] + row_y = body_top + for ln in lines: + if row_y >= body_bottom: + break + if ln[0] == "gap": + row_y += 1 + continue + if ln[0] == "cat": + s.put(ix0, row_y, ln[1], S_DIM) + s.hline(row_y, ix0 + len(ln[1]) + 1, ix1, HAIR) + row_y += 1 + continue + _, label, value, sub = ln + is_focus = label == focus_label + is_hover = hover_label == label and not is_focus + bg = BAR_SEL if is_focus else (BAR_HOV if is_hover else None) + if bg: + s.fill(x + 1, row_y, x + w - 1, bg) + marker_st = St(fg=VIOLET, bg=bg) if is_focus else St(fg=DIM, bg=bg) if bg else S_DIM + s.put(ix0 + 1, row_y, "▸", marker_st) + lab_st = St(fg=TEXT, b=is_focus, bg=bg) if bg else S + val_st = St(fg=TEXT if value != "off" else DIM, bg=bg) if bg else (S if value != "off" else S_DIM) + if c.narrow and sub: + value = "" if len(label) + len(value) + 10 > (ix1 - ix0) else value + val_len = len(value) + (3 if sub else 0) + label = clip(label, ix1 - 1 - val_len - 1 - (ix0 + 3)) + if search and search.lower() in label.lower(): + k = label.lower().find(search.lower()) + pre, mid, post = label[:k], label[k : k + len(search)], label[k + len(search) :] + s.spans(ix0 + 3, row_y, [(pre, lab_st), (mid, St(fg=VIOLET, b=is_focus, bg=bg)), (post, lab_st)]) + else: + s.put(ix0 + 3, row_y, label, lab_st) + if sub: + s.right_spans(row_y, [(value, val_st), (" >", St(fg=DIM, bg=bg) if bg else S_DIM)], ix1 - 1) + else: + s.right(row_y, value, ix1 - 1, val_st) + row_y += 1 + # footer + if c.narrow: + legend(s, y + h - 3, x + 1, x + w - 1, [("↑↓", "nav"), ("Space", "toggle"), ("/", "search")]) + legend(s, y + h - 2, x + 1, x + w - 1, [("F2/Esc", "close")]) + else: + s.center_spans( + y + h - 4, + [("Tip · Ask Cortex: ", S_MUTED), ('"change theme to Cortex Day"', S_DIM), (" or ", S_MUTED), ('"what does compact mode do?"', S_DIM)], + x + 1, + x + w - 1, + ) + legend( + s, + y + h - 3, + x + 1, + x + w - 1, + [("↑/↓/j/k", "nav"), ("g/G", "top/btm"), ("Space", "toggle"), ("Enter", "toggle"), ("→", "expand"), ("/", "search"), ("d", "reset")], + ) + legend(s, y + h - 2, x + 1, x + w - 1, [("F2/Esc", "close")]) + return x, y, w, h + + +def settings_backdrop(s, c): + header(s, c) + top = composer(s, c, focused=False, caret=False) + scene_about(s, c, limit=top - 1) + footer(s, c) + + +def board_settings_appearance(s, c): + settings_backdrop(s, c) + paint_settings(s, c, focus_label="Compact mode") + + +def board_settings_mouse(s, c): + settings_backdrop(s, c) + # scrolled so the Mouse category leads the list + paint_settings(s, c, focus_label="Scroll lines", scroll=13) + + +def board_settings_row_hover(s, c): + settings_backdrop(s, c) + paint_settings(s, c, focus_label="Compact mode", hover_label="Show timestamps") + + +def board_settings_search(s, c): + settings_backdrop(s, c) + paint_settings(s, c, focus_label="Scroll lines", search="scro", search_focused=True) + + +def board_settings_theme_submenu(s, c): + settings_backdrop(s, c) + x, y, w, h = modal(s, c, "Settings") + ix0, ix1 = x + 2, x + w - 2 + s.spans(ix0, y + 1, [("Appearance", S_DIM), (" › ", S_MUTED), ("Theme", S)]) + s.hline(y + 2, ix0, ix1, HAIR) + row_y = y + 3 if c.narrow else y + 4 + for k, (name, desc, current) in enumerate(THEMES): + is_focus = k == 0 + bg = BAR_SEL if is_focus else None + if bg: + s.fill(x + 1, row_y, x + w - 1, bg) + s.put(ix0 + 1, row_y, "●" if current else "○", St(fg=TEXT if current else DIM, bg=bg) if bg else (S if current else S_DIM)) + s.put(ix0 + 3, row_y, name, St(fg=VIOLET if is_focus else TEXT, b=is_focus, bg=bg) if bg else S) + if not c.narrow: + s.put(ix0 + 18, row_y, desc, St(fg=DIM, bg=bg) if bg else S_DIM) + if current: + s.right(row_y, "current", ix1 - 1, St(fg=DIM, bg=bg) if bg else S_DIM) + row_y += 1 + if c.narrow: + legend(s, y + h - 3, x + 1, x + w - 1, [("Enter", "select"), ("←", "back")]) + legend(s, y + h - 2, x + 1, x + w - 1, [("F2/Esc", "close")]) + else: + s.center_spans(y + h - 4, [("Themes never change the accent rule: violet on focus only.", S_MUTED)], x + 1, x + w - 1) + legend(s, y + h - 3, x + 1, x + w - 1, [("↑/↓/j/k", "nav"), ("Enter", "select"), ("←", "back"), ("d", "reset")]) + legend(s, y + h - 2, x + 1, x + w - 1, [("F2/Esc", "close")]) + + +# --------------------------------------------------------------------------- # +# E. Modes / tools / errors +# --------------------------------------------------------------------------- # + + +def board_mode_agent(s, c): + header(s, c) + top = composer(s, c, mode="Agent") + scene_shell(s, c, limit=top - 1) + footer(s, c) + + +def board_mode_plan(s, c): + header(s, c) + top = composer(s, c, mode="Plan", placeholder="Describe what you want — Cortex drafts a plan first") + f = Flow(s, c, limit=top - 1) + f.user("add retry with backoff to the api client", "11:20 AM") + f.thought("Thought for 5.8s") + f.reply( + [ + "**Plan** — no files change until you approve.", + "", + "1. Wrap `ApiClient::send` in a retry loop: 3 attempts, exponential backoff with jitter.", + "2. Retry only on timeouts and 5xx; never on 4xx.", + "3. Surface the final failure as product copy: 'The coding service is temporarily unavailable'.", + "4. Unit tests for the backoff schedule and the give-up path.", + ] + if not c.narrow + else ["**Plan** — no edits until approved.", "1. retry loop, 3 attempts", "2. tests for backoff"], + "11:20 AM", + ) + footer(s, c) + + +def board_mode_ask(s, c): + header(s, c) + top = composer(s, c, mode="Ask", placeholder="Ask about the codebase — read-only") + f = Flow(s, c, limit=top - 1) + f.user("where is the alternate-screen default decided?", "11:31 AM") + f.thought("Thought for 1.1s") + f.reply( + ["`TuiConfig::default()` in `src/cortex-engine/src/config/types.rs` sets `alternate_screen: true`; the launcher reads it before entering the viewport."] + if not c.narrow + else ["`TuiConfig::default()` sets `alternate_screen: true`."], + "11:31 AM", + ) + footer(s, c) + + +def board_mode_bash(s, c): + header(s, c) + composer(s, c, mode="Bash", content=[("cargo test -p cortex-tui", S)], sigil="!") + footer(s, c, [("Enter", "run"), ("Esc", "leave bash"), ("Ctrl+x", "shortcuts")] if not c.narrow else [("Enter", "run"), ("Esc", "leave bash")]) + + +def board_permission_prompt(s, c): + header(s, c) + top = composer(s, c, focused=False, caret=False, placeholder="Choose an option above") + f = Flow(s, c, y=1 if c.narrow else 2, limit=top if c.narrow else top - 1) + if not c.narrow: + f.user("add ioredis and a mock for the tests", "09:40 AM") + f.thought("Thought for 1.4s") + f.line([("●", S_DIM), (" Cortex wants to run", S)]) + f.command("$ npm install ioredis && npm install -D ioredis-mock") + f.options(["Yes, run once", "Yes, always allow npm install in this project", "Edit command", "No — tell Cortex what to do instead"], focused=0) + footer(s, c, [("↑↓", "select"), ("Enter", "confirm"), ("e", "edit command"), ("Esc", "cancel")] if not c.narrow else [("Enter", "confirm"), ("Esc", "cancel")]) + + +def board_permission_prompt_hover(s, c): + header(s, c) + top = composer(s, c, focused=False, caret=False, placeholder="Choose an option above") + f = Flow(s, c, limit=top - 1) + f.user("add ioredis and a mock for the tests", "09:40 AM") + f.thought("Thought for 1.4s") + f.line([("●", S_DIM), (" Cortex wants to run", S)]) + f.command("$ npm install ioredis && npm install -D ioredis-mock") + f.options(["Yes, run once", "Yes, always allow npm install in this project", "Edit command", "No — tell Cortex what to do instead"], focused=0, hover=1) + footer(s, c, [("↑↓", "select"), ("Enter", "confirm"), ("e", "edit command"), ("Esc", "cancel")]) + + +def board_permissions_picker(s, c): + header(s, c) + top = composer(s, c, content=[("/permissions", S_ACC), (" ", S)]) + rows = [ + ([("● ", S), ("Smart", S)], "auto-approve safe reads · ask before edits · current"), + ([("○ ", S_DIM), ("Read-only", S)], "never edit files or run commands"), + ([("○ ", S_DIM), ("Full access", S)], "only ask when leaving the sandbox"), + ] + menu_top = menu(s, c, top, rows, focused=0, name_w=15) + s.spans(c.x0 + 2, menu_top - 2, [("Permissions", S), (" · how Cortex asks before acting", S_DIM)], max_x=c.x1) + backdrop_tail(s, c, menu_top - 2) + footer(s, c, [("Enter", "apply"), ("Esc", "close")]) + + +def board_mcp_servers(s, c): + header(s, c) + top = composer(s, c, content=[("/mcp", S_ACC), (" ", S)]) + rows = [ + ([("✓ ", S_OK), ("github", S)], "12 tools · connected"), + ([("✓ ", S_OK), ("filesystem", S)], "8 tools · connected"), + ([("⠇ ", S_DIM), ("linear", S)], "authenticating…"), + ([("× ", S_ERR), ("sentry", S)], "failed — token expired · r to reconnect"), + ] + if c.narrow: + rows = rows[:3] + menu_top = menu(s, c, top, rows, focused=0, name_w=15) + s.spans(c.x0 + 2, menu_top - 2, [("MCP servers", S), (" · 2 of 4 connected", S_DIM)], max_x=c.x1) + if not c.narrow: + backdrop_tail(s, c, menu_top - 2) + footer(s, c, [("Enter", "details"), ("r", "reconnect"), ("a", "add server"), ("Esc", "close")] if not c.narrow else [("Enter", "details"), ("Esc", "close")]) + + +def board_mcp_drop(s, c): + header(s, c) + top = composer(s, c) + f = scene_shell(s, c, limit=top - 1) + f.line([("×", S_ERR), (" github", S), (" dropped", S_DIM)]) + f.dim("Reconnecting 2/3 — tools from github are paused until it is back.", indent=2) + footer(s, c) + + +def board_plugins(s, c): + header(s, c) + top = composer(s, c, content=[("/plugins", S_ACC), (" ", S)]) + rows = [ + ([("✓ ", S_OK), ("cortex-review", S)], "1.2.0 · enabled · adds /review"), + ([("✓ ", S_OK), ("mermaid-preview", S)], "0.4.1 · enabled"), + ([("○ ", S_DIM), ("jira", S)], "0.9.0 · disabled"), + ] + menu_top = menu(s, c, top, rows, focused=0, name_w=20) + s.spans(c.x0 + 2, menu_top - 2, [("Plugins", S), (" · 2 of 3 enabled", S_DIM)], max_x=c.x1) + backdrop_tail(s, c, menu_top - 2) + footer(s, c, [("Enter", "toggle"), ("i", "install"), ("u", "update"), ("Esc", "close")] if not c.narrow else [("Enter", "toggle"), ("Esc", "close")]) + + +def bar_cells(used: int, total: int, width: int, fg_full: str = DIM) -> list: + filled = round(width * used / total) if total else 0 + return [("█" * filled, St(fg=fg_full)), ("█" * (width - filled), St(fg=BAR_SEL))] + + +def board_usage(s, c): + header(s, c) + top = composer(s, c, content=[("/usage", S_ACC), (" ", S)]) + y = top - 7 if not c.narrow else top - 4 + s.spans(c.x0 + 2, y, [("Usage", S), (" · Cortex Pro · renews Oct 1", S_DIM)], max_x=c.x1) + rows = [("Agent requests", 42, 500, "42 / 500"), ("Tokens this month", 84, 120, "8.4M / 12M"), ("Cloud agent minutes", 132, 400, "132 / 400")] + for k, (label, used, total, txt) in enumerate(rows): + yy = y + 1 + k + pct = f"{round(100 * used / total):>3}%" + if c.narrow: + s.put(c.x0 + 2, yy, clip(label, 19), S) + s.right_spans(yy, [(txt, S_DIM), (" ", S), (pct, S)], c.x1 - 1) + else: + s.put(c.x0 + 2, yy, label, S) + x = s.put(c.x0 + 24, yy, txt.rjust(10), S_DIM) + x = s.spans(x + 3, yy, bar_cells(used, total, 40)) + s.put(x + 2, yy, pct, S_DIM) + if not c.narrow: + s.put(c.x0 + 2, y + 5, "MAX bills by token instead of per request — manage at cortex.foundation/billing", S_MUTED) + backdrop_tail(s, c, y) + footer(s, c, [("Esc", "close")]) + + +def board_quota_exhausted(s, c): + header(s, c) + top = composer(s, c, placeholder="Add a follow-up — held until quota resets", focused=False, caret=False) + f = scene_shell(s, c, limit=top - 1) + f.line([("×", S_ERR), (" Agent quota exhausted", S_ERR)]) + yy = f.y + if f.ok(): + x = s.put(f.tx + 2, yy, "Agent requests", S) + x = s.put(f.tx + 20, yy, "500 / 500", S_DIM) + s.spans(x + 3, yy, bar_cells(500, 500, 24 if not c.narrow else 6, fg_full=RED), max_x=c.x1 - 1) + f.y += 1 + f.dim("Resets in 4h 12m. Switch to MAX token billing to continue now, or upgrade at cortex.foundation/billing", indent=2) + footer(s, c, [("/usage", "details"), ("Ctrl+x", "shortcuts")]) + + +def board_sandbox(s, c): + header(s, c) + top = composer(s, c, content=[("/sandbox", S_ACC), (" ", S)]) + rows = [ + ([("Filesystem", S)], "workspace only · ~/code/cortex"), + ([("Network", S)], "allowlist · registry.npmjs.org, github.com"), + ([("Escalation", S)], "ask before running outside the sandbox"), + ] + menu_top = menu(s, c, top, rows, focused=0, name_w=14) + s.spans(c.x0 + 2, menu_top - 2, [("Sandbox", S), (" · ", S_DIM), ("✓ On", S_OK)], max_x=c.x1) + backdrop_tail(s, c, menu_top - 2) + footer(s, c, [("Space", "toggle"), ("Enter", "edit"), ("Esc", "close")]) + + +def board_sandbox_deny(s, c): + header(s, c) + top = composer(s, c, focused=False, caret=False, placeholder="Choose an option above") + f = Flow(s, c, y=1 if c.narrow else 2, limit=top if c.narrow else top - 1) + if not c.narrow: + f.user("install the deps with the vendor script", "02:15 PM") + f.thought("Thought for 0.9s") + f.tile("Shell", "$ curl -s https://example.com/install.sh | sh") + f.line([("×", S_ERR), (" Sandbox denied", S_ERR)]) + f.dim("curl was blocked by the workspace sandbox. Network is allowlisted.", indent=2) + f.options(["Keep blocked", "Allow once", "Allow for this session"], focused=0) + footer(s, c, [("↑↓", "select"), ("Enter", "confirm"), ("Esc", "cancel")] if not c.narrow else [("Enter", "confirm"), ("Esc", "cancel")]) + + +def board_cloud_handoff(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("& fix the flaky login redirect test and open a PR", "03:02 PM", sigil=">") + f.line([("↑", S), (" Handed off to Cortex Cloud", S)]) + f.line([("agent ", S_DIM), ("ag_4f2a", S), (" · running", S_DIM)], indent=2) + f.line([("branch ", S_DIM), ("cortex/fix-login-redirect", S)], indent=2) + f.line([("follow ", S_DIM), ("cortex.foundation/agents/ag_4f2a", S), (" · or /jobs right here", S_DIM)], indent=2) + footer(s, c) + + +def board_diagnostics(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("wire the model chip into the composer border", "04:11 PM") + f.thought("Thought for 2.6s") + f.tile("Edit", "src/cortex-tui/src/composer.rs", meta_parts=[("+12", S_OK), (" ", S), ("−3", S_ERR)]) + f.tile("Diagnostics", "src/cortex-tui/src/composer.rs", "2") + if c.narrow: + f.line([("error ", S_ERR), ("E0308 mismatched types", S)], indent=2) + f.line([("warn ", S_WARN), ("unused variable `hints`", S)], indent=2) + else: + f.line([("error ", S_ERR), ("E0308 mismatched types — expected `Span`, found `String`", S), (" composer.rs:42:9", S_DIM)], indent=2) + f.line([("warn ", S_WARN), ("unused variable `hints`", S), (" composer.rs:57:13", S_DIM)], indent=2) + footer(s, c) + + +def board_interrupt_stopped(s, c): + header(s, c) + top = composer(s, c, placeholder="Reply, or ↑ to edit your last message") + f = Flow(s, c, limit=top - 1) + f.user("run the tui tests and fix whatever fails", "09:14 AM") + f.thought("Thought for 2.1s") + f.tile("Shell", "$ cargo test -p cortex-tui", "stopped") + f.line([("×", S_ERR), (" Stopped", S_ERR)]) + f.dim("Worked for 12s · 4.1k tokens") + footer(s, c) + + +def board_error_unavailable(s, c): + header(s, c) + top = composer(s, c, placeholder="Try again — your work so far is saved") + f = Flow(s, c, limit=top - 1) + f.user("tell me about yourself", "12:49 AM") + f.line([("×", S_ERR), (" The coding service is temporarily unavailable", S_ERR)]) + f.dim("Try again in a moment — your work so far is saved in this session.", indent=2) + footer(s, c, [("Enter", "retry"), ("Ctrl+x", "shortcuts")]) + + +def board_tool_tiles(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("why do tests fail on the composer?", "09:14 AM") + f.thought("Thought for 2.1s") + f.line([("▾", S_DIM), (" 3 tool calls", S), (" Read ×2 · Grep ×1", S_DIM)]) + f.tile("Read", "src/cortex-tui/src/composer.rs", "212 lines") + f.tile("Read", "src/cortex-tui/src/tests/composer.rs", "88 lines") + f.tile("Grep", '"model_chip" in src/', "3 hits in 2 files") + f.tile("Shell", "$ cargo test -p cortex-tui composer", meta_parts=[("× 101", S_ERR), (" · 12s", S_DIM)]) + f.dim("test composer::chip_in_border … FAILED — expected `Cortex Mini 1 (medium)`, got ``", indent=2) + footer(s, c) + + +def board_tool_tiles_collapsed(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("why do tests fail on the composer?", "09:14 AM") + f.thought("Thought for 2.1s") + f.line([("▸", S_DIM), (" 3 tool calls", S), (" Read ×2 · Grep ×1", S_DIM)]) + f.tile("Shell", "$ cargo test -p cortex-tui composer", meta_parts=[("× 101", S_ERR), (" · 12s", S_DIM)]) + f.blank() + f.reply(["The chip is painted before the model name resolves, so the border shows an empty label on the first frame."], "09:15 AM") + footer(s, c) + + +def board_shell_running(s, c): + header(s, c) + top = composer(s, c, placeholder="Add a follow-up — Enter to queue", focused=False, caret=False) + f = Flow(s, c, limit=top - 1) + f.user("run the tui tests and fix whatever fails", "09:14 AM") + f.thought("Thought for 2.1s") + f.tile("Shell", "$ cargo test -p cortex-tui", "running · 8s", glyph="⠇", glyph_st=S) + f.dim(" Compiling cortex-tui v0.1.7 (/home/m/code/cortex/src/cortex-tui)", indent=2) + f.dim(" Finished test [unoptimized + debuginfo] target(s) in 6.91s", indent=2) + f.dim(" Running unittests src/lib.rs", indent=2) + footer(s, c, [("Esc", "interrupt"), ("Enter", "queue follow-up"), ("Ctrl+x", "shortcuts")] if not c.narrow else [("Esc", "interrupt")]) + + +def board_diff_hunk(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("move the model chip into the composer border", "04:11 PM") + f.thought("Thought for 2.6s") + f.tile("Edit", "src/cortex-tui/src/composer.rs", meta_parts=[("+2", S_OK), (" ", S), ("−1", S_ERR)]) + g = S_MUTED + f.line([("@@ -41,7 +41,8 @@", g)], indent=2) + f.line([("41 41 ", g), (" let chip = model_chip(state);", S)], indent=2) + f.line([("42 ", g), ("- footer.push(chip);", S_ERR)], indent=2) + f.line([(" 42 ", g), ("+ border.push_right(chip);", S_OK)], indent=2) + f.line([(" 43 ", g), ("+ footer.push(hints);", S_OK)], indent=2) + f.line([("43 44 ", g), (" Ok(())", S)], indent=2) + footer(s, c) + + +def board_edit_collapsed(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("move the model chip into the composer border", "04:11 PM") + f.thought("Thought for 2.6s") + f.tile("Edit", "src/cortex-tui/src/composer.rs", meta_parts=[("+2", S_OK), (" ", S), ("−1", S_ERR), (" · ▸ show diff", S_DIM)]) + f.tile("Edit", "src/cortex-tui/src/footer.rs", meta_parts=[("+4", S_OK), (" ", S), ("−9", S_ERR), (" · ▸ show diff", S_DIM)]) + f.blank() + f.reply(["Moved the chip into the bottom hairline and dropped it from the footer."], "04:12 PM") + footer(s, c) + + +def board_md_table(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("compare the models", "05:00 PM") + f.thought("Thought for 0.8s") + if c.narrow: + f.line([("+--------------+--------+", S_HAIR)]) + f.line([("| ", S_HAIR), ("Model ", S_BOLD), ("| ", S_HAIR), ("Effort", S_BOLD), (" |", S_HAIR)]) + f.line([("+--------------+--------+", S_HAIR)]) + f.line([("| ", S_HAIR), ("Cortex Mini 1", S), ("| ", S_HAIR), ("Medium", S), (" |", S_HAIR)]) + f.line([("+--------------+--------+", S_HAIR)]) + else: + rows = [("Model", "Default effort", "Context", "Billing"), ("Cortex Mini 1", "Medium", "500K", "per request"), ("Cortex 1", "High", "500K", "per request"), ("Cortex Max 1", "High", "1M", "per token")] + widths = [15, 16, 9, 13] + sep = "+" + "+".join("-" * (w + 2) for w in widths) + "+" + f.line([(sep, S_HAIR)]) + for k, row in enumerate(rows): + parts = [] + for w, cell in zip(widths, row): + parts.append(("| ", S_HAIR)) + parts.append((cell.ljust(w + 1), S_BOLD if k == 0 else S)) + parts.append(("|", S_HAIR)) + f.line(parts) + if k == 0: + f.line([(sep, S_HAIR)]) + f.line([(sep, S_HAIR)]) + footer(s, c) + + +def board_code_fence(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("show me a minimal retry helper", "05:12 PM") + f.thought("Thought for 1.0s") + w = f.x1 - 1 - f.tx + f.line([("─ rust ", S_DIM), ("─" * (w - 7), S_HAIR)]) + g = S_MUTED + code = [ + [("pub async fn ", S_BOLD), ("with_retry(mut op: F) -> Result", S)], + [("where", S_BOLD), (" F: FnMut() -> Fut>,", S)], + [("{", S)], + [(" ", S), ("for", S_BOLD), (" attempt ", S), ("in", S_BOLD), (" 0..3 {", S)], + [(" ", S), ("match", S_BOLD), (" op().await {", S)], + [(" Ok(v) => ", S), ("return", S_BOLD), (" Ok(v),", S)], + [(" Err(e) ", S), ("if", S_BOLD), (" attempt == 2 => ", S), ("return", S_BOLD), (" Err(e),", S)], + [(" Err(_) => sleep(backoff(attempt)).await,", S)], + [(" }", S)], + [(" }", S)], + [(" unreachable!()", S)], + [("}", S)], + ] + if c.narrow: + code = code[:3] + for i, parts in enumerate(code): + f.line([(f"{i + 1:>2} ", g)] + parts) + f.line([("─" * w, S_HAIR)]) + footer(s, c) + + +def board_login(s, c): + # `cortex login` is an inline flow — no header, composer or footer. + y = 1 + s.put(c.x0 + 1, y, "Welcome to Cortex CLI!", S_BOLD) + s.put(c.x0 + 1, y + 2, "How would you like to log in?", S) + rows = [("1 Continue with browser", "Opens cortex.foundation/cli/auth"), ("2 Paste an API key", "Enter your key to authenticate")] + for k, (label, desc) in enumerate(rows): + yy = y + 4 + k + if k == 0: + s.fill(c.x0, yy, c.x1, BAR_SEL) + s.put(c.x0 + 1, yy, ">", St(fg=VIOLET, bg=BAR_SEL)) + x = s.put(c.x0 + 3, yy, label, St(fg=TEXT, bg=BAR_SEL)) + if not c.narrow: + s.put(c.x0 + 30, yy, desc, St(fg=DIM, bg=BAR_SEL)) + else: + x = s.put(c.x0 + 3, yy, label, S) + if not c.narrow: + s.put(c.x0 + 30, yy, desc, S_DIM) + footer(s, c, [("↑↓", "select"), ("Enter", "confirm"), ("Esc", "quit")], y=y + 7) + + +def board_login_waiting(s, c): + y = 1 + s.put(c.x0 + 1, y, "Welcome to Cortex CLI!", S_BOLD) + s.spans(c.x0 + 1, y + 2, [("⠇ ", S_DIM), ("Waiting for browser authentication…", S)]) + s.spans(c.x0 + 1, y + 4, [("Your code ", S_DIM), ("WXYZ-1234", S_BOLD)]) + s.put(c.x0 + 1, y + 5, clip("If the browser didn't open, visit cortex.foundation/cli/auth and enter the code.", c.inner_w - 2), S_DIM) + footer(s, c, [("Esc", "cancel")], y=y + 7) + + +def board_login_success(s, c): + y = 1 + s.put(c.x0 + 1, y, "Welcome to Cortex CLI!", S_BOLD) + s.spans(c.x0 + 1, y + 2, [("✓ ", S_OK), ("Signed in as ", S), ("mathis@cortex.foundation", S_BOLD)]) + s.spans(c.x0 + 1, y + 4, [("Run ", S_DIM), ("cortex", S), (" to start a session.", S_DIM)]) + + +def board_login_error(s, c): + y = 1 + s.put(c.x0 + 1, y, "Welcome to Cortex CLI!", S_BOLD) + s.spans(c.x0 + 1, y + 2, [("× ", S_ERR), ("Sign-in didn't complete", S_ERR)]) + s.put(c.x0 + 1, y + 3, clip("Your Cortex API key may be invalid, expired, or revoked.", c.inner_w - 2), S_DIM) + s.put(c.x0 + 1, y + 4, clip("Run 'cortex login' or set CORTEX_API_KEY, then try again.", c.inner_w - 2), S_DIM) + footer(s, c, [("Enter", "try again"), ("Esc", "quit")], y=y + 6) + + +def board_shortcuts_overlay(s, c): + settings_backdrop(s, c) + if c.narrow: + x, y, w, h = modal(s, c, "Shortcuts") + rows = [("Shift+Tab", "cycle Agent / Plan / Ask"), ("@", "mention files"), ("!", "bash mode"), ("&", "hand off to Cortex Cloud"), ("Ctrl+c", "stop"), ("F2", "settings"), ("Esc", "interrupt / close")] + for k, (key, label) in enumerate(rows): + s.spans(x + 2, y + 2 + k, [(key.ljust(10), S), (label, S_DIM)], max_x=x + w - 2) + legend(s, y + h - 2, x + 1, x + w - 1, [("Ctrl+x/Esc", "close")]) + return + x, y, w, h = modal(s, c, "Shortcuts", w=min(84, c.cols - 4), h=14) + left = [ + ("Shift+Tab", "cycle Agent / Plan / Ask"), + ("@", "mention files"), + ("!", "bash mode"), + ("&", "hand off to Cortex Cloud"), + ("/", "slash commands"), + ("Alt+Enter", "newline in the composer"), + ("↑ / ↓", "edit last · browse history"), + ] + right = [ + ("Ctrl+p", "command palette"), + ("Ctrl+r", "search past sessions"), + ("Ctrl+c", "stop the current turn"), + ("Esc", "interrupt · close"), + ("F2", "settings"), + ("PgUp / PgDn", "scroll the transcript"), + ("Ctrl+x", "this overlay"), + ] + for k in range(len(left)): + yy = y + 2 + k + s.spans(x + 3, yy, [(left[k][0].ljust(12), S), (left[k][1], S_DIM)]) + s.spans(x + w // 2 + 1, yy, [(right[k][0].ljust(13), S), (right[k][1], S_DIM)]) + s.hline(y + 2 + len(left) + 1, x + 2, x + w - 2, HAIR) + s.center_spans(y + 2 + len(left) + 2, [("Docs & guides: cortex.foundation/docs · Cortex CLI v" + VERSION, S_MUTED)], x + 1, x + w - 1) + legend(s, y + h - 2, x + 1, x + w - 1, [("Ctrl+x/Esc", "close")]) + + +def board_resume_picker(s, c): + header(s, c) + top = composer(s, c, content=[("/resume", S_ACC), (" ", S)]) + rows = [ + ([("fix login redirect", S)], "2h ago · 14 messages · cortex/fix-login-redirect"), + ([("composer chip design", S)], "yesterday · 31 messages"), + ([("bump version to 0.1.7", S)], "3 days ago · 6 messages"), + ] + menu_top = menu(s, c, top, rows, focused=0, name_w=24) + search_field(s, c.x0 + 2, menu_top - 3, c.inner_w - 4, placeholder="Type to search sessions") + backdrop_tail(s, c, menu_top - 3) + footer(s, c, [("Enter", "resume"), ("f", "favorite"), ("d", "delete"), ("Esc", "close")] if not c.narrow else [("Enter", "resume"), ("Esc", "close")]) + + +def board_clear_confirm(s, c): + header(s, c) + top = composer(s, c, content=[("/clear", S_ACC)], caret=False, focused=False) + y = top - 5 + backdrop_tail(s, c, y) + f = Flow(s, c, y=y, limit=top - 1) + f.line([("Clear this conversation?", S)]) + f.dim("The transcript is dropped. Git, files and config stay as they are.") + f.options(["Yes, clear", "No, keep it"], focused=0) + footer(s, c, [("Enter", "confirm"), ("Esc", "cancel")]) + + +def board_plan_confirm(s, c): + header(s, c) + top = composer(s, c, mode="Plan", focused=False, caret=False, placeholder="Choose an option above") + f = Flow(s, c, limit=top - 1) + f.user("add retry with backoff to the api client", "11:20 AM") + f.thought("Thought for 5.8s") + f.reply( + [ + "**Plan** — no files change until you approve.", + "", + "1. Wrap `ApiClient::send` in a retry loop: 3 attempts, exponential backoff with jitter.", + "2. Retry only on timeouts and 5xx; never on 4xx.", + "3. Surface the final failure as product copy: 'The coding service is temporarily unavailable'.", + "4. Unit tests for the backoff schedule and the give-up path.", + ], + "11:21 AM", + ) + f.line([("Implement this plan?", S)]) + f.options(["Yes, switch to Agent mode and implement", "No, keep planning — tell Cortex what to change"], focused=0) + footer(s, c, [("Enter", "confirm"), ("Esc", "keep planning")]) + + +def board_queue(s, c): + header(s, c) + top = composer(s, c, placeholder="Add a follow-up — Enter to queue", focused=True) + f = Flow(s, c, limit=top - 4) + f.user("run the tui tests and fix whatever fails", "09:14 AM") + f.thought("Thought for 2.1s") + f.tile("Shell", "$ cargo test -p cortex-tui", "running · 8s", glyph="⠇", glyph_st=S) + y = top - 3 + s.spans(c.x0 + 2, y, [("Queued · 2", S), (" — sent when the current step finishes", S_DIM)], max_x=c.x1) + s.spans(c.x0 + 4, y + 1, [("1 ", S_DIM), ("also update the README screenshots", S)], max_x=c.x1) + s.spans(c.x0 + 4, y + 2, [("2 ", S_DIM), ("run the full test suite before you finish", S)], max_x=c.x1) + footer(s, c, [("Enter", "queue"), ("↑", "edit queued"), ("Ctrl+c", "stop"), ("Ctrl+x", "shortcuts")] if not c.narrow else [("Enter", "queue"), ("Ctrl+c", "stop")]) + + +def board_files_picker(s, c): + header(s, c) + top = composer(s, c, content=[("explain ", S), ("@comp", S_ACC)]) + paths = [ + ("src/cortex-tui/src/composer.rs", "212 lines"), + ("src/cortex-tui/src/tests/composer.rs", "88 lines"), + ("src/cortex-core/src/components/mod.rs", "1.4k lines"), + ("docs/guides/composer.md", "61 lines"), + ] + rows = [] + for path, meta in paths: + k = path.lower().find("comp") + rows.append(([(path[:k], S), (path[k : k + 4], S_ACC), (path[k + 4 :], S)], meta)) + menu_top = menu(s, c, top, rows, focused=0, hover=2, name_w=40) + backdrop_tail(s, c, menu_top) + footer(s, c, [("Enter", "attach"), ("Tab", "complete"), ("Esc", "close")]) + + +def board_jobs(s, c): + header(s, c) + top = composer(s, c, content=[("/jobs", S_ACC), (" ", S)]) + rows = [ + ([("⠇ ", S), ("cloud · fix login redirect", S)], "running · 4m · cortex/fix-login-redirect"), + ([("✓ ", S_OK), ("subagent · explore test layout", S)], "done · 1m 12s · 3 files read"), + ([("○ ", S_DIM), ("queued · refresh README screenshots", S)], "starts when the current step finishes"), + ] + menu_top = menu(s, c, top, rows, focused=0, name_w=38) + s.spans(c.x0 + 2, menu_top - 2, [("Jobs", S), (" · 1 running · 1 queued", S_DIM)], max_x=c.x1) + backdrop_tail(s, c, menu_top - 2) + footer(s, c, [("Enter", "open"), ("x", "cancel"), ("Esc", "close")]) + + +def board_skills(s, c): + header(s, c) + top = composer(s, c, content=[("/skills", S_ACC), (" ", S)]) + rows = [ + ([("release-notes", S)], "Draft release notes from the git log · project"), + ([("pdf-report", S)], "Render a PDF from a markdown report · user"), + ([("db-migrate", S)], "Write and verify a schema migration · project"), + ] + menu_top = menu(s, c, top, rows, focused=0, name_w=18) + search_field(s, c.x0 + 2, menu_top - 3, c.inner_w - 4, placeholder="Type to search skills") + backdrop_tail(s, c, menu_top - 3) + footer(s, c, [("Enter", "run"), ("r", "reload"), ("Esc", "close")]) + + +def board_todos(s, c): + header(s, c) + top = composer(s, c, placeholder="Add a follow-up — Enter to queue", focused=False, caret=False) + f = Flow(s, c, limit=top - 1) + f.user("move the model chip into the composer border", "04:11 PM") + f.thought("Thought for 2.6s") + f.line([("⠇", S), (" Working 2/5", S), (" · 38s · 6.1k tokens", S_DIM)]) + f.line([("✓ ", S_OK), ("Read composer.rs and footer.rs", S_DIM)], indent=2) + f.line([("✓ ", S_OK), ("Locate the chip painter", S_DIM)], indent=2) + f.line([("› ", S), ("Move the chip into the bottom hairline", S)], indent=2) + f.line([("○ ", S_DIM), ("Drop the model from the footer", S_DIM)], indent=2) + f.line([("○ ", S_DIM), ("Run the TUI snapshot tests", S_DIM)], indent=2) + footer(s, c, [("Esc", "interrupt"), ("Enter", "queue follow-up"), ("Ctrl+x", "shortcuts")]) + + +def board_question(s, c): + header(s, c) + top = composer(s, c, focused=False, caret=False, placeholder="Choose an option above, or type your own answer") + f = Flow(s, c, limit=top - 1) + f.user("add retry with backoff to the api client", "11:20 AM") + f.thought("Thought for 1.9s") + f.line([("●", S_DIM), (" Which failures should be retried?", S)]) + f.options(["Timeouts and 5xx only (recommended)", "Every network error", "Let me decide per call site"], focused=0) + footer(s, c, [("↑↓", "select"), ("Enter", "answer"), ("Esc", "skip")]) + + +def board_sudo(s, c): + header(s, c) + top = composer(s, c, focused=False, caret=False, placeholder="Enter the password above") + f = Flow(s, c, limit=top - 1) + f.user("install the system deps", "02:40 PM") + f.thought("Thought for 0.7s") + f.tile("Shell", "$ sudo apt-get install -y libssl-dev") + f.command("Password for mathis: ••••••••") + s.caret = (f.tx + len("Password for mathis: ••••••••"), f.y - 1) + f.dim("Never stored, logged, or shown to the model — sent straight to sudo.", indent=2) + footer(s, c, [("Enter", "submit"), ("Esc", "cancel")]) + + +def board_config_tree(s, c): + header(s, c) + top = composer(s, c, content=[("/config", S_ACC)], caret=False) + f = Flow(s, c, limit=top - 1) + f.user("/config", "05:30 PM") + f.line([("~/.cortex/config.json", S), (" · read-only view · edit with your editor", S_DIM)]) + g = S_DIM + rows = [ + ("model", "cortex-1-mini"), + ("effort", "medium"), + ("permissions", "smart"), + ("sandbox", "workspace"), + ("tui.alternate_screen", "true"), + ("tui.theme.name", "cortex-night"), + ("tui.animations", "true"), + ("mcp.servers", "github · filesystem · linear · sentry"), + ] + for k, v in rows: + f.line([(k.ljust(24), g), (v, S)], indent=2) + footer(s, c) + + +def board_btw(s, c): + header(s, c) + top = composer(s, c) + f = Flow(s, c, limit=top - 1) + f.user("run the tui tests and fix whatever fails", "09:14 AM") + f.thought("Thought for 2.1s") + f.tile("Shell", "$ cargo test -p cortex-tui", "running · 8s", glyph="⠇", glyph_st=S) + f.blank() + f.user("/btw what is the difference between Plan and Ask?", "09:15 AM") + f.line([("♦", S_DIM), (" Side note", S_DIM), (" · answered without touching the running turn", S_MUTED)]) + f.blank() + f.reply(["**Plan** drafts an approach and waits for approval before editing. **Ask** never edits — it only answers questions about the codebase."], "09:15 AM") + footer(s, c, [("Esc", "interrupt"), ("Enter", "queue follow-up"), ("Ctrl+x", "shortcuts")]) + + +# --------------------------------------------------------------------------- # +# Registry — (id, painter, meta). ``narrow`` = also rendered at 40×12. +# --------------------------------------------------------------------------- # + +SECTIONS = { + "A": "Entry / welcome", + "B": "Session", + "C": "Slash + model", + "D": "Settings", + "E": "Modes / tools / errors", +} + +# (id, painter, narrow_too, section, description) +BOARDS_META = [ + # A. Entry / welcome + ("welcome-cortex", board_welcome_cortex, True, "A", "Cold start `cortex` — clean welcome, alternate screen, no shell echoes"), + ("welcome-agent", board_welcome_agent, True, "A", "Cold start `agent` — same chrome, agent wording + placeholder"), + ("first-run-tips", board_first_run, True, "A", "First launch — charcoal tips panel under the welcome"), + ("session-empty", board_session_empty, True, "A", "Resumed / after first turn — header, composer, footer only"), + # B. Session + ("session-user-bars", board_session_user_bars, True, "B", "Two user prompt bars + timestamps, Thought, reply, Worked, ▼ more, opt-in banner"), + ("session-thought", board_session_thought, False, "B", "`♦ Thought for Xs` collapsed"), + ("session-thought-expanded", board_session_thought_expanded, False, "B", "Thought expanded (Show thinking blocks = on)"), + ("session-thinking-live", board_session_thinking_live, True, "B", "Live `⠇ Thinking · 3s` while the turn runs"), + ("session-assistant", board_session_assistant, True, "B", "Plain reply with bold + bullets"), + ("session-worked", board_session_worked, False, "B", "`Worked for Xs` after a reply"), + ("session-optin", board_session_optin, True, "B", "`Help improve Cortex` banner — Opt out | Opt in"), + ("session-optin-hover", board_session_optin_hover, False, "B", "Banner with the mouse over `[Opt in]`"), + ("composer-empty", board_composer_empty, True, "B", "Empty composer — caret before the placeholder, violet `>`"), + ("composer-typing", board_composer_typing, True, "B", "Mid-type, caret on"), + ("composer-typing-blink", board_composer_typing_blink, False, "B", "Mid-type, caret off (blink phase)"), + ("composer-hover", board_composer_hover, True, "B", "Mouse over the composer — hairline lifts to #525252"), + ("composer-multiline", board_composer_multiline, False, "B", "Alt+Enter newlines — box grows upward"), + ("footer-shortcuts", board_footer_shortcuts, False, "B", "Footer strip with text typed (4 hints)"), + ("footer-hover", board_footer_hover, False, "B", "Mouse over `Ctrl+x:shortcuts`"), + ("tokens-topright", board_tokens_topright, True, "B", "Token counter `142K / 500K` top-right"), + ("tokens-topright-warn", board_tokens_topright_warn, False, "B", "Counter ≥ 90 % — amber + /compact hint"), + ("compact-chat", board_compact_chat, True, "B", "Compact mode — edge-to-edge bars, no timestamps"), + # C. Slash + model + ("slash-palette", board_slash_palette, True, "C", "`/` palette — focused row + hover row + `… more` trailer"), + ("slash-model-typed", board_slash_model_typed, True, "C", "`/mod` typed — violet matched chars, ghost completion"), + ("model-list", board_model_list, True, "C", "`/model` — Cortex Mini 1 · Cortex 1 · Cortex Max 1"), + ("model-list-hover", board_model_list_hover, False, "C", "Model list with mouse over row 3"), + ("model-effort-high", board_model_effort_high, True, "C", "Effort radios — High focused"), + ("model-effort-medium", board_model_effort_medium, False, "C", "Effort radios — Medium focused"), + ("model-effort-low", board_model_effort_low, False, "C", "Effort radios — Low focused"), + ("model-effort-hover", board_model_effort_hover, False, "C", "Effort radios — Medium focused, mouse over Low"), + # D. Settings + ("settings-appearance", board_settings_appearance, True, "D", "Settings modal — Appearance, Compact mode focused"), + ("settings-mouse", board_settings_mouse, True, "D", "Settings scrolled to Mouse / Behavior"), + ("settings-row-hover", board_settings_row_hover, True, "D", "Keyboard focus on Compact mode, mouse over Show timestamps"), + ("settings-search", board_settings_search, False, "D", "`/ scro` search — filtered rows, violet match"), + ("settings-theme-submenu", board_settings_theme_submenu, True, "D", "Theme submenu — Cortex Night / Cortex Day / Ocean Dark / Monokai"), + # E. Modes / tools / errors + ("mode-agent", board_mode_agent, False, "E", "Agent mode — dim chip in the composer border"), + ("mode-plan", board_mode_plan, True, "E", "Plan mode — `Plan · no edits` chip, plan reply"), + ("mode-ask", board_mode_ask, True, "E", "Ask mode — `Ask · read-only` chip"), + ("mode-bash", board_mode_bash, False, "E", "Bash mode (`!`) — chip + `!` sigil"), + ("permission-prompt", board_permission_prompt, True, "E", "Exec approval — command on gray, numbered radios"), + ("permission-prompt-hover", board_permission_prompt_hover, False, "E", "Exec approval with mouse over option 2"), + ("permissions-picker", board_permissions_picker, False, "E", "`/permissions` — Smart / Read-only / Full access"), + ("mcp-servers", board_mcp_servers, True, "E", "`/mcp` — connected ✓, authenticating, failed ×"), + ("mcp-drop", board_mcp_drop, False, "E", "MCP server dropped mid-turn (error red)"), + ("plugins", board_plugins, False, "E", "`/plugins` — enabled / disabled rows"), + ("usage", board_usage, True, "E", "`/usage` — plan bars"), + ("quota-exhausted", board_quota_exhausted, False, "E", "Agent quota exhausted — red title, held composer"), + ("sandbox", board_sandbox, False, "E", "`/sandbox` — filesystem / network / escalation"), + ("sandbox-deny", board_sandbox_deny, False, "E", "Sandbox blocked a command — red title, radios"), + ("cloud-handoff", board_cloud_handoff, False, "E", "`&` handoff to Cortex Cloud"), + ("diagnostics", board_diagnostics, True, "E", "Diagnostics tile — error red, warn amber"), + ("interrupt-stopped", board_interrupt_stopped, True, "E", "Esc / Ctrl+c — `× Stopped`"), + ("error-unavailable", board_error_unavailable, False, "E", "API down — product-facing error"), + ("tool-tiles", board_tool_tiles, False, "E", "Grouped tool calls expanded — Read / Grep / Shell"), + ("tool-tiles-collapsed", board_tool_tiles_collapsed, False, "E", "Grouped tool calls collapsed"), + ("shell-running", board_shell_running, False, "E", "Live Shell tile with output"), + ("diff-hunk", board_diff_hunk, True, "E", "Edit tile + unified hunk — green +, red −"), + ("edit-collapsed", board_edit_collapsed, False, "E", "Collapsed edit blocks (setting on)"), + ("md-table", board_md_table, False, "E", "Markdown table — gray plus-ASCII grid"), + ("code-fence", board_code_fence, False, "E", "Fenced code — language tag hairline, gutter, bold keywords"), + ("login", board_login, True, "E", "`cortex login` — inline picker"), + ("login-waiting", board_login_waiting, False, "E", "Waiting for browser + device code"), + ("login-success", board_login_success, False, "E", "`✓ Signed in`"), + ("login-error", board_login_error, False, "E", "Sign-in failed — product copy"), + ("shortcuts-overlay", board_shortcuts_overlay, True, "E", "Ctrl+x shortcuts overlay"), + ("resume-picker", board_resume_picker, False, "E", "`/resume` — search field + session rows"), + ("clear-confirm", board_clear_confirm, False, "E", "`/clear` confirm radios"), + ("plan-confirm", board_plan_confirm, False, "E", "`Implement this plan?` radios"), + ("queue", board_queue, False, "E", "Follow-up queue while a step runs"), + ("files-picker", board_files_picker, False, "E", "`@` file picker — violet matched chars, hover row"), + ("jobs", board_jobs, False, "E", "`/jobs` — cloud agent, subagent, queued"), + ("skills", board_skills, False, "E", "`/skills` — search field + skill rows"), + ("todos", board_todos, False, "E", "Working 2/5 checklist — ✓ done · › current · ○ pending"), + ("question", board_question, False, "E", "Clarifying question radios"), + ("sudo", board_sudo, False, "E", "Elevated Shell — password row on gray"), + ("config-tree", board_config_tree, False, "E", "`/config` read-only key tree"), + ("btw", board_btw, False, "E", "`/btw` side note during a running turn"), +] + +BOARDS = [(bid, fn, {"narrow": narrow, "section": sec, "desc": desc}) for bid, fn, narrow, sec, desc in BOARDS_META] diff --git a/docs/media/tui-lock-v2/tools/render_lock_v2.py b/docs/media/tui-lock-v2/tools/render_lock_v2.py new file mode 100644 index 0000000..0191d13 --- /dev/null +++ b/docs/media/tui-lock-v2/tools/render_lock_v2.py @@ -0,0 +1,465 @@ +#!/usr/bin/env python3 +"""Cortex CLI — TUI lock v2 board renderer. + +Design-only tool. It paints a fixed character grid (a headless "terminal") +from the board recipes in ``boards.py`` and rasterises each grid to PNG with +IBM Plex Mono, so that every hex value in the chrome contract survives +pixel-exact. Box-drawing glyphs are drawn as vectors so hairlines are crisp +at any cell size. A plain-text dump of every grid is written next to the +PNGs so implementers can diff a MockTerminal capture against the lock. + +Usage: + python3 render_lock_v2.py --out ../ --sizes 120x40,40x12 + python3 render_lock_v2.py --only welcome-cortex,settings-appearance + +Fonts: IBM Plex Mono is fetched on first run into ``~/.cache/cortex-lock-v2`` +(override with ``--font-dir``). Glyphs missing from Plex (``♦ ▸ ▼ ● ○ ⠇``) +fall back to DejaVu Sans Mono from the system. +""" + +from __future__ import annotations + +import argparse +import os +import sys +import urllib.request +from dataclasses import dataclass, field, replace +from pathlib import Path + +from PIL import Image, ImageDraw, ImageFont + +# --------------------------------------------------------------------------- # +# Chrome contract (the only colours a board may use) +# --------------------------------------------------------------------------- # + +TOKENS = { + "bg": "#000000", + "text": "#F5F5F5", + "dim": "#6B7280", + "muted": "#4B5563", + "hairline": "#3A3A3A", + "hairline_hover": "#525252", + "panel": "#141414", + "bar_user": "#1C1C1C", + "bar_hover": "#1A1A1A", + "bar_selected": "#262626", + "accent": "#A78BFA", + "success": "#4ADE80", + "warning": "#FFC857", + "error": "#F87171", +} + +BG = TOKENS["bg"] +TEXT = TOKENS["text"] +DIM = TOKENS["dim"] +MUTED = TOKENS["muted"] +HAIR = TOKENS["hairline"] +HAIR_HI = TOKENS["hairline_hover"] +PANEL = TOKENS["panel"] +BAR_USER = TOKENS["bar_user"] +BAR_HOV = TOKENS["bar_hover"] +BAR_SEL = TOKENS["bar_selected"] +VIOLET = TOKENS["accent"] +GREEN = TOKENS["success"] +AMBER = TOKENS["warning"] +RED = TOKENS["error"] + +# Cell geometry: IBM Plex Mono advance is 0.6 em, so 20 px → 12 px per column; +# its ascent+descent (1025+275) is 1.3 em → 26 px per row. +FONT_PX = 20 +CELL_W = 12 +CELL_H = 26 +BASELINE = 20 +PAD = 12 + +BOX_CHARS = set("─│╭╮╰╯┌┐└┘├┤┬┴┼") + + +@dataclass(frozen=True) +class St: + fg: str = TEXT + bg: str | None = None + b: bool = False + i: bool = False + u: bool = False + + def __call__(self, **kw) -> "St": + return replace(self, **kw) + + +S = St() +S_DIM = St(fg=DIM) +S_MUTED = St(fg=MUTED) +S_HAIR = St(fg=HAIR) +S_ACC = St(fg=VIOLET) +S_BOLD = St(b=True) +S_OK = St(fg=GREEN) +S_WARN = St(fg=AMBER) +S_ERR = St(fg=RED) + + +@dataclass +class Cell: + ch: str = " " + fg: str = TEXT + bg: str = BG + b: bool = False + i: bool = False + u: bool = False + + +@dataclass +class Screen: + cols: int + rows: int + cells: list = field(default_factory=list) + caret: tuple | None = None # (x, y) bar caret drawn by the renderer + + def __post_init__(self): + self.cells = [[Cell() for _ in range(self.cols)] for _ in range(self.rows)] + + # -- primitives ------------------------------------------------------- # + def cell(self, x: int, y: int) -> Cell | None: + if 0 <= x < self.cols and 0 <= y < self.rows: + return self.cells[y][x] + return None + + def put(self, x: int, y: int, s: str, st: St = S, max_x: int | None = None) -> int: + """Write ``s`` at (x, y); returns the next column. Clips at max_x/cols.""" + limit = self.cols if max_x is None else min(max_x, self.cols) + for ch in s: + if x >= limit: + break + c = self.cell(x, y) + if c is not None: + c.ch = ch + c.fg = st.fg + if st.bg is not None: + c.bg = st.bg + c.b, c.i, c.u = st.b, st.i, st.u + x += 1 + return x + + def spans(self, x: int, y: int, parts, max_x: int | None = None) -> int: + for text, st in parts: + x = self.put(x, y, text, st, max_x) + return x + + def right(self, y: int, s: str, x_end: int, st: St = S) -> int: + """Right-align ``s`` so its last glyph sits at column ``x_end - 1``.""" + return self.put(x_end - len(s), y, s, st) + + def right_spans(self, y: int, parts, x_end: int) -> int: + total = sum(len(t) for t, _ in parts) + return self.spans(x_end - total, y, parts) + + def center(self, y: int, s: str, x0: int, x1: int, st: St = S) -> int: + w = x1 - x0 + return self.put(x0 + max(0, (w - len(s)) // 2), y, s, st) + + def center_spans(self, y: int, parts, x0: int, x1: int) -> int: + total = sum(len(t) for t, _ in parts) + return self.spans(x0 + max(0, (x1 - x0 - total) // 2), y, parts) + + def fill(self, x0: int, y: int, x1: int, bg: str): + for x in range(max(0, x0), min(x1, self.cols)): + c = self.cells[y][x] + c.bg = bg + + def fill_rect(self, x0: int, y0: int, x1: int, y1: int, bg: str): + for y in range(max(0, y0), min(y1, self.rows)): + self.fill(x0, y, x1, bg) + + def clear_rect(self, x0: int, y0: int, x1: int, y1: int, bg: str = BG): + for y in range(max(0, y0), min(y1, self.rows)): + for x in range(max(0, x0), min(x1, self.cols)): + self.cells[y][x] = Cell(bg=bg) + + def hline(self, y: int, x0: int, x1: int, fg: str = HAIR): + for x in range(max(0, x0), min(x1, self.cols)): + self.put(x, y, "─", St(fg=fg)) + + def vline(self, x: int, y0: int, y1: int, fg: str = HAIR): + for y in range(max(0, y0), min(y1, self.rows)): + self.put(x, y, "│", St(fg=fg)) + + def box(self, x: int, y: int, w: int, h: int, fg: str = HAIR, rounded: bool = True): + tl, tr, bl, br = ("╭", "╮", "╰", "╯") if rounded else ("┌", "┐", "└", "┘") + st = St(fg=fg) + self.hline(y, x + 1, x + w - 1, fg) + self.hline(y + h - 1, x + 1, x + w - 1, fg) + self.vline(x, y + 1, y + h - 1, fg) + self.vline(x + w - 1, y + 1, y + h - 1, fg) + self.put(x, y, tl, st) + self.put(x + w - 1, y, tr, st) + self.put(x, y + h - 1, bl, st) + self.put(x + w - 1, y + h - 1, br, st) + + def text_dump(self) -> str: + lines = [] + for row in self.cells: + lines.append("".join(c.ch for c in row).rstrip()) + return "\n".join(lines) + "\n" + + +def clip(s: str, width: int) -> str: + if width <= 0: + return "" + if len(s) <= width: + return s + if width == 1: + return "…" + return s[: width - 1] + "…" + + +# --------------------------------------------------------------------------- # +# Fonts +# --------------------------------------------------------------------------- # + +PLEX_FILES = { + ("regular", False): "IBMPlexMono-Regular.ttf", + ("regular", True): "IBMPlexMono-Italic.ttf", + ("bold", False): "IBMPlexMono-Bold.ttf", + ("bold", True): "IBMPlexMono-BoldItalic.ttf", +} +PLEX_URL = "https://raw.githubusercontent.com/google/fonts/main/ofl/ibmplexmono/{}" +SYSTEM_FONTS = Path("/usr/share/fonts/truetype") +# Symbol fallbacks, in order: `♦ ▸ ▼ ● ○` come from DejaVu Sans Mono, the +# braille spinner `⠇` from Cascadia Mono / DejaVu Sans. All monospace-ish at 12 px. +FALLBACKS = [ + ("dejavu/DejaVuSansMono.ttf", "dejavu/DejaVuSansMono-Bold.ttf"), + ("cascadia/CascadiaMono.ttf", "cascadia/CascadiaMono.ttf"), + ("dejavu/DejaVuSans.ttf", "dejavu/DejaVuSans-Bold.ttf"), +] + + +class Fonts: + def __init__(self, font_dir: Path): + font_dir.mkdir(parents=True, exist_ok=True) + self.plex = {} + for key, name in PLEX_FILES.items(): + path = font_dir / name + if not path.exists(): + url = PLEX_URL.format(name) + print(f"fetching {url}", file=sys.stderr) + urllib.request.urlretrieve(url, path) + self.plex[key] = ImageFont.truetype(str(path), FONT_PX) + self._plex_cmap = self._cmap(font_dir / PLEX_FILES[("regular", False)]) + self.fallbacks = [] # (cmap, regular, bold) + for regular, bold in FALLBACKS: + rp, bp = SYSTEM_FONTS / regular, SYSTEM_FONTS / bold + if rp.exists(): + self.fallbacks.append( + (self._cmap(rp), ImageFont.truetype(str(rp), FONT_PX), ImageFont.truetype(str(bp if bp.exists() else rp), FONT_PX)) + ) + + @staticmethod + def _cmap(path: Path) -> set: + try: + from fontTools.ttLib import TTFont + + return set(TTFont(str(path)).getBestCmap().keys()) + except Exception: # pragma: no cover - fontTools optional + return set(range(0x20, 0x7F)) + + def pick(self, ch: str, bold: bool, italic: bool) -> ImageFont.FreeTypeFont: + if ord(ch) in self._plex_cmap: + return self.plex[("bold" if bold else "regular", italic)] + for cmap, regular, bold_font in self.fallbacks: + if ord(ch) in cmap: + return bold_font if bold else regular + return self.plex[("bold" if bold else "regular", italic)] + + +# --------------------------------------------------------------------------- # +# Rasteriser +# --------------------------------------------------------------------------- # + + +def _draw_box_char(draw: ImageDraw.ImageDraw, ch: str, x0: int, y0: int, color: str): + w, h = CELL_W, CELL_H + xm = x0 + w // 2 - 1 # 2 px stroke centred on the cell + ym = y0 + h // 2 - 1 + r = w // 2 + + def hseg(a, b): + draw.rectangle([a, ym, b - 1, ym + 1], fill=color) + + def vseg(a, b): + draw.rectangle([xm, a, xm + 1, b - 1], fill=color) + + left, right, top, bottom = x0, x0 + w, y0, y0 + h + if ch == "─": + hseg(left, right) + elif ch == "│": + vseg(top, bottom) + elif ch == "┌": + hseg(xm, right) + vseg(ym, bottom) + elif ch == "┐": + hseg(left, xm + 2) + vseg(ym, bottom) + elif ch == "└": + hseg(xm, right) + vseg(top, ym + 2) + elif ch == "┘": + hseg(left, xm + 2) + vseg(top, ym + 2) + elif ch == "├": + vseg(top, bottom) + hseg(xm, right) + elif ch == "┤": + vseg(top, bottom) + hseg(left, xm + 2) + elif ch == "┬": + hseg(left, right) + vseg(ym, bottom) + elif ch == "┴": + hseg(left, right) + vseg(top, ym + 2) + elif ch == "┼": + hseg(left, right) + vseg(top, bottom) + elif ch in "╭╮╰╯": + # quarter arcs of radius r joining the cell mid-lines + if ch == "╭": + cx, cy = xm + r, ym + r + draw.arc([cx - r, cy - r, cx + r + 1, cy + r + 1], 180, 270, fill=color, width=2) + vseg(ym + r, bottom) + elif ch == "╮": + cx, cy = xm + 1 - r, ym + r + draw.arc([cx - r, cy - r, cx + r + 1, cy + r + 1], 270, 360, fill=color, width=2) + vseg(ym + r, bottom) + elif ch == "╰": + cx, cy = xm + r, ym + 1 - r + draw.arc([cx - r, cy - r, cx + r + 1, cy + r + 1], 90, 180, fill=color, width=2) + vseg(top, ym + 1 - r + 1) + else: # ╯ + cx, cy = xm + 1 - r, ym + 1 - r + draw.arc([cx - r, cy - r, cx + r + 1, cy + r + 1], 0, 90, fill=color, width=2) + vseg(top, ym + 1 - r + 1) + + +def rasterise(screen: Screen, fonts: Fonts) -> Image.Image: + width = screen.cols * CELL_W + PAD * 2 + height = screen.rows * CELL_H + PAD * 2 + img = Image.new("RGB", (width, height), BG) + draw = ImageDraw.Draw(img) + + # backgrounds first so glyph anti-aliasing blends onto the right bar colour + for y, row in enumerate(screen.cells): + for x, c in enumerate(row): + if c.bg != BG: + px, py = PAD + x * CELL_W, PAD + y * CELL_H + draw.rectangle([px, py, px + CELL_W - 1, py + CELL_H - 1], fill=c.bg) + + for y, row in enumerate(screen.cells): + for x, c in enumerate(row): + px, py = PAD + x * CELL_W, PAD + y * CELL_H + if c.ch == " ": + pass + elif c.ch in BOX_CHARS: + _draw_box_char(draw, c.ch, px, py, c.fg) + else: + font = fonts.pick(c.ch, c.b, c.i) + draw.text((px, py + BASELINE), c.ch, font=font, fill=c.fg, anchor="ls") + if c.u: + draw.rectangle([px, py + BASELINE + 3, px + CELL_W - 1, py + BASELINE + 3], fill=c.fg) + + if screen.caret is not None: + cx, cy = screen.caret + px, py = PAD + cx * CELL_W, PAD + cy * CELL_H + draw.rectangle([px, py + 3, px + 1, py + CELL_H - 4], fill=TEXT) + return img + + +# --------------------------------------------------------------------------- # +# index.md +# --------------------------------------------------------------------------- # + + +def render_index(boards, sizes) -> str: + wide = [s for s in sizes if int(s.split("x")[0]) >= 80] + narrow = [s for s in sizes if int(s.split("x")[0]) < 80] + wide_dir = wide[0] if wide else "120x40" + narrow_dir = narrow[0] if narrow else "40x12" + lines = [ + "# Cortex CLI — TUI lock v2 · board index", + "", + "Design-only pack for the full TUI redesign (reference layout language, Cortex chrome).", + f"Every board exists at **{wide_dir}**; boards where density matters also at **{narrow_dir}**.", + "Text dumps of each grid live in `txt//.txt`. Spec: [`SPEC.md`](SPEC.md).", + "", + "Regenerate: `python3 tools/render_lock_v2.py --index` (fetches IBM Plex Mono on first run).", + "", + ] + total_w = total_n = 0 + for sec_key, sec_name in boards.SECTIONS.items(): + rows = [(bid, meta) for bid, _, meta in boards.BOARDS if meta["section"] == sec_key] + lines += [f"## {sec_key}. {sec_name}", "", "| Board | State | Wide | Narrow |", "|---|---|---|---|"] + for bid, meta in rows: + total_w += 1 + w_link = f"[{wide_dir}]({wide_dir}/{bid}.png)" + if meta.get("narrow"): + total_n += 1 + n_link = f"[{narrow_dir}]({narrow_dir}/{bid}.png)" + else: + n_link = "—" + lines.append(f"| `{bid}` | {meta['desc']} | {w_link} | {n_link} |") + lines.append("") + lines += [f"**{total_w}** boards at {wide_dir} · **{total_n}** at {narrow_dir} · {total_w + total_n} PNGs.", ""] + return "\n".join(lines) + + +# --------------------------------------------------------------------------- # +# CLI +# --------------------------------------------------------------------------- # + + +def main(argv=None) -> int: + here = Path(__file__).resolve().parent + sys.path.insert(0, str(here)) + import boards # noqa: E402 (local module) + + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--out", default=str(here.parent), help="lock directory (default: parent of tools/)") + ap.add_argument("--sizes", default="120x40,40x12") + ap.add_argument("--only", default="", help="comma-separated board ids") + ap.add_argument("--font-dir", default=os.environ.get("CORTEX_LOCK_FONT_DIR", str(Path.home() / ".cache/cortex-lock-v2"))) + ap.add_argument("--no-txt", action="store_true") + ap.add_argument("--index", action="store_true", help="also (re)write index.md next to the size folders") + args = ap.parse_args(argv) + + fonts = Fonts(Path(args.font_dir)) + out = Path(args.out) + only = {s.strip() for s in args.only.split(",") if s.strip()} + if args.index: + (out / "index.md").write_text(render_index(boards, args.sizes.split(",")), encoding="utf-8") + written = [] + for size in args.sizes.split(","): + cols, rows = (int(v) for v in size.lower().split("x")) + narrow = cols < 80 + png_dir = out / size + txt_dir = out / "txt" / size + png_dir.mkdir(parents=True, exist_ok=True) + if not args.no_txt: + txt_dir.mkdir(parents=True, exist_ok=True) + for board_id, fn, meta in boards.BOARDS: + if only and board_id not in only: + continue + if narrow and not meta.get("narrow", False): + continue + screen = Screen(cols, rows) + fn(screen, boards.Ctx(cols, rows, narrow)) + img = rasterise(screen, fonts) + path = png_dir / f"{board_id}.png" + img.save(path, optimize=True) + written.append(path) + if not args.no_txt: + (txt_dir / f"{board_id}.txt").write_text(screen.text_dump(), encoding="utf-8") + print(f"wrote {len(written)} boards under {out}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/docs/media/tui-lock-v2/txt/120x40/btw.txt b/docs/media/tui-lock-v2/txt/120x40/btw.txt new file mode 100644 index 0000000..e83a0eb --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/btw.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ⠇ Shell $ cargo test -p cortex-tui · running · 8s + + > /btw what is the difference between Plan and Ask? 09:15 AM + + ♦ Side note · answered without touching the running turn + + Plan drafts an approach and waits for approval before editing. Ask never edits — it only answers 09:15 AM + questions about the codebase. + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Esc:interrupt | Enter:queue follow-up | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/clear-confirm.txt b/docs/media/tui-lock-v2/txt/120x40/clear-confirm.txt new file mode 100644 index 0000000..d1e1f38 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/clear-confirm.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + Clear this conversation? + The transcript is dropped. Git, files and config stay as they are. + > 1 Yes, clear + 2 No, keep it + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /clear │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:confirm | Esc:cancel diff --git a/docs/media/tui-lock-v2/txt/120x40/cloud-handoff.txt b/docs/media/tui-lock-v2/txt/120x40/cloud-handoff.txt new file mode 100644 index 0000000..0abc117 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/cloud-handoff.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > & fix the flaky login redirect test and open a PR 03:02 PM + + ↑ Handed off to Cortex Cloud + agent ag_4f2a · running + branch cortex/fix-login-redirect + follow cortex.foundation/agents/ag_4f2a · or /jobs right here + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/code-fence.txt b/docs/media/tui-lock-v2/txt/120x40/code-fence.txt new file mode 100644 index 0000000..3249b0b --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/code-fence.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > show me a minimal retry helper 05:12 PM + + ♦ Thought for 1.0s + + ─ rust ──────────────────────────────────────────────────────────────────────────────────────────────────────────── + 1 pub async fn with_retry(mut op: F) -> Result + 2 where F: FnMut() -> Fut>, + 3 { + 4 for attempt in 0..3 { + 5 match op().await { + 6 Ok(v) => return Ok(v), + 7 Err(e) if attempt == 2 => return Err(e), + 8 Err(_) => sleep(backoff(attempt)).await, + 9 } + 10 } + 11 unreachable!() + 12 } + ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/compact-chat.txt b/docs/media/tui-lock-v2/txt/120x40/compact-chat.txt new file mode 100644 index 0000000..4d49181 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/compact-chat.txt @@ -0,0 +1,40 @@ + 14K / 500K + > hey + ♦ Thought for 0.4s + Hey — what do you want to work on? + Worked for 1.8s + > tell me about yourself + ♦ Thought for 0.4s + I'm Cortex, a coding agent that runs in your terminal. + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. Here + I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + Worked for 4.6s + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/composer-empty.txt b/docs/media/tui-lock-v2/txt/120x40/composer-empty.txt new file mode 100644 index 0000000..c65c435 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/composer-empty.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/composer-hover.txt b/docs/media/tui-lock-v2/txt/120x40/composer-hover.txt new file mode 100644 index 0000000..c65c435 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/composer-hover.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/composer-multiline.txt b/docs/media/tui-lock-v2/txt/120x40/composer-multiline.txt new file mode 100644 index 0000000..b2b9964 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/composer-multiline.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > add retry with backoff to the api client: │ + │ - max 3 attempts, jitter │ + │ - surface the final error as product copy │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Alt+Enter:newline | Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/composer-typing-blink.txt b/docs/media/tui-lock-v2/txt/120x40/composer-typing-blink.txt new file mode 100644 index 0000000..6cfb3ca --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/composer-typing-blink.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > add retry with backoff to the api client │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Alt+Enter:newline | Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/composer-typing.txt b/docs/media/tui-lock-v2/txt/120x40/composer-typing.txt new file mode 100644 index 0000000..6cfb3ca --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/composer-typing.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > add retry with backoff to the api client │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Alt+Enter:newline | Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/config-tree.txt b/docs/media/tui-lock-v2/txt/120x40/config-tree.txt new file mode 100644 index 0000000..ba79cdb --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/config-tree.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > /config 05:30 PM + + ~/.cortex/config.json · read-only view · edit with your editor + model cortex-1-mini + effort medium + permissions smart + sandbox workspace + tui.alternate_screen true + tui.theme.name cortex-night + tui.animations true + mcp.servers github · filesystem · linear · sentry + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /config │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/diagnostics.txt b/docs/media/tui-lock-v2/txt/120x40/diagnostics.txt new file mode 100644 index 0000000..96d29b1 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/diagnostics.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > wire the model chip into the composer border 04:11 PM + + ♦ Thought for 2.6s + + ● Edit src/cortex-tui/src/composer.rs · +12 −3 + ● Diagnostics src/cortex-tui/src/composer.rs · 2 + error E0308 mismatched types — expected `Span`, found `String` composer.rs:42:9 + warn unused variable `hints` composer.rs:57:13 + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/diff-hunk.txt b/docs/media/tui-lock-v2/txt/120x40/diff-hunk.txt new file mode 100644 index 0000000..6894094 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/diff-hunk.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > move the model chip into the composer border 04:11 PM + + ♦ Thought for 2.6s + + ● Edit src/cortex-tui/src/composer.rs · +2 −1 + @@ -41,7 +41,8 @@ + 41 41 let chip = model_chip(state); + 42 - footer.push(chip); + 42 + border.push_right(chip); + 43 + footer.push(hints); + 43 44 Ok(()) + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/edit-collapsed.txt b/docs/media/tui-lock-v2/txt/120x40/edit-collapsed.txt new file mode 100644 index 0000000..1070726 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/edit-collapsed.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > move the model chip into the composer border 04:11 PM + + ♦ Thought for 2.6s + + ● Edit src/cortex-tui/src/composer.rs · +2 −1 · ▸ show diff + ● Edit src/cortex-tui/src/footer.rs · +4 −9 · ▸ show diff + + Moved the chip into the bottom hairline and dropped it from the footer. 04:12 PM + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/error-unavailable.txt b/docs/media/tui-lock-v2/txt/120x40/error-unavailable.txt new file mode 100644 index 0000000..2392620 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/error-unavailable.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > tell me about yourself 12:49 AM + + × The coding service is temporarily unavailable + Try again in a moment — your work so far is saved in this session. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Try again — your work so far is saved │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:retry | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/files-picker.txt b/docs/media/tui-lock-v2/txt/120x40/files-picker.txt new file mode 100644 index 0000000..e73e030 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/files-picker.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + > src/cortex-tui/src/composer.rs 212 lines + src/cortex-tui/src/tests/composer.rs 88 lines + src/cortex-core/src/components/mod.rs 1.4k lines + docs/guides/composer.md 61 lines + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > explain @comp │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:attach | Tab:complete | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/first-run-tips.txt b/docs/media/tui-lock-v2/txt/120x40/first-run-tips.txt new file mode 100644 index 0000000..0f622ec --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/first-run-tips.txt @@ -0,0 +1,40 @@ + 0 / 500K + + Welcome to Cortex, the coding agent CLI + v0.1.7 · / commands · @ files · ! shell · & cloud + + A few tips to get the most out of this tool: + 1. Use /model to switch between models and adjust reasoning effort. + 2. Add @ files to give Cortex the right context. + 3. Press Shift+Tab anytime to cycle Agent / Plan / Ask. + 4. Ctrl+x lists every shortcut · F2 opens settings. + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/footer-hover.txt b/docs/media/tui-lock-v2/txt/120x40/footer-hover.txt new file mode 100644 index 0000000..c65c435 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/footer-hover.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/footer-shortcuts.txt b/docs/media/tui-lock-v2/txt/120x40/footer-shortcuts.txt new file mode 100644 index 0000000..0ade72e --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/footer-shortcuts.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > hello │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Alt+Enter:newline | Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/interrupt-stopped.txt b/docs/media/tui-lock-v2/txt/120x40/interrupt-stopped.txt new file mode 100644 index 0000000..4d61618 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/interrupt-stopped.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ● Shell $ cargo test -p cortex-tui · stopped + × Stopped + Worked for 12s · 4.1k tokens + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Reply, or ↑ to edit your last message │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/jobs.txt b/docs/media/tui-lock-v2/txt/120x40/jobs.txt new file mode 100644 index 0000000..c8d4b14 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/jobs.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + Jobs · 1 running · 1 queued + + > ⠇ cloud · fix login redirect running · 4m · cortex/fix-login-redirect + ✓ subagent · explore test layout done · 1m 12s · 3 files read + ○ queued · refresh README screenshots starts when the current step finishes + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /jobs │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:open | x:cancel | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/login-error.txt b/docs/media/tui-lock-v2/txt/120x40/login-error.txt new file mode 100644 index 0000000..84bcb5d --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/login-error.txt @@ -0,0 +1,40 @@ + + Welcome to Cortex CLI! + + × Sign-in didn't complete + Your Cortex API key may be invalid, expired, or revoked. + Run 'cortex login' or set CORTEX_API_KEY, then try again. + + Enter:try again | Esc:quit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/media/tui-lock-v2/txt/120x40/login-success.txt b/docs/media/tui-lock-v2/txt/120x40/login-success.txt new file mode 100644 index 0000000..2385dab --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/login-success.txt @@ -0,0 +1,40 @@ + + Welcome to Cortex CLI! + + ✓ Signed in as mathis@cortex.foundation + + Run cortex to start a session. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/media/tui-lock-v2/txt/120x40/login-waiting.txt b/docs/media/tui-lock-v2/txt/120x40/login-waiting.txt new file mode 100644 index 0000000..8fa8232 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/login-waiting.txt @@ -0,0 +1,40 @@ + + Welcome to Cortex CLI! + + ⠇ Waiting for browser authentication… + + Your code WXYZ-1234 + If the browser didn't open, visit cortex.foundation/cli/auth and enter the code. + + Esc:cancel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/media/tui-lock-v2/txt/120x40/login.txt b/docs/media/tui-lock-v2/txt/120x40/login.txt new file mode 100644 index 0000000..9fd9e22 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/login.txt @@ -0,0 +1,40 @@ + + Welcome to Cortex CLI! + + How would you like to log in? + + > 1 Continue with browser Opens cortex.foundation/cli/auth + 2 Paste an API key Enter your key to authenticate + + ↑↓:select | Enter:confirm | Esc:quit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/media/tui-lock-v2/txt/120x40/mcp-drop.txt b/docs/media/tui-lock-v2/txt/120x40/mcp-drop.txt new file mode 100644 index 0000000..3388453 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/mcp-drop.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ● Shell $ cargo test -p cortex-tui · ✓ 0 · 41s + ● Read src/cortex-tui/src/composer.rs · 212 lines + ● Grep "alternate_screen" in src/ · 6 hits in 4 files + + × github dropped + Reconnecting 2/3 — tools from github are paused until it is back. + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/mcp-servers.txt b/docs/media/tui-lock-v2/txt/120x40/mcp-servers.txt new file mode 100644 index 0000000..eb05384 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/mcp-servers.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + MCP servers · 2 of 4 connected + + > ✓ github 12 tools · connected + ✓ filesystem 8 tools · connected + ⠇ linear authenticating… + × sentry failed — token expired · r to reconnect + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /mcp │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:details | r:reconnect | a:add server | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/md-table.txt b/docs/media/tui-lock-v2/txt/120x40/md-table.txt new file mode 100644 index 0000000..431f471 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/md-table.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > compare the models 05:00 PM + + ♦ Thought for 0.8s + + +-----------------+------------------+-----------+---------------+ + | Model | Default effort | Context | Billing | + +-----------------+------------------+-----------+---------------+ + | Cortex Mini 1 | Medium | 500K | per request | + | Cortex 1 | High | 500K | per request | + | Cortex Max 1 | High | 1M | per token | + +-----------------+------------------+-----------+---------------+ + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/mode-agent.txt b/docs/media/tui-lock-v2/txt/120x40/mode-agent.txt new file mode 100644 index 0000000..962c710 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/mode-agent.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ● Shell $ cargo test -p cortex-tui · ✓ 0 · 41s + ● Read src/cortex-tui/src/composer.rs · 212 lines + ● Grep "alternate_screen" in src/ · 6 hits in 4 files + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/mode-ask.txt b/docs/media/tui-lock-v2/txt/120x40/mode-ask.txt new file mode 100644 index 0000000..cb1f6d1 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/mode-ask.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > where is the alternate-screen default decided? 11:31 AM + + ♦ Thought for 1.1s + + `TuiConfig::default()` in `src/cortex-engine/src/config/types.rs` sets `alternate_screen: true`; the 11:31 AM + launcher reads it before entering the viewport. + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Ask · read-only ──────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Ask about the codebase — read-only │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/mode-bash.txt b/docs/media/tui-lock-v2/txt/120x40/mode-bash.txt new file mode 100644 index 0000000..bc67392 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/mode-bash.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Bash · runs in your shell ────────────────────────────────────────────────────────────────────────────────────────╮ + │ ! cargo test -p cortex-tui │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:run | Esc:leave bash | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/mode-plan.txt b/docs/media/tui-lock-v2/txt/120x40/mode-plan.txt new file mode 100644 index 0000000..bd40171 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/mode-plan.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > add retry with backoff to the api client 11:20 AM + + ♦ Thought for 5.8s + + Plan — no files change until you approve. 11:20 AM + + 1. Wrap `ApiClient::send` in a retry loop: 3 attempts, exponential backoff with jitter. + 2. Retry only on timeouts and 5xx; never on 4xx. + 3. Surface the final failure as product copy: 'The coding service is temporarily unavailable'. + 4. Unit tests for the backoff schedule and the give-up path. + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Plan · no edits ──────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Describe what you want — Cortex drafts a plan first │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/model-effort-high.txt b/docs/media/tui-lock-v2/txt/120x40/model-effort-high.txt new file mode 100644 index 0000000..49780ac --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/model-effort-high.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + > High Effort Deepest reasoning — best for hard, multi-file changes + Medium Effort Balanced reasoning for everyday coding · default + Low Effort Fastest responses for quick edits and questions + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /model Cortex Mini 1 │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:apply | Tab:back to models | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/model-effort-hover.txt b/docs/media/tui-lock-v2/txt/120x40/model-effort-hover.txt new file mode 100644 index 0000000..689b689 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/model-effort-hover.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + High Effort Deepest reasoning — best for hard, multi-file changes + > Medium Effort Balanced reasoning for everyday coding · default + Low Effort Fastest responses for quick edits and questions + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /model Cortex Mini 1 │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:apply | Tab:back to models | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/model-effort-low.txt b/docs/media/tui-lock-v2/txt/120x40/model-effort-low.txt new file mode 100644 index 0000000..d9ccd73 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/model-effort-low.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + High Effort Deepest reasoning — best for hard, multi-file changes + Medium Effort Balanced reasoning for everyday coding · default + > Low Effort Fastest responses for quick edits and questions + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /model Cortex Mini 1 │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:apply | Tab:back to models | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/model-effort-medium.txt b/docs/media/tui-lock-v2/txt/120x40/model-effort-medium.txt new file mode 100644 index 0000000..689b689 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/model-effort-medium.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + High Effort Deepest reasoning — best for hard, multi-file changes + > Medium Effort Balanced reasoning for everyday coding · default + Low Effort Fastest responses for quick edits and questions + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /model Cortex Mini 1 │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:apply | Tab:back to models | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/model-list-hover.txt b/docs/media/tui-lock-v2/txt/120x40/model-list-hover.txt new file mode 100644 index 0000000..3853a46 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/model-list-hover.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + > Cortex Mini 1 Fast default for everyday coding · current + Cortex 1 Deeper reasoning for hard changes + Cortex Max 1 Longest context — bills by token instead of per request · MAX + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /model │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:choose | Tab:effort | ↑↓:select | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/model-list.txt b/docs/media/tui-lock-v2/txt/120x40/model-list.txt new file mode 100644 index 0000000..3853a46 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/model-list.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + > Cortex Mini 1 Fast default for everyday coding · current + Cortex 1 Deeper reasoning for hard changes + Cortex Max 1 Longest context — bills by token instead of per request · MAX + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /model │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:choose | Tab:effort | ↑↓:select | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/permission-prompt-hover.txt b/docs/media/tui-lock-v2/txt/120x40/permission-prompt-hover.txt new file mode 100644 index 0000000..8408422 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/permission-prompt-hover.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > add ioredis and a mock for the tests 09:40 AM + + ♦ Thought for 1.4s + + ● Cortex wants to run + $ npm install ioredis && npm install -D ioredis-mock + > 1 Yes, run once + 2 Yes, always allow npm install in this project + 3 Edit command + 4 No — tell Cortex what to do instead + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Choose an option above │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + ↑↓:select | Enter:confirm | e:edit command | Esc:cancel diff --git a/docs/media/tui-lock-v2/txt/120x40/permission-prompt.txt b/docs/media/tui-lock-v2/txt/120x40/permission-prompt.txt new file mode 100644 index 0000000..8408422 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/permission-prompt.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > add ioredis and a mock for the tests 09:40 AM + + ♦ Thought for 1.4s + + ● Cortex wants to run + $ npm install ioredis && npm install -D ioredis-mock + > 1 Yes, run once + 2 Yes, always allow npm install in this project + 3 Edit command + 4 No — tell Cortex what to do instead + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Choose an option above │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + ↑↓:select | Enter:confirm | e:edit command | Esc:cancel diff --git a/docs/media/tui-lock-v2/txt/120x40/permissions-picker.txt b/docs/media/tui-lock-v2/txt/120x40/permissions-picker.txt new file mode 100644 index 0000000..e5d44d2 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/permissions-picker.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + Permissions · how Cortex asks before acting + + > ● Smart auto-approve safe reads · ask before edits · current + ○ Read-only never edit files or run commands + ○ Full access only ask when leaving the sandbox + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /permissions │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:apply | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/plan-confirm.txt b/docs/media/tui-lock-v2/txt/120x40/plan-confirm.txt new file mode 100644 index 0000000..f8b47ef --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/plan-confirm.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > add retry with backoff to the api client 11:20 AM + + ♦ Thought for 5.8s + + Plan — no files change until you approve. 11:21 AM + + 1. Wrap `ApiClient::send` in a retry loop: 3 attempts, exponential backoff with jitter. + 2. Retry only on timeouts and 5xx; never on 4xx. + 3. Surface the final failure as product copy: 'The coding service is temporarily unavailable'. + 4. Unit tests for the backoff schedule and the give-up path. + + Implement this plan? + > 1 Yes, switch to Agent mode and implement + 2 No, keep planning — tell Cortex what to change + + + + + + + + + + + + + + + + + + + + ╭─ Plan · no edits ──────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Choose an option above │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:confirm | Esc:keep planning diff --git a/docs/media/tui-lock-v2/txt/120x40/plugins.txt b/docs/media/tui-lock-v2/txt/120x40/plugins.txt new file mode 100644 index 0000000..e7504a7 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/plugins.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + Plugins · 2 of 3 enabled + + > ✓ cortex-review 1.2.0 · enabled · adds /review + ✓ mermaid-preview 0.4.1 · enabled + ○ jira 0.9.0 · disabled + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /plugins │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:toggle | i:install | u:update | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/question.txt b/docs/media/tui-lock-v2/txt/120x40/question.txt new file mode 100644 index 0000000..609ed4a --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/question.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > add retry with backoff to the api client 11:20 AM + + ♦ Thought for 1.9s + + ● Which failures should be retried? + > 1 Timeouts and 5xx only (recommended) + 2 Every network error + 3 Let me decide per call site + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Choose an option above, or type your own answer │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + ↑↓:select | Enter:answer | Esc:skip diff --git a/docs/media/tui-lock-v2/txt/120x40/queue.txt b/docs/media/tui-lock-v2/txt/120x40/queue.txt new file mode 100644 index 0000000..d343145 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/queue.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ⠇ Shell $ cargo test -p cortex-tui · running · 8s + + + + + + + + + + + + + + + + + + + + + + + + + + Queued · 2 — sent when the current step finishes + 1 also update the README screenshots + 2 run the full test suite before you finish + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Add a follow-up — Enter to queue │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:queue | ↑:edit queued | Ctrl+c:stop | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/quota-exhausted.txt b/docs/media/tui-lock-v2/txt/120x40/quota-exhausted.txt new file mode 100644 index 0000000..ebb6a12 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/quota-exhausted.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ● Shell $ cargo test -p cortex-tui · ✓ 0 · 41s + ● Read src/cortex-tui/src/composer.rs · 212 lines + ● Grep "alternate_screen" in src/ · 6 hits in 4 files + + × Agent quota exhausted + Agent requests 500 / 500 ████████████████████████ + Resets in 4h 12m. Switch to MAX token billing to continue now, or upgrade at cortex.foundation/billing + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Add a follow-up — held until quota resets │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + /usage:details | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/resume-picker.txt b/docs/media/tui-lock-v2/txt/120x40/resume-picker.txt new file mode 100644 index 0000000..6655104 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/resume-picker.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + Type to search sessions + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + > fix login redirect 2h ago · 14 messages · cortex/fix-login-redirect + composer chip design yesterday · 31 messages + bump version to 0.1.7 3 days ago · 6 messages + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /resume │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:resume | f:favorite | d:delete | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/sandbox-deny.txt b/docs/media/tui-lock-v2/txt/120x40/sandbox-deny.txt new file mode 100644 index 0000000..5e35f39 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/sandbox-deny.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > install the deps with the vendor script 02:15 PM + + ♦ Thought for 0.9s + + ● Shell $ curl -s https://example.com/install.sh | sh + × Sandbox denied + curl was blocked by the workspace sandbox. Network is allowlisted. + > 1 Keep blocked + 2 Allow once + 3 Allow for this session + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Choose an option above │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + ↑↓:select | Enter:confirm | Esc:cancel diff --git a/docs/media/tui-lock-v2/txt/120x40/sandbox.txt b/docs/media/tui-lock-v2/txt/120x40/sandbox.txt new file mode 100644 index 0000000..121172c --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/sandbox.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + Sandbox · ✓ On + + > Filesystem workspace only · ~/code/cortex + Network allowlist · registry.npmjs.org, github.com + Escalation ask before running outside the sandbox + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /sandbox │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Space:toggle | Enter:edit | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/session-assistant.txt b/docs/media/tui-lock-v2/txt/120x40/session-assistant.txt new file mode 100644 index 0000000..9b55e1b --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-assistant.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/session-empty.txt b/docs/media/tui-lock-v2/txt/120x40/session-empty.txt new file mode 100644 index 0000000..c65c435 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-empty.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/session-optin-hover.txt b/docs/media/tui-lock-v2/txt/120x40/session-optin-hover.txt new file mode 100644 index 0000000..bc0897e --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-optin-hover.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + + + + + + + + + + + + + + + + + + + + + Help improve Cortex [Opt out] [Opt in] + Off by default. Opt in to let Cortex retain coding data — prompts, traces & metrics — to improve the product. + Change anytime in /settings → Privacy. + Read Terms and Privacy Policy. + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/session-optin.txt b/docs/media/tui-lock-v2/txt/120x40/session-optin.txt new file mode 100644 index 0000000..bc0897e --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-optin.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + + + + + + + + + + + + + + + + + + + + + Help improve Cortex [Opt out] [Opt in] + Off by default. Opt in to let Cortex retain coding data — prompts, traces & metrics — to improve the product. + Change anytime in /settings → Privacy. + Read Terms and Privacy Policy. + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/session-thinking-live.txt b/docs/media/tui-lock-v2/txt/120x40/session-thinking-live.txt new file mode 100644 index 0000000..be043f1 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-thinking-live.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > why does the composer lose focus after /model? 10:02 AM + + ⠇ Thinking · 3s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Add a follow-up — Enter to queue │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Esc:interrupt | Enter:queue follow-up | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/session-thought-expanded.txt b/docs/media/tui-lock-v2/txt/120x40/session-thought-expanded.txt new file mode 100644 index 0000000..8a6a367 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-thought-expanded.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > why does the composer lose focus after /model? 10:02 AM + + ♦ Thought for 3.2s ▾ + + The user reports focus loss after the model picker closes. + Reading composer.rs — close_picker() early-returns when effort is open, + so focus_composer() is skipped. That matches the report. + + The picker steals focus and never hands it back. `close_picker()` returns early when the effort radios 10:02 AM + are open. + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/session-thought.txt b/docs/media/tui-lock-v2/txt/120x40/session-thought.txt new file mode 100644 index 0000000..b62baef --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-thought.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > why does the composer lose focus after /model? 10:02 AM + + ♦ Thought for 3.2s + + The picker steals focus and never hands it back. `close_picker()` returns early when the effort radios 10:02 AM + are open. + + Worked for 6.0s + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/session-user-bars.txt b/docs/media/tui-lock-v2/txt/120x40/session-user-bars.txt new file mode 100644 index 0000000..20d4546 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-user-bars.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + ▼ + + Help improve Cortex [Opt out] [Opt in] + Off by default. Opt in to let Cortex retain coding data — prompts, traces & metrics — to improve the product. + Change anytime in /settings → Privacy. + Read Terms and Privacy Policy. + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/session-worked.txt b/docs/media/tui-lock-v2/txt/120x40/session-worked.txt new file mode 100644 index 0000000..b9bcf99 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/session-worked.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/settings-appearance.txt b/docs/media/tui-lock-v2/txt/120x40/settings-appearance.txt new file mode 100644 index 0000000..f0db1b9 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/settings-appearance.txt @@ -0,0 +1,40 @@ + 14K / 500K + ╭─ Settings ───────────────────────────────────────────────────────────────────────────── [x] ─╮ + > hey │ / to search │ 12:49 AM + │ ──────────────────────────────────────────────────────────────────────────────────────────── │ + ♦ Thought│ │ + │ Appearance ───────────────────────────────────────────────────────────────────────────────── │ + Hey — wha│ ▸ Compact mode off │ 12:49 AM + │ ▸ Default screen mode Fullscreen > │ + Worked fo│ ▸ Show timestamps on │ + │ ▸ Show thinking blocks on │ + > tell me│ ▸ Group tool calls on │ 12:49 AM + │ ▸ Collapsed edit blocks off │ + ♦ Thought│ ▸ Line numbers on │ + │ ▸ Word wrap on │ + I'm Corte│ ▸ Syntax highlight on │ 12:49 AM + │ ▸ Animations on │ + I mostly │ ▸ Theme Cortex Night > │search. + Here I ru│ │ + │ Mouse ────────────────────────────────────────────────────────────────────────────────────── │ + In practi│ ▸ Mouse capture on │ + • I get s│ ▸ Scroll lines 3 │ + • I prefe│ ▸ Invert scroll off │ + • I can a│ ▸ Copy on select off │ + │ │ + Tell me w│ Behavior ─────────────────────────────────────────────────────────────────────────────────── │ + │ ▸ Auto approve off │ + Worked fo│ ▸ Sandbox mode on │ + │ ▸ Streaming on │ + │ ▸ Auto scroll on │ + │ ▸ Sound off │ + │ ▸ Notifications off │ + │ │ + │ AI ───────────────────────────────────────────────────────────────────────────────────────── │ + │ ▸ Thinking mode on │ + │ │ + ╭─ Agent ──│ Tip · Ask Cortex: "change theme to Cortex Day" or "what does compact mode do?" │──────────╮ + │ > Plan, s│ ↑/↓/j/k nav | g/G top/btm | Space toggle | Enter toggle | → expand | / search | d reset │ │ + ╰──────────│ F2/Esc close │(medium) ─╯ + ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/settings-mouse.txt b/docs/media/tui-lock-v2/txt/120x40/settings-mouse.txt new file mode 100644 index 0000000..63680d1 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/settings-mouse.txt @@ -0,0 +1,40 @@ + 14K / 500K + ╭─ Settings ───────────────────────────────────────────────────────────────────────────── [x] ─╮ + > hey │ / to search │ 12:49 AM + │ ──────────────────────────────────────────────────────────────────────────────────────────── │ + ♦ Thought│ │ + │ Mouse ────────────────────────────────────────────────────────────────────────────────────── │ + Hey — wha│ ▸ Mouse capture on │ 12:49 AM + │ ▸ Scroll lines 3 │ + Worked fo│ ▸ Invert scroll off │ + │ ▸ Copy on select off │ + > tell me│ │ 12:49 AM + │ Behavior ─────────────────────────────────────────────────────────────────────────────────── │ + ♦ Thought│ ▸ Auto approve off │ + │ ▸ Sandbox mode on │ + I'm Corte│ ▸ Streaming on │ 12:49 AM + │ ▸ Auto scroll on │ + I mostly │ ▸ Sound off │search. + Here I ru│ ▸ Notifications off │ + │ │ + In practi│ AI ───────────────────────────────────────────────────────────────────────────────────────── │ + • I get s│ ▸ Thinking mode on │ + • I prefe│ ▸ Context aware on │ + • I can a│ ▸ Debug mode off │ + │ │ + Tell me w│ Git ──────────────────────────────────────────────────────────────────────────────────────── │ + │ ▸ Co-author on │ + Worked fo│ ▸ Auto commit off │ + │ ▸ Sign commits off │ + │ │ + │ Cloud ────────────────────────────────────────────────────────────────────────────────────── │ + │ ▸ Cloud sync off │ + │ ▸ Auto save on │ + │ ▸ Session history on │ + │ │ + │ │ + ╭─ Agent ──│ Tip · Ask Cortex: "change theme to Cortex Day" or "what does compact mode do?" │──────────╮ + │ > Plan, s│ ↑/↓/j/k nav | g/G top/btm | Space toggle | Enter toggle | → expand | / search | d reset │ │ + ╰──────────│ F2/Esc close │(medium) ─╯ + ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/settings-row-hover.txt b/docs/media/tui-lock-v2/txt/120x40/settings-row-hover.txt new file mode 100644 index 0000000..f0db1b9 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/settings-row-hover.txt @@ -0,0 +1,40 @@ + 14K / 500K + ╭─ Settings ───────────────────────────────────────────────────────────────────────────── [x] ─╮ + > hey │ / to search │ 12:49 AM + │ ──────────────────────────────────────────────────────────────────────────────────────────── │ + ♦ Thought│ │ + │ Appearance ───────────────────────────────────────────────────────────────────────────────── │ + Hey — wha│ ▸ Compact mode off │ 12:49 AM + │ ▸ Default screen mode Fullscreen > │ + Worked fo│ ▸ Show timestamps on │ + │ ▸ Show thinking blocks on │ + > tell me│ ▸ Group tool calls on │ 12:49 AM + │ ▸ Collapsed edit blocks off │ + ♦ Thought│ ▸ Line numbers on │ + │ ▸ Word wrap on │ + I'm Corte│ ▸ Syntax highlight on │ 12:49 AM + │ ▸ Animations on │ + I mostly │ ▸ Theme Cortex Night > │search. + Here I ru│ │ + │ Mouse ────────────────────────────────────────────────────────────────────────────────────── │ + In practi│ ▸ Mouse capture on │ + • I get s│ ▸ Scroll lines 3 │ + • I prefe│ ▸ Invert scroll off │ + • I can a│ ▸ Copy on select off │ + │ │ + Tell me w│ Behavior ─────────────────────────────────────────────────────────────────────────────────── │ + │ ▸ Auto approve off │ + Worked fo│ ▸ Sandbox mode on │ + │ ▸ Streaming on │ + │ ▸ Auto scroll on │ + │ ▸ Sound off │ + │ ▸ Notifications off │ + │ │ + │ AI ───────────────────────────────────────────────────────────────────────────────────────── │ + │ ▸ Thinking mode on │ + │ │ + ╭─ Agent ──│ Tip · Ask Cortex: "change theme to Cortex Day" or "what does compact mode do?" │──────────╮ + │ > Plan, s│ ↑/↓/j/k nav | g/G top/btm | Space toggle | Enter toggle | → expand | / search | d reset │ │ + ╰──────────│ F2/Esc close │(medium) ─╯ + ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/settings-search.txt b/docs/media/tui-lock-v2/txt/120x40/settings-search.txt new file mode 100644 index 0000000..8b15fdc --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/settings-search.txt @@ -0,0 +1,40 @@ + 14K / 500K + ╭─ Settings ───────────────────────────────────────────────────────────────────────────── [x] ─╮ + > hey │ / scro │ 12:49 AM + │ ──────────────────────────────────────────────────────────────────────────────────────────── │ + ♦ Thought│ │ + │ Mouse ────────────────────────────────────────────────────────────────────────────────────── │ + Hey — wha│ ▸ Scroll lines 3 │ 12:49 AM + │ ▸ Invert scroll off │ + Worked fo│ │ + │ Behavior ─────────────────────────────────────────────────────────────────────────────────── │ + > tell me│ ▸ Auto scroll on │ 12:49 AM + │ │ + ♦ Thought│ │ + │ │ + I'm Corte│ │ 12:49 AM + │ │ + I mostly │ │search. + Here I ru│ │ + │ │ + In practi│ │ + • I get s│ │ + • I prefe│ │ + • I can a│ │ + │ │ + Tell me w│ │ + │ │ + Worked fo│ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╭─ Agent ──│ Tip · Ask Cortex: "change theme to Cortex Day" or "what does compact mode do?" │──────────╮ + │ > Plan, s│ ↑/↓/j/k nav | g/G top/btm | Space toggle | Enter toggle | → expand | / search | d reset │ │ + ╰──────────│ F2/Esc close │(medium) ─╯ + ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/settings-theme-submenu.txt b/docs/media/tui-lock-v2/txt/120x40/settings-theme-submenu.txt new file mode 100644 index 0000000..cf0124d --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/settings-theme-submenu.txt @@ -0,0 +1,40 @@ + 14K / 500K + ╭─ Settings ───────────────────────────────────────────────────────────────────────────── [x] ─╮ + > hey │ Appearance › Theme │ 12:49 AM + │ ──────────────────────────────────────────────────────────────────────────────────────────── │ + ♦ Thought│ │ + │ ● Cortex Night Default inky chrome · violet on focus only current │ + Hey — wha│ ○ Cortex Day Light chrome for bright rooms │ 12:49 AM + │ ○ Ocean Dark Deep blue and cyan accents │ + Worked fo│ ○ Monokai Classic code-editor colors │ + │ │ + > tell me│ │ 12:49 AM + │ │ + ♦ Thought│ │ + │ │ + I'm Corte│ │ 12:49 AM + │ │ + I mostly │ │search. + Here I ru│ │ + │ │ + In practi│ │ + • I get s│ │ + • I prefe│ │ + • I can a│ │ + │ │ + Tell me w│ │ + │ │ + Worked fo│ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + ╭─ Agent ──│ Themes never change the accent rule: violet on focus only. │──────────╮ + │ > Plan, s│ ↑/↓/j/k nav | Enter select | ← back | d reset │ │ + ╰──────────│ F2/Esc close │(medium) ─╯ + ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/shell-running.txt b/docs/media/tui-lock-v2/txt/120x40/shell-running.txt new file mode 100644 index 0000000..c9b18e2 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/shell-running.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ⠇ Shell $ cargo test -p cortex-tui · running · 8s + Compiling cortex-tui v0.1.7 (/home/m/code/cortex/src/cortex-tui) + Finished test [unoptimized + debuginfo] target(s) in 6.91s + Running unittests src/lib.rs + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Add a follow-up — Enter to queue │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Esc:interrupt | Enter:queue follow-up | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/shortcuts-overlay.txt b/docs/media/tui-lock-v2/txt/120x40/shortcuts-overlay.txt new file mode 100644 index 0000000..53559e4 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/shortcuts-overlay.txt @@ -0,0 +1,40 @@ + 14K / 500K + ╭─ Shortcuts ──────────────────────────────────────────────────────────────── [x] ─╮ + > hey │ │ 12:49 AM + │ Shift+Tab cycle Agent / Plan / Ask Ctrl+p command palette │ + ♦ Thought for 0│ @ mention files Ctrl+r search past sessions │ + │ ! bash mode Ctrl+c stop the current turn │ + Hey — what do y│ & hand off to Cortex Cloud Esc interrupt · close │ 12:49 AM + │ / slash commands F2 settings │ + Worked for 1.8s│ Alt+Enter newline in the composer PgUp / PgDn scroll the transcript │ + │ ↑ / ↓ edit last · browse history Ctrl+x this overlay │ + > tell me about│ │ 12:49 AM + │ ──────────────────────────────────────────────────────────────────────────────── │ + ♦ Thought for 0│ Docs & guides: cortex.foundation/docs · Cortex CLI v0.1.7 │ + │ Ctrl+x/Esc close │ + I'm Cortex, a c╰──────────────────────────────────────────────────────────────────────────────────╯ 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/skills.txt b/docs/media/tui-lock-v2/txt/120x40/skills.txt new file mode 100644 index 0000000..4b66faa --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/skills.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + Type to search skills + ────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + + > release-notes Draft release notes from the git log · project + pdf-report Render a PDF from a markdown report · user + db-migrate Write and verify a schema migration · project + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /skills │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:run | r:reload | Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/slash-model-typed.txt b/docs/media/tui-lock-v2/txt/120x40/slash-model-typed.txt new file mode 100644 index 0000000..71fca84 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/slash-model-typed.txt @@ -0,0 +1,40 @@ + 14K / 500K + + + + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + > /model Choose the model for this session + /mode Switch between Agent, Plan and Ask + /mcp-reload Reconnect every configured MCP server + /custom-commands Manage custom commands + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /model │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Alt+Enter:newline | Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/slash-palette.txt b/docs/media/tui-lock-v2/txt/120x40/slash-palette.txt new file mode 100644 index 0000000..4eefe18 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/slash-palette.txt @@ -0,0 +1,40 @@ + 14K / 500K + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + > /model Choose the model for this session + /mode Switch between Agent, Plan and Ask + /permissions Set the approval policy for edits and commands + /plan Draft a plan before writing any code + /effort Tune reasoning effort for the current model + /mcp View and manage MCP servers + /sandbox Configure sandboxed command execution + /usage Plan usage, quota and limits + … 87 more — keep typing to filter + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > / │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Alt+Enter:newline | Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/sudo.txt b/docs/media/tui-lock-v2/txt/120x40/sudo.txt new file mode 100644 index 0000000..0e08abf --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/sudo.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > install the system deps 02:40 PM + + ♦ Thought for 0.7s + + ● Shell $ sudo apt-get install -y libssl-dev + Password for mathis: •••••••• + Never stored, logged, or shown to the model — sent straight to sudo. + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Enter the password above │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Enter:submit | Esc:cancel diff --git a/docs/media/tui-lock-v2/txt/120x40/todos.txt b/docs/media/tui-lock-v2/txt/120x40/todos.txt new file mode 100644 index 0000000..8a308fb --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/todos.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > move the model chip into the composer border 04:11 PM + + ♦ Thought for 2.6s + + ⠇ Working 2/5 · 38s · 6.1k tokens + ✓ Read composer.rs and footer.rs + ✓ Locate the chip painter + › Move the chip into the bottom hairline + ○ Drop the model from the footer + ○ Run the TUI snapshot tests + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Add a follow-up — Enter to queue │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Esc:interrupt | Enter:queue follow-up | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/tokens-topright-warn.txt b/docs/media/tui-lock-v2/txt/120x40/tokens-topright-warn.txt new file mode 100644 index 0000000..f6dd1fe --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/tokens-topright-warn.txt @@ -0,0 +1,40 @@ + 462K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ● Shell $ cargo test -p cortex-tui · ✓ 0 · 41s + ● Read src/cortex-tui/src/composer.rs · 212 lines + ● Grep "alternate_screen" in src/ · 6 hits in 4 files + + Context is 92% full — /compact summarizes the thread to free room. + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/tokens-topright.txt b/docs/media/tui-lock-v2/txt/120x40/tokens-topright.txt new file mode 100644 index 0000000..4cb6cf9 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/tokens-topright.txt @@ -0,0 +1,40 @@ + 142K / 500K + + > run the tui tests and fix whatever fails 09:14 AM + + ♦ Thought for 2.1s + + ● Shell $ cargo test -p cortex-tui · ✓ 0 · 41s + ● Read src/cortex-tui/src/composer.rs · 212 lines + ● Grep "alternate_screen" in src/ · 6 hits in 4 files + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/tool-tiles-collapsed.txt b/docs/media/tui-lock-v2/txt/120x40/tool-tiles-collapsed.txt new file mode 100644 index 0000000..7e84760 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/tool-tiles-collapsed.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > why do tests fail on the composer? 09:14 AM + + ♦ Thought for 2.1s + + ▸ 3 tool calls Read ×2 · Grep ×1 + ● Shell $ cargo test -p cortex-tui composer · × 101 · 12s + + The chip is painted before the model name resolves, so the border shows an empty label on the first 09:15 AM + frame. + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/tool-tiles.txt b/docs/media/tui-lock-v2/txt/120x40/tool-tiles.txt new file mode 100644 index 0000000..b2b3933 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/tool-tiles.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > why do tests fail on the composer? 09:14 AM + + ♦ Thought for 2.1s + + ▾ 3 tool calls Read ×2 · Grep ×1 + ● Read src/cortex-tui/src/composer.rs · 212 lines + ● Read src/cortex-tui/src/tests/composer.rs · 88 lines + ● Grep "model_chip" in src/ · 3 hits in 2 files + ● Shell $ cargo test -p cortex-tui composer · × 101 · 12s + test composer::chip_in_border … FAILED — expected `Cortex Mini 1 (medium)`, got `` + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/usage.txt b/docs/media/tui-lock-v2/txt/120x40/usage.txt new file mode 100644 index 0000000..e9bd928 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/usage.txt @@ -0,0 +1,40 @@ + 14K / 500K + + > hey 12:49 AM + + ♦ Thought for 0.4s + + Hey — what do you want to work on? 12:49 AM + + Worked for 1.8s + + > tell me about yourself 12:49 AM + + ♦ Thought for 0.4s + + I'm Cortex, a coding agent that runs in your terminal. 12:49 AM + + I mostly help you build and debug software: code, architecture, debugging, reviews, docs, and a bit of research. + Here I run in an interactive terminal, so I can read your files, run commands, and change the project. + + In practice: + • I get straight to the point + • I prefer concrete work over long explanations + • I can also discuss, explain, or help you plan + + Tell me what you'd like to do. + + Worked for 4.6s + + Usage · Cortex Pro · renews Oct 1 + Agent requests 42 / 500 ████████████████████████████████████████ 8% + Tokens this month 8.4M / 12M ████████████████████████████████████████ 70% + Cloud agent minutes 132 / 400 ████████████████████████████████████████ 33% + + MAX bills by token instead of per request — manage at cortex.foundation/billing + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > /usage │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Esc:close diff --git a/docs/media/tui-lock-v2/txt/120x40/welcome-agent.txt b/docs/media/tui-lock-v2/txt/120x40/welcome-agent.txt new file mode 100644 index 0000000..b3084a0 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/welcome-agent.txt @@ -0,0 +1,40 @@ + 0 / 500K + + Welcome to Cortex Agent — describe a task, it does the work + v0.1.7 · / commands · @ files · ! shell · & cloud + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Describe a task for the agent │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/120x40/welcome-cortex.txt b/docs/media/tui-lock-v2/txt/120x40/welcome-cortex.txt new file mode 100644 index 0000000..ded9849 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/120x40/welcome-cortex.txt @@ -0,0 +1,40 @@ + 0 / 500K + + Welcome to Cortex, the coding agent CLI + v0.1.7 · / commands · @ files · ! shell · & cloud + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ╭─ Agent ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────────────────────────────────────────────────────────────────────────────────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/compact-chat.txt b/docs/media/tui-lock-v2/txt/40x12/compact-chat.txt new file mode 100644 index 0000000..814a381 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/compact-chat.txt @@ -0,0 +1,12 @@ + 14K / 500K + > hey + ♦ Thought for 0.4s + Hey — what do you want to work on? + Worked for 1.8s + > tell me about yourself + ♦ Thought for 0.4s + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/composer-empty.txt b/docs/media/tui-lock-v2/txt/40x12/composer-empty.txt new file mode 100644 index 0000000..d6f6fbd --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/composer-empty.txt @@ -0,0 +1,12 @@ + 14K / 500K + + + + + + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/composer-hover.txt b/docs/media/tui-lock-v2/txt/40x12/composer-hover.txt new file mode 100644 index 0000000..d6f6fbd --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/composer-hover.txt @@ -0,0 +1,12 @@ + 14K / 500K + + + + + + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/composer-typing.txt b/docs/media/tui-lock-v2/txt/40x12/composer-typing.txt new file mode 100644 index 0000000..0fcf08f --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/composer-typing.txt @@ -0,0 +1,12 @@ + 14K / 500K + + + + + + + ╭─ Agent ────────────────────────────╮ + │ > add retry with backoff to the ap │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/diagnostics.txt b/docs/media/tui-lock-v2/txt/40x12/diagnostics.txt new file mode 100644 index 0000000..eec3f27 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/diagnostics.txt @@ -0,0 +1,12 @@ + 14K / 500K + + > wire the model chip into the com… + + ♦ Thought for 2.6s + + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/diff-hunk.txt b/docs/media/tui-lock-v2/txt/40x12/diff-hunk.txt new file mode 100644 index 0000000..b9d9e23 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/diff-hunk.txt @@ -0,0 +1,12 @@ + 14K / 500K + + > move the model chip into the com… + + ♦ Thought for 2.6s + + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/first-run-tips.txt b/docs/media/tui-lock-v2/txt/40x12/first-run-tips.txt new file mode 100644 index 0000000..2623e73 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/first-run-tips.txt @@ -0,0 +1,12 @@ + 0 / 500K + + Welcome to Cortex + v0.1.7 · / commands · @ files + + A few tips to get started: + 1. /model switches model + effort. + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/interrupt-stopped.txt b/docs/media/tui-lock-v2/txt/40x12/interrupt-stopped.txt new file mode 100644 index 0000000..18f778f --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/interrupt-stopped.txt @@ -0,0 +1,12 @@ + 14K / 500K + + > run the tui tests and fix whatev… + + ♦ Thought for 2.1s + + + ╭─ Agent ────────────────────────────╮ + │ > Reply, or ↑ to edit your last m… │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/login.txt b/docs/media/tui-lock-v2/txt/40x12/login.txt new file mode 100644 index 0000000..7714df7 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/login.txt @@ -0,0 +1,12 @@ + + Welcome to Cortex CLI! + + How would you like to log in? + + > 1 Continue with browser + 2 Paste an API key + + ↑↓:select | Enter:confirm | Esc:quit + + + diff --git a/docs/media/tui-lock-v2/txt/40x12/mcp-servers.txt b/docs/media/tui-lock-v2/txt/40x12/mcp-servers.txt new file mode 100644 index 0000000..6dab9b7 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/mcp-servers.txt @@ -0,0 +1,12 @@ + 14K / 500K + + MCP servers · 2 of 4 connected + + > ✓ github 12 tools · connec… + ✓ filesystem 8 tools · connect… + ⠇ linear authenticating… + ╭─ Agent ────────────────────────────╮ + │ > /mcp │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Enter:details | Esc:close diff --git a/docs/media/tui-lock-v2/txt/40x12/mode-ask.txt b/docs/media/tui-lock-v2/txt/40x12/mode-ask.txt new file mode 100644 index 0000000..19c978b --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/mode-ask.txt @@ -0,0 +1,12 @@ + 14K / 500K + + > where is the alternate-screen de… + + ♦ Thought for 1.1s + + + ╭─ Ask · read-only ──────────────────╮ + │ > Ask about the codebase — read-o… │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/mode-plan.txt b/docs/media/tui-lock-v2/txt/40x12/mode-plan.txt new file mode 100644 index 0000000..99c4d60 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/mode-plan.txt @@ -0,0 +1,12 @@ + 14K / 500K + + > add retry with backoff to the ap… + + ♦ Thought for 5.8s + + + ╭─ Plan · no edits ──────────────────╮ + │ > Describe what you want — Cortex… │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/model-effort-high.txt b/docs/media/tui-lock-v2/txt/40x12/model-effort-high.txt new file mode 100644 index 0000000..8456f71 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/model-effort-high.txt @@ -0,0 +1,12 @@ + 14K / 500K + + Worked for 4.6s + + > High Effort Deepest reasoning… + Medium Effort Balanced reasonin… + Low Effort Fastest responses… + ╭─ Agent ────────────────────────────╮ + │ > /model Cortex Mini 1 │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Enter:apply | Esc:close diff --git a/docs/media/tui-lock-v2/txt/40x12/model-list.txt b/docs/media/tui-lock-v2/txt/40x12/model-list.txt new file mode 100644 index 0000000..438ee26 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/model-list.txt @@ -0,0 +1,12 @@ + 14K / 500K + + Worked for 4.6s + + > Cortex Mini 1 Fast default for… + Cortex 1 Deeper reasoning… + Cortex Max 1 Longest context … + ╭─ Agent ────────────────────────────╮ + │ > /model │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Enter:choose | Tab:effort | Esc:close diff --git a/docs/media/tui-lock-v2/txt/40x12/permission-prompt.txt b/docs/media/tui-lock-v2/txt/40x12/permission-prompt.txt new file mode 100644 index 0000000..dfc8e42 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/permission-prompt.txt @@ -0,0 +1,12 @@ + 14K / 500K + ● Cortex wants to run + $ npm install ioredis && npm insta… + > 1 Yes, run once + 2 Yes, always allow npm install … + 3 Edit command + 4 No — tell Cortex what to do in… + ╭─ Agent ────────────────────────────╮ + │ > Choose an option above │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Enter:confirm | Esc:cancel diff --git a/docs/media/tui-lock-v2/txt/40x12/session-assistant.txt b/docs/media/tui-lock-v2/txt/40x12/session-assistant.txt new file mode 100644 index 0000000..5f3ddbe --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/session-assistant.txt @@ -0,0 +1,12 @@ + 14K / 500K + + > tell me about yourself + + ♦ Thought for 0.4s + + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/session-empty.txt b/docs/media/tui-lock-v2/txt/40x12/session-empty.txt new file mode 100644 index 0000000..d6f6fbd --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/session-empty.txt @@ -0,0 +1,12 @@ + 14K / 500K + + + + + + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/session-optin.txt b/docs/media/tui-lock-v2/txt/40x12/session-optin.txt new file mode 100644 index 0000000..b496053 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/session-optin.txt @@ -0,0 +1,12 @@ + 14K / 500K + + + Help improve Cortex[Opt out] [Opt in] + Off by default · anytime in /settings + Read Terms and Privacy Policy. + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/session-thinking-live.txt b/docs/media/tui-lock-v2/txt/40x12/session-thinking-live.txt new file mode 100644 index 0000000..87192c7 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/session-thinking-live.txt @@ -0,0 +1,12 @@ + 14K / 500K + + > why does the composer lose focus… + + ⠇ Thinking · 3s + + + ╭─ Agent ────────────────────────────╮ + │ > Add a follow-up — Enter to queue │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Esc:interrupt | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/session-user-bars.txt b/docs/media/tui-lock-v2/txt/40x12/session-user-bars.txt new file mode 100644 index 0000000..3a19e33 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/session-user-bars.txt @@ -0,0 +1,12 @@ + 14K / 500K + + > hey + + ♦ Thought for 0.4s + + Hey — what do you want to work on? + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/settings-appearance.txt b/docs/media/tui-lock-v2/txt/40x12/settings-appearance.txt new file mode 100644 index 0000000..92da8c7 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/settings-appearance.txt @@ -0,0 +1,12 @@ +╭─ Settings ───────────────────── [x] ─╮ +│ / to search │ +│ ──────────────────────────────────── │ +│ Appearance ───────────────────────── │ +│ ▸ Compact mode off │ +│ ▸ Default screen mode > │ +│ ▸ Show timestamps on │ +│ ▸ Show thinking blocks on │ +│ ▸ Group tool calls on │ +│ ↑↓ nav | Space toggle | / search │ +│ F2/Esc close │ +╰──────────────────────────────────────╯ diff --git a/docs/media/tui-lock-v2/txt/40x12/settings-mouse.txt b/docs/media/tui-lock-v2/txt/40x12/settings-mouse.txt new file mode 100644 index 0000000..659dc46 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/settings-mouse.txt @@ -0,0 +1,12 @@ +╭─ Settings ───────────────────── [x] ─╮ +│ / to search │ +│ ──────────────────────────────────── │ +│ Mouse ────────────────────────────── │ +│ ▸ Mouse capture on │ +│ ▸ Scroll lines 3 │ +│ ▸ Invert scroll off │ +│ ▸ Copy on select off │ +│ │ +│ ↑↓ nav | Space toggle | / search │ +│ F2/Esc close │ +╰──────────────────────────────────────╯ diff --git a/docs/media/tui-lock-v2/txt/40x12/settings-row-hover.txt b/docs/media/tui-lock-v2/txt/40x12/settings-row-hover.txt new file mode 100644 index 0000000..92da8c7 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/settings-row-hover.txt @@ -0,0 +1,12 @@ +╭─ Settings ───────────────────── [x] ─╮ +│ / to search │ +│ ──────────────────────────────────── │ +│ Appearance ───────────────────────── │ +│ ▸ Compact mode off │ +│ ▸ Default screen mode > │ +│ ▸ Show timestamps on │ +│ ▸ Show thinking blocks on │ +│ ▸ Group tool calls on │ +│ ↑↓ nav | Space toggle | / search │ +│ F2/Esc close │ +╰──────────────────────────────────────╯ diff --git a/docs/media/tui-lock-v2/txt/40x12/settings-theme-submenu.txt b/docs/media/tui-lock-v2/txt/40x12/settings-theme-submenu.txt new file mode 100644 index 0000000..d8579b2 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/settings-theme-submenu.txt @@ -0,0 +1,12 @@ +╭─ Settings ───────────────────── [x] ─╮ +│ Appearance › Theme │ +│ ──────────────────────────────────── │ +│ ● Cortex Night current │ +│ ○ Cortex Day │ +│ ○ Ocean Dark │ +│ ○ Monokai │ +│ │ +│ │ +│ Enter select | ← back │ +│ F2/Esc close │ +╰──────────────────────────────────────╯ diff --git a/docs/media/tui-lock-v2/txt/40x12/shortcuts-overlay.txt b/docs/media/tui-lock-v2/txt/40x12/shortcuts-overlay.txt new file mode 100644 index 0000000..67e741e --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/shortcuts-overlay.txt @@ -0,0 +1,12 @@ +╭─ Shortcuts ──────────────────── [x] ─╮ +│ │ +│ Shift+Tab cycle Agent / Plan / Ask │ +│ @ mention files │ +│ ! bash mode │ +│ & hand off to Cortex Cloud │ +│ Ctrl+c stop │ +│ F2 settings │ +│ Esc interrupt / close │ +│ │ +│ Ctrl+x/Esc close │ +╰──────────────────────────────────────╯ diff --git a/docs/media/tui-lock-v2/txt/40x12/slash-model-typed.txt b/docs/media/tui-lock-v2/txt/40x12/slash-model-typed.txt new file mode 100644 index 0000000..a2eb6df --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/slash-model-typed.txt @@ -0,0 +1,12 @@ + 14K / 500K + + Worked for 4.6s + + > /model Choose the mod… + /mode Switch between… + /mcp-reload Reconnect ever… + ╭─ Agent ────────────────────────────╮ + │ > /model │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/slash-palette.txt b/docs/media/tui-lock-v2/txt/40x12/slash-palette.txt new file mode 100644 index 0000000..c73f2a7 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/slash-palette.txt @@ -0,0 +1,12 @@ + 14K / 500K + + Worked for 4.6s + + > /model Choose the model… + /mode Switch between A… + /permissions Set the approval… + ╭─ Agent ────────────────────────────╮ + │ > / │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Enter:send | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/tokens-topright.txt b/docs/media/tui-lock-v2/txt/40x12/tokens-topright.txt new file mode 100644 index 0000000..e41c016 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/tokens-topright.txt @@ -0,0 +1,12 @@ + 142K / 500K + + > run the tui tests and fix whatev… + + ♦ Thought for 2.1s + + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/usage.txt b/docs/media/tui-lock-v2/txt/40x12/usage.txt new file mode 100644 index 0000000..2ba3d78 --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/usage.txt @@ -0,0 +1,12 @@ + 14K / 500K + + + Usage · Cortex Pro · renews Oct 1 + Agent requests 42 / 500 8% + Tokens this month 8.4M / 12M 70% + Cloud agent minutes 132 / 400 33% + ╭─ Agent ────────────────────────────╮ + │ > /usage │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Esc:close diff --git a/docs/media/tui-lock-v2/txt/40x12/welcome-agent.txt b/docs/media/tui-lock-v2/txt/40x12/welcome-agent.txt new file mode 100644 index 0000000..219e8ec --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/welcome-agent.txt @@ -0,0 +1,12 @@ + 0 / 500K + + Welcome to Cortex Agent + v0.1.7 · / commands · @ files + + + + ╭─ Agent ────────────────────────────╮ + │ > Describe a task for the agent │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts diff --git a/docs/media/tui-lock-v2/txt/40x12/welcome-cortex.txt b/docs/media/tui-lock-v2/txt/40x12/welcome-cortex.txt new file mode 100644 index 0000000..932c3df --- /dev/null +++ b/docs/media/tui-lock-v2/txt/40x12/welcome-cortex.txt @@ -0,0 +1,12 @@ + 0 / 500K + + Welcome to Cortex + v0.1.7 · / commands · @ files + + + + ╭─ Agent ────────────────────────────╮ + │ > Plan, search, build anything │ + ╰─────────── Cortex Mini 1 (medium) ─╯ + + Shift+Tab:mode | Ctrl+x:shortcuts