pi-codex-image-gen
Image generation and editing for Pi using your ChatGPT Codex login.
Package details
Install pi-codex-image-gen from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-codex-image-gen- Package
pi-codex-image-gen- Version
0.3.1- Published
- Nov 5, 2026
- Downloads
- 4,329/mo · 1,931/wk
- Author
- mocito
- License
- Apache-2.0
- Types
- extension, skill
- Size
- 290.5 KB
- Dependencies
- 2 dependencies · 4 peers
Pi manifest JSON
{
"skills": [
"./skills"
],
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-codex-image-gen
Create and edit images without leaving Pi.
pi-codex-image-gen turns natural-language requests and reference images into PNG, JPEG, or WebP assets through ChatGPT subscription image generation. Sign in from Pi; no Codex app or separate API key is required.
Features
- Generate images in conversation — describe the asset you need and let Pi create it.
- Edit from references — transform up to five local or recent conversation images.
- Create native cutouts — request transparent backgrounds and preserve alpha during edits, without API billing or chroma keying.
- Save where work happens — return images inline or organize them by project, session, or custom directory.
- Separate image login — keep Pi chat on
openaiOAuth while the extension handles image authentication. - Scripted workflows without image payloads — generate recoverable originals through codemode and load images only for explicit display.
Recovery and parallel requests
codex_list_image_artifacts({offset?, limit?, revision?}) returns metadata from
the same validated current-branch records as /image-artifacts, never bytes
or arbitrary manifests. It does not generate an image or consume image quota.
Pages default to 8 records (maximum 20) and 50,000 bytes. Continue with returned
nextOffset and revision; restart at offset zero if records change.
Each item includes artifact, toolCallId and availability (present,
missing, unavailable). Availability is a filesystem snapshot, not proof of
original contents or permission to read another branch.
// Recover a generation completed before a later script error; do not regenerate.
const r = await tools.codex_list_image_artifacts({});
text(r.artifacts.map(x => ({ path: x.artifact.path, availability: x.availability })));
Artifact results additionally return generationDurationMs, routingProvider,
routingModel, optional responseId, imageGenerationId, and reportedImage.
The latter is an allowlisted, bounded backend report, not measured dimensions,
transparency, or proof of the served model. Inspect pixels separately.
Results keep requestedImage, reportedImage, and measuredImage separate.
measuredImage contains decoded width, height, output format, alphaMin,
alphaMax, and hasTransparency. Measurement is best-effort: it admits at most
16,777,216 header-declared pixels to an isolated decoder worker, with a three-second
inspection deadline. Originals are saved before inspection. If decoding fails,
exceeds a limit, or is cancelled, measuredImage is omitted and imageWarning
reports that pixels are unverified. This is not a full image-security audit.
Visual inspection is still required for edge quality and content.
If Codex returns a different supported format, the original is retained without
conversion, using its actual MIME type and filename extension. imageWarning
reports the mismatch; it never triggers regeneration. Bounded requestId and
imagegenRequestId values are returned when available.
Direct and artifact generation share account-local admission: two active operations, eight queued operations, and at most 32 account scopes per process module. The five-minute total deadline includes admission wait; network work also keeps its existing deadline. Queueing is not authorization to generate extra assets. Approved arguments are snapshotted before waits. Storage is reserved after admission and before generation, not for every queued call. Cancellation/reload releases queued work; completed originals are retained. Cancellation after dispatch can still consume quota. There is no prompt-based deduplication or new automatic retry policy.
Backend counters remain informational in details.usage, not Pi ledger
entries, verified charges or subscription-quota measurements. Unknown costs are
unknown, not zero. Goal token budgets do not enforce image quota. Image ledger
mapping is explicitly deferred until a reliable provider contract is approved.
Install
pi install npm:pi-codex-image-gen
During local development from this monorepo:
pi install /path/to/pi-mono/packages/pi-codex-image-gen
For a one-off test run without installing:
pi -e /path/to/pi-mono/packages/pi-codex-image-gen
To uninstall:
pi remove npm:pi-codex-image-gen
Quick usage
In a Pi session:
> Generate a pixel-art sword icon, 32×32, with a blue blade and gold hilt
The agent will invoke codex_generate_image with your prompt, optionally include up to five local or recent conversation images for editing, stream the response from the Codex backend, and save the resulting image to disk. The model parameter controls the Codex routing model, not the image model. The backend selects the image model; backendImageModel is "unknown" unless the response explicitly reports an image model.
The tool reports generation stages and the backend's returned size, quality, background, and format in details.reportedImage. These are server-reported values, not guarantees inferred from the prompt. details.measuredImage, when available, describes independently decoded pixels. details.byteCount records decoded bytes; details.generationDurationMs records elapsed generation/save/inspection time.
Native transparency
Both tools accept background: "transparent", "opaque", or "auto".
Omitting the parameter preserves the existing Responses request behavior.
const result = await tools.codex_generate_image_artifact({
prompt: "Isolate this product; preserve its shape, fine edges, and label text.",
referencedImagePaths: ["product.png"],
background: "transparent",
outputFormat: "png",
save: "project"
});
text(result);
Transparent output requires PNG or WebP; JPEG combinations reject before authentication or generation. Preserve existing transparency during edits unless an opaque background is requested. Use native alpha first, not a chroma-key source or a separately billed API fallback. Check measured alpha and inspect the image: a valid alpha channel alone does not guarantee a good cutout.
Optional dedicated Images transport
Responses remains the default and supports PNG, JPEG, and WebP. Select
transport: "images" per call or in trusted configuration to use the Codex
subscription's dedicated /images/generations and /images/edits routes.
References select the edit route automatically. This is not the public
Images API and does not use API keys.
The opt-in transport is PNG-only. It follows Codex's client contract:
gpt-image-2, quality: "auto", and size: "auto". The identifier is not proof
of which model weights are served. Explicit routing model arguments and
JPEG/WebP output reject before generation; configured routing models apply
only to Responses. Per-call transport overrides configuration.
When background is omitted, new Images generation uses opaque, while
reference edits use auto rather than forcing opacity. Explicitly request
transparent when an edit must preserve alpha; automatic background selection
is not a guarantee.
There is no automatic transport fallback after any failure. This avoids duplicate quota consumption and silent changes in output behavior. GIF, SVG, complexity, masks, markup, exact size/quality controls, and Flare/Sunburst selection are not exposed. In November 2026 tests, GIF requests were rejected by both Pi and an official GIF-enabled Codex alpha. Client support alone does not establish server access.
Subscription reliability and limits
- Requests identify this package with a Pi User-Agent. The image login uses the Codex-compatible public OAuth client; it does not launch the Codex app, read its credentials, import browser cookies, or fall back to paid API calls.
- One five-minute network deadline covers the connection, retries, and stream. Escape cancels network work; the remote generation may still finish.
- Prompts: 32,000 characters. References: five regular PNG/JPEG/WebP files or conversation images, at most 20 MiB each and 50 MiB combined.
- Responses: 100 MiB total, with at most one 32 MiB decoded output image. Base64 and format signatures are checked; bounded worker inspection additionally measures supported images when possible. Backend text and revised prompts are limited to 4,000 characters; HTTP error bodies are read only up to 16 KiB and are not displayed.
- Transient HTTP failures have bounded retries. Quota exhaustion, moderation errors, failed/incomplete streams, connection errors, and deadlines are not automatically retried. Avoid immediately repeating an ambiguous failure: the first generation may have consumed quota.
- Local save settings are checked before generation. Existing files are never overwritten; a persistent save failure still returns the direct inline image or scripted original artifact and a bounded warning.
- Cloudflare challenges are reported as connection failures, not as proof that your subscription or image model is unsupported.
Direct and codemode tools
Use Pi 1.4.0 and Node.js >=22.19.0.
| Tool | Reachability | Delivery |
|---|---|---|
codex_generate_image |
Model-only; available directly with codemode off, on, or only. Nested calls are blocked. |
Summary and inline image, plus an optional persistent save. |
codex_generate_image_artifact |
Codemode and other nested callers. Not declared directly by default, but explicit activation is supported. | Structured metadata and an original file path; no image payload. |
Pi's codemode exposure is not a strict codemode-only restriction. Other tools
can call the artifact tool through ctx.executeTool(). If explicitly activated
directly, it still returns paths and metadata rather than an image attachment.
Both tools use the same generation/editing parameters, image login, backend,
validation, and quota safeguards.
Both definitions share the codex_images namespace and advisory hints:
mutating, non-destructive (no overwrites), non-idempotent, and open-world.
Generation can consume quota and write files; these hints never grant approval.
Await describeNamespace("codex_images") or
searchTools("image artifact", { namespace: "codex_images" }) for the callable
artifact tool, including with zero inline budget. The inline tool stays
model-only and receives no new output schema. The artifact schema, delivery,
recovery, explicit-request policy, and no-automatic-retry rules are unchanged.
const result = await tools.codex_generate_image_artifact({
prompt: "A red fox in watercolor",
save: "none"
});
text(result); // summary, artifact: {path, mimeType, byteCount}, savedPath?, saveWarning?
For explicit display:
const preview = await tools.read({ path: result.artifact.path });
if (preview?.type === "image") image(preview);
else text(preview); // Pi can omit images it cannot decode or bound.
text(result.summary);
read can resize or omit an image that cannot be decoded within Pi's display
limits. Check that its result is an image block before calling image() when
handling untrusted outputs. The original file is unchanged. Do not print image
bytes using text(), console, or return, or store them in codemode's store.
Large originals (up to 32 MiB) are transported as paths, not base64 through
codemode's 16,777,216-character output budget. Pi's image() also saves a
temporary display copy.
For chained edits, use referencedImagePaths: [result.artifact.path].
numLastImagesToInclude also reads artifact records from the current session
branch, including generations that were never displayed. The normal 20 MiB
per-reference and 50 MiB aggregate limits still apply: a 32 MiB output is
recoverable but cannot be used as an edit input without first reducing its size.
Each edit is a new generation request and can consume quota.
Artifact storage and recovery
The artifact tool reserves a new private pi-codex-image-* directory under the
OS temporary directory before generating. Original files have user-only
permissions (directory 0700, file 0600) and are never overwritten.
save: "none" means no persistent user copy for this tool; it does not
disable temporary original storage. The direct tool's none mode still does
not write the image to disk.
Completed originals are not automatically deleted by this extension, including on script failure/timeout, reload, shutdown, or branch changes. They remain until user or OS temporary-file cleanup; there is no guaranteed retention period across OS cleanup or reboot. Copy needed assets to persistent storage. Only incomplete reservations owned by the current call are cleaned up.
Before generation, a branch-local codex-image-artifact-reservation entry
anchors recovery to the originating branch. On completion, a private, bounded
JSON manifest beside the reserved original records path, MIME type, byte count,
and call ID. Normal same-branch completions also append a
codex-image-artifact session entry, without image bytes or prompts. Late
completions after cancellation do not append records to unrelated branches or
replacement sessions; the original branch's reservation reads the manifest.
Run /image-artifacts to list the last 20 recorded original paths on the
current branch without generation or network work. Records survive reload,
resume, and session forks that preserve the entries; abandoned branches are
not included. Listing reads validated recovery manifests, not image bytes, and
does not verify that an original still exists. A missing
original fails recent-image editing before generation; do not regenerate it
automatically.
If temporary storage is known to be unavailable, the artifact call fails before generation. If writing the original fails after generation, a successful requested persistent save becomes the recovery artifact, with a warning. If neither file can be saved, the call fails explicitly: quota may already have been consumed and there is no recoverable artifact. No generation retry is made. A failure to persist session recovery metadata is reported with the recoverable file path rather than hiding the completed file.
Native Pi image models
codex-images is an authentication-only provider, not an image-model
catalog entry. Pi's models.generateImages() and
ctx.modelRegistry.generateImages() do not expose this package's subscription
backend. Continue using the direct or artifact tool above. OpenRouter image
models use their own credentials/billing and are not a subscription fallback.
A native adapter remains deferred; the historical assessment used Pi 1.1.0. The generic image context provides text/image blocks, not this package's save modes, routing override, output-format control, or branch-aware recent-image selection. Generic calls also do not inherit the image tools' approval hooks or exclusions. Registering an image operation would add another callable surface, not merely another discovery label.
Generic codemode image results are held in memory until explicitly displayed.
An undisplayed image has no automatically saved original or /image-artifacts
record. VM memory or aggregate output limits can reject display after
generation finishes. A successful image() display saves a temporary copy,
but that is not this package's pre-generation reservation and branch-recovery
contract. The artifact tool avoids transporting large originals as base64.
The current tools retain backend numeric counters in details.usage; these
are informational, not Pi ledger entries or verified subscription charges.
Pi aggregates reported native image usage on a codemode result, but a raw
extension generateImages() call does not automatically persist it. Neither
missing usage nor a zero catalog price proves generation is free. A future
adapter needs an explicit accounting and unknown-cost policy as well as safe
delivery, recovery, authentication, and approval contracts.
Images 2.5 and API fallback
The optional skills/imagegen/scripts/image_gen.py API CLI accepts --model gpt-image-2.5-flare or --model gpt-image-2.5-sunburst, including their 2026-09-08 snapshots. Both accept --quality xhigh and --quality max in addition to the existing quality settings. The CLI default remains gpt-image-2. Both 2.5 models support --size auto and custom dimensions such as 1536x864, under the documented size constraints. Resolutions above 2560x1440 are experimental.
The existing CLI's native-transparency path uses OPENAI_API_KEY and separate API billing. It is not required for native transparency through the Pi subscription tools. This change does not expand API fallback capabilities.
Public API model selection does not establish support for the same options on the private Codex backend. The extension does not expose Flare/Sunburst selection or claim that your account has received the Images 2.5 rollout.
In subscription tests on September 11, 2026, the direct endpoint accepted Flare, Sunburst, and an invalid model name without reporting a served model. It also returned different size, quality, and background values than requested. The Responses route generated an image successfully. These account-specific results do not justify a guaranteed subscription model selector. See the investigation and test procedure.
Authentication
| Credential / route | Model selection | Usage and fallback |
|---|---|---|
codex-images OAuth / private Codex Responses or Images |
model selects a Responses routing model, not an image model; Images uses automatic server-selected rendering |
ChatGPT image quota; preferred credential |
Legacy Pi openai-codex OAuth / same backend |
Same routing semantics | Used only when owned image credentials are absent; no switch after an auth/generation failure |
Pi openai ChatGPT plan-sharing login |
Any chat model | Not accepted for image generation; never sent to this backend |
| OpenAI API key | Explicit standalone Python CLI only | Separate API billing; never an automatic fallback from the Pi tool |
Changing the chat default to GPT-6.1 Sol does not change image authentication or certify the image backend's served model. The backend chooses the image model; successful inference on another route is not image capability evidence.
The extension owns an image-capable ChatGPT OAuth flow, registered as Codex Images (codex-images). Pi stores its credentials and handles refresh. Your chat provider can remain openai; image authentication is independent.
> /login codex-images
Complete the browser login with your ChatGPT account. You can also run /login and select Codex Images (ChatGPT subscription). The browser redirects to http://localhost:1455/auth/callback. If the callback cannot reach Pi, paste the full redirect URL into Pi's login prompt, not into chat. Login expires after ten minutes.
Use Pi 1.4.0. Pi stores the codex-images credential in its agent auth store (normally ~/.pi/agent/auth.json). /logout codex-images removes that credential without changing your chat login. No credential files are created by the extension itself.
The package implements the Codex-compatible OAuth protocol itself. It neither imports Pi's openai-codex OAuth helpers nor requires the Codex app or its credential store. It still depends on OpenAI continuing to accept that public OAuth client and private image endpoint; this is not a new OAuth application registered with OpenAI.
Existing Pi openai-codex credentials remain a compatibility fallback when codex-images credentials are absent and the legacy provider is available. With both image logins, codex-images wins. A selected login that fails to refresh or generate does not switch to another account. Configured but unusable image credentials also block fallback, including a stored API-key credential that Pi's OAuth-only provider cannot resolve. Re-run /login codex-images to repair that login instead of silently using a different account.
Both image logins use fixed HTTPS routes under https://chatgpt.com/backend-api/codex/: Responses by default, or the dedicated Images routes when explicitly selected. Pi's new openai plan-sharing OAuth grant is different and does not support image generation. The extension never sends that chat token to the Codex backend. API keys do not enable this tool or API-key billing.
Configuration
Create a JSON config file at one (or both) of these locations:
| Scope | Path |
|---|---|
| Global | ~/.pi/agent/extensions/codex-image-gen.json |
| Project | <project-root>/.pi/extensions/codex-image-gen.json |
Project config overrides global config only when project trust is active. If project trust is declined or otherwise inactive, project config is ignored and global config still applies. Example:
{
"save": "global",
"saveDir": "~/Pictures/generated",
"model": "gpt-6-astra"
}
Config keys
| Key | Type | Default | Description |
|---|---|---|---|
save |
string | "global" |
Default save mode (see below). |
saveDir |
string | — | Directory used when save=custom. |
model |
string | "gpt-6-astra" |
Codex routing model, not the backend image model. |
transport |
string | "responses" |
Subscription route: responses or opt-in PNG-only images. |
Environment variables
| Variable | Description |
|---|---|
PI_CODEX_IMAGE_SAVE_MODE |
Overrides the save config key. |
PI_CODEX_IMAGE_SAVE_DIR |
Overrides the saveDir config key (custom mode). |
PI_OFFLINE=1 |
Disables install/update telemetry. |
PI_TELEMETRY=0 |
Disables install/update telemetry. |
Save modes
| Mode | Behavior |
|---|---|
none |
Direct tool: inline image, no disk save. Artifact tool: private temporary original, no persistent copy. |
project |
Saves to <project>/.pi/generated-images/<session-id>/. |
global |
Saves to ~/.pi/agent/generated-images/<session-id>/. |
custom |
Saves to a user-specified directory (requires saveDir or env). ~ and ~/... expand to the current user's home directory. |
Tool parameters
Both generation entry points accept these parameters.
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt |
string | ✅ | The image generation prompt. |
model |
string | — | Override the Codex model. Defaults to config or gpt-6-astra. |
outputFormat |
string | — | png (default), jpeg, or webp. |
background |
string | — | transparent, opaque, or auto; omission preserves existing Responses behavior. |
transport |
string | — | Override configured subscription transport: responses or PNG-only images. |
save |
string | — | Override save mode for this call. |
saveDir |
string | — | Directory when save=custom. Relative paths resolve under CWD. |
referencedImagePaths |
string[] | — | Up to five local images to edit. Relative paths resolve under CWD. |
numLastImagesToInclude |
integer | — | Include the most recent one to five conversation images for editing. Mutually exclusive with referencedImagePaths. |
How it works
- Resolves package-owned
codex-imagesOAuth via Pi, or falls back to available legacy Piopenai-codexOAuth. - Sends a request through Responses and its routing model (default
gpt-6-astra), or the explicitly selected PNG-only Images transport. - For edits, attaches the selected local or conversation images to the request.
- The backend selects an image model to generate or edit the image.
- Parses bounded SSE or Images JSON and validates base64 and the actual returned file format.
- For the artifact tool, commits the reserved temporary original and records its branch-local recovery metadata.
- Saves a persistent copy according to the active save mode; failures produce a bounded warning without discarding a usable inline image or artifact.
- Attempts bounded, isolated pixel inspection, then returns the direct inline image or structured artifact metadata. Codemode displays an image only through an explicit
readandimage()operation.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| "Missing image OAuth credentials" | No image-capable subscription login; chat OAuth and API keys are not sufficient | Run /login codex-images |
| 401 / 403 response | Image login rejected or token expired | Re-run /login codex-images |
| 429 response | Rate limited | Wait and retry; the extension retries automatically with backoff |
| "Codex did not return an image" | Backend refused the prompt | Rephrase the prompt and try again |
| "save=custom requires saveDir" | Missing config | Set saveDir in config or PI_CODEX_IMAGE_SAVE_DIR env var |
| Unsupported-feature error | Backend feature gate or unsupported parameter | Check the supported subscription controls; do not switch transports or billing automatically |
imageWarning |
Format mismatch, unavailable inspection, or inconsistent properties | Keep the completed original and inspect it locally; do not regenerate automatically |
License
Apache-2.0. See LICENSE.
This package includes imagegen skill helper files derived from OpenAI Codex, including skills/imagegen/scripts/image_gen.py. Those files remain under the Apache License, Version 2.0. See NOTICE and skills/imagegen/LICENSE.txt.