iamlukethedev / herald-canvas
Make and edit pictures in Herald Canvas, the layered image editor in Herald OS - posters, banners, thumbnails, collages and photo fixes through the canvas tool, with editable text and shape layers, layer effects (shadows, strokes, glows) copied between layers, masks, alignment and guides, auto tone and colour, filters (sharpen, denoise, blur), colour lookup tables, on-device background removal and content-aware fill, generated pictures placed where asked, Photoshop files opened and exported with their layers, how to plan an edit from a description, plus the .comp project format and every adjustment setting
Herald Canvas
Herald Canvas is the image editor built into Herald OS: layers, folders, masks, blend modes,
adjustment layers, editable text and shapes, drawn on the GPU. The person has the usual tools too
(selections, brush, fill, gradient, transform, crop). Use it whenever the person wants a picture
made or changed:
"make a poster for Saturday's gig", "warm this photo up", "put our logo on these", "make a
YouTube thumbnail". They watch each change appear in the Canvas window, and every change is one
step they can undo there (⌘Z, or canvas action=undo).
The workflow
Start.
canvas action=new name="Gig poster" width=1080 height=1350 background="#101014"
makes a project in~/Pictures/Herald Canvas/and opens it; it answers with thepath. To
work on something that exists,canvas action=open path="~/Pictures/photo.jpg": an image
becomes a new project there (the original file is never changed) and the answer gives itspath; a.compproject opens as it is. A Photoshop document (.psd,.psb) keeps its layers,
folders, masks, text and the adjustments Herald has, and the answer lists anything approximated
(tell the person what changed). HEIC, TIFF and camera RAW open where the system can convert
them; on Linux an error names the packages to install. A canvas is at most 30,000 pixels a side
and 100 million in all. Withoutproject, actions work on the image in front.Build it in layers, bottom to top. Each
add_layerlands above the active layer:a picture:
source="~/Downloads/band.jpg"orsource="https://…"; it fits inside the canvas,
centred (fit=coverfills it,fit=nonekeeps its own size, or givex,y,width).- a colour block:
color="#ff5a36" x=0 y=1100 width=1080 height=250. a gradient:
gradient="#00000000,#000000cc" angle=90 y=700 height=650(a fade to dark at
the bottom, under text). Colours run first to last, each with an optional position
(gradient="#1b1340 0%, #6b2d5c 55%, #ffb347"; ones without share the space between), and
transparent colours fade while keeping the colour beside them.stylelays it out: linear
(the default, alongangle), radial (from the box's centre out to its corners, a vignette or
a spotlight), angle (a sweep around the centre), reflected (mirrored from the centre line) or
diamond.- an empty layer to group with others: no source, colour or gradient.
Words. `add_text content="NIGHT\nMARKET" x=72 y=420 font="Helvetica Neue Bold" size=180
color="#ffffff"` makes a text layer the person can edit later (double-click it with the Type
tool). Point text:xis its left edge, or its centre withalign=center, or its right edge
withalign=right;yis its top. Givewidthfor a paragraph that wraps inside a box fromx(at least 16 pixels).sizeis pixels, 1…2000;trackingadds pixels between letters
(−100…1000; a little negative tightens a big headline);leadingis the line spacing from
baseline to baseline in pixels (0…5000; 0, the default, is automatic: 120% of the size, and
about the size itself sets a headline tight). Fonts are installed families with an optional style ("Avenir Next
Demi Bold", "Georgia Italic"); a missing font falls back to the system font, so check the
preview.set_text layer="Headline" content=… color=…changes it in place and keeps its size,
turn and position. Text from Compositor or Photoshop may carry per-letter colour and font runs:
they stay through edits where the edited range allows, and a newcolororfontfor the
whole text replaces them.Shapes.
add_shape kind=rounded x=72 y=900 width=936 height=300 color="#ff5a36"(a
rectangle withradius, orkind=rectangle,kind=ellipsefor circles and ovals,kind=line
fromx, ybywidthacross andheightdown,lineWidththick). Panels behind text, rules,
badges and dots are shapes, not filled boxes: they stay crisp and editable.set_shape layer="Date panel" kind=ellipse color="#ffb347"restyles one in place:kind
(rectangle, rounded, ellipse, line; a shape becoming a line runs corner to corner in its box),color,radius(rectangles) orlineWidth(lines).Arrange.
set_layer layer="band" x=… y=… width=…(one side alone keeps the proportions),rotation=-8,opacity=0.8,blend="Multiply",order=top,visible=false,folder="Background".group layers="band,glow" name="Hero"makes a folder. Line layers up
exactly withalign layers="Logo,Badge" edge=bottom(each other; one layer, orto=canvas,
lines up with the canvas,margin=72keeping that far from its edges;to=selectionwith what
the person selected; two edges at once,edge="center,middle"), and space three or more evenly
withalign layers="A,B,C" distribute=horizontal(equal gaps;vertical, or by an edge:left,center, …). Layers line up by what they show, not by transparent margins.
Guides lay out the page and everything snaps to them in the window:guides guide=add margins=64 columns=12 gutter=24(margins as pixels or"6%"of the short
side, columns between them),guides guide=add axis=vertical position="50%", `guides
guide=add center=true,guides guide=remove axis=horizontal position=900,guides guide=clear`
andguides guide=list. They never export.Grade. For a photo, start with
auto_adjust(kind=tone, the usual first step for a dull
photo,contrast, orcolorto take out a colour cast too): it adds an editable Levels layer
worked out from the picture. Then `add_adjustment kind="Hue/Saturation" settings={"saturation":
20}` and the like (every kind and field is under Adjustment settings below). An adjustment
changes everything below it; withclip=trueonly the layer right below. Change it later withset_adjustment layer="Hue/Saturation" settings={"saturation": 35}(merged over what it has;canvas action=layersshows each adjustment'ssettings).Polish. `set_effects layer="Headline" effects={"shadow": {"distance": 8, "blur": 16,
"opacity": 0.45}}` adds a drop shadow; strokes, glows, inner shadows and colour overlays work the
same way (see Layer effects below), andset_effects layer="Subtitle" from="Headline"copies
one layer's effects onto another.mask layer="Photo" mask=hideand friends show or hide parts
of a layer without erasing anything.filtersharpens, denoises or blurs a layer's pixels (see
Filters below).The canvas.
resize width=1080 height=1920 anchor=topgrows or cuts the canvas around an
anchor (layers keep their pixels, so nothing is lost);resize scale=0.5, orimage=truewith
a width, scales everything instead.crop x=0 y=135 width=1080 height=1080keeps a box;crop ratio=4:5keeps the largest centred box of that shape (1:1,3:2,16:9,9:16,original, or with a box, holds it to the ratio);crop angle=-1.5first turns the picture
that many degrees clockwise (negative is counterclockwise) to level a tilted horizon, then keeps
the largest box with no empty corners.Look before you say it is done.
canvas action=previewanswers with a PNGfile; view it,
then fix what is off. Do this after every few steps on anything that matters.Deliver.
canvas action=export to="~/Desktop/gig-poster.png"(or.jpgwithquality=0.9,.webpup to 16,383 pixels a side;scale=0.5for half size). For a printer
or a designer,.psd(orformat=psd) keeps the layers, folders, masks, clipping, blend modes,
text and the adjustments Photoshop has (Herald's own eight among them), at full size; Grain, the
blurs and Add Noise show only in its flattened image, and shapes become pixels; the answer lists
what was approximated. Replacing
a file needsoverwrite=true, and the person is asked first. Projects save themselves after
every change.
canvas action=layers lists everything with ids, kinds, placement and clipping: use it to find
names and to check what is where. Ids are stable; names are friendlier (the topmost layer with a
name wins). canvas action=history lists every step, the person's and yours, with the current one
marked; undo steps=3 (or redo) moves through several at once.
Good design habits
Ask one question when the brief is thin (size, words, colours); otherwise choose and say what
you chose. Common sizes: Instagram post 1080×1350, story 1080×1920, YouTube thumbnail
1280×720, A4 print 2480×3508 at 300 ppi, slide 1920×1080.Keep a clear hierarchy: one focal image, at most two type sizes, generous margins (about 6% of
the short side), and a limited palette pulled from the photo.Put text on calm areas, over a gradient fade or on a shape panel, and check contrast in the
preview. Big headlines read best bold with tight tracking; body text wants a paragraphwidth
of about 60 characters and 1.2 to 1.4 line spacing.Prefer adjustment layers to changing pixels: they stay editable, and the person can switch them
off.- Name layers for what they are ("Headline", "Sky"), and folder related pieces.
- Never use pictures the person has not given you or asked you to find; mention sources.
A poster, start to finish
canvas action=new name="Night market" width=1080 height=1350 background="#0d0d12"
canvas action=guides guide=add margins=72
canvas action=add_layer source="~/Pictures/market.jpg" fit=cover name="Photo"
canvas action=auto_adjust kind=color clip=true
canvas action=add_adjustment kind="Color Balance" clip=true settings={"midCyanRed": 12, "midYellowBlue": -14, "highlightYellowBlue": -8}
canvas action=add_layer gradient="#0d0d1200,#0d0d12f0" angle=90 y=650 height=700 name="Fade"
canvas action=add_text content="NIGHT\nMARKET" x=72 y=700 font="Helvetica Neue Bold" size=168 leading=150 tracking=2 color="#fff4e6" name="Headline"
canvas action=set_effects layer="Headline" effects={"shadow": {"distance": 6, "blur": 18, "opacity": 0.5}}
canvas action=add_shape kind=line x=72 y=1100 width=240 lineWidth=8 color="#ffb347" name="Accent rule"
canvas action=add_shape kind=rounded x=72 y=1140 width=600 height=120 radius=24 color="#ffb347" name="Date panel"
canvas action=add_text content="Saturday 9 November · 6 pm till late" x=104 y=1172 width=540 font="Helvetica Neue Medium" size=40 color="#0d0d12" name="Date"
canvas action=align layers="Date panel,Date" edge=middle
canvas action=preview
canvas action=set_text layer="Headline" size=180
canvas action=export to="~/Desktop/night-market.png"Blend modes
Normal; Darken, Multiply, Color Burn, Linear Burn; Lighten, Screen, Color Dodge, Linear Dodge
(Add); Overlay, Soft Light, Hard Light, Vivid Light, Linear Light, Pin Light, Hard Mix;
Difference, Exclusion, Subtract, Divide; Hue, Saturation, Color, Luminosity. Multiply darkens
(shadows, paper texture), Screen lightens (glows, light leaks), Overlay and Soft Light add
contrast, Color tints while keeping the detail. Folders are pass-through: their own mode is always
Normal, and their opacity and mask apply to everything inside.
Adjustment settings
Pass only what you change; the rest keeps its default. These are the exact ranges the format
allows (Compositor refuses a whole project over one value outside them, so Herald Canvas refuses
the change and says which field and range): when a command answers with a range error, fix that
value and try again.
Hue/Saturation:
hue−360…360,saturation−100…100,lightness−100…100,colorize
true/false (with colorize, hue picks the tint).Levels:
levels.channelRGB, Red, Green or Blue, andlevels.ranges, four ranges (RGB,
red, green, blue), eachblack0…254,gamma0.1…9.99,white1…255 (aboveblack),outputBlack0…255,outputWhite0…255. Give all four ranges when you set them.Curves:
curves.channels, four point lists (RGB, red, green, blue) of 2…32{"x": 0…255, "y": 0…255}in increasing x, the first at x 0 and the last at x 255. A gentle
S for contrast:[{"x":0,"y":0},{"x":64,"y":52},{"x":192,"y":204},{"x":255,"y":255}].Exposure:
exposureSettings.exposure−20…20 stops,offset−0.5…0.5,gamma0.01…9.99
(worked in linear light).Gradient Map:
gradientMapSettings.shadowsandhighlightsas{"red", "green", "blue"}
0…1 or any CSS colour ("#1b1340"),reversed.- Grain:
grainSettings.amount0…100,size0.5…20 pixels,roughness0…100,seed. - Invert: no settings.
Black & White:
blackWhiteSettings.reds,yellows,greens,cyans,blues,magentas−200…300 (how light each colour turns),tint,tintHue0…360,tintSaturation
0…100.Color Balance:
colorBalanceSettingswithshadowCyanRed,shadowMagentaGreen,shadowYellowBlue, the same three formid…andhighlight…, each −100…100 (positive is
towards red, green, blue), andpreserveLuminosity.- Gaussian Blur:
blurRadius0.1…250 pixels. Motion Blur:
motionAngle−90…90 (counterclockwise from horizontal),motionDistance
1…2000 pixels.Add Noise:
noiseAmount0.1…400 (percent),noiseGaussian,noiseMonochromatic,noiseSeed.
Eight more are Herald Canvas's own; their settings are flat (no nested record of their own):
Brightness/Contrast:
brightness−150…150 (lifts or lowers the midtones; black and white
stay),contrast−50…100.Vibrance:
vibrance−100…100 (strengthens dull colours most and spares skin tones),saturation−100…100 (as Hue/Saturation saturates).Photo Filter:
colorany CSS colour or{"red", "green", "blue"}0…1 (a warming orange to
start),density0…100 (percent),preserveLuminosity(true keeps the brightness).Channel Mixer:
red,greenandblue, each output channel as{"red", "green", "blue", "constant"}percentages of the inputs, withconstant−200…200
(all four take −200…200);monochrometrue makes one gray from thegrayrow (default 40, 40,
20).Selective Color: per range
reds,yellows,greens,cyans,blues,magentas,whites,neutrals,blacks, an object ofcyan,magenta,yellowandblack−100…100
(percent of ink to add or take away), andabsolute(false, the default, changes each ink by that
share of what is there).- Posterize:
levels2…255 (bands a channel). - Threshold:
level1…255 (brighter is white, darker black). Color Lookup:
table, a.cubefile (settings={"table": "~/LUTs/Portra.cube"}): a 3D
colour table from a grading tool, 2…65 entries a side. Its name and size show inlayers.
Compositor (the Mac app that shares the format) shows Brightness/Contrast exactly, Vibrance only
with vibrance 0, a Photo Filter only with preserveLuminosity false, and the rest as no change;
mention that when the person says they will open the project in Compositor.
An adjustment never adds opacity: over transparency it shows nothing, and a blur softens colour
but keeps the edges of what is below it. A mask on an adjustment layer limits where it applies.
Quick recipes: warmer, Color Balance with midCyanRed +10 and midYellowBlue −15 (or aPhoto Filter at density 20); moodier, Curves with a lowered midpoint plusHue/Saturation saturation=-25; brighter, Exposure exposure=0.4, or Brightness/Contrast withbrightness 30 to lift the midtones; punchier colour without garish skin, Vibrance vibrance=35;
vintage, Gradient Map from deep blue to cream at opacity 0.35 with blend Soft Light, plusGrain amount=20; a film look, Color Lookup with the person's .cube at opacity 0.6 to 1;
dramatic black and white, Channel Mixer with monochrome true and gray {"red": 60,
"green": 50, "blue": -10}; a screen-print poster, Posterize levels=5; dreamy,Gaussian Blur blurRadius=12 at opacity 0.4 with blend Screen.
Filters
filter layer="Photo" kind=… settings={…} changes a layer's pixels for good, as one step the
person can undo (with inSelection=true, only inside what they selected in the window). Prefer an
adjustment layer when there is one for the job (the Gaussian Blur, Motion Blur and Add Noise
adjustments stay editable). Not for text or shape layers.
unsharp mask:
amount1…500 (percent, 100),radius0.1…250 pixels (1),threshold0…255
(0; raise it to leave skin and sky alone). Gentle: 80, 1, 3; crisp detail: 150, 0.8, 2.smart sharpen:
amount1…500 (150),radius0.1…64 (1),reduceNoise0…100 (10). Sharpens
brightness only and holds back halos: the better choice for portraits and noisy photos.- reduce noise:
strength0…10 (6),preserveDetails0…100 (60),colorNoise0…100 (45). - gaussian blur:
radius0.1…250 (4). motion blur:angle−90…90,distance1…2000. high pass:
radius0.1…250 (10): fine detail on gray; on a copy of the photo set to Overlay
or Soft Light, it sharpens.add noise:
amount0.1…400 (10),gaussian,monochromatic,seed. median:radius
1…25 (2): takes out specks and dust.
Layer effects
set_effects layer=… effects={…} puts effects on a picture, text or shape layer (not on folders
or adjustment layers). Per effect, an object merged over what the layer has (or over the effect's
defaults when it has none), true to add it with its defaults, false to remove it, and{"enabled": false} to hide it while keeping its settings. clear=true removes them all first.
Sizes and distances are layer pixels; color is any CSS colour (or red, green, blue 0…1);opacity is 0…1. The effects follow the layer's own mask, and the layer's opacity and blend mode
apply to the layer and its effects together.
shadow (drop shadow, under the layer):
angle−360…360, where the light comes from (90 is
straight above, so the shadow falls straight down; 120 drops it down and to the right),distance0…5000,blur0…500 (how soft),color,opacity. Defaults 90, 20, 20, black, 0.5.innerShadow (inside the edges, as if cut out): the same fields; defaults 90, 10, 10, black,
0.5.- outerGlow:
size0…500,color,opacity; defaults 20, white, 0.75. - innerGlow:
size0…500,color,opacity; defaults 10, white, 0.75. stroke:
size0…500,inside(false puts it outside the edge, with round corners),color,opacity; defaults 4, black, 1, outside.- colorOverlay (tints the layer, keeping its shape):
color,opacity; defaults red, 1.
Recipes:
A soft drop shadow for a cut-out photo or a card:
effects={"shadow": {"angle": 120, "distance": 18, "blur": 40, "opacity": 0.35}}.A glow on a headline over a dark picture:
effects={"outerGlow": {"size": 28, "color": "#ffd27a", "opacity": 0.8}}.Legible white text on a busy photo: `effects={"stroke": {"size": 3, "color": "#111"},
"shadow": {"distance": 4, "blur": 10, "opacity": 0.6}}`.A sticker look: `effects={"stroke": {"size": 14, "color": "#fff"}, "shadow": {"distance": 6,
"blur": 12, "opacity": 0.3}}`.- Hide the stroke but keep it for later:
effects={"stroke": {"enabled": false}}.
Masks
A mask shows (white) or hides (black) parts of a layer without erasing anything; folders and
adjustment layers take masks too. mask layer=… mask=<action>:
revealorhide: a mask showing or hiding everything (replacing one the layer has).revealSelectionorhideSelection: from what the person has selected in the Canvas window.invert,enable,disable(kept but not used),remove.apply: bake the mask into the pixels and drop it (not for folders or adjustments).unlink: the mask stays where it is when the layer moves;linkties it to the layer again.
Typical use: a vignette is a Curves or Exposure layer that darkens, with a mask hiding its
centre; a two-tone grade is two adjustments, each masked to its half.
On-device AI tools
These run on the person's computer (nothing is uploaded) with models they download once, when
they first use the tool in the Canvas window. A command never downloads a model: when one is
missing, the answer says which, and you ask the person to allow it in Herald Canvas (Layer >
Remove Background, or the Object Select tool), then try again.
Remove a background:
canvas action=remove_background layer="Photo"hides everything but the
subject with a layer mask, so nothing is erased (mask layer="Photo" mask=invertkeeps the
background instead).mode=cutoutputs just the subject on a new layer above and hides the original.threshold(0…1, 0.5) moves the edge in (higher) or out (lower),feathersoftens it in pixels,
andrefine=falsekeeps the model's own edge. Good for product shots, portraits and stickers.Remove something / fill a hole: `canvas action=content_fill layer="Photo" x=… y=… width=…
height=…` fills that box from the pixels around it (a passer-by, a wire, a logo on a wall). Give a
box a little larger than the thing;newLayer=truekeeps the fill on its own layer so it can be
masked or undone separately. Without a box it fills what the person selected in the open window.Place a picture exactly:
canvas action=place_image source=… x=… y=… width=… height=…
(fit=coverfills the box and cuts the overflow,containfits inside,stretch), withmask_image=…a grayscale picture over the same box (white shows). This is how generated
pictures land where the person asked.
The person also has Select > Subject, Select > Select and Mask (refining an edge for hair and fur),
Edit > Content-Aware Fill, the Spot Healing and Healing brushes (J), the Clone Stamp (S) and the
Object Select tool (W, with the Magic Wand) in the window; point them there when a job needs a
hand on the picture.
Generated pictures
When the person asks the Canvas window for Generative Fill or a New Generated Layer, Herald sends
you a request naming the project, the box, the files it saved (a picture of the area and its mask)
and the file to save your picture to. Make the picture with your image generation tool (pick its
aspect ratio from the box; if it can edit an image, give it the area's picture), save it there,
place it with place_image exactly as the request says, check it with preview, and say what you
made. If you have no image generation tool, or it fails, say so in a sentence and place nothing.
Planning an edit from a description
Requests like "make it moodier", "warmer and brighter", "put the logo bottom right" or "make the sky
dramatic" come from the window's Ask Hermes field with the project, its layers and a preview.
Look first:
canvas action=previewandcanvas action=layers. Decide what the request means
for this picture (moodier: darker midtones, less saturation, cooler shadows, a vignette).Prefer adjustment layers over changing pixels:
auto_adjustas a first pass on a dull or
tinted photo, Curves, Levels or Brightness/Contrast for tone, Hue/Saturation or Vibrance for
colour strength, Color Balance, a Photo Filter or a Gradient Map for colour casts, Exposure for
brightness, Color Lookup for a look the person has as a.cubefile.
Clip an adjustment to one layer (clip=true) when only that layer should change, and mask an
adjustment (a vignette is a darkening Curves layer with its centre masked out) to limit it.Keep it editable and tidy: name what you add ("Moody grade", "Vignette"), group related layers,
use layer effects for shadows and glows, andplace_imageoradd_layerfor new pictures,
placed with an explicit box ("bottom right" is a box a margin of about 4% in from the corner).Look again with
preview, adjust what is too strong (lower an adjustment layer's opacity
rather than redoing it), and finish by telling the person in a sentence or two what you changed
and why, so they can tweak it or undo it.
The .comp format (for writing projects directly)
For many layers at once it can be faster to write a project yourself; Herald Canvas reloads an
open project the moment its files change. A project is a folder Name.comp holdingmanifest.json and images/:
{
"format": "com.compositor.project",
"version": 11,
"colorSpace": "sRGB",
"resolution": 72,
"documentID": "<UUID>",
"width": 1080,
"height": 1350,
"activeLayerID": "<UUID of a layer>",
"guides": [],
"layers": [
{
"id": "6F1D…",
"name": "Photo",
"isVisible": true,
"isGroup": false,
"opacity": 1,
"blendMode": "Normal",
"imageFile": "6F1D….png",
"transform": { "origin": [0, 0], "size": [1080, 1350], "rotation": 0, "flipX": false, "flipY": false, "sampling": "High quality" }
}
]
}Rules that matter (break one and the whole file is refused):
layersrun bottom to top. A folder has"isGroup": trueand noimageFile; its children
carry"parentID"and come right after it.Ids are uppercase UUIDs, unique. A layer's picture is
images/<ID>.png(8-bit RGBA PNG) and
its maskimages/<ID>.mask.png(8-bit grayscale, white shows), named after the layer exactly.- Every layer has a
namethat is not blank. transform.originis the top-left corner in canvas pixels (−1000000…1000000),sizethe drawn
size (1…300000 a side; the PNG is stretched to it),rotationdegrees clockwise around the
centre,sampling"High quality", "Smooth" or "Nearest".Write every image first, then
manifest.jsonlast, through a temporary file and a rename, so
the editor never reads half a project.maskSourceIDclips a layer to another (never a folder, and never to a folder or an adjustment
layer);adjustmentmakes an adjustment layer (noimageFile; its record needskind,hue,saturation,lightness,colorize, plus fulllevelsandcurves).effectsholds the layer effects, one record per effect as listed under
Layer effects (a missing record means no such effect). An unlinked mask has"maskLinked": false
and its ownmaskPlacementtransform. Keep fields you do not understand exactly as they were.A text or shape layer is a normal pixel layer (its PNG shows it) with a
textrecord
(content,fontNameas a PostScript name,fontSizein pixels 1…2000,red/green/blue
0…1,alignmentLeft, Center or Right,tracking−100…1000,leading0…5000 (baseline to
baseline; 0 is automatic),boxSize[width, height] for paragraph text, each 16…30000, and
optionalcolorRuns(location,length,red,green,blue) andfontRuns(location,length,fontName), sorted, apart and inside the text, counted in UTF-16 units)
or ashaperecord (kindRectangle, Ellipse or Line,red/green/blue,cornerRadius, and for lineslineWidthwithstartandendas fractions of the box). The
PNG must match the record, so preferadd_textandadd_shape, which draw it; painting on such
a layer turns it into plain pixels.guidesis a list of{"id": "<UUID>", "axis": "vertical" or "horizontal", "position": <px>}.Herald's own adjustments (Brightness/Contrast and the others above) go in
heraldAdjustment,
never inadjustment.kind:{"kind": "Vibrance", "vibrance": 30, "saturation": 0}, with the
fields listed under Adjustment settings. The layer still needs a completeadjustmentrecord
(Compositor reads that one); Herald makes it again fromheraldAdjustmentwhen it opens the
project, so a Levels record with its defaults will do. A Color Lookup's table is the fileimages/<ID>.cube, with"name"and"size"(its LUT3DSIZE) in the record. Preferadd_adjustment, which writes all of it.
The same files open in Compositor on a Mac.