mirror of
https://github.com/anthropics/claude-plugins-official.git
synced 2026-07-17 21:23:30 +00:00
Compare commits
8 Commits
fix-window
...
fix-2071-m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a67587c816 | ||
|
|
502de97746 | ||
|
|
679f52da9e | ||
|
|
13a0208f38 | ||
|
|
e9b54375b8 | ||
|
|
fc49e6815f | ||
|
|
06b6d5b96f | ||
|
|
2a3dd81146 |
@@ -742,18 +742,37 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "convex-backend",
|
||||
"description": "Convex backend skill for building reactive, type-safe, production-grade backends. Helps Claude design schemas, server functions, auth, file storage, scheduled jobs, and real-time multiplayer features on Convex.",
|
||||
"name": "convex",
|
||||
"displayName": "Convex",
|
||||
"description": "Official Convex plugin for Claude Code with bundled Convex skills, the convex-expert subagent for code-writing, a runtime-error monitor, and MCP access for backend development, schema design, real-time features, auth, file storage, scheduled jobs, and AI agents.",
|
||||
"author": {
|
||||
"name": "Convex"
|
||||
"name": "Convex",
|
||||
"url": "https://convex.dev"
|
||||
},
|
||||
"category": "development",
|
||||
"category": "database",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/get-convex/convex-backend-skill.git",
|
||||
"sha": "5e59870cda2a5892e18a7164d1a46fcf57b70bea"
|
||||
},
|
||||
"homepage": "https://convex.dev"
|
||||
"homepage": "https://github.com/get-convex/convex-backend-skill",
|
||||
"keywords": [
|
||||
"convex",
|
||||
"backend",
|
||||
"database",
|
||||
"realtime",
|
||||
"reactive",
|
||||
"websocket",
|
||||
"auth",
|
||||
"storage",
|
||||
"scheduler",
|
||||
"cron",
|
||||
"agent",
|
||||
"rag",
|
||||
"mobile",
|
||||
"typescript",
|
||||
"mcp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "crowdstrike-falcon-foundry",
|
||||
@@ -2566,6 +2585,20 @@
|
||||
},
|
||||
"homepage": "https://github.com/vercel/vercel-plugin"
|
||||
},
|
||||
{
|
||||
"name": "vibe-prospecting",
|
||||
"description": "Vibe Prospecting connects Claude to live B2B company and contact data so users can search, match, enrich, filter, and export prospects at scale. It turns natural-language requests into structured GTM workflows for lead generation, CRM enrichment, company research, executive discovery, and multi-step prospecting automation inside Claude Cowork and Claude Code.",
|
||||
"author": {
|
||||
"name": "vibeprospecting.ai"
|
||||
},
|
||||
"category": "productivity",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/explorium-ai/vibeprospecting-plugin.git",
|
||||
"sha": "ada4d569dbf70194fe18750ecbc5170e9a3f120a"
|
||||
},
|
||||
"homepage": "https://www.vibeprospecting.ai/product/claude-plugin"
|
||||
},
|
||||
{
|
||||
"name": "windsor-ai",
|
||||
"description": "Connect Claude Code to 325+ business data sources via Windsor.ai. Query marketing, sales, CRM, ecommerce, finance, and analytics data from Google Ads, Meta, HubSpot, Salesforce, Shopify, Stripe, and hundreds more — directly from your terminal.",
|
||||
|
||||
163
.github/workflows/scan-plugins.yml
vendored
163
.github/workflows/scan-plugins.yml
vendored
@@ -381,3 +381,166 @@ jobs:
|
||||
echo "::error::Scan step failed without a parseable policy verdict (likely an infra error)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# emit-verdict: post a sticky comment per entry to the bump PR with the
|
||||
# structured verdict, so downstream tooling (label automation, delist
|
||||
# authoring) can read verdicts directly instead of scraping job logs.
|
||||
# Sticky comment marker: `<!-- bump-pr-verdict:<name> -->`.
|
||||
#
|
||||
# Mirrors the schema_v1 contract from
|
||||
# anthropics/claude-plugins-community-internal#3908 so the triage scripts
|
||||
# in mcp-local-directory/scripts/triage/ work uniformly across both repos.
|
||||
# -official doesn't run per-entry static checks (zombie, schema, binaries,
|
||||
# etc.) so the `scan.*` axes are emitted as "skipped". The granular policy
|
||||
# booleans (`has_broad_scope_hooks`, `has_undisclosed_telemetry`,
|
||||
# `description_matches_behavior`) aren't surfaced by this workflow's
|
||||
# per-entry artifact yet, so they're emitted as null; the triage
|
||||
# `triage_bool_to_str` helper maps null → "?" so display is graceful.
|
||||
# Status describes the execution state, not the outcome — `ran` when the
|
||||
# scan action evaluated this SHA fresh, `cached` when a prior verdict was
|
||||
# reused (cf. run-verdicts.json's `source` field). Outcome lives in
|
||||
# `policy.passes`. policy-sweep.sh dispatches on this exact vocabulary.
|
||||
#
|
||||
# PR resolution: pull_request events carry the PR number directly. The
|
||||
# bump workflow creates bump PRs via GITHUB_TOKEN (which doesn't fire
|
||||
# pull_request triggers — recursion guard) and dispatches this scan via
|
||||
# workflow_dispatch on the bump branch. In that case we look up the
|
||||
# open PR by head ref. No PR (scan_all dispatch on main, etc.) → no-op.
|
||||
#
|
||||
# continue-on-error at the job level: emit failure must NOT block the
|
||||
# `scan` required check. Consumers fall back to log-scraping if the
|
||||
# comment is absent (gradual migration; no flag day).
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
emit-verdict:
|
||||
needs: [scan]
|
||||
if: always() && needs.scan.result != 'skipped' && needs.scan.result != 'cancelled'
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Download scan verdicts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: scan-verdicts
|
||||
path: /tmp/scan-verdicts
|
||||
continue-on-error: true
|
||||
|
||||
- name: Resolve PR number for this ref
|
||||
id: pr
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_FROM_EVENT: ${{ github.event.pull_request.number }}
|
||||
REF: ${{ github.ref_name }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "$EVENT_NAME" == "pull_request" && -n "$PR_FROM_EVENT" ]]; then
|
||||
echo "number=$PR_FROM_EVENT" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
# workflow_dispatch on the bump branch: find the open PR for it.
|
||||
# head filter takes the form owner:branch.
|
||||
owner="${REPO%%/*}"
|
||||
pr=$(gh api "/repos/${REPO}/pulls?state=open&head=${owner}:${REF}&per_page=1" \
|
||||
--jq '.[0].number // ""')
|
||||
if [[ -z "$pr" ]]; then
|
||||
echo "::notice::No open PR for ref ${REF} — sticky comments skipped (verdicts still in scan-verdicts artifact)"
|
||||
fi
|
||||
echo "number=$pr" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build and post sticky comments
|
||||
if: steps.pr.outputs.number != ''
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
PR: ${{ steps.pr.outputs.number }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
verdicts_path=/tmp/scan-verdicts/run-verdicts.json
|
||||
# Missing/empty artifact: scan job ran but didn't produce verdicts
|
||||
# (e.g. the relevance gate said "no changes"). Nothing to comment;
|
||||
# exit clean.
|
||||
if [[ ! -s "$verdicts_path" ]]; then
|
||||
echo "::notice::No run-verdicts.json artifact — nothing to emit"
|
||||
exit 0
|
||||
fi
|
||||
count=$(jq 'length' "$verdicts_path")
|
||||
if [[ "$count" == "0" ]]; then
|
||||
echo "::notice::run-verdicts.json is empty — nothing to emit"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ran_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
# scan.* axes: -official doesn't run per-entry static checks; emit
|
||||
# "skipped" for each so the schema is shape-compatible with -internal.
|
||||
scan_stub='{"clone":"skipped","subpath_missing":"skipped","schema":"skipped","zombie":"skipped","tool_allowlist":"skipped","binaries":"skipped","unique":"skipped","mcp":"skipped"}'
|
||||
|
||||
# Pre-fetch all PR comments once (paginated) for the marker lookup.
|
||||
gh api --paginate "/repos/$REPO/issues/$PR/comments" \
|
||||
--jq '.[] | {id, body}' > /tmp/comments.ndjson
|
||||
|
||||
jq -c '.[]' "$verdicts_path" | while read -r entry; do
|
||||
name=$(jq -r '.name' <<< "$entry")
|
||||
passes=$(jq -r '.passes' <<< "$entry")
|
||||
summary=$(jq -r '.summary // ""' <<< "$entry")
|
||||
violations=$(jq -r '.violations // ""' <<< "$entry")
|
||||
source=$(jq -r '.source // "scan"' <<< "$entry")
|
||||
|
||||
# status = execution state (cf. -internal#3908 vocabulary).
|
||||
# Outcome is in `passes`. Map source → status: scan-action-run
|
||||
# → "ran"; cache-served → "cached". Anything else falls through
|
||||
# as "ran" (only those two values appear in run-verdicts.json).
|
||||
case "$source" in
|
||||
cache) status="cached" ;;
|
||||
scan) status="ran" ;;
|
||||
*) status="ran" ;;
|
||||
esac
|
||||
|
||||
policy=$(jq -n \
|
||||
--argjson passes "$passes" \
|
||||
--arg summary "$summary" \
|
||||
--arg violations "$violations" \
|
||||
--arg source "$source" \
|
||||
--arg status "$status" \
|
||||
'{passes: $passes,
|
||||
has_broad_scope_hooks: null,
|
||||
has_undisclosed_telemetry: null,
|
||||
description_matches_behavior: null,
|
||||
summary: $summary,
|
||||
violations: $violations,
|
||||
source: $source,
|
||||
status: $status}')
|
||||
|
||||
verdict=$(jq -n \
|
||||
--argjson scan "$scan_stub" \
|
||||
--argjson policy "$policy" \
|
||||
--arg ran_at "$ran_at" \
|
||||
--arg run_id "$RUN_ID" \
|
||||
'{schema_version: 1, ran_at: $ran_at, run_id: $run_id, scan: $scan, policy: $policy}')
|
||||
|
||||
marker="<!-- bump-pr-verdict:$name -->"
|
||||
body=$(printf '%s\n```json\n%s\n```' "$marker" "$verdict")
|
||||
|
||||
# jq's first() short-circuits and avoids SIGPIPE under pipefail if
|
||||
# duplicate markers exist (shouldn't, but a prior buggy run could
|
||||
# double-post). -s slurps NDJSON; `// empty` yields no output when
|
||||
# no match.
|
||||
existing=$(jq -rs --arg m "$marker" \
|
||||
'first(.[] | select(.body | startswith($m)) | .id) // empty' \
|
||||
/tmp/comments.ndjson)
|
||||
|
||||
if [[ -n "$existing" ]]; then
|
||||
gh api -X PATCH "/repos/$REPO/issues/comments/$existing" -f body="$body" >/dev/null
|
||||
echo "Updated comment $existing for $name"
|
||||
else
|
||||
gh api -X POST "/repos/$REPO/issues/$PR/comments" -f body="$body" >/dev/null
|
||||
echo "Created comment for $name"
|
||||
fi
|
||||
done
|
||||
|
||||
202
LICENSE
Normal file
202
LICENSE
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
31
README.md
31
README.md
@@ -42,6 +42,37 @@ plugin-name/
|
||||
└── README.md # Documentation
|
||||
```
|
||||
|
||||
## Skill-bundle plugins
|
||||
|
||||
When a plugin's source repository ships skills (`SKILL.md` files) without a `.claude-plugin/plugin.json` manifest, the marketplace entry can declare the skills directly using `strict: false` and an explicit `skills` array.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "example-bundle",
|
||||
"description": "Brief description of the bundled skills.",
|
||||
"author": { "name": "Author Name" },
|
||||
"category": "development",
|
||||
"source": {
|
||||
"source": "git-subdir",
|
||||
"url": "https://github.com/example-org/sdk.git",
|
||||
"path": "packages/agent-skills",
|
||||
"ref": "main",
|
||||
"sha": "<commit sha>"
|
||||
},
|
||||
"strict": false,
|
||||
"skills": [
|
||||
"./skill-a",
|
||||
"./skill-b",
|
||||
"./skill-c"
|
||||
],
|
||||
"homepage": "https://github.com/example-org/sdk"
|
||||
}
|
||||
```
|
||||
|
||||
Each path in `skills` is relative to `source.path` and points at a directory containing a `SKILL.md`. Paths can reach deeper than a single level — for example, `["./libA/skill-1", "./libB/skill-2"]` exposes a curated subset across multiple library subdirectories. Each skill is registered as `<plugin-name>:<skill-name>` in Claude Code.
|
||||
|
||||
For the underlying schema, see [Strict mode](https://code.claude.com/docs/en/plugin-marketplaces) in the marketplace documentation.
|
||||
|
||||
## License
|
||||
|
||||
Please see each linked plugin for the relevant LICENSE file.
|
||||
|
||||
@@ -39,7 +39,7 @@ ls -la package.json pyproject.toml Cargo.toml go.mod pom.xml 2>/dev/null
|
||||
cat package.json 2>/dev/null | head -50
|
||||
|
||||
# Check dependencies for MCP server recommendations
|
||||
cat package.json 2>/dev/null | grep -E '"(react|vue|angular|next|express|fastapi|django|prisma|supabase|stripe)"'
|
||||
cat package.json 2>/dev/null | grep -E '"(react|vue|angular|next|express|fastapi|django|prisma|supabase|convex|stripe)"'
|
||||
|
||||
# Check for existing Claude Code config
|
||||
ls -la .claude/ CLAUDE.md 2>/dev/null
|
||||
@@ -55,7 +55,7 @@ ls -la src/ app/ lib/ tests/ components/ pages/ api/ 2>/dev/null
|
||||
| Language/Framework | package.json, pyproject.toml, import patterns | Hooks, MCP servers |
|
||||
| Frontend stack | React, Vue, Angular, Next.js | Playwright MCP, frontend skills |
|
||||
| Backend stack | Express, FastAPI, Django | API documentation tools |
|
||||
| Database | Prisma, Supabase, raw SQL | Database MCP servers |
|
||||
| Database | Prisma, Supabase, Convex, raw SQL | Database / backend MCP servers |
|
||||
| External APIs | Stripe, OpenAI, AWS SDKs | context7 MCP for docs |
|
||||
| Testing | Jest, pytest, Playwright configs | Testing hooks, subagents |
|
||||
| CI/CD | GitHub Actions, CircleCI | GitHub MCP server |
|
||||
@@ -75,6 +75,7 @@ See [references/mcp-servers.md](references/mcp-servers.md) for detailed patterns
|
||||
| Uses popular libraries (React, Express, etc.) | **context7** - Live documentation lookup |
|
||||
| Frontend with UI testing needs | **Playwright** - Browser automation/testing |
|
||||
| Uses Supabase | **Supabase MCP** - Direct database operations |
|
||||
| Uses Convex | **Convex MCP** - Live deployment introspection, run queries/mutations, manage env vars and logs |
|
||||
| PostgreSQL/MySQL database | **Database MCP** - Query and schema tools |
|
||||
| GitHub repository | **GitHub MCP** - Issues, PRs, actions |
|
||||
| Uses Linear for issues | **Linear MCP** - Issue management |
|
||||
|
||||
@@ -72,6 +72,18 @@ MCP (Model Context Protocol) servers extend Claude's capabilities by connecting
|
||||
|
||||
**Value**: Claude can query tables, manage auth, and interact with Supabase storage directly.
|
||||
|
||||
### Convex MCP
|
||||
**Best for**: Projects using Convex as the backend (reactive database + server functions + auth + storage + scheduling, all on one platform)
|
||||
|
||||
| Recommend When | Examples |
|
||||
|----------------|----------|
|
||||
| Convex project detected | `convex` in deps, `convex/` directory present, `convex.json` at repo root |
|
||||
| Real-time / reactive UI | `useQuery` / `useMutation` / `useAction` from `convex/react` |
|
||||
| Mobile + Convex | `convex/react-native` in deps |
|
||||
| AI / chat / agent features on Convex | `@convex-dev/agent` in deps |
|
||||
|
||||
**Value**: Claude can introspect the live deployment (tables, function specs, env vars, logs) and execute queries/mutations against it via tools like `tables`, `function-spec`, `data`, `run-once-query`, `logs`, `env list/set/get`. Run via `npx convex mcp start`.
|
||||
|
||||
### PostgreSQL MCP
|
||||
**Best for**: Direct PostgreSQL database access
|
||||
|
||||
@@ -253,6 +265,7 @@ MCP (Model Context Protocol) servers extend Claude's capabilities by connecting
|
||||
| Popular npm packages | context7 |
|
||||
| React/Vue/Next.js | Playwright MCP |
|
||||
| `@supabase/supabase-js` | Supabase MCP |
|
||||
| `convex` in deps, `convex/` directory, or `convex.json` | Convex MCP |
|
||||
| `pg` or `postgres` | PostgreSQL MCP |
|
||||
| GitHub remote | GitHub MCP |
|
||||
| `.linear` or Linear refs | Linear MCP |
|
||||
|
||||
@@ -32,6 +32,8 @@ BUILD_FAILED = 3 # venv create or pip install raised/timed out
|
||||
# llm.py also matches Windows venv layout (Lib/site-packages). Don't reuse the
|
||||
# value — telemetry rows from older plugin builds still emit 4.
|
||||
SKIP_SENTINEL = 5 # another SessionStart is currently building
|
||||
HOOK_PY_INCOMPATIBLE = 6 # hook interpreter is <3.10 — SDK syntax can't load
|
||||
# here no matter how the venv was built. See #2071.
|
||||
|
||||
|
||||
def _sdk_on_syspath() -> bool:
|
||||
@@ -62,6 +64,29 @@ def main() -> tuple[int, str, str]:
|
||||
err_phase / err_kind are non-empty only on BUILD_FAILED — they let
|
||||
telemetry split bootstrap failures by root cause.
|
||||
"""
|
||||
# Honesty check (fixes the misleading NOOP_VENV in #2071): the SDK
|
||||
# requires Python >=3.10 and uses 3.10+ syntax (match statements,
|
||||
# PEP 604 unions). On a 3.9 hook interpreter we CANNOT import it no
|
||||
# matter how the venv was built — llm.py runs in this same interpreter
|
||||
# and the syntax-level import will SyntaxError. macOS ships 3.9.6 as
|
||||
# the default `python3` and `/usr/bin` precedes Homebrew in PATH, so
|
||||
# this case is the default state for a large share of macOS users.
|
||||
#
|
||||
# sg-python.sh now prefers python3.10+ binaries so most users won't
|
||||
# reach this branch; the fallback to 3.9 is preserved for the
|
||||
# pattern-warning hooks that don't need the SDK. Reporting
|
||||
# HOOK_PY_INCOMPATIBLE here:
|
||||
# (a) avoids 30-60s of wasted pip install,
|
||||
# (b) avoids the lie where the venv_py probe says NOOP_VENV but the
|
||||
# consumer import fails, and
|
||||
# (c) gives telemetry a clean bucket to size the affected fleet.
|
||||
if sys.version_info < (3, 10):
|
||||
return (
|
||||
HOOK_PY_INCOMPATIBLE,
|
||||
"hook_py",
|
||||
f"py_{sys.version_info[0]}.{sys.version_info[1]}",
|
||||
)
|
||||
|
||||
if _sdk_on_syspath():
|
||||
return NOOP_SYSTEM, "", ""
|
||||
|
||||
@@ -195,6 +220,56 @@ def main() -> tuple[int, str, str]:
|
||||
sentinel.unlink(missing_ok=True)
|
||||
|
||||
|
||||
def _maybe_emit_user_notice(outcome: int, pv: int) -> str | None:
|
||||
"""Return a one-time user-visible notice when the agentic reviewer is
|
||||
in a persistent broken state on this machine, or None if we've already
|
||||
shown the notice for this plugin version (or shouldn't show one).
|
||||
|
||||
The marker file is plugin-version-keyed: a future plugin update can
|
||||
re-notify if behavior changes (e.g. we ship out-of-process SDK in v3
|
||||
and want to tell affected users it's fixed). Failures to write the
|
||||
marker degrade to "skip the notice this session" so we don't spam
|
||||
every SessionStart on a read-only home dir.
|
||||
|
||||
Currently only HOOK_PY_INCOMPATIBLE qualifies. BUILD_FAILED is
|
||||
intentionally excluded — it covers transient causes (network failure,
|
||||
pip registry hiccup, in-flight rebuild) where the next session may
|
||||
succeed and a permanent notice would mislead.
|
||||
"""
|
||||
if outcome != HOOK_PY_INCOMPATIBLE:
|
||||
return None
|
||||
try:
|
||||
state_dir = Path(
|
||||
os.environ.get("SECURITY_WARNINGS_STATE_DIR")
|
||||
or os.path.expanduser("~/.claude/security")
|
||||
)
|
||||
marker = state_dir / f".agentic_unavailable_notice_v{pv or 0}"
|
||||
if marker.exists():
|
||||
return None
|
||||
state_dir.mkdir(parents=True, exist_ok=True)
|
||||
# Write timestamp + Python version so the marker is self-documenting
|
||||
# if a user goes looking. O_EXCL would be racier with no real win
|
||||
# (two concurrent SessionStarts both showing the notice once is fine).
|
||||
marker.write_text(
|
||||
f"{time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())} "
|
||||
f"py={sys.version_info[0]}.{sys.version_info[1]}\n"
|
||||
)
|
||||
except OSError:
|
||||
return None
|
||||
return (
|
||||
f"⚠ security-guidance plugin: the cross-file commit reviewer "
|
||||
f"(layer 3 of 3 — catches IDOR, auth-bypass, cross-file SSRF) "
|
||||
f"is unavailable in this environment. It requires Python ≥3.10, "
|
||||
f"but the hook is running on "
|
||||
f"{sys.version_info[0]}.{sys.version_info[1]}.\n\n"
|
||||
f"Pattern checks and the single-shot LLM diff review are still "
|
||||
f"active. To enable the deeper reviewer, install Python 3.10+ "
|
||||
f"(e.g. `brew install python` on macOS) and restart Claude Code.\n\n"
|
||||
f"This notice is shown once per plugin version. "
|
||||
f"See: github.com/anthropics/claude-plugins-official/issues/2071"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Tell the harness this is async — venv create + pip install can take
|
||||
# 30-60s on a cold cache, well past the default sync hook timeout.
|
||||
@@ -231,4 +306,18 @@ if __name__ == "__main__":
|
||||
pv = _plugin_version_int()
|
||||
if pv:
|
||||
metrics["pv"] = pv
|
||||
print(json.dumps({"metrics": metrics}), flush=True)
|
||||
response: dict[str, object] = {"metrics": metrics}
|
||||
# One-time user-visible notice when the agentic reviewer is dead on
|
||||
# arrival. Uses hookSpecificOutput.additionalContext (SessionStart's
|
||||
# supported channel for surfacing text to both the model and the user)
|
||||
# plus systemMessage as a belt-and-suspenders. Marker-file-gated so
|
||||
# this fires exactly once per plugin version per install — see
|
||||
# _maybe_emit_user_notice.
|
||||
notice = _maybe_emit_user_notice(outcome, pv)
|
||||
if notice:
|
||||
response["hookSpecificOutput"] = {
|
||||
"hookEventName": "SessionStart",
|
||||
"additionalContext": notice,
|
||||
}
|
||||
response["systemMessage"] = notice
|
||||
print(json.dumps(response), flush=True)
|
||||
|
||||
@@ -47,21 +47,65 @@ fi
|
||||
|
||||
probe() {
|
||||
# $1..N: the interpreter command (may be multi-word like `py -3`)
|
||||
# Probe writes the major version to stdout and exits 0 iff it's >=3.
|
||||
"$@" -c 'import sys; print(sys.version_info[0])' 2>/dev/null
|
||||
# Writes "<major>.<minor>" to stdout and exits 0 iff at least Python 3.
|
||||
"$@" -c 'import sys; print(f"{sys.version_info[0]}.{sys.version_info[1]}")' 2>/dev/null
|
||||
}
|
||||
|
||||
# True iff arg is a "M.m" version string >= 3.10. claude_agent_sdk requires
|
||||
# Python >= 3.10; below that, pip install fails ("No matching distribution")
|
||||
# and the LLM-powered review (Stop / commit / push) silently no-ops while
|
||||
# pattern checks (PostToolUse regex) keep working. macOS ships 3.9.6 as the
|
||||
# default `python3` on current versions, so this guard matters in practice.
|
||||
# See anthropics/claude-plugins-official#2071.
|
||||
is_sdk_compatible() {
|
||||
case "$1" in
|
||||
3.1[0-9]|3.[2-9][0-9]|[4-9].*|[1-9][0-9].*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Pass 1 — try minor-versioned binaries in descending order. These are only
|
||||
# present if the user explicitly installed them (Homebrew / python.org / pyenv),
|
||||
# so picking one here always upgrades over the system `python3`. Highest
|
||||
# available wins; the user doesn't have to PATH-prefer it.
|
||||
for cmd in "python3.13" "python3.12" "python3.11" "python3.10"; do
|
||||
v=$(probe "$cmd") || continue
|
||||
if is_sdk_compatible "$v"; then
|
||||
exec "$cmd" "$@"
|
||||
fi
|
||||
done
|
||||
|
||||
# Pass 2 — bare interpreters, but only if SDK-compatible. Covers Linux distros
|
||||
# that ship 3.10+ as the default `python3`, and Windows where `python` /
|
||||
# `py -3` resolves to the user's python.org install.
|
||||
for cmd in "python3" "python" "py -3"; do
|
||||
# Word-split intentionally so `py -3` works
|
||||
# shellcheck disable=SC2086
|
||||
v=$(probe $cmd) || continue
|
||||
if [ "$v" = "3" ]; then
|
||||
if is_sdk_compatible "$v"; then
|
||||
# shellcheck disable=SC2086
|
||||
exec $cmd "$@"
|
||||
fi
|
||||
done
|
||||
|
||||
# Pass 3 — fallback to any Python 3, even <3.10. Pattern-based checks
|
||||
# (PostToolUse regex on Edit/Write) only need 3.6+ and are useful on their
|
||||
# own; the SDK-dependent paths will detect the version mismatch and degrade
|
||||
# inside the Python code. Without this fallback, the entire plugin would
|
||||
# stop working on default macOS, which is a regression vs today.
|
||||
for cmd in "python3" "python" "py -3"; do
|
||||
# shellcheck disable=SC2086
|
||||
v=$(probe $cmd) || continue
|
||||
# Accept anything that successfully reported a "M.m" string.
|
||||
case "$v" in
|
||||
[0-9]*.[0-9]*)
|
||||
# shellcheck disable=SC2086
|
||||
exec $cmd "$@"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "security-guidance: no working Python 3 interpreter found." >&2
|
||||
echo " tried: python3, python, py -3" >&2
|
||||
echo " tried: python3.13, python3.12, python3.11, python3.10, python3, python, py -3" >&2
|
||||
echo " on Windows, install Python from https://python.org (NOT the Microsoft Store)" >&2
|
||||
echo " on macOS, install Python 3.10+ via Homebrew (\`brew install python\`)" >&2
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user