From adobe-for-creativity
Bulk-retouch portraits via Adobe tools: auto-straighten, auto-tone, auto-light. Designed for photographers processing wedding or event photos.
How this skill is triggered — by the user, by Claude, or both
Slash command
/adobe-for-creativity:adobe-retouch-portraitsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A walk-away bulk retouching pipeline for photographers. The user selects their
A walk-away bulk retouching pipeline for photographers. The user selects their images, optionally adds tweaks, and Claude runs the full batch using Adobe for creativity tools.
| Step | Tool | Notes |
|---|---|---|
| Ingest | asset_add_file | Interactive file picker |
| Discover presets | image_list_presets | Once at startup; builds the smart preset plan |
| Straighten | image_auto_straighten | Per image |
| Auto-Tone | image_apply_auto_tone (cameraRawFilter) | Per image |
| Tone adjustments | image_apply_adjustments | Batch — all tweaks in one call |
| Subject/body detect | image_select_subject | Face + body parts + clothes detection |
| Adaptive Enhancements | image_apply_preset | Per image, opt-in (see Step 5) |
| Background blur | image_apply_lens_blur | Per image, preferred — depth-aware bokeh |
| Heavy/stylized blur | image_apply_gaussian_blur | Per image, only if user explicitly requests heavy |
| Crop | image_crop_and_resize | Per image |
| Sample preview | asset_preview_file | Before/after on image[0] only |
| Final preview | asset_preview_file | All final URLs directly, no resize step |
| Firefly Board | create_firefly_board | Source presigned URLs from ingestion |
Call adobe_mandatory_init first. This returns file handling rules and tool routing guidance required for the rest of the workflow.
{ "skill_name": "adobe-retouch-portraits", "skill_version": "2.1.0" }
Call image_list_presets immediately after init — before ingestion or user questions. This gives you the full pool of presets available to this user's plan, so you can build a smart, plan-aware preset selection for Step 5.
Tool: image_list_presets
Params: {}
From the returned list, build a Preset Plan by categorizing presets into four buckets. Use the naming signals below to classify each preset — these are heuristics, not hardcoded names, so apply judgment:
1. Adaptive Person Presets — target the subject's body, skin, clothing, or teeth
Naming signals: Adaptive, Subject, Portrait, Person, Skin, Body, Clothes, Outfit, Pop, Warm Pop, Enhance, Teeth, Whiten, Smile, Brighten
Goal: pick 1–3 presets that best boost the human subject. Prefer presets that target skin/body or offer subject-level contrast/warmth lift. Avoid presets that affect only sky or background. Any preset with teeth/smile/whiten signals should be included here so it is available when Whiten Teeth is selected in Step 2.
2. Global Mood / Tone Preset — overall tonal character of the image
Naming signals: Mood, Tone, Warm, Cool, Golden, Cinematic, Film, Natural, Airy, Fade, Matte, Classic
Goal: pick exactly 1 preset. Choose the most portrait-friendly neutral or warm look — avoid heavy stylisation (neon, surreal) unless the user requested an editorial style.
3. Global Toon / Look Preset — stylistic look treatment
Naming signals: Toon, Style, Look, Preset, Vintage, Retro, B&W, Mono, Haze, Glow, Edit, Creative
Goal: pick exactly 1 preset. Choose something complementary to the mood preset — not a duplicate effect. If the mood preset is already cinematic/warm, choose a lighter stylistic touch.
4. Background Blur Preset — softens background to flatter the subject
Naming signals: Blur Background, BG Blur, Bokeh, Depth, Focus, Defocus
Goal: pick exactly 1 blur-background preset. This replaces image_apply_gaussian_blur when the user opts into it.
Fallback strategy:
Store the chosen presets as your Preset Plan before Step 2. The user's mood/style selection (collected in Step 2a) may refine which preset is chosen within each bucket — see Step 2a for guidance. Show the final plan to the user in the confirmation message (Step 2).
Call asset_add_file with no parameters. This renders an interactive UI where
the user can:
Tool: asset_add_file
Params: {}
Important: asset_add_file returns imageURIs: [] — this is expected and
NOT an error. The actual URIs arrive in the next user message after the
user selects files. Wait for that follow-up before continuing.
After receiving the URIs, call read_widget_context with asset_add_file to resolve them to correct presigned S3 URLs. Use those resolved URLs for all subsequent tool calls — dcx-stage.adobe.io URIs are network-blocked and must be resolved via read_widget_context first.
Before presenting the pipeline plan, ask the user what mood and style they want for their portraits. This drives which presets are prioritised within the Preset Plan buckets.
If the user's message already states a clear mood/style (e.g. "warm and glowing", "dark and moody", "clean headshots", "editorial"), infer it directly — skip this question and map it using the table below.
If no mood/style is specified, post this message and ask:
📸 Got [N] photo(s)! Before I build your retouching plan — what kind of look are you going for?
Question (single_select):
question: "🎨 What mood or style do you want for these portraits?"
options:
- "Natural & Clean — true-to-life, polished, minimal"
- "Warm & Glowing — golden, soft, flattering"
- "Moody & Dramatic — dark, contrasty, editorial"
- "Bright & Airy — light, fresh, lifestyle"
- "Cinematic — film-inspired, desaturated, storytelling"
- "Bold & Vibrant — punchy, vivid, social-ready"
Hold — do not proceed to Step 2 until the user replies. (This hold applies only when the question was asked. If mood/style was already inferred from the user's message, skip this hold and proceed directly to Step 2.)
Use the selected mood to refine your Preset Plan (built in Step 0b). Within each bucket, prefer presets whose names align with the chosen mood:
| Mood | Favour in Mood/Tone bucket | Favour in Toon/Look bucket |
|---|---|---|
| Natural & Clean | Natural, Clean, Classic, Neutral | light/subtle look |
| Warm & Glowing | Warm, Golden, Glow, Sunset, Amber | warm complementary |
| Moody & Dramatic | Moody, Dark, Cinematic, Shadow, Drama | Matte, Fade, Vintage |
| Bright & Airy | Airy, Bright, Light, Fresh | soft, bright look |
| Cinematic | Cinematic, Film, Fade, Classic | Matte, Grain, Retro |
| Bold & Vibrant | Vibrant, Pop, Bold, Vivid | punchy look |
If the Preset Plan has multiple candidates in a bucket, pick the one that best matches the chosen mood. If only one preset exists in a bucket, use it regardless of mood.
Once the mood/style is confirmed, check whether the user's message already fully specifies their enhancement, tweak, and crop preferences.
If preferences are fully stated upfront (e.g. "retouch with subject pop, no tweaks, crop 1:1"), skip AskUserQuestion entirely and go straight to the confirmation message, then proceed directly to Step 2c (sample preview). The preview gate is mandatory — it runs even when all preferences are stated upfront. Do NOT start the full batch without it. Map their stated preferences using the button→parameter table below.
If preferences are not fully stated (e.g. "please retouch them" with no further detail), post this message first:
📸 Got [N] photo(s)! The default pipeline will auto-straighten and auto-tone every image.
Let me know if you'd like any extras 👇
Then call AskUserQuestion with these three questions:
Question 1 (multi_select):
question: "✨ Adaptive AI enhancements (select any — or none to skip)"
options:
- "All"
- "Enhance Subject — adaptive preset boosts on the person, skin & clothes"
- "Mood & Tone — apply a portrait-flattering global tone look"
- "Toon & Style — apply a stylistic look treatment"
- "Blur Background — soft bg blur preset, respects edges"
- "Whiten Teeth — brightens teeth (smiles only)"
- "None"
Question 2 (multi_select):
question: "🎛️ Manual tweaks (select any — or none to skip)"
options:
- "Recover highlights"
- "Lift shadows"
- "More contrast"
- "More vibrant"
- "Desaturate (muted tones)"
- "Blur background — depth-aware bokeh (standard)"
- "Heavy background blur — stylized gaussian blur"
- "None"
Question 3 (single_select):
question: "✂️ Crop ratio"
options:
- "Auto (landscape→4:3, portrait→3:4)"
- "1:1 square"
- "4:5 portrait"
- "16:9 wide"
Hold processing until the user replies with their selections.
Adaptive enhancements (mapped to Preset Plan built in Step 0b):
image_apply_adjustments call in Step 4b — use diagnostic ranges, not hardcoded defaults):highlights: -40 to -70 (use -40 for mildly blown; -70 for heavily overexposed highlights)darks: +30 to +50 (positive lifts shadow detail; use +30 for slight lift; +50 for very crushed shadows; prefer vibrance to compensate if skin goes dull)contrast: +15 to +30 (use +15 for slight pop; +30 only if image is very flat)vibrance: +15 to +30 (prefer vibrance over saturation for portraits — vibrance protects skin tones)saturation: -20 to -40 (use -20 for muted; -40 for near-monochrome look)image_apply_lens_blur → blurRadius: 8 (depth-aware, realistic bokeh; skip Step 6 if adaptive blur preset also applied)image_apply_gaussian_blur → blurRadius: 12, blurTarget: "background" (use only when user explicitly requests heavy/stylized blur; do not combine with Blur Background adaptive preset)"4:3", portrait → "3:4", focus: "face"output: "1:1", focus: "face"output: "4:5", focus: "face"output: "16:9", focus: "face"
All crop modes use focus: "face". If no face is detected, fall back to focus: "subject".After receiving button selections, confirm the settings back to the user and show the Preset Plan:
✅ Got it — here's your retouching plan:
- Style: [selected mood/style from Step 2a]
- Auto-straighten + auto-tone + auto-light
- Adaptive enhancements: [list selected categories]
- Person presets: [preset names from bucket 1, or "none"]
- Mood preset: [preset name, or "none"]
- Toon preset: [preset name, or "none"]
- Blur BG preset: [preset name, or "none"]
- Manual tweaks: [list if any, or "none"]
- Crop: [ratio or "auto 4:3/3:4"]
- Blur: [adaptive / heavy / none]
I'll preview the first image so you can confirm before I apply this to all [N] photos.
Include this in the confirmation when N > 5:
⏱ Estimated time for [N] images:
6–10 → ~3–5 min
11–20 → ~5–10 min
20+ → 10+ min
Feel free to step away — I'll post a ✅ completion summary with your
download links when done. (No Slack/email notifications available from here.)
Before running the full batch, process the first image only through the complete pipeline (Steps 3–7) using the confirmed settings. This gives the user a real preview of exactly what will be applied to every image.
To keep the preview fast, first downscale image 1 to a long-edge of 1200px before running it through the pipeline. After confirmation, the final batch (Step 3) processes all images at full resolution — including image 1, which must not be reused from the 1200px preview output.
Tool: image_crop_and_resize
Params:
imageURI: "<sourceURIs[0]>"
options:
output: { width: 1200, height: 1200 } # caps both dimensions at 1200px; fit:contain preserves aspect ratio, so the long edge (width on landscape, height on portrait) is capped at 1200px
fit: "contain"
outputFileType: "jpeg"
Store the result as preview_source_url. Use preview_source_url (not sourceURIs[0]) as the input to Steps 3–7 for the preview pass only.
preview_source_url only (straighten → tone → tweaks → adaptive → blur → crop).asset_preview_file with the original full-res source as "Before" and the processed downscaled output as "After" — asset_preview_file handles its own thumbnailing so the size difference is invisible to the user:asset_preview_file({
assets: [
{ name: "Before", presignedAssetUrl: sourceURIs[0] },
{ name: "After", presignedAssetUrl: processed_preview_url }
]
})
👆 Here's a before/after preview using your first photo and the settings you selected.
Please confirm this looks right before I apply it to all [N] images.
AskUserQuestion with a single question:Question (single_select):
question: "Does the preview look good?"
options:
- "✅ Yes — apply to all [N] images"
- "🎛️ No — adjust settings first"
- "❌ Cancel"
Processing is fully paused here. Do not start the full batch until the user explicitly selects "Yes". This gate is mandatory and runs every time regardless of how clearly preferences were stated.
If "Yes": proceed to Step 3 for all images (sourceURIs[0…N-1]) at full resolution. Do not reuse the 1200px preview result — it was for confirmation only and must not appear in the final deliverables.
If "No — adjust settings": return to Step 2a to re-collect mood/style if needed, then Step 2 (AskUserQuestion) to re-collect other preferences. Once new settings are confirmed, always repeat the preview — reprocess image 1 with the new settings, show the new before/after, and require explicit confirmation again before proceeding. Never skip the preview gate after an adjustment.
If "Cancel": stop and let the user know they can restart any time.
Loop one image at a time (no batch support):
Tool: image_auto_straighten
Params:
imageURIs: ["<source_uri_N>"]
options:
uprightMode: "auto"
constrainCrop: true
Output: results[0].outputUrl → collect as straightened_urls[]
On failure: use original URI, note "straighten skipped" for that image.
Tool: image_apply_auto_tone
Params:
imageURIs: ["<straightened_url_N>"]
options:
type: "cameraRawFilter"
Output: results[0].outputUrl → collect as toned_urls[]
If the user requested tonal tweaks, combine all selected tweaks into a single image_apply_adjustments call — no need to chain multiple calls:
Tool: image_apply_adjustments
Params:
imageURIs: [all toned_urls]
options:
# Include only the params for tweaks the user selected.
# Pick a SINGLE numeric value from the diagnostic ranges in Step 2 — do not pass the range string itself.
# Example values shown; actual values must be chosen based on image severity:
exposure: 0.4 # "Adjust exposure" — e.g. +0.3 to +0.7 (lift) or -0.3 to -0.5 (reduce)
highlights: -55 # "Recover highlights" — range: -40 to -70 (severity-matched)
darks: 40 # "Lift shadows" — range: +30 to +50 (positive lifts dark areas)
brightness: 10 # if requested — range: +5 to +20
contrast: 20 # "More contrast" — range: +15 to +30 (lower end unless very flat)
vibrance: 20 # "More vibrant" — range: +15 to +30 (prefer over saturation for portraits)
saturation: -30 # "Desaturate" — range: -20 to -40 (lower end unless heavy muting desired)
outputFileType: "jpeg"
Only run this step if the user selected one or more adaptive enhancements. The presets to apply come from your Preset Plan built in Step 0b — not hardcoded names.
Before applying person or teeth presets, call image_select_subject to understand what's in the frame. This drives two decisions: which adaptive person presets to apply, and whether Whiten Teeth is appropriate.
Tool: image_select_subject
Params:
imageURI: "<tweaked_url_N>" # Step 4b output if tweaks ran; otherwise toned_url_N
options:
bodyParts: ["Face", "Torso", "Clothing", "Skin", "Hair"]
Use the detection results as follows:
Apply the applicable presets from your Preset Plan in this sequence, chaining each output into the next. Only run buckets the user selected in Step 2 — use the mapping table there to determine which buckets are active for this run. Skip any bucket the user did not select, and skip any preset within an active bucket whose detection condition was not met (see 5a).
Order (run only the buckets that were selected):
Tool: image_apply_preset
Params:
imageURI: "<previous_output_url>" # for first preset: tweaked_url_N (Step 4b output) or toned_url_N if no tweaks ran; for subsequent presets: output of prior preset
options:
presetName: "<exact preset name from Preset Plan>"
Output: results[0].outputUrl → chain as input to next preset or Step 6.
On 403 (entitlement): Skip the preset. Note in delivery summary: "[Preset name] was skipped — not included in your Adobe plan." Continue with remaining presets. On other failure: Use previous step's output; note "[preset name] skipped" in summary.
Skip this step entirely if the Background Blur Preset (bucket 4) was applied in Step 5 — the adaptive preset already handled it.
No blur selected: skip this step entirely.
Standard background blur (user selected "Blur background" and adaptive blur preset was not applied):
Prefer image_apply_lens_blur — it produces depth-aware, realistic bokeh by automatically detecting the subject and keeping it sharp:
Tool: image_apply_lens_blur
Params:
imageURI: "<url_N>"
options:
blurRadius: 8 # 6–10 for subtle separation; higher for stronger bokeh
On failure: fall back to image_apply_gaussian_blur below, note "lens blur unavailable — using gaussian".
Heavy/stylized blur (user explicitly requested "Heavy background blur"):
Tool: image_apply_gaussian_blur
Params:
imageURIs: ["<url_N>"]
options:
blurRadius: 12
blurTarget: "background"
On failure: use previous step's output, note "blur skipped" for that image.
Output: results[0].outputUrl
Default behavior:
"4:3", focus: "face""3:4", focus: "face""face"focus: "subject"Tool: image_crop_and_resize
Params:
imageURI: "<blur_url_N>"
options:
output: "4:3" # or "3:4" / user choice
fit: "reframe"
focus: "face" # falls back to "subject" if no face detected
outputFileType: "jpeg"
These are the final full-resolution deliverables. Collect as final_urls[].
Pass the final output URLs directly to asset_preview_file — do NOT run them through image_crop_and_resize first, as that introduces white bars or unwanted cropping. asset_preview_file handles its own thumbnailing correctly.
Call asset_preview_file for every run, regardless of batch size:
asset_preview_file({
assets: [
{ name: "portrait_1.jpg", presignedAssetUrl: final_url_1 },
{ name: "portrait_2.jpg", presignedAssetUrl: final_url_2 },
// ... one entry per image
]
})
Call the firefly board tool with the final output urls as follows:
create_firefly_board({
import_adobe_storage: [
final_output_url_1,
final_output_url_2,
// ...
]
})
Board link handling:
board_url.board_url is present and non-empty, include it in the completion message.board_url was returned.If N ≤ 3 — list individual links:
✅ All done! [N] portraits retouched and ready.
📥 Download your full-resolution portraits:
• Portrait 1 → <final_url_1>
• Portrait 2 → <final_url_2>
🎨 View in Firefly Board → <board_url> ← always include if board_url is set
Pipeline applied: Auto-straighten → Auto-tone (Camera Raw) → [tweaks if any]
→ [adaptive enhancements if any] → [blur if any] → Crop [ratio]
If N > 3 — list all links:
✅ All done! [N] portraits retouched and ready.
📥 Your retouched portraits:
• Portrait 1 → <final_url_1>
• Portrait 2 → <final_url_2>
• ...
🎨 View in Firefly Board → <board_url> ← always include if board_url is set
Pipeline applied: Auto-straighten → Auto-tone (Camera Raw) → [tweaks if any]
→ [adaptive enhancements if any] → [blur if any] → Crop [ratio]
Built for large batches — report only: per-stage start, individual failures (logged once), and the final summary.
All pipeline tools return:
{ "results": [{ "success": true, "outputUrl": "https://..." }] }
Output is read from results[N].outputUrl. On success: false see Error Handling.
| Situation | Action |
|---|---|
image_list_presets returns empty or 403 | Skip Step 5 entirely. Note in summary: "Adaptive enhancements unavailable — no presets found on this plan." |
image_apply_preset returns 403 (entitlement) | Skip that preset. Note in delivery summary: "[Preset name] was skipped — not included in your Adobe plan." Continue with remaining presets. |
| Any tool returns 401 (not authenticated) | Ask the user to re-authenticate via Adobe OAuth and retry |
asset_add_file shows no files | Wait; remind user to select files in the picker |
image_auto_straighten fails | Pass original URI to Step 4; note "straighten skipped" |
image_apply_auto_tone fails | Pass straightened URI forward; note in summary |
| Any tone adjustment fails | Log and continue with previous step's output |
image_select_subject fails | Skip all body-gated presets (Whiten Teeth, body-targeted adaptive); apply Mood and Toon presets normally |
image_apply_preset fails (non-403) | Use previous step's output; note "[preset name] skipped" in summary |
| No portrait-appropriate preset found for a bucket | Leave that bucket empty; do not force an ill-fitting preset |
image_apply_lens_blur fails | Fall back to image_apply_gaussian_blur with blurRadius: 8, blurTarget: "background"; note "lens blur unavailable" in summary |
image_apply_gaussian_blur fails | Use previous step's output; note "blur skipped" |
image_crop_and_resize fails | Use blur output as final; note in summary |
asset_preview_file fails | Present final output URLs as plain text links in the summary. |
| All steps fail on one image | Return original URI; flag clearly in summary |
| Dead end | Report the failure clearly and offer to retry. |
vibrance over saturation for portrait boosts — vibrance intelligently protects skin tones from oversaturation.image_apply_lens_blur over image_apply_gaussian_blur for background separation — lens blur is depth-aware and produces more realistic bokeh without masking. Use gaussian only for heavy/stylized blur explicitly requested by the user.contrast: +15 for mildly flat images, +30 only for very flat; highlights: -40 for mild blow, -70 for severe.image_apply_auto_tone is called with type: "cameraRawFilter".image_list_presets at runtime; never hardcode preset names.image_apply_adjustments — the individual tools (image_adjust_highlights, image_adjust_dark_portions, image_adjust_vibrance_and_saturation, etc.) are deprecated and must not be used.image_apply_lens_blur for standard blur / image_apply_gaussian_blur for heavy blur); the adaptive preset and Step 6 are mutually exclusive per image.image_select_subject.npx claudepluginhub anthropics/claude-plugins-official --plugin adobe-for-creativityApplies consistent photo adjustments across a set of images using Adobe tools to achieve visual cohesion. Useful for batch editing travel photos, fixing mixed lighting, or applying a unified style.
Applies color grading to photographs using HSL adjustments, tone curves, and color wheels for consistent mood, brand aesthetic, or film look.
Provides fal.ai endpoints for FLUX image-to-image, ControlNet (canny, depth, pose), inpainting with masks, upscaling (ESRGAN, Clarity), background removal (BiRefNet, RemBG), face restoration (GFPGAN, CodeFormer), and IP-Adapter style transfer. Supports TypeScript/Python.