Overview
Generate multi-style 2x2 grid meme stickers (2x2 grid) from user-uploaded photos, split into 4 independent stickers, and optionally convert specified stickers or all of them into animated GIF meme packs. Supports four built-in styles: Q-version, 3D clay, pixel style, and Emoji, as well as user-defined styles.
Dependencies
- tools: meitu-cli — Meitu AI Open Platform CLI (image generation/editing, video generation, format conversion)
- Install:
npm install -g meitu-cli@latest(package name meitu-cli)
- Install:
- credentials: Meitu AI Open Platform API credentials
- Environment variables:
MEITU_OPENAPI_ACCESS_KEY/MEITU_OPENAPI_SECRET_KEY - Or configuration file:
~/.meitu/credentials.json - Preferred environment variables:
MEITU_OPENAPI_ACCESS_KEY/MEITU_OPENAPI_SECRET_KEY - Or preset credentials file:
~/.meitu/credentials.json - If manual initialization of local credentials is needed, you may explicitly run
meitu config set-ak --value "..."+meitu config set-sk --value "..."(will write to local file) - Verify:
meitu auth verify --json
- Environment variables:
- workspace (optional):
{OPENCLAW_HOME}/workspace/visual/- Not found → skip all knowledge reads, skill works without it
Path alias: Below,
$VISUAL={OPENCLAW_HOME}/workspace/visual/
Core Workflow
Preflight → [Context] → Execute → Refine → Deliver → [Record]
↑ 创意型任务执行 ↑ 项目模式时执行
↑ 工具型任务跳过 ↑ 一次性模式跳过
Preflight
meitu --version→ if not installed, promptnpm install -g meitu-cli@latestmeitu auth verify --json→ if credentials are invalid, guide configuration- Detect mode: cwd has
openclaw.yaml→ project mode; else → one-off Check$VISUALdirectory → determine capabilities can_record = cwd has openclaw.yaml AND$VISUALexists (if either is missing, false) - output_dir resolution (MUST be completed within Preflight):
Resolve output_dir: openclaw.yaml →
./output/| else →$VISUAL/output/meitu-stickers/mkdir -p {output_dir}
Context (executed for creative tasks + project mode)
mode = one-off → skip this step, go directly to Execute.
User explicitly references brand assets AND $VISUAL exists → read only as needed $VISUAL/assets/
mode = project → execute step by step:
- Read
./DESIGN.md - Extract Context References → try to read
$VISUAL/assets/or$VISUAL/rules/global assets → if unreadable, use inline fallback values in DESIGN.md - Read quality.yaml → global.md → scenes/{type}.md (type is read from openclaw.yaml's
project.types(array takes priority) orproject.type, both skip if missing) → quality forbidden list filters generated elements, preferences enhance creative direction; design is null → create after Execute
Execute
Classify Input
| Scenario | Condition | Action |
|---|---|---|
| A — Single clear subject photo | User uploads 1 image containing an identifiable subject (person/animal/character/building/product/food) | → Select Style |
| B — Multiple photos | User uploads > 1 image | → Composite → Select Style |
| C — Already in meme pack style | User's image is already in some meme pack style | → Select Style, treat as refinement/editing request |
| D — No image uploaded | No image | Reply with prompt (see below), wait for upload |
Scenario D reply: "Please upload a photo, and I'll help you generate meme stickers~" If it contains multi-image keywords such as "a group"/"a set" → additionally prompt "If you need a group photo effect, please select and upload multiple images at once"
Composite Multiple Photos (Scenario B only)
meitu text-to-image \
--skill_name skill_meitu-stickers \
--image_list "<image_url_1>" "<image_url_2>" \
--prompt "将多张图片主体物合成一张合照(如第一张照片的人物与第二张照片人物合照),{user_pose_requirement},保持主体物样貌相似度不变,保持图片风格不变" \
--json --download-dir {output_dir}/composite
{user_pose_requirement}: if the user specified a pose/interaction, add it; otherwise omit this clause.- From
downloaded_files[0].saved_pathRead the composite result and use it as the source image for Generate Sticker Grid.
Select Style
Style recognition decision table:
| User keyword | Style ID | Description |
|---|---|---|
| Chibi, chibi, big head sticker, cute chibi | chibi |
Big head small body, rounded features, exaggerated expressions |
| 3D, clay, clay, clay sculpture, clay | clay |
3D clay/plasticine texture, soft and rounded, matte texture |
| Pixel, pixel, 8bit, retro game | pixel |
Pixel art style, crisp pixel edges, limited palette |
| emoji, emoji, round face | emoji |
Thick outlines, flat colors, simplified features, round face |
| Other specified styles (e.g. "watercolor", "cyberpunk") | custom |
Build prompt based on user description |
| No style specified | — | Proactively ask (see below) |
When no style is specified, ask: "Which style of sticker do you want? I support these built-in styles: 🎨 Chibi — Big head cute style 🧸 3D Clay — Three-dimensional clay texture 👾 Pixel — Retro game art style 😊 Emoji — Round face flat style
You can also tell me any style you want, such as "watercolor style" or "cyberpunk"~"
Generate Sticker Grid
Prompt template: See references/prompts.md。
- Select the corresponding style section (
## chibi/## clay/## pixel/## emoji/## custom) - Concatenate
## GRID_CONSTRAINTSEnsure the generated result can beimage-grid-splitcorrectly split
Style → command decision table:
| Style ID | Command | Reason |
|---|---|---|
chibi |
text-to-image --image_list |
Reference a real person image for artistic stylization (big head chibi) |
clay |
text-to-image --image_list |
Reference a real person image to generate 3D clay style |
pixel |
text-to-image --image_list |
Reference a real person image to generate pixel style |
emoji |
text-to-image --image_list |
Reference a real person image to generate flat emoji style |
custom(Art style type: watercolor/cyberpunk/oil painting, etc.) |
text-to-image --image_list |
Under 2.0.6, stylization prioritizes reference-image-based generation |
custom(Realistic type: portrait/ID photo, etc.) |
text-to-image --image_list |
Preserve character features, but avoid relying on the old image-edit style model |
custom(Uncertain) |
text-to-image --image_list |
Uniformly use reference-image generation to reduce routing divergence |
Note: The current CLI already supports
image-edit --model nougatas an explicit high-quality editing path; however, sticker scenarios still uniformly prioritizetext-to-image --image_list, because four-grid stickers are better suited to the reference-image generation pipeline, with more stable style and composition control.
Generation command:
meitu text-to-image \
--skill_name skill_meitu-stickers \
--image_list "<source_image_url>" \
--ratio 1:1 \
--size 2K \
--prompt "{STYLE_PROMPT} {GRID_CONSTRAINTS}" \
--json --download-dir {output_dir}
{STYLE_PROMPT} Responsible for specifying the style type (chibi / clay / pixel / emoji / custom).
Error fallback strategy (L1-L5):
| Level | Operation | Specific content |
|---|---|---|
| L1 | Remove low-priority modifiers | Remove descriptive modifiers from the style prompt (e.g. "matte clay texture with subtle highlights"), keep core style words + GRID_CONSTRAINTS |
| L2 | Simplify style description | Reduce the style prompt to one sentence: e.g. chibi → "2x2 grid of chibi stickers from this photo, 4 expressions" + GRID_CONSTRAINTS |
| L3 | Remove optional inputs | N/A (source image is a required input) |
| L4 | Minimize to core elements | prompt → "2x2 sticker grid, 4 stickers, {style} style, white background, well separated" |
| L5 | Stop and report error | 2 consecutive failures → report error to the user, with code and hint |
Show the 2x2 grid to the user, and wait for confirmation before splitting the image. Do not directly execute grid-split. → Enter Refine
Refine
Phase 1: Confirm the 2x2 grid
Show the generated 2x2 grid, explain the style used, and ask: "This is the generated {style_name}-style 2x2 grid sticker pack. Are you satisfied with the overall effect? If so, I'll help you split it into 4 separate stickers~"
Wait for the user's reply:
Feedback classification and handling:
| Feedback type | Example | Handling method |
|---|---|---|
| Change style | "Switch to pixel style", "Try 3D" | Go back to Select Style → Generate Sticker Grid |
| Adjust expressions | "The second expression is too exaggerated", "Make it cuter" | Adjust the expression description in the prompt → Generate Sticker Grid |
| Adjust style details | "Make the colors more vivid", "Make the lines thicker" | Append prompt modifiers → Generate Sticker Grid |
| Image splitting issues | "The stickers are too close together", "There is overlap" | Strengthen GRID_CONSTRAINTS spacing → Generate Sticker Grid |
| Satisfied | "OK", "Sure", "Satisfied" | → Enter Phase 2 |
It is recommended to iterate at most 3 rounds; after that, proactively suggest adjusting the direction or splitting the requirements.
Phase 2: Split the image + confirm stickers
After the user confirms the 2x2 grid, execute the image split:
meitu image-grid-split --image_url "<grid_image_url>" --json --download-dir {output_dir}/split --skill_name skill_meitu-stickers
If image-grid-split returns fewer than 4 images(grid spacing insufficient for detection):
- Re-generate 2x2 grid with stronger spacing prompt — append: "Ensure each sticker is clearly separated with at least 25% white space between them. Each sticker must be a completely independent illustration with no visual connection to adjacent stickers."
- Retry
image-grid-split. If still < 4 → deliver grid image as-is and inform user.
Show all 4 separate stickers at once(after downloading all images, show them all in the same reply, do not split into batches), and ask: "All split~ Would you like to convert one of them or all of them into animated stickers (GIF)? Just tell me the numbers (e.g., 1, 3) or say "all". If you don't need it, just say you're satisfied and I'll help you save them~"
Wait for the user's reply:
- No GIF → Enter Deliver
- Specify GIF conversion(one / multiple / all) → Execute GIF conversion (below) → Show results → Enter Deliver
GIF conversion process (execute sequentially, one by one):
a. Image to Video:
meitu image-to-video \
--skill_name skill_meitu-stickers \
--image_list "<selected_sticker_url>" \
--prompt "{style_name} character performing a simple animated expression, loopable motion" \
--json \
--download-dir {output_dir}/video
Wait for async result (CLI automatically polls, video downloaded to {output_dir}/video)。
b. Show the video to the user(already downloaded to {output_dir}/video), and let the user preview the animation effect.
c. Video to GIF (use the video file downloaded locally by image-to-video):
meitu video-to-gif --video_url "{output_dir}/video/<video_task_id_file>" --prompt "transparent animated sticker" --json --download-dir {output_dir}/gif --skill_name skill_meitu-stickers
If user selects "all", process all stickers sequentially (one at a time: image→video→show video→gif, then next). If user selects multiple (e.g., "1 and 3"), process the specified ones sequentially.
Deliver
The file is already in output_dir(used during generation --download-dir), only rename is needed:
mv {output_dir}/split/{task_id_file} {output_dir}/{YYYY-MM-DD}_{style}-sticker-{n}.{ext}
Animated GIF → mv {output_dir}/gif/{task_id_file} {output_dir}/{YYYY-MM-DD}_{style}-sticker-{n}-animated.{ext}
Record (executed in project mode)
can_record = cwd has openclaw.yaml AND $VISUAL exists (if either is missing, false) → skip when false. In one-off mode, feedback is only valid for the current conversation.
Exception: in one-off mode, if the user repeatedly expresses the same preference → Agent MAY propose writing to $VISUAL/rules/quality.yaml
User approved style →
read $VISUAL/memory/observations/observations.yaml → scan similar key → merge or append → write back.
len(projects) >= 2 → propose promotion (non-blocking).
Non-blocking promotion proposal (mention at the end of the reply, without interrupting the main flow) → confirmed → write target + delete observation entry
User rejected ("不要 XX") → has openclaw.yaml → ask scope → project: ./DESIGN.md Constraints / universal: quality.yaml no openclaw.yaml → current task only
No feedback → skip entirely.
Output
- 4 independent meme stickers (from grid split), style consistent with user's choice
- Optional: animated GIF meme (for selected sticker(s))
- File naming:
{YYYY-MM-DD}_{style}-sticker-{n}.{ext}(e.g.,2026-03-22_chibi-sticker-1.jpg、2026-03-22_pixel-sticker-3-animated.gif)