IEDL Language Reference
Reusable image-edit recipes for the 5AM editor and CLI: adjustments, masks, presets, local analysis, retouching, and masked AI edits.
IEDL is a versioned, line-based recipe language that creates the editable document used by the 5AM image editor. The browser and CLI use the same rendering engine. You can generate a recipe from a brief, edit its text, apply it to different images, and export both the result and a resolved bundle.
Browse the public image-edit examples for visual examples and sample IEDL recipes.
Optional setup
The core CLI does not require IEDL, Node, or Chrome. Image editing is optional:
5am update --runtime-only
This installs the runtime and its locked JavaScript dependencies for your installed CLI version. Install Node.js 20+ to execute image-edit commands. Rendering and input-bound inspection also require compatible Chrome/Chromium; the runner discovers an installed browser automatically. Setup does not install Node or a browser.
Normal CLI updates keep an already-installed managed runtime synchronized. Core-only updates do not download it. You can also opt in during installation with install.sh --with-image-edit. Manually downloaded binaries and older binary-only updaters use the same update --runtime-only setup command.
Use --runtime /path/to/runner.mjs or IEDL_RUNTIME for an explicitly managed runtime, --node /path/to/node for Node, and --browser /path/to/chrome or CHROME_PATH for rendering with a specific browser. External runtime bindings remain your responsibility to maintain.
Generate and render
5am media image-edit generate --brief "Warm portrait, gentle contrast, 4:5 crop. Local adjustments only; no AI selections or generative edits." -o portrait.iedl
5am media image-edit validate portrait.iedl
5am media image-edit render portrait.iedl --input photo.jpg -o edited.jpg --resolved edited.iedl-resolved.json --bundle edited.iedl.zip
generate makes the Gemini HTTP request in Go; the shared JavaScript runtime prepares the prompt/schema and validates the response without receiving credentials. It calls the model through the CLI's normal authenticated Gemini access flow and validates the returned recipe before writing it. It uses model quota even if the resulting recipe contains only local edits. Invalid output is rejected; the CLI does not silently repair it. --model selects a supported model; --overwrite explicitly replaces an existing output file.
validate checks a recipe without rendering or invoking remote editing services. inspect binds an input and reports the plan, including unresolved operations; it does not execute automatic adjustments or generate selections:
5am media image-edit inspect portrait.iedl --input photo.jpg
Rendering writes local files. Uploading an edited copy to the library is a separate action.
File format and parameters
A complete local recipe:
iedl 1
input image
param warmth number default=6 min=-100 max=100
layer tone adjustment
adjust tone temperature=$warmth contrast=8 shadows=6
crop aspect=4:5 anchor=center
output format=jpeg quality=0.92
- Start with
iedl 1and exactly oneinput image. Use one statement per line. - Commands are case-insensitive; field names and identifiers are case-sensitive.
- Identifiers start with an ASCII letter and contain letters, digits,
_, or-, up to 128 characters. Created identifiers must be unique and cannot be reused after deletion. - Strings use JSON double quotes and escaping. Comments begin with
#outside strings/JSON, at the start of a line or after whitespace.color=#ffee00remains a value. - Arrays and objects use JSON. Spatial values inside JSON are strings; curve coordinates are normalized numbers.
- Parameters support
number,boolean,string,dimension, andenum. Numeric defaults are numbers:default=6, notdefault="6". Enum parameters require a nonempty stringvaluesarray; only numbers acceptmin/max. $namereplaces a complete named-field value. There is no arbitrary code, string interpolation, file access, or network call in recipe syntax. A parameter without a default needs an explicit binding.
Override a parameter at execution:
5am media image-edit render portrait.iedl --input photo.jpg --param warmth=8 -o warmer.jpg
Structured recipes use { "version": 1, "operations": [{ "op": "input", "args": ["image"], "fields": {} }] }. Text and structured recipes share validation. Canonical printing preserves operations, not comments or original whitespace.
Coordinates and execution order
Coordinates refer to the EXIF-oriented original, with a top-left origin. Use px for pixels, %w horizontally, %h vertically, and %s for scalar sizes as a percentage of the original's shorter dimension. Brush size and feather radius use scalar units.
Statements build the document in order. Setting a field again replaces that field; separate layers express sequential effects. Within each layer the renderer uses its fixed processing order. Rotation and flips change presentation without rewriting masks or strokes. Clone/heal source sampling uses the original at render resolution.
Relative coordinates make geometry portable, but do not find a face, blemish, or suitable cloning source in a different photograph. AI selections analyze the original. Mask export also uses original-image coordinates.
Operation reference
| Operation | Form | Behavior |
|---|---|---|
| Input | input image | Bind exactly one source. |
| Parameter | param NAME TYPE default=VALUE | Declare a typed reusable value before referencing it. |
| Asset | asset ID | Declare an asset supplied through --asset ID=path or a browser binding. |
| Layer | layer ID KIND | Create an adjustment, retouch, raster, text, or frequency layer. |
| Layer properties | set LAYER opacity=0.5 | Set properties such as enabled, opacity, blend, mask, position, or text. |
| Adjustments | adjust LAYER exposure=0.2 shadows=10 | Set editor sliders: exposure, contrast, highlights, shadows, whites, blacks, temperature, tint, saturation, vibrance, texture, clarity, dehaze, sharpening, denoise, colorNoise. |
| Curves | curve LAYER rgb points=[{"x":0,"y":0},{"x":1,"y":1}] | Channels: rgb/r/g/b. Increasing x values from 0 to 1. |
| HSL | hsl LAYER orange saturation=-5 luminance=3 | Eight bands: red, orange, yellow, green, aqua, blue, purple, magenta. Hue/saturation/luminance: −100…100. |
| Mask | mask ID | Create a manually composed mask. |
| Mask refinement | refine MASK feather=3px density=0.9 | Update refinement, inversion, density, or enabled state. |
| Mask component | component MASK ID KIND points=[...] | Add brush, linear, radial, rectangle, ellipse, lasso, polygon, color, luminance, or raster coverage. |
| Stroke | stroke LAYER ID KIND points=[...] | Clone, heal, spot, patch, dodge, burn, red-eye, liquify, liquify-smooth, or reconstruct. Clone/heal/patch need a source point. |
| Duplicate | duplicate layer SOURCE NEW_ID | Duplicate a layer or mask with a fresh ID. |
| Delete | delete layer ID | Delete a layer, mask, or asset; referenced masks/assets cannot be deleted. |
| Order | order LAYER before=OTHER | Reorder a layer with exactly one of before or after. |
| Crop | crop aspect=4:5 anchor=center | Aspect crop or explicit x/y/width/height inside the original. |
| Rotate | rotate degrees=90 | Set a presentation rotation: 0, 90, 180, or 270 degrees. |
| Flip | flip x=true y=false | Set horizontal/vertical flip flags. |
| Analyze | analyze NAME image input=original | Record local image or mask findings. |
| Auto | auto exposure id=NEW_LAYER | Create an adjustment layer for exposure, white-balance, vibrance, or baseline. |
| Wand | wand NEW_MASK x=20%w y=30%h tolerance=0.1 | Create a local contiguous raster selection. |
| AI selection | select NEW_MASK subject | Create subject/background/sky/object/skin selection. Object requires x/y. |
| Preset | apply family-natural@1 id=NEW_LAYER strength=0.5 | Expand a versioned preset into editable operations. |
| Erase | erase MASK id=NEW_LAYER | Run the existing Magic Eraser removal operation through an explicit mask. |
| Generative edit | generative-edit id=NEW_LAYER mask=MASK prompt="..." | Create a masked raster layer from a prompt-guided remote edit. |
| Output | output format=jpeg quality=0.92 | JPEG, PNG, or WebP; quality 0.1…1. |
Creation matters: select and wand create masks themselves; do not also write mask with that ID. auto and apply create layers themselves; do not predeclare those layers. Use refine, adjust, or set to modify the created objects. This avoids duplicate-identifier errors.
Mask components combine with operation=add, subtract, or intersect; the first component establishes coverage. White applies the effect and black protects the image. Disabling a mask with enabled=false bypasses it and applies the layer everywhere. Layer blends include normal, multiply, screen, overlay, soft-light, and luminosity.
Local analysis and smart baseline
Analyze once and reuse those findings for separate adjustments:
iedl 1
input image
analyze scene image input=original
auto exposure id=lighting analysis=scene
auto vibrance id=color analysis=scene
apply family-natural@1 id=look strength=0.5
output format=jpeg quality=0.92
input=original measures the unedited image. input=current measures preceding edits and presentation transforms. Named findings are immutable; declare a new analysis to measure after a correction. They describe light/color appearance, not event categories such as weddings or engagements.
For subject-local correction:
iedl 1
input image
select subjectMask subject
analyze subjectLight image input=original mask=subjectMask
auto baseline id=subjectTone analysis=subjectLight mask=subjectMask
output format=jpeg quality=0.92
Masked image analysis requires input=original, and its auto consumer must use the same mask. auto baseline and auto vibrance require named image analysis. Exposure and white balance can use named findings or analyze preceding edits themselves.
Smart baseline is an experimental conservative starting point. It may intentionally make no change when evidence is insufficient. Requested exposure/white-balance/vibrance can fail when no recommendation is available. Analysis uses bounded previews and does not replace full-resolution photographic review.
Preset catalog
Use apply PRESET@1, not invented function syntax such as skinSmooth(). These looks are experimental and editable; review their effect on each photograph. Strength ranges from 0 to 1. Required masks are never generated implicitly.
| Preset | Default strength | Required selection |
|---|---|---|
skin-smooth@1 | 0.4 | Skin |
subject-pop@1 | 0.65 | Subject |
bw-classic@1 | 1 | None |
bw-high-contrast@1 | 1 | None |
bw-matte@1 | 1 | None |
teal-orange@1 | 0.65 | None |
cinematic@1 | 0.7 | None |
wedding-clean@1 | 0.7 | None |
wedding-airy@1 | 0.6 | None |
golden-romance@1 | 0.6 | None |
editorial-portrait@1 | 0.65 | None |
soft-pastel@1 | 0.65 | None |
indoor-celebration@1 | 0.65 | None |
family-natural@1 | 0.7 | None |
autumn-warmth@1 | 0.6 | None |
landscape-crisp@1 | 0.65 | None |
woodland-soft@1 | 0.65 | None |
night-sky-natural@1 | 0.5 | None |
milky-way-definition@1 | 0.5 | Sky |
dark-moody@1 | 0.65 | None |
B&W presets need strength 1 for full monochrome; lower strengths blend color back. Skin smoothing needs an explicit skin mask. Skin selection is experimental: inspect eyes, brows, lips, teeth, hair, and edges rather than assuming perfect protection. The recipe lab's Mask review section supports full-resolution coverage inspection and downloadable observations.
Masked AI edits
iedl 1
input image
param instruction string default="Create a soft sunset matching the existing lighting."
select sky sky
refine sky feather=3px
generative-edit id=sunset mask=sky prompt=$instruction
output format=png
Save this as sky.iedl, then bind the actual library source:
5am media image-edit render sky.iedl --media-id MEDIA_ID -o sunset.png --resolved sunset.json --bundle sunset.iedl.zip
Use --media-id instead of --input for remote edits; the CLI downloads the matching original. Subject/background/sky/object/skin selection and erase/generative-edit use the authenticated backend and normal access/credit checks. A prompt must be nonblank and at most 4000 characters. Any supported existing mask can be supplied. erase MASK id=cleanup uses the backend's default removal prompt.
Keep credentials and endpoint URLs out of recipes. Each explicit execution can create a new paid request. Do not automatically retry an ambiguous remote failure.
Bundles, masks, and batches
A reusable recipe resolves analysis and selections separately for each input. A resolved bundle preserves the document, concrete adjustments, generated assets, source hashes, and rendering provenance for one result:
5am media image-edit render edited.iedl.zip --input photo.jpg -o replay.jpg
5am media image-edit render sunset.iedl.zip --input photo.jpg --mask sky -o sky-mask.png
5am media image-edit batch portrait.iedl --input-dir photos --output-dir edited --report batch.json
Use the original source corresponding to each bundle; a mismatched source is rejected. Bundle replay reuses stored generated assets. Masks export at original resolution. Local batch input is nonrecursive PNG/JPEG/WebP and runs serially; use local-only recipes for this directory workflow. Remote edits need explicit matching library media IDs per image.
Bind imported assets with repeated --asset name=path flags. Recipes cannot read arbitrary paths or fetch arbitrary URLs. --timeout sets a per-image deadline; scripts, images, layers and assets also have runtime limits. Full-image decode and export still consume memory beyond the bounded analysis preview.
Matching engine versions and assets improve reproducibility, but browser/GPU/font differences mean output is not guaranteed universally byte-identical.
LLM skills and workflow automation
The repository's cli/skills/iedl/SKILL.md is the focused skill for direct recipe authoring. Its references/IMAGE_EDIT_DSL.md supplies the detailed field ranges and document semantics; references/IEDL_TEST_HARNESS.md and references/IEDL_GENERATION_EVAL.md describe verification. Read the skill and those references when integrating an LLM that produces IEDL directly.
Workflow Python should stay small: ask 5am media image-edit generate --brief ... to author a recipe, validate the saved file, and render through subprocess argument lists. It should not embed the full IEDL specification or directly control model APIs or Puppeteer. If a user supplies an approved recipe, copy its content unchanged and validate/render it instead of generating a replacement.
Managed workflows require an explicitly provisioned image-edit runner. A larger machine size alone does not supply Node, Chromium, or the bundle. If that capability is unavailable, produce diagnostics rather than attempting speculative generation/rendering or installing dependencies during a managed run.
Review and troubleshooting
- Runtime missing: run
5am update --runtime-onlyfor the installed release, or bind an existing runtime explicitly. - Node/browser missing: install Node 20+ and compatible Chrome/Chromium as needed, or supply the corresponding executable override.
- Duplicate identifier: remove a redundant declaration; selection/auto/preset operations create their own objects.
- Parameter requires number: use a numeric default/binding, not a quoted numeric string.
- Selection or remote edit failed: inspect the backend error and source binding before retrying. Local analysis does not need a segmentation service.
A valid recipe is not automatically a good photograph. Review before/after results, facial detail, clipping, color casts, halos, and mask boundaries. The recipe lab supports experiments and mask review; Portrait Balance supports a small album preview and approved-recipe workflow handoff. Live recipe-generation evals measure brief adherence separately from local rendering and human visual review.