Skip to content

Commit 549846b

Browse files
authored
Add codex login --api-key (#1759)
Allow setting the API key via `codex login --api-key`
1 parent 96654a5 commit 549846b

File tree

10 files changed

+218
-46
lines changed

10 files changed

+218
-46
lines changed

codex-rs/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/chatgpt/src/chatgpt_token.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub fn set_chatgpt_token_data(value: TokenData) {
1818

1919
/// Initialize the ChatGPT token from auth.json file
2020
pub async fn init_chatgpt_token_from_auth(codex_home: &Path) -> std::io::Result<()> {
21-
let auth = codex_login::load_auth(codex_home)?;
21+
let auth = codex_login::load_auth(codex_home, true)?;
2222
if let Some(auth) = auth {
2323
let token_data = auth.get_token_data().await?;
2424
set_chatgpt_token_data(token_data);

codex-rs/cli/src/login.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
use std::env;
2+
13
use codex_common::CliConfigOverrides;
24
use codex_core::config::Config;
35
use codex_core::config::ConfigOverrides;
46
use codex_login::AuthMode;
7+
use codex_login::OPENAI_API_KEY_ENV_VAR;
58
use codex_login::load_auth;
9+
use codex_login::login_with_api_key;
610
use codex_login::login_with_chatgpt;
711

812
pub async fn run_login_with_chatgpt(cli_config_overrides: CliConfigOverrides) -> ! {
@@ -21,14 +25,40 @@ pub async fn run_login_with_chatgpt(cli_config_overrides: CliConfigOverrides) ->
2125
}
2226
}
2327

28+
pub async fn run_login_with_api_key(
29+
cli_config_overrides: CliConfigOverrides,
30+
api_key: String,
31+
) -> ! {
32+
let config = load_config_or_exit(cli_config_overrides);
33+
34+
match login_with_api_key(&config.codex_home, &api_key) {
35+
Ok(_) => {
36+
eprintln!("Successfully logged in");
37+
std::process::exit(0);
38+
}
39+
Err(e) => {
40+
eprintln!("Error logging in: {e}");
41+
std::process::exit(1);
42+
}
43+
}
44+
}
45+
2446
pub async fn run_login_status(cli_config_overrides: CliConfigOverrides) -> ! {
2547
let config = load_config_or_exit(cli_config_overrides);
2648

27-
match load_auth(&config.codex_home) {
49+
match load_auth(&config.codex_home, true) {
2850
Ok(Some(auth)) => match auth.mode {
2951
AuthMode::ApiKey => {
3052
if let Some(api_key) = auth.api_key.as_deref() {
3153
eprintln!("Logged in using an API key - {}", safe_format_key(api_key));
54+
55+
if let Ok(env_api_key) = env::var(OPENAI_API_KEY_ENV_VAR) {
56+
if env_api_key == api_key {
57+
eprintln!(
58+
" API loaded from OPENAI_API_KEY environment variable or .env file"
59+
);
60+
}
61+
}
3262
} else {
3363
eprintln!("Logged in using an API key");
3464
}

codex-rs/cli/src/main.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use codex_chatgpt::apply_command::run_apply_command;
88
use codex_cli::LandlockCommand;
99
use codex_cli::SeatbeltCommand;
1010
use codex_cli::login::run_login_status;
11+
use codex_cli::login::run_login_with_api_key;
1112
use codex_cli::login::run_login_with_chatgpt;
1213
use codex_cli::proto;
1314
use codex_common::CliConfigOverrides;
@@ -92,6 +93,9 @@ struct LoginCommand {
9293
#[clap(skip)]
9394
config_overrides: CliConfigOverrides,
9495

96+
#[arg(long = "api-key", value_name = "API_KEY")]
97+
api_key: Option<String>,
98+
9599
#[command(subcommand)]
96100
action: Option<LoginSubcommand>,
97101
}
@@ -133,7 +137,11 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
133137
run_login_status(login_cli.config_overrides).await;
134138
}
135139
None => {
136-
run_login_with_chatgpt(login_cli.config_overrides).await;
140+
if let Some(api_key) = login_cli.api_key {
141+
run_login_with_api_key(login_cli.config_overrides, api_key).await;
142+
} else {
143+
run_login_with_chatgpt(login_cli.config_overrides).await;
144+
}
137145
}
138146
}
139147
}

codex-rs/cli/src/proto.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub async fn run_main(opts: ProtoCli) -> anyhow::Result<()> {
3636
.map_err(anyhow::Error::msg)?;
3737

3838
let config = Config::load_with_cli_overrides(overrides_vec, ConfigOverrides::default())?;
39-
let auth = load_auth(&config.codex_home)?;
39+
let auth = load_auth(&config.codex_home, true)?;
4040
let ctrl_c = notify_on_sigint();
4141
let CodexSpawnOk { codex, .. } = Codex::spawn(config, auth, ctrl_c.clone()).await?;
4242
let codex = Arc::new(codex);

codex-rs/core/src/codex_wrapper.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub struct CodexConversation {
2626
/// that callers can surface the information to the UI.
2727
pub async fn init_codex(config: Config) -> anyhow::Result<CodexConversation> {
2828
let ctrl_c = notify_on_sigint();
29-
let auth = load_auth(&config.codex_home)?;
29+
let auth = load_auth(&config.codex_home, true)?;
3030
let CodexSpawnOk {
3131
codex,
3232
init_id,

codex-rs/core/tests/client.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,14 +327,14 @@ fn auth_from_token(id_token: String) -> CodexAuth {
327327
AuthMode::ChatGPT,
328328
PathBuf::new(),
329329
Some(AuthDotJson {
330-
tokens: TokenData {
330+
openai_api_key: None,
331+
tokens: Some(TokenData {
331332
id_token,
332333
access_token: "Access Token".to_string(),
333334
refresh_token: "test".to_string(),
334335
account_id: None,
335-
},
336-
last_refresh: Utc::now(),
337-
openai_api_key: None,
336+
}),
337+
last_refresh: Some(Utc::now()),
338338
}),
339339
)
340340
}

codex-rs/login/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ tokio = { version = "1", features = [
1818
"rt-multi-thread",
1919
"signal",
2020
] }
21+
22+
[dev-dependencies]
23+
tempfile = "3"

0 commit comments

Comments
 (0)