cli: rename profile v2 flag to --profile (#23883)

## Why

Profile v2 is taking over the user-facing profile selection path, so the
CLI no longer needs to expose the transitional `--profile-v2` spelling.
This switches the public args surface to `--profile` before the
remaining legacy profile plumbing is removed separately.

## What

- Rebind `--profile` and `-p` to the v2 profile name argument that
selects `$CODEX_HOME/<name>.config.toml`.
- Stop parsing the legacy shared CLI profile argument while keeping its
implementation path in place for follow-up cleanup.
- Update CLI validation, profile-name parse errors, and the
legacy-profile collision message/tests to refer to `--profile`.

## Testing

- `cargo test -p codex-cli -p codex-config -p codex-protocol -p
codex-utils-cli`
This commit is contained in:
jif-oai
2026-05-21 16:45:27 +02:00
committed by GitHub
parent c1d7f4c8f8
commit 8a511d5881
4 changed files with 14 additions and 19 deletions
+6 -11
View File
@@ -1477,7 +1477,7 @@ fn profile_v2_for_subcommand<'a>(
subcommand: DebugSubcommand::PromptInput(_), subcommand: DebugSubcommand::PromptInput(_),
}) => Ok(Some(profile_v2)), }) => Ok(Some(profile_v2)),
_ => anyhow::bail!( _ => anyhow::bail!(
"--profile-v2 only applies to runtime commands: `codex`, `codex exec`, `codex review`, `codex resume`, `codex fork`, and `codex debug prompt-input`." "--profile only applies to runtime commands: `codex`, `codex exec`, `codex review`, `codex resume`, `codex fork`, and `codex debug prompt-input`."
), ),
} }
} }
@@ -2286,21 +2286,19 @@ mod tests {
#[test] #[test]
fn profile_v2_is_rejected_for_config_management_subcommands() { fn profile_v2_is_rejected_for_config_management_subcommands() {
assert!( assert!(profile_v2_for_args(&["codex", "--profile", "work", "features", "list"]).is_err());
profile_v2_for_args(&["codex", "--profile-v2", "work", "features", "list"]).is_err()
);
} }
#[test] #[test]
fn profile_v2_is_allowed_for_runtime_subcommands() { fn profile_v2_is_allowed_for_runtime_subcommands() {
assert_eq!( assert_eq!(
profile_v2_for_args(&["codex", "--profile-v2", "work", "resume"]) profile_v2_for_args(&["codex", "--profile", "work", "resume"])
.expect("resume supports profile-v2") .expect("resume supports profile-v2")
.as_deref(), .as_deref(),
Some("work") Some("work")
); );
assert_eq!( assert_eq!(
profile_v2_for_args(&["codex", "--profile-v2", "work", "debug", "prompt-input"]) profile_v2_for_args(&["codex", "--profile", "work", "debug", "prompt-input"])
.expect("debug prompt-input supports profile-v2") .expect("debug prompt-input supports profile-v2")
.as_deref(), .as_deref(),
Some("work") Some("work")
@@ -2310,8 +2308,7 @@ mod tests {
#[test] #[test]
fn profile_v2_rejects_non_plain_names_at_parse_time() { fn profile_v2_rejects_non_plain_names_at_parse_time() {
assert!( assert!(
MultitoolCli::try_parse_from(["codex", "--profile-v2", "nested/work", "resume"]) MultitoolCli::try_parse_from(["codex", "--profile", "nested/work", "resume"]).is_err()
.is_err()
); );
} }
@@ -2762,8 +2759,6 @@ mod tests {
"-m", "-m",
"gpt-5.1-test", "gpt-5.1-test",
"-p", "-p",
"my-profile",
"--profile-v2",
"my-config", "my-config",
"-C", "-C",
"/tmp", "/tmp",
@@ -2776,7 +2771,7 @@ mod tests {
assert_eq!(interactive.model.as_deref(), Some("gpt-5.1-test")); assert_eq!(interactive.model.as_deref(), Some("gpt-5.1-test"));
assert!(interactive.oss); assert!(interactive.oss);
assert_eq!(interactive.config_profile.as_deref(), Some("my-profile")); assert_eq!(interactive.config_profile.as_deref(), None);
assert_eq!(interactive.config_profile_v2.as_deref(), Some("my-config")); assert_eq!(interactive.config_profile_v2.as_deref(), Some("my-config"));
assert_matches!( assert_matches!(
interactive.sandbox_mode, interactive.sandbox_mode,
+5 -5
View File
@@ -196,9 +196,9 @@ async fn exec_cli_applies_model_instructions_file() {
); );
} }
/// Verify that `codex exec --profile ...` preserves the active profile when it /// Verify that `codex exec --profile ...` preserves the active user config
/// starts the in-process app-server thread, so profile-scoped /// profile when it starts the in-process app-server thread, so the selected
/// `model_instructions_file` is applied to the outbound request. /// profile's `model_instructions_file` reaches the outbound request.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn exec_cli_profile_applies_model_instructions_file() { async fn exec_cli_profile_applies_model_instructions_file() {
skip_if_no_network!(); skip_if_no_network!();
@@ -223,8 +223,8 @@ async fn exec_cli_profile_applies_model_instructions_file() {
let home = TempDir::new().unwrap(); let home = TempDir::new().unwrap();
std::fs::write( std::fs::write(
home.path().join("config.toml"), home.path().join("default.config.toml"),
format!("[profiles.default]\nmodel_instructions_file = \"{custom_path_str}\"\n",), format!("model_instructions_file = \"{custom_path_str}\"\n"),
) )
.unwrap(); .unwrap();
+1 -1
View File
@@ -114,7 +114,7 @@ impl fmt::Display for ProfileV2NameParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
"invalid --profile-v2 value `{}`; pass a plain name such as `work`", "invalid --profile value `{}`; pass a plain name such as `work`",
self.value self.value
) )
} }
+2 -2
View File
@@ -31,11 +31,11 @@ pub struct SharedCliOptions {
pub oss_provider: Option<String>, pub oss_provider: Option<String>,
/// Configuration profile from config.toml to specify default options. /// Configuration profile from config.toml to specify default options.
#[arg(long = "profile", short = 'p')] #[arg(skip)]
pub config_profile: Option<String>, pub config_profile: Option<String>,
/// Layer $CODEX_HOME/<name>.config.toml on top of the base user config. /// Layer $CODEX_HOME/<name>.config.toml on top of the base user config.
#[arg(long = "profile-v2")] #[arg(long = "profile", short = 'p')]
pub config_profile_v2: Option<ProfileV2Name>, pub config_profile_v2: Option<ProfileV2Name>,
/// Select the sandbox policy to use when executing model-generated shell /// Select the sandbox policy to use when executing model-generated shell