castwrightv0.6.0

CASOON Open Source

Terminal demos you write, not record.

Describe a terminal session in a short YAML file. castwright turns it into the demo for your README, docs or landing page — an animated SVG, a live terminal or a GIF. No screen recording, no retakes.

pnpm add -D @casoon/castwright
npm i -D @casoon/castwright
yarn add -D @casoon/castwright
Free · MITv0.6.0Node 22+asciicast v2
Terminal: cat deploy.terminal.yaml shows a short castwright scene, highlighted, in which npm run deploy prints two green check marks for build and upload. castwright build deploy.terminal.yaml --format svg then writes dist/deploy.svg, and castwright build without a format writes dist/deploy.cast.

Who it is for

output formats: cast, SVG, GIF and MP4
4
bundled terminal themes
7
scripts in the SVG — it plays on GitHub
0
headless browsers in your build
0

How it works

A scene is a list of steps: a command that gets typed, what it prints, a file to show, a pause. You write it like any other file in your repository and review it in a diff.

castwright compiles the scene to a standard asciicast file, byte for byte the same on every build. From there it becomes whatever the place needs: a player for the web page, an animated SVG for the README, or a GIF and MP4 for everywhere else.

How castwright worksYou write a terminal scene as a .terminal.yaml file. Commands that should show real output run once with --allow-exec --record, which writes what they printed back into the file; a VHS .tape builds the same way. castwright compiles the scene to asciicast v2, the same bytes on every build. That one cast plays in the web player, exports to an animated SVG without script, and to GIF or MP4 through agg and ffmpeg.How castwright worksWrite a scene → CompileReal commands → Compile: recordedCompile → Web player: .castCompile → Animated SVGCompile → GIF or MP4recorded.castWrite a scene – .terminal.yamlWrite a scene.terminal.yamlReal commands – exec: or a VHS .tape, run onceReal commandsexec: or a VHS .tape, run onceCompile – asciicast v2, same bytesCompileasciicast v2, same bytesWeb player – xterm.js, Vite, AstroWeb playerxterm.js, Vite, AstroAnimated SVG – no script, for READMEsAnimated SVGno script, for READMEsGIF or MP4 – via agg and ffmpegGIF or MP4via agg and ffmpeg
How castwright worksYou write a terminal scene as a .terminal.yaml file. Commands that should show real output run once with --allow-exec --record, which writes what they printed back into the file; a VHS .tape builds the same way. castwright compiles the scene to asciicast v2, the same bytes on every build. That one cast plays in the web player, exports to an animated SVG without script, and to GIF or MP4 through agg and ffmpeg.How castwright worksWrite a scene → CompileReal commands → Compile: recordedCompile → Web player: .castCompile → Animated SVGCompile → GIF or MP4recorded.castWrite a scene – .terminal.yamlWrite a scene.terminal.yamlReal commands – exec: or a VHS .tape, run onceReal commandsexec: or a VHS .tape, run onceCompile – asciicast v2, same bytesCompileasciicast v2, same bytesWeb player – xterm.js, Vite, AstroWeb playerxterm.js, Vite, AstroAnimated SVG – no script, for READMEsAnimated SVGno script, for READMEsGIF or MP4 – via agg and ffmpegGIF or MP4via agg and ffmpeg
How castwright worksYou write a terminal scene as a .terminal.yaml file. Commands that should show real output run once with --allow-exec --record, which writes what they printed back into the file; a VHS .tape builds the same way. castwright compiles the scene to asciicast v2, the same bytes on every build. That one cast plays in the web player, exports to an animated SVG without script, and to GIF or MP4 through agg and ffmpeg.How castwright worksWrite a scene → CompileReal commands → Compile: recordedCompile → Web player: .castCompile → Animated SVGCompile → GIF or MP4recorded.castWrite a scene – .terminal.yamlWrite a scene.terminal.yamlReal commands – exec: or a VHS .tape, run onceRealcommandsexec: or a VHS.tape, run onceCompile – asciicast v2, same bytesCompileasciicast v2,same bytesWeb player – xterm.js, Vite, AstroWeb playerxterm.js, Vite,AstroAnimated SVG – no script, for READMEsAnimated SVGno script, forREADMEsGIF or MP4 – via agg and ffmpegGIF or MP4via agg andffmpeg
How castwright worksYou write a terminal scene as a .terminal.yaml file. Commands that should show real output run once with --allow-exec --record, which writes what they printed back into the file; a VHS .tape builds the same way. castwright compiles the scene to asciicast v2, the same bytes on every build. That one cast plays in the web player, exports to an animated SVG without script, and to GIF or MP4 through agg and ffmpeg.How castwright worksWrite a scene → CompileReal commands → Compile: recordedCompile → Web player: .castCompile → Animated SVGCompile → GIF or MP4recorded.castWrite a scene – .terminal.yamlWrite a scene.terminal.yamlReal commands – exec: or a VHS .tape, run onceRealcommandsexec: or a VHS.tape, run onceCompile – asciicast v2, same bytesCompileasciicast v2,same bytesWeb player – xterm.js, Vite, AstroWeb playerxterm.js, Vite,AstroAnimated SVG – no script, for READMEsAnimated SVGno script, forREADMEsGIF or MP4 – via agg and ffmpegGIF or MP4via agg andffmpeg

Quickstart

From an empty file to a demo in your README. Putting the player on a page, the full walkthrough and every option are in the documentation.

  1. Write a demo.terminal.yaml: the commands to type and what they print.
  2. Build it to an animated SVG with one command.
  3. Put it in your README as an <img>, or play it in the page with the Vite plugin or the Astro component.
Build
npx castwright build demo.terminal.yaml --format svg

New in v0.6.0

Changelog →

Frequently asked questions

What does a build actually produce?

One asciicast v2 file. From there it becomes a web player, an animated SVG for a README, or a GIF or MP4 through agg and ffmpeg — whichever the place needs.

Does it need a headless browser or a screen recording?

No. The compiler runs in plain Node, and the same input always produces the same bytes — no wall clock, no unseeded randomness — so a compiled cast is a text file you can commit and read in a diff.

Can a scene show real command output instead of typed-out text?

Yes. An exec: step runs the command for real in a pseudo-terminal, and --record writes what it printed back into the file, so every later build replays those exact bytes instead of running anything again.

Does it only work with Astro?

No. @casoon/astro-castwright is a thin wrapper around a Vite plugin that also covers SvelteKit, Nuxt, Remix, SolidStart, Qwik, VitePress and plain Vite — and with no bundler at all, a single script tag loads the player.

Is the player accessible?

Yes. Its children are the terminal's real, selectable final text, generated at build time; reduced motion shows that final frame immediately, there is always a real pause control, and it is never a keyboard trap.