Base URL: https://skillsmith.ch (mirrored at https://skillsmith-web.vercel.app). All responses are JSON. No SDK needed -- plain HTTP.
| Tier | Scans/day | DB lookups/day | Price |
|---|---|---|---|
| Free | 5 | 5 | $0 |
| Pay-as-you-go (additive) | +1 per purchase | +1 per purchase | $0.02 / scan, $0.01 / lookup |
| Pro | 100 | 150 | $5 USDC / 30 days |
| Premium | Unlimited | Unlimited | $10 USDC / 30 days |
All paid tiers are activated by sending USDC (SPL token, Solana mainnet,
mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v) to
2esJogvKTYDuxZaB9PEuEaHvz4U6TuQnTx3pkLcdH34N, then submitting
the finalized transaction signature. Pay-as-you-go always requires an
existing account (api_key) and is additive to whatever tier
you're on -- it never replaces the free daily quota, it tops it up. No
card, no subscription billing surprises -- Pro/Premium simply expire
after 30 days.
"Database" here means the Safe Skills Database --
looking up a hash's verdict (/api/lookup), browsing clean
skills (/api/registry), or fetching a published skill's
actual, usable content (/api/skill). All three share the
same daily lookup quota.
Every scan/lookup call needs an api_key, either as a JSON
body field, a query param (GET requests), or an
Authorization: Bearer <key> header. Get one from
POST /api/signup or by signing in with GitHub
(/api/auth/github/start), which recovers the same key/quota
on any device you sign in from again.
skillsmith runs an MCP
server at https://skillsmith.ch/mcp (JSON-RPC 2.0 over HTTP)
so Claude Code, Cursor, Codex, or any MCP-compatible agent can scan and
reuse skills directly, without shelling out to curl. Same detection
engine, same accounts/quota as the REST API and the web UI -- one
account works everywhere.
{
"mcpServers": {
"skillsmith": {
"type": "http",
"url": "https://skillsmith.ch/mcp"
}
}
}
Claude Code: add the above to .mcp.json, run /mcp,
select "skillsmith". Cursor/Codex/other MCP hosts: paste the same JSON
into their MCP config panel.
Every tool call needs an api_key argument. Call the
skillsmith_signup tool once (free, no email) and reuse the
key for every other call -- or ask your agent to "sign up for skillsmith
and remember the key."
| Tool | Arguments | Does |
|---|---|---|
skillsmith_signup | (none) | Create an account, get an api_key |
scan_skill | api_key, text or url, publish? | Lint + security-scan a SKILL.md |
lookup_hash | api_key, sha256 | Check if a hash was scanned before |
get_skill_content | api_key, sha256 | Fetch a published skill's actual text |
list_safe_skills | api_key, limit? | Browse the Safe Skills Database |
file_report | api_key, sha256, verdict (malicious | false_positive | note), comment? | File a community verdict report (20/day/key, shown publicly) |
find_similar | api_key, sha256 | Skill-DNA near-duplicate search (≤12 Hamming distance, unpublished names masked) |
watch_skill | api_key, url (create) | watch_id (check) | Rug-pull watch: baseline a GitHub-hosted SKILL.md and re-check whether it changed after you vetted it (10 watches/day/key) |
whoami | api_key | Check tier/quota usage |
analyze_behavior | api_key, text | Behavioral sandbox: an AI analyst simulates what an agent following the skill would do (capabilities, action trace, IOCs, 0-10 severity). Slow (~30-120s); 5/day/account. |
Raw JSON-RPC example (what your MCP host does under the hood):
curl -X POST https://skillsmith.ch/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"skillsmith_signup","arguments":{}}}'
/healthLiveness probe. Returns {"status": "ok", ...} with HTTP 200; no auth, no quota.
/badge?sha256=...&style=flatSVG trust badge for a scanned hash (unlimited, no auth, cached 60s). Optional style: flat (default), flat-square, round. Colors follow the verdict: green (clean), amber (low), orange (medium), red (high). Usage: <img src="https://skillsmith.ch/badge?sha256=..."> in your README.
/feed.xmlAtom feed of recently verified-clean agent skills (automated heuristic verdicts, clean-gated). No auth; CDN-cached 5 minutes + 60s server-side micro-cache. Subscribe to stay current on new registry entries.
/api/public_scan?sha256=...Key-less verdict lookup for one hash — enough for badge landing pages: {sha256, name, risk_level, risk_score, lint_ok, parse_ok, seen_count, first_seen_at, last_seen_at, has_content}. Rate limited (200/day/IP, soft). No findings, no content.
/api/certificate?sha256=...&api_key=...Issue an HMAC-signed verdict certificate for a scanned hash (valid 90 days). Response: {"certificate": {sha256, risk_level, security_score, issued_at, signature}}. Requires sign-in.
/api/certificateVerify a certificate. Body: {"certificate": {...}} — no auth needed to verify. Returns {valid, matches_current_verdict, current_risk_level}: valid means signed by skillsmith within its 90-day window; matches_current_verdict tells you whether the hash still carries that verdict today.
/api/report?sha256=.../api/report?sha256=...Public community verdicts for a hash: {"total": n, "tally": {"malicious": x, "false_positive": y, "note": z}, "reports": [...]}.
/api/reportFile a community verdict. Body: {api_key, sha256, verdict, comment?} where verdict is false_positive | malicious | note. Requires a valid api_key; 20 reports/day/key.
/api/similar?sha256=...&api_key=...Skill-DNA neighbours: near-duplicate variants of the skill (64-bit simhash, hamming distance ≤ 12). Requires sign-in; free.
/api/hook-scanRun the normal scan pipeline and get back a ready-to-post Discord or Slack webhook payload. Body: {api_key, url | text, format?} — url must be a github.com/raw.githubusercontent.com link; format is "discord" (default) or "slack". Consumes one scan from your quota. Response: a Discord embed object or Slack attachment object (plus a disclaimer field).
/api/watchWatch a GitHub-hosted SKILL.md for rug-pulls. Body: {api_key, url, webhook_url?} where url is a github.com blob or raw.githubusercontent.com URL (only those hosts are fetched — no SSRF). Optional webhook_url: a Discord (https://discord.com/api/webhooks/...) or Slack (https://hooks.slack.com/services/...) webhook that automatically receives a rug-pull alert when the content changes (provider-allowlisted, best-effort). Stores the content hash as baseline. 10 watches/day/key. Response: {watch_id, baseline_sha256}.
/api/watch?watch_id=...&api_key=...On-demand rug-pull check: re-fetches the watched URL and compares the hash. Status is unchanged, changed (= the skill was modified after you vetted it) or unreachable. Response includes baseline/current sha256, check count and timestamps.
/api/watch?watch_id=...&api_key=...Remove a watch you own (hard delete incl. all stored versions; foreign/unknown ids return 404 without oracle). Shares the 200/day watch-operation cap.
List your watches: GET /api/watch?list=1&api_key=... returns all watches owned by your key ({count, watches:[{watch_id,url,last_status,checks,created_at,changed_at}]}, max 100; 20 lists/day/key).
/api/statsAggregate global counters: {"total_scans": n, "by_risk": {...}}. Public, cached 60s.
/api/signupCreate an anonymous account. No email/password.
curl -X POST https://skillsmith.ch/api/signup
{"api_key": "sk_...", "free_daily_limit": 5, "pro_daily_limit": 100, "pro_price_usdc": 5.0, "pro_duration_days": 30}
/api/signup?api_key=...Check your account's current tier and quota usage.
curl "https://skillsmith.ch/api/signup?api_key=sk_..."
{"tier": "free", "limit": 5, "used": 2, "remaining": 3, "pro_price_usdc": 5.0, "pro_duration_days": 30}
/api/auth/github/startRedirects to GitHub OAuth. On success, redirects back to
/#key=sk_... with your (possibly pre-existing) account key.
/api/scanLint + security-scan one SKILL.md. Consumes 1 unit of your scan quota.
curl -X POST https://skillsmith.ch/api/scan \
-H "Content-Type: application/json" \
-d '{"api_key":"sk_...","text":"---\nname: x\ndescription: y\n---\n\nbody"}'
# or scan a GitHub link instead of pasting text:
curl -X POST https://skillsmith.ch/api/scan \
-d '{"api_key":"sk_...","url":"https://github.com/owner/repo/blob/main/SKILL.md"}'
Response includes parse_ok, lint_ok,
lint_issues[], findings[], risk_score,
risk_level, security_score (0-100),
sha256, scan_history, disclaimer, and
quota. For a hash scanned before, the response also carries
trend (direction: improved/declined/unchanged,
delta vs. the previous scan, previous_security_score)
and explanation[] — plain-language translations of each finding
with advice.
/api/scan_proTwo things, based on what you send:
1. Activate Pro or Premium:
curl -X POST https://skillsmith.ch/api/scan_pro \
-d '{"api_key":"sk_...","activate_payment_signature":"<tx>"}'
# add "tier":"premium" (and send $10 instead of $5) for the unlimited tier
2. Batch-scan up to 25 files (once Pro/Premium is active; consumes 1 unit of your scan quota per call, not per file):
curl -X POST https://skillsmith.ch/api/scan_pro \
-d '{"api_key":"sk_...","files":[{"name":"a/SKILL.md","text":"..."},{"name":"b/SKILL.md","text":"..."}]}'
/api/lookup?sha256=...&api_key=...VirusTotal-style hash lookup: has this exact file been scanned before? Requires sign-in; consumes 1 unit of your daily DB-lookup quota (separate from the scan quota -- see pricing table above).
curl "https://skillsmith.ch/api/lookup?sha256=4807c1a3de60...&api_key=sk_..."
{"found": true, "record": {"sha256": "...", "name": "date-formatter", "seen_count": 3, "risk_level": "clean", ...}, "quota": {...}}
/api/registry?api_key=...&limit=50Browse the public Safe Skills Database: skills that scanned clean +
lint-ok, newest first. Each entry has a has_content flag --
true if the submitter published the actual content (see below). Also
consumes 1 unit of your DB-lookup quota. Explicitly an automated-heuristic
result, not a manual audit.
curl "https://skillsmith.ch/api/registry?api_key=sk_..."
/api/skill?sha256=...&api_key=...Fetch the actual, usable SKILL.md content for a hash -- the "use the
skill" endpoint, distinct from /api/lookup (verdict/metadata
only). Only works if the submitter explicitly published it by ticking
"Publish to Safe Skills DB" on a clean scan (POST /api/scan
with "publish": true). Returns 404 if not published.
Consumes 1 unit of your DB-lookup quota.
curl "https://skillsmith.ch/api/skill?sha256=4807c1a3de60...&api_key=sk_..."
{"sha256": "...", "text": "---\nname: date-formatter\n...", "quota": {...}}
/api/buy_credit (pay-as-you-go, additive)Buy one extra scan or lookup without a Pro/Premium subscription. Always requires an existing account and on-chain USDC payment; tops up whatever tier you're already on, never replaces it.
curl -X POST https://skillsmith.ch/api/buy_credit \
-d '{"api_key":"sk_...","payment_signature":"<tx>","kind":"scan"}' # $0.02, +1 scan
curl -X POST https://skillsmith.ch/api/buy_credit \
-d '{"api_key":"sk_...","payment_signature":"<tx>","kind":"lookup"}' # $0.01, +1 lookup
| Status | Meaning |
|---|---|
| 400 | Bad request (missing/invalid field, malformed hash, etc.) |
| 401 | Sign in required, or your api_key is unknown/invalid |
| 402 | Payment required or not yet verified on-chain |
| 429 | Daily quota exceeded for your current tier |
| 503 | Storage temporarily unavailable (rare) — retry later; honor the Retry-After header |
Full implementation: github.com/Larslllllll/skillsmith-web (this web app) and github.com/Larslllllll/skillsmith (the underlying CLI/library and detection engine, also usable standalone or as a GitHub Action).
Submit raw skill content and an AI analyst inside an isolated Vercel container simulates what an agent following it would do: capabilities, action trace, IOCs and a severity verdict ("any.run for agent skills"). The content is never executed against real systems.
POST /api/sandbox-run
Content-Type: application/json
{ "text": "--- name: my-skill ... (raw SKILL.md content, max 100 KB)" }
Response: report with analysis_id, static_iocs, ai_analysis (simulated_actions, capabilities_summary, severity 0-10, recommendation). Rate limit: 10/day/IP.
Shareable permalink: GET /api/analysis?id=<analysis_id>
Interactive UI: /analysis.html