agentsclimarketplace

Manim slides

Skill RubenBranco/Manim-Slides-Skill/skills/manim-slides

Build animated presentations with manim-slides 5.6.0 (Manim CE + RevealJS). Use when the user wants to author slides with Python animations, render them, or convert to HTML/RevealJS, PPTX, or PDF. Includes scaffolder for new presentations and a one-shot render-and-build pipeline.From its SKILL.md

Install
npx -y skills add RubenBranco/Manim-Slides-Skill --skill manim-slides

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

21.2 KB, as published. Nobody here has run it

Manim Slides Skill

Author animated presentations with manim-slides 5.6.0. Manim CE primary; ManimGL covered in references/manimgl.md. RevealJS HTML is the primary export target; PPTX/PDF/ZIP covered in references/pptx-pdf-zip.md.

Locate the skill directory

Before running any script, resolve $SKILL_DIR and cd into it:

if [ -n "${CLAUDE_PLUGIN_ROOT}" ]; then
  SKILL_DIR="${CLAUDE_PLUGIN_ROOT}/skills/manim-slides"
elif [ -d "${HOME}/.codex/manim-slides-skill/skills/manim-slides" ]; then
  SKILL_DIR="${HOME}/.codex/manim-slides-skill/skills/manim-slides"
else
  SKILL_DIR="$(pwd)"
fi
cd "$SKILL_DIR"

The skill itself does not install dependencies. The user is responsible for environment setup. If a script fails with ModuleNotFoundError: manim or manim-slides: command not found, install the prerequisites below.

Prerequisites

System tools:

  • ffmpeg — required for all rendering. Install with brew install ffmpeg (macOS), apt install ffmpeg (Debian/Ubuntu), or choco install ffmpeg (Windows).
  • LaTeX distribution (TeX Live, MacTeX, or MiKTeX) — only required if you use Tex / MathTex mobjects. Skip if you only use Text.
  • Python ≥ 3.9.
  • Qt (PySide6 or PyQt6) — only required for manim-slides present (the live Qt presenter). Headless RevealJS HTML export does not need Qt. Install via pip install "manim-slides[pyside6-full]" if needed.

Python packages (run once, from $SKILL_DIR):

# Runtime only (manim-slides + manim CE)
pip install -r requirements.txt
# or with uv:
uv pip install -r requirements.txt

# For development (adds pytest + pytest-mock)
pip install -e ".[dev]"

scripts/scaffold.py only uses Python's standard library and runs without any of these installed. scripts/build.py shells out to the manim-slides CLI, so manim-slides must be on $PATH (i.e. installed via the commands above) before invoking it.

Quick Start

# 1. Scaffold a new presentation directory
python3 scripts/scaffold.py ~/my-talk

# 2. Edit the generated slides.py
$EDITOR ~/my-talk/slides.py

# 3. Render and convert to RevealJS HTML in one step
python3 scripts/build.py ~/my-talk/slides.py MyTalk

This produces ~/my-talk/presentation.html (a single-file RevealJS deck).

Authoring slides — the Slide class

Subclass Slide (or ThreeDSlide for 3D scenes) instead of Manim's regular Scene:

from manim import *
from manim_slides import Slide

class MyPresentation(Slide):
    def construct(self):
        title = Text("Hello", font_size=72)
        self.play(Write(title))
        self.next_slide()           # ends slide 1, opens slide 2
        self.play(FadeOut(title))

self.next_slide(...) — keyword arguments

KwargDefaultHonored byDescription
loopFalsepresent, htmlLoop this segment until the user advances. Cannot be the first or last slide for RevealJS.
auto_nextFalsepresent, htmlAuto-advance once the segment ends. In RevealJS, sets data-autoslide to the segment duration in ms.
playback_rate1.0present onlyPlayback speed (forward).
reversed_playback_rate1.0present onlyPlayback speed when reversing.
notes""present, html, pptxSpeaker notes. Markdown for HTML; plaintext for PPTX. Press S in the browser to open speaker view.
dedent_notesTruesame as notestextwrap.dedent notes before rendering.
skip_animationsFalseallDon't render this segment at all (useful while iterating).
srcNoneallUse an external image/GIF/video as the slide content instead of the Manim animation. Type auto-detected from MIME.
direction"horizontal"html only"vertical" creates a RevealJS sub-slide (up/down arrows).

Hard rules

  • A loop=True segment cannot be the first or last slide of the deck when targeting RevealJS. Place at least one regular slide before and after it.
  • Forgetting next_slide() between two play() calls collapses them into one segment. Always call next_slide() between slides.

