Metadata-Version: 2.4
Name: easymanim
Version: 0.2.0
Summary: A Python framework layer for writing concise, intent-first Manim animations.
Project-URL: Homepage, https://github.com/ankushbisht01/EasyManim
Project-URL: Documentation, https://github.com/ankushbisht01/EasyManim#readme
Project-URL: Issues, https://github.com/ankushbisht01/EasyManim/issues
Author: EasyManim contributors
License: MIT
License-File: LICENSE
Keywords: animation,framework,manim,visualization
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: manim>=0.20.1
Requires-Dist: networkx>=3.0
Requires-Dist: numpy>=1.24
Provides-Extra: dev
Requires-Dist: mkdocs-material>=9.5; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pre-commit>=3.6; extra == 'dev'
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: types-networkx; extra == 'dev'
Requires-Dist: types-pygments; extra == 'dev'
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == 'mcp'
Description-Content-Type: text/markdown

# EasyManim

[![PyPI version](https://badge.fury.io/py/easymanim.svg)](https://badge.fury.io/py/easymanim)
[![Python Versions](https://img.shields.io/pypi/pyversions/easymanim.svg)](https://pypi.org/project/easymanim/)
[![CI](https://github.com/example/easymanim/actions/workflows/ci.yml/badge.svg)](https://github.com/example/easymanim/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/example/easymanim/graph/badge.svg)](https://codecov.io/gh/example/easymanim)

EasyManim is a Python framework layer over Manim Community Edition. It keeps Manim as the runtime, but lets authors write scenes in terms of intent: elements, beats, themes, and common animation verbs.

## Installation

```bash
pip install easymanim
```

This repository currently contains the first maintainable framework slice: enough to build text/math scenes, group elements, run dry plans, register extensions, and drop down to raw Manim when needed.

```python
from easymanim import Scene


class CompletingTheSquare(Scene):
    def build(self):
        title = self.title("Completing the square")
        self.write(title)

        eq = self.math(r"x^2 + 6x + 5 = 0", isolate=[r"x^2", r"6x", r"5"])
        self.write(eq, below=title)

        self.morph(eq, r"(x + 3)^2 = 4", match="tex")
        self.highlight(eq, color="success")
```

## Commands

```bash
easy check examples/quadratic_formula.py QuadraticFormula --strict --json
easy plan examples/quadratic_formula.py QuadraticFormula
easy storyboard examples/two_pointers.py TwoPointers   # one PNG per beat
easy render examples/quadratic_formula.py QuadraticFormula --quality low
easy prompt   # print the API card — paste it into any LLM to write EasyManim
easy new element orbit   # scaffold a plugin: your own self.orbit(...) verb
```

`check` and `plan` use a dry-run adapter, so they validate EasyManim code without rendering. `render` delegates to the Manim CLI.

### Writing scenes with an LLM

EasyManim is new, so no model has it in training data. Three ways to fix that,
in increasing order of automation:

```bash
easy prompt                       # 1. paste the API card into any chat
easy agent                        # 2. install it into AGENTS.md / CLAUDE.md
pip install "easymanim[mcp]"      # 3. let agents discover the tools themselves
easy mcp
```

The card is generated from the live registry, so **your own plugins are
documented automatically**. The MCP server exposes four tools — `api_card`,
`check_scene`, `plan_scene`, `scaffold_plugin` — to any MCP client.

Then close the loop: `easy check --json` returns structured errors (with
`did_you_mean` suggestions) the model self-corrects from, and `easy
storyboard` renders one PNG per beat so a multimodal model can critique its
own frames before a full render. With narration audio,
`self.sync("narration.words.json")` pins every `beat(say=...)` to real word
timestamps — see [examples/two_pointers.py](examples/two_pointers.py) and
[docs/llm-authoring.md](docs/llm-authoring.md).

### Domains we never thought of

The verb list stays small on purpose — growing it forever would just rebuild
Manim. Instead, any "things and relationships" domain is described as data:

```python
cascade = self.diagram(
    {"apc": "Antigen-presenting cell", "helper": "Helper T cell", "b": "B cell"},
    [("apc", "helper", "presents"), ("helper", "b", "activates")],
    layout="tree",
)
self.show(cascade, at="center")
self.ripple(cascade)              # every verb still applies
```

Layout is automatic and nodes stay addressable (`cascade["b"]`). When a domain
truly needs a new visual noun, `easy new element <name>` scaffolds a plugin —
raw Manim lives inside it, scenes stay intent-first, and the API card picks it
up. See [examples/unseen_domain.py](examples/unseen_domain.py) and
[docs/extending.md](docs/extending.md).

## Diagram Vocabulary

Beyond text and math, EasyManim ships the shapes explainer videos reach for over
and over. Each returns a group whose pieces stay addressable.

```python
cpu = self.panel(3.0, 1.3, at=(-3, 0), text="CPU", sub="16 cores")
stack = self.layers([("hardware", "muted"), ("kernel", "accent"), "your code"])
cores = self.units(16, cols=8)  # countable resources
cap = self.meter(10, filled=8)  # capacity, and overflow
term = self.terminal([("$ uname -a", "text"), ("Darwin", "warning")])
chart = self.comparison([("power draw", 0.5, 0.82)])

self.emphasize(cpu["box"], color="warning")  # the frame, not its text
self.travel(pulse, [l.at("center") for l in stack.children])
```

Anchors (`element.at("right")`) remove hand-computed half-widths, and
`theme.timing.pace` retimes every hold in a film from one number — useful when a
silent cut has to grow room for narration. See
[`examples/diagram_primitives.py`](examples/diagram_primitives.py).

## Design Position

EasyManim is not a Manim replacement. Every element exposes `.raw`, and every scene exposes `.manim`, so raw Manim remains available:

```python
eq = self.math("E = mc^2")
eq.raw.set_color_by_tex("E", "#ffcc00")
self.manim.play(eq.raw.animate.shift(UP))
```

See [DESIGN.md](DESIGN.md) for the larger framework direction.

