Skip to content

chore: add AGENTS.md and agent skills for making and reviewing icons - #2822

Open
Snailedlt wants to merge 12 commits into
devicons:developfrom
Snailedlt:chore/claude-skills
Open

Snailedlt wants to merge 12 commits into
devicons:developfrom
Snailedlt:chore/claude-skills

Conversation

@Snailedlt

@Snailedlt Snailedlt commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Sets up the repo for AI coding agents: an AGENTS.md guide and two Agent Skills under .claude/skills/. Nothing else changes; the build and the website aren't affected.

AGENTS.md

Short guide: where things are, and links to the wiki for the rules (icons, PR titles, releases) instead of copying them, so the wiki stays the one place to update. AGENTS.md is read by most agents (Codex, Copilot, Cursor, …); CLAUDE.md only imports it for Claude Code.

Skills

Claude Code (and other agents with skill support) load them automatically. Agents without it can read each SKILL.md and run the scripts directly.

svg-icons: making and fixing icons

devicon-icon-review: reviewing icon PRs

  • references/devicon-standards.md: the wiki's rules plus what maintainers ask for in reviews, each with a link to an example comment.
  • scripts/check_icon.js: checks an icon's devicon.json entry against its files (versions vs files, font versions are one path in one fill matching color, aliases, id prefixes, sort order).
  • It posts to GitHub only when asked, and never approves on its own.

Both skills include a few test cases in evals/.

Prepared by Claude (an AI assistant) on behalf of @Snailedlt.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Yashh56
Yashh56 requested review from a team, Yashh56, canaleal, lunatic-fox and weh and removed request for a team October 31, 2026 17:08
@Snailedlt
Snailedlt requested a balanced review from Copilot November 1, 2026 11:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved defects can alter official SVG artwork, accept invalid icons, reject valid aliases, and hide missing files during directory comparisons.

9 open issues
1 file not reviewed
  • .claude/skills/svg-icons/scripts/package-lock.json: Generated file
What changed in this PR

Adds two repository-local Claude Code skills for creating SVG icon variants and reviewing Devicon icon contributions. The changes provide contributor tooling and evaluation fixtures without changing production icons, the website, or the build.

Changes:

  • Adds SVG inspection, rendering, generation, optimization, validation, tracing, and comparison helpers.
  • Documents Devicon review standards and adds a metadata/file consistency checker.
  • Adds four evaluation scenarios covering icon creation, font repair, and reviews.
