agentsclimarketplace

Test manim

Skill shihabshahrier/manim-coding-skill/skills/test-manim

Create teaching-quality STEM animations using ManimGL. Generates narrative-driven animations as 15-second chunks merged into a final video. Configurable topic, duration, and model name. Works with Claude Code and opencode across any model. Invoke: /test-manim "topic" [--duration 30|60|90|120] [--model name] Default duration: 30s. Primary goal: great storytelling + visual clarity.From its SKILL.md

Install
npx -y skills add shihabshahrier/manim-coding-skill --skill test-manim

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

3 things to look at

  • skips confirmationTells the agent to proceed without asking first, 1 time: "Do not ask clarifying questions mid-task — decide and proceed".
  • 2 stars2 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.
  • runs commandsInstructs the agent to run 7 commands, including `mkdir -p` and 6 more.

SKILL.md

9.8 KB, ~2.7k tokens by cl100k_base, as published. Nobody here has run it

ManimGL STEM Animation Skill

Produce pedagogically-effective STEM teaching animations: narrative-first, chunk-based (15s segments), rendered in ManimGL (manimgl v1.7+), merged into one final video.


Invocation

/test-manim "Newton's Laws of Motion"
/test-manim "Fourier Series" --duration 60
/test-manim "Neural Networks" --duration 90 --model minimax
ArgDefaultValues
topicrequiredany STEM subject string
--duration3030, 60, 90, 120 (seconds)
--modelsession modelidentifier used in folder name

Phase 0 — Parse & Scaffold

Extract from invocation:

  • TOPIC — subject string (required)
  • DURATION — total seconds (default: 30)
  • MODEL_NAME — folder identifier (default: derive from session context or use "claude")
  • CHUNK_COUNT = ceil(DURATION / 15)
  • TOPIC_SLUG = TOPIC lowercased, spaces→underscores, strip special chars

Create project at current working directory:

manim-{MODEL_NAME}/
  {TOPIC_SLUG}/
    scenes/
      chunk_01_{name}.py
      chunk_02_{name}.py
      ...
    output/
      chunks/
      final/
    assets/
    SCENE_PLAN.md
    render.sh
    merge.sh

Create all directories with mkdir -p before writing any files. Make render.sh and merge.sh executable with chmod +x.


Phase 1 — Narrative Planning (ALWAYS before code)

Write SCENE_PLAN.md completely before writing any .py files.

Story Arc Requirements

Every animation must have:

  1. Hook (first chunk): One striking visual that poses the core question
  2. Build (middle chunks): One concept per chunk, each building on prior
  3. Resolution (last chunk): Visual synthesis connecting all prior chunks; key insight held on screen

SCENE_PLAN.md Template

# {TOPIC} — Animation Plan

**Duration**: {DURATION}s | **Chunks**: {CHUNK_COUNT} × 15s | **Model**: {MODEL_NAME}

## Story Arc
- Hook: [striking opening visual — what question does it pose?]
- Build: [ordered list of concepts, one per chunk]
- Resolution: [final synthesis — what understanding has the viewer gained?]

## Visual Language
- Background: BLACK
- Primary concept color: BLUE
- Secondary concept color: YELLOW
- Accent / highlight: RED or GREEN
- Text / labels: WHITE
- Rule: one color = one concept, consistent across ALL chunks

## Chunks

### Chunk 1 — {name} (0s–15s)
- Role: Hook
- Concept: [what is demonstrated]
- Opening: [first visual the viewer sees]
- Key moment: [the reveal or insight at ~10s]
- Closing: [held frame at 15s — clean fade out]
- ManimGL objects: [list specific classes]
- Equations: [LaTeX strings if any]

### Chunk 2 — {name} (15s–30s)
- Role: Build
- Concept: ...
[repeat for each chunk]

### Chunk {CHUNK_COUNT} — {name} ({DURATION-15}s–{DURATION}s)
- Role: Resolution
- Concept: ...
- Callback: [reference to visuals from chunk 1]

## Issues Log
[fill during render phase]

Phase 2 — Scene File Generation

Load references/manim-gl-api.md before writing any scene code. Load references/storytelling.md during planning to shape narrative.

Write ALL chunk files before rendering any of them.

