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:

sh
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

sh
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:

sh
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
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 1 and exactly one input 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=#ffee00 remains a value.
  • Arrays and objects use JSON. Spatial values inside JSON are strings; curve coordinates are normalized numbers.
  • Parameters support number, boolean, string, dimension, and enum. Numeric defaults are numbers: default=6, not default="6". Enum parameters require a nonempty string values array; only numbers accept min/max.
  • $name replaces 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:

sh
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

OperationFormBehavior
Inputinput imageBind exactly one source.
Parameterparam NAME TYPE default=VALUEDeclare a typed reusable value before referencing it.
Assetasset IDDeclare an asset supplied through --asset ID=path or a browser binding.
Layerlayer ID KINDCreate an adjustment, retouch, raster, text, or frequency layer.
Layer propertiesset LAYER opacity=0.5Set properties such as enabled, opacity, blend, mask, position, or text.
Adjustmentsadjust LAYER exposure=0.2 shadows=10Set editor sliders: exposure, contrast, highlights, shadows, whites, blacks, temperature, tint, saturation, vibrance, texture, clarity, dehaze, sharpening, denoise, colorNoise.
Curvescurve LAYER rgb points=[{"x":0,"y":0},{"x":1,"y":1}]Channels: rgb/r/g/b. Increasing x values from 0 to 1.
HSLhsl LAYER orange saturation=-5 luminance=3Eight bands: red, orange, yellow, green, aqua, blue, purple, magenta. Hue/saturation/luminance: −100…100.
Maskmask IDCreate a manually composed mask.
Mask refinementrefine MASK feather=3px density=0.9Update refinement, inversion, density, or enabled state.
Mask componentcomponent MASK ID KIND points=[...]Add brush, linear, radial, rectangle, ellipse, lasso, polygon, color, luminance, or raster coverage.
Strokestroke LAYER ID KIND points=[...]Clone, heal, spot, patch, dodge, burn, red-eye, liquify, liquify-smooth, or reconstruct. Clone/heal/patch need a source point.
Duplicateduplicate layer SOURCE NEW_IDDuplicate a layer or mask with a fresh ID.
Deletedelete layer IDDelete a layer, mask, or asset; referenced masks/assets cannot be deleted.
Orderorder LAYER before=OTHERReorder a layer with exactly one of before or after.
Cropcrop aspect=4:5 anchor=centerAspect crop or explicit x/y/width/height inside the original.
Rotaterotate degrees=90Set a presentation rotation: 0, 90, 180, or 270 degrees.
Flipflip x=true y=falseSet horizontal/vertical flip flags.
Analyzeanalyze NAME image input=originalRecord local image or mask findings.
Autoauto exposure id=NEW_LAYERCreate an adjustment layer for exposure, white-balance, vibrance, or baseline.
Wandwand NEW_MASK x=20%w y=30%h tolerance=0.1Create a local contiguous raster selection.
AI selectionselect NEW_MASK subjectCreate subject/background/sky/object/skin selection. Object requires x/y.
Presetapply family-natural@1 id=NEW_LAYER strength=0.5Expand a versioned preset into editable operations.
Eraseerase MASK id=NEW_LAYERRun the existing Magic Eraser removal operation through an explicit mask.
Generative editgenerative-edit id=NEW_LAYER mask=MASK prompt="..."Create a masked raster layer from a prompt-guided remote edit.
Outputoutput format=jpeg quality=0.92JPEG, 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
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
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.

PresetDefault strengthRequired selection
skin-smooth@10.4Skin
subject-pop@10.65Subject
bw-classic@11None
bw-high-contrast@11None
bw-matte@11None
teal-orange@10.65None
cinematic@10.7None
wedding-clean@10.7None
wedding-airy@10.6None
golden-romance@10.6None
editorial-portrait@10.65None
soft-pastel@10.65None
indoor-celebration@10.65None
family-natural@10.7None
autumn-warmth@10.6None
landscape-crisp@10.65None
woodland-soft@10.65None
night-sky-natural@10.5None
milky-way-definition@10.5Sky
dark-moody@10.65None

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
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:

sh
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:

sh
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-only for 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.