File Description
.claude/​skills/​svg-icons/​SKILL.md Defines SVG tooling setup and workflow.
.claude/​skills/​svg-icons/​scripts/​versions.js Generates icon and wordmark variants.
.claude/​skills/​svg-icons/​scripts/​validate.js Checks SVG structure and geometry.
.claude/​skills/​svg-icons/​scripts/​trace.js Traces raster colour masks into paths.
.claude/​skills/​svg-icons/​scripts/​render.js Creates multi-size PNG previews.
.claude/​skills/​svg-icons/​scripts/​pixdiff.js Compares rendered SVG pixels.
.claude/​skills/​svg-icons/​scripts/​paperenv.js Configures Paper.js with a stub canvas.
.claude/​skills/​svg-icons/​scripts/​package.json Declares helper dependencies.
.claude/​skills/​svg-icons/​scripts/​package-lock.json Locks helper dependency resolutions.
.claude/​skills/​svg-icons/​scripts/​optimize.js Optimizes SVGs and prefixes IDs.
.claude/​skills/​svg-icons/​scripts/​inspect.js Reports shapes, colours, and bounds.
.claude/​skills/​svg-icons/​scripts/​build.js Provides shared geometry and export helpers.
.claude/​skills/​svg-icons/​references/​techniques.md Documents icon-processing recipes.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​prompt.md Requests original and plain variants.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​place-files.sh Copies evaluation input files.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​graders/​08-looked-at-render.md Checks visual inspection occurred.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​graders/​07-original-colours.md Checks original colours are preserved.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​graders/​06-fills-box.md Checks sizing and centring.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​graders/​05-gap-between-colours.md Checks separation between colour regions.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​graders/​04-letter-is-hole.md Checks white details become transparent holes.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​graders/​03-plain-one-colour.md Checks the plain variant is monochrome.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​graders/​02-plain-one-path.md Checks single-path output.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​graders/​01-viewbox-no-size.md Checks viewBox and root dimensions.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​files/​acme-logo.svg Supplies a multicolour logo fixture.
.claude/​skills/​svg-icons/​evals/​plain-from-multicolour-logo/​case.yaml Defines variant-generation expectations.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​prompt.md Requests repair of a stroked icon.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​place-files.sh Copies the repair fixture.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​graders/​05-explains-cause.md Checks the font issue is explained.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​graders/​04-colour-kept.md Checks colour preservation.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​graders/​03-ring-hole-kept.md Checks ring transparency is preserved.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​graders/​02-looks-the-same.md Checks visual fidelity after repair.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​graders/​01-one-path-no-strokes.md Checks strokes become one filled path.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​files/​radar-plain.svg Supplies a stroked radar fixture.
.claude/​skills/​svg-icons/​evals/​fix-stroked-plain-for-font/​case.yaml Defines font-repair expectations.
.claude/​skills/​devicon-icon-review/​SKILL.md Defines review workflow and posting boundaries.
.claude/​skills/​devicon-icon-review/​scripts/​check_icon.js Checks icon metadata and SVG files.
.claude/​skills/​devicon-icon-review/​references/​devicon-standards.md Collects standards and review references.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​prompt.md Requests a local Drizzle review.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​place-files.sh Copies the Drizzle snapshot.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​graders/​07-nothing-posted.md Checks no GitHub writes occur.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​graders/​06-fixes-given.md Checks feedback includes concrete fixes.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​graders/​05-requests-changes.md Checks the expected review verdict.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​graders/​04-flags-font-plain.md Checks missing font-version detection.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​graders/​03-flags-white-fill.md Checks near-white fill detection.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​graders/​02-flags-padding.md Checks padding is identified.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​graders/​01-flags-width-height.md Checks root dimensions are flagged.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​files/​icons/​drizzle/​drizzle-original.svg Supplies an intentionally flawed SVG.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​files/​devicon.json Supplies metadata with a font mismatch.
.claude/​skills/​devicon-icon-review/​evals/​review-drizzle-pr-snapshot/​case.yaml Defines expected Drizzle findings.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​prompt.md Requests an Nx readiness review.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​place-files.sh Copies the Nx snapshot.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​graders/​04-font-ready-confirmed.md Checks font-readiness confirmation.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​graders/​03-checked-official-logo.md Checks comparison with the official source.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​graders/​02-no-false-violations.md Checks avoidance of false findings.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​graders/​01-no-blocking-issues.md Checks the expected clean-review verdict.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​files/​icons/​nx/​nx-original.svg Supplies the Nx original fixture.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​files/​icons/​nx/​nx-line.svg Supplies the Nx line fixture.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​files/​devicon.json Supplies Nx versions and alias metadata.
.claude/​skills/​devicon-icon-review/​evals/​review-clean-nx-icon/​case.yaml Defines clean-review expectations.

Review effort: Balanced

