diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index a97948f3ea..20309955cc 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -9,6 +9,8 @@ use crate::onboarding::onboarding_screen::OnboardingScreenArgs; use crate::should_show_login_screen; use crate::slash_command::SlashCommand; use crate::tui; +use clap::CommandFactory; +use clap::Parser as ClapParser; use codex_core::config::Config; use codex_core::protocol::Event; use codex_core::protocol::EventMsg; @@ -371,6 +373,24 @@ impl App<'_> { widget.add_status_output(); } } + SlashCommand::Help => { + if let AppState::Chat { widget } = &mut self.app_state { + #[derive(ClapParser, Debug)] + #[command(version)] + struct HelpCli { + #[clap(flatten)] + config_overrides: codex_common::CliConfigOverrides, + #[clap(flatten)] + inner: crate::Cli, + } + + let mut cmd = HelpCli::command(); + let mut buf: Vec = Vec::new(); + let _ = cmd.write_help(&mut buf); + let help_text = String::from_utf8_lossy(&buf).to_string(); + widget.add_help_output(help_text); + } + } SlashCommand::Prompts => { if let AppState::Chat { widget } = &mut self.app_state { widget.add_prompts_output(); diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index d03a51bd70..e48032bdff 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -618,6 +618,10 @@ impl ChatWidget<'_> { self.add_to_history(HistoryCell::new_prompts_output()); } + pub(crate) fn add_help_output(&mut self, help_text: String) { + self.add_to_history(HistoryCell::new_help_output(help_text)); + } + /// Forward file-search results to the bottom pane. pub(crate) fn apply_file_search_result(&mut self, query: String, matches: Vec) { self.bottom_pane.on_file_search_result(query, matches); diff --git a/codex-rs/tui/src/history_cell.rs b/codex-rs/tui/src/history_cell.rs index 1236d4b550..59e5e03b3b 100644 --- a/codex-rs/tui/src/history_cell.rs +++ b/codex-rs/tui/src/history_cell.rs @@ -129,6 +129,9 @@ pub(crate) enum HistoryCell { view: TextBlock, }, + /// Output from the `/help` command. + HelpOutput { view: TextBlock }, + /// Error event from the backend. ErrorEvent { view: TextBlock, @@ -194,6 +197,7 @@ impl HistoryCell { | HistoryCell::GitDiffOutput { view } | HistoryCell::StatusOutput { view } | HistoryCell::PromptsOutput { view } + | HistoryCell::HelpOutput { view } | HistoryCell::ErrorEvent { view } | HistoryCell::SessionInfo { view } | HistoryCell::CompletedMcpToolCall { view } @@ -705,6 +709,18 @@ impl HistoryCell { } } + pub(crate) fn new_help_output(help_text: String) -> Self { + let mut lines: Vec> = Vec::new(); + lines.push(Line::from("/help".magenta())); + for l in help_text.lines() { + lines.push(Line::from(l.to_string())); + } + lines.push(Line::from("")); + HistoryCell::HelpOutput { + view: TextBlock::new(lines), + } + } + pub(crate) fn new_error_event(message: String) -> Self { let lines: Vec> = vec![vec!["🖐 ".red().bold(), message.into()].into(), "".into()]; diff --git a/codex-rs/tui/src/slash_command.rs b/codex-rs/tui/src/slash_command.rs index e58ab8521e..1abafc6bc8 100644 --- a/codex-rs/tui/src/slash_command.rs +++ b/codex-rs/tui/src/slash_command.rs @@ -18,6 +18,7 @@ pub enum SlashCommand { Diff, Status, Prompts, + Help, Logout, Quit, #[cfg(debug_assertions)] @@ -35,6 +36,7 @@ impl SlashCommand { SlashCommand::Diff => "show git diff (including untracked files)", SlashCommand::Status => "show current session configuration and token usage", SlashCommand::Prompts => "show example prompts", + SlashCommand::Help => "show command help", SlashCommand::Logout => "log out of Codex", #[cfg(debug_assertions)] SlashCommand::TestApproval => "test approval request",