Generate primitive color tonal scales from a brand hex or RGB input, write them to code tokens, and push variable values to Figma. Triggers: "generate color scale", "dls-color-scale", "create color palette", "create color scale", "brand color tokens", "primitive color tokens", "generate palette from hex", "add color to DLS".
Generate a full tonal scale (steps 50–950) for one or more color families. Each family accepts one or more anchor values; pinned values lock their exact step, unpinned values are placed at the step whose generated color they match most closely. Writes primitive tokens to code and pushes to the Figma variable collection defined in the bridge.
Global invariants: README-agent.md If
schema.mddoes not exist, stop and route todls-new. If the Figma bridge for primitive colors is missing, stop and route todls-config.
Before anything else, check the user's raw message (trim whitespace, lowercase).
help:
.cursor/skills/dls-color-scale/references/help.md.Primitive colors is not set in schema.md, stop: "Bridge is missing for Primitive colors. Run dls-config to set the collection name and file key, then re-run dls-color-scale."tokens.md does not have a primitive color path, stop and ask the user to specify the code file path before continuing.If .cursor/skills/dls-color-scale/MEMORY.md exists, read it now — both sections:
## Summary — condensed learnings from all older runs; treat these as standing guidance for this skill.## Recent Runs — the most recent entries; apply any Improve next time notes to your approach for this run.If the file does not exist, skip and proceed to Step 1.
Ask:
red, brand, neutral)? Used as the token prefix. Accept one or multiple families in a single run.#rrggbb or rgb(r,g,b)), each optionally paired with a step number.
#FAFAFA at 50, #111111 at 950): that hex is locked to that step exactly.#DDDDDD): the agent places it at the best-matching step after generating the scale (see Step 2).Scale direction is fixed: step 50 is always the lightest, step 950 is always the darkest.
Early placement notice for unpinned values
After the user answers all four questions, and before generating the scale, for every unpinned value:
"
{hex}will be placed at approximately step {N} (L≈{L}%) by lightness fit. Pin it to a different step, or proceed with best-fit?"
This lets the user redirect early — before any scale computation — if the estimated placement is not what they expected.
For each color family:
2a — Build the initial scale using pinned anchors
2b — Place unpinned values
For each unpinned value, find the step in the generated scale whose hex is closest by perceptual distance (ΔECMC or simple HSL-lightness proximity). Treat that step as a pinned anchor, regenerate the affected segment of the scale (so the curve still passes through the newly pinned point), and annotate the step with ← best fit in the preview.
If two unpinned values resolve to the same step, flag the conflict and ask the user which one to keep (or whether to override one to an adjacent step).
2c — Present and confirm
Output the full scale as hex values before writing anything:
red-50: #fafafa ← your input (pinned)
red-100: #f0f0f0
...
red-400: #dddddd ← best fit (unpinned)
...
red-700: #777777 ← best fit (unpinned)
...
red-950: #111111 ← your input (pinned)
Ask: "Does this scale look right? Proceed to write to code (and Figma if you chose that)?"
tokens.md for the primitive color code path.schema.md).--color-red-50: #fff5f5;
--color-red-100: #ffe3e3;
/* ... */
--color-red-950: #1c0606;
red scale, present the diff and confirm before overwriting.figma-use skill.schema.md: file key and collection name for Primitive colors.{family}/{step} (e.g. red/500)COLORAdd or update the entry for this color family in tokens.md §4 (Figma collection mapping) and §3 (code paths) if not already present. Note all anchor steps (pinned and best-fit) and the scale algorithm used in a comment.
After writing to code (and optionally Figma), update the Storybook token gallery to include the new or updated primitive color scale.
dls-showcase skill (.cursor/skills/dls-showcase/SKILL.md).dls-showcase Step 5 ("Token showcase") for the color family(ies) added this run:
src/stories/Tokens/Colors.stories.tsx) to include swatches for every new step ({family}-50 → {family}-950).schema.md.dls-showcase Step 8 (retro) so that skill's MEMORY.md is updated.If the Storybook directory does not exist or cannot be determined from
schema.md, note this as aKnown gapin the retro and skip this step rather than blocking the overall run.
Before writing the retro, confirm all of the following:
#ffffff) or pure black (#000000) unless explicitly approved by the usertokens.md is updated with the color family code path and Figma mapping{family}/{step}If any item fails, fix it before proceeding. If it cannot be fixed (e.g. Figma MCP unavailable), record it as a Known gap bullet in the retro instead.
Write to .cursor/skills/dls-color-scale/MEMORY.md:
Prepend a new entry under ## Recent Runs:
### {date}
- **Went well:** {what worked smoothly — be specific}
- **Friction:** {what caused delays, errors, or extra back-and-forth}
- **Improve next time:** {one concrete change to make on the next run}
- **Summary:** {date} — Generated scale(s): {family names}. Steps: {count}. Code: written. Figma: {written | skipped}. Showcase: {updated | skipped — reason}. Conflicts: {count}.
Compaction rule: if ## Recent Runs exceeds 20 entries, condense the oldest 15 into a prose paragraph under ## Summary (merge with any existing Summary), and retain only the 5 most recent entries in ## Recent Runs.
Create MEMORY.md with ## Summary and ## Recent Runs headers if the file does not exist yet.
| Artifact | Action |
|---|---|
| Primitive color token file (code) | Created / updated |
| Figma variable collection entries | Created / updated (if confirmed) |
tokens.md | Updated (code paths + Figma mapping) |
| Storybook token gallery story | Created / updated (color family swatches) |
.cursor/skills/dls-color-scale/MEMORY.md | Updated |
.cursor/skills/dls-showcase/MEMORY.md | Updated |