Comment on lines +176 to +177
.replace(/\s(font-family|font-size|font-weight|text-anchor)="none"/g, '')
.replace(/\s(stroke-width="0"|stroke-miterlimit="[^"]*"|stroke="none"|fill-rule="nonzero"|stroke-dasharray="none")/g, '');

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing this. The cleanup now only runs on paper.js's own output, which is flat with nothing inherited, so it can't change the artwork. optimize.js passes generic: true and leaves arbitrary SVGs to SVGO.

Prepared by Claude (an AI assistant) on behalf of @Snailedlt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Snailedlt Snailedlt changed the title chore: add Claude Code skills for making and reviewing icons chore: add CLAUDE.md and Claude Code skills for icon work Nov 1, 2026
- check_icon: an alias may share a name with a non-font SVG (e.g. Babel);
  flag fill="none" in font versions
- validate: reject extra shapes/groups in plain/line; flag artwork outside the box
- pixdiff: report files missing from either folder
- build: keep group opacity; don't flatten groups with transforms/compositing;
  paper.js cleanup only on paper output, not in optimize.js
- versions: a logo with white parts isn't treated as one-colour
- AGENTS.md holds the guide so any agent can use it; CLAUDE.md imports it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Snailedlt Snailedlt changed the title chore: add CLAUDE.md and Claude Code skills for icon work chore: add AGENTS.md and agent skills for making and reviewing icons Nov 1, 2026
@Snailedlt

Copy link
Copy Markdown
Collaborator Author

Thanks, Copilot. All 9 points were valid; fixed in 85f5eed:

  • Aliases: an alias may share its name with an SVG that isn't a font version (Babel's plain → original is the normal pattern). Only a clash with a font version is an error now; the docs are updated too.
  • fill="none" in a font version is now an error.
  • validate.js: extra shapes or groups in plain/line fail, and so does artwork outside the 128 box.
  • pixdiff.js: files missing from either folder are reported.
  • build.js: group opacity is kept; groups with transforms, opacity, clip paths, masks or filters aren't flattened; the paper.js cleanup only runs on paper's own output, not in optimize.js.
  • versions.js: a logo with white parts isn't treated as one-colour, so its original keeps the white fills.

Tested with real icons (babel, nx, informatica, vlang, react). The results are the same as before, apart from the intended fixes.

Prepared by Claude (an AI assistant) on behalf of @Snailedlt.

@Snailedlt
Snailedlt requested a balanced review from Copilot November 1, 2026 12:20
@Snailedlt
Snailedlt marked this pull request as draft November 1, 2026 12:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved defects can change SVG opacity and CSS styling, incorrectly validate font glyphs, and crash alias checks on malformed metadata.

3 open issues
4 previously missed issues

In code that hasn't changed since last review

Medium severity Reject null aliases before validating or checking alias references

.claude/​skills/​devicon-icon-review/​scripts/​check_icon.js:56

An alias array containing null crashes this check because typeof null is "object", so accessing a.base throws before an error is recorded. Invalid entries also remain available to the later aliases.some(a => a.base === v) call. Reject null explicitly and retain only structurally valid aliases for subsequent checks so malformed metadata produces an ERROR report instead of a TypeError.

Medium severity Exclude definitions and account for use instances in font path checks

.claude/​skills/​devicon-icon-review/​scripts/​check_icon.js:114

This counts paths inside <defs> as drawable artwork and does not count <use> instances. A font SVG containing only <defs><path .../></defs> passes despite rendering nothing, and a definition instantiated twice also passes as a single-path glyph. Reject definitions and uses in font versions, or expand references before checking the visible paths.

Medium severity Update CSS ID selectors when prefixing SVG element IDs

.claude/​skills/​svg-icons/​scripts/​build.js:199

This renames element IDs but leaves CSS ID selectors unchanged. For example, a media-query rule targeting #mark stops matching after the element becomes id="demo-original-mark". The helper therefore changes the appearance of SVGs with retained styles, including when called by optimize.js. Use SVG/CSS-aware prefixing, such as SVGO's prefixIds plugin, to update selectors and references together while retaining existing prefixes.

Medium severity Restrict single-path shortcut to fully opaque SVG leaves

.claude/​skills/​svg-icons/​scripts/​versions.js:56

A one-colour SVG with opacity="0.5" still passes this test, so original (and potentially original-wordmark) takes the one(lp, ...) shortcut. pathSvg() exports only path data and a fill, dropping the opacity and making the original fully opaque. Restrict this shortcut to fully opaque leaves, including fill alpha, so translucent originals go through originalOf() instead.

