OpenClaw skill and helper CLI for generating or editing images through the ChatGPT/Codex backend with local OAuth credentials.
By default this follows Codex's current hosted image flow: POST /responses with the native image_generation tool. The standalone typed image endpoints are available for probing with --backend images, but Codex source currently gates that path behind the under-development image-generation extension. The helper also preserves ChatGPT Cloudflare cookies for allowed ChatGPT hosts, matching Codex's restricted request client behavior. It does not start codex app-server, does not require a Codex binary, and does not require OPENAI_API_KEY.
- Node.js 22+
- Existing Codex or OpenClaw
openai-codexOAuth credentials on the machine
Supported auth stores:
- OpenClaw auth profiles:
~/.openclaw/agents/main/agent/auth-profiles.json - OpenClaw agent auth:
~/.openclaw/agents/main/agent/auth.json - OpenClaw legacy OAuth:
~/.openclaw/credentials/oauth.json - Codex CLI/Desktop:
~/.codex/auth.json
Check auth without generating:
node scripts/codex-imagen.mjs --smokeGenerate one image:
node scripts/codex-imagen.mjs 'generate image follow this prompt, no refine: "a cinematic fantasy city at sunrise"'Ask for multiple outputs in the prompt. There is no --count flag.
node scripts/codex-imagen.mjs --timeout 900 'generate 3 images follow this prompt, no refine: "three distinct ancient ARPG MMO screenshots"'Normal generation prints one saved PNG path per line. Diagnostics and progress are written to stderr unless --quiet is used.
node scripts/codex-imagen.mjs "prompt" [options]Prompt options:
--prompt <text>: prompt text.--prompt-file <path>: read UTF-8 prompt text from a file.- Positional text is accepted when
--promptand--prompt-fileare not used.
Reference image options:
-i, --image <path>: attach local image files. Repeat or comma-separate.--input-ref <path|url>: attach local paths,http(s)URLs, ordata:image/...URLs. Repeat or comma-separate.--image-url <url>: attach anhttp(s)ordata:image/...URL.--image-detail <auto|low|high|original>: set the Responsesinput_image.detailvalue. Ignored by--backend images. Default:high.
Output options:
-o, --output <path>: exact PNG path for one image, directory for many, or a path template that is numbered for multiple images.--out-dir <path>: output directory when--outputis not provided.--json: print a machine-readable summary instead of only image paths.
Runtime options:
--backend <responses|images>: Codex image backend. Default:responses, matching current Codex hostedimage_generation.imagescalls the under-development standalone typed endpoint.--model <name>: model slug. Defaults:gpt-5.4forresponses,gpt-image-2forimages.--retries <count>: retry transient empty failures this many times. Default:4, matching Codex's request retry default of 5 total attempts. Retries apply to network failures, HTTP 5xx, backendserver_error/ overloaded / unavailable responses, dropped/incomplete streams before any image is saved, and typed JSON responses without image data.--no-retry: disable transient generation retries.--timeout <seconds>: abort after this many seconds per generation attempt. Default:900, or300when an OpenClaw runtime is detected; must be greater than0. This is the recommended flag for OpenClaw and other agent usage.--timeout-seconds <seconds>: alias for--timeout.--timeout-ms <ms>: advanced compatibility flag for millisecond timeouts and sub-second tests. Use only one timeout flag per command. After timeout, a hard watchdog forces exit code124if the HTTP abort does not settle.--no-stream: request a non-streaming Responses response. Theimagesbackend is always non-streaming JSON.--quiet: suppress progress diagnostics on stderr.--verboseor--debug: print request progress, raw Responses event names, and reference image details to stderr.--cwd <path>: resolve relative input/output paths from this working directory.--base-url <url>: Codex backend base URL. Default:https://chatgpt.com/backend-api/codex.--refresh-url <url>: OAuth refresh endpoint. Default:https://auth.openai.com/oauth/token.
Auth options:
--auth <path>: explicit auth JSON path.--auth-profile <id>: OpenClaw profile id, for exampleopenai-codex:hxtxmu@gmail.com.--smoke: print redacted auth metadata and exit without generation.--force-refresh: refresh OAuth before generating.--refresh-only: refresh OAuth and exit. Does not require a prompt.--no-refresh: disable proactive refresh and the 401 refresh retry.
Use explicit reference-image flags. Positional arguments are reserved for prompt text.
node scripts/codex-imagen.mjs --input-ref ref1.png --input-ref ref2.jpg --prompt 'generate 3 images of him livestreaming in this world'
node scripts/codex-imagen.mjs -i ref1.png -i ref2.jpg --prompt 'change the main character into a woman'
node scripts/codex-imagen.mjs --image-url 'https://example.com/ref.png' --prompt 'use this image as the environment reference'Local references are converted to base64 data:image/... input images before sending. Supported local formats are PNG, JPEG, GIF, and WebP. The CLI warns when a base64 reference is large; use smaller JPEG references when high-fidelity pixel detail is not needed.
When no output option is set, the first available directory is used:
CODEX_IMAGEN_OUT_DIROPENCLAW_OUTPUT_DIROPENCLAW_AGENT_DIR/artifacts/codex-imagenOPENCLAW_STATE_DIR/artifacts/codex-imagen./codex-imagen-output
Automatic filenames use:
codex-imagen-<timestamp>-<optional-index>-<image-call-id>.png
--output behavior:
--output image.pngwith one image writes exactlyimage.png.--output image.pngwith multiple images writesimage-1.png,image-2.png, and so on.--output out/or--output outtreats the value as a directory and uses automatic filenames.--out-dir outalways writes automatic filenames underout.
In the default streaming Responses mode, each image is written as soon as it arrives. If a run times out after partial results, already saved images remain on disk and are still printed. If the hosted Responses stream terminates or closes before response.completed, the command follows Codex semantics: already completed images remain saved, but the command exits with a stream error.
Lookup order:
--authCODEX_IMAGEN_AUTH_JSON,OPENCLAW_CODEX_AUTH_JSON,CODEX_AUTH_JSONOPENCLAW_AGENT_DIR/auth-profiles.jsonorPI_CODING_AGENT_DIR/auth-profiles.jsonOPENCLAW_AGENT_DIR/auth.jsonorPI_CODING_AGENT_DIR/auth.json~/.openclaw/agents/main/agent/auth-profiles.json~/.openclaw/agents/main/agent/auth.json~/.openclaw/credentials/oauth.jsonCODEX_HOME/auth.json~/.codex/auth.json
Profile selection for OpenClaw auth-profiles.json:
--auth-profileCODEX_IMAGEN_AUTH_PROFILEorOPENCLAW_AUTH_PROFILE- OpenClaw config
auth.order.openai-codex, then configuredauth.profilesforopenai-codex - sibling
auth-state.jsonlastGood.openai-codex - best available
openai-codexOAuth profile, preferringopenai-codex:default, later expiry, email, and account id
Codex CLI is optional. If OpenClaw created the openai-codex OAuth profile through openclaw onboard --auth-choice openai-codex or openclaw models auth login --provider openai-codex, this helper can use that profile directly without installing Codex CLI. The helper reads and refreshes existing credentials; it does not run the first browser login itself.
The CLI refreshes expired or near-expiry OAuth tokens with the OpenAI OAuth refresh endpoint and writes updates back to the same auth file. The default refresh skew is 5 minutes, matching OpenClaw's OAuth usability margin.
When the auth file is OpenClaw's auth-profiles.json, refresh uses the same cross-agent lock path OpenClaw uses for openai-codex OAuth profiles, then locks the auth store before rereading and writing credentials. It also inherits a fresh matching profile from the main OpenClaw agent store when the current agent/workspace auth store is stale. That prevents concurrent agents from racing on one single-use refresh token and causing refresh_token_reused.
When auth is auto-discovered and the first auth file is irrecoverably stale, the CLI tries the next compatible auth source, such as CODEX_HOME/auth.json or ~/.codex/auth.json. Explicit --auth paths are not bypassed.
node scripts/codex-imagen.mjs --refresh-only --json
node scripts/codex-imagen.mjs --force-refresh --smoke --json
node scripts/codex-imagen.mjs --no-refresh --prompt 'generate one image'Use --no-refresh only when the caller already owns token refresh. For normal standalone/OpenClaw skill usage, leave refresh enabled.
Use --json for the full machine-readable summary:
node scripts/codex-imagen.mjs --json 'generate a small blue lotus icon'Generation JSON includes:
request_id,session_id,endpoint,modelimage_countandimageCountimages[].pathandimages[].decodedPathimages[].bytes,sha256,call_id,status,partial,revised_promptseen_event_typesoperation, for exampleresponses image_generation,image generation, orimage editresponse_metadatafor typed Images responsestimed_outretry_attemptsandretryAttemptswhen a later retry succeedsauth_refreshwhen refresh happened or was skipped during the run
--smoke --json prints redacted auth metadata. --refresh-only --json prints refresh metadata.
Use the skill directory as an OpenClaw skill:
codex-imagen/
SKILL.md
scripts/codex-imagen.mjs
OpenClaw callers should usually rely on the active agent auth store and output directory:
node {baseDir}/scripts/codex-imagen.mjs --json --timeout 300 --prompt 'generate an image'--timeout 300 means 5 minutes and matches OpenClaw's surrounding exec tool timeout unit. --timeout-ms 300000 is still accepted for older callers and advanced millisecond use.
For prompts that ask for 3 images, prefer --timeout 600, or ask for 2 images when the conversation should return quickly. If a multi-image request times out after saving 1 or 2 images, the helper returns those saved paths with timed_out: true.
By default the helper also retries transient empty failures with --retries 4, so a caller that sets a strict outer OpenClaw exec.timeout should budget for retry time or pass --no-retry. The helper never retries after streaming has saved an image. Timeouts after saved images return the saved paths; broken hosted Responses streams after saved images leave the files on disk but exit with a stream error, matching Codex turn semantics.
Use --cwd <path> when another agent launches this script from an unpredictable working directory.
The helper is plain Node.js 22+ and uses os.homedir(), path, and environment overrides instead of platform-specific shell behavior. It should work on macOS, Linux, and Windows.
In Windows cmd.exe, single quotes are not shell quotes, so use double quotes or --prompt-file:
node scripts\codex-imagen.mjs --prompt-file prompt.txt --out-dir outPowerShell accepts normal quoted strings, but for long prompts --prompt-file is still safer.
0: success1: generation failed, no image returned, or HTTP error2: invalid CLI usage124: timed out before any image was saved, or the hard watchdog forced exit after abort did not settle
Run local static checks:
npm run checkThe CI workflow checks syntax and CLI help/version output. It does not call live image generation because that requires local OAuth credentials.
MIT