Watercolor Animation Generator

Painted animation

by edenfunf · MIT license · ★ 3,630 on GitHub

Painted animation cover

Make hand-painted watercolour-and-ink cartoon videos (MP4) with code — p5.js + p5.brush rendered frame by frame in headless Chrome, encoded with ffmpeg — starring Clawd or any character. Use when the user asks to make an animation,…

---
name: painted-animation
description: Make hand-painted watercolour-and-ink cartoon videos (MP4) with code — p5.js + p5.brush rendered frame by frame in headless Chrome, encoded with ffmpeg — starring Clawd or any character. Use when the user asks to make an animation, animated short, cartoon, music video, lyric video, animated GIF/loop or "a video of Clawd…", or mentions the PDoomVideo / ClaudeAnimationBase approach. Covers storyboarding, the engine API, the render-and-look review loop, music/lyric sync and splitting long videos across subagents.
---

# Painted animation

A method for making short cartoons entirely in code, distilled from [JohnHeibel/PDoomVideo](https://github.com/JohnHeibel/PDoomVideo) (a 156 s music video painted by Claude Opus) and its generalised kit [ClaudeAnimationBase](https://github.com/JohnHeibel/ClaudeAnimationBase) (MIT), which is bundled here as `template/`.

**How it works:** every frame is a pure function of time `t`. `studio.html` loads p5.js + p5.brush and your scene files; each shot paints the whole 1920×1080 frame with watercolour fills and boiling ink lines. `render.mjs` drives headless Chrome to render contact sheets for review, or every frame in parallel, and ffmpeg encodes the MP4 (with audio if given).

## Workflow

### 0. Scaffold

```bash
bash .claude/skills/painted-animation/scripts/new_project.sh <project-dir>        # add --keep-demo to keep the example scene hooked up
```

Overview

A method for making short cartoons entirely in code, distilled from JohnHeibel/PDoomVideo (a 156 s music video painted by Claude Opus) and its generalised kit ClaudeAnimationBase (MIT), which is bundled here as template/.

Manual install (npx, ZIP)
Claude Codenpx skills add edenfunf/reelmimic --skill painted-animation -g -a claude-code
Claude Code (degit)npx degit edenfunf/reelmimic/.claude/skills/painted-animation#main ~/.claude/skills/painted-animation
Claude.ai / desktopZip the folder and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md7.4 KB
Read SKILL.md here
edenfunf/main1 file shown
SKILL.md
Show the full text86 lines

Painted animation

A method for making short cartoons entirely in code, distilled from JohnHeibel/PDoomVideo (a 156 s music video painted by Claude Opus) and its generalised kit ClaudeAnimationBase (MIT), which is bundled here as template/.

How it works: every frame is a pure function of time t. studio.html loads p5.js + p5.brush and your scene files; each shot paints the whole 1920×1080 frame with watercolour fills and boiling ink lines. render.mjs drives headless Chrome to render contact sheets for review, or every frame in parallel, and ffmpeg encodes the MP4 (with audio if given).

Workflow

0. Scaffold
bash .claude/skills/painted-animation/scripts/new_project.sh <project-dir>        # add --keep-demo to keep the example scene hooked up

This copies the template, unhooks the demo scene, runs npm install and checks node / ffmpeg / Chrome. Then read <project-dir>/ANIMATION_GUIDE.md in full before designing anything: it holds the rules, the animation principles and the complete engine / Clawd API. Look at docs/emotions.jpg and docs/views.jpg (the model sheets) with the Read tool.

For a music video or anything longer than ~20 s, also read references/music-video.md. For a lyric video, ask for the song file and an LRC first, and measure the tempo with scripts/beat_grid.py: lines are usually faster than you'd guess.

1. Storyboard before code

Write STORYBOARD.md in the project (format in the guide: logline, world + palette arc, motif, the character's emotion arc, then shots with reads — the timed list of what the viewer must understand). Worked example: examples/xiaozhen/ (a 31 s lyric video: storyboard and full scene code).

Show the storyboard to the user and let them react before building, unless they said to just go ahead.

2. Build shot by shot
  • Set duration, bpm, offset (and audio) in src/config.js.
  • One IIFE-wrapped file per scene/chapter in src/scenes/, ending with shots([[t0, fn], ...]); add its <script> to studio.html.
  • Block key poses first, check them as stills, then add the motion between them.
3. Render and look — every shot, several times

You can't see motion by reading code. From the project dir:

node render.mjs --sheet=0.1,0.8,1.6,2.4 --cols=4 --w=480 --out=out/check/a.jpg        # key frames
node render.mjs --strip=2.1:2.6 --out=out/check/strip.jpg                             # every frame of a moment
node render.mjs --sheet=2.3 --crop=760,420,500,400 --w=500 --out=out/check/face.jpg   # full-res detail

Open each image with Read and actually check it against the guide's review list: event clear? character big enough? reads timed so a first-time viewer gets them? anticipation / follow-through, no snaps? feet and held props touching? transitions at every seam? no text, no 3D, no pure black/white, no muddy glows? Fix and look again. Budget: ≥ 1 sheet per shot, a strip per key motion and transition, a crop per story-carrying face.

4. Render the video
node render.mjs --clip --out=out/video.mp4                                   # short videos, one worker
node render.mjs --frames --workers=4 && node render.mjs --encode --out=out/video.mp4 [--audio=assets/song.mp3]   # long ones, parallel + resumable

Report the output path, length and ms/frame. Offer open out/video.mp4.

The rules that matter most

These are the guide's rules condensed; the guide is authoritative.

  1. Handmade medium. Only paint() / inkLine() (p5.brush) — never plain p5 rect/ellipse/fill. Flat 2D only: turns go through drawn key views (turn(), spinView()), never 3D projection. Light via glow() (additive), because pigment-mixing makes yellow-over-blue go green.
  2. No text. No captions, labels, signs or word bubbles; show it instead. Reactions are painted emotes (!, sweat, hearts…). The one exception is karaoke in a lyric video, and at most a few big SFX.
  3. Something happens in every shot — an event, cause → reaction, set-ups that pay off.
  4. Time for the viewer. List each shot's reads; one read at a time; fast actions, held meanings; lead the eye; the reads set the shot length. This is where generated animation fails most.
  5. Alive. Nothing is still (idles from feel(), drifting cameras, boil); faces change through emotions() never by swapping; the character is big (medium shot u≈20–28, close-up 40–70); everything rides the beat.
  6. Transitions at every seam, chosen to fit the story (brush wipe, iris / shaped iris, whip pan, match cut, cut on action, camera carry-through).
  7. One piece. One world, a colour arc, an emotional thread, linked scenes, an ending that rhymes with the opening.

Engine gotchas

  • Pure functions of t. Frames render in parallel and out of order: no state across frames, no Math.random(), no frame-by-frame physics. hash(i) for stable randomness, jit() for boil.
  • boilSeed(key) before each separate background element/prop, or a moving thing makes everything drawn after it re-boil every frame (jitter).
  • Don't name globals after p5's. p5 defines line, OVERLAY, text, color, scale, … as globals; a top-level function line() fails with Cannot redefine property and the page never becomes ready (the renderer times out). Keep helpers inside the scene IIFE or give them distinct names.
  • Layering in doorways, windows and screens: draw what's inside, then paint the surrounding wall/frame back over it, so nothing wider than the opening shows outside it (the train's inDoor + door jambs, the TV bezel pieces).
  • A NaN in a point list throws Failed to construct 'OffscreenCanvas' — guard degenerate geometry.
  • Under camera zoom ≳ 2, huge shapes lose outlines; outline weight scales with zoom, so scale sw down in close-ups.
  • Cost = number of fills and strokes. Aim for ≤ ~1.5–2.5 s/frame (the log prints ms/frame). Prefer fewer, bigger shapes. On machines without a real GPU, watercolour fills are slow — consider fewer fill shapes, or --soft-gl as a last resort.
  • macOS: the renderer uses --use-angle=metal and finds /Applications/Google Chrome.app automatically; otherwise pass --chrome=<path>.

Adapting

  • Clawd is the default star, not a requirement. New characters, props and emotions are drawn with the same tools (paint, ribbon, through, glow) and kept on-model across shots; new emotions go in EMO in src/clawd.js.
  • src/karaoke.js (template) adds word-by-word karaoke for lyric videos via the window.overlayHook hook in core.js.
  • LOOPS.name = t => {...}; LOOPS.name.len = 4; + node render.mjs --loop=name --png makes a seamless loop for GIFs (ffmpeg -i out/loop_name/f%04d.png …).
  • Higher reasoning effort tends to give more extravagant, detailed scenes.
1---
2name: painted-animation
3description: Make hand-painted watercolour-and-ink cartoon videos (MP4) with code — p5.js + p5.brush rendered frame by frame in headless Chrome, encoded with ffmpeg — starring Clawd or any character. Use when the user asks to make an animation, animated short, cartoon, music video, lyric video, animated GIF/loop or "a video of Clawd…", or mentions the PDoomVideo / ClaudeAnimationBase approach. Covers storyboarding, the engine API, the render-and-look review loop, music/lyric sync and splitting long videos across subagents.
4---
5 
6# Painted animation
7 
8A method for making short cartoons entirely in code, distilled from [JohnHeibel/PDoomVideo](https://github.com/JohnHeibel/PDoomVideo) (a 156 s music video painted by Claude Opus) and its generalised kit [ClaudeAnimationBase](https://github.com/JohnHeibel/ClaudeAnimationBase) (MIT), which is bundled here as `template/`.
9 
10**How it works:** every frame is a pure function of time `t`. `studio.html` loads p5.js + p5.brush and your scene files; each shot paints the whole 1920×1080 frame with watercolour fills and boiling ink lines. `render.mjs` drives headless Chrome to render contact sheets for review, or every frame in parallel, and ffmpeg encodes the MP4 (with audio if given).
11 
12## Workflow
13 
14### 0. Scaffold
15 
16```bash
17bash .claude/skills/painted-animation/scripts/new_project.sh <project-dir> # add --keep-demo to keep the example scene hooked up
18```
19 
20This copies the template, unhooks the demo scene, runs `npm install` and checks node / ffmpeg / Chrome. Then **read `<project-dir>/ANIMATION_GUIDE.md` in full** before designing anything: it holds the rules, the animation principles and the complete engine / Clawd API. Look at `docs/emotions.jpg` and `docs/views.jpg` (the model sheets) with the Read tool.
21 
22For a music video or anything longer than ~20 s, also read [references/music-video.md](references/music-video.md). For a lyric video, ask for the song file and an LRC first, and measure the tempo with `scripts/beat_grid.py`: lines are usually faster than you'd guess.
23 
24### 1. Storyboard before code
25 
26Write `STORYBOARD.md` in the project (format in the guide: logline, world + palette arc, motif, the character's emotion arc, then shots with **reads** — the timed list of what the viewer must understand). Worked example: [examples/xiaozhen/](examples/xiaozhen/) (a 31 s lyric video: storyboard and full scene code).
27 
28Show the storyboard to the user and let them react before building, unless they said to just go ahead.
29 
30### 2. Build shot by shot
31 
32- Set `duration`, `bpm`, `offset` (and `audio`) in `src/config.js`.
33- One IIFE-wrapped file per scene/chapter in `src/scenes/`, ending with `shots([[t0, fn], ...])`; add its `<script>` to `studio.html`.
34- Block key poses first, check them as stills, then add the motion between them.
35 
36### 3. Render and look — every shot, several times
37 
38You can't see motion by reading code. From the project dir:
39 
40```bash
41node render.mjs --sheet=0.1,0.8,1.6,2.4 --cols=4 --w=480 --out=out/check/a.jpg # key frames
42node render.mjs --strip=2.1:2.6 --out=out/check/strip.jpg # every frame of a moment
43node render.mjs --sheet=2.3 --crop=760,420,500,400 --w=500 --out=out/check/face.jpg # full-res detail
44```
45 
46Open each image with Read and actually check it against the guide's review list: event clear? character big enough? reads timed so a first-time viewer gets them? anticipation / follow-through, no snaps? feet and held props touching? transitions at every seam? no text, no 3D, no pure black/white, no muddy glows? Fix and look again. Budget: ≥ 1 sheet per shot, a strip per key motion and transition, a crop per story-carrying face.
47 
48### 4. Render the video
49 
50```bash
51node render.mjs --clip --out=out/video.mp4 # short videos, one worker
52node render.mjs --frames --workers=4 && node render.mjs --encode --out=out/video.mp4 [--audio=assets/song.mp3] # long ones, parallel + resumable
53```
54 
55Report the output path, length and ms/frame. Offer `open out/video.mp4`.
56 
57## The rules that matter most
58 
59These are the guide's rules condensed; the guide is authoritative.
60 
611. **Handmade medium.** Only `paint()` / `inkLine()` (p5.brush) — never plain p5 `rect`/`ellipse`/`fill`. Flat 2D only: turns go through drawn key views (`turn()`, `spinView()`), never 3D projection. Light via `glow()` (additive), because pigment-mixing makes yellow-over-blue go green.
622. **No text.** No captions, labels, signs or word bubbles; show it instead. Reactions are painted emotes (`!`, sweat, hearts…). The one exception is karaoke in a lyric video, and at most a few big SFX.
633. **Something happens in every shot** — an event, cause → reaction, set-ups that pay off.
644. **Time for the viewer.** List each shot's reads; one read at a time; fast actions, held meanings; lead the eye; the reads set the shot length. This is where generated animation fails most.
655. **Alive.** Nothing is still (idles from `feel()`, drifting cameras, boil); faces change through `emotions()` never by swapping; the character is big (medium shot u≈20–28, close-up 40–70); everything rides the beat.
666. **Transitions at every seam**, chosen to fit the story (brush wipe, iris / shaped iris, whip pan, match cut, cut on action, camera carry-through).
677. **One piece.** One world, a colour arc, an emotional thread, linked scenes, an ending that rhymes with the opening.
68 
69## Engine gotchas
70 
71- **Pure functions of `t`.** Frames render in parallel and out of order: no state across frames, no `Math.random()`, no frame-by-frame physics. `hash(i)` for stable randomness, `jit()` for boil.
72- **`boilSeed(key)`** before each separate background element/prop, or a moving thing makes everything drawn after it re-boil every frame (jitter).
73- **Don't name globals after p5's.** p5 defines `line`, `OVERLAY`, `text`, `color`, `scale`, … as globals; a top-level `function line()` fails with `Cannot redefine property` and the page never becomes ready (the renderer times out). Keep helpers inside the scene IIFE or give them distinct names.
74- **Layering in doorways, windows and screens:** draw what's inside, then paint the surrounding wall/frame back over it, so nothing wider than the opening shows outside it (the train's `inDoor` + door jambs, the TV bezel pieces).
75- A `NaN` in a point list throws `Failed to construct 'OffscreenCanvas'` — guard degenerate geometry.
76- Under camera zoom ≳ 2, huge shapes lose outlines; outline weight scales with zoom, so scale `sw` down in close-ups.
77- Cost = number of fills and strokes. Aim for ≤ ~1.5–2.5 s/frame (the log prints ms/frame). Prefer fewer, bigger shapes. On machines without a real GPU, watercolour fills are slow — consider fewer `fill` shapes, or `--soft-gl` as a last resort.
78- macOS: the renderer uses `--use-angle=metal` and finds `/Applications/Google Chrome.app` automatically; otherwise pass `--chrome=<path>`.
79 
80## Adapting
81 
82- Clawd is the default star, not a requirement. New characters, props and emotions are drawn with the same tools (`paint`, `ribbon`, `through`, `glow`) and kept on-model across shots; new emotions go in `EMO` in `src/clawd.js`.
83- `src/karaoke.js` (template) adds word-by-word karaoke for lyric videos via the `window.overlayHook` hook in `core.js`.
84- `LOOPS.name = t => {...}; LOOPS.name.len = 4;` + `node render.mjs --loop=name --png` makes a seamless loop for GIFs (`ffmpeg -i out/loop_name/f%04d.png …`).
85- Higher reasoning effort tends to give more extravagant, detailed scenes.
86 
View all files on GitHub →

Details

License
MIT
Stars on the repo
★ 3,630
Checked
Source
edenfunf/reelmimic ↗
Creator
edenfunf · 6 listings
View creator

Similar skills

See all →
SkillMotion Effect Glossaryemilkowalski/skills · by emilkowalskiReverse-lookup glossary that turns a vague description of a web animation or motion effect into its exact term ("the bouncy thing when a popover opens" → Pop in; "the iOS rubber-band scroll" → Rubber-banding). Use when the user asks "what's it called when…", or describes a motion effect without knowing its name and wants the right word to prompt an AI or designer with. For naming an effect, not designing or building one.★ 40.8k GitHub starsSkillModern Web ReferenceGoogleChrome/modern-web-guidance · by GoogleChromeSearch tool for modern web development best practices. MANDATORY: Execute FIRST for all HTML/CSS and clientside JS tasks. Do NOT skip — web APIs evolve rapidly and training weights contain obsolete patterns. Trigger immediately for: - UI/Layout: Modals, dialogs, popovers, Glassmorphism/backdrop-filters, anchor positioning, container queries, `:has()`, `:user-valid`. - Scroll/Motion: View Transitions, Scroll-driven animations, scroll parallax/reveals. - Performance: CWV (LCP, INP), content-visibility, Fetch Priority, image optimization. - System/APIs: Local filesystem access, WebUSB, WebSockets sync, WebAssembly widgets. - Frameworks: Adapting layout/styles in React, Vue, Angular. - General Frontend: Forms, autofill, advanced inputs, custom scrollbars, modern component states, etc. DO NOT trigger for: - Backend: Database SQL, ORMs, Express API routes. - Pipelines: CI/CD deployment, Docker, Actions. - Generic: Local scripts (Python/Go tools), ESLint, Git.★ 2.4k GitHub starsSkillMotion Graphics Translatorapenasdouglas/ai-motion-library · by apenasdouglasTraduz pedidos de animação em português ("faz o número quicar", "entra um depois do outro", "dá um tranco no zoom") para o efeito de motion graphics certo, com o termo técnico, a duração e a aceleração. Use sempre que o usuário pedir animação, motion, transição ou efeito em vídeo, HTML, CSS, GSAP, Remotion, HyperFrames ou After Effects, principalmente quando o pedido for vago ("faz uma animação bonita") ou o vídeo for de canal dark (faceless) de curiosidades, história ou documentário. Also triggers on English requests for motion graphics, easing and animation effects in documentary or faceless YouTube videos.★ 68 GitHub starsSkillBrowser Automation ToolAndyShiu/claude-skill-playwright-browser · by AndyShiuHeadless, reproducible browser automation with Playwright for any project — screenshots of web pages or local dev servers (desktop/tablet/mobile, full page or one element, single page or every page/menu of an app in one batch), frontend audits (console errors, failed requests, broken images/links, responsive overflow, axe accessibility, LCP/CLS performance), before/after visual comparison, scripted E2E flows (log in, click, fill, page through, assert), and logged-in pages via saved sessions. Use this whenever the user wants to screenshot or visually check a site, find frontend bugs, see how a page looks on mobile, compare the UI before and after a CSS/code change, reproduce a bug from an issue or ticket and capture evidence images for it, verify a UI flow works, or run/write a browser test — even if they never say "Playwright" or "browser". If Claude in Chrome could also do the job, briefly ask which to use (with a recommendation) instead of silently picking.★ 49 GitHub starsSkillComponent Rebuilderalbertirgi/replica · by albertirgiRebuild a web page, section, component or interaction from a reference (a live URL, a local HTML file, a screenshot or design export, or a screen recording or GIF) inside the user's own codebase. Then measure the rebuild against the reference (element boxes, computed styles, pixels, motion timing and easing) and iterate until a numeric Replica Score passes. Use when the user wants to clone, replicate, recreate, copy, port or match a site, landing page, hero, navbar, pricing table, card, modal, footer, hover effect, scroll reveal, page-load animation or any other UI, or to "make it look/feel/move like" one. Also use when they say "pixel-perfect", "1:1", "exactly like this" or "same as <url>", or hand over a screenshot, Figma export or video and ask to build it, including when they want their own copy, brand or extra features on top.★ 43 GitHub starsSkillProfessional Site Builderbyensitmagnus/sitesmith · by byensitmagnusDesign, build, redesign, audit and polish websites and web apps that do not look AI-generated. Use for landing pages, marketing sites, product and e-commerce pages, SaaS sites, dashboards, web apps, local business sites, portfolios and editorial sites, and for improving existing React, Next.js, Astro, Vue, Tailwind, shadcn or plain HTML/CSS projects. Triggers on: build a website, make a landing page, design a page, redesign this, make it look better, fix the design, improve the UI, this looks generic, choose colours or fonts, pick a style, add animations, make it responsive, add dark mode, accessibility pass, hero section, pricing table, dashboard layout, product page, component styling, design system, design review, UI audit.New listing

More from edenfunf

SkillCel-Shaded Video Creatoredenfunf/reelmimic · by edenfunfMake Japanese TV-anime style videos (MP4) with code — cel-shaded characters with tapered line art, big detailed eyes, hair clumps with a specular band, comedic anime reactions (sweat drop, anger vein, sparkle eyes, ≥< eyes, dot eyes, tears), painted skies with cumulus clouds, school/street/classroom/rooftop sets with time-of-day palettes, speed/focus lines, impact frames, dramatic zooms, smears, sakura petals and anime subtitles (CJK). Canvas 2D rendered frame by frame in headless Chrome, encoded with ffmpeg. Use when a reference video or brief calls for anime / 動畫 / 日系動畫 / アニメ / cel-shaded / slice-of-life / school romance / shōnen-style reactions, or when the video-clone router picks the anime-cel style. 2D only; characters are original (Hina, Ren) or new ones built on the same rig.★ 3.6k GitHub starsSkillCrayon Picture Book Animatoredenfunf/reelmimic · by edenfunfMake warm children's picture-book animations (MP4) drawn in crayon, coloured pencil and pastel on cream drawing paper — waxy crayon scribble fills broken by paper tooth, coloured-pencil outlines, slow 8 fps line boil, page-turn transitions, picture-book page framing and hand-lettered CJK storybook captions. p5.js + p5.brush rendered frame by frame in headless Chrome, encoded with ffmpeg. Use when a reference video or brief calls for a crayon / colored-pencil / pastel / kids' drawing / picture-book / bedtime-story / 繪本 / 蠟筆 / 色鉛筆 / 童書 look, or when the video-clone router picks the crayon-storybook style.★ 3.6k GitHub starsSkillPaper Cutout Animation Makeredenfunf/reelmimic · by edenfunfMake paper cut-out / stop-motion style animated videos (MP4) with code — handmade construction paper, cardstock, kraft, felt and tissue pieces with scissor-cut or torn edges and soft drop shadows, photographed on a table under a warm lamp; jointed paper puppets with brass split-pin joints, moving in 12 fps steps. Canvas 2D rendered frame by frame in headless Chrome, encoded with ffmpeg. Use when a reference video or brief calls for paper craft, cut-paper, papercraft, stop-motion paper, kids' storybook collage, 剪紙 / 紙片 / 紙偶 / 定格動畫 looks, or when the video-clone router picks the paper-cutout style.★ 3.6k GitHub starsSkillCustom Video Composeredenfunf/reelmimic · by edenfunfAuthor or edit a custom HyperFrames composition when no specialized workflow fits, or when BRIEF.md sets flow: companion. Use for longer or multi-scene pieces, brand and sizzle reels, montages, static loops, static title cards, footage remixes, and freeform builds. Use motion-graphics instead for a short unnarrated motion-first unit, including an animated title. Route fresh creation through hyperframes before using this skill.★ 543 GitHub starsSkillCode Change Explaineredenfunf/reelmimic · by edenfunfTurn a GitHub pull request (a PR URL, owner/repo#N, or 'this PR' in a checked-out repo) into a code-change explainer video — changelog, feature reveal, fix, or refactor walkthrough built from the diff, commits, and files: the input is a code change, not a website. Not a product promo (/product-launch-video) or a no-PR topic explainer (/faceless-explainer). Unclear → /hyperframes.★ 543 GitHub stars