Skip to content

Add /codex:image for native image generation through Codex#271

Open
MoizIbnYousaf wants to merge 2 commits intoopenai:mainfrom
MoizIbnYousaf:feat/image
Open

Add /codex:image for native image generation through Codex#271
MoizIbnYousaf wants to merge 2 commits intoopenai:mainfrom
MoizIbnYousaf:feat/image

Conversation

@MoizIbnYousaf
Copy link
Copy Markdown

Summary

Adds /codex:image, a slash command that lets Claude Code users generate images by handing a craft-grade prompt to Codex's stable image_generation tool through the existing shared task runtime.

Mirrors the rescue trio architecturally — slash command + thin forwarder subagent + internal skill — so it composes with /codex:status, /codex:result, /codex:cancel, --background, and --wait for free.

What's added

  • plugins/codex/commands/image.md — slash command. Parses --background|--wait, --model, --out <path>, and free-form image intent. Pins inline Agent transport (subagent_type: "codex:codex-image") per the Skill(codex:rescue) infinite-recurses when invoked programmatically from main agent #234 fix to prevent skill recursion. Defaults to foreground. Always passes --write so Codex can save the PNG and optionally copy it to --out.
  • plugins/codex/agents/codex-image.md — thin forwarder subagent. Drafts the image prompt via the new image skill, wraps it in a single <task> block that tells Codex to use its native image_generation tool, and forwards exactly one task --write call to codex-companion.mjs. Returns Codex stdout verbatim. No file inspection, polling, summarizing, or follow-up work.
  • plugins/codex/skills/image/SKILL.md — internal contract (user-invocable: false). Encodes the six community-tested rules for prompting frontier image models: lead with style and intended use, quote every literal string, treat the prompt as context, explicit pixel dimensions not bare ratios, mandatory constraints block, generate fresh (no image-to-image). Includes a default dimensions table for common intents (social card, magazine cover, app icon, etc.).
  • tests/commands.test.mjs — adds a lint test for commands/image.md, agents/codex-image.md, and skills/image/SKILL.md. Also updates the "continue is not exposed" filename guard to include image.md.

Why this is a thin forwarder

The subagent does not write or run any image-generation code itself. Codex's built-in image_generation feature (stable, enabled by default) handles the API call, file save, and path reporting. The subagent's only job is to draft a craft-grade prompt and hand it to Codex through the same task runtime that powers /codex:rescue.

Test plan

  • npm test — all 87 tests pass, including the new image command forwards to codex-image subagent and pins inline Agent transport lint test.
  • Manual: /codex:image landscape social card promoting a fictional coffee bar called "Noon & Co." → Codex returns the absolute path of the generated PNG.
  • Manual: /codex:image --background magazine cover styled as a "field manual" for image prompting → returns a job id; /codex:status and /codex:result work normally.
  • Manual: /codex:image --out ~/Desktop/test.png small square logo for "Acme" → saved to the explicit path.

Out of scope

  • Reference-image editing (-i, --image on Codex). Image-to-image is unreliable on current frontier image models, and the image skill rule Feature: infra-aware adversarial review prompts + auto-scaling by diff size #6 explicitly tells Codex to generate fresh.
  • A dedicated image subcommand in codex-companion.mjs. The generic task route is sufficient because Codex's native tool already handles the API and file save — no Node script generation, no openai package install, no key handling.

🤖 Generated with Claude Code

Adds a slash command, forwarder subagent, and internal craft skill that
let users generate images by handing a prompt to Codex's stable
`image_generation` tool through the shared task runtime.

Mirrors the rescue trio (command + codex-rescue + codex-cli-runtime):

- `commands/image.md` parses `--background|--wait`, `--model`, `--out`,
  pins inline Agent transport (`subagent_type: "codex:codex-image"`) per
  the openai#234 fix, defaults to foreground, always passes `--write` so
  Codex can save the PNG and copy to `--out`.
- `agents/codex-image.md` is a thin forwarder. Drafts the image prompt
  via the new `image` skill, wraps it in a single `<task>` block that
  tells Codex to use its native image tool, and forwards exactly one
  `task` call. Returns Codex stdout verbatim.
- `skills/image/SKILL.md` encodes the six community-tested rules for
  prompting frontier image models (lead with style, quote literal text,
  pixel dimensions not ratios, mandatory constraints block, generate
  fresh) plus a default dimensions table.

The subagent does not write or run any image-generation code itself.
Codex's built-in `image_generation` feature handles the API call, file
save, and path reporting — the subagent's job is purely to hand Codex
a craft-grade prompt.

