Install
$ agentstack add skill-palmier-io-palmier-skills-color-grading ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Grade in the colorist's order, scopes-first — never skip to a look, since a look on top of a cast just bakes it in. One apply_color call merges onto the current grade (only the params you pass change), so build up across calls and verify with inspect_color between stages. Ranges live in the reference tables below; prose names the knob, not the number.
Workflow
- [ ] 1. inspect_color — read scopes BEFORE touching anything
- [ ] 2. Normalize — exposure + white balance to neutral
- [ ] 3. Primary — black/white points, contrast, saturation
- [ ] 4. Match — pull each shot toward the reference (if matching)
- [ ] 5. Secondary — hue curves for skin/sky/foliage
- [ ] 6. Look — wheels split-tone and/or LUT
- [ ] 7. inspect_color again — confirm scopes moved as intended
1. Read first. inspect_color(clipId). Check luma.black/luma.white (near 0/1? clipLowPct/clipHighPct flag crush/clip), balance.warmCool + balance.greenMagenta (nonzero = a cast to neutralize), zones (where the cast lives), and hueHistogram12 (orange bins 1–2 = skin, cyan/blue bins 6–8 = sky).
2. Normalize. exposure for global brightness (prefer it over gamma). temperature to correct warmCool — higher = warmer, so lower it if too warm. tint to correct greenMagenta, pushing opposite the cast. Re-inspect: both balances near 0 before moving on.
3. Primary. blacks/whites to set the points, contrast + highlights/shadows to shape roll-off, saturation for overall sat — reach for vibrance instead when you want to boost muted color without clobbering skin.
4. Match shots. Grade the hero fully, then for each other shot call inspect_color(clipId, reference: ), read the returned gap and its hints (e.g. "warmer than ref → cooler temperature"), apply the nudges, and repeat until the gap is small. Close it numerically — don't eyeball it.
5. Secondary. Adjust specific hues via hueCurves.targets (each targetHue affects ~±22°): hueShift rotates, satScale mutes/pops, lumShift darkens/brightens — e.g. deepen a sky without touching skin. Per-channel redCurve/greenCurve/blueCurve are tone-selective: tame a blown sky with blueCurve: [[0,0],[0.7,0.7],[1,0.85]].
6. Look. Split-tone with the wheels (*Hue+*Amount per zone, e.g. teal/orange = shadowsHue:210,shadowsAmount:0.2 + highsHue:30,highsAmount:0.15), add a film toe via masterCurve ([[0,0.06],[1,0.95]]), or fold in a lut:{path,strength} (.cube, absolute path; copied into project storage; pass strength alone to re-blend). For named stocks, build by hand — see Film looks below.
7. Confirm. Re-inspect_color: points near 0/1 without heavy clipping, neutral balance unless intentionally toned, skin in the orange bins.
apply_color reference
Merges onto the current grade; reset:true starts neutral. clipIds required (video/image only).
| Group | Params | Range | Notes | | :-- | :-- | :-- | :-- | | Tone | exposure / contrast | −3…3 EV / 0.5–1.5 | 1 = neutral contrast | | | highlights shadows blacks whites | −1…1 | points & roll-off | | White balance | temperature / tint | 2000–11000 K / −100…100 | higher = warmer; +tint green, −magenta | | Saturation | saturation / vibrance | 0–2 / −1…1 | 1 = neutral; vibrance protects skin | | Wheels (per zone) | shadowsHue/midsHue/highsHue + matching *Amount | 0–360° / 0–1 | hue push + strength | | | shadowsLum / midsGamma / highsGain | −0.5…0.5 / 0.5–2 / 0.5–1.5 | per-zone brightness | | Curves | masterCurve redCurve greenCurve blueCurve | [[x,y],…] 0–1 | master preserves chroma | | Hue curves | hueCurves.targets[] = {targetHue, hueShift, satScale, lumShift} | ±30° / 0–2 / ±0.5 | ~±22° selectivity | | LUT | lut = {path, strength} | strength 0–1 | .cube, abs path |
Hues: 0 red · 30 orange/skin · 60 yellow · 120 green · 180 cyan · 210 sky-blue · 240 blue · 300 magenta.
inspect_color(clipId | mediaRef, atFrame?, reference?) — clipId reads a clip's graded look, mediaRef a raw asset. Returns scopes (luma, meanRGB, zones, saturation, balance, hueHistogram12, colorfulPct) + the frame; with reference, also a gap and actionable hints (the backbone of shot matching).
Film looks (no LUT)
A LUT just freezes a set of curve/wheel/saturation moves — build any of them by hand, in this order:
- Tone curve (toe + shoulder). The biggest tell: film never hits pure black or clips white. Lift the
masterCurvetoe and roll off its shoulder with gentle mid-S, e.g.[[0,0.04],[0.25,0.22],[0.75,0.82],[1,0.97]]. - Per-channel crosstalk. Hue shifts with brightness — what separates real emulation from "S-curve + a tint." Lift the blue toe and pull its shoulder → teal shadows + warm highlights (
blueCurve: [[0,0.05],[0.5,0.5],[1,0.92]]); nudge green mids for Fuji. - Split-tone the wheels (shadows→teal, highlights→amber).
- Saturation sculpting —
vibranceover flatsaturation, plushueCurvessatScaleto mute/boost individual hues. - Hue rotation — small hue-vs-hue shifts (≤8°): Kodak warms oranges, Fuji greens.
The recipes below are this method with the dials pre-set — apply onto an already-normalized clip, then re-inspect_color and tune toward the shot (scale *Amount and curve deviations toward neutral for less intensity). If the user has the real .cube, prefer lut:{path,strength:0.85}; these approximate a stock's character, not its science.
Kodak 2383 — Hollywood print (warm, contrasty; dense blacks, teal shadows, amber highlights):
{ "contrast": 1.25, "saturation": 1.15, "vibrance": 0.1, "temperature": 6800, "blacks": -0.1, "whites": 0.05,
"shadowsHue": 195, "shadowsAmount": 0.12, "highsHue": 40, "highsAmount": 0.12, "masterCurve": [[0,0.02],[0.25,0.21],[0.75,0.83],[1,0.98]] }
Kodak 2389 — low-con print (clean, neutral; filmic roll-off, little tone):
{ "contrast": 1.08, "saturation": 1.03, "temperature": 6550, "blacks": -0.04, "highsHue": 45, "highsAmount": 0.06, "masterCurve": [[0,0.015],[0.3,0.29],[0.7,0.72],[1,0.99]] }
Fuji Eterna / 3513-like (soft, green-pastel; milky lifted blacks). The lifted toe is the signature — don't flatten it:
{ "contrast": 1.05, "saturation": 0.95, "vibrance": 0.12, "temperature": 6300, "blacks": 0.08, "shadows": 0.1, "highlights": -0.15, "whites": -0.04,
"midsHue": 120, "midsAmount": 0.08, "shadowsHue": 185, "shadowsAmount": 0.1, "masterCurve": [[0,0.06],[0.25,0.27],[0.8,0.82],[1,0.95]] }
Kodak Portra — warm negative (soft, skin-flattering). The −tint + orange curve flatters skin — confirm the orange bins grew, not the reds:
{ "contrast": 1.05, "saturation": 1.0, "vibrance": 0.15, "temperature": 6900, "tint": -3, "blacks": 0.06, "highlights": -0.1, "highsHue": 38, "highsAmount": 0.08,
"hueCurves": { "targets": [ { "targetHue": 30, "satScale": 1.08, "hueShift": -4 } ] } }
Bleach bypass (desaturated, high-contrast, metallic). Scale saturation 0.4–0.7 for intensity:
{ "contrast": 1.35, "saturation": 0.55, "temperature": 6300, "tint": 5, "blacks": -0.15, "whites": 0.1, "masterCurve": [[0,0.0],[0.2,0.13],[0.8,0.9],[1,1.0]] }
Teal & orange — blockbuster (cool shadows, warm skin). Keep the orange curve modest so faces don't go radioactive:
{ "contrast": 1.2, "saturation": 1.1, "vibrance": 0.15, "shadowsHue": 210, "shadowsAmount": 0.2, "highsHue": 30, "highsAmount": 0.15,
"hueCurves": { "targets": [ { "targetHue": 30, "satScale": 1.15 } ] } }
Vintage / faded (milky blacks, low sat, warm-yellow age). The high toe is the whole look — blacks never reach 0:
{ "contrast": 0.95, "saturation": 0.8, "temperature": 6700, "tint": 4, "blacks": 0.12, "highlights": -0.1, "masterCurve": [[0,0.1],[0.5,0.52],[1,0.92]] }
Notes
apply_coloris the colorist path and folds in LUT + curves + hue curves as live, editable effects.apply_effectis for generic, non-color FX — don't grade with it.- Trust scopes over the preview for balance — monitors and JPEGs lie about subtle casts; use the frame for composition/look judgment.
lumShiftis an additive HSV value shift in display space, not a linear luma divide, so per-hue darkening won't amplify shadow macroblocks.- Curve points are piecewise-linear, clamped flat outside their range — include endpoints near
[0,0]/[1,1]unless you mean to clip.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: palmier-io
- Source: palmier-io/palmier-skills
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.