Static-media slide via src=

from pathlib import Path

self.next_slide(src=Path("./figure.png"))   # static image becomes the next slide

Speaker notes example

self.next_slide(notes="""
# Section 2: Results

- Key finding 1
- Key finding 2
""")

In the browser, press S to open speaker view.

Vertical RevealJS stack

self.next_slide(direction="vertical")

ThreeDSlide

from manim import *
from manim_slides import ThreeDSlide

class My3D(ThreeDSlide):
    def construct(self):
        ...

Slide-class helpers

APIPurpose
self.canvasDict of "persistent" mobjects that survive across slides.
self.add_to_canvas(name=mob)Register a mobject in the canvas under name.
self.remove_from_canvas("name", ...)Remove from canvas.
self.canvas_mobjectsConvenience: the canvas as a tuple.
self.mobjects_without_canvasAll current mobjects except canvas members.
self.wipe(current, future, direction=LEFT, ...)Convenience wipe transition.
self.zoom(current, future, scale=4.0, out=False, ...)Convenience zoom transition.
self.wait_time_between_slidesProperty setter (default 0.0). Set to e.g. 0.1 to insert a small wait at every cut so animations finish.
self.start_skip_animations() / self.stop_skip_animations()Bracket regions whose animations should be skipped (useful while iterating).

Class attributes

AttributeDefaultUse
disable_cachingFalseBypass Manim's cache.
flush_cacheFalseFlush Manim's cache on each render.
skip_reversingFalseSkip generation of reversed videos. Set True if exporting only HTML/PPTX (those never play in reverse).
max_duration_before_split_reverse4.0Set to None to avoid the parallel-reverse-render deadlock that affects long videos.
num_processesNoneOverride CPU parallelism for rendering.

Common pitfalls

  • Multiple play() calls collapse without next_slide(). Forgetting the call between segments produces one mega-segment. Always end each conceptual slide with next_slide().
  • loop=True on the first or last slide is rejected by RevealJS. Put loop=True only on middle segments.
  • Reverse-rendering can deadlock on long videos. If a render hangs at the reverse step, set max_duration_before_split_reverse = None on the class. If you only export to HTML/PPTX, also set skip_reversing = True to skip the reverse render entirely.
  • ManimGL: self.wait() does not split slides. Always end a segment with self.play(...) before self.next_slide().
  • HTML without --one-file requires the assets folder. Without --one-file, the converter writes <output>_assets/ next to the HTML; the assets directory must travel with the HTML when shared (relative paths).

Rendering

manim-slides render [--CE | --GL] FILE.py SceneName [SceneName ...]

Quality flags (passed through to Manim):

FlagResolution / FPS
-ql854×480 @ 15 fps
-qm1280×720 @ 30 fps
-qh1920×1080 @ 60 fps
-qk4K

Other useful flags: --fps=N, --media_dir=DIR, --disable_caching, -n a,b (render only animation indices a..b).

Output paths:

  • ./slides/<SceneName>.json — the per-scene presentation manifest.
  • ./slides/files/<SceneName>/ — the assembled animation chunks.

Override the output dir with --folder (must be passed to subsequent commands too).

Converting to RevealJS HTML

manim-slides convert SceneName out.html [-c key=value ...]

The format is auto-detected from the extension; pass --to=html to be explicit. Most-used -c options:

OptionDefaultEffect
controlsfalseShow on-screen navigation arrows.
slide_numberfalseShow slide numbers (true / h.v / c/t / etc).
progressfalseProgress bar.
transitionnonenone / fade / slide / convex / concave / zoom.
transition_speeddefaultdefault / fast / slow.
reveal_themeblackBuilt-in RevealJS theme.
background_colorblackCSS color.
auto_animatetrueEnable RevealJS auto-animate between segments.
loopfalseWhole-deck loop.
embeddedfalseRender the deck as embeddable (no full-page styling).
show_notesfalseShow notes in the deck (vs. only in speaker view).

Single-file portable HTML

manim-slides convert MyScene out.html --one-file
manim-slides convert MyScene out.html --one-file --offline   # also inline JS/CSS

--one-file embeds videos as base64 data URIs. --offline downloads RevealJS itself (otherwise loaded from the CDN). Combine both for a fully offline, single-file deck.

Custom Jinja2 template

manim-slides convert MyScene out.html --use-template ./my-template.html

The default template lives at manim_slides/templates/revealjs.html (in the installed package). To add RevealJS plugins beyond notes and markdown (e.g. highlight, math), supply a custom template — see references/revealjs-customization.md.

