Overview
Generate a carousel set with one click, including a cover poster and multiple inner pages, with a unified style for the cover and inner pages. Suitable for scenarios such as Xiaohongshu image-set posts, knowledge card carousels, and product introduction image sets.
Not applicable scenarios: single poster (not a set), non-poster needs (such as copywriting, translation, visual suggestions, color proposals), content that only involves a poster/cover but does not point to a set
Dependencies
- tools: meitu-cli — the command-line tool for Meitu's AI open platform. Meitu is a technology company driven by AI with beauty at its core, committed to creating world-class imaging products and making image, video, design, and other imaging creation simple and efficient.
- Install:
npm install -g meitu-cli@latest(package name meitu-cli) - Commands used:
image-poster-generate
- Install:
- credentials: Meitu AI open platform API credentials
- Environment variable:
MEITU_OPENAPI_ACCESS_KEY/MEITU_OPENAPI_SECRET_KEY - Or configuration file:
~/.meitu/credentials.json - Configuration method:
meitu config set-ak --value "..."+meitu config set-sk --value "..." - Verification:
meitu auth verify --json
- Environment variable:
- workspace (optional):
{OPENCLAW_HOME}/workspace/visual/- Path resolution:
$OPENCLAW_HOMEenv var →~/.openclaw(macOS/Linux) /%LOCALAPPDATA%\openclaw(Windows) - If directory not found → skip all knowledge reads, skill works without it
- Path resolution:
- memory read/write paths (project mode):
$VISUAL/rules/quality.yaml— forbidden elements$VISUAL/memory/global.md— global preferences$VISUAL/memory/scenes/{type}.md— scene preferences$VISUAL/memory/observations/observations.yaml— observation staging
Path alias: Below,
$VISUAL={OPENCLAW_HOME}/workspace/visual/
Core Workflow
The process is arranged in actual execution order:
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 $VISUAL exists (if either is missing, false) - output_dir resolution (MUST be completed within Preflight, cannot be deferred to Execute or Deliver):
Resolve output_dir: openclaw.yaml →
./output/| else →$VISUAL/output/meitu-carousel/mkdir -p {output_dir}Hard constraint: output_dir MUST NOT point inside the skill folder - Project creation (only when the user actively requests it): manually create
{OPENCLAW_HOME}/workspace/visual/projects/{name}/+openclaw.yaml; already in the project directory → skip
Context (creative MUST / tool-type skip / one-off mode skip)
mode = one-off → skip this step and go directly to Execute. The following applies only to project mode:
Read step by step (all skip if missing):
- Read ./DESIGN.md → extract Context References (brand, palette, platform, etc.) → for each reference, try to read the global asset (e.g., brand: acme → $VISUAL/assets/brands/acme/) → if read, use the latest version; if not, use the inline fallback value in DESIGN.md
- Read $VISUAL/rules/quality.yaml → forbidden list
- Read $VISUAL/memory/global.md → global preferences
- Read project.types (array, preferred) or project.type (single value) from openclaw.yaml → for each type, read $VISUAL/memory/scenes/{type}.md Note: {type} comes from openclaw.yaml, not the skill name → quality forbidden list filters generated elements, preferences enhance the creative direction
Execute
Output directory: directly use the output_dir resolved in Preflight,mkdir -p {output_dir} ensure the directory exists. All subsequent meitu-cli calls uniformly use the --download-dir {output_dir} --json parameter, files are downloaded directly to the target directory, and JSON output is for the Agent to parse the results.
Global visual constraints(applicable to all generation steps — cover and inner pages):
- Color: bright and soft, moderate saturation, must not be too gaudy or old-fashioned, no more than three main colors
- Title: prohibit 3D/three-dimensional/embossed/shadow effects, no more than one font style
- Color tone: Overall yellow tint (yellow filter feel) is prohibited
- Elements: Generating duplicate elements is prohibited
Reference input routing table(--image_list How it is passed at different stages):
| Stage | Intent | --image_list |
Description |
|---|---|---|---|
| Stage 4: Cover | Pure text-to-image | Not passed | Generated from prompt, no reference image |
| Stage 5a: First inner page | Reference cover style | Pass in the cover image path (downloaded_files[0].saved_path) |
Ensure the inner page is visually consistent with the cover |
| Stage 5b: Subsequent inner pages | Apply template | Pass in the template page path (downloaded_files[0].saved_path) |
Copy the layout and style of the template page |
Stage 1: Information detection
Determine whether the user has provided cover copy and inner page copy information.
Branch logic:
- If both are detected → go to Stage 3
- If the user only provides cover copy → ask the user "Will you provide specific inner page copy? I will fill the information you provide into the note image." After the user provides information, go to Stage 3; if the user does not provide information, go to Stage 2
- If the user only provides inner page copy → ask the user "Will you provide specific cover copy? I will fill the information you provide into the note image." After the user provides information, go to Stage 3; if the user does not provide information, go to Stage 2
- If neither cover copy nor inner page copy is provided → ask the user "Will you provide specific cover copy and inner page copy? I will fill the information you provide into the note image." After the user provides information, go to Stage 3; if the user does not provide information, go to Stage 2
Stage 2: Copy content generation
When the user does not provide specific copy information: analyze and think based on the topic, and generate suitable cover copy or inner page copy or both according to what is missing, so that the final information includes cover copy and inner page copy.
Cover copy requirements:
- Cover title, no more than 10 characters
- Cover decorative text, no more than two groups, each group no more than 5 characters
Inner page copy requirements:
- The inner page copy for one inner page is 100-300 characters
- The inner page copy for all inner pages is 300-600 characters
- Each inner page is paired with a subtitle, each subtitle copy must be different, and the subtitle length is controlled at 5-12 characters
- The subtitle length is included in the 300-character limit
Copy checking and optimization rules:
- All title-like copy must not contain any structural symbols, including but not limited to "【, (, #, ", 「, {, ["
- The text must not contain any Markdown syntax or its variants
- Unless the user explicitly requests that the platform name be written into the copy, the platform name itself must not appear anywhere in the prompt
- Avoid: special symbols, watermarks, repeated text
- The image should only contain necessary copy related to this topic (title, subtitle, a small amount of explanation, etc.); do not add extra explanatory text such as "cover, poster, Xiaohongshu, XHS, example, template, subtitle"
- Do not show "style description words" on the image, such as "plush style, illustration style, 3D style, hand-drawn style", etc.
- Do not automatically add page numbers or sequence number text
Stage 3: Generate cover Prompt
When a cover prompt needs to be assembled → read references/xiaohongshu-cover.md to get the cover prompt template and rules.
Pass "a. provided by the user b. the cover copy generated by the model in Phase 2" as the summary parameter, and generate the cover poster Prompt based on the user's needs together with [cover copy].
Phase 4: Generate the note cover
Call meitu-cli:
meitu image-poster-generate \
--skill_name skill_meitu-carousel \
--prompt "{阶段 3 得到的完整输出结果,不做任何修改}" \
--ratio "3:4" \
--size "2K" \
--output_format jpeg \
--download-dir {output_dir} \
--json
Phase 5: Generate single-page note inner pages
Inner page generation principles: Each call generates only one inner-page note image, and one image corresponds to only one page of content. It is forbidden to lay out multiple pages of content or a grid collage in one image. It is forbidden to automatically add any text content other than [current page copy].
From [full inner-page copy set], sequentially extract [current page copy], and keep the total word count of this page under 300 characters.
5a. First inner page (template page)
When no inner page has been generated yet, call meitu-cli:
meitu image-poster-generate \
--skill_name skill_meitu-carousel \
--image_list {阶段 4 JSON 结果的 downloaded_files[0].saved_path} \
--prompt "{内页 prompt,见下方}" \
--ratio "3:4" \
--size "2K" \
--output_format jpeg \
--download-dir {output_dir} \
--json
Inner page prompt: "Based on the same visual style and completely consistent color scheme as the [cover image], generate the first inner-page poster. It may include the background of the [cover image] and 2-3 decorative elements, but must not include the cover's main visual elements. Show only the current page copy of this page. It is forbidden to generate text that is not included in the current page copy. The layout structure must be clear: the main subject of the image is a text-bearing area that occupies the main area. The title is located at the top and may have a simple-shaped backing or small decorative elements in the same style as the reference image (decide whether to include them based on the richness of the image). If there is a backing, its color must differ in lightness from the title to ensure title legibility and aesthetic experience. The generated backing or small decorative elements must be consistent with the overall style of the image. The title must not have a 3D effect. The body content is divided into multiple paragraphs, vertically left-aligned, neatly arranged in the text-bearing area, not touching the edge and retaining at least one character width, with line spacing equal to one body character height. Key text or secondary headings have an emphasis style for highlighting. The overall layout structure is clear and orderly. Text must not appear duplicated, garbled, or split. All body font sizes and paragraph spacing remain consistent. Body font size is controlled at 70-100px, and title font size is controlled at 150-220px. The page has no large areas of blank space. By adjusting font size, paragraph spacing, and the relationship of decorative elements, ensure the poster has an orderly rhythm of density and spacing, appropriate hierarchy, a natural reading flow, and a comfortable look. The background is simple and does not affect text reading. It is forbidden to splice multiple pages, grids, or small thumbnails within one image. The copy for this page is: title [title in current page copy], body [body in current page copy]."
Save the generated first inner-page image as [template page].
If after the [template page] is generated, there is still remaining unlaid-out text in [full inner-page copy set], proceed to 5b; otherwise go to Refine.
5b. Subsequent inner pages (apply template)
When a [template page] already exists, the next time an inner page is generated, call meitu-cli:
meitu image-poster-generate \
--skill_name skill_meitu-carousel \
--image_list {模板页 JSON 结果的 downloaded_files[0].saved_path} \
--prompt "{后续内页 prompt,见下方}" \
--ratio "3:4" \
--size "2K" \
--output_format jpeg \
--download-dir {output_dir} \
--json
Subsequent inner page prompt: "Copy the layout, style, font, color, line spacing, alignment, etc. of the [template page], and generate a new inner-page poster with exactly the same visuals. Only replace all text with the current page copy of this page. Text must not appear duplicated, garbled, or split. The page has no large areas of blank space. The poster has an orderly rhythm of density and spacing, appropriate hierarchy, a natural reading flow, and a comfortable look. Do not add page number text such as 'Page 1/Page 2', and do not add extra layouts such as multiple grids or thumbnails. The copy for this page is: title [title in current page copy], body [body in current page copy]."
Each time a page is generated, only display the "current page copy" and do not modify the template structure.
Source of the full inner-page copy set:
- a. All copy provided by the user
- b. All inner page copy generated by the model in Phase 2
Source of the current page's copy: From [the complete set of inner page copy], take in paragraph order the portion of text used for this page's layout, with a total word count <= 300 characters.
If [the complete set of inner page copy] still has remaining text that has not been laid out, execute Phase 5 again to generate the next inner page; otherwise proceed to Refine.
Refine
-
Display all generated results (cover + inner pages) + brief design rationale (why this style/color scheme/layout was chosen)
-
Wait for user feedback and route it by type:
Feedback type Adjustment method Example Dissatisfied with style/color scheme Modify the style description in the cover prompt → regenerate the cover → regenerate the inner pages accordingly "Too plain" "The color scheme doesn't look good" Layout/font size issues Adjust the layout parameters in the inner page prompt (font size, line spacing, alignment) → regenerate only that page "The text is too small" "Too crowded" Copy modification Replace the copy on the corresponding page → regenerate only that page "Change the title to XX" The overall direction is wrong Return to Execute Phase 1 and start over "This is completely not what I want" Need more inner pages User provides copy → return to Execute Phase 5 and continue generating "Add two more pages" Approved Proceed to Deliver "Okay" "Pretty good" -
A maximum of 3 iteration rounds is recommended; after exceeding that, proactively suggest adjusting the direction or splitting the requirements
Deliver
output_dir has already been resolved in Preflight; only renaming is done here.
mv {file} {output_dir}/{date}_{name}.{ext}
Naming example:2026-03-22_cover.jpeg、2026-03-22_inner-1.jpeg、2026-03-22_inner-2.jpeg
If DESIGN.md Iteration Log > 5 entries → compact: keep recent 5, archive older to ./drafts/design-history.md
Record
can_record = false → skip.(can_record = cwd has openclaw.yaml AND $VISUAL exists; if either is missing, it is false) In one-shot mode, feedback is valid only for the current conversation.
Exception: In one-shot mode, if the user repeatedly expresses the same preference → the Agent MAY propose adding $VISUAL/rules/quality.yaml。
In project mode:
-
User approved style → read
$VISUAL/memory/observations/observations.yaml→ scan similar key → merge or append → write back.len(projects) >= 2→ propose promotion (non-blocking) -
User rejected ("Do not XX") → Already in quality data → automatically filter; new rejection + has openclaw.yaml → ask scope → project:
./DESIGN.mdConstraints / universal:$VISUAL/rules/quality.yaml;no openclaw.yaml → current task only -
No feedback → skip.
Full protocol (observation schema, promotion routing, size control) → see references/memory-protocol.md。
Error Degradation
When a meitu-cli call fails, degrade and retry step by step according to the following levels:
| Level | Operation |
|---|---|
| L1 | Remove low-priority decorative descriptions from the prompt (decorative element details, background atmosphere words, color scheme modifiers) |
| L2 | Degrade enum parameter:--size 2K → --size 1K;--output_format keep jpeg |
| L3 | Remove optional input: remove the --image_list reference image and switch to pure text-to-image mode |
| L4 | Minimize to the core elements: keep only the title copy + basic style keywords + --ratio 3:4 |
| L5 | Stop and report an error, showing the user the code and hintin the JSON output, and suggest adjusting the requirements or checking the network/credentials. If error_type is ORDER_REQUIRED → prompt to top up; CREDENTIALS_MISSING → prompt to run meitu config set-ak + meitu config set-sk to configure credentials |
Retry at most 1 time per level; if it fails, move on to the next level. L3 applies only to inner-page generation steps that have --image_list (stages 5a/5b).
Output
The output path is determined by the output_dir resolved by Preflight:
| Mode | Path | Example |
|---|---|---|
Project mode (has openclaw.yaml) |
./output/{date}_{type}.jpeg |
./output/2026-03-22_cover.jpeg |
One-off mode ($VISUAL exists) |
$VISUAL/output/meitu-carousel/{date}_{type}.jpeg |
~/.openclaw/workspace/visual/output/meitu-carousel/2026-03-22_inner-1.jpeg |
File naming rule:{date}_{type}.{ext}, type is cover or inner-{n}(n starts from 1). |