Implement a default timeout and provide feedback for shell commands

Open 💬 8 comments Opened Oct 5, 2025 by coygeek
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What feature would you like to see?

I would like to request the implementation of a default timeout for all shell commands executed by the agent. When a command runs longer than this timeout, it should be terminated, and both the user and the agent should receive feedback that a timeout occurred.

Currently, if the agent runs a shell command that hangs, crashes in a weird way, or is simply long-running without the model specifying a timeout_ms, the CLI appears to freeze. The user is left with a "Working..." spinner indefinitely, with no indication of what's happening or a clear way to proceed besides killing the entire process.

A default timeout (e.g., 60 or 120 seconds) would act as a crucial safety net, ensuring that the agent can recover from stuck processes and the user is always kept in the loop.

When a timeout is hit:

  1. The child process should be terminated.
  2. A history event should be displayed in the TUI, indicating that the command timed out (e.g., • Ran command [timed out after 60s]).
  3. An error/timeout result should be sent back to the model so it can attempt to recover, try a different approach, or inform the user.

Additional information

This feature is standard in other agentic coding tools. For example, Claude Code has a BASH_DEFAULT_TIMEOUT_MS environment variable that provides this exact safety net. Its absence in Codex CLI is a noticeable gap in user experience and agent robustness.

Current Experience with Codex CLI:

  1. I ask the agent to perform a task, for example, "install dependencies for this project."
  2. The agent decides to run npm install.
  3. The command hangs due to a network issue or a problematic package script.
  4. The Codex TUI shows the spinner and "Working..." indefinitely. I have no idea if it's making progress or if it's completely stuck. My only recourse is to Ctrl+C out of the entire session.

Desired Experience:

  1. Same prompt as above.
  2. The agent runs npm install.
  3. The command hangs.
  4. After the default timeout (e.g., 120 seconds), the command is killed.
  5. The TUI displays a message like: • Ran npm install [timed out after 120s].
  6. The agent receives an error result for its tool call and can then reason about the failure, perhaps trying npm install --verbose or notifying me of the issue.

While the shell tool does have a timeout_ms parameter, the model does not and cannot be expected to proactively add a timeout to every single command it runs. A global default timeout would make the agent much more resilient and provide a significantly better user experience by preventing indefinite hangs.

View original on GitHub ↗

8 Comments

github-actions[bot] contributor · 9 months ago

Potential duplicates detected:

  • #4337
  • #4592
  • #4751
  • #4186
  • #3995

Powered by Codex Action

coygeek · 9 months ago

Here is a potential high-level plan for implementing a default timeout for shell commands.

Objective

Introduce a configurable, default timeout for all shell commands executed by the agent to prevent indefinite hangs. If a command exceeds this timeout, it will be terminated, and clear feedback will be provided to both the user (in the TUI) and the agent (as a tool result) to improve agent robustness and enable graceful recovery. The model-specified timeout_ms parameter will always take precedence when provided.

---

High-Level Plan

The implementation can be broken down into four main phases: Configuration, Core Execution Logic, TUI Feedback, and Agent Feedback.

Phase 1: Configuration Layer

This phase introduces a new, user-configurable setting for the default timeout.

  1. Add Configuration Field: Introduce a new optional field, shell_default_timeout_ms, to the TOML configuration struct (ConfigToml in codex-rs/core/src/config_types.rs).
  1. Update Core Config Struct: Propagate this new setting into the core Config struct (codex-rs/core/src/config.rs). If the value is not present in config.toml, a sensible hardcoded default (e.g., 120,000 ms) will be applied.
  1. Establish Precedence: The timeout duration for any given shell command will be resolved using the following order of precedence:
  2. The timeout_ms value explicitly provided by the model in the shell tool call.
  3. The shell_default_timeout_ms value from the user's config.toml.
  4. The hardcoded default value.
Phase 2: Core Execution Logic

This phase integrates the new configuration into the command execution pipeline.

  1. Update the ShellHandler: The logic will be centralized within the ShellHandler (codex-rs/core/src/tools/handlers/shell.rs), which is responsible for converting the model's tool call into the ExecParams struct used for execution.
  1. Apply Timeout Fallback: When constructing the ExecParams, the handler will check if the model provided a timeout_ms. If it did not, the handler will retrieve the shell_default_timeout_ms from the Config and populate the timeout_ms field in ExecParams.
  1. Reuse Existing Timeout Mechanism: This approach ensures that ExecParams always contains a timeout value, allowing us to leverage the existing robust timeout logic in codex-rs/core/src/exec.rs. This logic already uses tokio::time::timeout for process monitoring and termination, and it correctly returns a SandboxErr::Timeout error, which we will propagate.
Phase 3: Data Propagation and TUI Feedback

