feat(extensions): add OpenAI Codex CLI auth provider

Adds a new authentication provider that reads OAuth tokens from the
OpenAI Codex CLI (~/.codex/auth.json) to authenticate with OpenAI's API.

This allows ChatGPT Plus/Pro subscribers to use OpenAI models in OpenClaw
without needing a separate API key - just authenticate with 'codex login'
first, then enable this plugin.

Features:
- Reads existing Codex CLI credentials from ~/.codex/auth.json
- Supports all Codex-available models (gpt-4.1, gpt-4o, o1, o3, etc.)
- Automatic token expiry detection from JWT
- Clear setup instructions and troubleshooting docs

Usage:
  openclaw plugins enable openai-codex-auth
  openclaw models auth login --provider openai-codex --set-default
This commit is contained in:
Ralph
2026-02-16 12:27:53 +01:00
committed by Peter Steinberger
parent f82a3d3e2b
commit 3ac422fe2e
4 changed files with 266 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
# OpenAI Codex CLI Auth (OpenClaw plugin)
Use OpenAI models with your **ChatGPT Plus/Pro subscription** via the Codex CLI OAuth tokens.
This plugin reads authentication from the [OpenAI Codex CLI](https://github.com/openai/codex) and uses those OAuth credentials to access OpenAI models — no separate API key required.
## Enable
Bundled plugins are disabled by default. Enable this one:
```bash
openclaw plugins enable openai-codex-auth
```
Restart the Gateway after enabling.
## Prerequisites
1. **ChatGPT Plus or Pro subscription** — required for Codex CLI access
2. **Codex CLI installed and authenticated**:
```bash
# Install Codex CLI
npm install -g @openai/codex
# Authenticate (opens browser for OAuth)
codex login
```
This creates `~/.codex/auth.json` with your OAuth tokens.
## Authenticate with OpenClaw
After Codex CLI is authenticated:
```bash
openclaw models auth login --provider openai-codex --set-default
```
## Available Models
The following models are available through Codex CLI authentication:
- `openai/gpt-4.1`, `openai/gpt-4.1-mini`, `openai/gpt-4.1-nano`
- `openai/gpt-4o`, `openai/gpt-4o-mini`
- `openai/o1`, `openai/o1-mini`, `openai/o1-pro`
- `openai/o3`, `openai/o3-mini`
- `openai/o4-mini`
Default model: `openai/o3`
## How It Works
1. The plugin reads `~/.codex/auth.json` created by `codex login`
2. OAuth tokens from your ChatGPT subscription are extracted
3. OpenClaw uses these tokens to authenticate with OpenAI's API
4. Tokens auto-refresh when needed (handled by OpenClaw's credential system)
## Why Use This?
- **No separate API key** — use your existing ChatGPT Plus/Pro subscription
- **No usage-based billing** — covered by your subscription
- **Access to latest models** — same models available in ChatGPT
## Troubleshooting
### "No Codex auth found"
Run `codex login` to authenticate the Codex CLI first.
### Tokens expired
Re-run `codex login` to refresh your tokens, then re-authenticate:
```bash
codex login
openclaw models auth login --provider openai-codex --set-default
```
### Model not available
Some models may require specific subscription tiers (e.g., o1-pro requires ChatGPT Pro).

View File

@@ -0,0 +1,160 @@
import {
emptyPluginConfigSchema,
type OpenClawPluginApi,
type ProviderAuthContext,
type ProviderAuthResult,
} from "openclaw/plugin-sdk";
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
const PROVIDER_ID = "openai-codex";
const PROVIDER_LABEL = "OpenAI Codex CLI";
const AUTH_FILE = path.join(os.homedir(), ".codex", "auth.json");
/**
* OpenAI Codex models available via ChatGPT Plus/Pro subscription.
* These are the models exposed through the Codex CLI OAuth tokens.
*/
const CODEX_MODELS = [
"openai/gpt-4.1",
"openai/gpt-4.1-mini",
"openai/gpt-4.1-nano",
"openai/gpt-4o",
"openai/gpt-4o-mini",
"openai/o1",
"openai/o1-mini",
"openai/o1-pro",
"openai/o3",
"openai/o3-mini",
"openai/o4-mini",
] as const;
const DEFAULT_MODEL = "openai/o3";
interface CodexAuthTokens {
access_token: string;
refresh_token?: string;
account_id?: string;
expires_at?: number;
}
interface CodexAuthFile {
tokens?: CodexAuthTokens;
}
/**
* Read the Codex CLI auth.json file from ~/.codex/auth.json
*/
function readCodexAuth(): CodexAuthFile | null {
try {
if (!fs.existsSync(AUTH_FILE)) return null;
const content = fs.readFileSync(AUTH_FILE, "utf-8");
return JSON.parse(content) as CodexAuthFile;
} catch {
return null;
}
}
/**
* Decode JWT expiry timestamp from access token
*/
function decodeJwtExpiry(token: string): number | undefined {
try {
const payload = token.split(".")[1];
if (!payload) return undefined;
const decoded = JSON.parse(Buffer.from(payload, "base64").toString()) as { exp?: number };
return decoded.exp ? decoded.exp * 1000 : undefined;
} catch {
return undefined;
}
}
const openaiCodexPlugin = {
id: "openai-codex-auth",
name: "OpenAI Codex Auth",
description: "Use OpenAI models via Codex CLI authentication (ChatGPT Plus/Pro)",
configSchema: emptyPluginConfigSchema(),
register(api: OpenClawPluginApi) {
api.registerProvider({
id: PROVIDER_ID,
label: PROVIDER_LABEL,
docsPath: "/providers/models",
aliases: ["codex", "chatgpt"],
auth: [
{
id: "codex-cli",
label: "Codex CLI Auth",
hint: "Use existing Codex CLI authentication from ~/.codex/auth.json",
kind: "custom",
run: async (ctx: ProviderAuthContext): Promise<ProviderAuthResult> => {
const spin = ctx.prompter.progress("Reading Codex CLI auth…");
try {
const auth = readCodexAuth();
if (!auth?.tokens?.access_token) {
spin.stop("No Codex auth found");
await ctx.prompter.note(
"Run 'codex login' first to authenticate with OpenAI.\n\n" +
"Install Codex CLI: npm install -g @openai/codex\n" +
"Then run: codex login",
"Setup required",
);
throw new Error("Codex CLI not authenticated. Run: codex login");
}
spin.stop("Codex auth loaded");
const profileId = `openai-codex:${auth.tokens.account_id ?? "default"}`;
const expires = auth.tokens.expires_at
? auth.tokens.expires_at * 1000
: decodeJwtExpiry(auth.tokens.access_token);
const modelsConfig: Record<string, object> = {};
for (const model of CODEX_MODELS) {
modelsConfig[model] = {};
}
return {
profiles: [
{
profileId,
credential: {
type: "oauth",
provider: PROVIDER_ID,
access: auth.tokens.access_token,
refresh: auth.tokens.refresh_token ?? "",
expires: expires ?? Date.now() + 3600000,
},
},
],
configPatch: {
agents: {
defaults: {
models: modelsConfig,
},
},
},
defaultModel: DEFAULT_MODEL,
notes: [
"Using Codex CLI auth from ~/.codex/auth.json",
`Available models: ${CODEX_MODELS.join(", ")}`,
"Tokens auto-refresh when needed.",
],
};
} catch (err) {
spin.stop("Failed to load Codex auth");
throw err;
}
},
},
],
});
},
};
export default openaiCodexPlugin;

View File

@@ -0,0 +1,9 @@
{
"id": "openai-codex-auth",
"providers": ["openai-codex"],
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {}
}
}

View File

@@ -0,0 +1,15 @@
{
"name": "@openclaw/openai-codex-auth",
"version": "2026.2.16",
"private": true,
"description": "OpenAI Codex CLI auth provider plugin - use ChatGPT Plus/Pro subscription for OpenAI models",
"type": "module",
"devDependencies": {
"openclaw": "workspace:*"
},
"openclaw": {
"extensions": [
"./index.ts"
]
}
}