Install
$ agentstack add skill-shihabshahrier-manim-coding-skill-test-manim ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
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
| Arg | Default | Values | |-----|---------|--------| | topic | required | any STEM subject string | | --duration | 30 | 30, 60, 90, 120 (seconds) | | --model | session model | identifier 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:
- Hook (first chunk): One striking visual that poses the core question
- Build (middle chunks): One concept per chunk, each building on prior
- 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.8–1.5 - Key reveals:
run_time=1.5–2.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:
- Read full error — identify exact line + error type
- Check
references/manim-gl-api.mderror table for known fixes - Fix minimum code — do not rewrite whole chunk
- Re-render only failed chunk:
manimgl scenes/chunk_NN_name.py ClassName -w -q --hd --video_dir output/chunks --file_name chunk_NN_name - Log in
SCENE_PLAN.mdunder## 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
.pychunk files in one batch before running any render - Load references once —
manim-gl-api.mdat Phase 2 start,storytelling.mdat Phase 1 start - Run
render.shonce 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
| Feature | ManimGL (correct) | ManimCE (wrong — will error) | |---------|-------------------|------------------------------| | Import | from manimlib import * | from manim import * | | Regular text | TexText("hello") | Text("hello") | | Math | Tex(r"x^2") | MathTex(r"x^2") | | Create anim | ShowCreation(obj) | Create(obj) | | Write anim | Write(obj) | same ✓ | | Camera | self.camera.frame | self.camera | | Axes / NumberPlane | same ✓ | same ✓ |
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: shihabshahrier
- Source: shihabshahrier/manim-coding-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.