@@ -112,47 +112,41 @@ const TMUX_KEYS: QuickKey[] = [
112112 { label : ": cmd" , key : "\x02:" , title : "Command prompt" } ,
113113] ;
114114
115- // Common key combos for coding CLIs (Claude Code, Codex, OpenCode)
116- const CODE_CLI_KEYS : QuickKey [ ] = [
117- { label : "Shift+Tab" , key : "\x1b[Z" , title : "Change permission mode (Claude Code)" } ,
118- { label : "Ctrl+C" , key : "\x03" , title : "Cancel / interrupt" } ,
119- { label : "Ctrl+O" , key : "\x0f" , title : "Show logs (Claude Code)" } ,
120- { label : "Esc" , key : "\x1b" , title : "Escape / go back" } ,
115+ // Common key combos shared across all coding CLIs
116+ const CODE_COMMON_KEYS : QuickKey [ ] = [
117+ { label : "Ctrl+C" , key : "\x03" , title : "Cancel / interrupt / quit" } ,
118+ { label : "Ctrl+L" , key : "\x0c" , title : "Clear screen (Claude/Codex) / View logs (OpenCode)" } ,
119+ { label : "Ctrl+G" , key : "\x07" , title : "Open external editor (Claude/Codex)" } ,
120+ { label : "Esc" , key : "\x1b" , title : "Cancel generation / dismiss / go back" } ,
121+ { label : "Esc Esc" , key : "\x1b\x1b" , title : "Rewind history (Claude) / Edit prev message (Codex)" } ,
121122 { label : "y" , key : "y" , title : "Yes (approve)" } ,
122123 { label : "n" , key : "n" , title : "No (deny)" } ,
123124] ;
124125
125- interface CodeLaunchCmd {
126- label : string ;
127- title : string ;
128- command : string ;
129- cli : string ; // which CLI this belongs to, for grouping
130- }
131-
132- // Git quick action commands
133- const GIT_QUICK_CMDS : { label : string ; title : string ; command : string } [ ] = [
134- { label : "status" , title : "git status" , command : "git status\n" } ,
135- { label : "log" , title : "git log --oneline -10" , command : "git log --oneline -10\n" } ,
136- { label : "diff" , title : "git diff" , command : "git diff\n" } ,
137- { label : "add ." , title : "git add . (stage all)" , command : "git add .\n" } ,
138- { label : "fetch" , title : "git fetch" , command : "git fetch\n" } ,
139- { label : "pull" , title : "git pull" , command : "git pull\n" } ,
140- { label : "push" , title : "git push" , command : "git push\n" } ,
141- { label : "stash" , title : "git stash" , command : "git stash\n" } ,
142- { label : "stash pop" , title : "git stash pop" , command : "git stash pop\n" } ,
143- { label : "branch" , title : "git branch (list branches)" , command : "git branch\n" } ,
144- ] ;
145-
146- // Slash commands grouped by CLI
147- interface SlashCmdGroup {
148- cli : string ;
149- cmds : { label : string ; title : string ; command : string } [ ] ;
126+ // Per-vendor CLI groups: launch commands, keys, and slash commands
127+ interface CliVendor {
128+ name : string ;
129+ keys : QuickKey [ ] ;
130+ launch : { label : string ; title : string ; command : string } [ ] ;
131+ slashCmds : { label : string ; title : string ; command : string } [ ] ;
150132}
151133
152- const SLASH_CMD_GROUPS : SlashCmdGroup [ ] = [
134+ const CLI_VENDORS : CliVendor [ ] = [
153135 {
154- cli : "claude" ,
155- cmds : [
136+ name : "claude" ,
137+ keys : [
138+ { label : "Shift+Tab" , key : "\x1b[Z" , title : "Cycle permission modes" } ,
139+ { label : "Ctrl+O" , key : "\x0f" , title : "Toggle full transcript view" } ,
140+ { label : "Ctrl+R" , key : "\x12" , title : "Reverse history search" } ,
141+ { label : "Alt+T" , key : "\x1bt" , title : "Toggle extended thinking" } ,
142+ { label : "Alt+P" , key : "\x1bp" , title : "Model picker" } ,
143+ ] ,
144+ launch : [
145+ { label : "claude" , title : "Interactive mode" , command : "claude\n" } ,
146+ { label : "yolo" , title : "Skip all permission checks" , command : "claude --dangerously-skip-permissions\n" } ,
147+ { label : "plan" , title : "Read-only plan mode" , command : "claude --allowedTools Read,Glob,Grep,WebSearch,WebFetch\n" } ,
148+ ] ,
149+ slashCmds : [
156150 { label : "/clear" , title : "Clear conversation context" , command : "/clear\n" } ,
157151 { label : "/compact" , title : "Compact conversation to save context" , command : "/compact\n" } ,
158152 { label : "/cost" , title : "Show token usage and cost" , command : "/cost\n" } ,
@@ -166,8 +160,16 @@ const SLASH_CMD_GROUPS: SlashCmdGroup[] = [
166160 ] ,
167161 } ,
168162 {
169- cli : "codex" ,
170- cmds : [
163+ name : "codex" ,
164+ keys : [
165+ { label : "Ctrl+O" , key : "\x0f" , title : "Choose environment (cloud)" } ,
166+ ] ,
167+ launch : [
168+ { label : "suggest" , title : "Proposes changes for approval" , command : "codex --approval-mode suggest\n" } ,
169+ { label : "auto-edit" , title : "Applies file changes, asks for commands" , command : "codex --approval-mode auto-edit\n" } ,
170+ { label : "full-auto" , title : "Runs without confirmation" , command : "codex --approval-mode full-auto\n" } ,
171+ ] ,
172+ slashCmds : [
171173 { label : "/help" , title : "Show available commands" , command : "/help\n" } ,
172174 { label : "/model" , title : "Show or switch model" , command : "/model\n" } ,
173175 { label : "/exit" , title : "Exit Codex" , command : "/exit\n" } ,
@@ -176,8 +178,19 @@ const SLASH_CMD_GROUPS: SlashCmdGroup[] = [
176178 ] ,
177179 } ,
178180 {
179- cli : "opencode" ,
180- cmds : [
181+ name : "opencode" ,
182+ keys : [
183+ { label : "Ctrl+O" , key : "\x0f" , title : "Model selection dialog" } ,
184+ { label : "Ctrl+K" , key : "\x0b" , title : "Command dialog" } ,
185+ { label : "Ctrl+N" , key : "\x0e" , title : "New session" } ,
186+ { label : "Ctrl+X" , key : "\x18" , title : "Cancel generation" } ,
187+ { label : "Ctrl+S" , key : "\x13" , title : "Send message" } ,
188+ { label : "Ctrl+A" , key : "\x01" , title : "Switch session" } ,
189+ ] ,
190+ launch : [
191+ { label : "opencode" , title : "Interactive mode" , command : "opencode\n" } ,
192+ ] ,
193+ slashCmds : [
181194 { label : "/help" , title : "Show available commands" , command : "/help\n" } ,
182195 { label : "/exit" , title : "Exit OpenCode" , command : "/exit\n" } ,
183196 { label : "/clear" , title : "Clear conversation" , command : "/clear\n" } ,
@@ -186,17 +199,18 @@ const SLASH_CMD_GROUPS: SlashCmdGroup[] = [
186199 } ,
187200] ;
188201
189- const CODE_LAUNCH_CMDS : CodeLaunchCmd [ ] = [
190- // Claude Code
191- { cli : "claude" , label : "claude" , title : "Claude Code — interactive mode" , command : "claude\n" } ,
192- { cli : "claude" , label : "claude yolo" , title : "Claude Code — skip all permission checks" , command : "claude --dangerously-skip-permissions\n" } ,
193- { cli : "claude" , label : "claude plan" , title : "Claude Code — read-only plan mode" , command : "claude --allowedTools Read,Glob,Grep,WebSearch,WebFetch\n" } ,
194- // Codex CLI
195- { cli : "codex" , label : "codex suggest" , title : "Codex — suggest mode (proposes changes)" , command : "codex --approval-mode suggest\n" } ,
196- { cli : "codex" , label : "codex auto" , title : "Codex — auto-edit mode" , command : "codex --approval-mode auto-edit\n" } ,
197- { cli : "codex" , label : "codex full" , title : "Codex — full auto mode" , command : "codex --approval-mode full-auto\n" } ,
198- // OpenCode
199- { cli : "opencode" , label : "opencode" , title : "OpenCode — interactive mode" , command : "opencode\n" } ,
202+ // Git quick action commands
203+ const GIT_QUICK_CMDS : { label : string ; title : string ; command : string } [ ] = [
204+ { label : "status" , title : "git status" , command : "git status\n" } ,
205+ { label : "log" , title : "git log --oneline -10" , command : "git log --oneline -10\n" } ,
206+ { label : "diff" , title : "git diff" , command : "git diff\n" } ,
207+ { label : "add ." , title : "git add . (stage all)" , command : "git add .\n" } ,
208+ { label : "fetch" , title : "git fetch" , command : "git fetch\n" } ,
209+ { label : "pull" , title : "git pull" , command : "git pull\n" } ,
210+ { label : "push" , title : "git push" , command : "git push\n" } ,
211+ { label : "stash" , title : "git stash" , command : "git stash\n" } ,
212+ { label : "stash pop" , title : "git stash pop" , command : "git stash pop\n" } ,
213+ { label : "branch" , title : "git branch (list branches)" , command : "git branch\n" } ,
200214] ;
201215
202216// Tab IDs
@@ -803,26 +817,45 @@ export default function InputBox() {
803817 </ div >
804818 ) }
805819
806- { /* Code tab: coding CLI launchers + common keys */ }
820+ { /* Code tab: common keys + per-vendor panels */ }
807821 { activeGroup === CODE_TAB && (
808822 < div className = "border-b border-gray-700/50 bg-[#12122a] px-2 py-1.5 max-h-64 overflow-y-auto" >
809- { /* Coding CLI key combos */ }
823+ { /* Common keys across all CLIs */ }
810824 < div className = "flex flex-wrap gap-1 mb-1.5" >
811- < span className = "text-[10px] text-gray-600 w-full" > cli keys</ span >
812- { CODE_CLI_KEYS . map ( ( qk ) => (
825+ < span className = "text-[10px] text-gray-600 w-full" > common keys</ span >
826+ { CODE_COMMON_KEYS . map ( ( qk ) => (
813827 < button key = { qk . label } { ...repeatProps ( qk . key ) } disabled = { ! activeSessionId } title = { qk . title } className = { keyBtn } >
814828 { qk . label }
815829 </ button >
816830 ) ) }
817831 </ div >
818- { /* Slash commands grouped by CLI */ }
819- { SLASH_CMD_GROUPS . map ( ( group ) => (
820- < div key = { group . cli } className = "border-t border-gray-700/50 pt-1.5 mb-1.5" >
821- < span className = "text-[10px] text-gray-600 " > { group . cli } /commands </ span >
832+ { /* Per-vendor sections: launch + keys + slash commands */ }
833+ { CLI_VENDORS . map ( ( vendor ) => (
834+ < div key = { vendor . name } className = "border-t border-gray-700/50 pt-1.5 mb-1.5" >
835+ < span className = "text-[10px] text-gray-500 font-medium " > { vendor . name } </ span >
822836 < div className = "flex flex-wrap gap-1 mt-0.5" >
823- { group . cmds . map ( ( cmd ) => (
837+ { /* Launch buttons (purple) */ }
838+ { vendor . launch . map ( ( cmd ) => (
824839 < button
825- key = { `${ group . cli } -${ cmd . label } ` }
840+ key = { `${ vendor . name } -${ cmd . label } ` }
841+ onClick = { ( ) => { if ( activeSessionId ) sendInput ( activeSessionId , cmd . command ) ; } }
842+ disabled = { ! activeSessionId }
843+ title = { cmd . title }
844+ className = "px-2 py-0.5 text-[11px] bg-[#1a1a2e] text-purple-400 hover:text-purple-200 hover:bg-[#2a2a4a] disabled:text-gray-600 rounded border border-purple-800/60 whitespace-nowrap transition-colors select-none"
845+ >
846+ { cmd . label }
847+ </ button >
848+ ) ) }
849+ { /* Vendor-specific keys (gray, like common keys) */ }
850+ { vendor . keys . map ( ( qk ) => (
851+ < button key = { `${ vendor . name } -${ qk . label } ` } { ...repeatProps ( qk . key ) } disabled = { ! activeSessionId } title = { qk . title } className = { keyBtn } >
852+ { qk . label }
853+ </ button >
854+ ) ) }
855+ { /* Slash commands (cyan) */ }
856+ { vendor . slashCmds . map ( ( cmd ) => (
857+ < button
858+ key = { `${ vendor . name } -${ cmd . label } ` }
826859 onClick = { ( ) => { if ( activeSessionId ) sendInput ( activeSessionId , cmd . command ) ; } }
827860 disabled = { ! activeSessionId }
828861 title = { cmd . title }
@@ -834,23 +867,6 @@ export default function InputBox() {
834867 </ div >
835868 </ div >
836869 ) ) }
837- { /* CLI launch shortcuts */ }
838- < div className = "border-t border-gray-700/50 pt-1.5" >
839- < span className = "text-[10px] text-gray-600" > launch</ span >
840- < div className = "flex flex-wrap gap-1 mt-0.5" >
841- { CODE_LAUNCH_CMDS . map ( ( cmd ) => (
842- < button
843- key = { cmd . label }
844- onClick = { ( ) => { if ( activeSessionId ) sendInput ( activeSessionId , cmd . command ) ; } }
845- disabled = { ! activeSessionId }
846- title = { cmd . title }
847- className = "px-2 py-0.5 text-[11px] bg-[#1a1a2e] text-purple-400 hover:text-purple-200 hover:bg-[#2a2a4a] disabled:text-gray-600 rounded border border-purple-800/60 whitespace-nowrap transition-colors select-none"
848- >
849- { cmd . label }
850- </ button >
851- ) ) }
852- </ div >
853- </ div >
854870 </ div >
855871 ) }
856872
0 commit comments