Adds a lint test in `tests/commands.test.mjs` and updates the
"continue is not exposed" filename guard to include `image.md`.
@MoizIbnYousaf MoizIbnYousaf requested a review from a team April 25, 2026 23:20
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2557c742a9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

- If neither flag is present, default to foreground. Most single-image generations finish in well under a minute.
- `--background` and `--wait` are execution flags for Claude Code. Do not forward them to `task`, and do not treat them as part of the natural-language image intent.
- `--model` is a runtime-selection flag for the Codex side (the model that drives the image generation tool). Preserve it for the forwarded `task` call, but do not treat it as part of the image intent.
- `--out` is an optional absolute path for the saved PNG. If omitted, Codex uses its native generated_images directory and prints the absolute path. Preserve `--out` for the subagent.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict --out to workspace-writable paths

The command advertises --out as any absolute path (even the PR example ~/Desktop/...), but task runs are hard-coded to sandbox: "workspace-write" in codex-companion.mjs (line 488), so writing outside the workspace can fail at runtime. This means users following the new --out contract may get failed image runs for perfectly valid absolute destinations; either constrain/validate --out to workspace paths in the command contract or change runtime sandboxing for this flow.

Useful? React with 👍 / 👎.

Response style:

- Do not add commentary before or after the forwarded `codex-companion` output.
- If the Bash call fails or Codex cannot be invoked, return nothing.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Surface Codex invocation failures to the caller

This subagent is told to "return nothing" when the Bash call fails or Codex cannot be invoked, but the paired command expects to detect helper auth/install failures and instruct users to run /codex:setup. In missing-Codex or unauthenticated environments, swallowing failures here can produce an empty user-visible response instead of actionable setup guidance.

Useful? React with 👍 / 👎.

Codex's native image_generation tool always writes to
~/.codex/generated_images/<thread-id>/ig_*.png, regardless of any
output-path instruction in the prompt. Codex's text response can claim
a different path, but that is not authoritative — the file is in the
native location.

Without post-processing, /codex:image users see Codex's (sometimes
hallucinated) text path and have no reliable way to find the actual
PNG. This commit fixes that.

Changes:

- Add `latest-images --since <epoch-ms> [--copy-to <abs-path>] [--json]`
  subcommand to codex-companion.mjs. Walks ~/.codex/generated_images/
  for PNGs with mtime >= since, optionally copies them to a target
  path (file or directory), prints absolute paths bracketed by a clear
  ==Generated PNG(s)== marker.

- Update codex-image agent contract to chain `task` + `latest-images`
  in a single Bash invocation: capture SINCE_MS before the Codex run,
  invoke task --write, then invoke latest-images --since "$SINCE_MS"
  (with --copy-to <path> if the user supplied --out <path>). The user
  always sees the real saved path appended to Codex's stdout, even
  when Codex's text response is wrong or empty.

- Drop the now-unreachable `print absolute path on the last line` and
  `copy to user path` requirements from the agent's wrapping <task>
  block. Codex's image tool does neither — and asking for them just
  encourages hallucinated paths in the text response.

- Test coverage: new runtime test exercises latest-images against a
  fixture HOME with synthesized PNGs, covering the no-copy, --json,
  --copy-to file, and empty-window paths. Updated commands lint test
  to assert the chained-call pattern in the agent.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d4a50dc09

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +106 to +110
const root = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".codex", "generated_images");
const matches = [];
if (fs.existsSync(root)) {
const stack = [root];
while (stack.length > 0) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Scope latest-images matches to the active thread

latest-images currently walks the entire ~/.codex/generated_images tree and then filters by mtime window, so any other image run that writes during the same window is treated as part of this request. In practice, concurrent/background generations can cause unrelated PNGs to be returned and copied, and can even flip --copy-to <file>.png into the multi-file branch (producing suffixed filenames) despite the caller requesting a single destination file. Filtering by the task’s thread id (or another run-specific identifier) would avoid cross-run contamination.

Useful? React with 👍 / 👎.

Comment on lines +141 to +143
const looksLikeFile = /\.png$/i.test(copyTo);
if (looksLikeFile && matches.length === 1) {
fs.mkdirSync(path.dirname(copyTo), { recursive: true });
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Expand and validate --copy-to before copying images

--copy-to is consumed as a raw path without ~ expansion or absolute-path validation, so inputs like --out ~/Desktop/test.png (shown in the commit examples) are interpreted as a literal relative path and written under <cwd>/~/Desktop/... rather than the user’s home directory. Because the subagent guidance quotes the path, shell tilde expansion will not rescue this. Normalize home-path syntax and reject non-absolute targets to match the command contract and user expectations.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant