TUI: run `!` shell commands immediately instead of queuing them as prompts
What variant of Codex are you using?
TUI / CLI
What feature would you like to see?
! shell commands typed into the Codex TUI should execute immediately and skip the prompt FIFO queue, including before a session/thread has fully started when possible.
Today, !cmd is treated like a queued input action when submitted while Codex is busy. That makes sense for normal prompts, but !cmd is not a model prompt. It is a local shell command the user could run directly in their terminal, but happens to run through Codex because Codex is already open.
Requested behavior:
- Typing
!pwd,!git status --short,!date, etc. should execute immediately. - These commands should not wait behind queued user prompts.
- They should not be merged with, reordered by, or otherwise participate in prompt FIFO semantics.
- If the TUI has not yet attached to an active thread/session,
!cmdshould still run through a pre-session/local shell path if feasible. - Normal prompts and slash commands that start model work should keep the existing queue behavior.
Current behavior
From the current TUI implementation:
!cmdis classified asQueuedInputAction::RunShell.- When the user submits a
!cmdnormally, it routes to the user shell command path and runs. - When submitted via the queue path while a task is active, it is stored in the normal queued-input FIFO and later drained by
submit_queued_shell_prompt. - This means
!cmdcan wait behind prompts even though it does not require a model turn.
The current test name also documents the behavior:
tab_queues_bang_shell_prompts_while_task_running_without_execution
Why this should change
! commands are operational shell commands, not prompts. Users often type them in Codex for convenience because the TUI is already open, but semantically they are closer to direct terminal commands than follow-up chat turns.
Putting them into the prompt FIFO has a few downsides:
- A quick local command such as
!pwdor!git statuscan be delayed behind unrelated prompts. - The queue UI makes it look like the command is a future model interaction, even though no model reasoning is needed.
- Pre-session shell commands are blocked by the active-thread requirement, even though the command runner itself mostly needs cwd, shell config, env policy, and an output surface rather than model session state.
Implementation notes from source inspection
Relevant current paths:
codex-rs/tui/src/bottom_pane/chat_composer/slash_input.rs- classifies prepared text starting with
!asQueuedInputAction::RunShell codex-rs/tui/src/chatwidget/input_submission.rs- handles immediate shell-prefix submission in the normal submit path
codex-rs/tui/src/chatwidget/input_flow.rs- queue path stores
RunShellactions instead of executing them immediately codex-rs/tui/src/chatwidget/input_queue.rs- normal queued FIFO currently stores queued shell actions alongside queued prompt actions
codex-rs/tui/src/app_command.rsAppCommand::RunUserShellCommand { command }codex-rs/tui/src/app/thread_routing.rs- current app command routing requires an active thread id
codex-rs/app-server-protocol/src/protocol/v2/thread.rsthread/shellCommandrequiresthreadIdcodex-rs/core/src/session/handlers.rsrun_user_shell_commandcan run either alongside an active turn or as a standalone user shell command taskcodex-rs/core/src/tasks/user_shell.rs- actual execution uses user shell, cwd, shell environment policy, and emits shell output events
Based on that inspection, the immediate queue-bypass part can likely be handled in the TUI input flow by executing QueuedInputAction::RunShell immediately instead of pushing it into queued_user_messages.
The pre-session part likely needs a non-thread-scoped shell-command path. The existing thread/shellCommand endpoint requires a threadId, and TUI app-command routing currently errors when no active thread exists. There is already a non-thread-scoped command/exec app-server surface, but it is not a drop-in replacement for !cmd because !cmd preserves shell syntax and has different UI/event semantics.
Expected behavior
Examples:
- Start Codex and submit a long-running prompt.
- While that prompt is running, type:
``text``
!git status --short
- Codex should run
git status --shortimmediately and render the shell output, without waiting for the model turn or queued prompts to finish.
Similarly, during startup/pre-session:
- Open Codex.
- Before the active thread/session is fully available, type:
``text``
!pwd
- Codex should run the shell command using the configured/local workspace command context if possible, rather than failing with no active thread.
Additional information
I searched existing open issues and did not find an exact duplicate. Related but distinct issues:
- #21793:
!!/bang command ergonomics - #22224:
!commandexecution inside skill files - #15355: local ingress/session semantics for interactive TUI
- #14693: queued draft safety while Codex is running
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