Composite headline + subtitle onto branded PNG templates OR directly onto client-supplied photos via the shared task_server pipeline. Local Pillow compositor — no FAL, zero render cost. Two modes (template_compose + photo_compose) behind one wrapper.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Composite headline + subtitle onto branded PNG templates OR directly onto client-supplied photos via the shared task_server pipeline. Local Pillow compositor — no FAL, zero render cost. Two modes (template_compose + photo_compose) behind one wrapper.
ONLY call scripts/design_tool.py. Do NOT invent curl commands; the script
handles auth, the brief shape, and the task lifecycle correctly.
NEVER cat ~/.hermes/secrets/.task_token — the wrapper reads the token from
$TASK_TOKEN_FILE without echoing it.
NEVER claim a template was rendered unless the wrapper printed
✓ completed — file://.... Then verify with ls -la <path> before telling the
user the file exists.
If the wrapper exits non-zero, tell the user the real error. Do not fall back
to pmax-image — they are different skills with different voice+brand intent.
When to use this skill
Brand-template posts with a consistent visual identity (logo, colors, typography)
GMB posts where the headline IS the post
Announcements / promos where a designer-made PNG template already exists
When you want deterministic output (same headline → same pixels)
When NOT to use this skill
Fresh AI-generated imagery → pmax-image (FAL)
Video / reels → pmax-video (FAL)
When no template PNG exists for the client → onboard one first, or use pmax-image
Backend
Same task_server + worker as pmax-image / pmax-video. One queue, one lifecycle.
Render path: render_mode="template_compose" + render_model="template/v1" → the
worker dispatches to TemplateComposeBackend (local Pillow) instead of FAL.
The moment --image is present, the wrapper flips to render_mode=photo_compose. The photo becomes the base layer, and the client-card brand_kit drives the overlay stack:
Contrast overlay (darken text zone for legibility) — optional per brand_kit
Logo (transparent PNG at configured corner) — optional per brand_kit
CTA pill (text + color + position) — optional per brand_kit
Rules:
Local path only in v1. URLs rejected.
--image path is canonicalized via ~/mem0-server/asset_intake.py to ~/mem0-server/assets/uploads/YYYY-MM/<client>/<hash>.<ext> before submission — deterministic dedupe.
Text-box coords scale from a 1080 reference canvas to the actual photo dimensions, so any aspect ratio works.
3) Override the template / template_id
design_tool.py generate --client mock --template-id lux-barbershop --headline "X"
Rare — prefer one template per client. Useful for A/B tests.
brand_kit schema (client card)
Add to ~/.hermes/profiles/pmax-dareen/clients/<slug>.yaml (or the equivalent
for Tarek / Mousa when they wire client-specific brand data):
brand_kit:contrast_overlay:enabled:truezone:bottom# top | bottom | left | right | fullstrength:0.55# 0.0-1.0 opacity of the dark rectanglelogo:path:/Users/majana-agent/mem0-server/assets/logos/<client>.pngposition:top-right# corners + top-center/bottom-center/centerscale:0.14# fraction of canvas widthcta:text:"Book Now"color:"#D4A85C"text_color:"#111111"position:bottom-rightfont_size:28
All three sub-blocks are optional. Missing block → overlay skipped silently. Missing logo file → skipped. Invalid position → defaults to top-left.
3) Fire and return (don't block on render)
design_tool.py generate --client mock --headline "X" --no-wait
# returns immediately with task_id; poll with `status`
4) List templates (honest view of what's actually wired)
design_tool.py list-templates
Output shows ✓ for templates with real PNGs installed, ⚠ PNG missing for
configs pointing at TODO placeholder names. Do not try to render against a
⚠ template — the worker will fail with FileNotFoundError.
5) Status / list
design_tool.py status 42
design_tool.py list --client mock --limit 5
Template onboarding (adding a new client)
Designer delivers 1080×1080 PNG (or any square; the compositor respects it).
Drop at ~/Projects/design-agent/templates/<client-slug>.png.
Verify with design_tool.py list-templates that the new client shows ✓.
Aspect ratio note
--aspect is NOT a template-compose option. Templates already have fixed
dimensions (the PNG defines them). Aspect-ratio routing is for FAL-based
image/video jobs. If you need a different aspect ratio, onboard a separate
template PNG at those dimensions.
Under the hood
design_tool.py is a thin wrapper — it calls task_server directly.
image_worker.py has a TemplateComposeBackend class that dynamically loads
~/Projects/design-agent/design_agent.py::compose_brief().
compose_brief() is a pure function: (brief: dict, asset_path: Path) -> str.
RTL/Arabic is supported if arabic_reshaper + python-bidi are installed.
COMPOSITOR_VERSION in design_agent.py bumps when text-rendering behavior changes.
Current live-template inventory (2026-04-18)
Only mock has a real PNG. The other 3 configs (kiddos-urgent-care,
lux-barbershop, nail-box) have pending-designer placeholder paths.
Honest status: template_compose plumbing is done; product-done is pending
real client templates being delivered by the designer.