TUI: run `!` shell commands immediately instead of queuing them as prompts

Resolved 💬 1 comment Opened Jun 4, 2026 by thearyanag Closed Jun 5, 2026

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, !cmd should 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:

  • !cmd is classified as QueuedInputAction::RunShell.
  • When the user submits a !cmd normally, 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 !cmd can 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 !pwd or !git status can 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 ! as QueuedInputAction::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 RunShell actions 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.rs
  • AppCommand::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.rs
  • thread/shellCommand requires threadId
  • codex-rs/core/src/session/handlers.rs
  • run_user_shell_command can run either alongside an active turn or as a standalone user shell command task
  • codex-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:

  1. Start Codex and submit a long-running prompt.
  2. While that prompt is running, type:

``text
!git status --short
``

  1. Codex should run git status --short immediately and render the shell output, without waiting for the model turn or queued prompts to finish.

Similarly, during startup/pre-session:

  1. Open Codex.
  2. Before the active thread/session is fully available, type:

``text
!pwd
``

  1. 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: !command execution inside skill files
  • #15355: local ingress/session semantics for interactive TUI
  • #14693: queued draft safety while Codex is running

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