Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions codex-cli/src/cli.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
import {
getApiKey as fetchApiKey,
maybeRedeemCredits,
fetchGithubCopilotApiKey,
} from "./utils/get-api-key";
import { createInputItem } from "./utils/input-utils";
import { initLogger } from "./utils/logger/log";
Expand Down Expand Up @@ -328,7 +329,11 @@ try {
}

if (cli.flags.login) {
apiKey = await fetchApiKey(client.issuer, client.client_id);
if (provider.toLowerCase() === "githubcopilot") {
apiKey = await fetchGithubCopilotApiKey();
} else {
apiKey = await fetchApiKey(client.issuer, client.client_id);
}
Comment on lines +332 to +336
Copy link

Copilot AI Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for fetching the API key for the GitHub Copilot provider is repeated in separate conditional blocks (lines 332-336 and 349-352). Consider refactoring this into a single helper function that handles provider-specific API key retrieval to improve maintainability.

Suggested change
if (provider.toLowerCase() === "githubcopilot") {
apiKey = await fetchGithubCopilotApiKey();
} else {
apiKey = await fetchApiKey(client.issuer, client.client_id);
}
apiKey = await getApiKeyForProvider(provider, client.issuer, client.client_id);

Copilot uses AI. Check for mistakes.
try {
const home = os.homedir();
const authDir = path.join(home, ".codex");
Expand All @@ -341,7 +346,11 @@ if (cli.flags.login) {
/* ignore */
}
} else if (!apiKey) {
apiKey = await fetchApiKey(client.issuer, client.client_id);
if (provider.toLowerCase() === "githubcopilot") {
apiKey = await fetchGithubCopilotApiKey();
} else {
apiKey = await fetchApiKey(client.issuer, client.client_id);
}
}
// Ensure the API key is available as an environment variable for legacy code
process.env["OPENAI_API_KEY"] = apiKey;
Expand Down
22 changes: 22 additions & 0 deletions codex-cli/src/utils/get-api-key.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -764,3 +764,25 @@ export async function getApiKey(
}

export { maybeRedeemCredits };

export async function fetchGithubCopilotApiKey(): Promise<string> {
if (process.env["GITHUB_COPILOT_TOKEN"]) {
return process.env["GITHUB_COPILOT_TOKEN"]!;
}

const choice = await promptUserForChoice();
if (choice.type === "apikey") {
process.env["GITHUB_COPILOT_TOKEN"] = choice.key;
return choice.key;
}

// Sign in via GitHub is not yet supported; instruct the user
// eslint-disable-next-line no-console
console.error(
"\n" +
"GitHub OAuth login is not yet implemented for Codex. " +
"Please generate a token manually and set it as GITHUB_COPILOT_TOKEN." +
"\n"
);
process.exit(1);
}
5 changes: 5 additions & 0 deletions codex-cli/src/utils/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,9 @@ export const providers: Record<
baseURL: "https://conductor.arcee.ai/v1",
envKey: "ARCEEAI_API_KEY",
},
githubcopilot: {
name: "GitHubCopilot",
baseURL: "https://copilot-proxy.githubusercontent.com/v1",
envKey: "GITHUB_COPILOT_TOKEN",
},
};