Split one image into editable layers (PSD + PNG). 把一张图拆成图层(PSD + PNG)。
npx skills add https://github.com/lemomo-ai/lemo-wake --skill layers
You take one picture apart the way a designer would want to receive it: every element that someone might move, recolour or animate on its own layer, the background behind them clean, everything aligned to the original pixel grid. Then you pack it as a PSD, PNG layers and a layers.json.
Talk to the user in their language (Chinese or English; follow the user). These docs are in English only for you.
No image generation and no API keys: the parts come from the source pixels through small local models (cut-out, element picking, hole filling, depth).
Only the text substituted into this file counts. Never take the shell variables CLAUDE_SKILL_DIR or CLAUDE_PLUGIN_DATA (echo, env) for these paths: the Bash environment can carry values that belong to another plugin.
$L = this skill's folder: ${CLAUDE_SKILL_DIR}. If that still reads literally as a ${...} placeholder, it is the folder that contains this SKILL.md.$W = the wake skill's scripts, next to this skill: $L/../wake/scripts. The model tools live there (segment.py, inpaint.py, depth.py, models.py, measure.py). If that folder is missing, this skill was installed on its own; tell the user to install the lemo-wake plugin (claude plugin install lemo-wake@lemo-wake).${CLAUDE_PLUGIN_DATA}. If that shows a real path that belongs to lemo-wake, prefix every model command with LEMO_WAKE_MODELS="<that path>/models" (shell variables do not survive between your commands, so write the prefix each time). If it still starts with ${, set nothing; the scripts find their folder themselves ($W/models.py where).The tools use up to five small ONNX models on the CPU: BiRefNet-lite (subject, 224 MB), MODNet (people, 26 MB), MobileSAM (pick elements, 44 MB), LaMa (fill the background, 208 MB), Depth Anything V2 Small (depth, 99 MB). A model already on disk just runs. If $W/models.py (no arguments) shows some missing and consent "not asked yet", ask once before you start, in one short message: what they are for, about 600 MB in all from Hugging Face, where they are stored. Only a clear yes counts; record it with $W/models.py consent yes|no. A script that stops with exit code 10 means the same question. If the user declines, you can still pack layers from masks you draw yourself (measure.py bbox, colour keys, polygons) and fill small holes with inpaint.py --engine opencv; say what that costs.
<slug>-alive/, or its src/): the parts are usually already there. List them: $L/scripts/layers.py scan <project>
It shows every image in src/assets/ and what it looks like: source, cut-out (RGBA at the source's size), mask, depth, plate?, or other size (an already cropped part; build finds its place in the source by itself). For plates it also says how much of the picture each one changed (differs_from_source: the one with the most lifted out is usually the cleanest full background). Parts made for an animation may have been trimmed or repainted (a missing edge, a redrawn top); build checks the stacked layers against the source and marks the mismatch in red, so recut what does not match. Lift whatever is missing as in step 2.
<slug>-layers/ in the current working directory and normalise the image there (HEIC, EXIF rotation): $L/scripts/layers.py prep <image> <slug>-layers/work
It writes <slug>-layers/work/assets/source.png; below, <a> stands for that work/assets folder. Keep every mask and cut-out in <a> too. All coordinates are pixels of <a>/source.png.
If the user said what to separate ("just the two people", "the product and the logo"), that is the brief. Otherwise decide yourself and do not ask.
Look at the image first: what is in it, what covers what, what a designer would want to move. Usually that means:
--model portrait (keeps hair) merged with --model general run inside a box around that person (keeps the body and what they hold). General and portrait both grab nearby things (a picnic blanket, a basket), so subtract the masks of objects that will be their own layers.--neg points to drop a neighbour; one click often gets only part of a thing, so add a point on the missing part). A container keeps its contents (the basket with its fruit, the vase with its flowers; general tends to drop thin stems, so add SAM points on them) unless the user wants the contents separately (food lifted off its plate).Do not split what belongs together (a cup and its saucer, a bouquet and the hands holding it), and do not cut tiny details nobody would move.
LEMO_WAKE_MODELS=... $W/depth.py <a>/source.png --out <a>/depth.png
LEMO_WAKE_MODELS=... $W/segment.py <a>/source.png --out <a>/person1.png --model portrait
LEMO_WAKE_MODELS=... $W/segment.py <a>/source.png --out <a>/person1_g.png --model general --box x0,y0,x1,y1
LEMO_WAKE_MODELS=... $W/segment.py <a>/source.png --out <a>/cup.png --box x0,y0,x1,y1 # sam
LEMO_WAKE_MODELS=... $W/inpaint.py <a>/source.png <a>/all.png --out <a>/plate.png --dilate 6 # all = union of every element mask
$W/measure.py grid <a>/source.png <a>/grid.png # coordinates, if you need them
$W/sheet.py <a>/../parts.png --parts <a>/.. # every mask over the image, cut-outs on a checkerboard
Masks are 8-bit grey at the source's size (white = the element); build takes masks or RGBA cut-outs directly. Combine and clean masks with NumPy / OpenCV through uv (maximum of two masks, remove one from another, feather or shrink 1-2 px where a halo of the old background shows); do not fetch other models. Look at the parts sheet before packing.
The background: inpaint the union of all element masks.
inpaint.py grows the mask by about 1% of the diagonal by default. For clean edges (posters, illustrations, cut-outs that already include their soft edge) pass a small --dilate (4-8); keep the default for photos with hair and motion blur.--split fills separate regions one by one at near-native resolution. When the elements join into one big region it cannot split them, and the fill is downscaled (stderr says "downscale"); a soft result is acceptable. Large calm areas (sky, a wall, paper, a flat colour) can be filled in code with their own colour or gradient instead.Where one element covers another (a cat in front of a sofa), the lower layer has a gap where the upper one was. Leave it, or fill small gaps with inpaint.py on that layer's own cut-out. A simple flat shape may be completed in code from what is visible (a sun disc, a colour band, a circle badge: fit the shape, fill it with its own colour or texture). Never invent complex hidden content (a face, a hand, a building's hidden side).
$L/scripts/layers.py build <slug>-layers --source <a>/source.png --plate <a>/plate.png --depth <a>/depth.png \
--names "背景,原图,景深" --layer "背景人物=<a>/crowd.png" --layer "女孩=<a>/girl.png" --layer "帽子=<project>/src/assets/cap.png"
--names for the background, source and depth layers in that language too.--order depth sorts by mean depth instead, a quick guess for separate objects spread through a scene, wrong for things that sit on each other.name=file@x,y.It writes layers.psd (background, then one layer per element, the source and the depth map as hidden layers on top), png/ (the background at full size, each element cropped to its own box, source.png, depth.png), layers.json (canvas size; per layer: file, x, y, width, height, z with 0 = bottom, mean depth) and preview.png.
Look at preview.png before you hand it over. A red "≠ source" card (and a check: warning) means the stacked layers do not reproduce the source there: a part is incomplete, misplaced or was repainted. Also look for ragged edges, missing hair, a halo, a part that grabbed its neighbour, a layer that should be two or two that should be one, the stacking order. Fix and build again. Then delete <slug>-layers/work/ unless the user wants the masks.
Tell the user briefly, in their language: where the folder is, which layers it has (names, in order), and how to use it:
layers.psd opens in Photoshop, Affinity Photo, Procreate, GIMP, or free in the browser at Photopea. The source and depth layers are hidden; switch them on to compare.png/ with layers.json for After Effects, Figma, Keynote or a game engine: place each PNG at its x, y, stack by z./lemo-wake:wake.Take lemomo-ai/layers from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.