An API for an LLM to create images via brush strokes
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Documented (README)
git clone https://github.com/Gemberkoekje/EaselAPI && cp EaselAPI/*.md ~/.claude/agents/Resumen de Subagents
# Easel
**Can an LLM paint with real brush strokes, rather than draw with pixels? Yes — this is
the API for it.**
Easel is a headless painting engine for AI agents: brushes, paint load, wet blending
and canvas texture, driven from Python, from a shell, or over MCP. A brush carries a
finite load of paint and runs out along a stroke. Paint lands wet and mixes with what
is already there, in a pigment model where blue and yellow make green rather than grey.
The canvas has tooth, and a brush low on paint catches only the high points — so dry
brush is not a special effect, it is what happens when you run out of paint on rough
canvas. Between strokes you look at your own work, which is the whole point: the engine
is built for an agent that can see what it just did.
It is not a drawing library, not a rasteriser, and not an image generator — nothing
here turns a prompt into a picture. You choose and make every mark. There are no
layers, and no undo that costs nothing: you work in passes, and when something is wrong
you paint over it.
**Read the guide before you paint.** The engine is only the brush;
[`PAINTER.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/PAINTER.md) is the method, and six measured runs say the method
is the half that matters. It ships inside the package, so there is nothing to go and
find: **`easel guide`** prints its first page — the whole workflow, under a thousand
words — and `easel guide --full` prints the rest.
```python
from easel import Session, blob, cell
s = Session(1024, 768, texture="linen", ground="toned_grey", seed=7)
s.palette["shadow"] = s.palette.mix("ultramarine", "burnt_umber", 0.4)
s.block_in(blob(cell("D5")), brush="bristle", color="shadow", density=0.8)
s.look(values=True) # check the value structure
s.stroke([(0.2, 0.6), (0.6, 0.55), (0.9, 0.62)], "bristle", "yellow_ochre")
s.export("painting.png")
```
## Three paintings, made this way

*[**Inside a car wash, from the driver's seat**](https://github.com/Gemberkoekje/EaselAPI/blob/main/paintings/car_wash/NOTES.md) — 206
strokes of a 300 budget, 1152×720 linen, no reference photograph. The nineteen pass
scripts beside it reproduce that PNG byte for byte.*

*[**Three pears on a kitchen windowsill**](https://github.com/Gemberkoekje/EaselAPI/blob/main/paintings/windowsill_pears/NOTES.md) — 224
strokes, 1024×768 linen, no reference photograph.*

*[**A lighthouse on a rocky headland at dusk**](https://github.com/Gemberkoekje/EaselAPI/blob/main/paintings/lighthouse_dusk/NOTES.md) — 184
strokes of a 300 budget, 1024×768 linen, no reference photograph. Eighteen rehearsals,
none of them charged; the ten pass scripts beside it reproduce that PNG byte for byte.*
All three were painted by a language model working from [`PAINTER.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/PAINTER.md),
one call to this API at a time, with no human hand on the canvas and nothing traced.
Every stroke is in the log, every time-lapse was rebuilt from it, and the notes beside
each painting say what went wrong as well as what went right.
[`PAINTINGS.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/PAINTINGS.md) gathers the record, and *The worked examples* below
says what each one is made of.
**If you are about to paint from the guide yourself: have you decided what to paint?**
If you have, these are yours to study and the scripts beside them are the best thing
here. If you have not, do not look — a worked example names a subject and a named
subject chooses for you, as six of six fresh sessions once demonstrated by painting a
noun the guide had merely listed in passing. Decide first, then look.
## The brushes themselves

*Every brush, size and pressure profile, on each canvas texture. Regenerate with
`python scripts/make_brush_sampler.py` — this sheet is the project's primary test
artefact, and looking at it catches what the test suite cannot.*

*A mass does not have to be a rectangle. Each row is one way of building a shape,
each column a way of sweeping it; the last column is the box that mass would have
been. Regenerate with `python scripts/make_shape_sampler.py`.*
## Install
Requires Python 3.12 or newer. Only numpy and Pillow — nothing that is painful to
build on Windows.
```bash
pip install easel-paint # the engine, the CLI and the Python API
pip install "easel-paint[mcp]" # and the MCP server
```
From a checkout, `pip install -e .` and `pip install -e ".[mcp]"` do the same two
things.
Either installs an `easel` command. Pip puts it in the interpreter's scripts
directory, which is often not on `PATH` (it warns when it is not), so
`python -m easel ...` is always available as the same command by another name.
The MCP server is an opt-in extra because nothing else in the engine imports it.
See *MCP server* below.
## If you are an LLM agent, read PAINTER.md
[`PAINTER.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/PAINTER.md) is the guide written for you. It teaches the *workflow* —
tone the ground, paint back to front, check values, refine, edges, highlights
last — rather than listing functions, and it opens with *the first hour*: the whole
method on one page, so the eight warm-up exercises come before anything else.
It is one file of five, split by what you do with each rather than by subject, because
three painters each said the same two things — the guide is long, and the essay in it is
what made the rules stick. Nothing was cut to shorten it; it was moved, and `PAINTER.md`
is now held to a word budget by the test suite.
| | |
|---|---|
| [`PAINTER.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/PAINTER.md) | the method: the order of work, the mistakes, the exercises, the checklist. Held in your head |
| [`PAINTING.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/PAINTING.md) | the reasons: colour, wet paint, the brushes, working from a reference. Read once |
| [`RECIPES.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/RECIPES.md) | the procedures: the calls in order for a kind of thing, and what it looks like when it goes wrong |
| [`REFERENCE.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/REFERENCE.md) | the facts: units, defaults, what each argument does |
| [`CALIBRATION.md`](https://github.com/Gemberkoekje/EaselAPI/blob/main/CALIBRATION.md) | the numbers behind the rules, each with what it was measured on |
The engine is designed around one habit:
> Look every five to fifteen strokes. A stroke you did not look at was a guess.
[`llms.txt`](https://raw.githubusercontent.com/Gemberkoekje/EaselAPI/main/llms.txt) is
the same signpost in the format a model fetching this repository is increasingly told
to look for: the summary, what to know before reading further, and where each document
is, in about 850 words.
## What is in the box
| Piece | What it does |
|---|---|
| `Session` | The one object you hold. Canvas, palette, seed, history, `look()`. |
| `Canvas` | Linear-light RGB plus `wetness`, `thickness`, `sketch` (graphite) and canvas `height` (tooth). |
| Brushes | `round_soft`, `round_hard`, `liner`, `flat`, `bristle`, `knife`, `smudge`. Procedural tips, and `tip_wobble` gives a round one a silhouette of its own, redrawn per mark. |
| `Palette` | A limited pigment set with no black. Mix, tint, shade, and name your mixes. |
| Regions | `region("top-left")`, `cell("D6")`, `horizon(0.4)`, `below(...)`, `between(...)`. |
| Shapes | A mass that is not a box: `blob`, `ellipse`, `hull`, `union`, `ribbon`, `polygon`, and `s.circle()` for one that is round in pixels on any canvas. `smooth()` cuts the corners off an outline. Any of them goes where a region goes. |
| Masses | `block_in(place, ...)` fills a rectangle *or a shape* with overlapping passes, stopping at the silhouette, or drawing its contour with `edge="clean"`; `solid=True` when it has to be solid paint, because density spaces the passes rather than filling them. `sweep(edge, ...)` lays a mass as passes along its own boundary, stepped inward. Both emit ordinary strokes. |
| Passages and repairs | `scumble(band, a, b, n)` lays a soft passage as `n` overlapping passes stepping between two values — the thing a gradient tool would be for, as paint — and `direction="inward"` runs them round a patch instead of across it, for a value falling off from a centre. `cover(place, color)` buries a mistake with every clause of the correction recipe already set. `smudge(edge, ...)` loses an edge along its own shape: points, or a mass whose outline it walks. |
| `look()` | Grid overlay, greyscale values, region crop, side-by-side, diff, landmarks, and a fine grid of labelled tenths inside a crop. |
| DrawLo que la gente pregunta sobre EaselAPI
¿Qué es Gemberkoekje/EaselAPI?
+
Gemberkoekje/EaselAPI es subagents para el ecosistema de Claude AI. An API for an LLM to create images via brush strokes Tiene 0 estrellas en GitHub y su última actualización registrada es del 2026-09-12.
¿Cómo se instala EaselAPI?
+
Puedes instalar EaselAPI clonando el repositorio (https://github.com/Gemberkoekje/EaselAPI) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.
¿Es seguro usar Gemberkoekje/EaselAPI?
+
Nuestro agente de seguridad ha analizado Gemberkoekje/EaselAPI y le ha asignado un Trust Score de 87/100 (tier: Trusted). Revisa el desglose completo de comprobaciones superadas y flags en esta página.
¿Quién mantiene Gemberkoekje/EaselAPI?
+
Gemberkoekje/EaselAPI es mantenido por Gemberkoekje. La última actividad registrada en GitHub es del 2026-09-12, con 1 issues abiertos.
¿Hay alternativas a EaselAPI?
+
Sí. En ClaudeWave puedes explorar subagents similares en /categories/agents, ordenados por popularidad o actividad reciente.
Despliega EaselAPI en tu cloud
Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.
¿Mantienes este repo? Añade un badge a tu README
Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.
[](https://claudewave.com/repo/gemberkoekje-easelapi)<a href="https://claudewave.com/repo/gemberkoekje-easelapi"><img src="https://claudewave.com/api/badge/gemberkoekje-easelapi" alt="Featured on ClaudeWave: Gemberkoekje/EaselAPI" width="320" height="64" /></a>Más Subagents
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
The agent that grows with you
Java 面试 & 后端通用面试指南,覆盖计算机基础、数据库、分布式、高并发、系统设计与 AI 应用开发
Build Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.
The agent engineering platform.
Makes your AI agent think like the laziest senior dev in the room. The best code is the code you never wrote.