7 resolved since last review
1 file not reviewed
  • .claude/skills/svg-icons/scripts/package-lock.json: Generated file

Review effort: Balanced

mask = clip ? clip.intersect(m, { insert: false }) : m;
kids.shift();
}
kids.forEach(k => walk(k, mask, op * item.opacity));

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing this. Rebuilding compositing groups is a lot of code for something logos almost never use. Group opacity is multiplied onto each shape, which is exact unless shapes overlap, and leaves() prints a warning whenever opacity is involved.

Prepared by Claude (an AI assistant) on behalf of @Snailedlt.

Snailedlt and others added 2 commits November 1, 2026 13:30
- check_icon: report null/malformed aliases instead of crashing; reject
  <defs>/<symbol>/<use> in font versions
- prefixIds: also rename ID selectors in <style>
- versions: semi-transparent logos don't take the one-path shortcut
- leaves: warn when group opacity is flattened onto overlapping shapes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Snailedlt

Copy link
Copy Markdown
Collaborator Author

Second round, fixed in a858353:

  • Null aliases: malformed aliases are now reported as errors instead of crashing the check.
  • <defs>/<symbol>/<use> in font versions are rejected.
  • prefixIds also renames ID selectors inside <style>.
  • Semi-transparent logos no longer take the one-path shortcut in versions.js.

Not changing two things:

  • Group opacity compositing: recreating compositing groups is a lot of code for something logos almost never use. The leaves now get the multiplied opacity, which is exact unless shapes overlap, and the script prints a warning whenever opacity is involved.
  • Context-dependent cleanup: this now only runs on paper.js's own output, which is flat with nothing inherited, so removing those attributes can't change the artwork. optimize.js leaves arbitrary SVGs to SVGO.

I re-ran the skill evals (4 cases) after these changes; with the skills, every check passes.

Prepared by Claude (an AI assistant) on behalf of @Snailedlt.

Font versions may only have <svg xmlns viewBox> and one <path d fill>;
anything else is reported, instead of listing what isn't allowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Snailedlt

Copy link
Copy Markdown
Collaborator Author

@copilot Font versions are now checked against an allowlist (9cd4b66): only <svg xmlns viewBox> and one <path d fill> are allowed, and anything else is reported. This replaces the list of forbidden elements and attributes, so <defs>, <use>, styles, opacity and fill-rule are covered without naming each one. Also, svg-icons fixes now keep an icon's size unless asked (00b8aee). All skill evals still pass.

Prepared by Claude (an AI assistant) on behalf of @Snailedlt.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Geometry handling can silently discard visible artwork and alter faithful originals, while validation and SVG preview-generation defects also remain active.

2 open issues
5 previously missed issues

In code that hasn't changed since last review

High severity Retain non-empty paths regardless of area or contour winding

.claude/​skills/​svg-icons/​scripts/​build.js:59

This area filter silently drops visible artwork: small source-coordinate shapes fall below 0.01, and disjoint contours with opposite winding can have a summed signed area of zero. The builders can then omit logo details or fail on empty geometry before fitting it to 128 units. Remove the area cutoff from leaves() so neither source scale nor contour winding determines whether a non-empty path is retained.

High severity Preserve faithful originals when geometry-changing plain options are active

.claude/​skills/​svg-icons/​scripts/​versions.js:56

With a monochrome logo and --gap 2.5, this shortcut writes original from the processed plain path, whose shrink-and-regrow step can round corners or remove thin details. The same issue affects original-wordmark. Disable the shortcut when geometry-changing plain options are active so these options cannot alter the faithful original.

Medium severity Reject empty path data when validating icon glyphs

.claude/​skills/​devicon-icon-review/​scripts/​check_icon.js:80

