agentleFS
a-ng-da-ng-d/claude-ui-color-palette/skills/ui-color-palette-audit-palette/SKILL.md

ui-color-palette-audit-palette

Skill1 starsChanged 7 months agoMITView on GitHub

Audit color pairs for contrast compliance against WCAG 2.1 and APCA standards. Use when the user wants to check accessibility, validate color pairings, or compute a global contrast score for a palette.

We split this skill into the rules it gives an agent

13 rules. About 0 are common, 5 are distinctive, and 8 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 8

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use the ui-color-palette MCP tool get_palette to generate a palette with contrast data, then analyze the results for WCAG and APCA …

    line 9
  2. Distinctive:

    Prefer producing or reasoning from a compact CSV-like block instead of the original nested JSON:

    line 67
  3. Very specific:

    If a compact flat array (from a previous get_palette call with compact: true) is present → skip to Step 3.

    line 88
  4. Very specific:

    If only base + themes are present (no palette data) → continue to Step 1.

    line 89
  5. Distinctive:

    If nothing is present → ask the user for the source (palette config, hex colors, or palette ID).

    line 90
  6. Distinctive:

    Ask (or infer from context):

    line 96
  7. Distinctive:

    If the user has multiple color families and only cares about a subset, ask which ones — otherwise include all.

    line 104
  8. Very specific:

    Only the selected theme(s) in themes (not the full list if more exist)

    line 112
  9. Very specific:

    Ensure every theme has textColorsTheme set (e.g.

    line 113
  10. Distinctive:

    Start with a short CSV-like block or markdown table containing only the flattened audit rows needed for interpretation.

    line 181
  11. Very specific:

    6 fields max per shade: Follow the extraction budget strictly.

    line 233
  12. Very specific:

    Re-use session state: If PaletteData is already in context from a prior step, skip the API call entirely (Step 0).

    line 236
  13. Very specific:

    textColorsTheme is required: Ensure every theme has textColorsTheme set (e.g.

    line 237

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Audit Contrast

Use the ui-color-palette MCP tool get_palette to generate a palette with contrast data, then analyze the results for WCAG and APCA compliance.

MCP tool reference

Tool: get_palette

Input schema: see ui-color-palette-scale-palette for full base and themes field definitions. Key requirement: every theme must have textColorsTheme: { lightColor: "#FFFFFF", darkColor: "#000000" } for textContrast to be populated.

Always pass compact: true — returns a flat array of shade rows instead of the full nested PaletteData tree. Each row already has theme, color, shade, hex, contrast, and textContrast at the top level. All other color space values are omitted server-side.

Pre-computed contrast data

Each shade includes pre-computed scores. Do NOT recalculate contrast — just read the values.

Do NOT read shade.contrast (shade vs palette background) — this skill only uses shade.textContrast (light/dark text on shade).

shade.textContrast — light & dark text on shade (requires textColorsTheme set in theme)

FieldPathTypeDescription
WCAG light ratiotextContrast.wcag.light.rationumberWhite text on shade
WCAG light scoretextContrast.wcag.light.score"A" | "AA" | "AAA"WCAG level
WCAG dark ratiotextContrast.wcag.dark.rationumberBlack text on shade
WCAG dark scoretextContrast.wcag.dark.score"A" | "AA" | "AAA"WCAG level
APCA light LctextContrast.apca.light.lcnumberWhite text Lc
APCA light usagetextContrast.apca.light.recommendedUsagestringRecommended usage
APCA dark LctextContrast.apca.dark.lcnumberBlack text Lc
APCA dark usagetextContrast.apca.dark.recommendedUsagestringRecommended usage

Audit dataset

With compact: true, the API already returns a flat array — one object per shade. No transformation needed before Step 3.

Row schema

Each row in the flat array has these fields:

ColumnSource pathDescription
themeTheme label
colorColor family name
shadeShade label
hexDisplay color
textContrast.wcag.light.ratioWhite text WCAG ratio
textContrast.wcag.light.scoreWhite text WCAG level
textContrast.wcag.dark.ratioBlack text WCAG ratio
textContrast.wcag.dark.scoreBlack text WCAG level
textContrast.apca.light.lcWhite text APCA Lc
textContrast.apca.light.recommendedUsageWhite text recommendation
textContrast.apca.dark.lcBlack text APCA Lc
textContrast.apca.dark.recommendedUsageBlack text recommendation
best_textderived — LIGHT or DARK
wcag_passderived — true if light or dark passes AA
apca_passderived — true if light or dark has `Lc>= 60`
global_passderived — true if wcag_pass and apca_pass

CSV-like representation

Prefer producing or reasoning from a compact CSV-like block instead of the original nested JSON:

theme,color,shade,hex,wcag_light_ratio,wcag_light_score,wcag_dark_ratio,wcag_dark_score,apca_light_lc,apca_light_usage,apca_dark_lc,apca_dark_usage,best_text,wcag_pass,apca_pass,global_pass
Light,primary,50,#F8FAFC,1.07,A,17.58,AAA,-4.2,AVOID,106.0,FLUENT_TEXT,DARK,true,true,true
Light,primary,100,#E2E8F0,1.32,A,13.16,AAA,-11.5,AVOID,95.2,FLUENT_TEXT,DARK,true,true,true

This flattened representation is the preferred input for audit reasoning, summary statistics, and visualization.

Standards

  • WCAG 2.1: Contrast ratios — AA requires 4.5:1 for normal text, 3:1 for large text; AAA requires 7:1 / 4.5:1
  • APCA: Lightness contrast (Lc) values — minimum Lc 60 for body text, Lc 45 for large text, Lc 30 for non-text

Workflow

Step 0 — Check session state (free)

Before calling any tool, check whether a PaletteData slot is already populated in the conversation context (e.g. produced by ui-color-palette-scale-palette in the same session).

  • If a compact flat array (from a previous get_palette call with compact: true) is present → skip to Step 3. No API call needed.
  • If only base + themes are present (no palette data) → continue to Step 1.
  • If nothing is present → ask the user for the source (palette config, hex colors, or palette ID).

Step 1 — Scope the audit (before calling the API)

Determine the minimum configuration required. Do not pass more themes than necessary.

Ask (or infer from context):

Which theme do you want to audit?

  • Light (recommended)
  • Dark
  • Both If you do not answer, I will audit Light only.

If the user has multiple color families and only cares about a subset, ask which ones — otherwise include all.

Important: Pass only the scoped themes in the themes array. Removing unused themes significantly reduces the get_palette response size.

Step 2 — Call get_palette (targeted)

Call get_palette with:

  • The full base configuration (unchanged)
  • Only the selected theme(s) in themes (not the full list if more exist)
  • Ensure every theme has textColorsTheme set (e.g. { lightColor: "#FFFFFF", darkColor: "#000000" }) — required for textContrast to be populated
  • compact: true — mandatory for this skill; returns a flat array and omits all raw color values

Step 3 — Python extraction

The compact: true response is already a flat array — no traversal needed. Pass it directly to Python to produce the audit CSV.

import json, sys

data = json.load(sys.stdin)  # flat array of shade rows

FIELDS = [
    "theme", "color", "shade", "hex",
    "wcag_light_ratio", "wcag_light_score",
    "wcag_dark_ratio",  "wcag_dark_score",
    "apca_light_lc",    "apca_light_usage",
    "apca_dark_lc",     "apca_dark_usage",
    "best_text", "wcag_pass", "apca_pass", "global_pass",
]
print(",".join(FIELDS))

for row in data:
    tc = row.get("textContrast", {})
    wl = tc.get("wcag", {}).get("light", {})
    wd = tc.get("wcag", {}).get("dark",  {})
    al = tc.get("apca", {}).get("light", {})
    ad = tc.get("apca", {}).get("dark",  {})

    wcag_pass = wl.get("score") in ("AA", "AAA") or wd.get("score") in ("AA", "AAA")
    apca_pass = abs(al.get("lc", 0)) >= 60 or abs(ad.get("lc", 0)) >= 60
    best_text = "DARK" if abs(ad.get("lc", 0)) > abs(al.get("lc", 0)) else "LIGHT"

    out = [
        row.get("theme", ""), row.get("color", ""), row.get("shade", ""), row.get("hex", ""),
        wl.get("ratio", ""), wl.get("score", ""),
        wd.get("ratio", ""), wd.get("score", ""),
        al.get("lc", ""),    al.get("recommendedUsage", ""),
        ad.get("lc", ""),    ad.get("recommendedUsage", ""),
        best_text, wcag_pass, apca_pass, wcag_pass and apca_pass,
    ]
    print(",".join(str(v) for v in out))

Reason only from the CSV output — the raw JSON array is no longer needed once the CSV is produced.

Step 4 — Analyze and output

  1. Build the data visualization from the flattened rows (see output format below).
  2. Compute the global contrast score as a consolidated percentage:
    • WCAG pass rate = (shades where at least one of light/dark passes AA) / total shades × 100
    • APCA pass rate = (shades where at least one of light/dark has |Lc| ≥ 60) / total shades × 100
    • Global score = average of WCAG pass rate and APCA pass rate, displayed as XX%
  3. Flag failing pairs and provide actionable recommendations.

Arguments

$ARGUMENTS can be a list of hex colors to audit or a palette ID.

  • /ui-color-palette:audit-palette #1E293B #F8FAFC #3B82F6 #FFFFFF
  • /ui-color-palette:audit-palette palette-id-abc123

Output format

The response should have 3 layers: compact dataset, visual audit table, and global score.

1. Compact audit dataset

Start with a short CSV-like block or markdown table containing only the flattened audit rows needed for interpretation.

theme,color,shade,hex,wcag_light_ratio,wcag_dark_ratio,apca_light_lc,apca_dark_lc,best_text,wcag_pass,apca_pass
Light,primary,50,#F8FAFC,1.07,17.58,-4.2,106.0,DARK,true,true
Light,primary,100,#E2E8F0,1.32,13.16,-11.5,95.2,DARK,true,true

2. Visual audit table

Then present results per color as a visual table, one row per shade:

Per-color table

Color: {colorName} {sourceHex}

ShadeSwatchHexLight WCAGDark WCAGLight APCADark APCABest textStatus
50[#F8FAFC]#F8FAFC1.07 / A17.58 / AAA-4.2 / AVOID106.0 / FLUENT_TEXTDarkPass
100[#E2E8F0]#E2E8F01.32 / A13.16 / AAA-11.5 / AVOID95.2 / FLUENT_TEXTDarkPass
...
  • Best text: recommend Light or Dark based on the highest WCAG score (prioritize AAA > AA > A), then highest APCA |Lc| as tiebreaker.
  • Status: Pass if the shade has at least one readable text color for both WCAG AA and APCA body text; otherwise Fail.

Global contrast score

╔══════════════════════════════════════════╗
║          GLOBAL CONTRAST SCORE           ║
║                                          ║
║              85%                         ║
║                                          ║
║  WCAG AA pass rate:  90% (27/30 shades)  ║
║  APCA body text:     80% (24/30 shades)  ║
║                                          ║
║  Failing shades: 3                       ║
╚══════════════════════════════════════════╝

Failing shades summary

List every shade that fails both light and dark text for WCAG AA (ratio < 4.5) or APCA body text (|Lc| < 60):

ColorShadeHexIssueRecommendation
primary400#60A5FANeither text passes AADarken to 500 or lighten to 300

End with the global score and recommendations.

Tips

  • 6 fields max per shade: Follow the extraction budget strictly. Never read shade.contrast, shade.rgb, shade.lch, shade.oklch, shade.lab, shade.oklab, shade.hsl, shade.hsluv, shade.hsv, shade.cmyk, shade.gl — they are not needed and inflate context size.
  • Discard raw data immediately: As soon as a shade's CSV row is produced, release the raw shade object. Reason exclusively from the flattened rows.
  • Scope before calling: Pass only the required theme(s) in the themes array. Each extra theme multiplies the response size.
  • Re-use session state: If PaletteData is already in context from a prior step, skip the API call entirely (Step 0).
  • textColorsTheme is required: Ensure every theme has textColorsTheme set (e.g. { lightColor: "#FFFFFF", darkColor: "#000000" }) — otherwise textContrast will be absent and the audit cannot proceed.
  • Hex to rgb conversion (for ColorConfiguration.rgb): divide each 0–255 channel by 255. E.g. #3B82F6 → { r: 0.23, g: 0.51, b: 0.96 }.

Recommended subagent

Delegate this skill to palette-auditor.

The palette-auditor agent is optimized for WCAG/APCA contrast audits, global contrast scoring, risky pair detection, and remediation proposals. It knows the audit dataset schema defined in this skill and works from the flattened row representation rather than traversing full PaletteData.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.