PVC Image Gen Codex
Claude Code cannot make pictures, it can only look at them. The ChatGPT extension for VS Code brings Codex, a command line tool that can. This skill finds Codex on your computer. It turns your words into a brief, the kind of description an image model follows. Then it saves one image per run in the folder you name and checks the file is real before it shows you the picture. Every image spends your ChatGPT plan, not your Claude usage. Windows, Mac and Linux, with every live render so far on Windows.
// what it does
One Brief, One Real Image
Say "make me a picture of a red apple on a white table". The skill finds Codex, writes the brief, runs one render, checks the file that was written, and shows it to you.
Finds Codex on Its Own
Looks in the places your computer already searches, in the folders Mac and Linux installers use, then inside the ChatGPT extension for the version built for your computer. An extension update never breaks it.
Makes One Image per Run
Writes the brief in the order the image model responds to: subject, setting and light, framing, style, what to leave out. One PNG is written to the folder you name, in about two minutes.
Edits Without Losing the Rest
Say what stays and the one thing that changes. The skill sends the edit in the order that keeps the rest of the picture intact. After two edits it starts a fresh image, because every edit softens the whole frame a little.
Checks the File Is Real
A file only counts when it was written during the run. With Pillow, a free Python add-on, it also reports the size, and for a cut-out image it confirms the background is truly see-through and not painted on.
// the file
Read SKILL.md
The full skill file, v0.2.1, as published. The GitHub repo holds the same file plus README, .gitignore, LICENSE, NOTICE, REQUIREMENTS, TRADEMARK, and the scripts folder.
--- name: pvc-img-gen-codex description: Generates and edits real images from a text brief through the OpenAI Codex CLI that comes with the ChatGPT VS Code extension, on the user's ChatGPT account instead of Claude tokens. Use when asked to "generate an image", "make me a picture of X", "create the hero shot", "render the product photo", "make a transparent PNG of the logo", "change only the background of this image", "we need visuals for this page", or any time a page, post, deck, thumbnail or card needs an image that does not exist yet. Also use to edit an existing image while keeping named parts unchanged. Works on Windows, macOS and Linux; not in the web version of Claude Code. Requires the ChatGPT VS Code extension (openai.chatgpt) signed in, or the Codex CLI; Pillow optional. Not for local GPU generation (ComfyUI), not for judging an image already made (pvc-image-check), not for reading video (pvc-claude-vision), not for PVC skill card art (pvc-skill-art). metadata: author: pvc version: "0.2.1" license: Apache-2.0 --- <!-- SPDX-License-Identifier: Apache-2.0 --> # pvc-img-gen-codex Claude cannot paint. Codex can. The OpenAI ChatGPT VS Code extension bundles an authenticated Codex CLI that generates and edits images through the user's ChatGPT account, and this skill drives it: one call, one PNG, verified on disk before anyone trusts it. Runs cost ChatGPT quota, not Claude tokens. Runs on Windows, macOS and Linux. Proven on six concurrent portrait renders, background swaps that kept six faces intact, and brand boards that printed hex codes correctly. ## When to Use - A page, post, deck, thumbnail, card or share image needs a picture that does not exist yet - The user asks for a picture, image, shot, render, visual, illustration, cutout or mockup in plain words, even without naming Codex - An existing image is right except for one thing (background, one object, a color) and the fix should keep everything else exactly as it is - A cutout with a real transparent background is needed for compositing onto a page ## Where It Runs | Place | Works? | |-------|--------| | Claude Code in a terminal, VS Code, Cursor, Windsurf or a JetBrains IDE | Yes, when Codex is signed in on that machine | | The Claude desktop app, in a local session | Yes, same condition; the finder also checks the Homebrew and npm folders a desktop app may not have on its PATH | | Windows, macOS, Linux, WSL and Remote SSH (the `.vscode-server` extension folder) | Yes | | Claude Code on the web (claude.ai/code), a session started as Cloud, or any other cloud sandbox | No. There is no signed-in Codex there. Print Path D in one line and stop; do not try to install one | Every command below shows `python`. Run `python3 --version` once first: when it answers, use `python3` for every command in this skill (the usual case on macOS and Linux). On Windows use `py` when `python` is not found or opens the Microsoft Store. ## What This Skill Does Not Do - Local GPU generation: that belongs to a local tool such as ComfyUI, not this skill - Judging a finished image for six fingers, doubled cutlery or warped text: that is `pvc-image-check`, run it after every render - Video frames, YouTube or screen recordings: that is `pvc-claude-vision` or `pvc-video-to-transcript` - Pixel retouching, webp conversion or cropping: do those in PIL after the render, this skill only produces the source PNG - Style rules: the project's brand-kit.md (or the user) owns palette, light and mood; this skill turns them into a prompt, it does not invent them ## Trigger Examples Should trigger on: - "Generate the hero image for the pizza page" - "Make me a picture of a red apple on a white table" - "Can you get a transparent PNG of the mascot for the header?" - "The background on hero.png is wrong, swap it for a night street but keep the people" - "We need six portraits for the team section" Should NOT trigger on: - "Check hero.png for artifacts before we commit" (pvc-image-check) - "Render this on my own GPU with ComfyUI" (local generator, not this skill) - "What happens at 2:10 in this video?" (pvc-claude-vision) - "Make the card art for pvc-cache-bump" (pvc-skill-art, which drives this skill's gen_image.py itself) ## Step 1: Confirm Codex Exists Run the finder (do not read its source): ```bash python ".claude/skills/pvc-img-gen-codex/scripts/find_codex.py" ``` It prints the binary path, or `NOT FOUND` with the install hint. On `NOT FOUND` stop and print Path D below; nothing else in this skill works without it. The finder checks PATH first, then the usual install folders (Homebrew and npm global, which a desktop app may not have on its PATH), then the newest `openai.chatgpt-*` extension bundle under the VS Code, Insiders, Server, VSCodium, Cursor and Windsurf folders in the user's home. A bundle holds one `bin` folder per system, so the finder takes only the folder for this system and CPU, and the version bump on every extension update never breaks it. On macOS and Linux it also prints a `WARN` line with a `chmod +x` command when the binary is not executable; run that line, then go on. On Windows it prefers the extension's `codex.exe` over an npm `codex.cmd` shim and prints a `WARN` when only the shim exists (a shim takes one-line briefs only; the runner flattens the brief itself). When the user says Codex works in their terminal but the finder prints `NOT FOUND`, ask for the full path and pass it with `--codex` on every gen_image.py call. ## Step 2: Pick the Mode Three modes. Pick before running anything; say which one you picked in one line. | Mode | Use it when | Cost | |------|-------------|------| | Make | The image does not exist yet | one Codex run, about 2 minutes | | Edit | An image exists and only a named part should change | one Codex run, keeps the approved parts | | Batch | Several independent images are needed (a team row, a set of cards) | one run each, all in parallel, still about 2 minutes wall time | Default to Make. Pick Edit over a fresh Make whenever the owner has already approved part of the image: an edit keeps the approved pixels, a regen re-rolls the whole image. Cap edits at two on one image; after that fold every learned constraint into one fresh Make prompt, because each edit re-renders the whole frame and softness compounds like re-saving a JPEG. If the user says "just regenerate" or "start over", skip Edit and Make fresh. ## Step 3: Write the Brief The script wraps the brief with the save instruction. Write only the scene. A brief that works has, in this order: 1. Subject and action, concrete nouns ("a wood-fired margherita pizza on a dark slate board") 2. Setting and light ("on a rustic oak table, warm side light from a window on the left") 3. Framing ("close three-quarter view, the board fills the lower two thirds") 4. Style words from the brand kit ("editorial food photography, shallow depth of field") 5. Exclusions, one line ("no text, no hands, no cutlery") Rules the renders taught: - Remove object classes the model miscounts instead of constraining counts: "no cutlery" works, "exactly two forks" does not. Keep objects the scene requires (chairs at a set table) and constrain them simply - Text in the image: keep it to a few short strings and check the spelling on arrival; named labels are safer than hex codes when a hex misrenders - Blending into a page: bake the page's exact background hex into the scene ("the scene fades into flat #0F1115 at the edges") and edge-fade in PIL afterwards; never fake the blend with CSS masks - Transparent cutout: say "isolated on a fully TRANSPARENT background, PNG with alpha" and run with `--transparent` so the alpha gets verified (a fully transparent pixel must exist; the four corner alphas are reported, and a subject that reaches a corner gets a note, not a fail); a painted white or checkerboard background fails that check on purpose - Edit prompts state invariants first, then the single change: "Keep the six people, their faces, poses and clothes exactly as they are. Replace only the background with ..." When a project keeps a prompt log (client kits do, in prompts.md), write the exact prompt, the date and a one-line reason there BEFORE running. ## Step 4: Run One image per call. Output names are lowercase, hyphenated, `.png`, a bare file name (the folder goes in `--cwd`; the script refuses a folder inside `--out`), and never overwrite the edit source. Every render takes about 2 minutes, longer than Claude Code's default Bash timeout. Launch every gen_image.py call with Bash `run_in_background` and collect its status line when it finishes, the way Batch does. A foreground call needs a 10 minute timeout (600000 ms, the out-of-the-box ceiling) on the Bash call and `--retries 0`, so the script's two default attempts cannot outrun it. When a foreground call still hits its timeout, Claude Code moves it to the background and reports the task and its output file; collect the status line from there, the quota is not lost. Make: ```bash python ".claude/skills/pvc-img-gen-codex/scripts/gen_image.py" --cwd "assets/img" --out hero.png "<brief>" ``` Edit: ```bash python ".claude/skills/pvc-img-gen-codex/scripts/gen_image.py" --cwd "assets/img" --out hero-v2.png --edit hero.png "<invariants, then the one change>" ``` Transparent cutout: ```bash python ".claude/skills/pvc-img-gen-codex/scripts/gen_image.py" --cwd "assets/img" --out mascot.png --transparent "<brief ending in: isolated on a fully TRANSPARENT background, PNG with alpha>" ``` Batch: launch one call per image in the background (Bash `run_in_background`), each with its own `--out`, then collect the status lines as they finish. Six at once has worked, about 2 minutes each. Above that is untested, so add renders in batches of six. A brief with quotes, `$`, `%` or line breaks in it, or a long one: save it to a file and pass `--prompt-file brief.txt`, which keeps the brief out of the calling shell's quoting. That path resolves from where you run the command, not from `--cwd`, so give it relative to the repo root or absolute. Linux boxes and containers: when a FAIL ends with a `Likely cause:` line saying Codex could not start its sandbox, re-run the same command once with `--sandbox danger-full-access`. The script names that cause itself and skips its own retry. Codex may then write anywhere, so keep `--cwd` on the image folder. The script finds Codex, builds the command with the prompt BEFORE `-i` (the flag is greedy and eats a trailing prompt as a file path), runs it with a 10 minute timeout, retries once when no new file appears, and verifies the PNG opens. A file only counts when it was written during the run, so a leftover from an earlier render never passes as new. With Pillow present it also reports width, height and mode, and on `--transparent` checks that a fully transparent pixel exists and reports the four corner alphas. ## Step 5: Look, Then Hand Off 1. Read the PNG (the Read tool shows it). Confirm the subject, the framing and the exclusions in one sentence 2. Run `pvc-image-check` on it when that skill is installed in the project. When it is not, say so and do the object-logic look yourself: count hands and fingers, count cutlery and chair legs, read any lettering, trace shadows and crop edges 3. Post-processing (webp, resize, edge-fade) comes after the check, never before. Never upscale a render that came back under target; output at the native size ## What To Print One of six shapes, always ending with the next action. Path A, OK (the happy path): ``` Mode: Make Prompt logged: docs/prompts.md (2026-08-29) OK: assets/img/hero.png 1536x1024 RGB 2.1 MB (158s) Seen: slate board with one margherita, oak table, warm left light, no text, no hands. Next: running pvc-image-check on hero.png. ``` Path B, FAIL (Codex ran but no usable file, after the built-in retry): ``` Mode: Make FAIL: no usable hero.png after 2 attempts. Codex tail: <last lines from the script> Likely cause: the brief asked for a saved file name with a folder in it; Codex writes only into the working directory. Next: fixed brief below, one more run on your go. ``` Path C, TRANSPARENCY FAIL (file exists, alpha is fake): ``` Mode: Make (transparent) FAIL (transparency): assets/img/mascot.png 1024x1024 RGB, NO alpha channel (background is painted). Not retrying: rewrite the brief. Next: brief rewritten to "isolated on a fully TRANSPARENT background, PNG with alpha, no backdrop, no floor, no shadow plate"; run it on your go. ``` Path D, NO-CODEX (nothing to run): ``` NO-CODEX: no codex on PATH, in the usual install folders, or in an editor extension folder under your home. Install the OpenAI ChatGPT extension in VS Code (marketplace id openai.chatgpt), sign in with your ChatGPT account, then ask again; the finder reads the extension folder on every run. Or install the CLI (npm i -g @openai/codex, or brew install --cask codex on a Mac), run codex login, and restart Claude Code so its shell sees the new PATH. Alternative: any local image generator you already run (for example ComfyUI). Already have Codex somewhere on this machine? Give me its full path and I will re-run with --codex <path>. ``` Path E, QUOTA (Codex refused on auth or usage limit): ``` QUOTA: Codex refused after 4s (usage limit reached). Brief kept below, unchanged. Re-run when the ChatGPT limit resets, or sign in again if the message said not authenticated. ``` Path F, BATCH (several images in one run): one status line per file in launch order, then one Next line. ``` Mode: Batch (3 runs in parallel) OK: team-01.png 1024x1536 RGB (164s) FAIL: team-04.png, no usable file after 2 attempts (Codex tail below) OK: team-05.png 1024x1536 RGB (172s) Next: pvc-image-check on the two, then one more run for team-04.png with the tightened brief. ``` ## Worked Examples ### Make, happy path User: "Make me a picture of a red apple on a white table." Run: ```bash python ".claude/skills/pvc-img-gen-codex/scripts/gen_image.py" --cwd tests --out test-apple.png --retries 0 "A single red apple on a plain white wooden table, soft daylight from the left, photographic, no text" ``` Script output (real run, 2026-08-29, paths shortened): ``` codex: ~/.vscode/extensions/openai.chatgpt-26.707.41301-win32-x64/bin/windows-x86_64/codex.exe mode: generate target: tests/test-apple.png attempt 1/1 running (about 2 minutes) ... OK: tests/test-apple.png 1402x1122 RGB 1756545 bytes (159s, codex rc=0) ``` On a Mac the `codex:` line points at `bin/macos-aarch64/codex` (or `bin/macos-x86_64/codex` on Intel), on Linux at `bin/linux-x86_64/codex`; the rest reads the same. Print: ``` Mode: Make OK: tests/test-apple.png 1402x1122 RGB 1.7 MB (159s) Seen: one red apple with stem, centered on white painted planks, soft left light, no text. Next: pvc-image-check is not installed here; my own look finds one apple, one stem, one shadow, nothing doubled. ``` ### Edit, keep everything but one thing User: "Same apple but green." Run: ```bash python ".claude/skills/pvc-img-gen-codex/scripts/gen_image.py" --cwd tests --out test-apple-green.png --edit test-apple.png "Keep the apple, the table, the lighting and the framing exactly as they are. Change only the apple's color from red to green." ``` Print: ``` Mode: Edit (1 of 2 allowed on this image) OK: tests/test-apple-green.png 1402x1122 RGB 1.7 MB (100s) Seen: same framing and planks, apple now green, stem and shadow unchanged. Next: pvc-image-check on test-apple-green.png, comparing against test-apple.png for drift. ``` ### Batch, six portraits User: "We need six team portraits for the about page." Launch six background calls, one per person, same style block, different `--out` (`team-01.png`, `team-02.png`, ...). Collect the six status lines, then print one block: ``` Mode: Batch (6 runs in parallel) OK: team-01.png 1024x1536 RGB (164s) OK: team-02.png 1024x1536 RGB (170s) OK: team-03.png 1024x1536 RGB (166s) FAIL: team-04.png, no usable file after 2 attempts (Codex tail below) OK: team-05.png 1024x1536 RGB (172s) OK: team-06.png 1024x1536 RGB (168s) Next: pvc-image-check on the five, then one more run for team-04.png with the tightened brief. ``` ## Output Rubric - one_file_per_call: every run names one `--out`, and the print names the file that exists on disk with its size - verified_not_assumed: the OK line comes from the script's verify step, never from Codex saying it saved something - mode_stated: the print opens with Make, Edit or Batch, and edits count toward the two-edit cap - brief_quality: subject, setting, framing, style, exclusions, in that order, with miscounted object classes removed rather than counted - invariants_first: every edit prompt states what stays before what changes - hand_off: every OK ends with the pvc-image-check run, or says why it did not and gives the manual look - voice: no em dashes, PVC voice throughout - edge_case_coverage: Codex missing (Path D, install hint, local alternative named), web version of Claude Code (Path D, no install attempted), binary not runnable (NO-CODEX with the fix, apply it, retry), npm `.cmd` shim on Windows (brief flattened, extension `codex.exe` preferred), a folder inside `--out` (usage error, put it in `--cwd`), sandbox cannot start on Linux (FAIL names it, one rerun with `--sandbox danger-full-access`), auth or usage limit (Path E, brief kept), no file after retry (Path B, likely cause and fixed brief), fake transparency (Path C, no retry, rewritten brief), edit source equals output name (script refuses, pick a new name), third edit on one image (fold constraints into a fresh Make), long brief (prompt file), pvc-image-check absent (manual object-logic look) ## Resilience - Codex missing: Path D, stop. Never try to install it or run npm without the user asking - Binary found but not runnable (macOS, Linux: no exec bit; Windows: a path without `.exe`, `.cmd`, `.bat` or `.com`): the script prints NO-CODEX with the fix and exits 3 before any run. Apply it, then retry - npm `codex.cmd` shim on Windows: the run works, the brief is flattened to one line and a note says so; the extension's `codex.exe` is preferred when both exist - Sandbox cannot start (Linux, container, WSL): the FAIL print names it. Re-run once with `--sandbox danger-full-access`, `--cwd` still on the image folder - Codex refuses on auth or limit: Path E, keep the brief verbatim, stop; the user decides when to retry - File missing after the script's own retry: Path B with the Codex tail; rewrite the brief once, then wait for a go before spending more quota - Painted background on a transparent request: Path C, no retry with the same brief - Timeout (10 minutes): treat as Path B; ChatGPT is slow or queued, say so and offer one retry later - Edit source not found or same as output: the script exits with a usage error; fix the path or the name, no Codex run happened - Re-run on a name that already exists: the script says so up front and only reports OK when the file changed during the run. Use `-v2` names when the owner approved the earlier version - Pillow missing: the script still reports OK on a non-empty file, says size and alpha were not verified; open the file with Read to confirm it decodes ## Installation Place this folder at `<repo>/.claude/skills/pvc-img-gen-codex/`. Every command in this skill is written relative to the project root, so a project install keeps them working as printed. Claude Code watches `.claude/skills/` and picks the new skill up in the running session. Restart it (reload the VS Code window, or quit and relaunch `claude` in a terminal) only when you just created `.claude/skills/` for the first time, so a session starts watching that folder. Verify by typing `/` in the prompt box and confirming `/pvc-img-gen-codex` is in the list. Then run the finder once to confirm Codex is reachable. Optional self-check that spends no quota: `python ".claude/skills/pvc-img-gen-codex/scripts/test_skill.py"` runs the offline checks (the finder on fake Windows, Mac and Linux folders, the shim rule, the command shape, the PNG verifier) and ends with `N/N checks passed`.
// set it up
Install in 5 Minutes
The skill is one folder with three small Python scripts. You need three things. Python 3.9 or newer. A paid ChatGPT plan that includes Codex (Plus, Pro, Business, Edu or Enterprise as of September 2026), signed in through the OpenAI ChatGPT extension in VS Code or through the Codex command line tool installed on its own. And a computer you sit at, since the web version of Claude Code has no Codex. Pillow, a free Python add-on, is optional. REQUIREMENTS.md in the repo has the check for each. The live renders so far were on Windows; the Mac and Linux paths are covered by the skill's own offline tests.
Get the Folder
Open the GitHub repo. Click Code, then Download ZIP. Unzip it, open the folders until you see SKILL.md, then rename that folder to pvc-img-gen-codex.
Put It in Place
Move the folder to your-project/.claude/skills/pvc-img-gen-codex/. Keep it per project: every command in the skill runs from the project root.
Start a New Session
Open Claude Code in that project. Ask "what skills are available?" and check that pvc-img-gen-codex shows up on the list.
Say the Words
Type "make me a picture of a red apple on a white table". The skill finds Codex, runs one render of about two minutes, checks the file, and shows you the image.
// or let claude do it
Let Claude Install It
Paste this into any Claude Code session. Claude fetches the folder from GitHub and puts it in place.
Install the pvc-img-gen-codex skill for me. Source: https://github.com/pro-vibe-coding/pvc-img-gen-codex Target: .claude/skills/pvc-img-gen-codex/ inside this project. Make the folders if they do not exist. Steps: 1. Check that Python 3.9 or newer answers: python --version (py --version on Windows when python is missing or opens the Microsoft Store, python3 --version on Mac and Linux). If it does not answer, stop and tell me. Do not install Python or Codex for me, and do not run npm. Codex gets checked in step 6 with the skill's own finder, because the ChatGPT extension keeps its codex binary inside the extension folder, not on PATH. 2. Clone the source repo into a new folder in the system temp directory (%TEMP% on Windows, /tmp on Mac and Linux), never inside this project. If the clone is blocked, download the ZIP from the repo page and unzip it there instead. 3. Copy these seven files from the repo root into the target: SKILL.md, README.md, .gitignore, LICENSE, NOTICE, REQUIREMENTS.md, TRADEMARK.md Copy the whole scripts folder in as well, with find_codex.py, gen_image.py and test_skill.py inside it. Nothing in this skill runs without those three. 4. Do not change any file. Keep LICENSE and NOTICE. The assets folder stays behind, so the README image will not show. That is expected. 5. Delete the temp folder. If the delete is refused, print its path and let me remove it. Show me the full path of the installed folder. 6. Run python .claude/skills/pvc-img-gen-codex/scripts/find_codex.py (py on Windows, python3 on Mac and Linux) and show me the line it prints. NOT FOUND means Codex is not reachable yet: tell me to install the ChatGPT extension in VS Code and sign in, then stop. A WARN line with a chmod +x command on Mac or Linux means run that line once, then run the finder again. When it prints a path, run that path with login status and show me the answer. Anything other than Logged in using ChatGPT means I have to sign in to Codex before the first image, on a ChatGPT plan that includes Codex. Then tell me three things. One: if this project is a git repo, the skill folder shows up as new untracked files, so my next commit picks them up unless I ignore the folder or commit it on purpose. Two: start a new session and say "make me a picture of a red apple on a white table". Every image spends my ChatGPT plan, not my Claude usage. Three: pip install pillow is optional. Without it the file check confirms the PNG exists but cannot report its size or check transparency.
// good to know
Before You Run It
Four things worth knowing before you add it.
Spends ChatGPT, Not Claude
Every render comes out of the paid ChatGPT plan Codex is signed in to, not a free account. Claude Code pays only for the words around it.
Says When It Cannot Run
No Codex, an expired sign-in, a usage limit, or a fake see-through background: each stops the run with a one-line status and a next step, not a silent retry.
Open Source
Apache 2.0. Use it, change it, share it. Keep the LICENSE and NOTICE files. The names Pro Vibe Coding and PVC stay trademarks.
Follows GitHub
Version 0.2.1 is the main branch on GitHub right now, the same one the video shows. This site updates when the repo moves.
// get started
Want More Free Skills?
Join the Pro Vibe Coding community. Members get every skill first, with updates as they happen, and build real projects together.