Compare commits

...

2 Commits

Author SHA1 Message Date
Dylan Hurd
71d6525953 cleanup codex code 2025-09-26 14:05:58 -07:00
Dylan
f139e573ac Add config subcommand to validate configuration 2025-09-26 12:49:15 -07:00
3 changed files with 99 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
use codex_common::CliConfigOverrides;
use codex_common::create_config_summary_entries;
use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
const EXIT_CODE_INVALID_CONFIG: i32 = 3;
pub(crate) fn validate_config(cli_overrides: CliConfigOverrides, should_print: bool) {
let cli_overrides = match cli_overrides.parse_overrides() {
Ok(overrides) => overrides,
Err(err) => {
eprintln!("Error parsing -c overrides: {err}");
std::process::exit(EXIT_CODE_INVALID_CONFIG);
}
};
match Config::load_with_cli_overrides(cli_overrides, ConfigOverrides::default()) {
Ok(config) => {
if should_print {
println!("Current default config settings:");
println!("--------------------------------");
let entries = create_config_summary_entries(&config);
for (key, value) in entries {
println!("{key}: {value}");
}
println!("--------------------------------");
println!("* Note that various commands may override specific settings. *");
}
}
Err(err) => {
if should_print {
eprintln!("Config validation error: {err}");
}
std::process::exit(EXIT_CODE_INVALID_CONFIG);
}
}
}

View File

@@ -22,9 +22,11 @@ use owo_colors::OwoColorize;
use std::path::PathBuf;
use supports_color::Stream;
mod config_command;
mod mcp_cmd;
mod pre_main_hardening;
use crate::config_command::validate_config;
use crate::mcp_cmd::McpCli;
use crate::proto::ProtoCli;
@@ -85,6 +87,9 @@ enum Subcommand {
/// Resume a previous interactive session (picker by default; use --last to continue the most recent).
Resume(ResumeCommand),
/// Loads and validates a command. May support additional behavior in the future.
Config(ConfigCommand),
/// Internal: generate TypeScript protocol bindings.
#[clap(hide = true)]
GenerateTs(GenerateTsCommand),
@@ -101,6 +106,13 @@ struct CompletionCommand {
shell: Shell,
}
#[derive(Debug, Parser)]
struct ConfigCommand {
/// Skip printing result
#[arg(short = 's', default_value_t = false)]
silent: bool,
}
#[derive(Debug, Parser)]
struct ResumeCommand {
/// Conversation/session id (UUID). When provided, resumes this session.
@@ -313,6 +325,11 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
Some(Subcommand::Completion(completion_cli)) => {
print_completion(completion_cli);
}
Some(Subcommand::Config(config_cli)) => {
let ConfigCommand { silent } = config_cli;
validate_config(root_config_overrides, !silent);
}
Some(Subcommand::Debug(debug_args)) => match debug_args.cmd {
DebugCommand::Seatbelt(mut seatbelt_cli) => {
prepend_config_flags(

View File

@@ -0,0 +1,44 @@
use std::fs;
use std::path::Path;
use anyhow::Result;
use assert_cmd::Command;
use tempfile::TempDir;
fn codex_command(codex_home: &Path) -> Result<Command> {
let mut cmd = Command::cargo_bin("codex")?;
cmd.env("CODEX_HOME", codex_home);
Ok(cmd)
}
#[test]
fn config_subcommand_reports_success_for_valid_config() -> Result<()> {
let codex_home = TempDir::new()?;
let config_path = codex_home.path().join("config.toml");
fs::write(config_path, "model = \"gpt-5\"\n")?;
let mut cmd = codex_command(codex_home.path())?;
let output = cmd.arg("config").output()?;
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout)?;
assert!(stdout.contains("Current default config settings"));
Ok(())
}
#[test]
fn config_subcommand_exits_with_code_three_on_validation_error() -> Result<()> {
let codex_home = TempDir::new()?;
let config_path = codex_home.path().join("config.toml");
fs::write(config_path, "model = 123\n")?;
let mut cmd = codex_command(codex_home.path())?;
let output = cmd.arg("config").output()?;
assert_eq!(output.status.code(), Some(3));
let stderr = String::from_utf8(output.stderr)?;
assert!(stderr.contains("Config validation error"));
Ok(())
}