svg-animate — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited svg-animate (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are the entry point for SVG animation requests in this repository.
The repository (svg-animation-studio) is a compounding system: every animation reuses primitives from lib/primitives/, every new primitive earns the right to be added through /svg-add-primitive. Your job is to translate one sentence of natural language into a working output/<slug>.svg that visually delights — without breaking that compounding discipline.
LLMs that template-literal SVG strings end up with subtly broken markup, inconsistent IDs, and no way to evolve. This skill funnels everything through lib/composer.js so the system stays composable, snapshot-testable, and reusable across sessions. If you find yourself wanting to write <svg ...> inline anywhere, stop — composer.composeSVG exists for exactly that need.
ref/ (sketches, sample SVGs, screenshots).notification badge, ambient background, or icon.
talking, glowing, drifting, flickering.
If the request is vague ("make it cool"), ask one clarifying question — pick the highest-leverage one (usually: "what shape/character?" or "what motion?"). Don't grill the user.
Open lib/presets/index.js to see what already exists. Look at each candidate's compose() (~30 lines each) to learn the patterns. Decide one of:
slug, adjust params/colors.
primitives all exist in lib/primitives/. Build a new preset.
exist. Output a one-line summary plus:
"I need a<primitive-name>primitive inlib/primitives/<category>.js. Please run/svg-add-primitive <name>."
Do NOT add primitives inline. See docs/extension-protocol.md rule 1.
For inspiration mapping ("user wants X → reach for Y"), open references/preset-cookbook.md.
For the full lib API (signatures + defaults), open references/lib-api.md.
For any branded / multi-layer asset (cover, banner, logo, loader), use the modern composition path (it's how the quality bar is reproduced):
getPalette(opts.palette || '<default>') from lib/palettes.jsand reference accents by index (pal.accents[0]) — never hardcode hex.
composeScene({ layers, defs, style }) from lib/scene.js:it orders layers back-to-front and auto-nests a layer's static transform + animated className (so the CSS transform can't clobber positioning — Gotcha 2).
brandCover.js / gradientCover.js(covers), heroStrip.js / repoHero.js (banners), orbitLogo.js / pulseMonoLogo.js / spinBadge.js (logos/badges), dotLoader.js / rippleLoader.js / bounceChar.js (loaders/characters). chan-cover is the FROZEN reference — fork brand-cover instead.
For why timing / squash / staggering matter, open references/animation-principles.md. The 5-point quality checklist there is the same one /svg-verify will grade against — design with it in mind.
A preset file lives at lib/presets/<slugCamelCase>.js and exports:
module.exports = {
name: '<slug-kebab>',
viewBox: '0 0 W H',
width: W, height: H,
compose(opts = {}) {
motion.resetIdCounter(); // mandatory first line
// pull primitives, compose body + style, return composeSVG({...})
}
};Add the new slug to lib/presets/index.js.
Constraints, in priority order:
composeSVG is the only allowed way to assemble the root <svg> document.motion.resetIdCounter() as the first line of compose() so classnames are deterministic across calls — this is what makes snapshots stable.
user to override via opts.
≥ 1 primitive validates the compounding contract.
node lib/render-cli.js <slug>This writes to output/<slug>.svg. Inspect file size — if it's < 200 bytes, something is wrong (probably an empty body); if it's > 20 KB without good reason (heavy gradients or many elements), something is duplicated.
npm run test:snapshotFirst time for a new preset → snapshot is created. Subsequent runs → diff is shown. If diff is intentional (you tuned params), update with:
npm run snapshot:updateAlways re-verify visually after a snapshot update.
Invoke /svg-verify <slug> — it runs in an isolated subagent context, opens the SVG in chrome-devtools MCP, scores against the 5-point rubric, and returns ≤ 100 words. The screenshots and console messages stay in the subagent's context so this main thread doesn't drown in image data.
If the verdict is tweak: adjust params (duration, easing, magnitude, stagger), re-render, re-verify. Cap at 3 rounds before pausing to ask the user. If fail: probably a structural issue — re-read the source primitives and reconsider composition rather than tweaking magnitudes.
If pass: report to the user with:
output/<slug>.svgmotion.foo, shapes.bar, .../svg-export <slug> to optimize and ship.<svg ...> markup directly in a skill or preset. Always gothrough composer.composeSVG.
lib/primitives/*.js without going through/svg-add-primitive. The protocol exists to keep JSDoc, snapshot coverage, and lib-api.md in sync.
npm run snapshot:update without a visual recheck. Snapshotsare the only thing protecting you from silent regressions.
without a pass, pause and ask.
motion.* primitive already coversthe motion. Composability is the whole point.
If the user asks for "a few options", "show me 3 styles", "give me variants", or "compare different approaches", delegate to the svg-explorer subagent instead of running variants serially in this thread. The Agent dispatch pattern:
Use the svg-explorer agent to produce <N> variants of
"<user's description>" varying along axis <timing|palette|style|energy>.It returns a comparison block with file paths + a recommendation. Then run /svg-verify <recommended-slug> on the chosen winner, and /svg-export if the user accepts.
Why delegate? Generating N presets in parallel + rendering N SVGs + reading N preset diffs would pump verbose intermediate output into this thread. The fork keeps the comparison clean: you only see the final summary.
npm test fails on a preset you didn't touch → you broke a primitivesignature. Diff your primitive changes and either fix them or update the snapshot deliberately after visual recheck.
compose() throws → almost certainly a missing or renamed primitive.Open docs/lib-api.md and grep for the function you tried to call.
animation-principles.md section "Staggering"; the magnitude is probably outside 0.05–0.15 s.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.