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

View File

@@ -1477,7 +1477,7 @@ fn profile_v2_for_subcommand<'a>(
subcommand: DebugSubcommand::PromptInput(_),
}) => Ok(Some(profile_v2)),
_ => 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]
fn profile_v2_is_rejected_for_config_management_subcommands() {
assert!(
profile_v2_for_args(&["codex", "--profile-v2", "work", "features", "list"]).is_err()
);
assert!(profile_v2_for_args(&["codex", "--profile", "work", "features", "list"]).is_err());
}
#[test]
fn profile_v2_is_allowed_for_runtime_subcommands() {
assert_eq!(
profile_v2_for_args(&["codex", "--profile-v2", "work", "resume"])
profile_v2_for_args(&["codex", "--profile", "work", "resume"])
.expect("resume supports profile-v2")
.as_deref(),
Some("work")
);
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")
.as_deref(),
Some("work")
@@ -2310,8 +2308,7 @@ mod tests {
#[test]
fn profile_v2_rejects_non_plain_names_at_parse_time() {
assert!(
MultitoolCli::try_parse_from(["codex", "--profile-v2", "nested/work", "resume"])
.is_err()
MultitoolCli::try_parse_from(["codex", "--profile", "nested/work", "resume"]).is_err()
);
}
@@ -2762,8 +2759,6 @@ mod tests {
"-m",
"gpt-5.1-test",
"-p",
"my-profile",
"--profile-v2",
"my-config",
"-C",
"/tmp",
@@ -2776,7 +2771,7 @@ mod tests {
assert_eq!(interactive.model.as_deref(), Some("gpt-5.1-test"));
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_matches!(
interactive.sandbox_mode,

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
/// starts the in-process app-server thread, so profile-scoped
/// `model_instructions_file` is applied to the outbound request.
/// Verify that `codex exec --profile ...` preserves the active user config
/// profile when it starts the in-process app-server thread, so the selected
/// profile's `model_instructions_file` reaches the outbound request.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn exec_cli_profile_applies_model_instructions_file() {
skip_if_no_network!();
@@ -223,8 +223,8 @@ async fn exec_cli_profile_applies_model_instructions_file() {
let home = TempDir::new().unwrap();
std::fs::write(
home.path().join("config.toml"),
format!("[profiles.default]\nmodel_instructions_file = \"{custom_path_str}\"\n",),
home.path().join("default.config.toml"),
format!("model_instructions_file = \"{custom_path_str}\"\n"),
)
.unwrap();

View File

@@ -114,7 +114,7 @@ impl fmt::Display for ProfileV2NameParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"invalid --profile-v2 value `{}`; pass a plain name such as `work`",
"invalid --profile value `{}`; pass a plain name such as `work`",
self.value
)
}

View File

@@ -31,11 +31,11 @@ pub struct SharedCliOptions {
pub oss_provider: Option<String>,
/// Configuration profile from config.toml to specify default options.
#[arg(long = "profile", short = 'p')]
#[arg(skip)]
pub config_profile: Option<String>,
/// 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>,
/// Select the sandbox policy to use when executing model-generated shell