About seo-score
A skill that calculates Search SEO and AI Visibility scores from findings, applying defined weights, severity caps, bands, and coverage rules. It is for producing reproducible scores from audit results.
Key features
- 01Calculates Search SEO and AI scores
- 02Applies status and severity factors
- 03Adjusts active category weights
- 04Caps scores for severe failures
- 05Reports bands and coverage
Use cases
- 01Scoring a set of SEO findings
- 02Comparing search and AI visibility results
- 03Producing reproducible audit scores for CI
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ hainrixz/ claude-seo-ai --skill seo-scoreAfter installing, type/seo-scorein Claude Code to confirm it loaded.
Details
From the project READMEseo-score
Turns findings (conforming to schema/finding.schema.json) into the two scores. Full model in references/scoring-model.md — follow it exactly.
Steps
- Group findings by the category each module maps to, per score. A finding contributes only to the score(s) in
expected_impact.axis(search,ai, orboth). - Category value =
100 × Σ(status_factor × severity for scored findings) / Σ(severity), wherestatus_factor: pass 1.0, warn 0.5, fail 0.0. Excludeneeds_apiandnot_applicablefrom both sums. - Active weights: drop conditional categories (e-commerce/local/international) whose modules produced no findings; re-normalize remaining weights to sum to their active total.
- Score =
Σ(category_value × weight) / Σ(active weight)for each of Search SEO and AI Visibility. - Severity gating: if any finding has
severity: 5andstatus: fail, cap the affected score at 40 and setcapped: true. - Assign bands (A≥90, B≥80, C≥70, D≥60, F<60) and a one-line interpretation from the Search×AI quadrant.
6b. Coverage floor: report
coverage(the % of the axis's always-on weight that carried a scored finding). Below 50% the axis comes backprovisional: truewithstate: "partial"— quote the band and the coverage figure together, never the letter on its own. - M21 (AI discovery & agent endpoints — llms.txt, agents.md, UCP, agentic sitemap) weight is 0 — report it, never let it move the AI score.
Determinism
Prefer node "${CLAUDE_PLUGIN_ROOT}/scripts/score.mjs" --run <run-dir> (it reads <run-dir>/findings.json) or --findings <path> for a bare findings file, adding --vertical a,b, --multilingual and --environment production|preview|staging|local when the file carries no run context, so the number is reproducible and CI-checkable. --run takes a path, never the word latest: the score command resolves latest[:host] from <root>/<host>/latest.json first and passes the directory. If Node is unavailable, compute by hand following the same formula and note the fallback. Either way the math must match references/scoring-model.md.
Output
{ "search_seo": { "value": 78, "band": "C", "capped": false, "interpretation": "...", "categories": [ {"name":"Indexability & Crawl","weight":22,"value":91,"active":true}, ... ] },
"ai_visibility": { "value": 64, "band": "D", "capped": false, "interpretation": "Citable structure missing; add answer blocks and schema.", "categories": [ ... ] } }