Make command folding and output truncation in Codex CLI TUI configurable or disable-able

Open 💬 9 comments Opened Oct 1, 2025 by Konjac-XZ

Problem

Currently, the Codex CLI TUI forcibly folds multi-line commands and command output, showing only a few lines and replacing the rest with an ellipsis line (e.g., … +X lines). This makes it very difficult to review, debug, or copy full scripts or command outputs generated by the model, especially for heredoc-heavy workflows (e.g., python3 - <<'PY' ...).

There is no user-exposed setting in the CLI or config file to disable or configure this folding/truncation. The behavior is hard-coded in the TUI. Many users would prefer to see the full command/output or at least have the ability to customize the folding threshold.

References

Requested Solution

  • Add a user-facing configuration option (CLI flag or config.toml) to:
  • Disable command folding/output truncation entirely (always show full content)
  • Or, allow customizing the number of lines shown before folding (both for command lines and output)
  • Optionally, provide a per-session or per-command override (e.g., a hotkey to expand/collapse in the TUI)

Workarounds (not sufficient)

  • Using headless/non-interactive mode avoids the TUI, but disables the interactive session.
  • Building from source to raise caps is not user-friendly.

Impact

  • Users running or reviewing long scripts (e.g., model-generated bash/python heredocs) can see the full command, copy/edit/debug as needed.
  • Makes Codex CLI more transparent and user-friendly for advanced workflows.

---

Filed by @Konjac-XZ. If more details are needed, please let me know.

View original on GitHub ↗

9 Comments

kzhrv · 8 months ago

I would also like to see this enhancement. I would find it infinitely useful without any deeper layers adjustments.

bakaburg1 · 6 months ago

is this planned? I'd love to see what's going on instead of just

<img width="274" height="33" alt="Image" src="https://github.com/user-attachments/assets/6b4733f8-2a75-4e19-91bb-5344bce8d5b8" />

escape0707 · 4 months ago

I want to add that while this convenient feature is not implemented yet. I found I can view past run full command and its output when in the "double-tap-ESC history message editing" TUI.

I don't know why Google AI Mode and ChatGPT Pro all can't point that workaround out for me, but since they all direct me here for "existing issue", I guess I'll just "add this to the context". /s

Edit: The obvious disadvantage of this workaround is that I have to press ESC to get into this TUI, thus I can't inspect commands and outputs as they are getting run by the working Codex agent. I have to wait until it finishes.

TheReaperJay · 3 months ago

2026, aka 10 years later in AI land, and this is still the current Codex UX for anything longer than a few lines:

