Evaluate Skills#

GET/v1/repos/{owner}/{repo}/evaluate

Evaluate skills in a GitHub repository. Omit path to scan the entire repo and evaluate every SKILL.md found. Provide path to evaluate a single skill at that location.

Path Parameters#

ParameterTypeDescription
ownerstringGitHub username or organization
repostringRepository name

Query Parameters#

ParameterTypeDescription
pathstringOptional. Path to a specific skill — omit to evaluate all skills in the repo

GitHub URL segments are stripped automatically. You can paste paths directly from GitHub's UI — segments like tree/main/ or blob/main/ are removed before lookup. Both skills/my-skill and skills/my-skill/SKILL.md work.

Results are cached by commit SHA for 1 hour. If the repo's HEAD hasn't changed, the response is served from cache.

Response#

The response shape depends on whether path is provided.

  • Without path — returns a ScanResult object with a skills array containing one SkillResult per SKILL.md found (up to 50).
  • With path — returns a SkillEvaluateResult object: the skill's fields flattened at the top level alongside owner, repo, commit_sha, and scanned_at. No skills array, no truncated field.

Response Schemas#

ScanResult#

The root response object returned by the evaluate endpoint. Contains repository metadata and an array of evaluated skills.

FieldTypeDescription
ownerstringGitHub username or organization
repostringRepository name
commit_shastringFull SHA of the commit that was scanned
skillsSkillResult[]Array of evaluated skills found in the repository
scanned_atstringISO 8601 timestamp of when the scan was performed
errorstring | nullTop-level error message if the scan itself failed, otherwise null
truncatedbooleanTrue if the repository contained more than 50 skills and results were capped

Example

response
{ "owner": "anthropics", "repo": "claude-code", "commit_sha": "a04e4f9...", "skills": [ { "path": "skills/git-commit/SKILL.md", "name": "git-commit", "quality_score": 85.0, "overall_pass": true, "checks_run": 37, "checks_passed": 30, "checks_failed": 3, "results": [...] } ], "scanned_at": "2025-03-24T12:00:00+00:00", "error": null, "truncated": false }

SkillEvaluateResult#

The response object returned by GET /v1/repos/{owner}/{repo}/evaluate?path=.... A single skill's evaluation fields hoisted to the top level alongside repository metadata. No skills array, no truncated field.

FieldTypeDescription
ownerstringGitHub username or organization
repostringRepository name
commit_shastringFull SHA of the commit that was evaluated
scanned_atstringISO 8601 timestamp of when the evaluation was performed
pathstringPath to the SKILL.md file within the repository
namestring | nullSkill name extracted from frontmatter
descriptionstring | nullSkill description extracted from frontmatter
quality_scorenumberOverall quality score from 0 to 100
overall_passbooleanWhether all high-severity checks passed
checks_runnumberTotal number of checks executed
checks_passednumberNumber of checks that passed
checks_failednumberNumber of checks that failed
resultsCheckResult[]Detailed results for each individual check
summaryobjectAggregated pass/fail counts grouped by severity and dimension
errorstring | nullError message if the skill failed to evaluate, otherwise null

Example

response
{ "owner": "anthropics", "repo": "claude-code", "commit_sha": "a04e4f9...", "scanned_at": "2025-03-24T12:00:00+00:00", "path": "skills/git-commit/SKILL.md", "name": "git-commit", "description": "Write conventional commit messages", "quality_score": 85.0, "overall_pass": true, "checks_run": 37, "checks_passed": 30, "checks_failed": 3, "results": [...], "summary": {...}, "error": null }

SkillResult#

Represents the evaluation of a single SKILL.md file. Contains the quality score, individual check results, and aggregated summary.

FieldTypeDescription
pathstringPath to the SKILL.md file within the repository
namestring | nullSkill name extracted from frontmatter
descriptionstring | nullSkill description extracted from frontmatter
quality_scorenumberOverall quality score from 0 to 100
overall_passbooleanWhether all high-severity checks passed
checks_runnumberTotal number of checks executed
checks_passednumberNumber of checks that passed
checks_failednumberNumber of checks that failed
resultsCheckResult[]Detailed results for each individual check
summaryobjectAggregated pass/fail counts grouped by severity and dimension
errorstring | nullError message if this skill failed to evaluate, otherwise null

Summary Object

The summary field contains aggregated pass/fail counts, grouped two ways.

summary shape
{ "by_severity": { "high": { "passed": 5, "failed": 0 }, "medium": { "passed": 12, "failed": 2 }, "low": { "passed": 13, "failed": 1 } }, "by_dimension": { "structure": { "passed": 10, "failed": 1 }, "naming": { "passed": 3, "failed": 0 }, "description": { "passed": 2, "failed": 1 }, "content": { "passed": 10, "failed": 1 }, "security": { "passed": 5, "failed": 0 } } }

CheckResult#

An individual check result from the evaluation. There are 37 checks across 5 dimensions, each with a severity level.

FieldTypeDescription
check_idstringUnique identifier for the check
check_namestringHuman-readable check name
passedbooleanWhether this check passed
severity"high" | "medium" | "low"Severity level of the check
dimensionstringQuality dimension: "structure", "naming", "description", "content", or "security"
messagestringHuman-readable result message
fixstring?Suggested fix when the check fails
detailsobject?Additional check-specific data
locationstring?File location relevant to the check

Dimensions

DimensionDescription
structureSKILL.md existence, valid frontmatter, file organization
namingSkill name format, kebab-case, directory match
descriptionPresence, length, actionable phrasing
contentBody quality, examples, token budget, references
securityPrompt injection, YAML anomalies, unicode obfuscation

Example

single check result
{ "check_id": "naming_format", "check_name": "Name Format", "passed": false, "severity": "high", "dimension": "naming", "message": "Skill name 'MySkill' is not in kebab-case", "fix": "Rename to 'my-skill'" }

Errors#

StatusCause
404Repository or skill path not found
429GitHub API rate limit reached

Examples#

Whole repo:

bash
curl "https://api.skill-lab.dev/v1/repos/anthropics/claude-code/evaluate"
javascript
const res = await fetch("https://api.skill-lab.dev/v1/repos/anthropics/claude-code/evaluate");
const data = await res.json();
// data.skills[0].quality_score
python
import httpx

res = httpx.get("https://api.skill-lab.dev/v1/repos/anthropics/claude-code/evaluate")
data = res.json()
# data['skills'][0]['quality_score']

Single skill:

bash
curl "https://api.skill-lab.dev/v1/repos/owner/repo/evaluate?path=my-skill"
javascript
const res = await fetch("https://api.skill-lab.dev/v1/repos/owner/repo/evaluate?path=my-skill");
const data = await res.json();
// data.quality_score
python
import httpx

res = httpx.get("https://api.skill-lab.dev/v1/repos/owner/repo/evaluate?path=my-skill")
data = res.json()
# data['quality_score']

GitHub-style path (auto-stripped):

bash
# tree/main/ is stripped automatically
curl "https://api.skill-lab.dev/v1/repos/owner/repo/evaluate?path=tree/main/skills/my-skill"