Basic Cohub abilities. Most agents already have these mounted; listed here for reference.
Platform Published by the Neta team.
Official Made by the Neta team.
Verified Reviewed by the Neta team.
Community Shared by a Cohub user. Not reviewed — read SKILL.md before you use it.
animated-sticker-set
Verified@siosan/animated-sticker-set
Use it in Cohub
Paste this into your agent's chat — it fetches the skill and follows it.
Use the skill: animated-sticker-set. Run `npx -y @neta-art/neta-search-cli@latest skills use @siosan/animated-sticker-set --via site` and follow what it prints. Read its complete output, redirecting it to a temporary file first if necessary, and resolve relative paths from the skill directory it prints.
npx -y @neta-art/neta-search-cli@latest skills use @siosan/animated-sticker-set
Summary
Turn one of your characters into a set of 6 to 10 animated chat stickers, each showing a different emotion.
You choose the expressions from a menu of moving previews, such as waving, blushing, nodding, toasting, counting money or pounding the table.
Each sticker is a short looping animation of your character, with a caption already on it, in your language.
Every sticker saves in three forms: a looping GIF, a WeChat-size sticker and a transparent-background version.
You get a sticker page where you can save each one, and a + tile to request another set for the same character.
Works best with a character who has a clear look. The default is soft watercolor, or you can ask for chibi or the character's own art style.
SKILL.md
# Animated sticker set
One character, one sheet, one run: the sheet holds every expression, each expression is cut out on
its own, and each cut drawing becomes the first **and** last frame of a short clip. That single
decision is what makes the whole thing work — the clip starts and ends on the drawn expression, so
the loop closes by construction and the character cannot drift between stickers.
The creator picks the expressions themselves: the set is chosen in one questionnaire round, from a
library of templates that each carry a moving preview.
## Language
Reply in the user's language. Everything the creator sees — the page, the sticker names, the
captions — follows the user's language too. The scripts print English; translate what they print,
don't paste it. This holds for every message of the run, above all the final handover.
## Requirements
- Image and video generation come from the neta platform's `generate` skill. Read
`/mods/neta/.agents/skills/generate/SKILL.md` and `playbooks/image.md` before the first image, and
`playbooks/video.md` before the first video. If `/mods/neta` is missing, say so and stop.
- `<skill-dir>` = the folder this SKILL.md sits in.
- `cut-sheet.py` needs `python3` with numpy and Pillow; `sticker.py` also drives the vendored
cutting tools. Install them once with
`python3 <skill-dir>/scripts/sticker.py tools` — it puts `sprite-gen` (Apache-2.0) and libwebp's
`img2webp` into `/workspace/.cache/sticker-tools`. Use `PYTHONPATH=/workspace/.pylib/3.13` when
Pillow/numpy are not importable.
## Inputs
| Input | Required | Counts as given when |
|---|---|---|
| Character | yes | the message names a character of this world, or carries a selected character card. "My character" or a guess from recent works does not count → ask |
| Which expressions | yes | the user names them ("要搓手和招手"), or answered the picker |
| Look | no (house watercolor) | the user names one: the character's own art style, chibi / Q 版, or a named medium |
| Caption language | no | the user's language; the world's language if they wrote none |
Ask **one** round, only for what is open, through the platform questionnaire — the character, the
look, and the expression picker (see **Templates**). When the message gives the character, the look
and the expressions, build without asking anything.
**Say the cost in one line before the batch**: one video per sticker, on top of one sheet.
## Templates
A template is one emotion, written as a spec in `<skill-dir>/specs/<code>.json`: the action, how
long the clip is, whether it loops (`periodic`) or plays once (`once-return`), the window to cut,
and the prompt. Names and uses per language live in `specs/locales.js`.
**The picker.** `<skill-dir>/specs/previews.json` holds a moving preview per template, made once
with a demo character. The questionnaire shows them as a multi-select of tiles (see
[`references/picker.md`](references/picker.md)): the creator taps the expressions they want, and
that answer is the set.
| Code | Template | Reads as | In the picker |
|---|---|---|---|
| S01 | 搓手 | 等好消息 / 摩拳擦掌 | yes |
| S02 | 招手 | 打招呼 / 我在这 | yes |
| S04 | 害羞 | 不好意思 | yes |
| S05 | 生气 | 不行 / 气到了 | yes |
| S09 | 点头 | 收到 | yes |
| S10 | 摇头 | 别想了 | yes |
| S11 | 举杯 | 干一杯 / 庆祝 | yes |
| S12 | 举牌 | 看这个 / 你看 | yes |
| S14 | 数钱 | 发财了 / 赚到了 | yes |
| S15 | 捶桌 | 气死了 / 我不同意 | yes |
| S16 | 举手机 | 你看 / 快看这个 | yes |
| S13 | 干饭 | 吃吃吃 / 饿了 | no — the bowl's motion does not close the loop yet |
| S03 / S06 / S07 | 小问号 / 好困 / 震惊 | — | no — their symbol breaks the loop; pose-only drafts |
| S08 | 拍桌 | 拍板 | no — one-shot, needs a longer clip than the size budget allows |
**The motion has to come from the body.** A spec that only shakes a head or wiggles a prop reads
as "nothing happens" at 300 px. Every prompt carries a WHOLE BODY clause, and the action text names
what the torso does — lean, rear up, drop, bounce, rock side to side — with a count ("twice"). A
head-only action cannot be rescued by wording: change the action itself.
**A prop is what makes a sticker read.** Templates that only move a head or a paw all look alike:
six of the first batch were 搓手 / 招手 / 害羞 / 生气 / 点头 / 摇头, and on screen they read as
"nodding and swaying". The strong ones carry one object — a cup, a blank sign, a fan of bills, a
table edge, a phone — because the silhouette changes, not just the face. When writing a new spec,
say what the prop is, say it stays in frame for the whole clip (a prop that appears and vanishes
cannot loop), and let the body lean, crouch or bounce; only the background and the first/last frame
have to stay put.
A feeling no template covers: copy the nearest spec, rewrite `action` and `prompt` in the same
voice, mark it unverified, and say so in the reply.
## Deliver
**One page per character**: `<work>/index.html` + `stickers.json` + `stickers/`, published as a web
Work. Each run adds a **set** on top of that page; the page ends its grid with a **+** tile that
prepares the request for one more set, so the creator keeps going from the page. Page UI follows
the creator's language.
Hand over with an interaction-components Work card, a numbered list of the stickers as they came
out (`caption — what it does`), and next-steps. The sheet, the clips and the frame folders stay
ingredients: the working folder keeps `clip.mp4` per sticker and drops the intermediate frames once
a sticker passes.
## Steps
1. **Character, look, expressions.** Read `manifest.json` first. Once the character is given, read
the atom (`node /mods/neta/neta atom get "world/characters/<Name>.md"`). Then run the
questionnaire round for whatever is still open.
2. **Generate the sheet.** Fill
[`references/sheet-prompt.md`](references/sheet-prompt.md): one cell per chosen expression, in
the order of the codes, flat light-blue background, no die-cut outline, **no text in the art**
(the caption is baked into the GIF at export instead).
- **Every sticker is waist-up** — head, chest, arms and hands; never full body, in any look. A
standing figure in a 300 px sticker shrinks the face until the expression no longer reads.
- **Look**: with none named, use the house watercolor style line from the reference (soft
washes, fine ink line, about three heads tall). The creator's named look replaces only the
style line, never the framing.
- Square output: `size` → `1024x1024`; `aspect_ratio` → `1:1`. Nine cells go on a 3×3 sheet,
six on a 3×2.
- Pass the character's cover with `--image`; if the model refuses it for copyright, describe the
character in words instead (features, palette, outfit) and drop the reference — never retry
the same description.
- Submit synchronously with `--work-title` in the user's language.
3. **Cut the sheet.** `python3 <skill-dir>/scripts/cut-sheet.py "<sheet>" "<work>/cells" --grid 3x3
--names <code,code,…>`. Exit 0 means every cell is clean; a `touching` cell crossed into its
neighbour — rework the sheet once. Open `cells/preview.png` and check the same character with one
readable pose per cell, every cell waist-up (a cell showing legs or feet → rework the sheet
once), before spending a single video.
4. **Animate the set.** One command submits every clip, waits, cuts each to its own loop, bakes the
caption and exports the three formats:
```bash
PYTHONPATH=/workspace/.pylib/3.13 python3 <skill-dir>/scripts/set.py \
--cells "<work>/cells" --work "<work>" --codes S01,S04,S09,S10 \
--captions "<work>/captions.json" --lang <code> --jobs 4
```
`captions.json` is `{"S01": "搓搓手,等好消息", …}`. A clip already on disk is not generated
again; a failed clip is resubmitted alone (`--codes <code> --force`), never the whole batch.
5. **Look at every sticker.** The machine verdict first, then the pictures:
```bash
PYTHONPATH=/workspace/.pylib/3.13 python3 -c "import json,glob;[print(f, json.load(open(f))['ok'], json.load(open(f))['loopSeconds'], json.load(open(f))['keyFringePx']) for f in sorted(glob.glob('<work>/*/*/qa.json'))]"
```
`ok: true` needs key fringe ≤ 20 px, loop ≥ 1.2 s, and the sizes within budget (300 GIF ≤ 600 KB,
WeChat 240 ≤ 500 KB, WebP 240 ≤ 400 KB); `sticker.py cut` writes that to
`<work>/<code>/<code>/qa.json`. Then open each `qa-frames.png` and read it as motion: the action
is the template's, it is complete, the first frame meets the last, the character did not change,
no limb broke. One miss gets one resubmit of that clip; after that the set goes on with what is
best and the reply names what is still off. If a clip cannot be produced at all (blocked twice,
or the model is down), that one sticker ships as its cut still and the reply says so — the set
stays animated.
6. **Build the page.** Turn the finished set into the page:
```bash
python3 <skill-dir>/scripts/build-page.py --work "<work>/page" \
--title "<Name> · <set name>" --subtitle "<world>" --lang <code> --character "<Name>" \
--set-name set-01 --style "<look>" --items "<work>/items.json"
```
`items.json` is one entry per sticker (`code`, `gif`, `wechat`, `webp`, `caption`,
`captionInArt`, `loopSeconds`) — write it from the set's `set.json`. Re-running with `--append`
keeps the sets already on the page and puts the new one on top.
7. **Publish and place.**
```bash
node /mods/neta/neta work init web "<work>/page" --title "<Name> · <set name>"
node /mods/neta/neta work publish web "<work>/page"
node /mods/neta/.agents/skills/board-ops/scripts/place.mjs --title "<Name> · <set name>" --work "<work>/page"
```
`world_slug_required` → set a readable slug from the world's name and publish again. If it still
fails, do not fake a page: hand over the files and say the page did not publish.
8. **Reply and close.** Hand over the set with an interaction-components Work card whose target is
the Work (`jq -r .cohubWorkId "<work>/page/meta.json"`), then list the stickers as
`caption — what it is doing`, in the order they appear, so the creator can ask to change one by
number. Describe what the frame strips show. Then close with **next-steps**.
## Changing one sticker later
"Change number 2", "make the angry one angrier": edit that template's `action`/`prompt` for this
run, resubmit that one clip (`--codes <code> --force`), cut it again, rebuild the page with
`--append` using the same set name, and publish the same Work. Never hand-edit a frame or the
manifest.
## If generation is blocked
The video model moderates both the prompt and the frame image.
1. Neutralise the words — describe the action, not the character; no franchise names.
2. Neutralise the frame — if the base drawing itself is the problem, stop: that character cannot be
drawn here, so say so instead of burning clips.
3. A blocked clip costs nothing but costs minutes: at most two attempts per sticker, then report it
as blocked and finish the rest. Seven of eight delivered is a delivery, with the missing one
named.
## Out of scope
- No changes to the world's settings or `WORLD.md` visual style, and no edits to character cards or
their covers; a set only adds its own works.
- No deleting or overwriting files that existed before the run — a rework overwrites only that
run's own `<work>/` folders.
- No uploading to WeChat / LINE / Telegram sticker stores; no sets of real people.
- No still-only sticker series: this skill always animates. A still is only used as a single
sticker's fallback when its clip cannot be generated (SKILL.md step 5), never as the format of a
whole set.
## Not this skill
- One picture of the character → `generate`. A design sheet → `character-design-sheet`.
- A game sprite sheet, walk/run cycles, engine atlases → the sprite skills.
- A chat-roleplay with a character → `create-roleplay`.
## Gotchas
- The first gate run (56a09ef) drew Nemona and Luna as tiny full-body standing figures — the face
a few pixels wide at 300 px — while the Toge column, drawn waist-up in soft watercolor, read
clearly. Waist-up is now fixed in the sheet prompt and every template's start pose, and that
watercolor look is the default when the creator names none.