```text
Ran ssh YYY "duckdb -c \"DESCRIBE SELECT * FROM read_parquet('XXX') LIMIT 0;\""
└ ┌───────────────────────────────────────────┐
│ Describe │
… +36 lines
└───────────────────────────────────────────┘

… +126 lines
└─────────────────────────────────────────┘
│ Describe │
… +19 lines
└─────────────────────────────────┘


  This makes safe development much harder because you cannot reliably inspect full tool output inline.

  Current workaround is exporting results to files and re-reading them, which is obviously silly for normal CLI flow.

  I understand external contribution load is high, but this is a critical UX issue and cannot be fixed downstream in user config alone because the truncation behavior is hardcoded in the renderer.

Maybe need to surface more of the UX so that community can extend via plugins and bypass the acceptance requirements if dev pipeline is so full that these sorts of things stay open for half a year?

  ## Accurate fix (current Codex layout)

  Note: current paths are under codex-rs/tui_app_server/src/* (not codex-rs/tui/src/*).

  ### 1) `codex-rs/core/src/config/types.rs`

  Add enum:

#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, Default)]
#[serde(rename_all = "lowercase")]
pub enum ToolOutputDisplay {
#[default]
Collapsed,
Full,
}


  Add field to Tui:

#[serde(default)]
pub tool_output_display: ToolOutputDisplay,


  ### 2) `codex-rs/core/src/config/mod.rs`

  Import and expose runtime config field:

use crate::config::types::ToolOutputDisplay;

pub tool_output_display: ToolOutputDisplay,


  Wire from TOML:

tool_output_display: cfg
.tui
.as_ref()
.map(|t| t.tool_output_display)
.unwrap_or_default(),


  ### 3) `codex-rs/tui_app_server/src/exec_cell/model.rs`

  Store mode on ExecCell and carry it through rebuilds:

use codex_core::config::types::ToolOutputDisplay;

pub(crate) struct ExecCell {
pub(crate) calls: Vec<ExecCall>,
animations_enabled: bool,
tool_output_display: ToolOutputDisplay,
}


  Constructor keeps default behavior:

pub(crate) fn new(call: ExecCall, animations_enabled: bool) -> Self {
Self {
calls: vec![call],
animations_enabled,
tool_output_display: ToolOutputDisplay::Collapsed,
}
}


  Accessors:

pub(crate) fn tool_output_display(&self) -> ToolOutputDisplay {
self.tool_output_display
}

pub(crate) fn set_tool_output_display(&mut self, tool_output_display: ToolOutputDisplay) {
self.tool_output_display = tool_output_display;
}


  And in `with_added_call`, `preserve tool_output_display`.

  ### 4) `codex-rs/tui_app_server/src/exec_cell/render.rs`

  Import:

use codex_core::config::types::ToolOutputDisplay;


  Update constructor path to receive mode and set it:

pub(crate) fn new_active_exec_command(
call_id: String,
command: Vec<String>,
parsed: Vec<ParsedCommand>,
source: ExecCommandSource,
interaction_input: Option<String>,
animations_enabled: bool,
tool_output_display: ToolOutputDisplay,
) -> ExecCell {
let mut cell = ExecCell::new(
ExecCall {
call_id,
command,
parsed,
output: None,
source,
start_time: Some(Instant::now()),
duration: None,
interaction_input,
},
animations_enabled,
);
cell.set_tool_output_display(tool_output_display);
cell
}


  Overflow-safe ellipsis math:

let show_ellipsis = total > line_limit.saturating_mul(2);


  Gate truncation:

let full_output_mode =
self.tool_output_display() == ToolOutputDisplay::Full && !call.is_user_shell_command();

let line_limit = if call.is_user_shell_command() {
USER_SHELL_TOOL_CALL_MAX_LINES
} else if full_output_mode {
usize::MAX
} else {
TOOL_CALL_MAX_LINES
};

let display_limit = if call.is_user_shell_command() {
USER_SHELL_TOOL_CALL_MAX_LINES
} else if full_output_mode {
usize::MAX
} else {
layout.output_max_lines
};

let rendered_output = if full_output_mode {
prefixed_output
} else {
Self::truncate_lines_middle(
&prefixed_output,
display_limit,
width,
raw_output.omitted,
Some(Line::from(Span::from(layout.output_block.subsequent_prefix).dim())),
)
};


  ### 5) `codex-rs/tui_app_server/src/chatwidget.rs`

  Pass the new arg at all new_active_exec_command(...) call sites:

self.config.tool_output_display


  ### 6) `codex-rs/tui_app_server/src/pager_overlay.rs`

  Update test call site with explicit mode:

codex_core::config::types::ToolOutputDisplay::Collapsed


  ### 7) `codex-rs/core/src/config/config_tests.rs`

  Update expected structs (Tui and Config) to include:

tool_output_display: ToolOutputDisplay::Collapsed


  (and import ToolOutputDisplay in the test module).

  ### 8) User config

  `~/.codex/config.toml:`

[tui]
tool_output_display = "full" # full | collapsed


  collapsed preserves current behavior, full disables the collapse path for tool output rendering.

  ———

  In the meantime, anyone blocked by this can apply the patch and rebuild.

  Repo (script: fetch latest, apply patch, build/install):
  https://github.com/TheReaperJay/codex-full-tool-output-installer/tree/master

  Current patch target is pinned to the layout used by Codex CLI 0.117.0 / commit e39ddc6, so expect refreshes as upstream files move.
TheReaperJay · 3 months ago

To make it clear why this is a critical UX/security issue:
In the past few weeks we are dealing with increased security attacks through AI-assisted malware that is using all sorts of bleeding edge obfuscation tactics.

The fact that codex is truncating tool response with no way to force a review means this is yet another surface vector to slip things past even manual tool use - not to mention unattended agents.

escape0707 · 3 months ago

@TheReaperJay Bro thanks for the patch, but I just want to note that even if they don't accept non-contributor PRs and close them, the best way to get people try your patch is still to file a PR and mention it here rather than in a long and unorganized comment...

TheReaperJay · 3 months ago

Cool thanks @escape0707 - I read through the contributing guideline and saw that they just auto close the PR and assume they just straight up ignore it and move to a graveyard but you're right I'll give that a shot anyway!

Fwiw codex found this one for me and I can see there are lots of other issues opened for it too so I think you're right and it might surface it more.

kzhrv · 3 months ago

@TheReaperJay great lead on this issue!

Make a PR and link it here! We should take any chance to surface this issue just as @escape0707 said.

graehl · 3 months ago

absolutely deranged UX!
on par with while i am typing, giving a random 'approval' focus-stealing style. (why not a M- or C- required to approve if recent keystrokes)