by mgechev
"Unit tests" for your agent skills
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
# Add to your Claude Code skills
git clone https://github.com/mgechev/skillgradeGuides for using ai agents skills like skillgrade.
Last scanned: 5/17/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-05-17T06:46:51.142Z",
"semgrepRan": false,
"npmAuditRan": true,
"pipAuditRan": true
}See how skillgrade compares with popular alternatives.
The easiest way to evaluate your Agent Skills. Tests that AI agents correctly discover and use your skills.
See examples/ — superlint (simple) and angular-modern (TypeScript grader).

Prerequisites: Node.js 20+, Docker
npm i -g skillgrade
1. Initialize — go to your skill directory (must have SKILL.md) and scaffold:
cd my-skill/
GEMINI_API_KEY=your-key skillgrade init # or ANTHROPIC_API_KEY / OPENAI_API_KEY
# Use --force to overwrite an existing eval.yaml
Generates eval.yaml with AI-powered tasks and graders. Without an API key, creates a well-commented template.
2. Edit — customize eval.yaml for your skill (see eval.yaml Reference).
3. Run:
GEMINI_API_KEY=your-key skillgrade --smoke
The agent is auto-detected from your API key: GEMINI_API_KEY → Gemini, ANTHROPIC_API_KEY → Claude, OPENAI_API_KEY → Codex. Override with --agent=claude.
4. Review:
skillgrade preview # CLI report
skillgrade preview browser # web UI → http://localhost:3847
Reports are saved to $TMPDIR/skillgrade/<skill-name>/results/. Override with --output=DIR.
| Flag | Trials | Use Case |
|---|---|---|
--smoke |
5 | Quick capability check |
--reliable |
15 | Reliable pass rate estimate |
--regression |
30 | High-confidence regression detection |
| Flag | Description |
|---|---|
--eval=NAME[,NAME] |
Run specific evals by name (comma-separated) |
--grader=TYPE |
Run only graders of a type (deterministic or llm_rubric) |
--trials=N |
Override trial count |
--parallel=N |
Run trials concurrently |
--agent=gemini|claude|codex|acp|opencode|command |
Override agent (default: auto-detect from API key) |
--model=NAME |
Model the agent answers with (gemini, claude, codex, opencode). Default: whatever the agent CLI is configured to use |
--provider=docker|local |
Override provider |
--acp-command=CMD |
ACP agent command (e.g., gemini --acp) |
--command=CMD |
Command to run for the command agent (e.g., node mycli.js) |
--opencode-agent=NAME |
OpenCode agent (build|plan|explore) |
--opencode-model=MODEL |
OpenCode model (provider/model format) |
--output=DIR |
Output directory (default: $TMPDIR/skillgrade) |
--validate |
Verify graders using reference solutions |
--ci |
CI mode: exit non-zero if below threshold |
--threshold=0.8 |
Pass rate threshold for CI mode |
--preview |
Show CLI results after running |
version: "1"
# Optional: explicit path to skill directory (defaults to auto-detecting SKILL.md)
# skill: path/to/my-skill
defaults:
agent: gemini # gemini | claude | codex | acp | opencode | command
model: claude-opus-5 # model the agent answers with (gemini, claude, codex, opencode)
provider: docker # docker | local
trials: 5
timeout: 300 # seconds
threshold: 0.8 # for --ci mode
grader_model: gemini-3-flash-preview # default LLM grader model
grader_provider: gemini # default LLM grader provider: gemini | anthropic | openai
command: node mycli.js # command to run when agent is 'command' (see Custom Command Agent)
acp: # ACP agent configuration (optional)
command: gemini --acp # command to start ACP-compatible agent
env: # optional environment variables
DEBUG: "1"
docker:
base: node:20-slim
setup: | # extra commands run during image build
apt-get update && apt-get install -y jq
environment: # container resource limits
cpus: 2
memory_mb: 2048
tasks:
- name: fix-linting-errors
instruction: |
Use the superlint tool to fix coding standard violations in app.js.
workspace: # files copied into the container
- src: fixtures/broken-app.js
dest: app.js
- src: bin/superlint
dest: /usr/local/bin/superlint
chmod: "+x"
graders:
- type: deterministic
setup: npm install typescript # grader-specific deps (optional)
run: npx ts-node graders/check.ts
weight: 0.7
- type: llm_rubric
rubric: |
Did the agent follow the check → fix → verify workflow?
provider: gemini # optional: gemini (default) | anthropic | openai
model: gemini-3.5-flash # optional model override
weight: 0.3
# Per-task overrides (optional)
agent: claude
model: claude-sonnet-5 # override the model for this task only
grader_provider: anthropic # override default LLM grader provider
trials: 10
timeout: 600
String values (instruction, rubric, run) support file references — if the value is a valid file path, its contents are read automatically:
instruction: instructions/fix-linting.md
rubric: rubrics/workflow-quality.md
A task can carry the row's answer key and a set of labels:
- name: easy--tooltip-token
instruction: |
Report the background colour token of the Tooltip's default variant.
Write {"token": "..."} to answer.json.
expected: # the answer key — graders only, never the agent
token: Brand/100
variants: [default, hover]
metadata: # labels for --filter, recorded with the results
tier: easy
form: open
tags: [smoke]
graders:
- type: deterministic
run: node graders/check-token.mjs
Both are optional: a task without expected is scored purely on what its
graders measure, so golden-truth and metric-style tasks live in the same suite.
skillgrade delivers expected, it never interprets it — comparison is the
grader's job. A deterministic grader receives the task context as one JSON
document in SKILLGRADE_INPUT, so expected keeps its structure:
// graders/check-token.mjs — one script for every token task
const { task, trial, expected, metadata } = JSON.parse(process.env.SKILLGRADE_INPUT);
const answer = JSON.parse(fs.readFileSync('answer.json', 'utf8')); // cwd is the workspace
console.log(JSON.stringify({
score: answer.token === expected.token ? 1 : 0,
details: `${task}: want ${expected.token}, got ${answer.token ?? '(none)'}`,
}));
# or from a shell grader
want=$(jq -r .expected.token <<< "$SKILLGRADE_INPUT")
An llm_rubric grader gets expected as an ## Expected Output section in its
prompt. Both channels are built after the agent process has exited, and neither
writes to the workspace — unlike run: and rubric:, which are staged into the
agent's working directory before it starts, so keep answer keys out of those.
metadata is what --filter selects on. Values are OR within a key and AND
across keys; --filter and --not-filter are repeatable:
skillgrade --filter=tier=easy,medium # easy OR medium
skillgrade --filter=tier=hard --filter=form=refuse # hard AND refuse
skillgrade --filter=tags=smoke --not-filter=tags=flaky
skillgrade --filter-pattern='^easy--' # regex over task names
skillgrade --filter=tier=easy --list # print the selection, run nothing
A filter on a key that no task declares is an error rather than a silent
match-everything — --filter=teir=easy should not quietly run the whole suite.
Filters work the same whether the tasks are inline or imported.
Any section can live in another file. $import takes a file, a directory (every
.yaml/.yml inside it, sorted), a glob, or a list of those:
version: "1"
defaults:
$import: shared/defaults.yaml # merged in place — keys below win
trials: 3
tasks:
- $import: evals/easy/*.yaml # one task per file, or a file holding a list
- $import: evals/hard # a whole directory
trials: 10 # applied to every task it imports
- name: still-inline # inline tasks keep working
instruction: ...
graders: [...]
Each imported file is a normal YAML document — a single task, a list of tasks, or
an object for a section like defaults. Imported files may import further files;
paths are relative to the file that contains the $import, and cycles are an error.
A task keeps working when you move it into its own file: its relative paths
resolve against its own directory first, then the eval root. So
evals/easy/one.yaml can say instruction: instruction.md for the file next to it
while still pointing run: node graders/check.mjs at the shared graders directory
at the root.
Runs a command and parses JSON from stdout:
- type: deterministic
run: bash graders/check.sh
weight: 0.7
Output format:
{
"score": 0.67,
"details": "2/3 checks passed",
"checks": [
{"name": "file-created", "passed": true, "message": "Output file exists"},
{"name": "content-correct", "passed": false, "message": "Missing expected output"}
]
}
score (0.0–1.0) and details are required. checks is optional.
Bash example:
#!/bin/bash
passed=0; total=2
c1_pass=false c1_msg="File missing"
c2_pass=false c2_msg="Content wrong"
if test -f output.txt; then
passed=$((passed + 1)); c1_pass=true; c1_msg="File exists"
fi
if grep -q "expected" output.txt 2>/dev/null; then
passed=$((passed + 1)); c2_pass=true; c2_msg="Content correct"
fi
score=$(awk "BEGIN {printf \"%.2f\", $passed/$total}")
echo "{\"score\":$score,\"details\":\"$passed/$total passed\",\"checks\":[{\"name\":\"file
skillgrade is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by mgechev. "Unit tests" for your agent skills. It has 705 GitHub stars.
Yes. skillgrade passed SkillsLLM's automated security scan — a dependency vulnerability audit plus prompt-injection heuristics — with no high-severity issues. You can read the full report in the Security Report section on this page.
Clone the repository with "git clone https://github.com/mgechev/skillgrade" and add it to your Claude Code skills directory (see the Installation section above).
skillgrade is primarily written in TypeScript. It is open-source under mgechev on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh skillgrade against similar tools.
No comments yet. Be the first to share your thoughts!