cli: remove legacy profile v1 plumbing (#23886)

## Why

[#23883](https://github.com/openai/codex/pull/23883) moved the
user-facing `--profile` flag onto profile v2. The shared CLI option
layer still carried the old `config_profile` slot and several CLI
entrypoints still copied that value into legacy config overrides.
Leaving that path around makes the CLI surface look like it still
selects legacy `[profiles.*]` state even though `--profile` now means
`$CODEX_HOME/<name>.config.toml`.

## What

- Remove the legacy `config_profile` field and merge/copy path from
[`SharedCliOptions`](https://github.com/openai/codex/blob/95baaf72920c8db22097df8d15a0bb76c84528b6/codex-rs/utils/cli/src/shared_options.rs#L8-L177).
- Stop forwarding profile-v1 overrides from CLI, exec, TUI, doctor,
debug, feature, and exec-server paths; runtime profile selection remains
on `config_profile_v2` through
[`loader_overrides_for_profile`](https://github.com/openai/codex/blob/95baaf72920c8db22097df8d15a0bb76c84528b6/codex-rs/cli/src/main.rs#L1606-L1619).
- Resolve local OSS provider selection from the base config in exec and
TUI now that the legacy profile argument is gone.

## Testing

- Not run (cleanup-only follow-up to #23883).
This commit is contained in:
jif-oai
2026-05-21 17:21:37 +02:00
committed by GitHub
parent 298e5cfce1
commit e0e304b123
5 changed files with 14 additions and 70 deletions
-1
View File
@@ -496,7 +496,6 @@ fn config_overrides_from_interactive(
};
ConfigOverrides {
model: interactive.model.clone(),
config_profile: interactive.config_profile.clone(),
approval_policy,
sandbox_mode,
cwd: interactive.cwd.clone(),
+11 -51
View File
@@ -1331,7 +1331,7 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
root_remote_auth_token_env.as_deref(),
"debug clear-memories",
)?;
run_debug_clear_memories_command(&root_config_overrides, &interactive).await?;
run_debug_clear_memories_command(&root_config_overrides).await?;
}
},
Some(Subcommand::Execpolicy(ExecpolicyCommand { sub })) => match sub {
@@ -1381,14 +1381,8 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
"exec-server",
)?;
let strict_config = cmd.strict_config || root_strict_config;
run_exec_server_command(
cmd,
&arg0_paths,
&root_config_overrides,
interactive.config_profile.clone(),
strict_config,
)
.await?;
run_exec_server_command(cmd, &arg0_paths, &root_config_overrides, strict_config)
.await?;
}
Some(Subcommand::Features(FeaturesCli { sub })) => match sub {
FeaturesSubcommand::List => {
@@ -1397,7 +1391,6 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
root_remote_auth_token_env.as_deref(),
"features list",
)?;
// Respect root-level `-c` overrides plus top-level flags like `--profile`.
let mut cli_kv_overrides = root_config_overrides
.parse_overrides()
.map_err(anyhow::Error::msg)?;
@@ -1410,15 +1403,8 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
));
}
// Thread through relevant top-level flags (at minimum, `--profile`).
let overrides = ConfigOverrides {
config_profile: interactive.config_profile.clone(),
..Default::default()
};
let config = ConfigBuilder::default()
.cli_overrides(cli_kv_overrides)
.harness_overrides(overrides)
.build()
.await?;
let mut rows = Vec::with_capacity(FEATURES.len());
@@ -1444,7 +1430,7 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
root_remote_auth_token_env.as_deref(),
"features enable",
)?;
enable_feature_in_config(&interactive, &feature).await?;
enable_feature_in_config(&feature).await?;
}
FeaturesSubcommand::Disable(FeatureSetArgs { feature }) => {
reject_remote_mode_for_subcommand(
@@ -1452,7 +1438,7 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
root_remote_auth_token_env.as_deref(),
"features disable",
)?;
disable_feature_in_config(&interactive, &feature).await?;
disable_feature_in_config(&feature).await?;
}
},
}
@@ -1486,7 +1472,6 @@ async fn run_exec_server_command(
cmd: ExecServerCommand,
arg0_paths: &Arg0DispatchPaths,
root_config_overrides: &CliConfigOverrides,
config_profile: Option<String>,
strict_config: bool,
) -> anyhow::Result<()> {
let codex_self_exe = arg0_paths
@@ -1501,8 +1486,7 @@ async fn run_exec_server_command(
let environment_id = cmd
.environment_id
.ok_or_else(|| anyhow::anyhow!("--environment-id is required when --remote is set"))?;
let config =
load_exec_server_config(root_config_overrides, config_profile, strict_config).await?;
let config = load_exec_server_config(root_config_overrides, strict_config).await?;
let auth_provider =
load_exec_server_remote_auth_provider(&config, cmd.use_agent_identity_auth).await?;
let mut remote_config = codex_exec_server::RemoteEnvironmentConfig::new(
@@ -1520,8 +1504,7 @@ async fn run_exec_server_command(
// Local exec-server startup does not consume Config, but strict
// mode should still reject unknown fields before opening a listener.
let _validated_config =
load_exec_server_config(root_config_overrides, config_profile, strict_config)
.await?;
load_exec_server_config(root_config_overrides, strict_config).await?;
}
let listen_url = cmd
.listen
@@ -1564,7 +1547,6 @@ async fn load_exec_server_remote_auth_provider(
async fn load_exec_server_config(
root_config_overrides: &CliConfigOverrides,
config_profile: Option<String>,
strict_config: bool,
) -> anyhow::Result<codex_core::config::Config> {
let cli_kv_overrides = root_config_overrides
@@ -1572,10 +1554,6 @@ async fn load_exec_server_config(
.map_err(anyhow::Error::msg)?;
Ok(ConfigBuilder::default()
.cli_overrides(cli_kv_overrides)
.harness_overrides(ConfigOverrides {
config_profile,
..Default::default()
})
.strict_config(strict_config)
.build()
.await?)
@@ -1602,24 +1580,22 @@ async fn load_exec_server_remote_auth(
Ok(auth)
}
async fn enable_feature_in_config(interactive: &TuiCli, feature: &str) -> anyhow::Result<()> {
async fn enable_feature_in_config(feature: &str) -> anyhow::Result<()> {
FeatureToggles::validate_feature(feature)?;
let codex_home = find_codex_home()?;
ConfigEditsBuilder::new(&codex_home)
.with_profile(interactive.config_profile.as_deref())
.set_feature_enabled(feature, /*enabled*/ true)
.apply()
.await?;
println!("Enabled feature `{feature}` in config.toml.");
maybe_print_under_development_feature_warning(&codex_home, interactive, feature);
maybe_print_under_development_feature_warning(&codex_home, feature);
Ok(())
}
async fn disable_feature_in_config(interactive: &TuiCli, feature: &str) -> anyhow::Result<()> {
async fn disable_feature_in_config(feature: &str) -> anyhow::Result<()> {
FeatureToggles::validate_feature(feature)?;
let codex_home = find_codex_home()?;
ConfigEditsBuilder::new(&codex_home)
.with_profile(interactive.config_profile.as_deref())
.set_feature_enabled(feature, /*enabled*/ false)
.apply()
.await?;
@@ -1643,15 +1619,7 @@ fn loader_overrides_for_profile(
}
}
fn maybe_print_under_development_feature_warning(
codex_home: &std::path::Path,
interactive: &TuiCli,
feature: &str,
) {
if interactive.config_profile.is_some() {
return;
}
fn maybe_print_under_development_feature_warning(codex_home: &std::path::Path, feature: &str) {
let Some(spec) = FEATURES.iter().find(|spec| spec.key == feature) else {
return;
};
@@ -1709,7 +1677,6 @@ async fn run_debug_prompt_input_command(
};
let overrides = ConfigOverrides {
model: shared.model,
config_profile: shared.config_profile,
approval_policy,
sandbox_mode,
cwd: shared.cwd,
@@ -1777,18 +1744,12 @@ async fn run_debug_models_command(
async fn run_debug_clear_memories_command(
root_config_overrides: &CliConfigOverrides,
interactive: &TuiCli,
) -> anyhow::Result<()> {
let cli_kv_overrides = root_config_overrides
.parse_overrides()
.map_err(anyhow::Error::msg)?;
let overrides = ConfigOverrides {
config_profile: interactive.config_profile.clone(),
..Default::default()
};
let config = ConfigBuilder::default()
.cli_overrides(cli_kv_overrides)
.harness_overrides(overrides)
.build()
.await?;
@@ -2771,7 +2732,6 @@ mod tests {
assert_eq!(interactive.model.as_deref(), Some("gpt-5.1-test"));
assert!(interactive.oss);
assert_eq!(interactive.config_profile.as_deref(), None);
assert_eq!(interactive.config_profile_v2.as_deref(), Some("my-config"));
assert_matches!(
interactive.sandbox_mode,
+2 -3
View File
@@ -262,7 +262,6 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result
model: model_cli_arg,
oss,
oss_provider,
config_profile,
config_profile_v2,
sandbox_mode: sandbox_mode_cli_arg,
dangerously_bypass_approvals_and_sandbox,
@@ -379,7 +378,7 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result
let resolved = resolve_oss_provider(
oss_provider.as_deref(),
&config_toml,
config_profile.clone(),
/*config_profile*/ None,
);
if let Some(provider) = resolved {
@@ -409,7 +408,6 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result
let overrides = ConfigOverrides {
model,
review_model: None,
config_profile,
// Default to never ask for approvals in headless mode. Feature flags can override.
approval_policy: Some(AskForApproval::Never),
approvals_reviewer: None,
@@ -420,6 +418,7 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result
workspace_roots: None,
model_provider: model_provider.clone(),
service_tier: None,
config_profile: None,
codex_self_exe: arg0_paths.codex_self_exe.clone(),
codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(),
main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(),
+1 -2
View File
@@ -997,7 +997,7 @@ pub async fn run_main(
let resolved = resolve_oss_provider(
cli.oss_provider.as_deref(),
&config_toml,
cli.config_profile.clone(),
/*config_profile*/ None,
);
if let Some(provider) = resolved {
@@ -1041,7 +1041,6 @@ pub async fn run_main(
cwd
},
model_provider: model_provider_override.clone(),
config_profile: cli.config_profile.clone(),
codex_self_exe: arg0_paths.codex_self_exe.clone(),
codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(),
main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(),
-13
View File
@@ -30,10 +30,6 @@ pub struct SharedCliOptions {
#[arg(long = "local-provider")]
pub oss_provider: Option<String>,
/// Configuration profile from config.toml to specify default options.
#[arg(skip)]
pub config_profile: Option<String>,
/// Layer $CODEX_HOME/<name>.config.toml on top of the base user config.
#[arg(long = "profile", short = 'p')]
pub config_profile_v2: Option<ProfileV2Name>,
@@ -75,7 +71,6 @@ impl SharedCliOptions {
model,
oss,
oss_provider,
config_profile,
config_profile_v2,
sandbox_mode,
dangerously_bypass_approvals_and_sandbox,
@@ -88,7 +83,6 @@ impl SharedCliOptions {
model: root_model,
oss: root_oss,
oss_provider: root_oss_provider,
config_profile: root_config_profile,
config_profile_v2: root_config_profile_v2,
sandbox_mode: root_sandbox_mode,
dangerously_bypass_approvals_and_sandbox: root_dangerously_bypass_approvals_and_sandbox,
@@ -106,9 +100,6 @@ impl SharedCliOptions {
if oss_provider.is_none() {
oss_provider.clone_from(root_oss_provider);
}
if config_profile.is_none() {
config_profile.clone_from(root_config_profile);
}
if config_profile_v2.is_none() {
config_profile_v2.clone_from(root_config_profile_v2);
}
@@ -145,7 +136,6 @@ impl SharedCliOptions {
model,
oss,
oss_provider,
config_profile,
config_profile_v2,
sandbox_mode,
dangerously_bypass_approvals_and_sandbox,
@@ -163,9 +153,6 @@ impl SharedCliOptions {
if let Some(oss_provider) = oss_provider {
self.oss_provider = Some(oss_provider);
}
if let Some(config_profile) = config_profile {
self.config_profile = Some(config_profile);
}
if let Some(config_profile_v2) = config_profile_v2 {
self.config_profile_v2 = Some(config_profile_v2);
}