This phase ensures the user receives clear visual feedback when a command times out.

  1. Propagate Timeout Information: The ExecToolCallOutput struct already contains a timed_out: bool flag. The error handling path for SandboxErr::Timeout will be updated to ensure this flag is set to true on the resulting ExecToolCallOutput. The process exit code will also be set to a conventional timeout value (e.g., 124).
  1. Update the ExecCell Renderer: The UI component responsible for rendering command history (ExecCell in codex-rs/tui/src/exec_cell/) will be modified to check the timed_out flag of the CommandOutput.
  1. Display Timeout Status: If timed_out is true, the ExecCell will display a clear, distinct message in its header, such as [timed out after 120s], instead of the standard success (✓) or failure (✗) indicators. This provides immediate and unambiguous feedback to the user in the TUI.
Phase 4: Agent Feedback

This phase ensures the agent is informed of the timeout, enabling it to self-correct.

  1. Format the Tool Output for the Agent: The function that formats the tool execution result into a string for the model (format_exec_output_apply_patch in codex-rs/core/src/tools/mod.rs) will be updated.
  1. Provide Clear Error Message: When the timed_out flag is true, the formatter will prepend a clear, natural-language error message to any partial stdout/stderr that was captured (e.g., "Command timed out after 120 seconds."). This gives the model explicit context about the failure, allowing it to reason about the next best step, such as retrying with a longer timeout, attempting an alternative command, or notifying the user.

---

Testing Strategy

  • Unit Tests: Add a test to verify the configuration loading and the timeout precedence logic within the ShellHandler.
  • Integration Test: Create a test that executes a long-running command (e.g., sleep 5) without a model-specified timeout. Assert that the process is terminated by the new default timeout and that the returned ExecToolCallOutput has timed_out set to true and the correct exit code.
  • TUI Snapshot Test: Add a snapshot test for the ExecCell to confirm that the [timed out after ...] message is rendered correctly in the TUI history.
  • API Mock Test: Verify through a mock API test that the formatted timeout error string is correctly included in the tool output sent back to the agent in the subsequent request.
insilications · 9 months ago

Indeed, I am seeing a lot of shell function_call to rg where gpt5-codex chooses a timeout_ms of 1000, which is not enough for some searches.

Owen-OptiGrid · 8 months ago

I'd like shell command timeouts to be more visible / configurable too, for opposite reasons. I use Codex CLI with Terraform often which it works well with (provided I watch it carefully) but it often allows Terraform commands to timeout prematurely leaving lingering locks or corrupted/incomplete Terraform state and despite my best efforts to warn against that in the AGENTS.md it doesn't reliably adhere to my instructions.

I'd also suggest for running shell commands a TUI timeout progress bar with some hotkey shortcuts to extend or cancel the command early would also be great. Ultimately making a shell command timeout configurable with optional overrides for specific commands is what I'd like.

rueckert-digital · 7 months ago

As Codex might also be used for build processes, deployments or IO intensive other work we should be able to define the timeout treshold in config.toml and/or env var please.

Kreijstal · 6 months ago

please I need to configure timeout

coygeek · 4 months ago

Status Update (Feb 2026)

After reviewing the current codebase, this issue is partially resolved. Here's a breakdown:

What's been implemented
  1. Default timeout existsDEFAULT_EXEC_COMMAND_TIMEOUT_MS provides a fallback when the model doesn't specify timeout_ms. User-initiated shell commands use a 1-hour ceiling (PR #7025).
  2. TUI feedback — Timeout events now display with exit code 124 and a structured timeout prefix in the history.
  3. Agent feedbackbuild_content_with_timeout() prepends a clear timeout message to the tool output, enabling the model to reason about and recover from the failure.
  4. Related issues resolved — #4337 (indefinite hangs), #4186 (non-interactive timeouts), #3995 (stuck processes) are all closed.
What's still missing

The core ask from this issue and multiple commenters remains unresolved: user-configurable shell command timeouts.

  • There is no shell_default_timeout_ms (or equivalent) field in config.toml.
  • There is no environment variable equivalent to Claude Code's BASH_DEFAULT_TIMEOUT_MS.
  • ConfigToml has background_terminal_timeout for background terminals and tool_timeout_sec for MCP tools, but nothing for regular agent-initiated shell commands.
  • The model still sometimes picks poor timeout_ms values (e.g., 1000ms for rg searches, as noted by @insilications), and users have no way to set a floor or default.
  • Commenters have specific use cases requiring configurability: Terraform state locks (@Owen-OptiGrid), build/deploy processes (@rueckert-digital).
Recommendation

Keep this issue open until a user-facing configuration option is added (e.g., shell_default_timeout_ms in config.toml and/or an env var), with the precedence chain: model-specified timeout_ms > user config > hardcoded default.

Kreijstal · 4 months ago

1000ms for rg might be low if your codebase is huge you can have rg searches going on for 10 minutes