cowart-image-gen
GitHub在Cowart画布上生成并插入AI图像。支持替换选中的AI占位符或独立插入新图,自动适配尺寸、比例及位置,确保图像无缝融入当前页面。
Trigger Scenarios
Install
npx skills add zhongerxin/Cowart --skill cowart-image-gen -g -y
SKILL.md
Frontmatter
{
"name": "cowart-image-gen",
"description": "Generate a final AI bitmap for the Cowart canvas, including any requested in-image text by default. Use when the user asks Codex to create, fill, replace, or place an AI-generated image on a Cowart canvas. If an AI 图片 holder is selected, use it as the size target and replace it with the generated image by default; otherwise generate the image and insert it into the current Cowart page."
}
Cowart Image Gen
Use this skill when the user wants an AI-generated image placed onto the Cowart canvas. A selected AI 图片 holder gives a precise size and placement target, but it is not required. By default, a selected holder is a temporary target and should be replaced by the generated image.
Preconditions
The native Cowart widget should be open for the user's active project. Cowart state is read and written through Cowart MCP tools, not through a localhost browser service.
New holders are tldraw frame shapes with:
{
"type": "frame",
"meta": {
"cowartAiImageHolder": true
}
}
Older canvases may still contain legacy geo rectangle holders with the same
meta flag. Support both shapes.
Workflow
-
Read the selected shape from Cowart with the MCP
get_cowart_selectiontool. Pass the active user project directory asprojectDir. -
Check whether exactly one selected shape is an AI image holder. A holder is any selected shape with either:
isAiImageHolder: trueor:
meta.cowartAiImageHolder: trueIf yes, use the holder replacement workflow below. If not, do not ask the user to select a holder; use the standalone workflow below and insert the generated image into the current Cowart page.
-
Choose the placement workflow.
Holder replacement workflow: use the selected holder's
props.wandprops.has the size contract for both generation and placement. Before generating, derive and keep these values:targetWidth: selected holderprops.wtargetHeight: selected holderprops.htargetAspectRatio: the reducedtargetWidth:targetHeightratio when it maps cleanly, plus the decimaltargetWidth / targetHeight
If the selected holder matches a Cowart ratio preset such as
1:1,3:2,2:3,4:3,3:4,16:9, or9:16, use that preset label as the human-readable aspect ratio. The generated image should be composed for this target size and aspect ratio, and should not rely on later stretching or cropping to fit the holder.The generated image should replace the selected holder as a normal tldraw image shape:
parentId: same parent as the holderx,y,rotation: same as the holderprops.w,props.h: same as the holder
This leaves the final canvas with an image shape at the holder's position, not an AI holder that contains an image. Only preserve the holder when the user explicitly asks to keep the reusable slot.
Standalone workflow: when no AI holder is selected, generate the image anyway and insert it as a normal image shape on the current page. Prefer the current page from Cowart view state; if there is a selected non-holder shape and it is useful as context, place the image beside it, otherwise place it in a clear page area. If the user requested a size or aspect ratio, pass that size and ratio into generation and use it for display. Otherwise, use the generated bitmap's natural aspect ratio and a practical display width such as 512 canvas units.
-
Generate the bitmap with the built-in
imagegenskill unless the user explicitly requests another image path. If the requested asset needs visible copy, labels, poster text, ad text, UI text, or typography, include that text directly in the image generation prompt and let the image model produce the final bitmap. Do not default to generating a text-free background and then adding text locally unless the user explicitly asks for local typography, deterministic text overlay, SVG/vector output, or another non-imagegen layout step.For the holder workflow, the image generation request must explicitly include the selected holder's target size and aspect ratio. Add this information to the model prompt, for example:
Target canvas slot: 512 x 683 canvas units. Target aspect ratio: 3:4 (0.75 width/height). Compose the final bitmap for this portrait ratio so it fits the slot without cropping or stretching.If the image generation tool or model accepts size or aspect-ratio parameters, pass the closest supported option in addition to the prompt text. If only prompt text is available, the prompt text must still include
targetWidth,targetHeight, andtargetAspectRatio.Resolve the actual local output image carefully before inserting it into Cowart. Do not assume the built-in image generation flow always writes a fresh file under
$CODEX_HOME/generated_images.Preferred resolution order:
- Use the exact local image path returned by the current image generation tool call when one is available.
- If no new file path is returned, inspect the current Codex session JSONL for the current request and extract the PNG/base64 payload from the latest
image_generation_call.result, then write it to a timestamped output filename. - Use
$CODEX_HOME/generated_imagesonly when you can prove the file was created by the current request, for example by matching its timestamp after this generation step. Never pick an older image merely because it is the newest file in a stale generated_images directory.
Before inserting the resolved file into Cowart, visually inspect the local bitmap and confirm it is the newly generated image for this request, not a stale generated asset.
For project-bound output, copy the resolved generated image into the selected page's asset folder:
canvas/pages/<page-id-without-page-prefix>/assets/ -
Insert the generated image as a new tldraw image shape.
For the holder replacement workflow, call
insert_cowart_imagewith the holder id asanchorShapeIdand leavereplaceAiImageHolderunset or set it totrue. The MCP tool will place the image exactly where the holder was and remove the holder shape:type:imageparentId: same as holder parentx,y,rotation: same as holderprops.w,props.h: same as holderprops.assetId: the new image asset idmeta.cowartGeneratedForAiImageHolder: holder shape idmeta.cowartReplacedAiImageHolder:true
If the user explicitly asks to keep the AI holder reusable, call
insert_cowart_imagewithreplaceAiImageHolder: false; for frame holders that legacy mode inserts the generated image as a child of the frame.For the standalone workflow, insert it into the current page as a normal image:
type:imageparentId: current page id, unless placing beside a selected non-holder shape requires the same parentx,y: a clear page area or beside the selected non-holder shaperotation:0props.w,props.h: display size matching the generated bitmap aspect ratioprops.assetId: the new image asset idmeta.cowartGeneratedStandalone:true
-
Delete the selected holder by default as part of replacement. In the standalone workflow, do not create a holder first unless the user explicitly asks for one.
-
Save through Cowart MCP. Prefer
insert_cowart_imagefor inserting the generated bitmap, or usesave_cowart_canvas_stateonly when you must update the whole tldraw snapshot.Prefer page-local asset URLs in the image asset:
/page-assets/<page-id-without-page-prefix>/<filename> -
Let the Cowart widget refresh from MCP-backed storage, then confirm the inserted shape id, final dimensions, target aspect ratio, saved asset path, and replaced holder id when the holder replacement workflow was used.
Notes
- If the holder is a legacy rotated
georectangle, preserve the samerotationon the replacement image. - If there is already a generated image inside the holder from an older Cowart version, replacing the holder should remove the holder and its child image shape, then create one normal image shape in the holder's former position.
- Do not refuse generation solely because no
AI 图片holder is selected. Generate the bitmap and insert it into the current Cowart page. - Never overwrite an existing asset file; use a timestamped filename.
Version History
- 220ed77 Current 2026-07-05 11:56


