# SkillzDrive Developer Docs — full corpus

Every documentation page concatenated for one-shot loading into an LLM context. Pages are delimited by HTML comments naming their source URL.

<!-- BEGIN https://www.skillzdrive.com/docs -->

# SkillzDrive Developer Docs

> Markdown variant of the docs index at <https://www.skillzdrive.com/docs>.
> Agents: append `.md` to any `/docs/...` URL on this site for the
> agent-readable version. For the entire developer docs corpus in one
> fetch, use <https://www.skillzdrive.com/llms-full.txt>.

SkillzDrive is an MCP server that lets AI agents discover, install,
and execute "skills" — small, sandboxed packages that do real work
(PDF manipulation, image processing, spreadsheet generation, web
scraping, and more).

Three transports access the same drive:

- **MCP** — `https://www.skillzdrive.com/api/mcp` (Streamable HTTP). Best for AI agents.
- **REST** — `https://www.skillzdrive.com/api/v1`. Use from any language. Anonymous-capable for read endpoints.
- **CLI** — `npm install -g skillzdrive`. Symlinks skills into `.agents/skills/`, `.claude/`, `.cursor/`, etc.

## Start here

- [Quickstart](https://www.skillzdrive.com/docs/quickstart.md): connect a client and run your first skill in 5 minutes.
- [Custom Agent Integration](https://www.skillzdrive.com/docs/agent-integration.md): for developers building custom agents with direct MCP access.
- [AI Context system prompt](https://www.skillzdrive.com/docs/ai-context.md): drop-in context for non-MCP platforms (Claude Projects, Custom GPTs, .cursorrules).

## For developers

- [REST API overview](https://www.skillzdrive.com/docs/rest-api.md): base URL, auth, response shape, status codes.
- [REST API endpoint reference](https://www.skillzdrive.com/docs/rest-api/endpoints.md): every v1 route grouped by resource.
- [REST API webhooks](https://www.skillzdrive.com/docs/rest-api/webhooks.md): credit-alert subscriptions and HMAC verification.
- [CLI overview](https://www.skillzdrive.com/docs/cli.md): install and authenticate `skillzdrive`.
- [CLI command reference](https://www.skillzdrive.com/docs/cli/reference.md): every command with flags and exit codes.

## Guides

- [Discovering skills](https://www.skillzdrive.com/docs/guides/discovering-skills.md)
- [Executing scripts](https://www.skillzdrive.com/docs/guides/executing-scripts.md)
- [Authentication](https://www.skillzdrive.com/docs/guides/authentication.md)
- [Managing your drive with AI](https://www.skillzdrive.com/docs/guides/managing-drive.md)
- [Connecting an MCP client](https://www.skillzdrive.com/docs/guides/connecting.md)

## Concepts

- [MCP basics](https://www.skillzdrive.com/docs/mcp-basics.md)
- [Teams](https://www.skillzdrive.com/docs/guides/teams.md)
- [Sharing](https://www.skillzdrive.com/docs/guides/sharing.md)
- [Collections](https://www.skillzdrive.com/docs/guides/collections.md)
- [Security](https://www.skillzdrive.com/docs/security.md)

## MCP reference

- [Tools](https://www.skillzdrive.com/docs/reference/tools.md): all 29 `skills_*` tools.
- [Documentation resources](https://www.skillzdrive.com/docs/reference/resources.md): TOC + section reading model.
- [HTTP endpoints](https://www.skillzdrive.com/docs/reference/endpoints.md): MCP HTTP transport.

## Base URL summary

| Transport | URL |
|-----------|-----|
| MCP | `https://www.skillzdrive.com/api/mcp` |
| REST v1 | `https://www.skillzdrive.com/api/v1` |
| Marketplace JSON | `https://www.skillzdrive.com/marketplace.json` |

Auth header for MCP and REST: `Authorization: Bearer sk_live_<your-key>`.
Anonymous read access is rate-limited to 1 request per minute per IP;
include `X-Skillzdrive-Install-Id: <uuid>` for a per-installation
quota bucket.

## New to MCP?

MCP (Model Context Protocol) is an open standard for connecting AI
models to external tools. SkillzDrive is an MCP server — any
compliant client works. See [MCP basics](https://www.skillzdrive.com/docs/mcp-basics.md).
Once connected, install the `skillzdrive-mcp-guide` skill to teach
your agent all 29 tools automatically.

<!-- END https://www.skillzdrive.com/docs -->

<!-- BEGIN https://www.skillzdrive.com/docs/quickstart -->

# Quickstart

> Markdown variant of <https://www.skillzdrive.com/docs/quickstart>.
> Connect an MCP client to SkillzDrive and run your first skill in 3 steps.

Prerequisite: a SkillzDrive API key. Create one at
<https://www.skillzdrive.com/dashboard/get-setup>. Replace
`sk_live_YOUR_KEY` in the snippets below with your actual key.

## Step 1 — Connect your client

Add SkillzDrive to your MCP client configuration. The MCP endpoint is
the same across all clients: `https://www.skillzdrive.com/api/mcp`.

### Claude Code (`~/.claude.json` or `.mcp.json`)

```json
{
  "mcpServers": {
    "skillzdrive": {
      "url": "https://www.skillzdrive.com/api/mcp",
      "headers": {
        "Authorization": "Bearer sk_live_YOUR_KEY"
      }
    }
  }
}
```

### Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
on macOS, or `%APPDATA%\Claude\claude_desktop_config.json` on
Windows. Same JSON structure as Claude Code above.

### Cursor (`~/.cursor/mcp.json` or `.cursor/mcp.json`)

Same JSON structure as Claude Code above.

### Custom agent (TypeScript)

```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const client = new Client({ name: "my-agent", version: "1.0.0" });
const transport = new StreamableHTTPClientTransport(
  new URL("https://www.skillzdrive.com/api/mcp"),
  { requestInit: { headers: { Authorization: "Bearer sk_live_YOUR_KEY" } } },
);
await client.connect(transport);
```

### Web-based clients (Claude.ai, ChatGPT)

These use built-in connector UIs rather than JSON config. See the
visual setup guides on the human-facing quickstart page.

## Step 2 — Download the guide skill

The `skillzdrive-mcp-guide` skill is included in every account by
default. It teaches your agent all 29 MCP tools, the correct
execution workflows, error handling patterns, and management
operations — no system-prompt changes required.

Install it locally where your agent connects to SkillzDrive. Download
URL is exposed via the dashboard or by calling
`GET /api/skills/lookup?slug=skillzdrive-mcp-guide` followed by
`GET /api/skills/<id>/archive`.

## Step 3 — Test with a query

Ask your agent a natural-language question:

```
You: "What skills do I have?"
Agent: calls listSkills → shows your skill library

You: "Find me a skill for checking the weather"
Agent: calls discoverSkills → searches marketplace → suggests import
```

No manual tool calls required. The guide skill gives your agent the
context it needs to handle the workflow automatically.

## The Golden Path

The standard execution sequence for a script-based skill:

```
searchSkills → listScripts → runScript → readFile → closeSession
```

1. `searchSkills(query)` finds the right skill slug.
2. `listScripts(skillSlug)` returns exact script names — never guess.
3. `runScript(skillSlug, scriptName, reuseSession: true)` returns a `sessionId`.
4. `readFile(sessionId, "/tmp/last_run.out")` returns the script output.
5. `closeSession(sessionId)` frees the sandbox (or pass `closeAfter: true` on the final readFile).

## Next steps

- [Managing your drive with AI](https://www.skillzdrive.com/docs/guides/managing-drive.md)
- [Discovering skills](https://www.skillzdrive.com/docs/guides/discovering-skills.md)
- [Custom agent integration](https://www.skillzdrive.com/docs/agent-integration.md) — for developers building custom agents.
- [AI context system prompt](https://www.skillzdrive.com/docs/ai-context.md) — drop into Claude Projects / Custom GPTs / .cursorrules.

<!-- END https://www.skillzdrive.com/docs/quickstart -->

<!-- BEGIN https://www.skillzdrive.com/docs/agent-integration -->

# Custom Agent Integration

> Markdown variant of <https://www.skillzdrive.com/docs/agent-integration>.
> For developers building custom agents that connect directly to
> SkillzDrive via MCP.

If you use Claude Code, Cursor, Claude.ai, ChatGPT, or another client
with built-in MCP support, you don't need this page — follow the
[Quickstart](https://www.skillzdrive.com/docs/quickstart.md) instead.

## A. Making your agent aware of skills

### Baseline: install the guide skill

Connecting MCP and expecting the AI to use it is the #1 integration
mistake. **Most LLMs will NOT call MCP tools unless explicitly told
to.**

Install the `skillzdrive-mcp-guide` skill locally alongside your
agent. Once installed, the MCP server's briefing (plus
`skills_getStarted`) teaches your agent all 29 tools, execution
workflows, error handling patterns, and fallback chains — no system
prompt engineering required.

### Pattern 1: Pinned skills for sub-agents

In orchestrator/sub-agent architectures, the orchestrator discovers
skills dynamically (via `searchSkills` or `listSkills`), then pins a
specific skill or script to a sub-agent for efficiency. The
sub-agent skips discovery entirely and goes straight to execution.

```ts
// Orchestrator: discover dynamically, then delegate
const { results } = await mcpClient.callTool("skills_searchSkills", {
  query: userTask, // e.g. "merge these PDFs"
});
const skill = results[0]; // best match

// Pin the skill slug to a sub-agent's context
const subAgentPrompt = `You are a ${skill.name} specialist.
Use skill slug: ${skill.slug}
Go directly to skills_listScripts → skills_runScript → skills_readFile → skills_closeSession.
Do NOT call searchSkills or listSkills — your skill is already assigned.`;

await spawnSubAgent(subAgentPrompt);
```

This is the most efficient pattern for production systems. The
orchestrator handles discovery once, and each sub-agent operates
with minimal tool calls. You can pin down to a specific script name
if the orchestrator already knows which script to run.

### Pattern 2: Caching strategy

Don't re-fetch skill lists on every message. Skills and scripts
don't change mid-conversation.

| What to cache | Cache duration | When to refresh |
|---------------|----------------|-----------------|
| `listSkills` results | Entire session | Agent restart |
| `listScripts` per slug | Entire session | Agent restart |
| `runScript` results | **Never cache** | Every execution is unique |

## B. UI feedback for tool calls

The #2 mistake: running skills silently. Users see nothing for 5–30
seconds and think the app is broken. **Always show what's happening.**

### What to show at each stage

| Stage | What to show | Example |
|-------|--------------|---------|
| `searchSkills` | "Searching for skills..." | Spinner + message |
| `listScripts` | "Found merge.py — preparing..." | Status update |
| `runScript` | "Processing your PDF..." | Progress indicator |
| `readFile` | "Reading results..." | Brief flash |
| Success | Formatted result | Code block or rendered output |
| Error | Error + suggestions | Alert with recovery action |

### Implementation pattern

```ts
agent.onToolCall((toolName, args) => {
  switch (toolName) {
    case "skills_searchSkills":
      showStatus("Searching for skills...");
      break;
    case "skills_listScripts":
      showStatus(`Loading scripts for ${args.skillSlug}...`);
      break;
    case "skills_runScript":
      showStatus(`Running ${args.scriptName}...`);
      break;
    case "skills_readFile":
      showStatus("Reading results...");
      break;
  }
});

agent.onToolResult((toolName, result) => {
  if (toolName === "skills_runScript") {
    if (result.exitCode === 0) {
      showStatus("Script completed successfully", "success");
    } else {
      showStatus(result.error || "Script failed", "error");
    }
  }
});
```

### Displaying errors well

SkillzDrive errors are structured for great UX. Use all the fields:

```jsonc
{
  "error": "skill_not_found",            // Machine-readable code
  "message": "No skill with slug 'pdff'",// Show this to users
  "suggestions": [                       // Show as recovery options
    "Did you mean 'pdf'?",
    "Use skills_searchSkills to find skills"
  ],
  "_workflow": {                         // Use for automatic recovery
    "nextSteps": [
      { "tool": "skills_searchSkills", "example": { "query": "pdf" } }
    ]
  }
}
```

Display pattern:

1. Show `message` as the error text.
2. Show `suggestions[0]` as a clickable recovery action.
3. Use `_workflow.nextSteps` to auto-recover if possible.
4. **NEVER show raw JSON-RPC errors to users.**

## C. Async script execution

Scripts can take 5–60 seconds. Don't make users wait silently.
Acknowledge immediately, show progress, notify when done.

### Recommended pattern

1. Start the script (`runScript` with `reuseSession: true`).
2. Acknowledge immediately ("I'm processing your request...").
3. Continue conversation — let users ask other questions while the script runs.
4. Await completion — script finishes, read output.
5. Notify with results ("Your PDF merge is complete!").

```ts
async function executeSkillAsync(
  mcpClient: McpClient,
  skillSlug: string,
  scriptName: string,
  args?: string[],
) {
  notify("Starting skill execution...", "loading");

  const runResult = await mcpClient.callTool("skills_runScript", {
    skillSlug,
    scriptName,
    args,
    reuseSession: true,
  });

  if (runResult.exitCode !== 0) {
    notify(`Error: ${runResult.error}`, "error");
    return null;
  }

  const output = await mcpClient.callTool("skills_readFile", {
    sessionId: runResult.sessionId,
    filePath: "/tmp/last_run.out",
  });

  notify("Skill completed!", "success");
  displayOutput(output.content);

  await mcpClient.callTool("skills_closeSession", {
    sessionId: runResult.sessionId,
  });

  return output.content;
}
```

If `output.hasMore` is true, paginate with `startLine` and `limit`.
The default returns the first 200 lines.

## D. Integration checklist

### Connection
- [ ] MCP client connected via Streamable HTTP.
- [ ] API key authenticated and connected.

### Skill awareness
- [ ] Skills listed in system prompt or pre-loaded at startup.
- [ ] Agent knows to call `listScripts` before `runScript`.
- [ ] Skill slugs cached (not re-fetched every message).
- [ ] Script names cached per skill.

### Execution
- [ ] Agent uses `reuseSession: true` for all script runs.
- [ ] Agent reads output via `readFile` (not from `runScript` response).
- [ ] Agent closes sessions when done.

### User experience
- [ ] UI shows loading state during script execution.
- [ ] UI shows formatted results on success.
- [ ] UI shows error message + suggestions on failure.

## Next steps

- [AI context system prompt](https://www.skillzdrive.com/docs/ai-context.md) — copy-paste into your model's context.
- [Discovering skills](https://www.skillzdrive.com/docs/guides/discovering-skills.md) — deep dive on search, browsing, and skill types.
- [Executing scripts](https://www.skillzdrive.com/docs/guides/executing-scripts.md) — session lifecycle, credentials, output handling.

<!-- END https://www.skillzdrive.com/docs/agent-integration -->

<!-- BEGIN https://www.skillzdrive.com/docs/guides/discovering-skills -->

# Discovering Skills

> Markdown variant of <https://www.skillzdrive.com/docs/guides/discovering-skills>.

Find the right skill for any task — from your personal library or
the public marketplace.

## Two places to look

Skills live in two places. Your agent knows the difference and
searches the right one based on what you ask.

**Your drive** — skills you own, skills from your teams, and skills
shared with you. These are ready to use immediately.

> "What skills do I have?"
> "Do I have anything for PDFs?"

**The marketplace** — hundreds of public skills and the GitHub
skill catalog. Browse, import to your drive, and start using
immediately.

> "Find me a skill for data visualization"
> "What's available for working with spreadsheets?"

## How agents discover skills

The MCP tools that drive discovery:

- `skills_listSkills` — list everything in your drive (your skills + team + shared, filtered by API key scope).
- `skills_searchSkills(query)` — focused search of your drive by keyword.
- `skills_discoverSkills(keywords, offset)` — broad search of the public marketplace + cached GitHub catalog. Paginated 10/page.
- `skills_getLeaderboard(sort_by)` — top public skills by executions, installs, or rating.
- `skills_importToDrive(slug)` — bring a marketplace skill into your drive (charges credits per skill size).

When the user asks about something they already have, the agent
calls `searchSkills` or `listSkills`. When the user asks for
something new, the agent calls `discoverSkills`. The
`skillzdrive-mcp-guide` skill teaches this routing automatically.

## Real-world examples

### Find a skill you already have

> You: "I need to merge some PDF files. Do I have a skill for that?"
> Agent: searches your drive → finds "PDF Manipulation" with 3 scripts → ready to run.

### Discover something new from the marketplace

> You: "I need to analyze some survey data. Are there any skills for that on the marketplace?"
> Agent: searches marketplace → finds "Data Analyzer" and "Survey Insights" → imports your choice → runs it on your data.

### See your full library

> You: "Show me everything in my skill library."
> Agent: lists all skills → shows your personal skills, team skills, and shared skills in one view.

### Import and use in one step

> You: "Find a skill for creating presentations and use it to make a slide deck from this outline."
> Agent: searches marketplace → imports skill → runs it → presentation created.

## Two types of skills

### Script-based skills

Run code to get things done — convert files, analyze data, generate
reports, process images. Your agent runs the script in a cloud
sandbox (or locally) and returns the results.

Identifier: `hasScripts: true` in the skill metadata.

### Template-based skills

Provide knowledge and guidelines — writing styles, brand guides,
code patterns, workflows. Your agent reads the skill's documentation
and applies it to your task.

Identifier: `hasScripts: false`. The agent uses `skills_docTOC` and
`skills_docSection` instead of `skills_runScript`.

## Notes

- Your library automatically includes skills from your personal drive, team drives, and skills shared directly with you. All three sources are combined — no extra configuration needed.
- Importing a skill from the marketplace charges credits based on the skill's size. Skills already in your drive are free to use anytime.
- The catalog is dynamic — never hardcode skill lists. Always discover via `searchSkills`/`listSkills`/`discoverSkills`.

## Next steps

- [Executing scripts](https://www.skillzdrive.com/docs/guides/executing-scripts.md): how script-based skills run, session management, output.
- [Managing drive with AI](https://www.skillzdrive.com/docs/guides/managing-drive.md): organize skills, create collections, browse the marketplace.
- [MCP tools reference](https://www.skillzdrive.com/docs/reference/tools.md): every `skills_*` tool with arguments.

<!-- END https://www.skillzdrive.com/docs/guides/discovering-skills -->

<!-- BEGIN https://www.skillzdrive.com/docs/guides/executing-scripts -->

# Executing Scripts

> Markdown variant of <https://www.skillzdrive.com/docs/guides/executing-scripts>.

Run skill scripts in the cloud or locally — your agent handles the
details.

## Two ways to run scripts

When a skill has scripts (`hasScripts: true`), your agent can run
them in the cloud or download and execute them on your machine.

### Cloud execution (recommended)

Scripts run in an isolated cloud sandbox. Faster, safer, no local
setup. Dependencies are pre-installed automatically.

- **Cost**: credits per execution (5-min or 30-min sessions).
- **Speed**: fast — optimized containers with cached dependencies.
- **Safety**: fully isolated, destroyed after use.
- **Best for**: most tasks — data processing, file conversion, analysis.

Tools used: `skills_runScript`, `skills_readFile`,
`skills_closeSession`.

### Local execution (free)

Your agent downloads the script and runs it on your machine. Free,
but requires local dependencies and runs with your system
permissions.

- **Cost**: free — no credits charged.
- **Setup**: you manage dependencies (Python, pip packages, etc.).
- **Safety**: runs on your machine with your permissions.
- **Best for**: file uploads, local tools, cost-sensitive workflows.

Tools used: `skills_getScript` (or `skills_getScriptStream` if your
caller can't fetch signed URLs).

**Start with cloud execution.** It's the default for a reason. The
5-minute session is enough for most tasks. Use the 30-minute
session for long-running jobs like large dataset processing.
Switch to local only when you need local file access or want to
avoid credit usage entirely.

## Cloud session options

|  | 5-Minute Session | 30-Minute Session |
|---|---|---|
| Cost | Lower credits | Higher credits |
| Timeout | 5 minutes of inactivity | 30 minutes of inactivity |
| Best for | Quick tasks: file conversion, formatting, simple analysis | Heavy processing: large datasets, multi-step pipelines, ML tasks |
| Default? | Yes — recommended for most tasks | Only when needed |

## The Golden Path for cloud execution

```
listScripts → runScript(reuseSession: true) → readFile → closeSession
```

1. `skills_listScripts(skillSlug)` — get exact script names. Never guess.
2. `skills_runScript(skillSlug, scriptName, reuseSession: true)` — returns `sessionId` and `exitCode`.
3. `skills_readFile(sessionId, "/tmp/last_run.out")` — get stdout. Use `/tmp/last_run.err` for stderr.
4. `skills_closeSession(sessionId)` — free the sandbox. Or pass `closeAfter: true` on the final readFile.

Output is **not** in the `runScript` response — always read it via
`readFile`. Default returns the first 200 lines; if `hasMore` is
true, paginate with `startLine` and `limit`.

## Real-world examples

### Process a file in the cloud

> "Merge these three PDFs into one document."
> Agent: finds PDF skill → runs merge script in cloud → merged PDF ready in seconds.

### Long-running analysis

> "Analyze this 500MB CSV and generate a summary report with charts."
> Agent: runs analysis script (30-min session) → processes data → returns report.

### Run locally for free

> "Upload this skill file to my SkillzDrive."
> Agent: downloads upload script → runs locally (free) → skill uploaded to your drive.

### Chain multiple scripts

> "Extract text from this PDF, then translate it to Spanish."
> Agent: runs extract script → runs translate script (same session via `reuseSession: true`) → translated text ready.

## API keys and credentials

Some skills need third-party API keys to work — for example, a
skill that generates images might need a Gemini or OpenAI key. Your
agent will tell you if a credential is missing and what's needed.

Add API keys in your **SkillzDrive Account Settings** under
Credentials. They're encrypted and securely passed to scripts at
runtime — never stored in the sandbox.

If a script has `requiredEnvVars`, the user must configure those
API keys in their SkillzDrive account first.

## When things go wrong

| Issue | What happens | What to do |
|-------|--------------|------------|
| Missing credential | Script can't access a required API | Add the key in Account Settings → Credentials |
| Script timeout | Task took longer than session allows | Ask your agent to use a 30-minute session |
| Script error | Bug in the script itself | Your agent shows the error — try different input or a different skill |
| Insufficient credits | Not enough credits for cloud execution | Top up credits or run locally for free |
| Session expired (`session_not_found`) | Sandbox reaped after TTL | Re-run script with `reuseSession: true` to get a fresh sandbox |

## Next steps

- [Discovering skills](https://www.skillzdrive.com/docs/guides/discovering-skills.md)
- [MCP tools reference](https://www.skillzdrive.com/docs/reference/tools.md): every `skills_*` tool with arguments and the error response shape.

<!-- END https://www.skillzdrive.com/docs/guides/executing-scripts -->

<!-- BEGIN https://www.skillzdrive.com/docs/guides/authentication -->

# Authentication

> Markdown variant of <https://www.skillzdrive.com/docs/guides/authentication>.

API keys, OAuth 2.0, and securing your integration.

## API key authentication

Keys follow the format `sk_live_` + random string. This is the
simplest and most common method. Get keys from
<https://www.skillzdrive.com/dashboard/get-setup>.

### Pass via header (recommended)

```http
Authorization: Bearer sk_live_abc123def456...
```

### Or query parameter

```http
GET /api/mcp?apiKey=sk_live_abc123def456...
```

Header authentication is recommended for security — query
parameters can leak into logs and HTTP referrer headers.

## Key constraints

Each API key has properties that control access:

| Property | Description |
|----------|-------------|
| `enabled` | Must be `true` for the key to work |
| `expires_at` | Optional expiration date |
| `monthly_execution_quota` | Max script executions per month (0 = unlimited) |
| `current_month_usage` | Counter, resets monthly |
| `rate_limit_per_minute` | Max requests per minute |
| `allowed_skill_ids` | Optional whitelist of accessible skills (null = all) |

### Skill access resolution

Your API key's `allowed_skill_ids` intersects with the union of your
personal drive, team drives, and shared skills. If
`allowed_skill_ids` is null (all skills), you get access to the full
union. If it's a specific list, only skills in both the list and
the union are accessible.

## Error responses

When authentication fails, the server returns structured errors:

```json
{
  "error": "access_denied",
  "message": "API key required",
  "suggestions": ["Get an API key at https://www.skillzdrive.com/dashboard"]
}
```

## OAuth 2.0

For AI clients that require OAuth (Claude.ai, Claude Code, etc.),
the server implements full OAuth 2.0.

### Discovery endpoint

```http
GET /.well-known/oauth-authorization-server
```

Response:

```json
{
  "issuer": "https://www.skillzdrive.com",
  "authorization_endpoint": "https://www.skillzdrive.com/authorize",
  "token_endpoint": "https://www.skillzdrive.com/api/mcp/oauth/token",
  "registration_endpoint": "https://www.skillzdrive.com/api/mcp/oauth/register",
  "grant_types_supported": ["authorization_code", "client_credentials"],
  "code_challenge_methods_supported": ["S256", "plain"],
  "scopes_supported": ["skills:read", "skills:execute"]
}
```

### Authorization Code + PKCE

Used by Claude Code and other MCP clients that perform the full
OAuth dance.

Flow:

1. Client calls `POST /oauth/register` (Dynamic Client Registration).
2. Client redirects user to authorization endpoint with PKCE challenge.
3. User authorizes → redirect back with `code`.
4. Client exchanges `code` + `code_verifier` at `POST /oauth/token`.
5. Server returns API key as `access_token`.

Client registration body:

```json
{
  "redirect_uris": ["http://localhost:3000/callback"],
  "client_name": "My MCP App",
  "grant_types": ["authorization_code"],
  "token_endpoint_auth_method": "none"
}
```

Token exchange body:

```json
{
  "grant_type": "authorization_code",
  "code": "AUTH_CODE",
  "code_verifier": "VERIFIER",
  "redirect_uri": "http://localhost:3000/callback"
}
```

Token response:

```json
{
  "access_token": "sk_live_...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": "skills:read skills:execute"
}
```

### Client Credentials

Simple API key exchange for programmatic access without user
interaction.

```http
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=my-app&client_secret=sk_live_YOUR_KEY
```

Client credentials is the simplest OAuth flow — your API key is
both the secret and the resulting access token.

### API key resolution priority

When using OAuth, the server resolves the API key in this order:

1. API key linked during the authorization flow.
2. Bearer token on the token exchange request.
3. API key captured during client registration.

## Next steps

- [Connecting](https://www.skillzdrive.com/docs/guides/connecting.md): configure your MCP client to connect to SkillzDrive.
- [Security](https://www.skillzdrive.com/docs/security.md): best practices for securing API keys and integrations.
- [MCP tools reference](https://www.skillzdrive.com/docs/reference/tools.md): error response shape and full tool reference.

<!-- END https://www.skillzdrive.com/docs/guides/authentication -->

<!-- BEGIN https://www.skillzdrive.com/docs/guides/managing-drive -->

# Managing Your Drive with AI

> Markdown variant of <https://www.skillzdrive.com/docs/guides/managing-drive>.

Let your agent organize skills, create collections, and manage your
entire drive through natural conversation.

## Overview

Every action available in the dashboard is also exposed as an MCP
tool. Your agent can create collections, add or remove skills,
upload new skills, browse the marketplace, and export bundles —
all without you touching the web interface.

These tools let your agent self-organize its skill library. It can
create project-specific collections, import skills it discovers,
and clean up what it no longer needs — all within a single
conversation.

## Real-world examples

### Save a skill you built

> "I just created a skill on Claude.ai for generating SQL queries. Upload it to my SkillzDrive so I can use it from Cursor and share it with my team."
> Agent: downloads upload script → uploads your `.skill.zip` → skill is now in your drive and accessible from any connected client.

### Find a skill for something you need done

> "I need to convert a CSV file to a formatted PDF report. Is there a skill for that?"
> Agent: searches marketplace → finds matching skills → imports to your drive → runs it on your file → done.

### Replace a skill with a better version

> "I improved my code-review skill. Replace the old version in my drive with this updated one."
> Agent: uploads new version → replaces existing skill → all your clients and team members see the update immediately.

### Organize skills for a project

> "Create a collection called 'data-pipeline' with just my ETL, validation, and reporting skills. I want a clean API key that only exposes those three."
> Agent: creates collection → adds skills → returns a scoped API key that only sees those skills.

## Collections (MCP tools)

Collections let you group skills into subsets. Your agent can
create a collection, seed it with skills from your drive, and later
add, remove, or rename it.

| Action | Tool |
|--------|------|
| Create a collection (optionally with initial skills) | `skills_createCollection` |
| Add a skill to a collection | `skills_addToCollection` |
| Remove a skill from a collection | `skills_removeFromCollection` |
| Rename a collection | `skills_updateCollection` |

You can only add skills to a collection if they are already in your
drive. Use `skills_importToDrive` first to add marketplace skills.

## Drive management (MCP tools)

| Action | Tool |
|--------|------|
| Remove a skill from your drive entirely | `skills_removeFromDrive` |
| Toggle a skill on or off (keeps it in your drive) | `skills_toggleDriveSkill` |

**Toggle** disables a skill temporarily — it stays in your drive
but won't appear in tool listings. **Remove** deletes it from your
drive entirely. Use toggle when you want to keep a skill for later.

## Uploading skills

Your agent can upload new skills from local files using the
built-in `upload-to-skillzdrive` skill. It fetches the upload
script, runs it locally with your file, and the skill is created
and added to your drive automatically.

## Download & export

Your agent can export skills as downloadable bundles using
`skills_downloadSkills`. Three scopes are supported:

| Scope | What it exports |
|-------|-----------------|
| `drive` | All skills in your drive |
| `collection` | All skills in a specific collection |
| `skill` | A single skill |

## Local vs cloud execution

Some skills are designed to run on your machine instead of in a
cloud sandbox. Your agent uses `skills_getScript` to download the
script, then executes it locally.

|  | Local execution | Cloud execution |
|---|----------------|-----------------|
| Cost | Free (no credits) | Credits per execution |
| Filesystem | Full local access | Isolated sandbox only |
| Safety | Runs on your machine | Isolated, destroyed after use |
| Best for | File uploads, local tools | Complex processing, untrusted code |

## Teams and shares

Your MCP tool listings include skills from your personal drive, any
active team drives you belong to, and skills shared directly with
you. Team and sharing management is done via the web dashboard.

## Next steps

- [Discovering skills](https://www.skillzdrive.com/docs/guides/discovering-skills.md): search, browse, and understand the skill library.
- [MCP tools reference](https://www.skillzdrive.com/docs/reference/tools.md).

<!-- END https://www.skillzdrive.com/docs/guides/managing-drive -->

<!-- BEGIN https://www.skillzdrive.com/docs/guides/teams -->

# Teams

> Markdown variant of <https://www.skillzdrive.com/docs/guides/teams>.

Create a team, share a skill library, and give every member
automatic access across all their AI clients.

## What are teams?

A team is a shared skill library. When you add a skill to a team's
drive, every active member of that team automatically gets access
to it through their MCP connection — no manual sharing required.

Teams are ideal for organizations, project groups, or any situation
where multiple people need access to the same set of skills.

| Use case | Example |
|----------|---------|
| Company tooling | All engineers get the same code review, deployment, and testing skills |
| Project collaboration | A data science team shares analysis and visualization skills |
| Client delivery | An agency provides a curated skill set to each client's team |

## Creating a team

Go to the **Teams** tab in your dashboard and click **Create
Team**. Give it a name and optional description. You become the
team owner automatically.

## Inviting members

Two ways to invite people:

- **Invite link** — generate a link from the team detail page and share it. Anyone with the link can join.
- **Add by email** — type a member's email address to send them a direct invitation. They'll see a pending invitation in their Teams tab.

New members start with a **pending** status until they accept. Once
active, they immediately get access to all team skills.

## Adding skills to a team

From the team detail page, click **Add Skill** to add any skill
from your personal drive to the team's drive. You can also add
skills to teams from the **Share** dialog on any skill card (Teams
tab).

Skills added to a team drive appear automatically in every active
member's MCP tool listings — no extra configuration needed. If a
member is connected to SkillzDrive, they see team skills alongside
their own.

## Roles

| Role | Use skills | Add/remove skills | Manage members | Delete team |
|------|------------|-------------------|----------------|-------------|
| Owner | Yes | Yes | Yes | Yes |
| Admin | Yes | Yes | Yes | No |
| Moderator | Yes | Yes | No | No |
| Member | Yes | No (can request) | No | No |

## AI agents and teams

When an agent is connected via MCP, it sees team skills
automatically alongside the user's personal and shared skills. No
special tool calls are needed — team skills appear in
`skills_searchSkills` and `skills_listSkills` results.

## Next steps

- [Sharing](https://www.skillzdrive.com/docs/guides/sharing.md): share individual skills directly with specific users.
- [Collections](https://www.skillzdrive.com/docs/guides/collections.md): organize skills into subsets per API key.
- [Managing drive with AI](https://www.skillzdrive.com/docs/guides/managing-drive.md).

<!-- END https://www.skillzdrive.com/docs/guides/teams -->

<!-- BEGIN https://www.skillzdrive.com/docs/guides/sharing -->

# Sharing

> Markdown variant of <https://www.skillzdrive.com/docs/guides/sharing>.

Share individual skills with specific users via link or email.

## What is sharing?

Sharing gives another user access to a specific skill from your
drive. Unlike teams (which share an entire library), sharing is for
granting access to individual skills one at a time.

Once a user accepts a share, the skill appears in their MCP tool
listings automatically — just like their own drive skills.

## How to share a skill

Open any skill card in your drive and click the **Share** button.
The share dialog offers two methods:

| Method | How it works |
|--------|--------------|
| Share link | Generate a link and send it to anyone. They click the link to claim the share. Links expire after 24 hours. |
| Share by email | Enter a user's email in the Access tab. If they have an account, they'll see a pending share notification. |

## Accepting or rejecting a share

When someone shares a skill with you, it appears as a **pending
share** in your drive. You can:

- **Accept** — the skill appears in your MCP tool listings immediately.
- **Reject** — the share is dismissed and the skill does not appear in your drive.

Once accepted, shared skills appear alongside your own drive skills
in `skills_searchSkills` and `skills_listSkills` results. Your
agent uses them exactly like any other skill.

## Managing access

As the skill owner, you can see all recipients in the Share
dialog's **Access** tab. From there you can:

- See who has access and their status (pending, active).
- Revoke access for any recipient at any time.
- Send new shares by email.

## Sharing vs. teams

|  | Sharing | Teams |
|---|---------|-------|
| Scope | Individual skill | Entire skill library |
| Audience | Specific person | Group of people |
| Management | Per-skill share dialog | Centralized team page |
| Best for | Quick, one-off access grants | Ongoing group collaboration |

## Next steps

- [Teams](https://www.skillzdrive.com/docs/guides/teams.md): shared skill libraries for groups.
- [Collections](https://www.skillzdrive.com/docs/guides/collections.md): organize skills into subsets per API key.
- [Custom agent integration](https://www.skillzdrive.com/docs/agent-integration.md).

<!-- END https://www.skillzdrive.com/docs/guides/sharing -->

<!-- BEGIN https://www.skillzdrive.com/docs/guides/collections -->

# Collections

> Markdown variant of <https://www.skillzdrive.com/docs/guides/collections>.

Organize your skills into subsets so each API key only sees what it
needs.

## What are collections?

A collection is a named API key with a filtered skill list. By
default, an API key has access to all skills in your drive. A
collection restricts that to only specific skills.

This is useful when you want different AI clients, projects, or
environments to see different subsets of your library.

| Use case | Example |
|----------|---------|
| Per-project filtering | A "data-science" collection with only analysis and visualization skills |
| Per-client environments | Give Claude Desktop a different set of skills than Cursor |
| Security scoping | Limit a shared key to only approved, safe skills |

## Managing collections in the dashboard

The easiest way to work with collections is through the
**Collections** button in your drive.

1. **Open Collections** — click the **Collections** button in your drive to see all your collections and create new ones.
2. **Pick your skills** — create a collection with a descriptive name (e.g. "Data Science") and select which skills it should include from your drive.
3. **Use the collection's API key** — each collection gets its own API key. Connect with that key and your client will only see the skills you selected.

You can update a collection's skill list at any time. Changes take
effect on the next connection — no need to regenerate the API key.

## How collections affect what your agent sees

Each API key maps to one collection. When a client connects with
that key, it only sees skills in that collection's list.

```
API Key  →  Collection Filter  →  Filtered Skill List
```

Keys with no collection see all drive + team + shared skills. Keys
with an empty collection see nothing.

You can only add skills that are already in your drive. Import
marketplace skills first before adding them to a collection.

## Team & shared skill toggles

By default, every collection includes skills from your personal
drive, your teams, and skills shared with you. You can toggle each
source independently per collection.

| Toggle | Default | Effect |
|--------|---------|--------|
| Team skills | On | When on, the collection includes skills from all teams you belong to. Turn off to restrict to only your personal drive. |
| Shared skills | On | When on, the collection includes skills shared with you by other users. Turn off to exclude shared skills. |

These toggles are set independently on each collection. Your drive
key always includes all sources. Use these toggles when you want a
collection that only exposes your personal skills — for example, to
keep a client-specific key isolated from team or shared content.

## Managing collections via your agent

Your AI agent can also create and manage collections through
natural conversation. This is handy for quick adjustments without
opening the dashboard.

| What you say | What happens |
|--------------|-------------|
| "Create a collection called Data Science with my CSV and visualization skills" | Agent creates a new API key scoped to those skills |
| "Add the regression skill to my Data Science collection" | Agent adds the skill to the existing collection |
| "Remove CSV parser from Data Science" | Agent removes the skill from the collection |
| "Rename my Data Science collection to ML & Analytics" | Agent renames the collection |
| "Disable team skills on my Data Science collection" | Agent sets `includeTeamSkills` to false |

The agent uses these MCP tools:

- `skills_listCollections` — list owned collections (all-skills keys only).
- `skills_createCollection(name, skillSlugs?, includeTeamSkills?, includeSharedSkills?)`.
- `skills_updateCollection(collectionName, newName?, includeTeamSkills?, includeSharedSkills?)`.
- `skills_addToCollection(collectionName, skillSlug)` — single slug, not array.
- `skills_removeFromCollection(collectionName, skillSlug)` — single slug, not array.

Collections with `allowed_skill_ids=null` (all skills) reject
add/remove operations.

## Next steps

- [Teams](https://www.skillzdrive.com/docs/guides/teams.md): shared skill libraries for groups.
- [Sharing](https://www.skillzdrive.com/docs/guides/sharing.md): share individual skills with specific users.
- [Discovering skills](https://www.skillzdrive.com/docs/guides/discovering-skills.md).

<!-- END https://www.skillzdrive.com/docs/guides/collections -->

<!-- BEGIN https://www.skillzdrive.com/docs/guides/connecting -->

# Connecting an MCP Client

> Markdown variant of <https://www.skillzdrive.com/docs/guides/connecting>.

Transport options, session management, and platform-specific setup.

## Transport options

| Transport | How to connect | Best for |
|-----------|----------------|----------|
| Streamable HTTP | `POST /api/mcp` with `Accept: text/event-stream` | Claude Code, Claude Desktop, modern MCP clients |
| JSON-only HTTP | `POST /api/mcp` without SSE Accept header | ChatGPT, simple HTTP clients, REST-style integrations |
| Legacy SSE | `GET /api/mcp/sse` → receives endpoint → `POST /message?sessionId=` | Older MCP clients using separated SSE pattern |

Use Streamable HTTP. It's the modern MCP transport and what most
clients use by default.

## Streamable HTTP details

The Streamable HTTP transport uses a single endpoint with different
HTTP methods:

- **`POST /api/mcp`** — send JSON-RPC messages. If the client includes `Accept: text/event-stream`, the response uses SSE format.
- **`GET /api/mcp`** — open an SSE stream for server-initiated messages and notifications.
- **`DELETE /api/mcp`** — terminate a session. Include the `MCP-Session-Id` header.

## Session tracking

The server generates a session ID when you send the `initialize`
request. It's returned in the `MCP-Session-Id` response header.
Include this header in all subsequent requests to maintain your
session.

```http
MCP-Session-Id: <uuid>
```

## CORS configuration

The server sets these CORS headers to support browser-based and
cross-origin clients:

```http
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Accept, MCP-Session-Id, MCP-Protocol-Version
Access-Control-Expose-Headers: MCP-Session-Id
```

Localhost origins are allowed in development for local testing.

## Platform connection guide

| Platform | Config location | Transport |
|----------|-----------------|-----------|
| Claude.ai | Project settings → Integrations → Add MCP Server | Streamable HTTP |
| Claude Code | `~/.claude.json` or `.mcp.json` | Streamable HTTP |
| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) | Streamable HTTP |
| Cursor | `~/.cursor/mcp.json` or `.cursor/mcp.json` | Streamable HTTP |
| ChatGPT | Settings → Connectors → Developer mode | JSON-only HTTP |
| Custom agent | Your code (use MCP SDK) | Streamable HTTP |

## Minimal connection example

### TypeScript

```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const client = new Client({ name: "my-agent", version: "1.0.0" });

const transport = new StreamableHTTPClientTransport(
  new URL("https://www.skillzdrive.com/api/mcp"),
  { requestInit: { headers: { Authorization: "Bearer sk_live_YOUR_KEY" } } },
);

await client.connect(transport);
```

### Python

```python
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async with streamablehttp_client(
    "https://www.skillzdrive.com/api/mcp",
    headers={"Authorization": "Bearer sk_live_YOUR_KEY"},
) as (read_stream, write_stream, _):
    async with ClientSession(read_stream, write_stream) as session:
        await session.initialize()
```

## Protocol version

The `protocolVersion` field (e.g. `2024-11-05`) is the MCP
specification revision date, not the server version. The
SkillzDrive server supports:

- `2025-11-25`
- `2025-06-18`
- `2025-03-26`
- `2024-11-05`
- `2024-10-07`

## Next steps

- [Authentication](https://www.skillzdrive.com/docs/guides/authentication.md): API keys, Bearer tokens, OAuth flows.
- [Quickstart](https://www.skillzdrive.com/docs/quickstart.md): connect and run your first skill in 5 minutes.
- [Custom agent integration](https://www.skillzdrive.com/docs/agent-integration.md).

<!-- END https://www.skillzdrive.com/docs/guides/connecting -->

<!-- BEGIN https://www.skillzdrive.com/docs/mcp-basics -->

# MCP Basics

> Markdown variant of <https://www.skillzdrive.com/docs/mcp-basics>.

What is the Model Context Protocol and how does it work?

## What is MCP?

MCP (Model Context Protocol) is an open standard that lets AI
models interact with external tools and data sources through a
unified interface. It uses JSON-RPC 2.0 over HTTP, providing a
structured request/response pattern that any language or platform
can implement.

Think of it as a universal plugin system — any MCP-compliant client
can connect to any MCP-compliant server, regardless of who built
either side.

## How it works

```
Your Agent → MCP Client → SkillzDrive MCP Server → Skills
(AI model)   (SDK / lib)  (www.skillzdrive.com/api/mcp)  (scripts, docs, tools)
```

The MCP protocol defines three core concepts:

- **Tools** — functions the server exposes that clients can call. SkillzDrive provides 29 `skills_*` tools for skill discovery, documentation, script execution, and session management. This is the primary capability used by the SkillzDrive server.
- **Resources** — data the server provides that clients can read. SkillzDrive uses these for skill documentation TOCs and section content.
- **Prompts** — pre-built templates for common tasks. SkillzDrive doesn't use these.

## What you need

1. **An MCP client** — a library or built-in support in your platform. Claude.ai, Claude Code, Claude Desktop, Cursor, and ChatGPT all have MCP support built in. For custom agents, use an official SDK.
2. **A transport** — Streamable HTTP is recommended for remote servers like SkillzDrive. It's the modern MCP transport and what most clients use by default.
3. **Authentication** — a SkillzDrive API key, passed as a Bearer token in the `Authorization` header. Get one from <https://www.skillzdrive.com/dashboard/get-setup>.

## MCP client libraries

| Language | Package | Repo |
|----------|---------|------|
| TypeScript | `@modelcontextprotocol/sdk` | <https://github.com/modelcontextprotocol/typescript-sdk> |
| Python | `mcp` | <https://github.com/modelcontextprotocol/python-sdk> |
| Kotlin | `io.modelcontextprotocol:kotlin-sdk` | <https://github.com/modelcontextprotocol/kotlin-sdk> |
| C# | `ModelContextProtocol` | <https://github.com/modelcontextprotocol/csharp-sdk> |

## Official resources

- [MCP Specification](https://modelcontextprotocol.io/specification/2025-11-25) — the full protocol reference.
- [Build an MCP Client](https://modelcontextprotocol.io/docs/develop/build-client) — official tutorial.
- [MCP GitHub](https://github.com/modelcontextprotocol) — SDKs, examples, and the spec itself.

You don't need to understand the full MCP spec. SkillzDrive uses
standard MCP — any compliant client works out of the box.

## Next steps

- [Quickstart](https://www.skillzdrive.com/docs/quickstart.md): connect and run your first skill in 5 minutes.
- [Connecting](https://www.skillzdrive.com/docs/guides/connecting.md): transport options, session management, platform-specific setup.
- [Custom agent integration](https://www.skillzdrive.com/docs/agent-integration.md).

<!-- END https://www.skillzdrive.com/docs/mcp-basics -->

<!-- BEGIN https://www.skillzdrive.com/docs/rest-api -->

# REST API

> Markdown variant of <https://www.skillzdrive.com/docs/rest-api>.

HTTP + JSON access to the SkillzDrive catalog, drives, collections,
uploads, and executions. Use from any language that can speak HTTP —
no MCP client required.

If you're building an *agent* that calls skills, use
[the MCP interface](https://www.skillzdrive.com/docs/agent-integration.md)
instead — it's purpose-built for that. The REST API is for web apps,
mobile backends, CI pipelines, internal tools, and any 3rd-party
product that wants to manage SkillzDrive accounts programmatically.

## Base URL

```
https://www.skillzdrive.com/api/v1
```

Every endpoint is prefixed by this base URL. Responses are JSON.
Errors follow a consistent envelope (see below).

## Authentication

Most endpoints require a SkillzDrive API key. Pass it as a Bearer
token:

```
Authorization: Bearer sk_live_<your-key>
```

Create keys at <https://www.skillzdrive.com/dashboard/get-setup>.
Keys come in two flavors:

| Key type | Scope | Use when |
|----------|-------|----------|
| All-skills | Full drive + team + shared | Account owner; admin tools |
| Scoped collection | Subset named by `allowed_skill_ids` | Per-end-user keys; sub-account-style partner integrations |

### Anonymous access

A few public read endpoints work without any key — handy for
discovery-only clients. Anonymous requests are rate-limited to **1
request per minute per IP** and should include an install-id header
for soft identity:

```
X-Skillzdrive-Install-Id: <a-uuid-you-generate-once>
```

Anonymous-capable endpoints are marked `Anonymous: ✓` in the
[endpoint reference](https://www.skillzdrive.com/docs/rest-api/endpoints.md).

## Response shape

Successful responses carry a `data` key. Errors carry an `error`
object with a stable machine code and a human-readable message.

### Success

```json
{
  "data": {
    "collections": [
      { "name": "default", "scope": "all_skills", "skillCount": "all" },
      { "name": "acme-team", "scope": "scoped", "skillCount": 12 }
    ],
    "count": 2
  }
}
```

### Error

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Anonymous rate limit hit (1/min). Sign up free for unlimited access.",
    "retry_after_seconds": 53,
    "upgrade_url": "https://www.skillzdrive.com/signup?ref=cli-rate-limit"
  }
}
```

## HTTP status codes

| Status | Meaning | Typical error codes |
|--------|---------|---------------------|
| 200/201 | Success | — |
| 302 | Redirect to signed download URL | — |
| 400 | Bad request body | `invalid_json` |
| 401 | Auth required or invalid key | `auth_required`, `invalid_api_key`, `api_key_expired` |
| 403 | Forbidden (scope / quota / account) | `forbidden`, `scope_forbidden`, `account_inactive` |
| 404 | Not found | `not_found`, `method_not_found` |
| 409 | Conflict | `conflict`, `install_id_conflict` |
| 422 | Validation failed | `missing_required`, `invalid_params`, `invalid_sort_by` |
| 429 | Rate limit or quota hit | `rate_limit_exceeded`, `quota_exceeded`, `call_limit_reached` |
| 500 | Server error | `internal_error`, `render_failed` |
| 502 | MCP backend unreachable | `mcp_unreachable` |

## Your first call

Search the public catalog anonymously — zero signup required:

```bash
curl -H "X-Skillzdrive-Install-Id: $(uuidgen)" \
     "https://www.skillzdrive.com/api/v1/skills?q=weather"
```

```js
const res = await fetch(
  "https://www.skillzdrive.com/api/v1/skills?q=weather",
  { headers: { "X-Skillzdrive-Install-Id": crypto.randomUUID() } },
);
const { data } = await res.json();
console.log(data.skills);
```

```python
import requests, uuid
res = requests.get(
    "https://www.skillzdrive.com/api/v1/skills",
    params={"q": "weather"},
    headers={"X-Skillzdrive-Install-Id": str(uuid.uuid4())},
)
print(res.json()["data"]["skills"])
```

List the collections on your account (authenticated):

```bash
curl -H "Authorization: Bearer sk_live_..." \
     "https://www.skillzdrive.com/api/v1/collections"
```

## Architectural note

Every endpoint except the anonymous read/download/marketplace paths
forwards internally to a single MCP server. That means permission,
quota, collection filtering, and usage-logging semantics are
bit-identical to the MCP protocol — a REST call and an equivalent
MCP `tools/call` do the same thing.

## Keep reading

- [Endpoint reference](https://www.skillzdrive.com/docs/rest-api/endpoints.md): every route, grouped by resource.
- [Webhooks](https://www.skillzdrive.com/docs/rest-api/webhooks.md): credit-alert webhook subscriptions, HMAC verification.
- [CLI](https://www.skillzdrive.com/docs/cli.md): thin client over this API.

<!-- END https://www.skillzdrive.com/docs/rest-api -->

<!-- BEGIN https://www.skillzdrive.com/docs/rest-api/endpoints -->

# REST API endpoint reference

> Markdown variant of <https://www.skillzdrive.com/docs/rest-api/endpoints>.

Every v1 REST route, grouped by resource. All paths are relative to
`https://www.skillzdrive.com`. See the
[REST API overview](https://www.skillzdrive.com/docs/rest-api.md) for
authentication, response shape, and HTTP status codes.

Auth tags below:

- **Auth required** — must present a `Bearer sk_live_…` token.
- **Anonymous ✓** — works without a token (rate limited).
- **Internal only** — service-to-service; not part of the public surface.

## Skills

Search and discover skills from the public marketplace or the
caller's scoped catalog.

### `GET /api/v1/skills` — Anonymous ✓

List or search skills. With `?q=`, full-text searches
name/description/slug. Without, lists everything accessible to the
caller.

Query params:

- `q` — search query (required for anonymous).
- `limit` — max results (default 20, cap 50).
- `collection` — filter to a named collection (auth-only).

```bash
curl "https://www.skillzdrive.com/api/v1/skills?q=pdf&limit=5" \
     -H "X-Skillzdrive-Install-Id: $(uuidgen)"
```

### `GET /api/v1/skills/:slug` — Anonymous ✓

One skill by slug. Response includes `download` with the latest
content-addressed artifact URL when the skill has one (populated
after publish + backfill).

```jsonc
{
  "data": {
    "skill": {
      "id": "...",
      "slug": "pdf",
      "name": "PDF tools",
      "description": "...",
      "tags": ["document", "pdf"],
      "version": 3,
      "github_url": null,
      "category": "public"
    },
    "download": {
      "content_sha": "abc123...",
      "content_size": 45213,
      "version": 3,
      "url": "/api/v1/downloads/public/pdf/abc123....zip"
    }
  }
}
```

### `GET /api/v1/skills/discover` — Auth required

Broad discovery across marketplace + cached GitHub sources.
Paginated (10 results per page).

- `keywords` — required.
- `offset` — for pagination.

### `GET /api/v1/skills/leaderboard` — Auth required

Top public skills.

- `sort_by` — `executions` (default), `installs`, or `rating`.

## Drive

Manage the authenticated user's hosted drive — the set of skills
available to their API keys.

### `GET /api/v1/drive` — Auth required

List all accessible skills (drive ∪ team ∪ shared, filtered by the
key's `allowed_skill_ids`).

### `POST /api/v1/drive/import` — Auth required

Import a marketplace skill or GitHub URL into the drive.

```json
{ "skillSlug": "pdf" }
```

Accepts either a marketplace slug or a GitHub URL
(`https://github.com/owner/repo/tree/main/subpath`).

### `DELETE /api/v1/drive/:slug` — Auth required

Remove a skill from the drive.

### `POST /api/v1/drive/:slug/toggle` — Auth required

Flip the enabled state without removing.

### `GET /api/v1/drive/updates` — Auth required

List pending version updates for skills in the drive.

### `POST /api/v1/drive/updates/:slug/accept` — Auth required

Accept an update — may charge credits per existing pricing rules.

### `POST /api/v1/drive/updates/:slug/dismiss` — Auth required

Dismiss a pending update; no charge.

### `POST /api/v1/drive/sync/preview` — Auth required

Dry-run classification for a `skillzdrive sync` invocation. Tells
the caller, per-skill, what action would happen and how much it
would cost. Mutates no state.

### `POST /api/v1/drive/sync/execute` — Auth required

Server-side commit step. Re-validates classifications, executes
`claim_public` atomically, returns deferred upload/download
instructions for the CLI. Opens a row in `cli_sync_runs`.

```json
{
  "install_id": "uuid-from-cli",
  "kind": "first_run",
  "mode": "all",
  "classifications": [/* from sync/preview */]
}
```

`kind`: `first_run` | `daily` | `manual`.
`mode`: `all` | `public_only` | `pulls_only` | `as_many_as_credits_allow`.

Response includes a `run_id` and per-skill `results` listing the
action committed (e.g. `claim_public`, `upload_private`,
`download_install`) and any deferred upload/download instructions.

### `POST /api/v1/drive/sync/finalize` — Auth required

Closes the audit row. Sets
`users.drive_grandfather_high_water` on first run. Returns
post-sync drive count + watermark.

### `POST /api/v1/drive/diff` — Auth required

Lightweight three-way diff between local lockfile state and the
hosted drive. Drives the once-daily sync-divergence prompt.

```json
{
  "local": [{ "slug": "pdf-fill", "content_sha": "abc..." }]
}
```

Response classifies each skill as `local_only`, `drive_only`, or
`divergent` (with both shas).

## Collections

A collection is a named API key that scopes access to a subset of
the owner's drive. Partners use this pattern to give each of their
users a private slice of a master account.

### `GET /api/v1/collections` — Auth required

List the owner's collections. **Restricted:** only usable with an
all-skills key.

### `POST /api/v1/collections` — Auth required

Create a collection. Omit `skillSlugs` for an all-skills key.
Response returns the generated `sk_live_*` key exactly once.

```json
{
  "name": "acme-user-42",
  "skillSlugs": ["pdf", "docx-to-pdf"],
  "includeTeamSkills": true,
  "includeSharedSkills": true
}
```

### `PATCH /api/v1/collections/:name` — Auth required

Rename or reconfigure. Pass only the fields you want to change.

```json
{
  "newName": "acme-user-42-renamed",
  "skillSlugs": ["pdf"],
  "isPublicMarketplace": true
}
```

Setting `isPublicMarketplace: true` exposes the collection at
`/marketplace/collections/:name.json` — see the Marketplace section.

### `POST /api/v1/collections/:name/skills` — Auth required

Add a skill to the collection.

```json
{ "skillSlug": "pdf" }
```

### `DELETE /api/v1/collections/:name/skills/:slug` — Auth required

Remove a skill from the collection.

### `DELETE /api/v1/collections/:name` — Auth required

Delete the collection itself and revoke its API key. Irreversible.
**Restricted:** only usable with an all-skills key — scoped keys
cannot delete collections, including their own.

## Uploads

### `POST /api/v1/uploads/ticket` — Auth required

Mint a short-lived (10-minute, single-use) upload token. Response
includes the token itself plus an inline bash script for local
upload flows.

```json
{
  "collectionName": "acme-user-42",
  "filename": "my-skill.zip"
}
```

To upload, POST `multipart/form-data` with `file=@path/to/skill.zip`
and `Authorization: Bearer <ticket>` to
`/api/uploads/process-skill`.

### `POST /api/v1/uploads/url` — Auth required

Returns the canonical upload URL for browser-based flows.

## Downloads

### `POST /api/v1/downloads` — Auth required

Dynamically package skills into a zip and return a 24-hour signed
URL. Use for drive-wide or collection-wide exports, or one-off
bundling of a skill the caller doesn't have in their drive.

```json
{
  "scope": "drive",
  "collectionName": "acme-user-42",
  "skillSlug": "pdf"
}
```

`scope`: `drive` | `collection` | `skill`.

### `GET /api/v1/downloads/public/:slug/:sha.zip` — Anonymous ✓

**Content-addressed, immutable.** Redirects (302) to a signed
Supabase Storage URL for the exact zip bytes matching `:sha`. Cache
forever — these URLs never change.

```bash
curl -L "https://www.skillzdrive.com/api/v1/downloads/public/pdf/abc123...zip" \
     -o pdf.zip
```

## Runs

### `POST /api/v1/runs` — Auth required

Execute a skill script in the hosted E2B sandbox. Blocking
response — returns when the script finishes. Consumes credits per
the skill's `credit_cost_per_use`.

```json
{
  "skillSlug": "pdf",
  "scriptName": "extract.sh",
  "args": ["input.pdf"],
  "stdin": "",
  "sessionId": null,
  "reuseSession": false
}
```

Response:

```json
{
  "data": {
    "stdout": "...",
    "stderr": "",
    "exit_code": 0,
    "sessionId": "...",
    "duration_ms": 1420
  }
}
```

## Account

### `GET /api/v1/account/credits` — Auth required

Current credit balance, tier, monthly skill-call usage + limit, and
the 10 most recent transactions. Returns
`monthly_skill_call_limit: "unlimited"` for admin/moderator roles.

### `GET /api/v1/account/webhooks` — Auth required

List configured webhook subscriptions — see
[the dedicated Webhooks page](https://www.skillzdrive.com/docs/rest-api/webhooks.md).

### `POST /api/v1/account/webhooks` — Auth required

Create a webhook subscription.

### `DELETE /api/v1/account/webhooks/:id` — Auth required

Delete a webhook subscription.

## Marketplace

Public `.claude-plugin/marketplace.json`-compatible manifests.
Consumable by Anthropic Claude Code (`/plugin marketplace add <url>`)
and GitHub Copilot CLI
(`copilot plugin marketplace add <url>`).

### `GET /marketplace.json` — Anonymous ✓

The global public catalog. Every public+approved skill with a
downloadable source (artifact or GitHub). Cached 5 minutes.

```bash
# Then in Claude Code:
/plugin marketplace add https://www.skillzdrive.com/marketplace.json
```

### `GET /marketplace/collections/:name.json` — Anonymous ✓

Curated per-collection manifest. Returns 404 unless the collection
was published with `isPublicMarketplace: true` (see PATCH
Collections).

## Telemetry + migration

### `POST /api/v1/telemetry/anonymous` — Anonymous ✓

Record a CLI command event. Mandatory per product terms — no
opt-out — but the payload is entirely anonymized until a user logs
in and claims their install_id.

```json
{
  "install_id": "uuid-v4",
  "event_type": "install",
  "cli_version": "0.1.0",
  "os": "darwin/arm64",
  "skill_slugs": ["pdf", "docx"],
  "source_types": ["skillzdrive"],
  "metadata": { "installed": 2, "failed": 0 }
}
```

`event_type`: `install` | `sync` | `update` | `audit` | `scan` |
`init_defaults` | `login`.

### `POST /api/v1/migrations/anonymous-adopt` — Auth required

Claim an anonymous install_id for the authenticated user on first
login. Backfills any prior anonymous telemetry under that install_id
to the user's account. Idempotent. Returns 409 if another account
has already claimed that install_id.

```json
{ "install_id": "uuid-v4" }
```

<!-- END https://www.skillzdrive.com/docs/rest-api/endpoints -->

<!-- BEGIN https://www.skillzdrive.com/docs/rest-api/webhooks -->

# Webhooks

> Markdown variant of <https://www.skillzdrive.com/docs/rest-api/webhooks>.

Get notified when your account's credit balance crosses a threshold —
so partner systems can alert end-users before service stops.

Partners running a master SkillzDrive account on behalf of their
users need advance warning when credits are running low. Polling is
expensive and laggy; webhooks push a signed notification the moment
the balance crosses a threshold you picked.

## Event catalog

| event_type | Fires when | Uses `threshold_value`? |
|------------|-----------|-------------------------|
| `credits.threshold_hit` | Balance crosses downward from above `threshold_value` to at-or-below. | Required |
| `credits.exhausted` | Balance hits 0. | Ignored |

Each subscription fires **once per downward crossing**. If the
balance recovers (e.g. you top up) and crosses the threshold again
later, it fires again. It does not fire while the balance stays
below the threshold.

## Create a subscription

Use the REST API or the CLI. The response contains a **signing
secret shown exactly once** — save it now.

```bash
curl -X POST https://www.skillzdrive.com/api/v1/account/webhooks \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "credits.threshold_hit",
    "threshold_value": 500,
    "target_url": "https://example.com/hooks/skillzdrive"
  }'
```

CLI equivalent:

```bash
skillzdrive webhooks create \
  --event credits.threshold_hit \
  --threshold 500 \
  --url https://example.com/hooks/skillzdrive
```

JavaScript:

```js
const res = await fetch("https://www.skillzdrive.com/api/v1/account/webhooks", {
  method: "POST",
  headers: {
    authorization: "Bearer " + process.env.SKILLZDRIVE_API_KEY,
    "content-type": "application/json",
  },
  body: JSON.stringify({
    event_type: "credits.threshold_hit",
    threshold_value: 500,
    target_url: "https://example.com/hooks/skillzdrive",
  }),
});
const { data } = await res.json();
// SAVE data.secret NOW — it won't be returned again.
```

## Delivery format

Deliveries are HTTP `POST` with JSON body.

```http
POST https://example.com/hooks/skillzdrive
Content-Type: application/json
X-Skillzdrive-Event: credits.threshold_hit
X-Skillzdrive-Signature: sha256=<hmac-sha256 of raw body using your secret, hex>
```

```json
{
  "event": "credits.threshold_hit",
  "owner_user_id": "00000000-0000-0000-0000-000000000000",
  "credits_remaining": 487,
  "threshold": 500,
  "timestamp": "2026-04-22T03:15:42.000Z"
}
```

### Timeouts and delivery semantics

- Delivery timeout: **5 seconds**. Slower targets are treated as failed.
- At-most-once: failed deliveries are *not* retried in v1 (we log the HTTP status in `last_delivery_status`). Build your receiver to be idempotent anyway.
- No ordering guarantees.

## Verify signatures

Compute HMAC-SHA256 of the **raw request body** using your
subscription secret, hex-encode it, prefix with `sha256=`, and
constant-time compare against the `X-Skillzdrive-Signature` header.

### Node.js

```js
import { createHmac, timingSafeEqual } from "crypto";

function verifySkillzDriveSignature(rawBody, secret, headerValue) {
  const expected = "sha256=" +
    createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(headerValue);
  if (a.length !== b.length) return false;
  return timingSafeEqual(a, b);
}

// Express example — must use raw body
app.post("/hooks/skillzdrive",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const ok = verifySkillzDriveSignature(
      req.body,
      process.env.SKILLZDRIVE_WEBHOOK_SECRET,
      req.header("x-skillzdrive-signature") ?? "",
    );
    if (!ok) return res.status(401).end();
    const event = JSON.parse(req.body.toString());
    // ...handle event...
    res.status(200).end();
  });
```

### Python

```python
import hmac, hashlib

def verify_skillzdrive_signature(raw_body: bytes, secret: str, header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header)
```

### Ruby

```ruby
require "openssl"

def verify_skillzdrive_signature(raw_body, secret, header)
  expected = "sha256=" + OpenSSL::HMAC.hexdigest("sha256", secret, raw_body)
  ActiveSupport::SecurityUtils.secure_compare(expected, header)
end
```

**Verify the raw body**: signature verification depends on the exact
bytes we signed. Parse the header *before* JSON-decoding the body,
and feed the untouched `Buffer`/`bytes` to your HMAC. Frameworks
that silently re-encode JSON will break signatures.

## List and delete

```bash
# List
curl -H "Authorization: Bearer sk_live_..." \
     https://www.skillzdrive.com/api/v1/account/webhooks

# Delete
curl -X DELETE -H "Authorization: Bearer sk_live_..." \
     https://www.skillzdrive.com/api/v1/account/webhooks/<id>

# CLI equivalents
skillzdrive webhooks list
skillzdrive webhooks delete <id>
```

<!-- END https://www.skillzdrive.com/docs/rest-api/webhooks -->

<!-- BEGIN https://www.skillzdrive.com/docs/cli -->

# SkillzDrive CLI

> Markdown variant of <https://www.skillzdrive.com/docs/cli>.

One command installs, manages, and runs agent skills anywhere.
Anonymous by default — signup only when you need to publish, execute
hosted skills, or sync a personal drive.

## Install

```bash
# No install
npx skillzdrive --help

# Global
npm install -g skillzdrive
skillzdrive --help
```

Requires Node.js ≥20. Stores credentials in the OS keychain (macOS
Keychain, Windows Credential Manager, libsecret on Linux) with a
0600-permission file fallback.

## First run — anonymous

Works in any empty directory:

```bash
# Browse the public catalog
skillzdrive search weather

# Inspect a skill before installing
skillzdrive show pdf

# Install directly from GitHub
skillzdrive install github:anthropics/skills/skills/docx

# See what's installed locally
skillzdrive list
```

## First run — authenticated

Sign in for hosted installs, collections, execution, and webhooks:

```bash
# Paste your sk_live_* key from the dashboard
skillzdrive login --token sk_live_...

# Sync your entire hosted drive to local
skillzdrive sync

# Run a skill in the hosted sandbox
skillzdrive run pdf extract.sh -- input.pdf

# Check your credit balance
skillzdrive credits
```

## The drive model

The CLI keeps a single canonical copy of each skill in
`~/.skillzdrive/drive/` and symlinks that copy into each project's
per-agent directory. One skill on disk, many agent-view symlinks,
zero duplication.

```
~/.skillzdrive/
├── drive/
│   ├── pdf/                      # canonical copy — one per skill
│   │   ├── SKILL.md
│   │   ├── scripts/
│   │   └── .skillzdrive-meta.json
│   └── docx/
├── install_id                     # anonymous telemetry identity
└── cache/                          # content-addressed zip cache

~/project-a/
├── .claude/skills/pdf  → symlink → ~/.skillzdrive/drive/pdf
├── .codex/skills/pdf   → symlink → ~/.skillzdrive/drive/pdf
└── skillzdrive.lock.json           # pinned SHAs for reproducibility

~/project-b/
└── .agent/skills/pdf   → symlink → ~/.skillzdrive/drive/pdf
```

**Agent auto-detection**: run `skillzdrive install <slug>` without
`--agents` and the CLI symlinks into every agent dir already present
in the project (`.claude/`, `.codex/`, `.gemini/`, `.agents/`).
Falls back to `.agent/skills/` (the cross-agent convention) if none
detected.

## Reproducible installs

Every install writes a `skillzdrive.lock.json` at the project root
with the exact content SHA. Commit it, and your team + CI can
rebuild byte-identical installs:

```bash
# Fresh checkout
skillzdrive install --frozen
skillzdrive audit           # verifies presence + server drift, exits non-zero on missing skills
```

## Anonymous limits

Anonymous mode exists so you can try the CLI with zero friction —
but it's deliberately narrow. You hit signup pressure exactly when
you ask for something only an account can do.

| Capability | Anonymous | Authenticated |
|------------|-----------|---------------|
| Install public skills | 10 total | Per tier |
| Install `github:` skills | ✓ | ✓ |
| Install local skills (BYO) | ✓ | ✓ |
| Search the catalog | 1/min rate-limited | 600/min |
| Run hosted executions | — | ✓ (per tier) |
| Upload / publish | — | ✓ |
| Collections + teams | — | ✓ |
| Webhooks | — | ✓ |
| Credits | — | ✓ |

## Telemetry

The CLI sends anonymous telemetry on `install`, `sync`, `update`,
`audit`, `scan`, and `init`. It contains your install_id UUID
(generated on first run and stored at
`~/.skillzdrive/install_id`), the CLI version, OS string, and the
slugs of skills you operated on. No PII.

When you log in, the CLI claims the install_id for your account so
you get security alerts for skills you previously installed
anonymously.

## See also

- [Full command reference](https://www.skillzdrive.com/docs/cli/reference.md): every command + flag, with examples.
- [REST API](https://www.skillzdrive.com/docs/rest-api.md): the CLI is a thin client over this HTTP API.

<!-- END https://www.skillzdrive.com/docs/cli -->

<!-- BEGIN https://www.skillzdrive.com/docs/cli/reference -->

# CLI command reference

> Markdown variant of <https://www.skillzdrive.com/docs/cli/reference>.

Every `skillzdrive` command. Grouped by purpose. Auth tags:

- **Anonymous ✓** — works without `skillzdrive login`.
- **Auth required** — must be logged in (or pass `SKILLZDRIVE_API_KEY=...`).

## Global flags + environment

- `SKILLZDRIVE_API_BASE` — override API host. Defaults to `https://www.skillzdrive.com`.
- `~/.skillzdrive/install_id` — per-machine UUID sent as `X-Skillzdrive-Install-Id`. Generated on first run.
- `--help` / `-h` — on any command.
- `--version` / `-V` — print CLI version.

## Discover

### `skillzdrive search <query>` — Anonymous ✓

Search the public catalog. Anonymous requests rate-limited to 1/min.

```bash
skillzdrive search pdf
skillzdrive search "document" --limit 10
```

Flags: `--limit <n>` (default 20, cap 50).

### `skillzdrive show <slug>` — Anonymous ✓

Print metadata + download info for a single public skill.

### `skillzdrive discover <keywords>` — Auth required

Broader search across marketplace + GitHub, paginated 10 per page.

```bash
skillzdrive discover pdf
skillzdrive discover document --offset 10
```

### `skillzdrive leaderboard` — Auth required

Top 10 skills by the chosen sort dimension. Flags:
`--sort-by executions|installs|rating` (default `executions`).

## Local drive (canonical + symlinks)

Manage what's on this machine and linked into this project. No
server state.

### `skillzdrive install <source>` — Anonymous ✓

Install a skill into the canonical drive and symlink into this
project.

```bash
# By slug (uses SkillzDrive hosted artifact if available)
skillzdrive install pdf

# Direct GitHub
skillzdrive install github:anthropics/skills/skills/docx
skillzdrive install https://github.com/foo/bar

# Local path (BYO)
skillzdrive install ./my-skill

# Reinstall from the project's lockfile
skillzdrive install --frozen
```

Flags: `--agents claude,codex,gemini,goose,universal` (auto-detected
if omitted), `--frozen`.

### `skillzdrive list` / `ls` — Anonymous ✓

List canonical-drive skills.

### `skillzdrive remove <slug>` / `rm` — Anonymous ✓

Remove the canonical copy (symlinks in projects become dangling —
clean up with `unlink`).

### `skillzdrive link <slug>` — Anonymous ✓

Symlink an already-installed drive skill into this project without
re-downloading.

```bash
skillzdrive link pdf --agents claude,codex
```

### `skillzdrive unlink <slug>` — Anonymous ✓

Remove this project's symlinks for a drive skill. Canonical copy
untouched.

### `skillzdrive scaffold [name]` — Anonymous ✓

Create a new skill author project in `./<name>/` following the
agentskills.io spec.

```bash
skillzdrive scaffold my-new-skill
# → ./my-new-skill/{SKILL.md, scripts/hello.sh, references/, README.md}
```

## Auth + account

### `skillzdrive login` — Anonymous ✓

Store your API key in the OS keychain + claim your anonymous
install_id for this account.

```bash
skillzdrive login --token sk_live_...
# Without --token, prompts interactively.
```

### `skillzdrive logout` — Anonymous ✓

Clear the stored API key.

### `skillzdrive whoami` — Anonymous ✓

Print install_id + auth status + (if authenticated) a round-trip
key check.

### `skillzdrive credits` — Auth required

Balance, tier, monthly skill-call usage + limit, last 10
transactions.

## Workflows

### `skillzdrive sync` — Auth required

Pull your entire hosted drive into the canonical local drive.
Installs new, updates changed, skips unchanged.

### `skillzdrive init --defaults` — Anonymous ✓

Pull the SkillzDrive recommended starter set into this project.
Zero signup.

```bash
skillzdrive init --defaults
skillzdrive init --defaults --agents claude,codex
```

### `skillzdrive update [slugs...]` — Auth required

Re-fetch latest artifacts for listed skills, or all lockfile
entries if none given.

```bash
skillzdrive update                # all lockfile entries
skillzdrive update pdf docx
```

### `skillzdrive audit` — Auth required

Verify every lockfile entry is present on disk + check server for
updates. Non-zero exit only on missing skills.

### `skillzdrive run <slug> <script> [args...]` — Auth required

Execute a skill script in the hosted E2B sandbox. Blocking — prints
stdout/stderr on completion.

```bash
skillzdrive run pdf extract.sh -- input.pdf output.txt

# With stdin
skillzdrive run pdf process.sh --stdin "some input"

# Persistent sandbox session across calls
skillzdrive run pdf init.sh --reuse
skillzdrive run pdf step2.sh --session-id <from-previous-call>
```

Flags: `--stdin <str>`, `--session-id <id>`, `--reuse`.

## `drive` subcommand — hosted drive

```bash
skillzdrive drive list                 # list hosted drive
skillzdrive drive list --collection X  # filter to named collection
skillzdrive drive add <slug>           # import a marketplace skill or GitHub URL
skillzdrive drive remove <slug>        # remove from hosted drive
skillzdrive drive toggle <slug>        # flip enabled flag without removing
```

## `updates` subcommand

```bash
skillzdrive updates list               # pending updates for your drive
skillzdrive updates accept <slug>      # apply the update (may charge credits)
skillzdrive updates dismiss <slug>     # dismiss; no charge
```

## `collections` subcommand

A collection is a named API key that scopes a subset of your drive.
Publish one as a public marketplace to share with end-users.

```bash
skillzdrive collections list
skillzdrive collections create <name>                        # all-skills collection
skillzdrive collections create <name> --skills pdf,docx      # scoped collection
skillzdrive collections create <name> --skills pdf --include-team --include-shared
skillzdrive collections update <name> --rename <newName>
skillzdrive collections update <name> --skills pdf,docx      # replace skill list
skillzdrive collections add <name> <slug>                    # add one skill
skillzdrive collections remove <name> <slug>                 # remove one skill
skillzdrive collections publish-marketplace <name>           # expose as /marketplace/collections/<name>.json
skillzdrive collections publish-marketplace <name> --unpublish
```

`create` prints the generated `sk_live_*` for the new collection
exactly once — save it. That's the key the collection's end-user
will use to access only the scoped subset of your drive.

## `webhooks` subcommand

Credit-alert webhook subscriptions. See the
[Webhooks guide](https://www.skillzdrive.com/docs/rest-api/webhooks.md)
for payload + verification details.

```bash
skillzdrive webhooks list
skillzdrive webhooks create \
  --event credits.threshold_hit \
  --url https://example.com/hooks/skillzdrive \
  --threshold 500
skillzdrive webhooks create \
  --event credits.exhausted \
  --url https://example.com/hooks/skillzdrive
skillzdrive webhooks delete <id>
```

## Authoring + info

### `skillzdrive upload <path>` — Auth required

Upload a local `.zip` or `.skill` file to your drive. Replicates
the upload-ticket flow inline — no bash, no shell-history token
exposure.

```bash
skillzdrive upload ./my-skill.zip
skillzdrive upload ./my-skill.zip --collection acme-team
```

### `skillzdrive scan [slug]` — Anonymous ✓

Info about SkillzDrive's server-side security scans. Anonymous
mode is an upsell prompt; authenticated mode points at your
dashboard.

## Exit codes

| Code | Meaning |
|------|---------|
| 0 | Success. |
| 1 | Generic failure (API error, validation, missing files, SHA mismatch, etc.). Inspect stderr for the error code. |
| `<script exit>` | `run` returns the script's exit code when the server reports one. |

Structured errors print to stderr with `Error [code]: message` plus
an upsell URL when applicable. Pipe `2>` to capture.

<!-- END https://www.skillzdrive.com/docs/cli/reference -->

<!-- BEGIN https://www.skillzdrive.com/docs/reference/tools -->

# MCP Tools Reference

> Markdown variant of <https://www.skillzdrive.com/docs/reference/tools>.

The MCP server exposes a single namespace of tools, all prefixed
`skills_`. Tools are gated by auth and by whether the caller's
filtered skill set contains any executable scripts —
script-execution tools are omitted from `tools/list` when no allowed
skill has a script.

Auth tiers (the bearer presented to the MCP endpoint):

- **anonymous** — no key; only available when the server is started with `REQUIRE_API_KEY=false` (development).
- **authenticated** — any valid `sk_live_*` API key. Most tools.
- **scoped** — same as authenticated but the key has a non-null `allowed_skill_ids` (a "collection"). Some management tools reject scoped keys.
- **upload-only keys** — rejected by the MCP transport entirely.

There is no admin-tier MCP tool. Admin endpoints
(`/admin/reload-skills`, `/admin/apply-skill-deltas`,
`/admin/invalidate-auth-cache`, `/admin/debug-skills`) live on the
HTTP transport and require the `MCP_ADMIN_SECRET` header.

## Error response shape

Every error response includes structured fields:

```json
{
  "error": "skill_not_found",
  "message": "No skill with slug 'pdff'",
  "suggestions": ["Did you mean 'pdf'?", "Use skills_searchSkills to find skills"],
  "_workflow": {
    "nextSteps": [
      { "tool": "skills_searchSkills", "example": { "query": "pdf" } }
    ]
  }
}
```

- `error` — machine-readable code (e.g. `skill_not_found`, `script_not_found`, `access_denied`, `session_not_found`, `missing_credentials`, `quota_exceeded`).
- `message` — human-readable text. Show this to users.
- `suggestions` — array of recovery steps. Show the first one as an action.
- `_workflow.nextSteps` — what tool to call next for automatic recovery.

## Discovery

### `skills_getStarted`

Render the SkillzDrive welcome overview for the session. Returns
credits, current collection, trending skills, and quick actions.
Recommended as the first tool call.

- Auth: authenticated. Inputs: none.

### `skills_searchSkills`

Search skills by name, description, or tags within the caller's
allowed set.

- Auth: authenticated.
- Required: `query: string`.
- Optional: `limit: number` (default 10, max 50), `collectionName: string`.

### `skills_listSkills`

List all skills available to the caller with metadata (slug, name,
description, tags, `hasScripts`).

- Auth: authenticated.
- Optional: `tags: string[]`, `query: string`, `collectionName: string`.

### `skills_getSkill`

Single-skill lookup by slug. Honors `allowed_skill_ids` scope;
returns `not_found` when the slug isn't accessible to the caller.

- Auth: authenticated. Required: `slug: string`.

### `skills_getLeaderboard`

Top 10 public/premium skills over the last 30 days.

- Auth: authenticated.
- Optional: `sort_by: 'executions' | 'installs' | 'rating'` (default `executions`).

### `skills_discoverSkills`

Search the marketplace **and** the GitHub skill catalog. Each
result carries a `source: "marketplace" | "github"` field.
Paginated 10 per page.

- Auth: authenticated. Required: `keywords: string`.
- Optional: `offset: number` (default 0).

## Drive management

### `skills_importToDrive`

Import a skill (marketplace or GitHub) into the caller's drive.
Triggers download → security scan → doc enrichment. Charges import
credits. Long-running (1–2 min).

- Auth: authenticated. Required: `skillSlug: string`.

### `skills_removeFromDrive`

Remove a skill from the drive; rejects active shares and deletes
private copies.

- Auth: authenticated. Required: `skillSlug: string`.

### `skills_toggleDriveSkill`

Toggle a skill's `enabled` flag in `user_skill_lockers`.

- Auth: authenticated. Required: `skillSlug: string`.

### `skills_checkUpdates`

List pending skill updates with security-scan summaries.

- Auth: authenticated. Inputs: none.

### `skills_acceptUpdate`

Accept a pending update; pins the drive entry to the latest
version. Charges a small credit fee.

- Auth: authenticated. Required: `skillSlug: string`.

### `skills_dismissUpdate`

Dismiss a pending update; the drive entry stays on its current
pinned version. Free.

- Auth: authenticated. Required: `skillSlug: string`.

### `skills_downloadSkills`

Package skills as a zip and return a 24-hour signed Supabase URL.

- Auth: authenticated.
- Required: `scope: 'drive' | 'collection' | 'skill'`.
- Conditional: `collectionName` (when `scope='collection'`), `skillSlug` (when `scope='skill'`).

## Collections

A "collection" is a named, scoped API key. Both unscoped and scoped
callers can read collections; mutating tools generally require an
unscoped (all-skills) key.

### `skills_createCollection`

Mint a new scoped API key. Returns the `sk_live_*` once.

- Auth: authenticated, **unscoped only**.
- Required: `name: string`.
- Optional: `skillSlugs: string[]` (omit for all-skills), `includeTeamSkills: boolean` (default true), `includeSharedSkills: boolean` (default true).

### `skills_listCollections`

List collections owned by the account.

- Auth: authenticated, **unscoped only** (scoped keys get a permission error). Inputs: none.

### `skills_updateCollection`

Rename or toggle team/shared inclusion flags.

- Auth: authenticated, **unscoped only**.
- Required: `collectionName: string` (name or `sk_live_*`).
- Optional: `newName: string`, `includeTeamSkills: boolean`, `includeSharedSkills: boolean`.

### `skills_deleteCollection`

Delete a collection and revoke its API key. Irreversible.

- Auth: authenticated, **unscoped only** (scoped keys cannot delete, including their own).
- Required: `collectionName: string`.

### `skills_addToCollection`

Add a skill to a scoped collection. Single slug, not array.

- Auth: authenticated. Scoped keys operate on their own collection (the `collectionName` arg is ignored); unscoped callers must specify it.
- Required: `skillSlug: string`.
- Optional: `collectionName: string` (required for unscoped).

### `skills_removeFromCollection`

Remove a skill from a scoped collection. Same scoped/unscoped rules
as `addToCollection`.

- Auth: authenticated. Required: `skillSlug: string`.
- Optional: `collectionName: string`.

## Documentation

### `skills_docTOC`

Get the full table of contents for a skill's documentation.

- Auth: authenticated. Required: `skillSlug: string`.

### `skills_docSection`

Get the body of a specific documentation section.

- Auth: authenticated. Required: `skillSlug: string`, `sectionSlug: string`.

### `skills_getResourceInfo`

Metadata for a skill resource file (sections, token counts, type).

- Auth: authenticated. Required: `skillSlug: string`, `filePath: string`.

### `skills_readResourceContent`

Read a resource file's content (full or by section name). Blocked
for premium skills.

- Auth: authenticated. Required: `skillSlug: string`, `filePath: string`.
- Optional: `sectionName: string`.

## Scripts

These tools are only listed by `tools/list` if the caller has at
least one allowed skill with scripts.

### `skills_listScripts`

List executable scripts for one skill. **MUST call before `runScript`.**

- Auth: authenticated. Required: `skillSlug: string`.

### `skills_runScript`

Execute a script in an isolated E2B sandbox. Output is **not**
returned inline — read it via `skills_readFile`.

- Auth: authenticated.
- Required: `skillSlug: string`, `scriptName: string`.
- Optional: `args: string[]`, `stdin: string`, `sessionId: string`, `reuseSession: boolean` (default false; **always pass true** to enable readFile).

### `skills_readFile`

Read a file from an active session sandbox. Pass `closeAfter: true`
on the final read to release the session in the same call.

- Auth: authenticated. Required: `sessionId: string`, `filePath: string`.
- Optional: `startLine: number` (default 1), `limit: number` (default 200, max 500), `closeAfter: boolean` (default false).

### `skills_listOutputFiles`

List files in a sandbox directory.

- Auth: authenticated. Required: `sessionId: string`.
- Optional: `directory: string` (default `/tmp`), `closeAfter: boolean`.

### `skills_closeSession`

Close a session and free its sandbox. Sessions auto-expire after 5
minutes of inactivity.

- Auth: authenticated. Required: `sessionId: string`.

### `skills_getScript`

Return script metadata + a direct-storage signed download URL for
local execution.

- Auth: authenticated. Required: `skillSlug: string`, `scriptName: string`.

### `skills_getScriptStream`

Return script metadata + the script content **inline** in the tool
response (chunked). Used as a fallback when `skills_getScript`'s
download URL can't be fetched (sandboxed agents, large scripts).

- Auth: authenticated. Required: `skillSlug: string`, `scriptName: string`.

## Upload

### `skills_getUploadUrl`

Return the SkillzDrive website upload URL preconfigured for **this**
caller (embeds `key_id`/`key_name` so scoped keys land in the
caller's collection).

- Auth: authenticated. Inputs: none.

### `skills_createUploadTicket`

Mint a 10-minute single-use bearer token for the
`upload-to-skillzdrive` skill's `send-file.sh`. Response includes a
`websiteFallbackUrl` for environments that can't run a local script.

- Auth: authenticated. Scoped callers are locked to their own collection.
- Optional: `filename: string`, `collectionName: string` (unscoped callers only).

## Billing

### `skills_getCredits`

Current credit balance, monthly skill-call counter + tier limit,
and recent credit transactions.

- Auth: authenticated. Inputs: none.

### `skills_listWebhooks`

List the account's credit-alert webhook subscriptions.

- Auth: authenticated. Inputs: none.

### `skills_createWebhook`

Subscribe a URL to credit-alert webhooks. Returns the subscription
`id` + `secret` once (HMAC-SHA256 signing key for delivery
verification).

- Auth: authenticated.
- Required: `event_type: 'credits.threshold_hit' | 'credits.exhausted'`, `target_url: string` (HTTPS).
- Conditional: `threshold_value: number` (required for `credits.threshold_hit`).

### `skills_deleteWebhook`

Delete a webhook subscription.

- Auth: authenticated. Required: `id: string`.

## Quick reference: the Golden Path

```
listScripts → runScript(reuseSession: true) → readFile → closeSession
```

Output is in `/tmp/last_run.out` (stdout) and `/tmp/last_run.err`
(stderr). On `session_not_found`, re-run with `reuseSession: true`
to get a fresh sandbox.

<!-- END https://www.skillzdrive.com/docs/reference/tools -->

<!-- BEGIN https://www.skillzdrive.com/docs/reference/resources -->

# MCP Documentation Resources Reference

> Markdown variant of <https://www.skillzdrive.com/docs/reference/resources>.

Read skill documentation efficiently using the documentation tools.

## What are resources?

Resources are the documentation and reference files bundled with
each skill. They describe what the skill does, how to use it, and
include examples. You access them through three documentation
tools — you never need to construct URIs manually.

## Reading documentation

Use `skills_docTOC` to see what sections are available, then
`skills_docSection` to read the ones you need.

### Step 1: Get the table of contents

```json
{
  "name": "skills_docTOC",
  "arguments": { "skillSlug": "docx" }
}
```

Response:

```json
{
  "sections": [
    { "slug": "overview", "title": "Overview", "level": 1 },
    { "slug": "creating-documents", "title": "Creating Documents", "level": 2 },
    { "slug": "formatting", "title": "Formatting", "level": 2 },
    { "slug": "tables", "title": "Tables", "level": 2 }
  ]
}
```

### Step 2: Read a specific section

```json
{
  "name": "skills_docSection",
  "arguments": { "skillSlug": "docx", "sectionSlug": "tables" }
}
```

Read individual sections instead of full documentation. This keeps
token usage low and responses focused.

## Checking file metadata

Use `skills_getResourceInfo` to check a file's size, token count,
and available sections before reading it. This helps you decide
whether to read the full file or target specific sections.

```json
{
  "name": "skills_getResourceInfo",
  "arguments": { "skillSlug": "docx", "filePath": "references/formatting.md" }
}
```

Response:

```json
{
  "sections": ["Tables", "Fonts", "Margins", "Headers and Footers"],
  "tokenCount": 1200,
  "fileSize": 4096,
  "contentType": "text/markdown"
}
```

## Reading raw resource content

`skills_readResourceContent` returns the raw bytes of a resource
file (full or by section name). Blocked for premium skills.

```json
{
  "name": "skills_readResourceContent",
  "arguments": {
    "skillSlug": "docx",
    "filePath": "references/formatting.md",
    "sectionName": "Tables"
  }
}
```

## Token efficiency guide

Different approaches have different token costs. Use the most
targeted tool to minimize context window usage.

| Tool | Token cost | When to use |
|------|------------|-------------|
| `docTOC` | Low | First step — see what's available |
| `getResourceInfo` | Low | Check size and sections before reading |
| `docSection` | Medium | Read one specific section |
| Multiple `docSection` calls | High | Only when you need several sections |

## Next steps

- [MCP tools reference](https://www.skillzdrive.com/docs/reference/tools.md): every `skills_*` tool with arguments.
- [Discovering skills](https://www.skillzdrive.com/docs/guides/discovering-skills.md).

<!-- END https://www.skillzdrive.com/docs/reference/resources -->

<!-- BEGIN https://www.skillzdrive.com/docs/reference/endpoints -->

# MCP HTTP Endpoints Reference

> Markdown variant of <https://www.skillzdrive.com/docs/reference/endpoints>.

HTTP endpoints for connecting to the SkillzDrive MCP server.

## MCP endpoint

All MCP communication goes through a single endpoint using
Streamable HTTP transport:

```
https://www.skillzdrive.com/api/mcp
```

| Method | Purpose |
|--------|---------|
| `POST` | Send JSON-RPC messages (tool calls, initialize, etc.) |
| `GET` | Open SSE stream for server notifications |
| `DELETE` | Terminate session |

Most MCP client libraries handle the HTTP methods automatically.
You just configure the URL and auth header — the SDK does the
rest.

## Authentication

Include your API key in the `Authorization` header on every
request:

| Header | Value |
|--------|-------|
| `Authorization` | `Bearer sk_live_YOUR_KEY` |
| `Content-Type` | `application/json` |

## OAuth endpoints

For clients that use OAuth 2.0 instead of API keys (e.g. Claude
Code, Claude.ai):

| Method | Path | Purpose |
|--------|------|---------|
| `POST` | `/api/mcp/oauth/token` | Exchange authorization code or client credentials for a token |
| `POST` | `/api/mcp/oauth/register` | Dynamic client registration (RFC 7591) |
| `GET` | `/.well-known/oauth-authorization-server` | OAuth discovery metadata (RFC 8414) |

Most developers use API keys (simpler). OAuth is handled
automatically by MCP clients that support it — you don't need to
call these endpoints manually. See the
[Authentication guide](https://www.skillzdrive.com/docs/guides/authentication.md)
for details.

## Legacy SSE transport

For older MCP clients using the separated SSE pattern:

| Method | Path | Purpose |
|--------|------|---------|
| `GET` | `/api/mcp/sse` | Open SSE channel; response includes the message endpoint URL |
| `POST` | `/message?sessionId=…` | Send JSON-RPC messages bound to the SSE channel |

Streamable HTTP is preferred. Use legacy SSE only when your client
doesn't support the newer transport.

## CORS

The MCP server sets these CORS headers:

```http
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, Accept, MCP-Session-Id, MCP-Protocol-Version
Access-Control-Expose-Headers: MCP-Session-Id
```

## Next steps

- [MCP tools reference](https://www.skillzdrive.com/docs/reference/tools.md).
- [Authentication](https://www.skillzdrive.com/docs/guides/authentication.md): API keys, OAuth 2.0, securing your integration.
- [Connecting](https://www.skillzdrive.com/docs/guides/connecting.md): client config recipes.

<!-- END https://www.skillzdrive.com/docs/reference/endpoints -->

<!-- BEGIN https://www.skillzdrive.com/docs/ai-context -->

# SkillzDrive MCP Integration Context
# Paste this into your AI model's system prompt or context window.
# Base URL: https://www.skillzdrive.com/api/mcp
# Auth: Authorization: Bearer sk_live_YOUR_KEY
# Protocol: MCP (Model Context Protocol) — any compliant client works.

## Available Tools (29 total, 10 categories)

### Onboarding (1)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_getStarted | — | — | One-shot session briefing: tool catalog, workflows, fallback chains, collection context. Call once per session. |

### Discovery (2)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_searchSkills | query | limit, collectionName | Search skills by keyword. Recommended starting point. |
| skills_listSkills | — | query, tags, collectionName | List all accessible skills. |

### Documentation (4)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_docTOC | skillSlug | — | Get documentation table of contents. |
| skills_docSection | skillSlug, sectionSlug | — | Read a specific documentation section. |
| skills_getResourceInfo | skillSlug, filePath | — | Get file metadata (sections, token count, size). |
| skills_readResourceContent | skillSlug, filePath | sectionName | Read raw text content of a skill resource file. Blocked for premium skills. |

### Execution (4)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_listScripts | skillSlug | — | List executable scripts. MUST call before runScript. |
| skills_runScript | skillSlug, scriptName | args, stdin, reuseSession, sessionId | Execute script in sandbox. |
| skills_getScript | skillSlug, scriptName | — | Get script source/download URL for local execution. |
| skills_getScriptStream | skillSlug, scriptName | — | Same as getScript but returns content inline. Fallback when callers can't fetch signed URLs. |

### Session Management (3)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_readFile | sessionId, filePath | startLine, limit, closeAfter | Read file from active sandbox. Pass closeAfter:true on the final read to release the session in the same call. |
| skills_listOutputFiles | sessionId | directory, closeAfter | List files in sandbox directory. |
| skills_closeSession | sessionId | — | Close sandbox session and free resources. |

### Collections (5)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_listCollections | — | — | List owned collections. All-skills keys only. |
| skills_createCollection | name | skillSlugs, includeTeamSkills, includeSharedSkills | Create a named collection. |
| skills_updateCollection | collectionName | newName, includeTeamSkills, includeSharedSkills | Rename or reconfigure a collection. |
| skills_addToCollection | collectionName, skillSlug | — | Add one skill to a collection. |
| skills_removeFromCollection | collectionName, skillSlug | — | Remove one skill from a collection. |

### Drive Management (2)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_removeFromDrive | skillSlug | — | Remove a skill from your drive entirely. |
| skills_toggleDriveSkill | skillSlug | — | Toggle a skill on/off (keeps it in drive). |

### Marketplace (3)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_getLeaderboard | — | sort_by (executions/installs/rating) | Top 10 public/premium skills over the last 30 days. |
| skills_discoverSkills | keywords | offset | Search marketplace + GitHub catalog. Returns batches of 10. |
| skills_importToDrive | skillSlug | — | Import a marketplace or GitHub skill to your drive. Charges credits. |

### Updates (3)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_checkUpdates | — | — | List drive skills with pending updates from their owners. |
| skills_acceptUpdate | skillSlug | — | Apply a pending update. Charges credits. |
| skills_dismissUpdate | skillSlug | — | Dismiss a pending update without applying. |

### Upload (1)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_getUploadUrl | — | — | Get website upload URL with caller's key metadata baked in. Fallback when send-file.sh can't run. |

### Export (1)
| Tool | Required Args | Optional Args | Description |
|------|--------------|---------------|-------------|
| skills_downloadSkills | scope | collectionName, skillSlug | Download skills as ZIP. Scopes: drive, collection, skill. |

## Skill Discovery

The skill catalog is dynamic — new skills are added regularly. Never hardcode skill lists.
- Use searchSkills(query) to find skills for a specific task (e.g. "pdf", "image", "spreadsheet")
- Use listSkills() to browse all available skills
- Skills come from 3 sources: your drive, team drives, and skills shared with you

## Workflow: Script-Based Skills (hasScripts: true)

Follow this exact sequence:
1. searchSkills(query) or listSkills() → find the right skill slug
2. listScripts(skillSlug) → get exact script names (NEVER guess)
3. runScript(skillSlug, scriptName, reuseSession: true) → get sessionId
4. readFile(sessionId, "/tmp/last_run.out") → get script output
5. closeSession(sessionId) → free resources

## Workflow: Local-Execution Skills

1. searchSkills(query) or listSkills() → find the skill slug
2. listScripts(skillSlug) → get exact script names (NEVER guess)
3. getScript(skillSlug, scriptName) → get downloadUrl (+ inline content if available)
4. Download + run locally if your environment supports local code execution
Note: Local execution is FREE (no credits charged).

## Workflow: Template-Based Skills (hasScripts: false)

1. docTOC(skillSlug) → get section slugs
2. docSection(skillSlug, sectionSlug) → read relevant content
3. Generate output directly using the documentation

## Workflow: Upload a Skill

1. searchSkills("upload-to-skillzdrive") → find the upload skill
2. listScripts("upload-to-skillzdrive") → get "send-file.sh"
3. getScript("upload-to-skillzdrive", "send-file.sh") → get script with embedded API key
4. Run script LOCALLY: bash send-file.sh --file /path/to/skill.zip
Note: On platforms like claude.ai, whitelist www.skillzdrive.com first.

## Workflow: Manage Collections

- createCollection(name, skillSlugs?) → create new collection
- addToCollection(collectionName, skillSlug) → add one skill
- removeFromCollection(collectionName, skillSlug) → remove one skill
- updateCollection(collectionName, newName) → rename
Collections filter which skills are accessible per API key.

## Workflow: Marketplace Discovery

1. discoverSkills(keywords) → browse marketplace + GitHub skills
2. importToDrive(skillSlug) → import to your drive (charges credits)
3. Optionally addToCollection(collectionName, skillSlug) → organize

## Anti-Fragile Fallbacks

When a tool fails, don't give up — every error includes specific next steps. Common fallback chains:

- runScript fails in cloud → read stderr via readFile → if execution_tier supports local, call getScript and run on the user's machine
- getScript returns truncated content OR caller can't fetch downloadUrl → getScriptStream for inline chunked delivery
- readFile returns "session expired" → re-run runScript with reuseSession: true to get a fresh sandbox
- downloadSkills signed URL unreachable (sandboxed clients) → ask the user to paste the URL into their browser
- send-file.sh upload fails → getUploadUrl for browser-based upload with correct key metadata
- searchSkills returns empty → discoverSkills for marketplace + GitHub search
- slug-not-found errors → check the suggestions array for "Did you mean X?" matches, fall back to searchSkills

Follow _workflow.nextSteps on every response — the server names the specific tool to try next.

## UI Feedback Requirements

Show users what is happening at each stage:
- searchSkills → "Searching for skills..."
- listSkills → "Loading available skills..."
- listScripts → "Loading scripts..."
- runScript → "Running [scriptName]..." with a spinner/progress indicator
- readFile → "Reading results..."
- Success → Display formatted output (code block, file, or rendered content)
- Error → Show error message + first suggestion as recovery action
- "Did you mean X?" → Show typo correction as a clickable option

## Rules (follow strictly)

- NEVER guess skill slugs or script names — always discover via search or list first
- ALWAYS call listScripts before runScript
- ALWAYS use reuseSession: true when calling runScript (output is NOT in the run response)
- ALWAYS read output via readFile after runScript (check /tmp/last_run.out for stdout, /tmp/last_run.err for stderr)
- ALWAYS close sessions yourself — pass closeAfter: true on your final readFile to release the sandbox in the same call, or use closeSession directly. Do not leave sessions open for the 5-min TTL to reap.
- ALWAYS check hasScripts to determine which workflow to follow (script vs template)
- For local-execution skills, use getScript and run from downloadUrl
- Follow _workflow.nextSteps hints in every response for guided navigation
- If a script has requiredEnvVars, the user must configure those API keys in their SkillzDrive account first
- addToCollection/removeFromCollection take a single skillSlug, not an array
- Collections with allowed_skill_ids=null (all skills) reject add/remove operations

## Error Handling

Errors include structured fields:
- error: machine-readable code (skill_not_found, script_not_found, access_denied, etc.)
- message: human-readable text — show this to the user
- suggestions: array of recovery steps — show the first one as an action
- _workflow.nextSteps: what tool to call next for automatic recovery

Common errors:
| Error | Cause | Recovery |
|-------|-------|----------|
| skill_not_found | Bad slug | Check spelling, use searchSkills |
| script_not_found | Wrong name | Call listScripts first, use exact name |
| access_denied | Key restriction | Check API key permissions |
| session_not_found | Session expired | Re-run script with reuseSession: true |
| missing_credentials | User hasn't set up required API key | Direct user to Account settings |
| quota_exceeded | Monthly limit reached | Upgrade plan or wait for reset |

## Verification Checklist

After integrating, confirm each step works:
1. searchSkills("pdf") → returns results with slugs
2. listScripts(slug) → returns script names and descriptions
3. runScript(slug, scriptName, reuseSession: true) → returns sessionId + exitCode 0
4. readFile(sessionId, "/tmp/last_run.out") → returns script output content
5. closeSession(sessionId) → succeeds
6. Bad slug → returns error with suggestions array
7. UI shows loading/success/error states at each stage

## Performance Tips

- Cache listSkills results for the entire session (skills don't change mid-conversation)
- Cache listScripts per skill slug for the session (scripts don't change mid-conversation)
- Don't cache runScript results (each execution is unique)
- Use getResourceInfo before reading large files to check token count
- Use docSection to read specific sections instead of full documentation

<!-- END https://www.skillzdrive.com/docs/ai-context -->

<!-- BEGIN https://www.skillzdrive.com/docs/security -->

# Security

> Markdown variant of <https://www.skillzdrive.com/docs/security>.

How SkillzDrive protects your credentials and data.

## Credential encryption

Some skills require third-party API keys (e.g. `GEMINI_API_KEY`,
`OPENAI_API_KEY`). Users store their own keys — the platform never
provides keys on their behalf.

All credentials are encrypted with:

- **AES-256-GCM encryption at rest** — each credential has a unique initialization vector (IV).
- **Encryption key stored only in server environment variables** — never in the database or client code.
- **Masked values for display** (e.g. `AIz...xyz1`) — full values are never returned from any API endpoint.

## How credentials reach scripts

1. User stores their API key via the Account page (`/dashboard/account`).
2. When a script with `requiredEnvVars` is executed, the MCP server fetches and decrypts only the needed credentials.
3. Decrypted values are injected as environment variables into the isolated sandbox.
4. The sandbox is destroyed after execution — credentials are never persisted.

Credentials only exist in decrypted form for the duration of script
execution. They are never written to disk in the sandbox.

## What we never do

- Never log decrypted credential values.
- Never return full keys from any API response.
- Never store keys in plaintext.
- Never transmit keys to the client side.
- Never share credentials between users or sessions.

## Skill security scanning

Every skill imported into SkillzDrive — whether from the
marketplace, GitHub, or a direct upload — goes through an
automated security scan. Each skill receives a safety grade from
**A** to **F** so you can make an informed decision about what
enters your drive.

### What we scan for

- **Vulnerability detection** — dependencies are checked against known CVE databases via Snyk integration.
- **Code analysis** — static analysis identifies injection vulnerabilities, unsafe patterns, and security flaws in source code.
- **Skill-specific audit** — a proprietary scanner evaluates skill instructions and scripts for prompt injection, data exfiltration, and other agent-specific risks.
- **AI expert review** — when issues are found, Claude Opus evaluates the skill's intent and legitimacy and provides a clear safe/caution/unsafe recommendation.

### Safety grades

Scan results are distilled into a letter grade that appears on
skill cards, in your drive, and in MCP tool responses:

| Grade | Risk level | What it means |
|-------|------------|---------------|
| A | No known risks | Clean across all checks |
| B | Low risk | Minor issues, generally safe |
| C | Medium risk | Review before using in production |
| D | High risk | Significant issues — use with caution |
| F | Critical risk | Serious vulnerabilities or unsafe behavior detected |

Scan results are cached and automatically refreshed when a skill's
source code changes. You never need to request a scan manually.

## Script isolation

Scripts run in isolated sandboxes:

- **Separate Linux container** per execution.
- **No network access** between sandboxes.
- **No persistent storage** — sandbox destroyed after use.
- **Timeout enforcement** — scripts killed after configured limit.

## API key security

| Feature | Description |
|---------|-------------|
| Key format | `sk_live_` prefix for easy identification |
| Expiration | Optional `expires_at` date |
| Rate limiting | Per-minute request limits |
| Skill restrictions | Optional `allowed_skill_ids` whitelist |
| Monthly quotas | Execution count limits |

## User responsibilities

Security is a shared responsibility:

- Keep API keys rotated according to each provider's recommendations.
- Use least-privilege keys (e.g. read-only if the skill only reads).
- Revoke leaked keys immediately and update them in Account settings.
- Monitor your usage via the dashboard for unexpected activity.

## Reporting security issues

If you discover a security vulnerability, contact us at the link in
the dashboard. Do not file a public issue.

## Next steps

- [Authentication](https://www.skillzdrive.com/docs/guides/authentication.md): API keys, OAuth 2.0, securing your integration.
- [Custom agent integration](https://www.skillzdrive.com/docs/agent-integration.md).
- [Quickstart](https://www.skillzdrive.com/docs/quickstart.md).

<!-- END https://www.skillzdrive.com/docs/security -->
