diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 09d3786..9fbae81 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -34,7 +34,8 @@ "source": "git-subdir", "url": "https://github.com/adobe/skills.git", "path": "plugins/creative-cloud/adobe-for-creativity", - "ref": "main" + "ref": "main", + "sha": "0f1ad97af8b4de2107c2417184fc4c3114bda9d3" }, "homepage": "https://github.com/adobe/skills/tree/main/plugins/creative-cloud/adobe-for-creativity" }, @@ -66,7 +67,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/SalesforceAIResearch/agentforce-adlc.git" + "url": "https://github.com/SalesforceAIResearch/agentforce-adlc.git", + "sha": "9ef4d9b1958d4ed21179017d0452a81ec13c1de2" }, "homepage": "https://github.com/SalesforceAIResearch/agentforce-adlc" }, @@ -100,7 +102,8 @@ "source": { "source": "github", "repo": "aiven/aiven-ai-plugins", - "commit": "d2a7697b53826588d0faf795f39d2aa2362330da" + "commit": "d2a7697b53826588d0faf795f39d2aa2362330da", + "sha": "d2a7697b53826588d0faf795f39d2aa2362330da" }, "homepage": "https://aiven.io" }, @@ -113,7 +116,8 @@ "category": "database", "source": { "source": "url", - "url": "https://github.com/gemini-cli-extensions/alloydb.git" + "url": "https://github.com/gemini-cli-extensions/alloydb.git", + "sha": "0723d3ada808fe8f33e1b2808fd7a843c3d63ad2" }, "homepage": "https://cloud.google.com/alloydb" }, @@ -125,7 +129,8 @@ "source": "git-subdir", "url": "https://github.com/awslabs/agent-plugins.git", "path": "plugins/amazon-location-service", - "ref": "main" + "ref": "main", + "sha": "6cfb70e55aa142a8eda66e6ef7966d5921bdf9a2" }, "homepage": "https://github.com/awslabs/agent-plugins" }, @@ -135,7 +140,8 @@ "source": "git-subdir", "url": "https://github.com/amplitude/mcp-marketplace.git", "path": "plugins/amplitude", - "ref": "main" + "ref": "main", + "sha": "e9b4e15193666e1b513b5652ded23fab160bdc4e" }, "description": "Use Amplitude as an expert analyst — instrument Amplitude, discover product opportunities, analyze charts, create dashboards, manage experiments, and understand users and accounts.", "category": "monitoring", @@ -150,7 +156,8 @@ "category": "productivity", "source": { "source": "url", - "url": "https://github.com/apolloio/apollo-mcp-plugin.git" + "url": "https://github.com/apolloio/apollo-mcp-plugin.git", + "sha": "79577f9361c8b0d89e9fa36a1511bd4b37375f40" }, "homepage": "https://www.apollo.io/" }, @@ -188,7 +195,8 @@ "category": "productivity", "source": { "source": "url", - "url": "https://github.com/atlassian/atlassian-mcp-server.git" + "url": "https://github.com/atlassian/atlassian-mcp-server.git", + "sha": "9b52fb18e184edc307ce33f8bf4cdf148dedf1f2" }, "homepage": "https://github.com/atlassian/atlassian-mcp-server" }, @@ -201,7 +209,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/atlassian/forge-skills.git" + "url": "https://github.com/atlassian/forge-skills.git", + "sha": "9999904da629e0413db0343daeff863af311e8ab" }, "homepage": "https://developer.atlassian.com" }, @@ -212,7 +221,8 @@ "source": { "source": "url", "url": "https://github.com/BrainBlend-AI/atomic-agents.git", - "path": "claude-plugin/atomic-agents" + "path": "claude-plugin/atomic-agents", + "sha": "f849087b26bbb6fb5e63acb60f2b566ce874aaa7" }, "homepage": "https://github.com/BrainBlend-AI/atomic-agents", "tags": [ @@ -230,7 +240,8 @@ "source": "git-subdir", "url": "https://github.com/auth0/agent-skills.git", "path": "plugins/auth0", - "ref": "main" + "ref": "main", + "sha": "f7724bf7984c5b00496cac0f54526bb1cf505dcb" }, "homepage": "https://auth0.com/docs/quickstart/agent-skills" }, @@ -255,7 +266,8 @@ "source": "git-subdir", "url": "https://github.com/aws/agent-toolkit-for-aws.git", "path": "plugins/aws-agents", - "ref": "main" + "ref": "main", + "sha": "750230758fbf23acd60d075dedd7ead4092127ce" }, "homepage": "https://github.com/aws/agent-toolkit-for-aws" }, @@ -267,7 +279,8 @@ "source": "git-subdir", "url": "https://github.com/awslabs/agent-plugins.git", "path": "plugins/aws-amplify", - "ref": "main" + "ref": "main", + "sha": "6cfb70e55aa142a8eda66e6ef7966d5921bdf9a2" }, "homepage": "https://github.com/awslabs/agent-plugins" }, @@ -282,7 +295,8 @@ "source": "git-subdir", "url": "https://github.com/aws/agent-toolkit-for-aws.git", "path": "plugins/aws-core", - "ref": "main" + "ref": "main", + "sha": "750230758fbf23acd60d075dedd7ead4092127ce" }, "homepage": "https://github.com/aws/agent-toolkit-for-aws" }, @@ -297,7 +311,8 @@ "source": "git-subdir", "url": "https://github.com/aws/agent-toolkit-for-aws.git", "path": "plugins/aws-data-analytics", - "ref": "main" + "ref": "main", + "sha": "750230758fbf23acd60d075dedd7ead4092127ce" }, "homepage": "https://github.com/aws/agent-toolkit-for-aws" }, @@ -325,7 +340,8 @@ "source": "git-subdir", "url": "https://github.com/awslabs/agent-plugins.git", "path": "plugins/aws-serverless", - "ref": "main" + "ref": "main", + "sha": "6cfb70e55aa142a8eda66e6ef7966d5921bdf9a2" }, "homepage": "https://github.com/awslabs/agent-plugins" }, @@ -335,7 +351,8 @@ "category": "deployment", "source": { "source": "url", - "url": "https://github.com/microsoft/azure-skills.git" + "url": "https://github.com/microsoft/azure-skills.git", + "sha": "ed25b85a13ec001c53f538b07e0bfbe732673885" }, "homepage": "https://github.com/microsoft/azure-skills" }, @@ -372,7 +389,8 @@ "source": "git-subdir", "url": "https://github.com/Bigdata-com/bigdata-plugins-marketplace.git", "path": "plugins/bigdata-com", - "ref": "main" + "ref": "main", + "sha": "274b5365bdc61130225de736d3f3ca5210c0e37d" }, "homepage": "https://docs.bigdata.com" }, @@ -425,7 +443,8 @@ "category": "productivity", "source": { "source": "url", - "url": "https://github.com/circlebackai/claude-code-plugin.git" + "url": "https://github.com/circlebackai/claude-code-plugin.git", + "sha": "6369dec7da4059dd0a12cf1b62ba749799ee15ef" }, "homepage": "https://github.com/circlebackai/claude-code-plugin.git" }, @@ -491,7 +510,8 @@ "category": "database", "source": { "source": "url", - "url": "https://github.com/gemini-cli-extensions/cloud-sql-postgresql.git" + "url": "https://github.com/gemini-cli-extensions/cloud-sql-postgresql.git", + "sha": "69c0c820513d7f75a63eeb3ec84b01478037caeb" }, "homepage": "https://cloud.google.com/sql" }, @@ -525,7 +545,8 @@ "category": "database", "source": { "source": "url", - "url": "https://github.com/cockroachdb/claude-plugin.git" + "url": "https://github.com/cockroachdb/claude-plugin.git", + "sha": "31d0cc99fac1c97614cc787a96720104ea642375" }, "homepage": "https://github.com/cockroachdb/claude-plugin" }, @@ -568,7 +589,8 @@ "category": "productivity", "source": { "source": "url", - "url": "https://github.com/coderabbitai/skills.git" + "url": "https://github.com/coderabbitai/skills.git", + "sha": "a81eb76a1539e4a3f2b5c6fc133849124e72d303" }, "homepage": "https://github.com/coderabbitai/skills" }, @@ -602,7 +624,8 @@ "category": "security", "source": { "source": "url", - "url": "https://github.com/CrowdStrike/foundry-skills.git" + "url": "https://github.com/CrowdStrike/foundry-skills.git", + "sha": "e7fa0260b5a413d9a459d3afbc5ba427da6c6e04" }, "homepage": "https://github.com/CrowdStrike/foundry-skills" }, @@ -658,7 +681,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/gemini-cli-extensions/data-agent-kit-starter-pack.git" + "url": "https://github.com/gemini-cli-extensions/data-agent-kit-starter-pack.git", + "sha": "7bcfcb77435ec6d544b1131333f2297ca09c3930" }, "homepage": "https://cloud.google.com/bigquery" }, @@ -680,7 +704,8 @@ "source": "git-subdir", "url": "https://github.com/awslabs/agent-plugins.git", "path": "plugins/databases-on-aws", - "ref": "main" + "ref": "main", + "sha": "6cfb70e55aa142a8eda66e6ef7966d5921bdf9a2" }, "homepage": "https://github.com/awslabs/agent-plugins" }, @@ -693,7 +718,8 @@ "category": "monitoring", "source": { "source": "url", - "url": "https://github.com/datadog-labs/claude-code-plugin.git" + "url": "https://github.com/datadog-labs/claude-code-plugin.git", + "sha": "95d38f561e3d5e4fe9fb66c3c0bb19fb75e0458a" }, "homepage": "https://www.datadoghq.com/" }, @@ -719,7 +745,8 @@ "source": "git-subdir", "url": "https://github.com/microsoft/Dataverse-skills.git", "path": ".github/plugins/dataverse", - "ref": "main" + "ref": "main", + "sha": "b2f21c1eec233d1b20e89618c3ffcb25cfdd55e4" }, "homepage": "https://github.com/microsoft/Dataverse-skills" }, @@ -731,7 +758,8 @@ "source": "git-subdir", "url": "https://github.com/awslabs/agent-plugins.git", "path": "plugins/deploy-on-aws", - "ref": "main" + "ref": "main", + "sha": "6cfb70e55aa142a8eda66e6ef7966d5921bdf9a2" }, "homepage": "https://github.com/awslabs/agent-plugins" }, @@ -790,7 +818,8 @@ "source": "git-subdir", "url": "https://github.com/expo/skills.git", "path": "plugins/expo", - "ref": "main" + "ref": "main", + "sha": "786398d3574f33eb6714380f44ec09355819516e" }, "homepage": "https://github.com/expo/skills/blob/main/plugins/expo/README.md" }, @@ -837,7 +866,8 @@ "category": "design", "source": { "source": "url", - "url": "https://github.com/figma/mcp-server-guide.git" + "url": "https://github.com/figma/mcp-server-guide.git", + "sha": "fabc1ca81d839602ba7c1ca0f445a64246b3870e" }, "homepage": "https://github.com/figma/mcp-server-guide" }, @@ -854,7 +884,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/firecrawl/firecrawl-claude-plugin.git" + "url": "https://github.com/firecrawl/firecrawl-claude-plugin.git", + "sha": "122a6ae6cefb4393c2c30740aee55ba02532ccdc" }, "homepage": "https://github.com/firecrawl/firecrawl-claude-plugin.git" }, @@ -889,7 +920,8 @@ "source": { "source": "github", "repo": "fullstorydev/fullstory-skills", - "commit": "1ec5865e7ab1449f9a0859d164c4b6a8c53b6e2f" + "commit": "1ec5865e7ab1449f9a0859d164c4b6a8c53b6e2f", + "sha": "1ec5865e7ab1449f9a0859d164c4b6a8c53b6e2f" }, "homepage": "https://www.fullstory.com" }, @@ -951,7 +983,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/huggingface/skills.git" + "url": "https://github.com/huggingface/skills.git", + "sha": "7c71cfb2b12920002c3177474c779feeec4e9ad1" }, "homepage": "https://github.com/huggingface/skills.git" }, @@ -1004,7 +1037,8 @@ "source": { "source": "github", "repo": "jfrog/claude-plugin", - "commit": "761921eaa12b845beba1688d699a2d45091dfe83" + "commit": "761921eaa12b845beba1688d699a2d45091dfe83", + "sha": "d80db066e219aab8190f3dc4a463b71a3a180250" }, "homepage": "https://jfrog.com" }, @@ -1114,7 +1148,8 @@ "source": "git-subdir", "url": "https://github.com/pydantic/skills.git", "path": "plugins/logfire", - "ref": "main" + "ref": "main", + "sha": "92bd097356e1a4947f815449fb3570a9a5cfc21b" }, "homepage": "https://github.com/pydantic/skills/tree/main/plugins/logfire" }, @@ -1166,7 +1201,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/MicrosoftDocs/mcp.git" + "url": "https://github.com/MicrosoftDocs/mcp.git", + "sha": "954c17e72d65b0ee1fc7009c10b8a57e6889d34a" }, "homepage": "https://github.com/microsoftdocs/mcp" }, @@ -1192,7 +1228,8 @@ "source": "git-subdir", "url": "https://github.com/miroapp/miro-ai.git", "path": "claude-plugins/miro", - "ref": "main" + "ref": "main", + "sha": "00e619e63ca9a8fd788c2db9f294bc90773aac48" }, "homepage": "https://miro.com" }, @@ -1226,7 +1263,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/netlify/context-and-tools.git" + "url": "https://github.com/netlify/context-and-tools.git", + "sha": "a49ebc5965e0476edf958474d3feaeec754ffc6b" }, "homepage": "https://github.com/netlify/context-and-tools" }, @@ -1267,7 +1305,8 @@ "description": "Nimble web data toolkit — search, extract, map, crawl the web and work with structured data agents", "source": { "source": "url", - "url": "https://github.com/Nimbleway/agent-skills.git" + "url": "https://github.com/Nimbleway/agent-skills.git", + "sha": "626930f102dc51ef3858a28f94318ceabfdea071" }, "homepage": "https://docs.nimbleway.com/integrations/agent-skills/plugin-installation" }, @@ -1277,7 +1316,8 @@ "category": "productivity", "source": { "source": "url", - "url": "https://github.com/makenotion/claude-code-notion-plugin.git" + "url": "https://github.com/makenotion/claude-code-notion-plugin.git", + "sha": "9847f2aa1a15f25df35ed1fb7b4557dbb60cd651" }, "homepage": "https://github.com/makenotion/claude-code-notion-plugin" }, @@ -1347,7 +1387,8 @@ "category": "database", "source": { "source": "url", - "url": "https://github.com/pinecone-io/pinecone-claude-code-plugin.git" + "url": "https://github.com/pinecone-io/pinecone-claude-code-plugin.git", + "sha": "7dc3cfe091335f5053ec9e6eb05403e674a73c5e" }, "homepage": "https://github.com/pinecone-io/pinecone-claude-code-plugin" }, @@ -1397,7 +1438,8 @@ "category": "monitoring", "source": { "source": "url", - "url": "https://github.com/PostHog/ai-plugin.git" + "url": "https://github.com/PostHog/ai-plugin.git", + "sha": "ff08c376af53d7c5ba2e909b8065f786c7c3b506" }, "homepage": "https://posthog.com/docs/model-context-protocol" }, @@ -1451,7 +1493,8 @@ "source": "git-subdir", "url": "https://github.com/pydantic/skills.git", "path": "plugins/ai", - "ref": "main" + "ref": "main", + "sha": "92bd097356e1a4947f815449fb3570a9a5cfc21b" }, "homepage": "https://github.com/pydantic/skills/tree/main/plugins/ai" }, @@ -1485,7 +1528,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/qodo-ai/qodo-skills.git" + "url": "https://github.com/qodo-ai/qodo-skills.git", + "sha": "8fb6b5502dbe7876bbd672a27d6efa299f5820d7" }, "homepage": "https://github.com/qodo-ai/qodo-skills.git" }, @@ -1512,7 +1556,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/quarkusio/quarkus-agent-mcp.git" + "url": "https://github.com/quarkusio/quarkus-agent-mcp.git", + "sha": "c17280236a8080aab2bc10ff8e334922a2619a5f" }, "homepage": "https://quarkus.io" }, @@ -1624,7 +1669,8 @@ "source": "git-subdir", "url": "https://github.com/awslabs/agent-plugins.git", "path": "plugins/sagemaker-ai", - "ref": "main" + "ref": "main", + "sha": "6cfb70e55aa142a8eda66e6ef7966d5921bdf9a2" }, "homepage": "https://github.com/awslabs/agent-plugins" }, @@ -1674,7 +1720,8 @@ "source": { "source": "git-subdir", "url": "https://github.com/semgrep/mcp-marketplace.git", - "path": "plugin" + "path": "plugin", + "sha": "3711c33ad790df16e67c911eca792c473ec9a2a4" }, "homepage": "https://github.com/semgrep/mcp-marketplace.git" }, @@ -1684,7 +1731,8 @@ "category": "monitoring", "source": { "source": "url", - "url": "https://github.com/getsentry/sentry-for-claude.git" + "url": "https://github.com/getsentry/sentry-for-claude.git", + "sha": "fb398fdfff2055abc3d55917f6b6f0c0d5ad5e3b" }, "homepage": "https://github.com/getsentry/sentry-for-claude/tree/main" }, @@ -1734,7 +1782,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/Shopify/shopify-plugins.git" + "url": "https://github.com/Shopify/shopify-plugins.git", + "sha": "5631b93b88759561fec321192b6b083dbf0a2fd2" }, "homepage": "https://shopify.dev/docs/apps/build/devmcp" }, @@ -1747,7 +1796,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/Shopify/Shopify-AI-Toolkit.git" + "url": "https://github.com/Shopify/Shopify-AI-Toolkit.git", + "sha": "c5c18d86ce7b2a7ca51ebac7c4b1a4eda00c8e25" }, "homepage": "https://shopify.dev" }, @@ -1768,7 +1818,8 @@ "category": "productivity", "source": { "source": "url", - "url": "https://github.com/slackapi/slack-mcp-plugin.git" + "url": "https://github.com/slackapi/slack-mcp-plugin.git", + "sha": "7b9458950d38bb01ddb48b669f9fa89bcdfd98b8" }, "homepage": "https://github.com/slackapi/slack-mcp-plugin/tree/main" }, @@ -1797,7 +1848,8 @@ "category": "security", "source": { "source": "url", - "url": "https://github.com/SonarSource/sonarqube-agent-plugins.git" + "url": "https://github.com/SonarSource/sonarqube-agent-plugins.git", + "sha": "91eb175d6cf5d47a3edadbe61bdf782c31f0a65a" }, "homepage": "https://www.sonarsource.com" }, @@ -1807,7 +1859,8 @@ "category": "security", "source": { "source": "url", - "url": "https://github.com/sonatype/sonatype-guide-claude-plugin.git" + "url": "https://github.com/sonatype/sonatype-guide-claude-plugin.git", + "sha": "1dae73980f591d3196f5532ac72186513563d028" }, "homepage": "https://github.com/sonatype/sonatype-guide-claude-plugin.git" }, @@ -1831,7 +1884,8 @@ "category": "productivity", "source": { "source": "url", - "url": "https://github.com/speakai/speakai-mcp.git" + "url": "https://github.com/speakai/speakai-mcp.git", + "sha": "3fdf9d7b9bde86274eba60ce3d26f3588a19c1b9" }, "homepage": "https://mcp.speakai.co" }, @@ -1855,7 +1909,8 @@ }, "source": { "source": "github", - "repo": "browserbase/agent-browse" + "repo": "browserbase/agent-browse", + "sha": "13a7f4af8e36ca65e67d4da3dd74770e6f43dddd" }, "category": "automation", "keywords": [ @@ -1878,7 +1933,8 @@ "source": "git-subdir", "url": "https://github.com/stripe/ai.git", "path": "providers/claude/plugin", - "ref": "main" + "ref": "main", + "sha": "14623416d84fdfad0aea8744d4c6f838ebc87654" }, "homepage": "https://github.com/stripe/ai/tree/main/providers/claude/plugin" }, @@ -1899,7 +1955,8 @@ "category": "database", "source": { "source": "url", - "url": "https://github.com/supabase-community/supabase-plugin.git" + "url": "https://github.com/supabase-community/supabase-plugin.git", + "sha": "693a17a9970ba96e01afb9bef060d1dca48463ba" }, "homepage": "https://github.com/supabase-community/supabase-plugin" }, @@ -1909,7 +1966,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/obra/superpowers.git" + "url": "https://github.com/obra/superpowers.git", + "sha": "f2cbfbefebbfef77321e4c9abc9e949826bea9d7" }, "homepage": "https://github.com/obra/superpowers.git" }, @@ -2078,7 +2136,8 @@ "category": "security", "source": { "source": "url", - "url": "https://github.com/VantaInc/vanta-mcp-plugin.git" + "url": "https://github.com/VantaInc/vanta-mcp-plugin.git", + "sha": "a9dac8bef2ccda299b3a4ba7a1bc7e0dbb7195ac" }, "homepage": "https://help.vanta.com/en/articles/14094979-connecting-to-vanta-mcp#h_887ce3f337" }, @@ -2088,7 +2147,8 @@ "category": "deployment", "source": { "source": "url", - "url": "https://github.com/vercel/vercel-plugin.git" + "url": "https://github.com/vercel/vercel-plugin.git", + "sha": "78de7b549d3a8e197759c0c61859a8ccb69647c4" }, "homepage": "https://github.com/vercel/vercel-plugin" }, @@ -2174,7 +2234,8 @@ "category": "development", "source": { "source": "url", - "url": "https://github.com/zoom/zoom-plugin.git" + "url": "https://github.com/zoom/zoom-plugin.git", + "sha": "ab0f09b2ddc6682a7f69055c7861009ec6062775" }, "homepage": "https://developers.zoom.us/" }, @@ -2187,7 +2248,8 @@ "category": "security", "source": { "source": "url", - "url": "https://github.com/zscaler/zscaler-mcp-server.git" + "url": "https://github.com/zscaler/zscaler-mcp-server.git", + "sha": "6cf365968eb3b1e11306c973c51c1e54e98e704a" }, "homepage": "https://github.com/zscaler/zscaler-mcp-server" } diff --git a/.github/scripts/check-marketplace-sorted.ts b/.github/scripts/check-marketplace-sorted.ts deleted file mode 100644 index 0fcbf3b..0000000 --- a/.github/scripts/check-marketplace-sorted.ts +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env bun -/** - * Checks that marketplace.json plugins are alphabetically sorted by name. - * - * Usage: - * bun check-marketplace-sorted.ts # check, exit 1 if unsorted - * bun check-marketplace-sorted.ts --fix # sort in place - */ - -import { readFileSync, writeFileSync } from "fs"; -import { join } from "path"; - -const MARKETPLACE = join(import.meta.dir, "../../.claude-plugin/marketplace.json"); - -type Plugin = { name: string; [k: string]: unknown }; -type Marketplace = { plugins: Plugin[]; [k: string]: unknown }; - -const raw = readFileSync(MARKETPLACE, "utf8"); -const mp: Marketplace = JSON.parse(raw); - -const cmp = (a: Plugin, b: Plugin) => - a.name.toLowerCase().localeCompare(b.name.toLowerCase()); - -if (process.argv.includes("--fix")) { - mp.plugins.sort(cmp); - writeFileSync(MARKETPLACE, JSON.stringify(mp, null, 2) + "\n"); - console.log(`sorted ${mp.plugins.length} plugins`); - process.exit(0); -} - -for (let i = 1; i < mp.plugins.length; i++) { - if (cmp(mp.plugins[i - 1], mp.plugins[i]) > 0) { - console.error( - `marketplace.json plugins are not sorted: ` + - `'${mp.plugins[i - 1].name}' should come after '${mp.plugins[i].name}' (index ${i})`, - ); - console.error(` run: bun .github/scripts/check-marketplace-sorted.ts --fix`); - process.exit(1); - } -} - -console.log(`ok: ${mp.plugins.length} plugins sorted`); diff --git a/.github/scripts/validate-marketplace.ts b/.github/scripts/validate-marketplace.ts deleted file mode 100644 index 45f2600..0000000 --- a/.github/scripts/validate-marketplace.ts +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bun -/** - * Validates marketplace.json: well-formed JSON, plugins array present, - * each entry has required fields, and no duplicate plugin names. - * - * Usage: - * bun validate-marketplace.ts - */ - -import { readFile } from "fs/promises"; - -async function main() { - const filePath = process.argv[2]; - if (!filePath) { - console.error("Usage: validate-marketplace.ts "); - process.exit(2); - } - - const content = await readFile(filePath, "utf-8"); - - let parsed: unknown; - try { - parsed = JSON.parse(content); - } catch (err) { - console.error( - `ERROR: ${filePath} is not valid JSON: ${err instanceof Error ? err.message : err}` - ); - process.exit(1); - } - - if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) { - console.error(`ERROR: ${filePath} must be a JSON object`); - process.exit(1); - } - - const marketplace = parsed as Record; - if (!Array.isArray(marketplace.plugins)) { - console.error(`ERROR: ${filePath} missing "plugins" array`); - process.exit(1); - } - - const errors: string[] = []; - const seen = new Set(); - const required = ["name", "description", "source"] as const; - - marketplace.plugins.forEach((p, i) => { - if (!p || typeof p !== "object") { - errors.push(`plugins[${i}]: must be an object`); - return; - } - const entry = p as Record; - for (const field of required) { - if (!entry[field]) { - errors.push(`plugins[${i}] (${entry.name ?? "?"}): missing required field "${field}"`); - } - } - if (typeof entry.name === "string") { - if (seen.has(entry.name)) { - errors.push(`plugins[${i}]: duplicate plugin name "${entry.name}"`); - } - seen.add(entry.name); - } - }); - - if (errors.length) { - console.error(`ERROR: ${filePath} has ${errors.length} validation error(s):`); - for (const e of errors) console.error(` - ${e}`); - process.exit(1); - } - - console.log(`OK: ${marketplace.plugins.length} plugins, no duplicates, all required fields present`); -} - -main().catch((err) => { - console.error("Fatal error:", err); - process.exit(2); -}); diff --git a/.github/workflows/bump-plugin-shas.yml b/.github/workflows/bump-plugin-shas.yml index 4ea47b8..867cac8 100644 --- a/.github/workflows/bump-plugin-shas.yml +++ b/.github/workflows/bump-plugin-shas.yml @@ -1,133 +1,38 @@ -name: Bump plugin SHAs +name: Bump Plugin SHAs -# Weekly sweep of marketplace.json — for each entry whose upstream repo has -# moved past its pinned SHA, open a PR against main with updated SHAs. The -# validate-marketplace workflow then runs on the PR to confirm the file is -# still well-formed. +# Weekly sweep: for each external entry whose upstream HEAD has moved past +# its pinned SHA, validate at the new SHA with `claude plugin validate` +# inline, then open one PR with all passing bumps. # -# Adapted from claude-plugins-community-internal's bump-plugin-shas.yml -# for the single-file marketplace.json format. Key difference: all bumps -# are batched into one PR (since they all modify the same file). +# Bot-free — uses the default GITHUB_TOKEN. Because GITHUB_TOKEN-opened PRs +# don't trigger on:pull_request workflows, validation runs in this workflow +# before the PR is opened; the PR body links back here as the CI evidence. on: schedule: - cron: '23 7 * * 1' # Monday 07:23 UTC workflow_dispatch: inputs: - plugin: - description: Only bump this plugin (for testing) - required: false max_bumps: description: Cap on plugins bumped this run required: false default: '20' - dry_run: - description: Discover only, don't open PR - type: boolean - default: true - -concurrency: - group: bump-plugin-shas - cancel-in-progress: false permissions: contents: write pull-requests: write +concurrency: + group: bump-plugin-shas + jobs: bump: runs-on: ubuntu-latest - timeout-minutes: 15 steps: - uses: actions/checkout@v4 - - name: Check for existing bump PR - id: existing - env: - GH_TOKEN: ${{ github.token }} - run: | - existing=$(gh pr list --label sha-bump --state open --json number --jq 'length') - echo "count=$existing" >> "$GITHUB_OUTPUT" - if [ "$existing" -gt 0 ]; then - echo "::notice::Open sha-bump PR already exists — skipping" - fi - - - name: Ensure sha-bump label exists - if: steps.existing.outputs.count == '0' - env: - GH_TOKEN: ${{ github.token }} - run: gh label create sha-bump --color 0e8a16 --description "Automated SHA bump" 2>/dev/null || true - - - name: Overlay marketplace data from main - if: steps.existing.outputs.count == '0' - run: | - git fetch origin main --depth=1 --quiet - git checkout origin/main -- .claude-plugin/marketplace.json - - - name: Discover and apply SHA bumps - if: steps.existing.outputs.count == '0' - id: discover - env: - GH_TOKEN: ${{ github.token }} - PR_BODY_PATH: /tmp/bump-pr-body.md - PLUGIN: ${{ inputs.plugin }} - MAX_BUMPS: ${{ inputs.max_bumps }} - DRY_RUN: ${{ inputs.dry_run }} - run: | - args=(--max "${MAX_BUMPS:-20}") - [[ -n "$PLUGIN" ]] && args+=(--plugin "$PLUGIN") - [[ "$DRY_RUN" = "true" ]] && args+=(--dry-run) - python3 .github/scripts/discover_bumps.py "${args[@]}" - - - uses: oven-sh/setup-bun@v2 - if: steps.existing.outputs.count == '0' && steps.discover.outputs.count != '0' && inputs.dry_run != true - - - name: Validate marketplace.json - if: steps.existing.outputs.count == '0' && steps.discover.outputs.count != '0' && inputs.dry_run != true - run: | - bun .github/scripts/validate-marketplace.ts .claude-plugin/marketplace.json - bun .github/scripts/check-marketplace-sorted.ts - - - name: Push bump branch - if: steps.existing.outputs.count == '0' && steps.discover.outputs.count != '0' && inputs.dry_run != true - id: push - run: | - branch="auto/bump-shas-$(date +%Y%m%d)" - echo "branch=$branch" >> "$GITHUB_OUTPUT" - - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git checkout -b "$branch" - git add .claude-plugin/marketplace.json - git commit -m "Bump SHA pins for ${{ steps.discover.outputs.count }} plugin(s) - - Plugins: ${{ steps.discover.outputs.bumped_names }}" - git push -u origin "$branch" --force-with-lease - - # GITHUB_TOKEN cannot create PRs (org policy: "Allow GitHub Actions to - # create and approve pull requests" is disabled). Use the same GitHub App - # that -internal's bump workflow uses. - # - # Prerequisite: app 2812036 must be installed on this repo. The PEM - # secret must exist in this repo's settings (shared with -internal). - - name: Generate bot token - if: steps.push.outcome == 'success' - id: app-token - uses: actions/create-github-app-token@v1 + - uses: anthropics/claude-plugins-community/.github/actions/bump-plugin-shas@f846a0bcb0e721b1f93d60e8b73e91dafc4a1e87 with: - app-id: 2812036 - private-key: ${{ secrets.CLAUDE_DIRECTORY_BOT_PRIVATE_KEY }} - owner: ${{ github.repository_owner }} - repositories: ${{ github.event.repository.name }} - - - name: Create pull request - if: steps.push.outcome == 'success' - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: | - gh pr create \ - --base main \ - --head "${{ steps.push.outputs.branch }}" \ - --title "Bump SHA pins (${{ steps.discover.outputs.count }} plugins)" \ - --body-file /tmp/bump-pr-body.md \ - --label sha-bump + marketplace-path: .claude-plugin/marketplace.json + max-bumps: ${{ inputs.max_bumps || '20' }} + claude-cli-version: latest diff --git a/.github/workflows/scan-plugins.yml b/.github/workflows/scan-plugins.yml new file mode 100644 index 0000000..7734c01 --- /dev/null +++ b/.github/workflows/scan-plugins.yml @@ -0,0 +1,24 @@ +name: Scan Plugins + +on: + pull_request: + paths: + - '.claude-plugin/marketplace.json' + +permissions: + contents: read + +jobs: + scan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Non-blocking by default. Graceful no-op if ANTHROPIC_API_KEY is not + # configured on the repo. To enforce, set fail-on-findings: "true". + - uses: anthropics/claude-plugins-community/.github/actions/scan-plugins@f846a0bcb0e721b1f93d60e8b73e91dafc4a1e87 + with: + anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} + claude-cli-version: latest diff --git a/.github/workflows/validate-marketplace.yml b/.github/workflows/validate-marketplace.yml deleted file mode 100644 index abf3b38..0000000 --- a/.github/workflows/validate-marketplace.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Validate Marketplace JSON - -on: - pull_request: - paths: - - '.claude-plugin/marketplace.json' - -jobs: - validate: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - uses: oven-sh/setup-bun@v2 - - - name: Validate marketplace.json - run: bun .github/scripts/validate-marketplace.ts .claude-plugin/marketplace.json - - - name: Check plugins sorted - run: bun .github/scripts/check-marketplace-sorted.ts diff --git a/.github/workflows/validate-plugins.yml b/.github/workflows/validate-plugins.yml new file mode 100644 index 0000000..b297bde --- /dev/null +++ b/.github/workflows/validate-plugins.yml @@ -0,0 +1,34 @@ +name: Validate Plugins + +on: + pull_request: + paths: + - '.claude-plugin/**' + - '*/.claude-plugin/**' + - '*/agents/**' + - '*/skills/**' + - '*/commands/**' + push: + branches: [main] + paths: + - '.claude-plugin/**' + +permissions: + contents: read + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: anthropics/claude-plugins-community/.github/actions/validate-plugins@f846a0bcb0e721b1f93d60e8b73e91dafc4a1e87 + with: + marketplace-path: .claude-plugin/marketplace.json + # Official curated marketplace: SHA-pin (I5) is a HARD error. + # I8/I11 are warnings until the 15 known vendored-path/name issues + # are cleaned up (see PR body); tighten to "I1 I3" after. + warn-invariants: "I1 I3 I8 I11" + claude-cli-version: latest