Install
openclaw skills install @wufei-png/animated-sticker-makerMake one transparent animated sticker package from one static reference image and one natural-language motion prompt. Use only when the user explicitly names or invokes animated-sticker-maker (for example, $animated-sticker-maker on hosts with dollar-sign invocation); do not trigger for ordinary image, GIF, animation, or multi-sticker pack requests.
openclaw skills install @wufei-png/animated-sticker-makerTurn one reference image and one motion prompt into a short, transparent animated sticker. Derive the identity lock, motion plan, working background, frame timing, validation plan, and export settings internally; do not require the user to supply them.
Resolve every script and reference path against the directory containing this SKILL.md.
Require only:
reference_image: one static image containing a clear primary subject.prompt: natural language describing the intended expression, action, text, loop, or target platform.Support people, pets, mascots, illustrations, objects, and logos. If the image has multiple plausible subjects and the prompt does not identify one, ask once before generating. Do not promise stable multi-subject acting, scene animation, or camera motion in v1.
Produce one sticker per invocation. For a multi-sticker series, keep the shared identity specification, pack ordering, naming, and release-level brand assets in the owning project, then invoke this Skill separately for each sticker that needs its workflow. Do not turn project-specific pack orchestration into a generic Skill feature.
This is one Agent Skills package for hosts that support the standard; do not maintain a second host-specific instruction format. The host must provide a reference-conditioned raster generation or editing capability that can preserve the subject's identity. Use the host-native capability and fail before generation with a clear capability message when none is available. agents/openai.yaml is optional OpenAI UI and invocation metadata, not part of the workflow contract.
Use Python 3.10 or newer plus the packages in requirements.txt for deterministic processing. Do not make OpenCV a required dependency.
Create this structure unless the prompt explicitly overrides it:
output/<name>/
├── sticker.webp
├── source/
│ ├── frames/
│ │ ├── 000.png
│ │ └── ...
│ ├── rendered-frames/ # optional validated high-frame track
│ ├── reference.json # basename, hash, and image metadata
│ └── motion.json
├── validation/
│ ├── contact-sheet.png
│ └── report.json
└── exports/ # only when a platform or extra format is requested
└── <platform>/
Use 1024×1024 RGBA for continuous-tone, illustrated, or generated raster sources. For native pixel art or another strict low-resolution grid, preserve the logical source canvas and set motion.resampling to nearest; do not force it through a non-integer 1024×1024 redraw. Use 4–8 unique frames, per-frame durations, a total duration of about 1.2–2.0 seconds, and a 400–700 ms hold on the clearest semantic frame. Loop by default. Do not create preview.gif unless requested or required by the target platform.
Inspect the reference at full size and small-icon size. Record the subject, signature silhouette, palette, material, facial or functional anchors, fixed marks, and forbidden drift. Separate identity features from incidental background details.
Complete this step only when every visible feature that makes the subject recognizable is classified as fixed, flexible, or removable.
Read references/motion-plan.md. Convert the prompt into one primary semantic beat, a small set of anchor poses, deterministic transitions, exact text layers, frame durations, and loop behavior. Write the plan before producing final frames.
Use generation only for genuinely new poses, occlusion, or organic deformation. Use deterministic transforms for translation, scale, opacity, brightness, exact text, simple effects, timing, and packaging.
Complete this step only when each frame has one purpose and every requested semantic element appears in the plan.
Choose motion.resampling deliberately: lanczos for continuous-tone or illustrated raster work, and nearest for native pixel art and other hard grid-bound artwork.
Read the host's raster generation or editing instructions before generating. Always include the original reference when asking for a new anchor. Ask for a front-facing, isolated subject on either transparency or a flat high-distance work color. Generate the fewest anchors needed.
Inspect every anchor immediately against the identity lock. Reject identity drift before building temporal frames; do not hope that animation will hide it. Pause for user confirmation only when a choice changes the subject's identity or the requested meaning, not for routine numeric tuning.
If a generated anchor preserves one clean local expression or prop but drifts as a whole, reject it as a full anchor. You may salvage only that isolated component onto an approved identity-stable anchor when its boundary can be extracted without seams or duplicate features. Record the rejected source as a component source, the extraction rule, and the approved base anchor in the motion plan; never relabel the rejected full image as approved.
Complete this step only when all full-frame anchors are individually usable and every salvaged component has an approved base, a bounded role, and a deterministic extraction method.
If an anchor already has correct alpha, preserve it. Otherwise read references/transparency.md, choose a work color far from the subject palette, and run scripts/chroma_key.py. Keep shadows separate when the prompt or platform needs independent shadow control.
Complete this step only when the subject has no opaque background, color spill, bright fringe, clipped protrusion, or canvas-edge contact.
Create one RGBA PNG per unique frame. Preserve the subject's aspect ratio unless the motion explicitly calls for deformation. Keep exact text in deterministic layers so spelling, placement, and timing remain controlled. Favor anticipation, one clear semantic hold, and a short recovery over evenly timed motion.
When a companion object presses, sits on, or touches the subject, align it against the local silhouette beneath its footprint. Do not infer contact from the subject's global bounding-box edge when the surface is curved, notched, or deformed.
Complete this step only when the sequence reads correctly without filenames or explanation and the loop has no unintended jump.
Run:
python <skill-dir>/scripts/package_sticker.py \
--frames-dir <working-frames> \
--motion <motion.json> \
--reference-image <reference-image> \
--output <output/name>
Pass --expected-size <WIDTHxHEIGHT> when the internally derived source canvas differs from 1024x1024. Use --include-reference only when the user wants the original image embedded; the default package records its basename, hash, dimensions, mode, format, and byte size without copying it. Use the nonstandard timing or frame-count flags only when the user's prompt explicitly overrides the defaults. Do not continue to platform export when technical validation fails.
Complete this step only when sticker.webp, copied source frames, motion.json, reference.json, the contact sheet, and the technical report all exist and technical validation passes.
Packaging validates the core motion schema, rewrites copied keyframes as real PNG files at canonical frames/000.png, frames/001.png, and so on, and rewrites matching semantic-hold references with them. Treat the packaged source/motion.json as the self-contained source of truth; do not retain paths that only resolve in the working directory.
The packager re-opens sticker.webp to verify its format, canvas, frame count, loop setting, and transparency. Native pixel-art packages use lossless WebP encoding. The generated report binds the normalized motion, reference metadata, source frames, and encoded WebP with an artifact fingerprint; any later change invalidates the recorded visual validation.
Packaging is transactional. It builds and validates a candidate in a sibling staging directory, replaces the existing usable package only after technical validation succeeds, and writes the latest technically failed candidate to <output>.failed/. A successful replacement removes that failed candidate. A declared semantic_hold_frame must name exactly one authored keyframe.
When motion.render is present, the packager reads its relative working frame_dir, validates its numeric target_fps, frame count, durations, canvas, Alpha, and visibility, then normalizes the track into source/rendered-frames/ with its own validation/render-report.json. rendered-frames/ is an internal artifact directory, not a public CLI parameter.
Every successful repack creates new validation reports with visual validation pending. Re-run visual validation after every repack; never preserve a prior pass across changed artifacts.
Read references/validation.md. Inspect the animation, contact sheet, semantic hold, Alpha edges on light and dark backgrounds, and the subject at small-icon size. This is maker-side validation, not an approval workflow or separate reviewer role. Record the result in validation/report.json; scripted checks do not replace visual inspection.
Record the decision with:
python <skill-dir>/scripts/record_visual_validation.py <output/name/validation/report.json> \
--status pass \
--identity "..." --meaning "..." --loop "..." --alpha "..." --small-size "..."
If a platform is requested, read references/platform-exports.md, verify current official constraints, and write only derived files beneath exports/<platform>/. Do not resize or recompress the platform-neutral sources.
For a platform that accepts animated GIF, export from the validated package instead of the WebP:
python <skill-dir>/scripts/export_platform_gif.py \
--package <output/name> \
--platform <platform> \
--size <WIDTHxHEIGHT> \
--max-bytes <limit> \
--preview-output <derived-preview.png> \
--preview-max-bytes <preview-limit> \
--spec-url <official-url> \
--verified-on <YYYY-MM-DD>
The exporter requires technical_validation, visual_validation, and deliverable_ready to pass. A top-level status: pass alone is insufficient. It preserves source timing, applies the resampling policy recorded in motion.json, uses one shared GIF palette to reduce frame-to-frame color shimmer, chooses the highest tested color count that meets the byte limit, and records source validation, export parameters, and hashes. Omit preview arguments when the platform does not require one. --spec-url and --verified-on are mandatory provenance. Use --allow-unvalidated only for explicit diagnostics; its report is marked diagnostic_unvalidated and cannot become deliverable. If no palette candidate fits, change size, timing, or frame count only through an explicit validated decision; do not silently degrade the semantic hold.
Every normal export starts at pending_visual_validation, even when its source package and technical constraints pass. Inspect the actual GIF and preview, then record visual validation against the generated report with the same record_visual_validation.py command. The report sets deliverable_ready: true only while its fingerprint still matches those export files.
Keep authored keyframes as the default export track. When a platform benefits materially from smoother motion and the package contains a deterministic high-frame track declared by motion.render, export that track explicitly:
python <skill-dir>/scripts/export_platform_gif.py \
--package <output/name> \
--platform <platform> \
--size <WIDTHxHEIGHT> \
--max-bytes <limit> \
--frame-track render \
--track-report <output/name/validation/render-report.json> \
--fps-candidates 30,24,20,15 \
--min-colors 64
The render track needs its own passed technical and visual validation because it is a separate temporal artifact. motion.render.target_fps is the user-facing numeric generation target. --fps-candidates is an export fallback policy: the exporter searches palette sizes down to --min-colors at the preferred frame rate, then tries the next candidate. Do not create or select this track silently, and do not put subject-specific frame rates, palette floors, or platform limits into the generic Skill.
Complete the task only when the package and every requested export have passed both validation types and report deliverable_ready: true.
Ask the user only when a missing choice changes the intended subject, meaning, or irreversible public output. Make safe project-level adjustments to timing, position, scale, color-key thresholds, and compression without interrupting the run.