Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions codex-rs/core/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,14 @@
},
"type": "array"
},
"terminal_title": {
"default": null,
"description": "Ordered list of terminal title item identifiers.\n\nWhen set, the TUI renders the selected items into the terminal window/tab title. When unset, the TUI defaults to: `spinner` and `project`.",
"items": {
"type": "string"
},
"type": "array"
},
"theme": {
"default": null,
"description": "Syntax highlighting theme name (kebab-case).\n\nWhen set, overrides automatic light/dark theme detection. Use `/theme` in the TUI or see `$CODEX_HOME/themes` for custom themes.",
Expand Down
6 changes: 6 additions & 0 deletions codex-rs/core/src/config/config_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ fn config_toml_deserializes_model_availability_nux() {
show_tooltips: true,
alternate_screen: AltScreenMode::default(),
status_line: None,
terminal_title: None,
theme: None,
model_availability_nux: ModelAvailabilityNuxConfig {
shown_count: HashMap::from([
Expand Down Expand Up @@ -921,6 +922,7 @@ fn tui_config_missing_notifications_field_defaults_to_enabled() {
show_tooltips: true,
alternate_screen: AltScreenMode::Auto,
status_line: None,
terminal_title: None,
theme: None,
model_availability_nux: ModelAvailabilityNuxConfig::default(),
}
Expand Down Expand Up @@ -4349,6 +4351,7 @@ fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> {
tool_suggest: ToolSuggestConfig::default(),
tui_alternate_screen: AltScreenMode::Auto,
tui_status_line: None,
tui_terminal_title: None,
tui_theme: None,
otel: OtelConfig::default(),
},
Expand Down Expand Up @@ -4491,6 +4494,7 @@ fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> {
tool_suggest: ToolSuggestConfig::default(),
tui_alternate_screen: AltScreenMode::Auto,
tui_status_line: None,
tui_terminal_title: None,
tui_theme: None,
otel: OtelConfig::default(),
};
Expand Down Expand Up @@ -4631,6 +4635,7 @@ fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> {
tool_suggest: ToolSuggestConfig::default(),
tui_alternate_screen: AltScreenMode::Auto,
tui_status_line: None,
tui_terminal_title: None,
tui_theme: None,
otel: OtelConfig::default(),
};
Expand Down Expand Up @@ -4757,6 +4762,7 @@ fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> {
tool_suggest: ToolSuggestConfig::default(),
tui_alternate_screen: AltScreenMode::Auto,
tui_status_line: None,
tui_terminal_title: None,
tui_theme: None,
otel: OtelConfig::default(),
};
Expand Down
24 changes: 19 additions & 5 deletions codex-rs/core/src/config/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,40 @@ pub enum ConfigEdit {
ClearPath { segments: Vec<String> },
}

/// Produces a config edit that sets `[tui] theme = "<name>"`.
/// Produces a config edit that sets `[tui].theme = "<name>"`.
pub fn syntax_theme_edit(name: &str) -> ConfigEdit {
ConfigEdit::SetPath {
segments: vec!["tui".to_string(), "theme".to_string()],
value: value(name.to_string()),
}
}

/// Produces a config edit that sets `[tui].status_line` to an explicit ordered list.
///
/// The array is written even when it is empty so "hide the status line" stays
/// distinct from "unset, so use defaults".
pub fn status_line_items_edit(items: &[String]) -> ConfigEdit {
let mut array = toml_edit::Array::new();
for item in items {
array.push(item.clone());
}
let array = items.iter().cloned().collect::<toml_edit::Array>();

ConfigEdit::SetPath {
segments: vec!["tui".to_string(), "status_line".to_string()],
value: TomlItem::Value(array.into()),
}
}

/// Produces a config edit that sets `[tui].terminal_title` to an explicit ordered list.
///
/// The array is written even when it is empty so "disabled title updates" stays
/// distinct from "unset, so use defaults".
pub fn terminal_title_items_edit(items: &[String]) -> ConfigEdit {
let array = items.iter().cloned().collect::<toml_edit::Array>();

ConfigEdit::SetPath {
segments: vec!["tui".to_string(), "terminal_title".to_string()],
value: TomlItem::Value(array.into()),
}
}

pub fn model_availability_nux_count_edits(shown_count: &HashMap<String, u32>) -> Vec<ConfigEdit> {
let mut shown_count_entries: Vec<_> = shown_count.iter().collect();
shown_count_entries.sort_unstable_by(|(left, _), (right, _)| left.cmp(right));
Expand Down
6 changes: 6 additions & 0 deletions codex-rs/core/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,11 @@ pub struct Config {
/// `current-dir`.
pub tui_status_line: Option<Vec<String>>,

/// Ordered list of terminal title item identifiers for the TUI.
///
/// When unset, the TUI defaults to: `project` and `spinner`.
pub tui_terminal_title: Option<Vec<String>>,

/// Syntax highlighting theme override (kebab-case name).
pub tui_theme: Option<String>,

Expand Down Expand Up @@ -2823,6 +2828,7 @@ impl Config {
.map(|t| t.alternate_screen)
.unwrap_or_default(),
tui_status_line: cfg.tui.as_ref().and_then(|t| t.status_line.clone()),
tui_terminal_title: cfg.tui.as_ref().and_then(|t| t.terminal_title.clone()),
tui_theme: cfg.tui.as_ref().and_then(|t| t.theme.clone()),
otel: {
let t: OtelConfigToml = cfg.otel.unwrap_or_default();
Expand Down
7 changes: 7 additions & 0 deletions codex-rs/core/src/config/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,13 @@ pub struct Tui {
#[serde(default)]
pub status_line: Option<Vec<String>>,

/// Ordered list of terminal title item identifiers.
///
/// When set, the TUI renders the selected items into the terminal window/tab title.
/// When unset, the TUI defaults to: `spinner` and `project`.
#[serde(default)]
pub terminal_title: Option<Vec<String>>,

/// Syntax highlighting theme name (kebab-case).
///
/// When set, overrides automatic light/dark theme detection.
Expand Down
Loading
Loading