reanimate
Clone a section, widget, page or animation from any reference (a live website URL, a screen recording, an mp4/mov/webm, a gif, a Lottie file, a prototype export) frame by frame into the user's own codebase, then record the clone and verify it against the reference frame by frame, iterating until timing, easing, sequence and layout match. Use whenever the user wants to clone, copy, replicate, recreate, reverse-engineer, port or "steal" a hero, section, widget, marquee, carousel, hover effect, page transition, loader, scroll animation or interaction from a site or video, says "make it look/feel/move like this", "same animation as", "match this exactly", or hands over a gif/video and asks to build it, including when they also want to add their own content, colours or extra features on top, or only want part of the reference (one section, one widget, a few seconds). Covers canvas, WebGL, WebGPU and three.js / 3D scenes (shaders, particles, globes, glTF models) as well as CSS and JS motion. Pixel-level matching of fonts, colours and spacing is done only when they ask for it.
Install
npx skills add https://github.com/NiazMorshed2007/reanimate --skill reanimateVerifying the clone
A round is: capture the clone the same way as the reference → compare.ts → sheet.ts compare → easing.ts --compare-track for each tracked element → read everything → fix one cause → next round. Keep every round's directory (clone-1, compare-1, clone-2, …) so the report can show progress.
What compare.ts tells you
report.md / report.json:
- offset: the clone frame matched to reference frame 0 (auto-aligned on the first ten frames). A large offset means the clone starts late or early; fix the trigger timing or
--wait-before, do not rely on alignment to hide it. - mean mismatch and worst frames: fraction of pixels that differ per frame. Pixel-faithful work reads this directly. Motion-faithful work reads it as a trend: it should be low at rest and spike only where the two differ in state.
- motion window: first/last frame with visible change, and the peak, for both sets. The timing error is the difference, in seconds, of start, end, duration and peak. This is the main motion metric, independent of colours and copy.
- activity curve: bars of change per frame. Same shape = same easing and stagger; a clone whose bars are front-loaded against a reference whose bars are even is using a stronger ease-out, and so on.
diff/NNNN.png: red where pixels differ.sheet.ts compare --diffputs reference, clone and diff side by side with the mismatch per row.
easing.ts --compare-track other.json prints maxAbsDiff / meanAbsDiff of the property over time between the two tracks (in CSS px or opacity units) and the best-fit easing of the clone, to compare with the reference's.
Pass criteria
Motion-faithful (per spec row):
- start and end timing error ≤ 0.08 s (two frames at 25 fps); duration error ≤ 0.08 s
- easing: same best-fit family (out / in / in-out / linear / spring) and RMSE of the reference's best fit applied to the clone's track ≤ 0.05, or
meanAbsDiff≤ 5 % of the travel distance - stagger order and gaps within 0.04 s
- travel distance within 10 % of the reference relative to the element size, same direction
- nothing moves in the clone that is still in the reference, and vice versa
- compare sheets: the same visual state at the same timestamp, allowing for different copy/colours
Pixel-faithful adds:
- mean mismatch ≤ 2 %, no frame above 5 % (set
--threshold 0.02); at rest frames ≤ 0.5 % - fonts loaded and identical (check
inspect.json › fontson both captures), colours and sizes equal innodes - same assets at the same size
Mixed: the cloned region passes one of the above with --region limited to it; the additions are shown on a sheet and described.
Canvas, WebGL, 3D (captured with --clock virtual --gl, see references/webgl.md):
gl.ts compare --ref ref --clone clone-N: every animated channel in the reference has a clone channel of the same kind, start and end within 0.08 s, mean error ≤ 5 % of the reference's range (--mapwhen names differ); canvas attributes, renderer settings and draw structure (primitive, vertex count, blend state, cadence) the same, or the difference explained- the clock rate of every
clockchannel the same (gl.ts channels) - pixels as above. If the clone ports the reference's generator, the seeded random gives the same particles and the sharp mismatch applies. If not, judge with
compare.ts --blur 4and report the sharp number next to it
Reading failures → usual fix
When to stop
- Stop when every spec row passes its criteria and the latest sheets look the same state-by-state. Say so with the numbers.
- Stop after 5 rounds without progress on a row, or when the remaining difference is outside your control (font licence, a shader or model the user may not copy, third-party embed, physics you approximated). Report the row, its last numbers, and the reason. Never relax thresholds silently; if you think the user would accept a looser bar, say which and why.
- If the reference itself is inconsistent between captures (randomised content, A/B variants, network-dependent lazy loading), capture it with
--clock virtual(same seed) first: that removes timing and randomness, and two captures come out identical. Whatever still differs (A/B variants, server-side randomness) is the noise floor; measure it by comparing the reference against itself before judging the clone.