> For the complete documentation index, see [llms.txt](https://docs.skillplus.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.skillplus.xyz/sdk.md).

# SDK

SkillPlus SDKs let developers integrate SkillPlus into their own products, dashboards, CI pipelines, and marketplaces.

The SDKs are designed for applications that need to check AI skill security automatically.

## Quick start

The minimal call is one URL in, one rating out.

### TypeScript

```bash
npm install skillplus
```

```ts
import { SkillPlus } from "skillplus";

const skillplus = new SkillPlus({
  apiKey: process.env.SKILLPLUS_API_KEY!,
});

const result = await skillplus.query({
  repoUrl: "https://www.skills.sh/vercel-labs/skills/find-skills",
  // GitHub repositories work the same way: "https://github.com/owner/repo"
});

if (result.status === "found") {
  console.log(result.report.verdict); // "safe" | "medium" | "high" | "unknown" — UI labels: Safe / Caution / High Risk / Unrated
}
```

Prefer `verdict` (rating system v3) over the legacy `rating` field — `verdict` folds historical values onto the current three-tier scale. UI labels: safe→Safe, medium→Caution, high→High Risk, unknown→Unrated.

### Python

```bash
pip install skillplus
```

```python
from skillplus import SkillPlus

client = SkillPlus(api_key="skp_...")

result = client.query("https://www.skills.sh/vercel-labs/skills/find-skills")
# GitHub repositories work the same way: "https://github.com/owner/repo"

if result.status == "found" and result.report:
    print(result.report.verdict)  # "safe" | "medium" | "high" | "unknown" — UI labels: Safe / Caution / High Risk / Unrated
```

### The three integration patterns

```ts
// 1. Show a report — pure read, instant, binary answer
const r = await skillplus.query({ repoUrl });

// 2. Scan in the background — fire-and-forget ack, or wait for the report
const ack = await skillplus.scan({ repoUrl });
const report = await skillplus.scan({ repoUrl, wait: true });

// 3. Query-and-scan — never scanned? scan it (instant, or waiting)
const r1 = await skillplus.query({ repoUrl, scanIfMissing: true });
const r2 = await skillplus.query({ repoUrl, wait: true }); // r2.report is non-null
```

```python
# The same three patterns in Python
r = client.query(url)
ack = client.scan(url)
report = client.scan(url, wait=True)
r1 = client.query(url, scan_if_missing=True)
r2 = client.query(url, wait=True)
```

Both SDKs talk to the official SkillPlus service at `https://skillplus.xyz`. skills.sh URLs (with or without `www`) and GitHub URLs are both accepted everywhere.

## Result contracts

`query` is **binary** — internal pipeline states are never your problem:

| Status      | Meaning                                         | Extras                                                                                      |
| ----------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `found`     | A report exists — `result.report` is populated. | Use `report.verdict`, findings, supply chain, badge URL.                                    |
| `not_found` | No completed report (yet).                      | `result.scanning` is `true` when a scan is queued/running right now — "check back shortly". |

`scan` (without `wait`) returns an acknowledgement: `accepted` (`true` = this call queued a new scan; `false` = deduplicated — already scanning, or a fresh report exists and `force` wasn't set) and `scanning`.

Failures never appear as status values: a failing scan **throws/raises `SkillPlusError`** on the waiting paths.

### Client options

| Option (TS / Python)         | Default                 | Notes                                                                                |
| ---------------------------- | ----------------------- | ------------------------------------------------------------------------------------ |
| `baseUrl` / `base_url`       | `https://skillplus.xyz` | Point at staging or a self-hosted deployment.                                        |
| `timeoutMs` / `timeout`      | 30 s                    | Per-request timeout.                                                                 |
| `maxRetries` / `max_retries` | 2                       | Extra attempts on 429/502/503, timeouts, and network errors, honoring `Retry-After`. |

Finding severities follow rating system v3 (`high` / `medium` / `low`); reports scanned before v3 may still carry legacy values (`danger` / `warning` / `info`). `severityNormalized` / `severity_normalized` folds both generations onto one scale — prefer it.

## Integration flow

```mermaid
flowchart LR
    A[Your app, marketplace, or CI pipeline]
    B[SkillPlus SDK]
    C[Query existing report]
    D{Report found?}
    E[Return report, rating, badge]
    F[Request scan-if-missing]
    G[SkillPlus scan pipeline<br/>rules + graph + multi-agent AI]
    H[Structured result for your product]

    A --> B
    B --> C
    C --> D
    D -- yes --> E
    D -- no --> F
    F --> G
    G --> E
    E --> H
```

## Advanced options

The minimal `repoUrl` call is all most integrations need. The remaining options exist for specific situations:

### `query` options

| Option (TS / Python)                | Default       | When to use it                                                                                    |
| ----------------------------------- | ------------- | ------------------------------------------------------------------------------------------------- |
| `skillPath` / `skill_path`          | auto-detected | A repository contains many skills and you want one specific path, e.g. `skills/example`.          |
| `scanIfMissing` / `scan_if_missing` | `false`       | Queue a scan automatically when no report exists yet — one round trip instead of query-then-scan. |

```ts
// Example: check one skill inside a multi-skill repo, scanning it if unknown
const result = await skillplus.query({
  repoUrl: "https://github.com/owner/repo",
  skillPath: "skills/example",
  scanIfMissing: true,
});
```

### `scan` options

`scan(...)` requests analysis explicitly (rather than as a query fallback). It accepts `repoUrl`, plus optional `skillPath` and `force` (re-scan even if a fresh report exists).

Re-scans are **content-drift aware**: if the skill changed since the previous report, SkillPlus runs a full fresh scan as a new report instead of mixing two content versions.

## Full method reference

| TypeScript                 | Python                         | Use case                                                                                                                                                                       |
| -------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `query({ repoUrl, ... })`  | `query(url, ...)`              | Binary report check. `scanIfMissing` triggers a scan; `wait: true` blocks until the report exists.                                                                             |
| `scan({ repoUrl, ... })`   | `scan(url, ...)`               | Trigger a scan: instant ack by default, `wait: true` returns the finished report. `force` re-scans fresh reports.                                                              |
| `getReport(scanId)`        | `get_report(scan_id)`          | Retrieve the structured report: rating, findings, AI audit, supply-chain snapshot, recommendations.                                                                            |
| `getBadge(scanId)`         | `get_badge(scan_id)`           | Fetch the badge SVG for embedding.                                                                                                                                             |
| `getBadgeUrl(scanId)`      | `get_badge_url(scan_id)`       | Generate a badge URL for READMEs, marketplaces, or internal portals.                                                                                                           |
| `getReportPageUrl(scanId)` | `get_report_page_url(scan_id)` | The report page a person can read. The `reportUrl` / `report_url` field on a report is the API endpoint and returns JSON — use this one for links you put in front of a human. |

## High-concurrency workflows

The SDKs are designed for real product usage.

If many users request the same missing skill at the same time, SkillPlus reuses the scan work instead of launching repeated duplicate scans.

```mermaid
flowchart TD
    A[Many users request the same skill] --> B[SDK query with scanIfMissing]
    B --> C[SkillPlus detects existing queued or running work]
    C --> D[One scan is reused]
    D --> E[All callers receive the same report signal]
```

This makes it practical to integrate SkillPlus into high-traffic pages, marketplaces, and internal developer portals.

## Common SDK integrations

| Integration         | What SkillPlus provides                                                                  |
| ------------------- | ---------------------------------------------------------------------------------------- |
| Marketplace listing | Show rating, report link, and badge before installation.                                 |
| Developer portal    | Let internal users check skills before approval.                                         |
| CI workflow         | Gate a publish or merge on the skill's rating.                                           |
| Security dashboard  | Aggregate report data across approved skills — ratings stay live as new advisories land. |
| Author tooling      | Generate badges and report links for README files.                                       |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.skillplus.xyz/sdk.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