Counting paths does not establish that the glyph contains any geometry. With an otherwise valid entry, both <path fill="#123456"/> and <path fill="#123456" d=""/> currently produce zero errors and exit 0, although they render an empty icon. Require non-empty d data for the sole path before reporting the font version as valid.

Medium severity Prevent SVGO from converting required hex fills to named colors

.claude/​skills/​svg-icons/​scripts/​build.js:185

SVGO's default convertColors can shorten #ff0000 to red, but both validate.js and check_icon.js reject non-hex fills in font versions. Consequently, building or optimizing a red plain/line icon produces output that fails the supplied validation workflow. Disable named-colour shortening here so optimized fills retain the required hexadecimal representation.

Medium severity Escape filenames before embedding them in SVG text

.claude/​skills/​svg-icons/​scripts/​render.js:46

The filename is inserted into SVG text without XML escaping. A valid input filename such as AT&T.svg makes the preview sheet malformed XML, so rendering fails even though the input SVG is valid. Escape the text before embedding it.

1 resolved since last review
1 file not reviewed
  • .claude/skills/svg-icons/scripts/package-lock.json: Generated file

Review effort: Balanced

- leaves: keep shapes by bounds, not signed area (small units, opposite winding)
- versions: one-colour originals come from the raw shapes, not --gap's smoothing
- check/validate: a font path needs path data
- optimize: keep #hex fills (no SVGO colour names)
- render: escape file names in the preview sheet

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Snailedlt

Copy link
Copy Markdown
Collaborator Author

@copilot Fixed all 5 new points in 9ba6cc0:

  • Shape filter: shapes are kept when their bounds are non-empty, not by signed area.
  • One-colour originals: built from the raw shapes, so --gap no longer smooths them.
  • Empty paths: a font path without path data is now an error.
  • Hex fills: SVGO keeps #hex and no longer shortens fills to colour names.
  • Preview sheet: file names are escaped.

The 2 older points still stand as explained above. All skill evals still pass.

Prepared by Claude (an AI assistant) on behalf of @Snailedlt.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human assessment is needed to evaluate multiple SVG transformation and validation risks that can corrupt artwork, miss invalid fills, or prevent output generation.

2 open issues
1 file not reviewed
  • .claude/skills/svg-icons/scripts/package-lock.json: Generated file

Review effort: Balanced

@Snailedlt
Snailedlt marked this pull request as ready for review November 1, 2026 13:40
@Snailedlt Snailedlt added devops Devops, devex and automation related enhancements and removed enhancement labels Nov 1, 2026
Snailedlt and others added 2 commits November 1, 2026 19:09
svgo.config.js follows devicon's SVGOMG guide with precision 3 (lower
precision broke icomoon glyphs in devicons#2380), #hex colours, <style> classes
inlined before the element is dropped and raster images left for
validation to catch.

svg-icons optimizes changed files as the last change, then validates and
renders again. optimize.js --check lets the review flag files that would
shrink by over 20% (or 4 KB); smaller savings are noise from other SVGO
versions. The review also asks for peek screenshots of the latest SVGs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
optimize.js --check needed 500 saved bytes, which let small unoptimized
files through (41% on a 1 KB icon). 200 bytes still keeps re-optimized
files out. The drizzle review eval now also expects the review to flag
the unoptimized SVG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Snailedlt and others added 3 commits November 2, 2026 01:29
- convert colour names to hex before paper.js imports the SVG; paper
  resolves names through a canvas, which is a stub here, so "black"
  came out as #aN
- move gradient points with the fit in originals (they kept the
  source's coordinates)
- add --holes for light artwork on a tile, which isn't white enough to
  become holes in plain/line

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SVG fills an open subpath as if it were closed, but paper.js drops its
last segment in unite/subtract, so a rounded corner drawn last became a
straight cut (seen on Power BI's tallest bar).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_icon.js warns about #rrggbb colours (entry and SVGs) that fit #rgb; the docs ask for short hex.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devops Devops, devex and automation related enhancements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants