### Install Skill API Endpoint Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md An HTTP POST request to track the installation of a Claude Code Skill. This action increments the skill's installation counter. ```http POST /api/skills/:owner/:repo/:skillName/install ``` -------------------------------- ### Install Skill API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Tracks the installation of a Claude Code Skill and increments its installation counter. ```APIDOC ## POST /api/skills/:owner/:repo/:skillName/install ### Description Tracks the installation of a Claude Code Skill and increments its installation counter. ### Method POST ### Endpoint `/api/skills/:owner/:repo/:skillName/install` ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the GitHub repository containing the skill. - **repo** (string) - Required - The name of the GitHub repository. - **skillName** (string) - Required - The name of the skill directory. ### Request Example ``` POST /api/skills/anthropics/skills/algorithmic-art/install ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message. - **installs** (integer) - The updated total number of installations. #### Response Example ```json { "message": "Skill installation tracked successfully.", "installs": 501 } ``` ``` -------------------------------- ### GET /api/resolve/:owner/:marketplace/:plugin Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/README.md Resolves a specific plugin identifier to its corresponding git URL for CLI installation. ```APIDOC ## GET /api/resolve/:owner/:marketplace/:plugin ### Description Resolves a plugin identifier to a git repository URL. ### Method GET ### Endpoint /api/resolve/:owner/:marketplace/:plugin ### Parameters #### Path Parameters - **owner** (string) - Required - The GitHub owner of the plugin. - **marketplace** (string) - Required - The marketplace identifier. - **plugin** (string) - Required - The plugin name. ### Response #### Success Response (200) - **gitUrl** (string) - The repository URL for the plugin. #### Response Example { "gitUrl": "https://github.com/owner/repo.git" } ``` -------------------------------- ### GET /api/search Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/README.md Search for plugins by name, description, or keywords. ```APIDOC ## GET /api/search ### Description Performs a search across the registry for available plugins. ### Method GET ### Endpoint /api/search ### Parameters #### Query Parameters - **q** (string) - Required - The search query string. ### Response #### Success Response (200) - **results** (array) - List of matching plugins. #### Response Example { "results": [ { "name": "example-plugin", "description": "A sample plugin" } ] } ``` -------------------------------- ### HTTP Trigger Example Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md A basic example of an HTTP trigger in TypeScript, demonstrating how to handle incoming requests and return a simple response. Files with '.http.tsx' are treated as HTTP triggers. ```typescript export default async function (req: Request) { return new Response("Hello World"); } ``` -------------------------------- ### Interact with OpenAI API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Shows how to initialize the OpenAI client and make a chat completion request to the API. This example uses the 'gpt-4o-mini' model to generate a creative response to a user's prompt. ```typescript import { OpenAI } from "https://esm.town/v/std/openai"; const openai = new OpenAI(); const completion = await openai.chat.completions.create({ messages: [ { role: "user", content: "Say hello in a creative way" }, ], model: "gpt-4o-mini", max_tokens: 30, }); ``` -------------------------------- ### List Project Files Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Provides an example of using the `listFiles` utility function to retrieve a list of all files present in the current project. This can be helpful for dynamic file processing or generating file indexes. ```typescript const files = await listFiles(import.meta.url); ``` -------------------------------- ### Get Skill Stats API Endpoint Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md An HTTP GET request to retrieve installation statistics for a specific Claude Code Skill, including total, weekly, and monthly install counts. ```http GET /api/skills/:owner/:repo/:skillName/stats ``` -------------------------------- ### Manage Agent Skills Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/API.md Provides endpoints to retrieve skill information, track installations, search for skills, and fetch installation statistics. ```HTTP GET /api/skills/:owner/:repo/:skillName POST /api/skills/:owner/:repo/:skillName/install GET /api/skills/search?q=query&limit=20&offset=0 GET /api/skills/:owner/:repo/:skillName/stats ``` -------------------------------- ### GET /api/skills/:owner/:repo/:skillName Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/README.md Retrieves details for a specific skill. ```APIDOC ## GET /api/skills/:owner/:repo/:skillName ### Description Retrieves metadata and details for a specific skill. ### Method GET ### Endpoint /api/skills/:owner/:repo/:skillName ### Parameters #### Path Parameters - **owner** (string) - Required - GitHub owner. - **repo** (string) - Required - Repository name. - **skillName** (string) - Required - Name of the skill. ### Response #### Success Response (200) - **name** (string) - Skill name - **description** (string) - Skill description #### Response Example { "name": "my-skill", "description": "Automates task X" } ``` -------------------------------- ### Initialize Hono App and Middleware Setup Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/main.ts This snippet initializes a Hono web application and configures essential middleware. It includes CORS for cross-origin requests and Axiom middleware for logging HTTP requests with specific configurations for the 'claude-plugins-registry' Val. Dependencies include the 'hono' library for the web framework and a custom Axiom logger. ```typescript import { Hono } from "npm:hono@4.9"; import { cors } from "npm:hono@4.9/cors"; import { cache } from "npm:hono@4.9/cache"; import { getPluginStats } from "./api/plugins.ts"; import { resolvePlugin } from "./api/resolve.ts"; import { searchPlugins } from "./api/search.ts"; import { getSkill, getSkillStats, installSkill, searchSkills, } from "./api/skills.ts"; import { getPluginsSitemap, getSkillsSitemap } from "./api/sitemap.ts"; import { indexRepoSkills } from "./api/index-repo-skills.ts"; import { resolveSkills } from "./api/v2/resolve.ts"; import { type AxiomEnv, axiomMiddleware, } from "https://esm.town/v/kamalnrf/axiom-logger/hono.ts"; // Initialize Hono app const app = new Hono(); // Middleware app.use("*", cors()); app.use( "*", axiomMiddleware({ valName: "claude-plugins-registry", console: "warn", defaultFields: { type: "HTTP", }, }), ); ``` -------------------------------- ### Skill Stats API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Retrieves installation statistics for a specific Claude Code Skill, including total, weekly, and monthly installation counts. ```APIDOC ## GET /api/skills/:owner/:repo/:skillName/stats ### Description Retrieves installation statistics for a specific Claude Code Skill. ### Method GET ### Endpoint `/api/skills/:owner/:repo/:skillName/stats` ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the GitHub repository containing the skill. - **repo** (string) - Required - The name of the GitHub repository. - **skillName** (string) - Required - The name of the skill directory. ### Request Example ``` GET /api/skills/anthropics/skills/algorithmic-art/stats ``` ### Response #### Success Response (200) - **totalInstalls** (integer) - Total number of installations. - **weeklyInstalls** (integer) - Number of installations in the last week. - **monthlyInstalls** (integer) - Number of installations in the last month. #### Response Example ```json { "totalInstalls": 500, "weeklyInstalls": 50, "monthlyInstalls": 150 } ``` ``` -------------------------------- ### Plugin Resolution API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry Resolves a plugin identifier to its Git URL, enabling CLI installation. ```APIDOC ## GET /api/resolve/:owner/:marketplace/:plugin ### Description Resolves a plugin identifier to its Git URL for CLI installation. ### Method GET ### Endpoint `/api/resolve/:owner/:marketplace/:plugin` ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the GitHub repository. - **marketplace** (string) - Required - The marketplace name where the plugin is listed. - **plugin** (string) - Required - The name of the plugin. ### Request Example ``` GET /api/resolve/valtown/claude-plugins-registry/example-plugin ``` ### Response #### Success Response (200) - **gitUrl** (string) - The Git URL of the plugin repository. #### Response Example ```json { "gitUrl": "https://github.com/valtown/claude-plugins-registry/tree/main/.claude-plugin/example-plugin" } ``` ``` -------------------------------- ### Skills API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/API.md Endpoints for interacting with skills in the registry, including retrieving, installing, searching, and getting statistics. ```APIDOC ## Skills ### Get Skill ``` GET /api/skills/:owner/:repo/:skillName ``` Get skill information (read-only, does not increment install counter). **Example:** * `/api/skills/anthropics/skills/algorithmic-art` ### Install Skill ``` POST /api/skills/:owner/:repo/:skillName/install ``` Track skill installation and increment install counter. ### Search Skills ``` GET /api/skills/search?q=query&limit=20&offset=0 ``` Search skills by name, description, or author. **Query Parameters:** * `q` (optional) - Search query * `limit` (optional) - Results per page (default: 20, max: 100) * `offset` (optional) - Pagination offset ### Skill Statistics ``` GET /api/skills/:owner/:repo/:skillName/stats ``` Get install statistics for a skill. **Response:** ```json { "installs": { "total": 567, "week": 23, "month": 89 }, "lastInstalled": "2025-01-15T14:30:00.000Z" } ``` ``` -------------------------------- ### Cron Trigger Example Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md A basic example of a Cron trigger in TypeScript, intended for scheduled tasks. Files with '.cron.tsx' are recognized as Cron triggers. ```typescript export default async function () { // Scheduled task code } ``` -------------------------------- ### Get Skill API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Retrieves information about a specific Claude Code Skill. This is a read-only endpoint and does not increment installation counts. ```APIDOC ## GET /api/skills/:owner/:repo/:skillName ### Description Retrieves information about a specific Claude Code Skill. This is a read-only endpoint. ### Method GET ### Endpoint `/api/skills/:owner/:repo/:skillName` ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the GitHub repository containing the skill. - **repo** (string) - Required - The name of the GitHub repository. - **skillName** (string) - Required - The name of the skill directory. ### Request Example ``` GET /api/skills/anthropics/skills/algorithmic-art ``` ### Response #### Success Response (200) - **name** (string) - The name of the skill. - **description** (string) - The description of the skill. - **version** (string) - The version of the skill. - **dependencies** (string) - Any dependencies for the skill. - **author** (string) - The author of the skill. - **installs** (integer) - The total number of installations. - **metadata** (object) - Additional metadata about the skill. #### Response Example ```json { "name": "Algorithmic Art", "description": "Generates algorithmic art.", "version": "1.0.0", "dependencies": "python>=3.8", "author": "AI Artist", "installs": 500, "metadata": { "repoOwner": "anthropics", "repoName": "skills", "directoryPath": "algorithmic-art" } } ``` ``` -------------------------------- ### Email Trigger Example Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md A basic example of an Email trigger in TypeScript, designed to process incoming emails. Files with '.email.tsx' are identified as Email triggers. ```typescript export default async function (email: Email) { // Process email } ``` -------------------------------- ### Search Skills API Endpoint Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md An HTTP GET request to search for Claude Code Skills based on a query. Results are paginated and sorted by installation count, then by stars. ```http GET /api/skills/search?q=query&limit=20&offset=0 ``` -------------------------------- ### Plugin Statistics API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry Retrieves statistics for a specific plugin, such as downloads and installs. ```APIDOC ## GET /api/plugins/:owner/:marketplace/:plugin/stats ### Description Retrieves statistics for a specific plugin, including download and install counts. ### Method GET ### Endpoint `/api/plugins/:owner/:marketplace/:plugin/stats` ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the GitHub repository. - **marketplace** (string) - Required - The marketplace name where the plugin is listed. - **plugin** (string) - Required - The name of the plugin. ### Request Example ``` GET /api/plugins/valtown/claude-plugins-registry/example-plugin/stats ``` ### Response #### Success Response (200) - **downloads** (integer) - The total number of downloads. - **installs** (integer) - The total number of installs. #### Response Example ```json { "downloads": 1500, "installs": 1200 } ``` ``` -------------------------------- ### GET /api/sitemap/plugins Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/sitemap.ts Retrieves a paginated list of plugins suitable for sitemap generation. This endpoint is cached for 1 day to optimize performance. ```APIDOC ## GET /api/sitemap/plugins ### Description Returns paginated plugins for sitemap generation. The response is cached for 1 day. ### Method GET ### Endpoint /api/sitemap/plugins ### Query Parameters - **limit** (integer) - Optional - The maximum number of plugins to return per page. Defaults to 50000. - **offset** (integer) - Optional - The number of plugins to skip before returning results. Defaults to 0. ### Response #### Success Response (200) - **urls** (array) - An array of objects, where each object contains the `loc` (URL) and `lastmod` (last modified date) of a plugin. - **total** (integer) - The total number of plugins available. - **limit** (integer) - The limit used for pagination. - **offset** (integer) - The offset used for pagination. #### Response Example ```json { "urls": [ { "loc": "https://claude-plugins.dev/plugins/example-plugin", "lastmod": "2024-01-15T10:00:00Z" } ], "total": 200, "limit": 50000, "offset": 0 } ``` ``` -------------------------------- ### Skills API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/main.ts Endpoints for retrieving, searching, installing, and indexing skills. ```APIDOC ## GET /api/skills/:owner/:repo/:skillName ### Description Retrieves a specific skill by its owner, repository, and skill name. ### Method GET ### Endpoint /api/skills/:owner/:repo/:skillName ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the skill repository. - **repo** (string) - Required - The name of the repository containing the skill. - **skillName** (string) - Required - The name of the skill. ### Response #### Success Response (200) - **skill_details** (object) - Details of the skill. #### Response Example ```json { "skill_details": { "name": "example-skill", "description": "An example skill." } } ``` ``` ```APIDOC ## GET /api/skills/search ### Description Searches for skills based on a query. ### Method GET ### Endpoint /api/skills/search ### Parameters #### Query Parameters - **q** (string) - Required - The search query. - **limit** (integer) - Optional - The maximum number of results to return (default: 20). - **offset** (integer) - Optional - The number of results to skip (default: 0). ### Response #### Success Response (200) - **skills** (array) - A list of matching skills. #### Response Example ```json { "skills": [ { "name": "skill-x", "description": "Description for skill X." }, { "name": "skill-y", "description": "Description for skill Y." } ] } ``` ``` ```APIDOC ## GET /api/skills/:owner/:repo/:skillName/stats ### Description Retrieves statistics for a specific skill. ### Method GET ### Endpoint /api/skills/:owner/:repo/:skillName/stats ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the skill repository. - **repo** (string) - Required - The name of the repository containing the skill. - **skillName** (string) - Required - The name of the skill. ### Response #### Success Response (200) - **stats** (object) - Statistics related to the skill. #### Response Example ```json { "stats": { "usage_count": 500, "last_used": "2023-10-27T10:00:00Z" } } ``` ``` ```APIDOC ## POST /api/skills/index ### Description Indexes skills from a specified repository. This operation can be run as a dry run to preview changes. ### Method POST ### Endpoint /api/skills/index ### Parameters #### Request Body - **repo** (string) - Required - The owner and repository name in the format 'owner/repo'. - **dryRun** (boolean) - Optional - If true, the operation will only preview changes without making any modifications. - **maxFiles** (integer) - Optional - The maximum number of files to process during indexing. ### Request Example ```json { "repo": "kamalnrf/claude-plugins-registry", "dryRun": true, "maxFiles": 100 } ``` ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating the indexing status. - **indexed_skills** (array) - A list of skills that were indexed or would be indexed. #### Response Example ```json { "message": "Skills indexing preview complete.", "indexed_skills": [ "skill1", "skill2" ] } ``` ``` -------------------------------- ### Send Email Notifications Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Provides an example of how to send an email using the built-in email utility. By default, the email is sent to the owner of the Val. It supports both plain text and HTML content. ```typescript import { email } from "https://esm.town/v/std/email"; // By default emails the owner of the val await email({ subject: "Hi", text: "Hi", html: "

Hi

", }); ``` -------------------------------- ### GET /api/sitemap/skills Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/sitemap.ts Retrieves a paginated list of skills suitable for sitemap generation. This endpoint is cached for 1 day to optimize performance. ```APIDOC ## GET /api/sitemap/skills ### Description Returns paginated skills for sitemap generation. The response is cached for 1 day. ### Method GET ### Endpoint /api/sitemap/skills ### Query Parameters - **limit** (integer) - Optional - The maximum number of skills to return per page. Defaults to 50000. - **offset** (integer) - Optional - The number of skills to skip before returning results. Defaults to 0. ### Response #### Success Response (200) - **urls** (array) - An array of objects, where each object contains the `loc` (URL) and `lastmod` (last modified date) of a skill. - **total** (integer) - The total number of skills available. - **limit** (integer) - The limit used for pagination. - **offset** (integer) - The offset used for pagination. #### Response Example ```json { "urls": [ { "loc": "https://claude-plugins.dev/skills/example-skill", "lastmod": "2024-01-15T10:00:00Z" } ], "total": 100, "limit": 50000, "offset": 0 } ``` ``` -------------------------------- ### Get Skill Information API Endpoint (TypeScript) Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/skills.ts This TypeScript code defines the GET /api/skills/:owner/:repo/:skillName endpoint for the skills API. It handles retrieving skill information from the database, including sorting and filtering capabilities. Dependencies include Hono for context, Drizzle ORM for database operations, and custom clients for SQLite and caching. ```typescript /** * Skills API endpoints */ import type { Context } from "npm:hono@4.9"; import { and, asc, desc, eq, sql } from "npm:drizzle-orm@0.44.2"; import { sqlite } from "../clients/sqlite.ts"; import { db } from "../database/db.ts"; import { skills, skillStats } from "../database/schema.ts"; import { getLogger } from "https://esm.town/v/kamalnrf/axiom-logger/hono.ts"; import { getActiveSkillsCount } from "../clients/cache.ts"; import { sanitizeFtsQuery } from "../utils.ts"; import { GitHubClient } from "../clients/github.ts"; import { discoverSkillsInRepo } from "../lib/skills/discover.ts"; import { indexSkillFiles } from "../lib/skills/index-skill-files.ts"; const github = new GitHubClient(); const ALLOWED_SORT_COLUMNS = new Set([ "downloads", "stars", ]); function getSkillColumn(field: string) { switch (field) { case "downloads": return skills.installs; case "stars": return skills.stars; default: return null; } } /** * GET /api/skills/:owner/:repo/:skillName * Get skill info (read-only, no install increment) ``` -------------------------------- ### GET /api/skills/:owner/:repo/:skillName Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/skills.ts Retrieves information about a specific skill, including its owner, repository, and skill name. This endpoint is read-only and does not increment the skill's download count. ```APIDOC ## GET /api/skills/:owner/:repo/:skillName ### Description Retrieves information about a specific skill, including its owner, repository, and skill name. This endpoint is read-only and does not increment the skill's download count. ### Method GET ### Endpoint /api/skills/:owner/:repo/:skillName ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the repository. - **repo** (string) - Required - The name of the repository. - **skillName** (string) - Required - The name of the skill. ### Request Example ```json { "example": "No request body for GET request" } ``` ### Response #### Success Response (200) - **skillInfo** (object) - Detailed information about the skill. #### Response Example ```json { "example": "{\"name\": \"example-skill\", \"description\": \"An example skill\", \"owner\": \"kamalnrf\", \"repo\": \"claude-plugins-registry\", \"downloads\": 100, \"stars\": 50}" } ``` ``` -------------------------------- ### Search Skills API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Allows users to search for Claude Code Skills based on criteria like name, description, and author. Results are sorted by installation count and then by stars. ```APIDOC ## GET /api/skills/search ### Description Searches for Claude Code Skills by name, description, or author. Results are sorted by installs and then by stars. ### Method GET ### Endpoint `/api/skills/search` ### Parameters #### Query Parameters - **q** (string) - Optional - The search query string. - **limit** (integer) - Optional - The maximum number of results to return (default: 20). - **offset** (integer) - Optional - The number of results to skip (default: 0). ### Request Example ``` GET /api/skills/search?q=art&limit=5 ``` ### Response #### Success Response (200) - **skills** (array) - A list of matching skill objects. - **name** (string) - The name of the skill. - **description** (string) - The description of the skill. - **namespace** (string) - The skill's namespace (@owner/repo/skillName). - **installs** (integer) - The total installation count for the skill. - **stars** (integer) - The number of stars the skill has. #### Response Example ```json { "skills": [ { "name": "Algorithmic Art", "description": "Generates algorithmic art.", "namespace": "@anthropics/skills/algorithmic-art", "installs": 500, "stars": 75 } ] } ``` ``` -------------------------------- ### Search Plugins API Endpoint Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md An HTTP GET request to search for plugins based on a query string and optional category filter. Results are paginated and sorted by stars and then by downloads. ```http GET /api/search?q=query&category=cat&limit=20&offset=0 ``` -------------------------------- ### Serve Project Files with Hono Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Demonstrates how to use the `serveFile` utility function within a Hono framework to serve static files from project directories like 'frontend/' and 'shared/'. This ensures proper content types are set for served files. ```typescript // serve all files in frontend/ and shared/ app.get("/frontend/*", (c) => serveFile(c.req.path, import.meta.url)); app.get("/shared/*", (c) => serveFile(c.req.path, import.meta.url)); ``` -------------------------------- ### Serve Static Assets and Inject Initial Data with Hono Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Demonstrates how to serve static files from frontend and shared directories using utility functions and how to inject server-side data into the HTML template for client-side consumption. ```TypeScript import { readFile, serveFile, } from "https://esm.town/v/std/utils@85-main/index.ts"; // serve all files in frontend/ and shared/ app.get("/frontend/*", (c) => serveFile(c.req.path, import.meta.url)); app.get("/shared/*", (c) => serveFile(c.req.path, import.meta.url)); // For index.html, often you'll want to bootstrap with initial data app.get("/", async (c) => { let html = await readFile("/frontend/index.html", import.meta.url); // Inject data to avoid extra round-trips const initialData = await fetchInitialData(); const dataScript = ``; html = html.replace("", `${dataScript}`); return c.html(html); }); ``` -------------------------------- ### Get Skill API Endpoint Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md An HTTP GET request to retrieve information about a specific Claude Code Skill using its owner, repository, and skill name. This is a read-only endpoint and does not increment install counts. ```http GET /api/skills/:owner/:repo/:skillName Example: /api/skills/anthropics/skills/algorithmic-art ``` -------------------------------- ### Read Project Files Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Shows how to use the `readFile` utility to access the content of files within the project. This is useful for reading configuration files, templates, or other static assets. ```typescript // Read a file from the project const fileContent = await readFile("/frontend/index.html", import.meta.url); ``` -------------------------------- ### Initialize SQLite Client with Environment Fallback Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/clients/sqlite.ts This code exports a singleton SQLite client. It attempts to connect to a remote LibSQL database using environment variables, falling back to the built-in Val Town SQLite client if those variables are absent. ```TypeScript import { createClient } from "https://esm.sh/@libsql/client@0.6.0/web"; import { sqlite as vtSQLite } from "https://esm.town/v/std/sqlite2/main.tsx"; const URL = Deno.env.get("DB_API_URL"); const TOKEN = Deno.env.get("DB_API_TOKEN"); export const sqlite = (() => { if (URL && TOKEN) { return createClient({ url: URL, authToken: TOKEN, }); } return vtSQLite; })(); ``` -------------------------------- ### Import Val Town Utilities with Version Pins Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Illustrates the correct way to import Val Town utility functions, emphasizing the use of version pins to prevent breaking changes. This ensures stability when project dependencies are updated. ```typescript import { parseProject, readFile, serveFile, } from "https://esm.town/v/std/utils@85-main/index.ts"; ``` -------------------------------- ### Get Plugin Stats API Endpoint Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md An HTTP GET request to retrieve download statistics for a specific plugin, including total, weekly, and monthly download counts. ```http GET /api/plugins/:owner/:marketplace/:plugin/stats ``` -------------------------------- ### Create and Query SQLite Table Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Demonstrates how to create a new SQLite table if it doesn't exist and then query data from it using parameterized queries. It's recommended to change the table name when modifying the schema to ensure a fresh table is created. ```typescript import { sqlite } from "https://esm.town/v/stevekrouse/sqlite"; const TABLE_NAME = "todo_app_users_2"; // Create table - do this before usage and change table name when modifying schema await sqlite.execute(`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL )`); // Query data const result = await sqlite.execute( `SELECT * FROM ${TABLE_NAME} WHERE id = ?`, [1], ); ``` -------------------------------- ### Marketplace JSON Parsing with Zod Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Illustrates how to parse marketplace JSON data using Zod for minimal validation. It shows how to define a schema that accepts specific fields and allows others to pass through using `.passthrough()`. ```typescript const PluginSchema = z.object({ name: z.string().min(1), // Only required field description: z.string().optional(), version: z.string().optional(), }).passthrough(); // Allow all other fields ``` -------------------------------- ### Configure React Dependencies Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Details the process for configuring React libraries within Val Town, including pinning dependency versions using query parameters and setting the `jsxImportSource` pragma for React components. ```javascript // When using React libraries, pin versions with `?deps=react@18.2.0,react-dom@18.2.0` and start the file with `/** @jsxImportSource https://esm.sh/react@18.2.0 */` Ensure all React dependencies and sub-dependencies are pinned to the same version ``` -------------------------------- ### Parse Project Information Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Demonstrates how to use the `parseProject` utility to extract metadata about the current Val project, such as the username, project name, version, branch, and URLs. This information is crucial for building features like 'view source' links. ```typescript const projectVal = parseProject(import.meta.url); console.log(projectVal.username); // Owner of the project console.log(projectVal.name); // Project name console.log(projectVal.version); // Version number console.log(projectVal.branch); // Branch name console.log(projectVal.links.self.project); // URL to the project page ``` -------------------------------- ### Search GitHub Buckets for Skills (TypeScript) Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/cron/search-buckets.ts This script searches GitHub for 'SKILL.md' files, categorizing them into size-based buckets. It loads previously stored buckets from blob storage and creates initial buckets if none exist. The script uses a GitHubClient and Val Town's blob API to fetch and store data. ```typescript import { GitHubClient } from "../clients/github.ts"; import { blob } from "https://esm.town/v/std/blob"; const MIN_SIZE = 500; const MAX_SIZE = 150_000; const BASE_QUERY = `filename:SKILL.md language:Markdown "---" "name:" "description:"`; const BUCKET_NAME = "skills-search-buckets"; const MAX_PER_BUCKET = 950; const MIN_SPAN = 200; // Helper to read previously stored buckets (returns [] if none) async function getStoredBuckets(): Promise< Array<{ min: number; max: number; count: number }> > { try { const existing = await blob.getJSON< Array<{ min: number; max: number; count: number }> >(BUCKET_NAME); return Array.isArray(existing) ? existing : []; } catch { return []; } } export default async function (interval: Interval) { const startTime = Date.now(); try { console.log("GitHub Search Buckets for skills started"); const github = new GitHubClient(); // 1) Load stored buckets. If empty, create initial buckets for full range. let buckets = await getStoredBuckets(); if (buckets.length === 0) { // ... initial bucket creation logic ... } // ... rest of the search and bucket update logic ... } catch (error) { console.error("Error in GitHub Search Buckets:", error); } } ``` -------------------------------- ### Implement Redirects in Val Town Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Shows the correct method for implementing HTTP redirects in Val Town. It uses `new Response` with a 302 status and a `Location` header, as `Response.redirect` is noted as being broken. ```typescript return new Response(null, { status: 302, headers: { Location: "/place/to/redirect" }}}) ``` -------------------------------- ### Test GitHub Code Search - TypeScript Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/cron/indexer-query-tester.ts This TypeScript code snippet demonstrates how to use the GitHubClient to search for code. It defines a search query and fetches the first page of results, logging the search query and the total count of found files. It also includes commented-out code for more advanced searching and bucket finding. ```TypeScript import { GitHubClient } from "../clients/github.ts"; const github = new GitHubClient(); // const testQueries = [ // 'filename:SKILL.md path:skills/ language:Markdown "---" "name:" "description:"', // 'filename:SKILL.md language:Markdown "---" "name:" "description:" pushed:>=2025-10-14', // 'filename:SKILL.md language:Markdown size:100..5000 "---" "name:" "description:"', // 'filename:SKILL.md language:Markdown size:5001..20000 "---" "name:" "description:"', // ] const searchQuery = "repo:vercel-labs/agent-skills filename:SKILL.md"; console.log(`Searching: ${searchQuery}`); const firstPage = await github.searchCode(searchQuery); // console.log(`Found ${firstPage.total_count} SKILL.md files`); // Start with a broad plausible range for SKILL.md // const MIN_SIZE = 500; // const MAX_SIZE = 150_000; // const BASE_QUERY = `filename:SKILL.md language:Markdown "---" "name:" "description:"`; // const buckets = await github.findBuckets(BASE_QUERY, {min: MIN_SIZE, max: MAX_SIZE, maxPerBucket: 950, minSpan: 200}); // console.log(`Found ${buckets.length} buckets`, buckets.map(console.log)); // Fullname: Kamalnrf/claude-plugins, path: patches/giget@2.0.0.patch // const fileContent = await fetch( // "https://raw.githubusercontent.com/Kamalnrf/claude-plugins/refs/heads/main/CLAUDE.md", // ).then((res) => res.text()); // console.log("First Commit At =>", fileContent); ``` -------------------------------- ### POST /api/v2/skills/resolve Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/v2/resolve.ts Unified skill resolution API endpoint. Handles different input formats and returns installable skills with sourceUrl. ```APIDOC ## POST /api/v2/skills/resolve ### Description This endpoint resolves skills based on the provided target. It supports listing skills from an owner, a specific repository, or resolving a particular skill. ### Method POST ### Endpoint /api/v2/skills/resolve ### Parameters #### Request Body - **target** (string) - Required - Specifies the owner, owner/repo, or owner/repo/skill to resolve. - **limit** (number) - Optional - The maximum number of results to return. - **offset** (number) - Optional - The number of results to skip. ### Request Example ```json { "target": "owner/repo/skill", "limit": 10, "offset": 0 } ``` ### Response #### Success Response (200) - **namespace** (string) - The namespace of the resolved skill. - **name** (string) - The name of the resolved skill. - **relDir** (string) - The relative directory of the skill. - **sourceUrl** (string) - The URL of the skill's source code. #### Response Example ```json { "skills": [ { "namespace": "kamalnrf", "name": "claude-plugins-registry", "relDir": "api/v2", "sourceUrl": "https://github.com/kamalnrf/claude-plugins-registry" } ] } ``` ``` -------------------------------- ### Initialize API Dependencies Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/v2/resolve.ts Sets up the necessary clients and imports for the skill resolution endpoint, including the GitHub client, database schema, and logging utilities. ```TypeScript import type { Context } from "npm:hono@4.9"; import { and, eq, like } from "npm:drizzle-orm@0.44.2"; import { db } from "../../database/db.ts"; import { skills } from "../../database/schema.ts"; import { GitHubClient } from "../../clients/github.ts"; import { discoverSkillsInRepo } from "../../lib/skills/discover.ts"; import { getLogger } from "https://esm.town/v/kamalnrf/axiom-logger/hono.ts"; const github = new GitHubClient(); ``` -------------------------------- ### Get Plugin Statistics Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/API.md Retrieves download statistics for a specific plugin, including total, weekly, and monthly counts, along with the timestamp of the last download. ```HTTP GET /api/plugins/:owner/:marketplace/:plugin/stats ``` -------------------------------- ### Execute Database Migrations in TypeScript Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/database/run-migrations.ts This script imports the migration runner from the local database module and executes it within an asynchronous IIFE. It includes basic error handling to log failures and re-throw exceptions for visibility in the Val Town execution environment. ```typescript import { runMigrations } from "./db.ts"; (async function run() { try { await runMigrations(); console.log("Migrations completed successfully"); } catch (error) { console.error("Error running migrations:", error); throw error; } })(); ``` -------------------------------- ### Plugin Search API Source: https://www.val.town/x/kamalnrf/claude-plugins-registry Searches for plugins and skills by name, description, or keywords. ```APIDOC ## GET /api/search ### Description Searches for plugins and skills by name, description, or keywords. ### Method GET ### Endpoint `/api/search` ### Parameters #### Query Parameters - **q** (string) - Required - The search query string. ### Request Example ``` GET /api/search?q=image-generation ``` ### Response #### Success Response (200) - **results** (array) - A list of matching plugins and skills. - **name** (string) - The name of the plugin or skill. - **description** (string) - The description of the plugin or skill. - **type** (string) - The type of item (e.g., 'plugin', 'skill'). #### Response Example ```json { "results": [ { "name": "ImageGen", "description": "Generates images based on prompts.", "type": "plugin" } ] } ``` ``` -------------------------------- ### GET /api/resolve/:owner/:marketplace/:plugin Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/resolve.ts Resolves a specific plugin identifier (in the format of owner/marketplace/plugin) to its corresponding Git repository URL and associated metadata. ```APIDOC ## GET /api/resolve/:owner/:marketplace/:plugin ### Description Resolves a plugin identifier to its Git URL and metadata. This endpoint is used to look up plugin details based on the owner, marketplace, and plugin name. ### Method GET ### Endpoint /api/resolve/:owner/:marketplace/:plugin ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the plugin (e.g., @anthropics). - **marketplace** (string) - Required - The marketplace or collection name. - **plugin** (string) - Required - The specific name of the plugin. ### Request Example GET /api/resolve/anthropics/claude-code-plugins/agent-sdk-dev ### Response #### Success Response (200) - **gitUrl** (string) - The repository URL for the plugin. - **metadata** (object) - Additional plugin information. #### Error Response (400) - **error** (string) - "Missing owner, marketplace, or plugin name" ``` -------------------------------- ### Handle Server-Side Only Utilities Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md Highlights that utilities like `parseProject` and other Standard Library functions are restricted to server-side execution. For client-side access, data must be explicitly passed or fetched from the server. ```plaintext However, it's _extremely importing_ to note that `parseProject` and other Standard Library utilities ONLY RUN ON THE SERVER. If you need access to this data on the client, run it in the server and pass it to the client by splicing it into the HTML page or by making an API request for it. ``` -------------------------------- ### GET /api/plugins/:owner/:marketplace/:plugin/stats Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/plugins.ts Retrieves the total and weekly download statistics for a specific plugin identified by its owner, marketplace, and plugin name. ```APIDOC ## GET /api/plugins/:owner/:marketplace/:plugin/stats ### Description Fetches the download statistics for a specific plugin. Returns the total download count and the download count for the current week. ### Method GET ### Endpoint /api/plugins/:owner/:marketplace/:plugin/stats ### Parameters #### Path Parameters - **owner** (string) - Required - The owner of the plugin. - **marketplace** (string) - Required - The marketplace identifier. - **plugin** (string) - Required - The name of the plugin. ### Request Example GET /api/plugins/my-org/claude-store/my-plugin/stats ### Response #### Success Response (200) - **downloads** (object) - Object containing download metrics - **total** (number) - Total lifetime downloads - **week** (number) - Downloads in the last week #### Error Response (404) - **error** (string) - Error message indicating the plugin was not found #### Response Example { "downloads": { "total": 1500, "week": 120 } } ``` -------------------------------- ### Normalize GitHub Repository Input Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/api/index-repo-skills.ts A utility function that converts various GitHub input formats, such as full URLs or 'owner/repo' strings, into a standardized 'owner/repo' format. It uses regular expressions to validate and extract the repository path, returning null if the input is invalid. ```TypeScript function normalizeRepoInput(input: string): string | null { if (!input) return null; // Already in owner/repo format if (/^[\w.-]+\/[\w.-]+$/.test(input)) { return input; } // URL format const urlMatch = input.match( /(?:https?:\/\/)?(?:www\.)?github\.com\/([\w.-]+)\/([\w.-]+)/ ); if (urlMatch) { return `${urlMatch[1]}/${urlMatch[2]}`; } return null; } ``` -------------------------------- ### Index Skill Files Function Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/lib/skills/index-skill-files.ts The indexSkillFiles function processes a list of skill file references, parsing their content and updating the database. It handles logging, dry-run capabilities, and tracks indexing results including successes, failures, and duplicates. ```TypeScript export async function indexSkillFiles( refs: SkillFileRef[], { github, log, dryRun = false }: IndexSkillFilesOptions, ): Promise { const result: IndexSkillFilesResult = { found: refs.length, indexed: 0, invalid: 0, failed: 0, skipped: 0, unchanged: 0 }; // Implementation logic follows... ``` -------------------------------- ### Search Plugins Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/API.md Searches for plugins based on a query string, category, or pagination parameters. Returns a paginated list of matching plugins and the total count. ```HTTP GET /api/search?q=query&category=cat&limit=20&offset=0 ``` -------------------------------- ### Resolve Plugin API Endpoint Source: https://www.val.town/x/kamalnrf/claude-plugins-registry/code/AGENTS.md An HTTP GET request to resolve a plugin by its owner, marketplace, and plugin name. This endpoint returns the plugin's Git URL and associated metadata, while also incrementing download statistics. ```http GET /api/resolve/:owner/:marketplace/:plugin Example: /api/resolve/anthropics/claude-code-plugins/agent-sdk-dev ```