File Naming

chunk_{N:02d}_{slug}.py — slug is 1–3 words from chunk name, underscored, lowercase.

Required Scene Template

from manimlib import *


class Chunk{N}{PascalName}(Scene):
    def construct(self):
        # Target: ~15 seconds total
        # Color contract from SCENE_PLAN.md — do not deviate
        pass

Scene Code Rules

Timing — target exactly 15s per chunk

total = sum(all run_time values) + sum(all self.wait() values) ≈ 15
  • Animation transitions: run_time=0.81.5
  • Key reveals: run_time=1.52.5
  • After every major step: self.wait(1.5) minimum
  • Insight moment: self.wait(3)
  • Chunk closing hold: self.wait(2)

Layout — stay within camera bounds

  • Objects: x∈[-6,6], y∈[-3.5,3.5]
  • Title / top label: obj.to_edge(UP) (y≈3.0)
  • Main visual: obj.move_to(ORIGIN)
  • Bottom caption: obj.to_edge(DOWN) (y≈-3.0)

Typography

  • Math: Tex(r"F = ma")
  • Regular text: TexText("Newton's First Law")
  • Font sizes: title 48, body 36, caption 28
  • Example: TexText("An object at rest...", font_size=36)

Chunk cleanup — end of every construct()

# Safe fadeout — handles empty scene
to_fade = list(self.mobjects)
if to_fade:
    self.play(*[FadeOut(m) for m in to_fade], run_time=0.5)

Quality checks — verify before moving to render

  • At least one self.play() call (prevents black frame)
  • All objects positioned before first self.play()
  • self.add(obj) if object needs to appear instantly without animation
  • Cleanup block at end of construct()
  • Timing estimate ≈ 15s
  • No cross-file imports between chunks
  • No f-strings containing LaTeX — use raw strings r"..."

Phase 3 — Render

Write render.sh into the project root, then run it:

#!/bin/bash
set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
mkdir -p "$SCRIPT_DIR/output/chunks"