Discover all options

manim-slides convert --to=html --show-config       # all -c options + defaults
manim-slides convert --to=html --show-template     # default template content

Live Qt presenter (brief)

manim-slides present SceneName              # 'present' is the default subcommand
manim-slides SceneName                      # equivalent

Default keys (configured in .manim-slides.toml):

KeyAction
QQuit
SpacePlay / pause
→Next
←Previous
VReverse
RReplay
FToggle full screen
HHide / show mouse

Initialize / customize:

manim-slides init                  # write default .manim-slides.toml non-interactively
manim-slides wizard                # Qt key-rebinding GUI

Useful flags: --start-paused, -F/--full-screen, -S/--screen N, --start-at SCENE,SLIDE, --exit-after-last-slide, --playback-rate.

Diagnostics:

manim-slides checkhealth

Using the ManimGL backend (sidebar)

Manim Slides supports both Manim CE (default) and 3blue1brown's ManimGL.

pip install "manim-slides[manimgl]"

Imports change:

from manimlib import *                # was: from manim import *
from manim_slides import Slide        # unchanged

Render with:

manim-slides render --GL slides.py SceneName

Override auto-detection:

MANIM_API=manimlib FORCE_MANIM_API=1 manim-slides render slides.py SceneName

ManimGL caveats:

  • self.wait() does NOT split slides — always end a segment with self.play(...) before self.next_slide().
  • next_section is unavailable.
  • Sphinx directive, IPython magic, and the upstream ConvertExample only work on Manim CE.
  • ManimGL <1.7.1 requires an outdated NumPy. The [manimgl] extra pins setuptools<81.

For full details see references/manimgl.md.

Helper scripts

scripts/scaffold.py <target_dir>

Bootstraps a new presentation directory.

FlagDefaultDescription
target_dirrequiredDestination directory (must be empty unless --force).
--name NAMEbasename of target_dirProject / class name. Sanitized to a valid Python identifier (CamelCase).
--3dfalseUse ThreeDSlide starter. Mutually exclusive with --manimgl.
--manimglfalseUse ManimGL backend starter.
--forcefalseAllow writing into a non-empty directory (overwrites colliding files).

Files created: slides.py, pyproject.toml, .manim-slides.toml, Makefile, .gitignore, README.md.

# Default Manim CE scaffold
python3 scripts/scaffold.py ~/my-talk

# Custom class name
python3 scripts/scaffold.py ~/my-talk --name ThesisDefense

# 3D starter
python3 scripts/scaffold.py ~/3d-demo --3d

# ManimGL starter
python3 scripts/scaffold.py ~/gl-demo --manimgl

scripts/build.py <slides_file> <SceneName...>

Renders and converts to RevealJS HTML in one shot.

FlagDefaultDescription
slides_filerequiredThe .py file containing Slide subclasses.
scene_name (1+)requiredOne or more class names to render and concatenate.
--output OUTpresentation.htmlOutput HTML path.
--quality {l,m,h,k}hMaps to -ql/-qm/-qh/-qk.
--one-file/--no-one-file--one-fileEmbed assets as data URIs vs separate <output>_assets/.
--offlinefalseInline JS/CSS from the CDN (combine with --one-file).
--theme THEMEblackRevealJS theme (validated against the v5.6.0 allowlist).
--transition TfadeRevealJS transition.
--template TnoneCustom Jinja2 template (passes --use-template).
-c KEY=VALUEnone, repeatablePass-through -c option to manim-slides convert.
--skip-renderfalseSkip render; use existing ./slides/*.json.
--dry-runfalsePrint commands without executing.
--folder FOLDER./slidesSlides folder for both render and convert.
--backend {CE,GL}CEAdds --CE/--GL to the render step.
# Default build
python3 scripts/build.py slides.py MyTalk

# Light-theme deck with slide numbers and controls
python3 scripts/build.py slides.py MyTalk --theme white -c slide_number=true -c controls=true

# ManimGL backend, low quality (fast iteration)
python3 scripts/build.py slides.py MyTalk --backend GL --quality l

# Just the convert step (skip render if .json files already exist)
python3 scripts/build.py slides.py MyTalk --skip-render

# Print the commands without running
python3 scripts/build.py slides.py MyTalk --dry-run

Both scripts shell out to the upstream manim-slides CLI; they do not import from manim_slides internals. Use --dry-run to inspect the exact manim-slides ... invocations.

Going deeper

In-skill references (under references/):

Official upstream docs:

Keep looking

Skills are one crate of 628,853. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.