liebstoeckel

Your agent writes the deck

Install it, hand the skill to your agent, and one prompt becomes a finished presentation: a single HTML file built from real MDX and TSX that you own. No black box, no lock-in.

Read the docs Star on GitHub core + CLI open source, MPL-2.0
terminal
$ npm install -g bun
$ bun add -g @liebstoeckel/cli
$ liebstoeckel skill install --global

From prompt to finished deck

A real session. After the install, ask for a presentation: the agent reads the registry, scaffolds the deck, writes the slides, and rebuilds until the check is green.

your terminal

$ claude "Create a presentation comparing the glycemic index of different foods"

I'll create this presentation. Let me start by exploring the framework's registry and setting up the deck.

Bash(liebstoeckel registry list --json)

⎿ 14 components. Picking scatter-chart and bar-chart

Bash(liebstoeckel new glycemic-index)

⎿ scaffolded presentations/glycemic-index

Write(slides/04-not-the-whole-story.tsx)

⎿ GI versus glycemic load per serving, eight foods

Bash(liebstoeckel build --check --json)

{ ok: true, diagnostics: [] }

Done. Six slides: what GI measures, the rankings, why GI alone misleads, and the swaps that lower a meal. Built to glycemic-index.html.

The deck that session built. The springs and reveals come from the engine, not the model.

Don't take the video's word for it. The whole deck is one file, so here it is.

Download the deck

One command and your agent knows liebstoeckel

liebstoeckel skill install --global drops the liebstoeckel‑deck skill into your user account, so it is there for every project. It teaches an agent to drive the same CLI you do, over plain bash. No MCP server to run, no bespoke format. (Use --dir <deck> for a single project.)

Claude CodeCodexCursorGemini + AGENTS.md fallback

Reads the registry
It discovers chart components and their exact data shapes from registry view --json, so it never guesses a prop or a field.
Writes source you own
Charts scaffold into your deck's charts/ folder as MDX and TSX. It is yours to read, edit, and keep. There is no special agent format.
Loops until it compiles
It runs build --check and fixes each diagnostic until the deck builds clean. A green check is its definition of done.

You own what it writes

Every slide is a component. The agent writes the same MDX and TSX a human writes, with motion as a first-class citizen: animated code diffs, spring choreography, and Magic Move that carries an element from one slide to the next.

slides/04-not-the-whole-story.tsx
import { ScatterChart } from "../charts/ScatterChart";

export const notes = "Watermelon: GI 76, load 8. GI alone can mislead.";

export default function NotTheWholeStory() {
  return <ScatterChart layoutId="gi" data={foods} />;
}
rendered
layoutId

Built to be kept

Plenty of tools will generate a deck. The difference is what you keep: one file that is still code, still yours, and still alive.

Single-file output
Every deck builds to one portable .html with JS and CSS inlined and assets base64'd. No build server at runtime, no CDN to outlive. It drops into an email, a USB stick, an S3 bucket, an air-gapped room.
Ejectable, not exported
A deck is MDX and TSX in your repo: colleagues review it in a pull request, and the next agent picks up where the last one stopped. Even the built file opens back up, since liebstoeckel eject recovers the editable source from any deck.html.
Presenter view included
Speaker notes, the next slide, reveal steps, and elapsed time ship inside every build, not in a paid tier. Walk in with the file and present.
Live without a platform
Host the same file and it opens a session: the audience joins by QR, and polls, Q&A, and reactions sync to every phone in the room. Unhosted, it presents quietly offline.
Agents can check their work
Slides are typed components and builds are deterministic, so build --check tells an agent the truth about what it wrote. Next quarter's numbers are an edit to real code, not a fresh generation.
Motion that matters
Spring choreography, animated code diffs, and shared-element transitions are why we built our own engine instead of bending a generic tool. Motion is authored, never bolted on.
Brands, not styles
A deck declares brand: "acme" and inherits the whole look from typed design tokens. Override one token for a one-off without forking the theme.

Decks that talk back

Host the file you just downloaded and it opens a live session over Yjs. The audience joins from a phone by QR. Polls, Q&A, and reactions sync to every device in the room, and the deck still works offline, where plugins render a quiet fallback.

How live sessions work Build a plugin

The presenter view of the glycemic index deck: the current slide with a scatter chart of GI versus glycemic load, a preview of the next slide, speaker notes, three reveal steps, and clock and elapsed-time readouts
The presenter view, from the same file.

Or drive it yourself

Your agent and your hands share one CLI. Three commands take an empty folder to a deck you can present live or hand off as a single file. Every command speaks --json, so it scripts cleanly too.

  1. 1Scaffold a deck from a starter and pick a brand.
  2. 2Present live, where the audience joins by QR and you drive from the presenter view.
  3. 3Build to one self-contained dist/index.html.
$ liebstoeckel new my-talk
  scaffolded, brand liebstoeckel
$ liebstoeckel live my-talk
  presenter on localhost:3000, audience by QR
$ liebstoeckel build my-talk
  → dist/index.html, self-contained ✓
Cloud, coming soon

Hosted live for teams

The last step of the story. Your deck presents from a laptop free forever; liebstoeckel cloud is for the day that stops scaling: managed live sessions, shared team decks, presenter analytics, and org brands. The framework stays open and free.

Hand your next deck to your agent

terminal
$ npm install -g bun
$ bun add -g @liebstoeckel/cli
$ liebstoeckel skill install --global
Start with the docs