About kinetograph-migrate
A skill for migrating Remotion projects to Kinetograph, for projects that need to retain video code while changing the surrounding tooling. It guides diagnosis, fixes, checks, and strict rendering, and explicitly rules out using a browser in the render path.
Key features
- 01Inspect entry files and compositions
- 02Diagnose unsupported elements and properties
- 03Guide fixes by issue type
- 04Run lint and type checks
- 05Review stills and strip previews
- 06Render video in strict mode
Use cases
- 01Assess incompatibilities in a Remotion project
- 02Migrate project code to Kinetograph
- 03Validate migrated visuals and video output
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ 0xs4n4tg/ kinetograph --skill kinetograph-migrateAfter installing, type/kinetograph-migratein Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
references/three.mdtooling.mdunsupported.mdDetails
From the project READMEMigrate a Remotion project to Kinetograph
Most of a Remotion project runs unchanged. remotion and 24 @remotion/* packages are mapped onto Kinetograph's core
by the CLI, so the video code does not change. What changes is the tooling around it, and a few packages that have no
equivalent. There is no browser anywhere in the render path. Never add one: no Chrome, Puppeteer, Playwright or iframe
as a stopgap, for any reason.
Run commands as npx kinetograph <command>. Add --json to get one JSON object. For the other commands and the
project API, use the kinetograph skill.
The loop
- Find the entry and the compositions. Read
package.json(scripts, dependencies) and anyremotion.config.tstoo:doctoronly sees files the entry imports, so a player page, a render script or a config file never shows up in its report. Search the project for@remotion/(player|renderer|bundler|lambda|cloudrun|cli|three),from 'three'andIFrame, and treat each hit as a finding. The entry is the file that callsregisterRoot(oftensrc/index.ts;package.jsonscripts orremotion.config.tsname it). Runkinetograph compositions <entry>. If it fails with... is not supported by Kinetograph yet, that import is the first finding. (The message says to rundoctor, butdoctorstops on the same import until you fix it.) - Doctor.
kinetograph doctor <entry>(add--comp <id>for one composition). It reports every element, property and reason the engine cannot draw, with frame ranges. An import that cannot be bundled stops the command before any report, with the package named; fix that first and rundoctoragain. Keep the report; work from it. - Fix each finding. Pick by kind:
@remotion/threeorthreeimports: readreferences/three.md.@remotion/player,@remotion/renderer,@remotion/bundler,@remotion/lambda,@remotion/cloudrun,@remotion/cli,remotion.config.ts,npm runscripts, webpack overrides: readreferences/tooling.md.IFrame,@remotion/webcodecs,@remotion/media-parsersample callbacks,@remotion/rive,@remotion/skia, Canvas, WebGL or CSS issues in the report: readreferences/unsupported.md.- Anything else: the property or element is named in the report. Change it to one the engine draws, or leave it
out. Do not guess; run
doctoragain.
- Lint.
kinetograph lint <entry>andkinetograph check <entry>(type errors). Fix every error. Errors that say "no declaration file" forreactmean@types/reactis not installed: add it as a dev dependency at the project's React version and tell the user. That is not a migration problem and does not blockrender. - Look.
kinetograph strip <entry> -n 12 -o out/strip.png, then open the PNG. Usestill <entry> <frame>for one frame. Compare with what the project was meant to show (a Remotion render, a screenshot, the user's description; if you have none, check against the code and say that you could not compare).doctorandlintcan both be clean while text is missing, so check that every title and caption is on screen (see Fonts). - Render.
kinetograph render <entry> --comp <id> -o out/video.mp4 --strict(--range 0..30first for a quick test;a..bstops at b-1,a..=bincludes b).--strictfails on the first frame with anything unsupported, so no video leaves with something missing.
If --strict still fails after the fixes, a left-over is real. Either approximate it (say how) or remove it, then say
so in step 7. Do not hide it by dropping --strict for the final render.
- Report to the user. List what was ported as is, what was replaced (and with what), what was left out or approximated, and the commands to run the project now. Say plainly when the result differs from Remotion's.
Rules
- A
remotionimport needs no edit. Do not rewriteremotionor@remotion/*imports to@kinetographdev/core. - Never remove a feature silently. Every omission or approximation goes in the report from step 7.
- Fonts. Text in a font that is not registered may be drawn as nothing, with no warning from
doctor. AfontFamilythat names only system fonts (Helvetica, Arial, sans-serif) is the usual cause. Register a font file the user is allowed to use:@remotion/google-fonts/<Family>(loadFont()),registerFont({ family, path: staticFile('F.ttf') })from@kinetographdev/core, or@font-face { src: url(...) }in an imported.cssfile. Do not copy system fonts into the project. - Rendering is a pure function of the frame. Replace
Date.now(),Math.random()and timers with frame maths andrandom(seed). - There is no network.
fetchreads project files only. Copy remote assets intopublic/and usestaticFile. - Do not add dependencies for the render path, except
kinetographitself as a dev dependency (it brings@kinetographdev/core, which the 3D elements import from). If it is not on npm yet, ask the user where to install it from. Packages for the studio or tests are fine.
Coverage in one line
Core remotion and these @remotion/* packages are mapped: transitions, motion-blur, noise, paths, shapes,
layout-utils, animation-utils, captions, google-fonts, fonts, lottie, gif, media-utils, media, light-leaks, starburst,
sfx, zod-types, timeline-utils, media-parser, webcodecs, canvas, rive, skia. Not ported on purpose: three, player,
renderer, bundler, cli, lambda, cloudrun, tailwind, tailwind-v4 (Tailwind itself works). The full table is on the docs
site at /docs/guides/migrate/. GSAP (core, the free plugins, Flip) works too: seek a paused timeline to
frame / fps in a layout effect, or let a gsap.to in a useEffect play by itself (/docs/compat/#gsap).
Needs no rewrite: <Img src> of an .svg file (text inside it is left out), named and functional CSS colours
(white, rgb(), oklch()), <TransitionSeries> and <Series> children in a Fragment, <canvas> and <Canvas>,
-webkit-text-stroke, and symbols or emoji missing from a font (bundled fallback; CJK needs a font you load). Libraries
(Recharts, d3, rough.js, Chart.js, anime.js, Motion, Paper.js) run as they are when they draw from the frame; see
/docs/libraries/. Mermaid draws with its default HTML labels (<foreignObject>); load the label font first.