for scene_file in $(ls "$SCRIPT_DIR/scenes"/chunk_*.py | sort); do
    base="${scene_file##*/}"
    out_name="${base%.py}"

    class_name=$(python3 -c "
import ast
with open('$scene_file') as f:
    tree = ast.parse(f.read())
for node in ast.walk(tree):
    if isinstance(node, ast.ClassDef):
        print(node.name)
        break
")

    echo "Rendering: $class_name → output/chunks/$out_name.mp4"
    manimgl "$scene_file" "$class_name" \
        -w -q --hd \
        --video_dir "$SCRIPT_DIR/output/chunks" \
        --file_name "$out_name"
done

echo "All chunks rendered."

Render Error Protocol

If a chunk fails:

  1. Read full error — identify exact line + error type
  2. Check references/manim-gl-api.md error table for known fixes
  3. Fix minimum code — do not rewrite whole chunk
  4. Re-render only failed chunk: manimgl scenes/chunk_NN_name.py ClassName -w -q --hd --video_dir output/chunks --file_name chunk_NN_name
  5. Log in SCENE_PLAN.md under ## Issues Log

Do NOT merge until ALL chunks render without error.


Phase 4 — Merge

Write merge.sh into the project root, then run it:

#!/bin/bash
set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
CHUNKS_DIR="$SCRIPT_DIR/output/chunks"
FINAL_DIR="$SCRIPT_DIR/output/final"
mkdir -p "$FINAL_DIR"

CONCAT_FILE=$(mktemp /tmp/manim_concat_XXXXXX.txt)

for f in $(ls "$CHUNKS_DIR"/chunk_*.mp4 | sort); do
    echo "file '$f'" >> "$CONCAT_FILE"
done

OUTPUT_FILE="$FINAL_DIR/TOPIC_SLUG_final.mp4"

ffmpeg -f concat -safe 0 -i "$CONCAT_FILE" \
    -c:v libx264 -crf 18 -preset slow \
    -pix_fmt yuv420p \
    "$OUTPUT_FILE"

rm "$CONCAT_FILE"
echo "Final video: $OUTPUT_FILE"

Replace TOPIC_SLUG_final.mp4 with the actual topic slug when generating this file.

Verify output:

ffprobe -v error -show_entries format=duration -of csv=p=0 "output/final/TOPIC_SLUG_final.mp4"

Phase 5 — Report

## Animation Report: {TOPIC}

| Field | Value |
|-------|-------|
| Model | {MODEL_NAME} |
| Duration | {actual}s ({CHUNK_COUNT} chunks × ~15s) |
| Output | manim-{MODEL_NAME}/{TOPIC_SLUG}/output/final/{TOPIC_SLUG}_final.mp4 |

### What Was Created
[2–3 sentences: topic, visual approach, key animations used]

### Chunk Summary
| Chunk | Concept | Render | Notes |
|-------|---------|--------|-------|
| 1 | ... | ✓ | |
| 2 | ... | ✓ | |

### Code Quality
- ManimGL API: [correct / N workarounds needed]
- Timing: [within 2s of target per chunk / drifted by Xs]
- Color contract: [maintained / broken at chunk N]
- Cleanup: [all chunks fade cleanly / issues at chunk N]

### Issues Encountered
[list render errors and fixes — or "None"]

### Rating: X/10
[1-line justification]

### Recommendations
- [concrete improvement 1]
- [concrete improvement 2]

Token Efficiency Rules

  • Write ALL .py chunk files in one batch before running any render
  • Load references once — manim-gl-api.md at Phase 2 start, storytelling.md at Phase 1 start
  • Run render.sh once for all chunks — only re-render individual chunks when fixing errors
  • Plan fully (Phase 1 complete) before writing any code (Phase 2)
  • If topic is ambiguous, pick most common STEM interpretation, note in SCENE_PLAN.md
  • Do not ask clarifying questions mid-task — decide and proceed

Open-Weight Model Rules

Applied always; critical for non-Claude models:

  • from manimlib import * at top of every file — no partial imports
  • Every file self-contained — no cross-file imports between chunks
  • All LaTeX as raw strings: r"\frac{d}{dx}" not "\\frac{d}{dx}"
  • No f-strings containing LaTeX — backslash chars break in f-strings
  • Class names: strict PascalCase, no spaces, must not start with number
  • Keep each construct() under 80 lines — extract _helper() methods if needed
  • Colors by name constant only: BLUE, YELLOW, RED, GREEN, WHITE
  • Camera moves: self.play(self.camera.frame.animate.shift(RIGHT * 2))

ManimGL vs ManimCE — Critical Differences

FeatureManimGL (correct)ManimCE (wrong — will error)
Importfrom manimlib import *from manim import *
Regular textTexText("hello")Text("hello")
MathTex(r"x^2")MathTex(r"x^2")
Create animShowCreation(obj)Create(obj)
Write animWrite(obj)same ✓
Cameraself.camera.frameself.camera
Axes / NumberPlanesame ✓same ✓

What ships with it: 2 files

10.7 KB alongside SKILL.md

references/

Gives 0 of the 12 instructions most test skills give in ~2.7k tokens

Counted across 1,201 of the 2,096 authors here whose files we hold, read 2026-09-06

  • Write a failing test before writing codein 43 of 1201, across 36 files
  • Run the full test suitein 36 of 1201, across 35 files
  • Test only one variable per experimentin 34 of 1201, across 17 files
  • Read product marketing context before asking questionsin 34 of 1201, across 14 files
  • Mock external dependenciesin 34 of 1201, across 30 files
  • Define primary, secondary, and guardrail metricsin 33 of 1201, across 16 files
  • Pre-determine sample size before startingin 31 of 1201, across 14 files
  • Test behavior rather than implementationin 31 of 1201, across 29 files
  • Formulate a hypothesis before designing a testin 30 of 1201, across 13 files
  • Document every test hypothesis, variant, and resultin 29 of 1201, across 11 files
  • Use descriptive test function namesin 25 of 1201, across 21 files
  • Commit to the methodology without stopping earlyin 24 of 1201, across 8 files

Said here and by no other author read

  • write SCENE_PLAN.md before writing any code
  • target exactly 15 seconds per chunk
  • use raw strings for all LaTeX
  • import manimlib in every scene file
  • write all chunk files before rendering
  • make render.sh and merge.sh executable

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. 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.