Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ watch(() => route.fullPath, () => {
>
Privacy
</NuxtLink>
<NuxtLink
to="/terms"
class="font-mono text-xs text-muted underline-offset-2 hover:underline hover:text-default"
>
Terms
</NuxtLink>
<UButton
icon="i-lucide-keyboard"
color="neutral"
Expand Down
81 changes: 81 additions & 0 deletions docs/runbooks/agent-app-directories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# ChatGPT and Claude directory listings

The skilld MCP server at `https://skilld.dev/api/mcp` is listed in two directories.
Both listings point at the same server, so a server deploy updates both.

| Directory | Portal | Listing source |
| --- | --- | --- |
| [ChatGPT](https://chatgpt.com) and Codex plugin directory | [platform.openai.com/plugins](https://platform.openai.com/plugins) | `integrations/openai-plugin/` |
| Claude Connectors Directory | [claude.ai/directory/manage](https://claude.ai/directory/manage) | the Claude listing fields below |

## What review checks

Both portals scan the tools from the live server. Every tool must keep these properties:

- A `title`, and explicit `readOnlyHint`, `destructiveHint`, and `openWorldHint` values.
- A description that says what the tool does. It must not tell the model how to behave, call other apps, or fetch instructions from a URL.
- Output that holds only what the request needs. Do not add request IDs, trace IDs, or debug fields.

`layers/mcp/shared/mcp-tools.ts` holds the tools. The toolkit answers 403 to a request whose `Origin` header is not in `mcp.security.allowedOrigins` in `nuxt.config.ts`.

## Change a tool

1. Deploy the change.
2. In the [OpenAI](https://openai.com) portal, open the plugin, select **MCPs**, then **Rescan**. OpenAI also scans once a day.
3. A new tool stays unavailable in ChatGPT until the scan approves it. Keep the old input schema working until then.
4. Claude syncs tools from the server. If the portal flags a tool, fix it on the server.

## OpenAI plugin

The publisher must be an OpenAI organization owner or hold **Apps Management Write**.
The organization must complete individual verification for the name in `developerName`.
A project with EU data residency cannot submit a plugin with an MCP server.

1. Build the ZIP from the package directory:

```sh
cd integrations/openai-plugin && zip -r "$TMPDIR/skilld-openai-plugin.zip" plugin.json mcp.json assets
```

2. Upload the ZIP. Select **Upload new or existing plugin** and choose the verified developer identity.
3. Connect the `skilld` MCP server and choose **No authentication**.
4. The portal shows a domain-verification token. Set it as a Worker secret:

```sh
pnpm exec wrangler secret put NUXT_OPENAI_APPS_CHALLENGE --config wrangler.jsonc
```

Then check that `https://skilld.dev/.well-known/openai-apps-challenge` prints the token, and complete the challenge.
5. Scan the tools and resolve every finding.
6. In **Review details**, add the demo video URL. The review needs a video of the five positive test cases in ChatGPT.
7. Submit for review, accept the policy attestations, and publish after approval.

To change the listing text, the test cases, or the icon, edit `plugin.json`, raise `version`, and upload a new ZIP.

## Claude connector

Any paid Claude plan can submit. Use these fields in the portal.

| Field | Value |
| --- | --- |
| Server URL | `https://skilld.dev/api/mcp` |
| Server name | skilld |
| One-liner | Search curated agent skills, see who wrote each one, and get the command that runs it in your coding agent. |
| Description | `longDescription` in `integrations/openai-plugin/plugin.json` |
| Categories | Developer tools |
| Documentation URL | `https://skilld.dev/developers?setup=mcp&app=claude` |
| Privacy policy URL | `https://skilld.dev/privacy` |
| Support contact | `https://github.com/skilld-dev/skilld.dev/issues` |
| Icon | `public/logo-icon.png` |
| Slug | `skilld`. The slug is permanent after publication |
| Use cases | Find agent skills by topic, check provenance before a run, open curated collections, get run and install commands |
| Requirements | None. Every tool works without an account |
| Data access | Reads data only |
| Company | Harlan Wilton, `https://skilld.dev`, `harlan@harlanzw.com` |
| Authentication | No authentication |
| Data handling | First-party API. No health data. No sponsored content |
| Test account | None. Every tool works without sign-in |

Before you submit, add the server in Claude as a custom connector and call each tool once.
After submission, Anthropic scans the server and lists it as a Community connector.
Status and reviewer feedback appear in the portal. Escalations go to `mcp-review@anthropic.com`.
Binary file added integrations/openai-plugin/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions integrations/openai-plugin/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
"mcpServers": {
"skilld": {
"type": "streamable-http",
"url": "https://skilld.dev/api/mcp"
}
}
}
96 changes: 96 additions & 0 deletions integrations/openai-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "skilld",
"version": "1.0.0",
"description": "Search skilld.dev, a curated registry of agent skills, read who wrote each skill, and get the command that runs it.",
"author": {
"name": "Harlan Wilton",
"email": "harlan@harlanzw.com",
"url": "https://skilld.dev"
},
"homepage": "https://skilld.dev/developers?setup=mcp",
"repository": "https://github.com/skilld-dev/skilld.dev",
"license": "MIT",
"keywords": ["agent skills", "SKILL.md", "coding agents", "codex", "developer tools"],
"extensions": {
"com.openai": {
"interface": {
"displayName": "skilld",
"shortDescription": "Curated agent skills by humans",
"longDescription": "skilld searches skilld.dev, a curated registry of agent skills. A skill is a SKILL.md file that a maintainer writes in their own GitHub repository. It teaches a coding agent how to use a library, a framework, or a workflow.\n\nAsk for a skill by topic, such as Tailwind CSS, Nuxt, or database migrations. skilld returns the matching skills with their author, source repository, GitHub star count, and skilld.dev page. For one skill, it shows the exact SKILL.md and commit on GitHub, when the skill last changed, and the full skill text, so you can read a skill before you run it. It also opens curated collections, where a curator explains why each skill is in the set.\n\nEvery skill comes with its commands. npx skilld run gives the skill to a coding agent for one session and writes no files. npx skilld install keeps the skill in a project. skilld runs and installs nothing itself. You run the command in your own terminal or coding agent.\n\nskilld needs no account and reads public registry data only.",
"developerName": "Harlan Wilton",
"category": "Developer Tools",
"capabilities": ["Search agent skills", "Show skill provenance and source", "Open curated collections", "Return run and install commands"],
"websiteURL": "https://skilld.dev",
"supportURL": "https://github.com/skilld-dev/skilld.dev/issues",
"privacyPolicyURL": "https://skilld.dev/privacy",
"termsOfServiceURL": "https://skilld.dev/terms",
"defaultPrompt": [
"Find a skill for Tailwind CSS and give me the run command.",
"Who wrote the web-design-guidelines skill, and when did it last change?",
"What is in the Agent builder essentials collection on skilld?"
],
"brandColor": "#E11D48",
"brandColorDark": "#FB7185",
"composerIcon": "./assets/logo.png",
"logo": "./assets/logo.png"
},
"review": {
"test_cases": {
"positive": [
{
"description": "Search skills by topic",
"prompt": "Find a skill for Tailwind CSS.",
"tools_triggered": "search_skills",
"expected_behavior": "Lists Tailwind CSS skills from skilld.dev. Each result names the skill, its GitHub owner and repository, and its GitHub star count, with a skilld.dev page link and an npx skilld run command."
},
{
"description": "Show who wrote a skill and when it changed",
"prompt": "Who wrote the web-design-guidelines skill in vercel-labs/agent-skills, and when did it last change?",
"tools_triggered": "get_skill",
"expected_behavior": "Names Vercel Labs as the publisher. Links the SKILL.md file on GitHub and gives its commit, the last repository push date, and the last skill change date."
},
{
"description": "Read a skill before running it",
"prompt": "Show me the SKILL.md of vercel-labs/agent-skills/web-design-guidelines before I run it.",
"tools_triggered": "get_skill",
"expected_behavior": "Returns the SKILL.md text with a link to its source file on GitHub, and the npx skilld run command for the skill."
},
{
"description": "Open a curated collection",
"prompt": "What is in the agent-building-stack collection by harlan-zw on skilld?",
"tools_triggered": "get_collection",
"expected_behavior": "Returns the Agent builder essentials collection: its skills, the curator's reason for each skill, and the npx skilld add @harlan-zw/agent-building-stack command that installs the whole collection."
},
{
"description": "Get the run command for one skill",
"prompt": "Give me the command to try anthropics/skills/skill-creator without installing it.",
"tools_triggered": "install_command",
"expected_behavior": "Returns npx skilld run anthropics/skills/skill-creator and says that it writes no files. Offers npx skilld install anthropics/skills/skill-creator to keep the skill. States that the user runs the command, and does not claim that anything ran."
}
],
"negative": [
{
"description": "Generate a new skill. skilld indexes skills that maintainers wrote and does not write skills.",
"prompt": "Write a new SKILL.md for my React project and publish it on skilld."
},
{
"description": "Change registry data. Every skilld tool is read only.",
"prompt": "Delete the tailwind skill from skilld.dev."
},
{
"description": "A request unrelated to agent skills. skilld should not be called.",
"prompt": "What is the weather in Sydney today?"
}
]
},
"commerce": false,
"commerce_description": "skilld sells nothing and processes no payments."
},
"publication": {
"countries": [],
"release_notes": "First release. Search skilld.dev for agent skills, show who wrote each skill and where its source lives, open curated collections, and return run and install commands."
}
}
}
}
19 changes: 14 additions & 5 deletions layers/marketing/app/pages/developers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
API_OPENAPI_PATH,
apiSamples,
apiSnippets,
claudeConnectorUrl,
cursorInstallUrl,
mcpApps,
setupModes,
Expand Down Expand Up @@ -220,11 +221,19 @@ const uiClass = 'font-medium text-default'
</template>

<template v-else-if="app === 'claude'">
<ol class="list-decimal space-y-2 pl-5">
<li>Open <a href="https://claude.ai/customize/connectors" target="_blank" rel="noopener" :class="uiClass" class="underline underline-offset-2">Customize &gt; Connectors</a> in claude.ai or the Claude desktop app.</li>
<li>Select <strong :class="uiClass">Add custom connector</strong>. Name it skilld and paste the server URL. If Claude asks about authentication, choose <strong :class="uiClass">No sign-in</strong>.</li>
<li>In a chat, open the <strong :class="uiClass">+</strong> menu, select <strong :class="uiClass">Connectors</strong>, and check that skilld is on.</li>
</ol>
<UButton
:to="claudeConnectorUrl()"
external
label="Add to Claude"
icon="i-lucide-external-link"
class="min-h-11 hover:bg-primary-600 active:bg-primary-700"
/>
<p class="mt-5">
Claude opens the <strong :class="uiClass">Add custom connector</strong> dialog with skilld filled in. Check the name and the server URL, then confirm. In a chat, open the <strong :class="uiClass">+</strong> menu, select <strong :class="uiClass">Connectors</strong>, and check that skilld is on.
</p>
<p class="mt-4">
Or open <a href="https://claude.ai/customize/connectors" target="_blank" rel="noopener" :class="uiClass" class="underline underline-offset-2">Customize &gt; Connectors</a> in claude.ai or the Claude desktop app. Select <strong :class="uiClass">Add custom connector</strong>, name it skilld, and paste the server URL.
</p>
<p class="mt-4">
Every plan can add a custom connector. The Free plan allows one. On a Team or Enterprise plan, an Owner adds it for the organization first.
<a href="https://claude.com/docs/connectors/custom/add-unlisted" target="_blank" rel="noopener" class="underline underline-offset-2 hover:text-default">Read Anthropic's guide</a>.
Expand Down
11 changes: 11 additions & 0 deletions layers/marketing/app/pages/terms.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
const { data } = await useMarketingArticle({
collection: 'pages',
path: '/terms',
canonicalPath: '/terms',
})
</script>

<template>
<MarketingArticle v-if="data" :page="data" />
</template>
9 changes: 9 additions & 0 deletions layers/marketing/app/utils/developer-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ export function cursorInstallUrl(url: string = REGISTRY_MCP_URL): string {
return `cursor://anysphere.cursor-deeplink/mcp/install?name=${SERVER_NAME}&config=${encodeURIComponent(config)}`
}

/**
* Claude's link opens its Add custom connector dialog with the name and URL
* filled in. The user still confirms before Claude adds anything.
*/
export function claudeConnectorUrl(url: string = REGISTRY_MCP_URL): string {
const query = new URLSearchParams({ modal: 'add-custom-connector', connectorName: SERVER_NAME, connectorUrl: url })
return `https://claude.ai/customize/connectors?${query}`
}

/** VS Code's install link carries the whole server entry as URI-encoded JSON. */
export function vscodeInstallUrl(url: string = REGISTRY_MCP_URL): string {
return `vscode:mcp/install?${encodeURIComponent(vscodeServerJson(url))}`
Expand Down
1 change: 1 addition & 0 deletions layers/marketing/app/utils/page-admissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const FREEZE_AUDIT_PATHS: readonly string[] = [
'/developers',
'/skillgen',
'/privacy',
'/terms',
'/learn/private-repositories',
'/learn/create-agent-skills',
'/learn/author-project-skills',
Expand Down
22 changes: 19 additions & 3 deletions layers/marketing/content/pages/privacy.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: Privacy
description: What skilld.dev stores, why it needs the data, how long it keeps it, and how you delete your account.
label: Last updated 6 October 2026
updatedAt: 2026-10-06
label: Last updated 7 October 2026
updatedAt: 2026-10-07
---

## In short
Expand All @@ -12,6 +12,7 @@ updatedAt: 2026-10-06
- An account is optional. You sign in with [GitHub](https://github.com) to like Skills, watch Repositories, get email, or connect the skilld CLI.
- You can delete your account from your dashboard at any time.
- The skilld CLI sends no telemetry.
- The MCP server for [ChatGPT](https://chatgpt.com), Claude, and other MCP apps needs no account. It receives only what each tool needs, such as your search text.

## When you visit

Expand Down Expand Up @@ -125,6 +126,21 @@ When you sign in with the CLI, skilld stores a record for that token:

If the client sends your operating system and processor type, such as `darwin-arm64`, device sign-in records it. The sign-in page shows it, so you can check which machine asks for access. You can revoke a device in your [dashboard](/me/devices).

## The MCP server

ChatGPT, Claude, and other MCP apps can search skilld.dev through its MCP server at `https://skilld.dev/api/mcp`. The server needs no account and sets no cookie. Every tool is read only.

When your chat app calls a tool, skilld receives what that tool needs:

- `search_skills` receives your search text and a result count.
- `get_skill` receives the owner, Repository, and name of one Skill.
- `get_collection` receives a curator login and a collection slug.
- `install_command` receives one Skill, Repository, or collection reference.

skilld receives no chat history, no files from the chat, and no account details from the chat app. ChatGPT and Claude call the server from OpenAI or Anthropic servers, so skilld sees their IP address, not yours. Apps on your computer, such as Claude Code or Cursor, call it from your network. Rate limits count requests per IP address, and skilld stores no IP address.

Search text goes to Workers AI, as [Search](#when-you-visit-search) describes. Request logs follow the rules under [When you visit](#when-you-visit). OpenAI and Anthropic handle your chat under their own privacy policies.

## Error reports

skilld uses [Sentry](https://sentry.io) to find and fix errors.
Expand Down Expand Up @@ -171,4 +187,4 @@ Skills in your public Repositories stay in the registry, because GitHub is their

## Contact

Email [harlan@harlanzw.com](mailto:harlan@harlanzw.com) with questions about your data. To report a security problem, use [GitHub private vulnerability reporting](https://github.com/skilld-dev/skilld/security/advisories/new).
Harlan Wilton runs skilld.dev. Email [harlan@harlanzw.com](mailto:harlan@harlanzw.com) with questions about your data. To report a security problem, use [GitHub private vulnerability reporting](https://github.com/skilld-dev/skilld/security/advisories/new).
Loading
Loading