# Skill Lab API & CLI Reference > Generated from MDX sources at build time. The rendered page at https://skill-lab.dev/docs and this markdown share the same content — edits to the MDX update both. Base URL: `https://api.skill-lab.dev` Hosted docs: https://skill-lab.dev/docs Machine-readable index: https://skill-lab.dev/llms.txt --- ## Overview ### Introduction v1 REST / JSON API Reference // api.skill-lab.dev Programmatically scan GitHub repositories for SKILL.md files and evaluate them against 37 quality and security checks. Returns structured JSON with scores, pass/fail results, and fix suggestions. ```text https://api.skill-lab.dev ``` #### Quick Example ```bash curl https://api.skill-lab.dev/v1/repos/anthropics/claude-code/evaluate ``` > Prefer running locally? > [Install the sklab CLI](/docs/cli/cli-install) > to run the same checks and LLM judge against a skill directory on your > machine — no repo push required. ### Errors All error responses return a JSON object with a `detail` field containing the error message. error response format: ```json { "detail": "Not found: owner/repo. Check the URL and make sure the repository is public." } ``` #### Status Codes | Status | Meaning | When | | ------ | ------------ | --------------------------------------------------------------------------------- | | 400 | Bad Request | Malformed JSON body or validation failure | | 404 | Not Found | Repository or skill path does not exist, or the repository is private | | 429 | Rate Limited | Per-IP rate limit exceeded, or GitHub API rate limit exhausted on the server side | | 502 | Bad Gateway | Upstream service error (LLM endpoints) | Validation errors return detail as either a string or an array of Pydantic validation error objects. ### Rate Limits Requests are rate-limited per IP address. Limits vary by endpoint type: | Endpoint | Rate Limit | | -------------------------------------------- | ------------------ | | Scan endpoints (/evaluate, /info, /export) | 30 requests/minute | | LLM endpoints (/optimize, /triggers, /judge) | 5 requests/minute | | Other endpoints | 60 requests/minute | The API also fetches repository data through the GitHub REST API v3. GitHub's own rate limits apply on the server side: | Server Config | GitHub Rate Limit | | --------------- | ------------------- | | No GitHub token | 60 requests/hour | | With token | 5,000 requests/hour | #### Caching Evaluation results are cached on the server, keyed by `owner/repo/commit_sha` (and `path` for single-skill requests). - If the repository's HEAD has not changed, the cached result is returned instantly - Cache TTL is 1 hour — after expiry, the next request triggers a fresh evaluation - Full-repo and single-skill results are cached independently ## API ### Evaluate **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 | Parameter | Type | Description | | --------- | ------ | ------------------------------- | | owner | string | GitHub username or organization | | repo | string | Repository name | #### Query Parameters | Parameter | Type | Description | | --------- | ------ | ---------------------------------------------------------------------------- | | path | string | Optional. 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](#scanresult) object with a `skills` array containing one [SkillResult](#skillresult) per SKILL.md found (up to 50). - **With `path`** — returns a [SkillEvaluateResult](#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 \\See also the `ScanResult` field reference below. | Field | Type | Description | | ----------- | -------------------------------- | ---------------------------------------------------------------------------- | | owner | string | GitHub username or organization | | repo | string | Repository name | | commit\_sha | string | Full SHA of the commit that was scanned | | skills | \[SkillResult\[]]\(#skillresult) | Array of evaluated skills found in the repository | | scanned\_at | string | ISO 8601 timestamp of when the scan was performed | | error | string \| null | Top-level error message if the scan itself failed, otherwise null | | truncated | boolean | True if the repository contained more than 50 skills and results were capped | **Example:** ```json { "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 \\See also the `SkillEvaluateResult` field reference below. | Field | Type | Description | | -------------- | -------------------------------- | ------------------------------------------------------------- | | owner | string | GitHub username or organization | | repo | string | Repository name | | commit\_sha | string | Full SHA of the commit that was evaluated | | scanned\_at | string | ISO 8601 timestamp of when the evaluation was performed | | path | string | Path to the SKILL.md file within the repository | | name | string \| null | Skill name extracted from frontmatter | | description | string \| null | Skill description extracted from frontmatter | | quality\_score | number | Overall quality score from 0 to 100 | | overall\_pass | boolean | Whether all high-severity checks passed | | checks\_run | number | Total number of checks executed | | checks\_passed | number | Number of checks that passed | | checks\_failed | number | Number of checks that failed | | results | \[CheckResult\[]]\(#checkresult) | Detailed results for each individual check | | summary | object | Aggregated pass/fail counts grouped by severity and dimension | | error | string \| null | Error message if the skill failed to evaluate, otherwise null | **Example:** ```json { "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 \\See also the `SkillResult` field reference below. | Field | Type | Description | | -------------- | -------------------------------- | -------------------------------------------------------------- | | path | string | Path to the SKILL.md file within the repository | | name | string \| null | Skill name extracted from frontmatter | | description | string \| null | Skill description extracted from frontmatter | | quality\_score | number | Overall quality score from 0 to 100 | | overall\_pass | boolean | Whether all high-severity checks passed | | checks\_run | number | Total number of checks executed | | checks\_passed | number | Number of checks that passed | | checks\_failed | number | Number of checks that failed | | results | \[CheckResult\[]]\(#checkresult) | Detailed results for each individual check | | summary | object | Aggregated pass/fail counts grouped by severity and dimension | | error | string \| null | Error message if this skill failed to evaluate, otherwise null | **Example:** ```json { "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 \\See also the `CheckResult` field reference below. | Field | Type | Description | | ----------- | --------------------------- | --------------------------------------------------------------------------------- | | check\_id | string | Unique identifier for the check | | check\_name | string | Human-readable check name | | passed | boolean | Whether this check passed | | severity | "high" \| "medium" \| "low" | Severity level of the check | | dimension | string | Quality dimension: "structure", "naming", "description", "content", or "security" | | message | string | Human-readable result message | | fix | string? | Suggested fix when the check fails | | details | object? | Additional check-specific data | | location | string? | File location relevant to the check | **Example:** ```json { "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 | Status | Cause | | ------ | ---------------------------------- | | 404 | Repository or skill path not found | | 429 | GitHub 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" ``` ### Check Registry **GET** `/v1/checks` Returns the full catalog of static checks that skill-lab runs during evaluation. Each check includes its dimension, severity, and whether it is required by the Agent Skills spec. #### Response Returns an object with a `checks` array and a `count` integer. Each check has: `check_id`, `check_name`, `dimension`, `severity`, `spec_required`, `description`, and `fix`. #### Example ```bash curl https://api.skill-lab.dev/v1/checks ``` ### Skill Info **GET** `/v1/repos/{owner}/{repo}/info` Returns parsed metadata and token estimates without running the full evaluation. Omit `path` to get info for every SKILL.md in the repo. Provide `path` to get info for a single skill. Lighter weight than evaluate — useful for discovery and cataloging. #### Path Parameters | Parameter | Type | Description | | --------- | ------ | ------------------------------- | | owner | string | GitHub username or organization | | repo | string | Repository name | #### Query Parameters | Parameter | Type | Description | | --------- | ------ | ---------------------------------------------------------------------------- | | path | string | Optional. Path to a specific skill — omit to evaluate all skills in the repo | #### Response The response shape depends on whether `path` is provided. - **Without `path`** — returns an object with `owner`, `repo`, `commit_sha`, a `skills` array of info objects (up to 50), and `truncated`. - **With `path`** — returns a single info object with `name`, `description`, `raw_frontmatter`, `body_preview` (first 500 chars), `has_scripts`, `has_references`, `has_assets`, `estimated_tokens`, and `parse_errors`. example response: ```json { "owner": "anthropics", "repo": "claude-code", "path": "skills/git-commit/SKILL.md", "name": "git-commit", "description": "Write conventional commit messages", "raw_frontmatter": { "name": "git-commit", ... }, "body_preview": "# Git Commit\nGenerate conventional ...", "has_scripts": false, "has_references": true, "has_assets": false, "estimated_tokens": 1240, "parse_errors": [] } ``` #### Errors | Status | Cause | | ------ | ---------------------------------- | | 404 | Repository or skill path not found | | 429 | GitHub API rate limit reached | #### Examples Single skill: ```bash curl "https://api.skill-lab.dev/v1/repos/owner/repo/info?path=my-skill" ``` ```javascript const res = await fetch("https://api.skill-lab.dev/v1/repos/owner/repo/info?path=my-skill"); const data = await res.json(); // data.estimated_tokens ``` ```python import httpx res = httpx.get("https://api.skill-lab.dev/v1/repos/owner/repo/info?path=my-skill") data = res.json() # data['estimated_tokens'] ``` Whole repo: ```bash curl "https://api.skill-lab.dev/v1/repos/anthropics/claude-code/info" ``` ### Export **GET** `/v1/repos/{owner}/{repo}/export` Renders all skills in a repository as agent-platform-ready prompt snippets in XML, Markdown, or JSON format. #### Path Parameters | Parameter | Type | Description | | --------- | ------ | ------------------------------- | | owner | string | GitHub username or organization | | repo | string | Repository name | #### Query Parameters | Parameter | Type | Description | | --------- | ----------------------------- | ------------------------------ | | format | "xml" \| "markdown" \| "json" | Output format (default: `xml`) | #### Response Returns an object with `owner`, `repo`, `format`, `skill_count`, and `content` (the rendered string). example response: ```json { "owner": "anthropics", "repo": "claude-code", "format": "xml", "skill_count": 3, "content": "\n ...\n" } ``` #### Errors | Status | Cause | | ------ | ---------------------------------- | | 404 | Repository or skill path not found | | 429 | GitHub API rate limit reached | #### Example ```bash curl "https://api.skill-lab.dev/v1/repos/owner/repo/export?format=xml" ``` ```javascript const res = await fetch("https://api.skill-lab.dev/v1/repos/owner/repo/export?format=xml"); const data = await res.json(); // data.content ``` ```python import httpx res = httpx.get("https://api.skill-lab.dev/v1/repos/owner/repo/export?format=xml") data = res.json() # data['content'] ``` ### Optimize **POST** `/v1/repos/{owner}/{repo}/optimize` Runs LLM-powered optimization on a SKILL.md file. Returns the original and optimized content with before/after quality scores. Rate limited to 5 requests per minute. #### Path Parameters | Parameter | Type | Description | | --------- | ------ | ------------------------------- | | owner | string | GitHub username or organization | | repo | string | Repository name | #### Query Parameters | Parameter | Type | Description | | --------- | ------ | -------------------------------------------- | | path | string | Path to the skill directory or SKILL.md file | #### Request Body Optional JSON body: | Field | Type | Description | | ----- | ------- | ----------------------------------------------- | | model | string? | LLM model override (default: server-configured) | #### Response Returns `original_content`, `optimized_content`, `original_score`, `optimized_score`, `original_failures`, `optimized_failures`, and `usage` (token counts). example response: ```json { "owner": "owner", "repo": "repo", "path": "skills/my-skill/SKILL.md", "original_content": "---\nname: my-skill\n---\n...", "optimized_content": "---\nname: my-skill\n---\n...", "original_score": 72.5, "optimized_score": 95.0, "original_failures": 5, "optimized_failures": 1, "usage": { "model": "claude-haiku-4-5-20251001", "input_tokens": 2100, "output_tokens": 1800 } } ``` > This endpoint calls an LLM and may take 10-30 seconds to respond. > Results are cached per commit SHA and model — repeated requests for the same > skill on the same commit return the cached response. #### Errors | Status | Cause | | ------ | ---------------------------------------- | | 404 | Repository or skill path not found | | 422 | LLM generation failed | | 429 | Rate limit exceeded | | 503 | Service not configured (missing API key) | | 504 | Operation timed out | #### Example ```bash curl -X POST "https://api.skill-lab.dev/v1/repos/owner/repo/optimize?path=my-skill" ``` ```javascript const res = await fetch("https://api.skill-lab.dev/v1/repos/owner/repo/optimize?path=my-skill", { method: "POST" }); const data = await res.json(); // data.optimized_score ``` ```python import httpx res = httpx.post("https://api.skill-lab.dev/v1/repos/owner/repo/optimize?path=my-skill") data = res.json() # data['optimized_score'] ``` ### Triggers **POST** `/v1/repos/{owner}/{repo}/triggers` Generates trigger test YAML for a SKILL.md file using an LLM. The generated tests cover explicit, implicit, contextual, and negative trigger types. Rate limited to 5 requests per minute. #### Path Parameters | Parameter | Type | Description | | --------- | ------ | ------------------------------- | | owner | string | GitHub username or organization | | repo | string | Repository name | #### Query Parameters | Parameter | Type | Description | | --------- | ------ | -------------------------------------------- | | path | string | Path to the skill directory or SKILL.md file | #### Request Body Optional JSON body: | Field | Type | Description | | ----- | ------- | ----------------------------------------------- | | model | string? | LLM model override (default: server-configured) | #### Response Returns `skill_name`, `triggers_yaml` (the generated YAML string), `test_count`, and `usage` (token counts). example response: ```json { "owner": "owner", "repo": "repo", "path": "skills/my-skill/SKILL.md", "skill_name": "my-skill", "triggers_yaml": "triggers:\n - type: explicit\n prompt: ...", "test_count": 12, "usage": { "model": "claude-haiku-4-5-20251001", "input_tokens": 3200, "output_tokens": 900 } } ``` > This endpoint calls an LLM and may take 10-30 seconds to respond. > Results are cached per commit SHA and model — repeated requests for the same > skill on the same commit return the cached response. #### Errors | Status | Cause | | ------ | ---------------------------------------- | | 404 | Repository or skill path not found | | 422 | LLM generation failed | | 429 | Rate limit exceeded | | 503 | Service not configured (missing API key) | | 504 | Operation timed out | #### Example ```bash curl -X POST "https://api.skill-lab.dev/v1/repos/owner/repo/triggers?path=my-skill" ``` ```javascript const res = await fetch("https://api.skill-lab.dev/v1/repos/owner/repo/triggers?path=my-skill", { method: "POST" }); const data = await res.json(); // data.triggers_yaml ``` ```python import httpx res = httpx.post("https://api.skill-lab.dev/v1/repos/owner/repo/triggers?path=my-skill") data = res.json() # data['triggers_yaml'] ``` ### Judge **POST** `/v1/repos/{owner}/{repo}/judge` Runs an LLM-as-judge quality review on a SKILL.md file. Scores the skill across 9 criteria on two axes: Activation Quality and Instruction Quality. Returns per-criterion scores (0-4), axis scores, an overall judge score (0-100), a verdict band, and improvement suggestions. Rate limited to 5 requests per minute. #### Path Parameters | Parameter | Type | Description | | --------- | ------ | ------------------------------- | | owner | string | GitHub username or organization | | repo | string | Repository name | #### Query Parameters | Parameter | Type | Description | | --------- | ------ | -------------------------------------------- | | path | string | Path to the skill directory or SKILL.md file | #### Request Body Optional JSON body: | Field | Type | Description | | ----- | ------- | ---------------------------------------------------------- | | model | string? | LLM model override — supports claude-\*, gpt-\*, gemini-\* | #### Response Returns `criteria` (array of 9 objects with `id`, `name`, `axis`, `score`, `reasoning`), `activation_score`, `instruction_score`, `judge_score` (0-100), `verdict` (Poor/Fair/Good/Very Good/Excellent), `suggestions`, and `usage`. example response: ```json { "owner": "owner", "repo": "repo", "path": "skills/my-skill/SKILL.md", "criteria": [ { "id": "trigger_clarity", "name": "Trigger Clarity", "axis": "activation", "score": 3, "reasoning": "..." } ], "activation_score": 75.0, "instruction_score": 80.0, "judge_score": 77.8, "verdict": "Good", "suggestions": ["Add explicit trigger examples", "..."], "usage": { "model": "claude-haiku-4-5-20251001", "input_tokens": 2900, "output_tokens": 1100 } } ``` > This endpoint calls an LLM and may take 10-30 seconds to respond. > Multi-provider: pass a `claude-*`, `gpt-*`, or `gemini-*` model ID > to use different providers. #### Errors | Status | Cause | | ------ | ---------------------------------------- | | 404 | Repository or skill path not found | | 422 | LLM generation failed | | 429 | Rate limit exceeded | | 503 | Service not configured (missing API key) | | 504 | Operation timed out | #### Example ```bash curl -X POST "https://api.skill-lab.dev/v1/repos/owner/repo/judge?path=my-skill" ``` ```javascript const res = await fetch("https://api.skill-lab.dev/v1/repos/owner/repo/judge?path=my-skill", { method: "POST" }); const data = await res.json(); // data.judge_score ``` ```python import httpx res = httpx.post("https://api.skill-lab.dev/v1/repos/owner/repo/judge?path=my-skill") data = res.json() # data['judge_score'] ``` ### Health **GET** `/health` Returns server status. Use this to verify the API is running and reachable. #### Response 200 OK: ```json { "status": "ok" } ``` #### Example ```bash curl https://api.skill-lab.dev/health ``` ## CLI ### Installation `sklab` is the CLI that ships with the [skill-lab](https://pypi.org/project/skill-lab/) PyPI package. It runs the same static checks and LLM judge as the hosted API — but locally, against a skill directory on your machine. Python 3.10 or newer is required. #### Install ```bash $ pip install skill-lab ``` Or with uv: ```bash $ uv pip install skill-lab ``` #### Verify ```bash $ sklab --version ``` Running `sklab` on its own scans the current directory for SKILL.md files and prints a getting-started guide. #### API Keys Static commands (`check`, `scan`, `info`, `list-checks`) run without any credentials. LLM-powered commands — `evaluate` (judge step), `generate`, `trigger`, and `optimize` — need an API key: | Provider | Env var | Model prefix | | --------- | ------------------- | ------------ | | Anthropic | `ANTHROPIC_API_KEY` | `claude-*` | | OpenAI | `OPENAI_API_KEY` | `gpt-*` | | Google | `GEMINI_API_KEY` | `gemini-*` | Provider is auto-detected from the model prefix passed to `--model`. Keys are read from the environment, a `.env` file in the current directory, or any standard shell-profile setup. The default model is `claude-haiku-4-5-20251001` (Anthropic). #### Trigger Testing Prerequisite `sklab trigger` drives a live LLM runtime through the Claude CLI: ```bash $ npm install -g @anthropic-ai/claude-code ``` ### Quickstart From a fresh install to a scored skill in three commands. ##### 1. Install and scan ```bash $ pip install skill-lab $ cd path/to/your-skills $ sklab ``` Running `sklab` on its own discovers every SKILL.md under the current directory and prints the getting-started guide. ##### 2. Evaluate a skill ```bash $ export ANTHROPIC_API_KEY=sk-ant-... $ sklab evaluate ./my-skill ``` Runs 37 static checks plus a 9-criteria LLM judge. Pass `--skip-review` to skip the LLM step if you do not have a key. ##### 3. Gate CI ```yaml # .github/workflows/skills.yml - run: pip install skill-lab - run: sklab check --repo ``` `sklab check` exits 1 on any high-severity failure, so it drops straight into a pre-merge job. #### Next steps ### sklab evaluate Static checks plus LLM quality review with 0–100 scoring. > **Also available over HTTP.** The [Evaluate Skills endpoint](/docs/endpoints/evaluate) runs the same logic on the server against a GitHub repository — useful when you want results in a browser, a CI job without installing Python, or an agent that reaches skill-lab.dev directly. ```bash sklab evaluate [SKILL_PATH] [OPTIONS] ``` Runs 37 static checks across Structure, Naming, Description, Content, and Security, then sends the skill to an LLM judge that scores it on 9 criteria across Activation and Instruction axes. Use --skip-review for a static-only run, or --format json to emit the same payload shape as the /v1/evaluate endpoint. #### Arguments | Argument | Required | Description | | ----------- | -------- | --------------------------------------------------------------- | | SKILL\_PATH | no | Path to the skill directory. Defaults to the current directory. | #### Options | Flag | Value | Description | | --------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | --output, -o | \ | Write the report to a file (implies --format json if --format is not set). | | --format, -f | json\|console (default: `console`) | Output format. | | --verbose, -V | flag | Show all checks (including passing ones) and LLM reasoning. | | --spec-only, -s | flag | Run only the checks required by the Agent Skills spec. | | --all, -a | flag | Discover and evaluate every skill under the current directory. | | --repo | flag | Discover and evaluate every skill from the git repo root. | | --skip-review | flag | Skip the LLM judge (static checks only). | | --model, -m | \ (default: `claude-haiku-4-5-20251001`) | Model for the LLM judge. Supports Anthropic, OpenAI (gpt-\*), and Gemini (gemini-\*) models — provider auto-detected from the prefix. | | --optimize | flag | Automatically chain into sklab optimize after evaluation (no interactive prompt). | #### Examples Evaluate one skill ```bash sklab evaluate ./my-skill ``` JSON report to disk ```bash sklab evaluate ./my-skill -f json -o report.json ``` Static checks only (no API key) ```bash sklab evaluate ./my-skill --skip-review ``` Every skill in the current repo ```bash sklab evaluate --repo ``` Evaluate then optimize in one step ```bash sklab evaluate ./my-skill --optimize ``` #### Output Console rendering groups checks by dimension with pass/fail status and the LLM judge's per-criterion scores. With --format json, the output matches the /v1/repos/{owner}/{repo}/evaluate response payload. #### Exit Codes | Code | Meaning | | ---- | --------------------------------------------------- | | 0 | All high-severity checks passed. | | 1 | One or more checks failed, or a CLI error occurred. | #### Notes - LLM review requires ANTHROPIC\_API\_KEY, OPENAI\_API\_KEY, or GEMINI\_API\_KEY. The env var is selected from the model prefix. - \--all and --repo are mutually exclusive, and cannot be combined with a positional SKILL\_PATH. ### sklab check Quick pass/fail check — exits 0 or 1, designed for CI pipelines. ```bash sklab check [SKILL_PATH] [OPTIONS] ``` Runs the same static checks as evaluate, skips the LLM step, and prints only high-severity failures. The non-zero exit code on failure makes it a drop-in gate for pre-commit hooks and CI jobs. #### Arguments | Argument | Required | Description | | ----------- | -------- | --------------------------------------------------------------- | | SKILL\_PATH | no | Path to the skill directory. Defaults to the current directory. | #### Options | Flag | Value | Description | | --------------- | ----- | ----------------------------------------------------------------------- | | --spec-only, -s | flag | Validate only against the Agent Skills spec (skip quality suggestions). | | --all, -a | flag | Check every skill under the current directory. | | --repo | flag | Check every skill from the git repo root. | #### Examples CI gate ```bash sklab check ./my-skill ``` Pre-commit (all skills) ```bash sklab check --all ``` Spec-only in CI ```bash sklab check --repo --spec-only ``` #### Exit Codes | Code | Meaning | | ---- | --------------------------------------------------- | | 0 | All checks passed. | | 1 | One or more checks failed, or a CLI error occurred. | ### sklab scan Security-focused scan with BLOCK / SUS / ALLOW status per skill. ```bash sklab scan [SKILL_PATH] [OPTIONS] ``` Runs the 5 security checks — prompt injection, evaluator manipulation, unicode obfuscation, YAML anomalies, and suspicious size/structure — and classifies each skill as BLOCK, SUS, or ALLOW. BLOCK triggers a non-zero exit so you can wire it into pre-merge checks. #### Arguments | Argument | Required | Description | | ----------- | -------- | --------------------------------------------------------------- | | SKILL\_PATH | no | Path to the skill directory. Defaults to the current directory. | #### Options | Flag | Value | Description | | ------------- | ----- | ------------------------------------------------------------------- | | --all, -a | flag | Scan every skill under the current directory. | | --verbose, -v | flag | Show findings for SUS skills in addition to BLOCK (bulk mode only). | #### Examples Scan one skill ```bash sklab scan ./my-skill ``` Audit every skill ```bash sklab scan --all ``` #### Output Per-skill status: BLOCK on injection / jailbreak / unicode / YAML / evaluator findings; SUS on size or structure anomalies only; ALLOW if no findings. #### Exit Codes | Code | Meaning | | ---- | ------------------------------------ | | 0 | ALLOW or SUS only. | | 1 | One or more skills classified BLOCK. | ### sklab info Skill metadata and token cost estimates (discovery / activation / on-demand). > **Also available over HTTP.** The [Skill Info endpoint](/docs/endpoints/skill-info) runs the same logic on the server against a GitHub repository — useful when you want results in a browser, a CI job without installing Python, or an agent that reaches skill-lab.dev directly. ```bash sklab info [SKILL_PATH] [OPTIONS] ``` Shows the parsed frontmatter fields and three token-cost estimates: discovery (name + description — the cost to keep the skill loaded), activation (full SKILL.md body), and on-demand (references / assets / scripts). Useful for catalog pages and budget planning — no LLM call, no API key required. #### Arguments | Argument | Required | Description | | ----------- | -------- | --------------------------------------------------------------- | | SKILL\_PATH | no | Path to the skill directory. Defaults to the current directory. | #### Options | Flag | Value | Description | | ----------- | ------- | --------------------------------------------------------------- | | --json | flag | Emit structured JSON (pipe-friendly). | | --field, -f | \ | Extract a single field by dotted path (e.g. tokens.activation). | #### Examples Human-readable ```bash sklab info ./my-skill ``` Pipe to jq ```bash sklab info ./my-skill --json | jq .tokens ``` Single field ```bash sklab info ./my-skill -f tokens.activation ``` ### sklab prompt Export one or more skills as a prompt snippet for agent platforms. > **Also available over HTTP.** The [Export Skills endpoint](/docs/endpoints/export) runs the same logic on the server against a GitHub repository — useful when you want results in a browser, a CI job without installing Python, or an agent that reaches skill-lab.dev directly. ```bash sklab prompt [SKILL_PATHS...] [OPTIONS] ``` Renders the named skills as XML, Markdown, or JSON suitable for pasting into an agent platform's system prompt. Accepts multiple paths — pass several skills to render them as a single combined prompt. #### Arguments | Argument | Required | Description | | ------------ | -------- | ----------------------------------------------------------------- | | SKILL\_PATHS | no | One or more skill directories. Defaults to the current directory. | #### Options | Flag | Value | Description | | ------------ | ------------------------------------ | -------------- | | --format, -f | xml\|markdown\|json (default: `xml`) | Output format. | #### Examples Single skill as XML ```bash sklab prompt ./skill-a ``` Multiple skills ```bash sklab prompt ./skill-a ./skill-b ``` JSON to a file ```bash sklab prompt ./skill-a -f json > skills.json ``` ### sklab generate Auto-generate \~13 trigger test cases for a skill via LLM. > **Also available over HTTP.** The [Generate Triggers endpoint](/docs/endpoints/triggers) runs the same logic on the server against a GitHub repository — useful when you want results in a browser, a CI job without installing Python, or an agent that reaches skill-lab.dev directly. ```bash sklab generate [SKILL_PATH] [OPTIONS] ``` Reads the SKILL.md description and produces .sklab/tests/triggers.yaml with \~13 test cases across all 4 trigger types: explicit, implicit, contextual, and negative. Run \`sklab trigger\` afterwards to execute the tests against a live runtime. #### Arguments | Argument | Required | Description | | ----------- | -------- | --------------------------------------------------------------- | | SKILL\_PATH | no | Path to the skill directory. Defaults to the current directory. | #### Options | Flag | Value | Description | | ----------- | --------------------------------------------------- | ----------------------------------------------------------------------------- | | --model, -m | \ (default: `claude-haiku-4-5-20251001`) | Model ID. Supports Anthropic, OpenAI (gpt-\*), and Gemini (gemini-\*) models. | | --force | flag | Overwrite an existing triggers.yaml file. | #### Examples Generate with default model ```bash sklab generate ./my-skill ``` Use a different model ```bash sklab generate ./my-skill -m claude-sonnet-4-6 ``` Overwrite existing tests ```bash sklab generate ./my-skill --force ``` #### Notes - Requires an API key for the selected provider (ANTHROPIC\_API\_KEY, OPENAI\_API\_KEY, or GEMINI\_API\_KEY). - The skill path is a positional argument — it comes before the --model flag. ### sklab trigger Run trigger tests against a live LLM runtime. ```bash sklab trigger [SKILL_PATH] [OPTIONS] ``` Executes the tests in .sklab/tests/triggers.yaml and reports which prompts correctly activated (or correctly failed to activate) the skill. Use --type to filter by a single trigger category while debugging. #### Arguments | Argument | Required | Description | | ----------- | -------- | --------------------------------------------------------------- | | SKILL\_PATH | no | Path to the skill directory. Defaults to the current directory. | #### Options | Flag | Value | Description | | ------------ | ---------------------------------- | --------------------------------------------------------------------------------- | | --provider | local\|docker (default: `local`) | Execution provider: local (temp-dir isolation) or docker (container isolation). | | --type, -t | \ | Only run tests of this trigger type: explicit, implicit, contextual, or negative. | | --output, -o | \ | Write the JSON report to a file. | | --format, -f | json\|console (default: `console`) | Output format. | #### Examples Run all tests ```bash sklab trigger ./my-skill ``` Debug false positives ```bash sklab trigger ./my-skill -t negative ``` Container isolation ```bash sklab trigger ./my-skill --provider docker ``` #### Notes - Requires the Claude CLI: npm install -g @anthropic-ai/claude-code. - Run \`sklab generate\` first if .sklab/tests/triggers.yaml does not yet exist. ### sklab stats Personal usage history and score trends across the skills you have evaluated. ```bash sklab stats [count|score|tokens] [--here] ``` With no subcommand, prints a usage overview from \~/.sklab/usage.db. Pass a subcommand to drill into one metric. Invocation data is populated by the PostToolUse hook — run \`sklab setup\` once to install it. #### Subcommands | Subcommand | Description | | ---------- | ---------------------------------------------- | | count | Skill invocation counts for the current month. | | score | Score trend across all evaluated skills. | | tokens | Token usage per skill for the current month. | #### Options | Flag | Value | Description | | ------ | ----- | ---------------------------------------------------- | | --here | flag | Limit results to skills inside the current git repo. | #### Examples Overview ```bash sklab stats ``` Per-month invocations ```bash sklab stats count ``` Scope to this repo ```bash sklab stats tokens --here ``` #### Notes - If you see 'No usage data found', run \`sklab setup\` first — the PostToolUse hook is what populates the stats database. ### sklab list-checks Browse all 37 checks across 5 dimensions. > **Also available over HTTP.** The [Check Registry endpoint](/docs/endpoints/check-registry) runs the same logic on the server against a GitHub repository — useful when you want results in a browser, a CI job without installing Python, or an agent that reaches skill-lab.dev directly. ```bash sklab list-checks [OPTIONS] ``` Prints a table of every check with its ID, dimension, severity, and whether the Agent Skills spec requires it. Use it as a reference when reading evaluate output. #### Options | Flag | Value | Description | | ------------------ | ------ | -------------------------------------------------------------------------- | | --dimension, -d | \ | Filter by dimension: structure, naming, description, content, or security. | | --spec-only, -s | flag | Only spec-required checks. | | --suggestions-only | flag | Only quality-suggestion checks (non-spec). | #### Examples All checks ```bash sklab list-checks ``` Security only ```bash sklab list-checks -d security ``` Spec-required only ```bash sklab list-checks --spec-only ``` ### sklab optimize LLM-powered SKILL.md rewrite with diff preview and score delta. > **Also available over HTTP.** The [Optimize Skill endpoint](/docs/endpoints/optimize) runs the same logic on the server against a GitHub repository — useful when you want results in a browser, a CI job without installing Python, or an agent that reaches skill-lab.dev directly. ```bash sklab optimize [SKILL_PATH] [OPTIONS] ``` Reads the latest evaluation from .sklab/evals/ (so run \`sklab evaluate\` first), feeds the static failures and judge feedback to an LLM, and proposes an improved SKILL.md. Shows a unified diff and a before/after score before applying. Pass --auto to skip the confirmation prompt. #### Arguments | Argument | Required | Description | | ----------- | -------- | --------------------------------------------------------------- | | SKILL\_PATH | no | Path to the skill directory. Defaults to the current directory. | #### Options | Flag | Value | Description | | ----------- | --------------------------------------------------- | ----------------------------------------------------------------------------- | | --model, -m | \ (default: `claude-haiku-4-5-20251001`) | Model ID. Supports Anthropic, OpenAI (gpt-\*), and Gemini (gemini-\*) models. | | --auto | flag | Apply the rewrite without the confirmation prompt. | #### Examples Review diff interactively ```bash sklab optimize ./my-skill ``` Apply without prompt ```bash sklab optimize ./my-skill --auto ``` Use a stronger model ```bash sklab optimize ./my-skill -m claude-sonnet-4-6 ``` #### Notes - Requires a prior \`sklab evaluate\` run — optimize reads from .sklab/evals/. - Requires ANTHROPIC\_API\_KEY, OPENAI\_API\_KEY, or GEMINI\_API\_KEY for the selected provider. ### sklab setup Install the PostToolUse hook that powers sklab stats. ```bash sklab setup ``` Writes PostToolUse hooks into \~/.claude/settings.json (Claude Code) and \~/.cursor/hooks.json (Cursor) so sklab records a row in \~/.sklab/usage.db every time a skill fires. Safe to re-run — the command is idempotent. #### Examples One-time install ```bash sklab setup ``` #### Notes - Without this hook, \`sklab stats\` has no data to show. - The hook only records skill names, token counts, and timestamps — no prompt or file contents.