mirror of
https://github.com/anthropics/claude-plugins-official.git
synced 2026-06-16 14:23:35 +00:00
Compare commits
189 Commits
morganl/co
...
venv-targe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7fe15d9ba | ||
|
|
e97f9a40b9 | ||
|
|
78fa3df8d6 | ||
|
|
56fd6abb97 | ||
|
|
c9b8f92b53 | ||
|
|
7279412e77 | ||
|
|
484653886e | ||
|
|
c7af5e02bc | ||
|
|
8ea0761c82 | ||
|
|
600c99b404 | ||
|
|
d28241b7ef | ||
|
|
46c72e981f | ||
|
|
3f8fc630b8 | ||
|
|
fbd57be8e5 | ||
|
|
413d293096 | ||
|
|
e4a454a7eb | ||
|
|
d30ef44d74 | ||
|
|
6ee4f1e1df | ||
|
|
c4b91a6e24 | ||
|
|
e656f87725 | ||
|
|
eaa69c48cb | ||
|
|
46dc6920be | ||
|
|
92954b1b92 | ||
|
|
0784122e63 | ||
|
|
7465bdcc27 | ||
|
|
7209a2ca09 | ||
|
|
71941bb301 | ||
|
|
eeb3316d51 | ||
|
|
66bca6b6f6 | ||
|
|
be8b438e1a | ||
|
|
43297b9419 | ||
|
|
b110a96045 | ||
|
|
9087f2c348 | ||
|
|
9277728768 | ||
|
|
5518e4b87d | ||
|
|
2bf67d3cfd | ||
|
|
c5fd33161c | ||
|
|
2b58efffc3 | ||
|
|
f4cf218b9b | ||
|
|
db5b3d5999 | ||
|
|
5316ced830 | ||
|
|
13ac3cb075 | ||
|
|
5a20d10780 | ||
|
|
9eae436aa2 | ||
|
|
ee7ce490f9 | ||
|
|
460bc2b3a4 | ||
|
|
1a7db730cb | ||
|
|
3ebb9c7a85 | ||
|
|
9ef08d32aa | ||
|
|
b8e4462957 | ||
|
|
2f9c3234ab | ||
|
|
c5660ed060 | ||
|
|
9ecfe41bdd | ||
|
|
d5265b0377 | ||
|
|
c7f3eb4b8f | ||
|
|
3b46b04964 | ||
|
|
a379ddd580 | ||
|
|
8a0797c1eb | ||
|
|
447aef7de0 | ||
|
|
7e9d5e46d1 | ||
|
|
14e6461b03 | ||
|
|
634ea8dfdf | ||
|
|
fa5b2907d3 | ||
|
|
f0a6e581ab | ||
|
|
820c25f30e | ||
|
|
62e1eee8ba | ||
|
|
1266fa54fe | ||
|
|
662eb2a84d | ||
|
|
b9fcf71aa3 | ||
|
|
276c66d983 | ||
|
|
96627692d8 | ||
|
|
2dad4fb0e9 | ||
|
|
764c85b81b | ||
|
|
0fc58e49d1 | ||
|
|
14207a6858 | ||
|
|
51081f898a | ||
|
|
c6cd307f91 | ||
|
|
1f41ee16b7 | ||
|
|
0590b22bed | ||
|
|
c0e06a05f0 | ||
|
|
cb3f6930c7 | ||
|
|
481d531f7d | ||
|
|
9d53eaee3b | ||
|
|
887f70cb5d | ||
|
|
a96db3dd4d | ||
|
|
5a4b44267a | ||
|
|
627d4dd3c4 | ||
|
|
4902efd113 | ||
|
|
cf6decf9e8 | ||
|
|
088593ec3b | ||
|
|
206d02f684 | ||
|
|
e2be9a8197 | ||
|
|
68a97f85ba | ||
|
|
f1aaa8e4ce | ||
|
|
5b6b55808d | ||
|
|
db71168abe | ||
|
|
1f761e4c37 | ||
|
|
8f09d55614 | ||
|
|
d0419b8ad5 | ||
|
|
09404ab125 | ||
|
|
de573bd846 | ||
|
|
f92fc04666 | ||
|
|
2b8ae0bc72 | ||
|
|
1b3d7c29eb | ||
|
|
26e06be79b | ||
|
|
5e14a52052 | ||
|
|
640704824b | ||
|
|
e53f64964b | ||
|
|
a9310efd27 | ||
|
|
b6a4ea1f6a | ||
|
|
2057bc4652 | ||
|
|
0bcd12a7d1 | ||
|
|
f2691c1439 | ||
|
|
330492c3d6 | ||
|
|
e7e1e791cb | ||
|
|
0714e5b202 | ||
|
|
623b6704d3 | ||
|
|
f5e552802c | ||
|
|
e69b3a26ef | ||
|
|
475e5fe15f | ||
|
|
b61e11909c | ||
|
|
7eb80c4f5b | ||
|
|
1e0be923c5 | ||
|
|
df5224ba07 | ||
|
|
e832e2bf0d | ||
|
|
9895dfca58 | ||
|
|
83d32aefd5 | ||
|
|
2804bac441 | ||
|
|
a1936eee01 | ||
|
|
b8ecaf01a6 | ||
|
|
d2bae5e20b | ||
|
|
e96f539e2d | ||
|
|
77c424ab52 | ||
|
|
a771b69148 | ||
|
|
301dfbc752 | ||
|
|
6f5b19f93b | ||
|
|
85d6e100e2 | ||
|
|
6829c593c8 | ||
|
|
0c33859bd9 | ||
|
|
1c5aba82fb | ||
|
|
2092653e18 | ||
|
|
7ba21d89e2 | ||
|
|
0445ef3cf4 | ||
|
|
190a64c2ed | ||
|
|
f7ac27f10c | ||
|
|
488e71feb9 | ||
|
|
2e5bcca08e | ||
|
|
8681d8d6d1 | ||
|
|
0ec0005a3c | ||
|
|
7f680b8500 | ||
|
|
8f005f9b76 | ||
|
|
746c982737 | ||
|
|
88233b24ba | ||
|
|
4f49895abd | ||
|
|
9d49c4b135 | ||
|
|
ff5feaeb7f | ||
|
|
379a00dba5 | ||
|
|
0161a176c7 | ||
|
|
7dd654e4ea | ||
|
|
b167faa74a | ||
|
|
bdde825b98 | ||
|
|
cd49446ad3 | ||
|
|
b667e7f193 | ||
|
|
a3a7e77735 | ||
|
|
6ab6953eee | ||
|
|
27524414d8 | ||
|
|
336212b41d | ||
|
|
dd7fcb43f2 | ||
|
|
ebecea5c95 | ||
|
|
8525d71094 | ||
|
|
8288a4a320 | ||
|
|
0d91490722 | ||
|
|
de6b8cf296 | ||
|
|
b4f01b62bf | ||
|
|
d7d03756e2 | ||
|
|
54eb24e9d6 | ||
|
|
8acfe8b3cb | ||
|
|
1fb5d16181 | ||
|
|
8aac392a4d | ||
|
|
eeb0e11315 | ||
|
|
22be09177b | ||
|
|
1f5ce124fa | ||
|
|
30f8e267a1 | ||
|
|
7be381f4cf | ||
|
|
3175a58228 | ||
|
|
c78c61e117 | ||
|
|
e7710f24ba | ||
|
|
2fe8c1d7ad | ||
|
|
43fcf6d513 |
@@ -19,7 +19,7 @@
|
||||
"url": "https://github.com/42Crunch-AI/claude-plugins.git",
|
||||
"path": "plugins/api-security-testing",
|
||||
"ref": "v1.5.5",
|
||||
"sha": "db2fb7e53e3d93a863930b6f6b7895be5ee01f21"
|
||||
"sha": "5cfa510f7ea4d940f0ff5f6688a21e4ea0db0a18"
|
||||
},
|
||||
"homepage": "https://42crunch.com"
|
||||
},
|
||||
@@ -35,7 +35,7 @@
|
||||
"url": "https://github.com/adobe/skills.git",
|
||||
"path": "plugins/creative-cloud/adobe-for-creativity",
|
||||
"ref": "main",
|
||||
"sha": "e23271f65aa7572f567d085d6baec5c2408e2ad5"
|
||||
"sha": "253f56901e058800ccb97ffd5bf1e3329d5f2e00"
|
||||
},
|
||||
"homepage": "https://github.com/adobe/skills/tree/main/plugins/creative-cloud/adobe-for-creativity"
|
||||
},
|
||||
@@ -67,7 +67,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/endorlabs/ai-plugins.git",
|
||||
"sha": "975f0ce422b1f2677681ffd085aef34ea1826b70"
|
||||
"sha": "a6737fcf72336399e212e45cd25a250c2df3b7b4"
|
||||
},
|
||||
"homepage": "https://www.endorlabs.com"
|
||||
},
|
||||
@@ -77,7 +77,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/AikidoSec/aikido-claude-plugin.git",
|
||||
"sha": "79ac524f87c9faa9a356ff3d495b8a5b77e01bbd"
|
||||
"sha": "603d5eac5ef00d9db65fa4f15058345e7bce3352"
|
||||
},
|
||||
"homepage": "https://github.com/AikidoSec/aikido-claude-plugin"
|
||||
},
|
||||
@@ -93,7 +93,7 @@
|
||||
"url": "https://github.com/Airtable/skills.git",
|
||||
"path": "plugins/airtable",
|
||||
"ref": "main",
|
||||
"sha": "21d2fe52774d861e2f2f997eeac2bf965e8590b8"
|
||||
"sha": "295ab93b7d765912ee1a0dc7f1abb0ecaf73f138"
|
||||
},
|
||||
"homepage": "https://www.airtable.com"
|
||||
},
|
||||
@@ -109,7 +109,7 @@
|
||||
"url": "https://github.com/airwallex/airwallex-marketplace.git",
|
||||
"path": "plugins/airwallex",
|
||||
"ref": "master",
|
||||
"sha": "a903ab7693a5f6d46f2fab6f895a2f96a879ee0f"
|
||||
"sha": "a49ef1ec801fd776adc4db9f2bb4a78463981bc9"
|
||||
},
|
||||
"homepage": "https://www.airwallex.com/docs"
|
||||
},
|
||||
@@ -150,7 +150,7 @@
|
||||
"url": "https://github.com/awslabs/agent-plugins.git",
|
||||
"path": "plugins/amazon-location-service",
|
||||
"ref": "main",
|
||||
"sha": "fc54dfa24a1f05095b9fcbb4baa4750996bb171d"
|
||||
"sha": "58373593c6ed2e4684181f81369c0b7a4c916423"
|
||||
},
|
||||
"homepage": "https://github.com/awslabs/agent-plugins"
|
||||
},
|
||||
@@ -161,7 +161,7 @@
|
||||
"url": "https://github.com/amplitude/mcp-marketplace.git",
|
||||
"path": "plugins/amplitude",
|
||||
"ref": "main",
|
||||
"sha": "e9b4e15193666e1b513b5652ded23fab160bdc4e"
|
||||
"sha": "fb22979da93d27dcb17b832dbd473e6b0caf2ca8"
|
||||
},
|
||||
"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",
|
||||
@@ -223,7 +223,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/astronomer/agents.git",
|
||||
"sha": "7ce4a12d3cabb506294134c91a1b876d4b166a70"
|
||||
"sha": "789b4544b85a989694501e4f405b522f2d711cf6"
|
||||
},
|
||||
"homepage": "https://github.com/astronomer/agents"
|
||||
},
|
||||
@@ -233,7 +233,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/atlanhq/agent-toolkit.git",
|
||||
"sha": "789507c02d2495235240d10d67aaac8b2051023a"
|
||||
"sha": "86bb1ad27f80e189b328333d2271b360ae579f2b"
|
||||
},
|
||||
"homepage": "https://docs.atlan.com/"
|
||||
},
|
||||
@@ -244,7 +244,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/atlassian/atlassian-mcp-server.git",
|
||||
"sha": "9b52fb18e184edc307ce33f8bf4cdf148dedf1f2"
|
||||
"sha": "f4911dba81f25782c88815b03deabf444cd46e0d"
|
||||
},
|
||||
"homepage": "https://github.com/atlassian/atlassian-mcp-server"
|
||||
},
|
||||
@@ -275,7 +275,7 @@
|
||||
"url": "https://github.com/auth0/agent-skills.git",
|
||||
"path": "plugins/auth0",
|
||||
"ref": "main",
|
||||
"sha": "bdf0dc23f8b17446b2c94bc9f2e5a58d3f1bc114"
|
||||
"sha": "b595bdb9b574569e864eef86c3d48c06e2cf414c"
|
||||
},
|
||||
"homepage": "https://auth0.com/docs/quickstart/agent-skills"
|
||||
},
|
||||
@@ -291,7 +291,7 @@
|
||||
"url": "https://github.com/aws/agent-toolkit-for-aws.git",
|
||||
"path": "plugins/aws-agents",
|
||||
"ref": "main",
|
||||
"sha": "55b9acfefdcf0866b6bc6cc56c16e6e18e65bd2b"
|
||||
"sha": "f5ba81082aafe865ffe947ceabc574a7a0353e57"
|
||||
},
|
||||
"homepage": "https://github.com/aws/agent-toolkit-for-aws"
|
||||
},
|
||||
@@ -304,7 +304,7 @@
|
||||
"url": "https://github.com/awslabs/agent-plugins.git",
|
||||
"path": "plugins/aws-amplify",
|
||||
"ref": "main",
|
||||
"sha": "fc54dfa24a1f05095b9fcbb4baa4750996bb171d"
|
||||
"sha": "58373593c6ed2e4684181f81369c0b7a4c916423"
|
||||
},
|
||||
"homepage": "https://github.com/awslabs/agent-plugins"
|
||||
},
|
||||
@@ -320,7 +320,7 @@
|
||||
"url": "https://github.com/aws/agent-toolkit-for-aws.git",
|
||||
"path": "plugins/aws-core",
|
||||
"ref": "main",
|
||||
"sha": "55b9acfefdcf0866b6bc6cc56c16e6e18e65bd2b"
|
||||
"sha": "f5ba81082aafe865ffe947ceabc574a7a0353e57"
|
||||
},
|
||||
"homepage": "https://github.com/aws/agent-toolkit-for-aws"
|
||||
},
|
||||
@@ -336,7 +336,7 @@
|
||||
"url": "https://github.com/aws/agent-toolkit-for-aws.git",
|
||||
"path": "plugins/aws-data-analytics",
|
||||
"ref": "main",
|
||||
"sha": "55b9acfefdcf0866b6bc6cc56c16e6e18e65bd2b"
|
||||
"sha": "f5ba81082aafe865ffe947ceabc574a7a0353e57"
|
||||
},
|
||||
"homepage": "https://github.com/aws/agent-toolkit-for-aws"
|
||||
},
|
||||
@@ -365,7 +365,7 @@
|
||||
"url": "https://github.com/awslabs/agent-plugins.git",
|
||||
"path": "plugins/aws-serverless",
|
||||
"ref": "main",
|
||||
"sha": "fc54dfa24a1f05095b9fcbb4baa4750996bb171d"
|
||||
"sha": "58373593c6ed2e4684181f81369c0b7a4c916423"
|
||||
},
|
||||
"homepage": "https://github.com/awslabs/agent-plugins"
|
||||
},
|
||||
@@ -381,7 +381,7 @@
|
||||
"url": "https://github.com/awslabs/startups.git",
|
||||
"path": "advisor/plugins/aws-startup-advisor",
|
||||
"ref": "main",
|
||||
"sha": "1dd909352dc228f978c2685724cb38e64efe6be4"
|
||||
"sha": "944e5b17bb4b6a84a76b6382e3f5d7fa9abd7bbd"
|
||||
},
|
||||
"homepage": "https://github.com/awslabs/startups"
|
||||
},
|
||||
@@ -392,7 +392,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/microsoft/azure-skills.git",
|
||||
"sha": "02a614f6ee1f052826f834d65c61e430ad152c8e"
|
||||
"sha": "966330ee4fc61978b6e324993687e917125a1f36"
|
||||
},
|
||||
"homepage": "https://github.com/microsoft/azure-skills"
|
||||
},
|
||||
@@ -414,7 +414,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/base44/skills.git",
|
||||
"sha": "ec420cf2edd2c7e9a523d5afe2e71498a6357fa4"
|
||||
"sha": "aef0fa35f21b3c0c000d5ab8c0b068e6188618b6"
|
||||
},
|
||||
"homepage": "https://docs.base44.com"
|
||||
},
|
||||
@@ -430,7 +430,7 @@
|
||||
"url": "https://github.com/Bigdata-com/bigdata-plugins-marketplace.git",
|
||||
"path": "plugins/bigdata-com",
|
||||
"ref": "main",
|
||||
"sha": "67c30be97a0a3f46bc6e8d56df449ae108eda9c5"
|
||||
"sha": "76a043a08c0a10eb73756d04031a613568017067"
|
||||
},
|
||||
"homepage": "https://docs.bigdata.com"
|
||||
},
|
||||
@@ -472,7 +472,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/brightdata/skills.git",
|
||||
"sha": "bd5bd76bc889f54b744bab3db3cbd42751a1e5b0"
|
||||
"sha": "8d427e9871566efe3f0a1c8888f98b6fe8288831"
|
||||
},
|
||||
"homepage": "https://docs.brightdata.com"
|
||||
},
|
||||
@@ -502,7 +502,7 @@
|
||||
"url": "https://github.com/carta/plugins.git",
|
||||
"path": "plugins/carta-cap-table",
|
||||
"ref": "main",
|
||||
"sha": "9eb312908f4a2e2d15e4e935320981433a549f77"
|
||||
"sha": "ab95e738e5fa8945d0e0faa1e43b7d618980ac76"
|
||||
},
|
||||
"homepage": "https://carta.com"
|
||||
},
|
||||
@@ -518,7 +518,7 @@
|
||||
"url": "https://github.com/carta/plugins.git",
|
||||
"path": "plugins/carta-crm",
|
||||
"ref": "main",
|
||||
"sha": "9eb312908f4a2e2d15e4e935320981433a549f77"
|
||||
"sha": "4b5796517b62c4aeaac1a0bb6ccdaebeb73475a5"
|
||||
},
|
||||
"homepage": "https://carta.com"
|
||||
},
|
||||
@@ -534,7 +534,7 @@
|
||||
"url": "https://github.com/carta/plugins.git",
|
||||
"path": "plugins/carta-investors",
|
||||
"ref": "main",
|
||||
"sha": "9eb312908f4a2e2d15e4e935320981433a549f77"
|
||||
"sha": "ab95e738e5fa8945d0e0faa1e43b7d618980ac76"
|
||||
},
|
||||
"homepage": "https://carta.com"
|
||||
},
|
||||
@@ -561,7 +561,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/ChromeDevTools/chrome-devtools-mcp.git",
|
||||
"sha": "702d3734f276a18efd67561ae00b88ce954cc515"
|
||||
"sha": "228cf3936ad99d9e0c09b43d77fbbac8712f2357"
|
||||
},
|
||||
"homepage": "https://github.com/ChromeDevTools/chrome-devtools-mcp"
|
||||
},
|
||||
@@ -720,7 +720,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/cloudflare/skills.git",
|
||||
"sha": "c5b7b06b073fa0b4abbd63964630f97d81da69c4"
|
||||
"sha": "12520fd63a1e958be217a93f48ce1f04bc9055f3"
|
||||
},
|
||||
"description": "Skills for the Cloudflare developer platform: Workers, Durable Objects, Agents SDK, MCP servers, Wrangler CLI, and web performance.",
|
||||
"category": "deployment",
|
||||
@@ -804,7 +804,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/CodSpeedHQ/codspeed.git",
|
||||
"sha": "c6112f168b405df8e7310b12a9b80484cd01ac14"
|
||||
"sha": "41f4db99123434f3e24d0b9caca3e2b65d7ee24d"
|
||||
},
|
||||
"homepage": "https://codspeed.io"
|
||||
},
|
||||
@@ -872,7 +872,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/CrowdStrike/foundry-skills.git",
|
||||
"sha": "c542c932956fd19177a62b94577f288c832d4680"
|
||||
"sha": "a7e6a75ad2d9aa4093771e8c07d455c1ce39aae1"
|
||||
},
|
||||
"homepage": "https://github.com/CrowdStrike/foundry-skills"
|
||||
},
|
||||
@@ -918,7 +918,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/dash0hq/dash0-agent-plugin.git",
|
||||
"sha": "5ff7aa5b8e52e10d10e45ea8e2f7cbebc86758bf"
|
||||
"sha": "37fd498b0775d98fcd27ff3c0fe3f68e412482a4"
|
||||
},
|
||||
"homepage": "https://dash0.com/"
|
||||
},
|
||||
@@ -929,7 +929,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/astronomer/agents.git",
|
||||
"sha": "7ce4a12d3cabb506294134c91a1b876d4b166a70"
|
||||
"sha": "789b4544b85a989694501e4f405b522f2d711cf6"
|
||||
},
|
||||
"homepage": "https://github.com/astronomer/agents"
|
||||
},
|
||||
@@ -943,7 +943,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/gemini-cli-extensions/data-agent-kit-starter-pack.git",
|
||||
"sha": "fb9086456d5fbc780edf86f0ac413345ba628173"
|
||||
"sha": "6f60c83ad13436f953224a61477d6380c199214b"
|
||||
},
|
||||
"homepage": "https://github.com/gemini-cli-extensions/data-agent-kit-starter-pack"
|
||||
},
|
||||
@@ -953,7 +953,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/astronomer/agents.git",
|
||||
"sha": "7ce4a12d3cabb506294134c91a1b876d4b166a70"
|
||||
"sha": "789b4544b85a989694501e4f405b522f2d711cf6"
|
||||
},
|
||||
"homepage": "https://github.com/astronomer/agents"
|
||||
},
|
||||
@@ -966,7 +966,7 @@
|
||||
"url": "https://github.com/awslabs/agent-plugins.git",
|
||||
"path": "plugins/databases-on-aws",
|
||||
"ref": "main",
|
||||
"sha": "fc54dfa24a1f05095b9fcbb4baa4750996bb171d"
|
||||
"sha": "58373593c6ed2e4684181f81369c0b7a4c916423"
|
||||
},
|
||||
"homepage": "https://github.com/awslabs/agent-plugins"
|
||||
},
|
||||
@@ -1008,7 +1008,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/gemini-cli-extensions/dataproc.git",
|
||||
"sha": "20eec06eee7683311689f4a1437cbb14ac8cd33e"
|
||||
"sha": "80d126d27d84ded752c84668472dd6f75896fc59"
|
||||
},
|
||||
"homepage": "https://github.com/gemini-cli-extensions/dataproc"
|
||||
},
|
||||
@@ -1022,7 +1022,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/datarobot-oss/datarobot-agent-skills.git",
|
||||
"sha": "b5a8f7a4bc4d31a1f139a232efbba6127af0474a"
|
||||
"sha": "ec2ecdd49d54ef490b344a850cff1feb1230c409"
|
||||
},
|
||||
"homepage": "https://datarobot.com"
|
||||
},
|
||||
@@ -1035,7 +1035,7 @@
|
||||
"url": "https://github.com/microsoft/Dataverse-skills.git",
|
||||
"path": ".github/plugins/dataverse",
|
||||
"ref": "main",
|
||||
"sha": "2d50cf65f80efc17ac50632222d61fb374115a70"
|
||||
"sha": "2c37394346be1afc1db12cc5b89f5dee3617c45c"
|
||||
},
|
||||
"homepage": "https://github.com/microsoft/Dataverse-skills"
|
||||
},
|
||||
@@ -1048,7 +1048,7 @@
|
||||
"url": "https://github.com/awslabs/agent-plugins.git",
|
||||
"path": "plugins/deploy-on-aws",
|
||||
"ref": "main",
|
||||
"sha": "fc54dfa24a1f05095b9fcbb4baa4750996bb171d"
|
||||
"sha": "58373593c6ed2e4684181f81369c0b7a4c916423"
|
||||
},
|
||||
"homepage": "https://github.com/awslabs/agent-plugins"
|
||||
},
|
||||
@@ -1126,7 +1126,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/exa-labs/exa-mcp-server.git",
|
||||
"sha": "f08388256c5806f457fae777b5528eb02a48e703"
|
||||
"sha": "9ea4ba3e67f87c462c3e06b192470e837ed9009e"
|
||||
},
|
||||
"homepage": "https://exa.ai/docs/reference/exa-mcp"
|
||||
},
|
||||
@@ -1150,7 +1150,7 @@
|
||||
"url": "https://github.com/expo/skills.git",
|
||||
"path": "plugins/expo",
|
||||
"ref": "main",
|
||||
"sha": "c38860242118df93d4ec4381a34f4144fff61928"
|
||||
"sha": "1a5693e0acc95a0829ff1656b4426fee2f2c1167"
|
||||
},
|
||||
"homepage": "https://github.com/expo/skills/blob/main/plugins/expo/README.md"
|
||||
},
|
||||
@@ -1166,7 +1166,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/fastly/fastly-agent-toolkit.git",
|
||||
"sha": "6bd17d685a1b361a2b368bf0236f39efb1be62d6"
|
||||
"sha": "73af5b94a98448ffeed6e2993495dc83c9a597be"
|
||||
},
|
||||
"homepage": "https://github.com/fastly/fastly-agent-toolkit/blob/main/README.md"
|
||||
},
|
||||
@@ -1198,7 +1198,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/figma/mcp-server-guide.git",
|
||||
"sha": "a742f0a700a7772ff5ed85f7c9fc1dad5afa9fcc"
|
||||
"sha": "2efd0e37d10c35c4a7cf6d2b7381c9dc1a569bd4"
|
||||
},
|
||||
"homepage": "https://github.com/figma/mcp-server-guide"
|
||||
},
|
||||
@@ -1216,7 +1216,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/firecrawl/firecrawl-claude-plugin.git",
|
||||
"sha": "6768fb78185aab9e5b5a04777f84703863fb025b"
|
||||
"sha": "b33447585ac521b091eae672bd4cad4ec1d093f6"
|
||||
},
|
||||
"homepage": "https://github.com/firecrawl/firecrawl-claude-plugin.git"
|
||||
},
|
||||
@@ -1230,7 +1230,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/gemini-cli-extensions/firestore-native.git",
|
||||
"sha": "f88103bd0ccfe9e1e7a3a7d849de26d197978c9a"
|
||||
"sha": "d7f42424cfddfb567efbae100023b94dfb4571be"
|
||||
},
|
||||
"homepage": "https://github.com/gemini-cli-extensions/firestore-native"
|
||||
},
|
||||
@@ -1244,7 +1244,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/atlassian/forge-skills.git",
|
||||
"sha": "02103cca4addb4c42d64d4e18a9d1a7f186edf6c"
|
||||
"sha": "c7df956176eb1c2a10ffabc4eaacc5d843d8bede"
|
||||
},
|
||||
"homepage": "https://developer.atlassian.com/platform/forge/"
|
||||
},
|
||||
@@ -1333,7 +1333,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/huggingface/skills.git",
|
||||
"sha": "d7223848c3895fbd447faf2aec73e0a6cdd7fdcd"
|
||||
"sha": "7bf59b7f85b79c74207b10d5e425934514e8b089"
|
||||
},
|
||||
"homepage": "https://github.com/huggingface/skills.git"
|
||||
},
|
||||
@@ -1347,7 +1347,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/hunter-io/claude-plugin.git",
|
||||
"sha": "494b0bd6ac252c7c8d78402cb51c7f635b1469ad"
|
||||
"sha": "06bcb94a4e6498d8557a4543f8d5c4ea429b0c0a"
|
||||
},
|
||||
"homepage": "https://hunter.io"
|
||||
},
|
||||
@@ -1361,7 +1361,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/heygen-com/hyperframes.git",
|
||||
"sha": "25420bf4cfc37b179b4efeace9db25a7178b61bf"
|
||||
"sha": "c52165d1b63cf11955ceb4e2265cbe34b0718852"
|
||||
},
|
||||
"homepage": "https://hyperframes.heygen.com"
|
||||
},
|
||||
@@ -1415,7 +1415,7 @@
|
||||
"source": "github",
|
||||
"repo": "jfrog/claude-plugin",
|
||||
"commit": "259c8e718266c16e99b4f30ae9b1ed0f9f00d98d",
|
||||
"sha": "117febaa29cbe9449cfb42d1c39b83b858d801a1"
|
||||
"sha": "6788fe15d4a63d47f038c05e58ae533aeb2dadb6"
|
||||
},
|
||||
"homepage": "https://jfrog.com"
|
||||
},
|
||||
@@ -1429,7 +1429,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/gemini-cli-extensions/knowledge-catalog.git",
|
||||
"sha": "317e96fdd12aa61778b950192aff627efdc21099"
|
||||
"sha": "b3df58e81ae46a1497a1186fc82119d328ec730c"
|
||||
},
|
||||
"homepage": "https://github.com/gemini-cli-extensions/knowledge-catalog"
|
||||
},
|
||||
@@ -1540,7 +1540,7 @@
|
||||
"url": "https://github.com/pydantic/skills.git",
|
||||
"path": "plugins/logfire",
|
||||
"ref": "main",
|
||||
"sha": "e412b6d8d4b6199ac577c5ee8653dcff840b3e92"
|
||||
"sha": "1e7a4567d8375e8ef07ad078d7f38bc03ce5e944"
|
||||
},
|
||||
"homepage": "https://github.com/pydantic/skills/tree/main/plugins/logfire"
|
||||
},
|
||||
@@ -1554,7 +1554,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/gemini-cli-extensions/looker.git",
|
||||
"sha": "e912c0342f1bfd436e9236aaef7cc732239c80f7"
|
||||
"sha": "ef38964514c9b6634ac9a211d3987222bb36bf6e"
|
||||
},
|
||||
"homepage": "https://github.com/gemini-cli-extensions/looker"
|
||||
},
|
||||
@@ -1602,7 +1602,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/lusha-oss/lusha-mcp-plugin.git",
|
||||
"sha": "8fc71d5473ea40e01a92001787f0f3caaf5ca30e"
|
||||
"sha": "affbc76b03c1a46c0dffc5b7a374cf7af17b26e8"
|
||||
},
|
||||
"homepage": "https://www.lusha.com"
|
||||
},
|
||||
@@ -1708,7 +1708,7 @@
|
||||
"url": "https://github.com/awslabs/startups.git",
|
||||
"path": "migrate/plugins/migration-to-aws",
|
||||
"ref": "main",
|
||||
"sha": "1dd909352dc228f978c2685724cb38e64efe6be4"
|
||||
"sha": "944e5b17bb4b6a84a76b6382e3f5d7fa9abd7bbd"
|
||||
},
|
||||
"homepage": "https://github.com/awslabs/startups"
|
||||
},
|
||||
@@ -1759,7 +1759,7 @@
|
||||
"url": "https://github.com/neondatabase/agent-skills.git",
|
||||
"path": "plugins/neon-postgres",
|
||||
"ref": "main",
|
||||
"sha": "bd9ec7ff273ce54bdd3ebe581d5b0802a3479618"
|
||||
"sha": "58b84dfb0815cca6dbb2f40bfdb23ddf934d2b5f"
|
||||
},
|
||||
"homepage": "https://github.com/neondatabase/agent-skills/tree/main/plugins/neon-postgres"
|
||||
},
|
||||
@@ -1770,7 +1770,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/netlify/context-and-tools.git",
|
||||
"sha": "5f777ba63df12f4eb189be4c58bd35d0c8316505"
|
||||
"sha": "c594226e29e05cd6da81b73e8d5a67c6742b4437"
|
||||
},
|
||||
"homepage": "https://github.com/netlify/context-and-tools"
|
||||
},
|
||||
@@ -1839,7 +1839,7 @@
|
||||
"url": "https://github.com/NVIDIA/skills.git",
|
||||
"path": "plugins/nvidia-skills",
|
||||
"ref": "main",
|
||||
"sha": "0482ebce81bd8f2d39990317bb3cfb07637e39fd"
|
||||
"sha": "071d2fe0ef34b77a56f2f1401c223848572d5a97"
|
||||
},
|
||||
"homepage": "https://github.com/NVIDIA/skills"
|
||||
},
|
||||
@@ -1855,7 +1855,7 @@
|
||||
"url": "https://github.com/oracle-samples/oracle-aidp-samples.git",
|
||||
"path": "ai/claude-code-plugins/oracle-ai-data-platform-workbench-spark-connectors",
|
||||
"ref": "main",
|
||||
"sha": "00cedef34c99d642d969f87965736768de01cbd6"
|
||||
"sha": "deadf8f862f1360e08fd7de470ad1af38c3edb31"
|
||||
},
|
||||
"homepage": "https://docs.oracle.com/en/cloud/paas/ai-data-platform/index.html"
|
||||
},
|
||||
@@ -1885,7 +1885,7 @@
|
||||
"url": "https://github.com/growthxai/output.git",
|
||||
"path": "coding_assistants/claude/plugins/outputai",
|
||||
"ref": "main",
|
||||
"sha": "2cc4685ebadfba9586f01890df48e1b25bd1049a"
|
||||
"sha": "be9352cb3cb4bd7c204be0150db8c205dd939d9e"
|
||||
},
|
||||
"homepage": "https://output.ai"
|
||||
},
|
||||
@@ -1995,7 +1995,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/PostHog/ai-plugin.git",
|
||||
"sha": "db4a86632293ca66eec9a6d278786ddb22c1787e"
|
||||
"sha": "f674efefafeff7152294642f8559906eed885210"
|
||||
},
|
||||
"homepage": "https://posthog.com/docs/model-context-protocol"
|
||||
},
|
||||
@@ -2050,7 +2050,7 @@
|
||||
"url": "https://github.com/pydantic/skills.git",
|
||||
"path": "plugins/ai",
|
||||
"ref": "main",
|
||||
"sha": "e412b6d8d4b6199ac577c5ee8653dcff840b3e92"
|
||||
"sha": "1e7a4567d8375e8ef07ad078d7f38bc03ce5e944"
|
||||
},
|
||||
"homepage": "https://github.com/pydantic/skills/tree/main/plugins/ai"
|
||||
},
|
||||
@@ -2088,7 +2088,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/qdrant/skills.git",
|
||||
"sha": "82337ccd4be601e52871f101844d57b2adbac52b"
|
||||
"sha": "0814a0875db7a31bf29e46821668ef1b07f9f696"
|
||||
},
|
||||
"homepage": "https://skills.qdrant.tech"
|
||||
},
|
||||
@@ -2113,7 +2113,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/TheQtCompanyRnD/agent-skills.git",
|
||||
"sha": "a7189a7bc17e616b725e7ce4e46a4f5ebd50d94f"
|
||||
"sha": "2be55aaf050cf0e5d92d62966c473d2c5f6d780a"
|
||||
},
|
||||
"homepage": "https://www.qt.io/"
|
||||
},
|
||||
@@ -2127,7 +2127,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/quarkusio/quarkus-agent-mcp.git",
|
||||
"sha": "e711107a1171507212dd0edd17b5a922212c3a97"
|
||||
"sha": "0ecd6237518001b92da64499f0b43103a278f95f"
|
||||
},
|
||||
"homepage": "https://quarkus.io"
|
||||
},
|
||||
@@ -2140,7 +2140,7 @@
|
||||
"url": "https://github.com/railwayapp/railway-skills.git",
|
||||
"path": "plugins/railway",
|
||||
"ref": "main",
|
||||
"sha": "1df604ebd18f528ff16b84975125ecff944cc036"
|
||||
"sha": "836d42c1b652953c17a4523a07f1b8a68cc22064"
|
||||
},
|
||||
"homepage": "https://docs.railway.com/ai/claude-code-plugin"
|
||||
},
|
||||
@@ -2300,7 +2300,7 @@
|
||||
"url": "https://github.com/awslabs/agent-plugins.git",
|
||||
"path": "plugins/sagemaker-ai",
|
||||
"ref": "main",
|
||||
"sha": "fc54dfa24a1f05095b9fcbb4baa4750996bb171d"
|
||||
"sha": "58373593c6ed2e4684181f81369c0b7a4c916423"
|
||||
},
|
||||
"homepage": "https://github.com/awslabs/agent-plugins"
|
||||
},
|
||||
@@ -2314,7 +2314,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/sanity-io/agent-toolkit.git",
|
||||
"sha": "66f0ec5d9167b3ccb8b3450e5ec34f3b523d4139"
|
||||
"sha": "2d7b7c08a31a6e5b613e33a9edc76456e4d7c052"
|
||||
},
|
||||
"homepage": "https://www.sanity.io"
|
||||
},
|
||||
@@ -2348,7 +2348,7 @@
|
||||
"url": "https://github.com/SAP/open-ux-tools.git",
|
||||
"path": "packages/fiori-mcp-server",
|
||||
"ref": "main",
|
||||
"sha": "fbfe8c32fb9fc64583aa72ac03ab64f553c407ee"
|
||||
"sha": "cf2d1ef7f5641416c8f3ce7da7afac6c9271ad39"
|
||||
},
|
||||
"homepage": "https://github.com/SAP/open-ux-tools/tree/main/packages/fiori-mcp-server"
|
||||
},
|
||||
@@ -2380,14 +2380,14 @@
|
||||
"url": "https://github.com/spotify/save-to-spotify.git",
|
||||
"path": "plugin",
|
||||
"ref": "main",
|
||||
"sha": "cd4ea68111d96769b09c0b0d2199e692cf00a73c"
|
||||
"sha": "a62408bcfb5e5be686e1fdcc361398493b8c4160"
|
||||
},
|
||||
"homepage": "https://github.com/spotify/save-to-spotify"
|
||||
},
|
||||
{
|
||||
"name": "security-guidance",
|
||||
"description": "Security review for Claude-generated code. Pattern-based warnings on edits, LLM-powered diff review on Stop, and an agentic commit reviewer that catches injection, XSS, SSRF, hardcoded secrets, and 25+ other vulnerability classes.",
|
||||
"version": "2.0.3",
|
||||
"version": "2.0.5",
|
||||
"author": {
|
||||
"name": "Anthropic",
|
||||
"email": "support@anthropic.com"
|
||||
@@ -2415,7 +2415,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/getsentry/sentry-for-claude.git",
|
||||
"sha": "030b01fb76b21f5d7ef6af5a3c3dfa658a9b5024"
|
||||
"sha": "9780bfc111f97b359893169e79c33d1e393891e5"
|
||||
},
|
||||
"homepage": "https://github.com/getsentry/sentry-for-claude/tree/main"
|
||||
},
|
||||
@@ -2431,7 +2431,7 @@
|
||||
"url": "https://github.com/getsentry/cli.git",
|
||||
"path": "plugins/sentry-cli",
|
||||
"ref": "main",
|
||||
"sha": "9e9fe0fb6444f18ed109058b2749cced3c21f87e"
|
||||
"sha": "a55d2a805aea69f6abb3fe58ed162377867ba2c5"
|
||||
},
|
||||
"homepage": "https://sentry.io"
|
||||
},
|
||||
@@ -2534,7 +2534,7 @@
|
||||
"url": "https://github.com/Snowflake-Labs/snowflake-ai-kit.git",
|
||||
"path": "plugins/cortex-code",
|
||||
"ref": "main",
|
||||
"sha": "6a22eb1ff3b451c35e40468a118bbee54610c9bd"
|
||||
"sha": "5a8f277f623394838ee76399261f4704c19eaba7"
|
||||
},
|
||||
"homepage": "https://docs.snowflake.com/en/user-guide/cortex-code"
|
||||
},
|
||||
@@ -2548,7 +2548,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/SonarSource/sonarqube-agent-plugins.git",
|
||||
"sha": "712b93281f4e67c16ed9b81dde090e1f73f8bfc8"
|
||||
"sha": "8c46904b2c21eb98d827c185e15ef5f6dd820312"
|
||||
},
|
||||
"homepage": "https://www.sonarsource.com"
|
||||
},
|
||||
@@ -2608,7 +2608,7 @@
|
||||
"url": "https://github.com/stripe/ai.git",
|
||||
"path": "providers/claude/plugin",
|
||||
"ref": "main",
|
||||
"sha": "b8f6adcb5d05f6ff01334411561ee8cb1ec014c6"
|
||||
"sha": "d076d0558c3b3d86149c2dddc84054fe9c6dd3e0"
|
||||
},
|
||||
"homepage": "https://github.com/stripe/ai/tree/main/providers/claude/plugin"
|
||||
},
|
||||
@@ -2620,7 +2620,7 @@
|
||||
"source": "url",
|
||||
"url": "https://github.com/sumup/sumup-skills.git",
|
||||
"path": "providers/claude/plugin",
|
||||
"sha": "715464b459def2d16e930e9ec8008f60e18a8b4d"
|
||||
"sha": "5b9b2d72c63fefd9038db0a9c571d3d64ff6353c"
|
||||
},
|
||||
"homepage": "https://www.sumup.com/"
|
||||
},
|
||||
@@ -2707,7 +2707,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/togethercomputer/skills.git",
|
||||
"sha": "fb94cc1402900eb608c31e7102fc23566f8b0363"
|
||||
"sha": "86bdd6627675eac3f2055f028e4acdd4d1b03fb0"
|
||||
},
|
||||
"homepage": "https://www.together.ai"
|
||||
},
|
||||
@@ -2769,7 +2769,7 @@
|
||||
"url": "https://github.com/UI5/plugins-coding-agents.git",
|
||||
"path": "plugins/ui5",
|
||||
"ref": "main",
|
||||
"sha": "9b3d7d80356f687725f9584988e4038dbead0d53"
|
||||
"sha": "6d72751f0b2983c379aaa457fe4c7cf4a075a66d"
|
||||
},
|
||||
"homepage": "https://github.com/UI5/plugins-coding-agents"
|
||||
},
|
||||
@@ -2787,7 +2787,7 @@
|
||||
"url": "https://github.com/UI5/plugins-coding-agents.git",
|
||||
"path": "plugins/ui5-typescript-conversion",
|
||||
"ref": "main",
|
||||
"sha": "9b3d7d80356f687725f9584988e4038dbead0d53"
|
||||
"sha": "80f2d93287054f9d30dd990e842e15bcfca581c9"
|
||||
},
|
||||
"homepage": "https://github.com/UI5/plugins-coding-agents"
|
||||
},
|
||||
@@ -2803,7 +2803,7 @@
|
||||
"url": "https://github.com/val-town/plugins.git",
|
||||
"path": "plugin",
|
||||
"ref": "main",
|
||||
"sha": "02631f998eda9b88d73d699703b062db059d506b"
|
||||
"sha": "1f7928397349f2ccb228302d8b062c7f20745871"
|
||||
},
|
||||
"homepage": "https://val.town"
|
||||
},
|
||||
@@ -2881,7 +2881,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/wix/skills.git",
|
||||
"sha": "188ed338f39d70e5aef7f9a2582bbf338f223b78"
|
||||
"sha": "def21835af3e6f0d86bf8c18acb1aaad7fdc9cd8"
|
||||
},
|
||||
"homepage": "https://dev.wix.com/docs/wix-cli/guides/development/about-wix-skills"
|
||||
},
|
||||
@@ -2907,7 +2907,7 @@
|
||||
"url": "https://github.com/workos/skills.git",
|
||||
"path": "plugins/workos",
|
||||
"ref": "main",
|
||||
"sha": "e8900cc504fd759407d1a963d13f59383fa39ebc"
|
||||
"sha": "2c3acef61ea29296cb6e73e0c59fb5e98f0b1847"
|
||||
},
|
||||
"homepage": "https://workos.com"
|
||||
},
|
||||
@@ -2934,7 +2934,7 @@
|
||||
"url": "https://github.com/zapier/zapier-mcp.git",
|
||||
"path": "plugins/zapier",
|
||||
"ref": "main",
|
||||
"sha": "770167c572deaf74c588b45d88003ddf2145d608"
|
||||
"sha": "ea8ed6b4de66e9bb46c12b3a38da8286e3770ad9"
|
||||
},
|
||||
"homepage": "https://github.com/zapier/zapier-mcp/tree/main/plugins/zapier"
|
||||
},
|
||||
@@ -2988,7 +2988,7 @@
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://github.com/zscaler/zscaler-mcp-server.git",
|
||||
"sha": "f84ce4f0ed48047614a4202ac311cbdf00ea9a10"
|
||||
"sha": "a2162c384e1ffb68b3bf14783ea9a1a762c85ff5"
|
||||
},
|
||||
"homepage": "https://github.com/zscaler/zscaler-mcp-server"
|
||||
}
|
||||
|
||||
@@ -29,6 +29,10 @@ The commands degrade gracefully, but each of these makes the output meaningfully
|
||||
- **The whole system in the tree**: deployment descriptors (JCL, CICS definitions, route configs), copybooks/includes, and DDL/schemas. Entry-point detection and data lineage in `/modernize-map` are guesswork without them.
|
||||
- **Production telemetry** (optional): an observability MCP server or batch job logs enable the runtime overlay in `/modernize-assess` and timing annotations on critical paths.
|
||||
|
||||
## Secret handling
|
||||
|
||||
Legacy systems routinely contain live credentials, and assessment artifacts get committed and shared. **Every agent in this plugin masks credential values** — findings, rule-card parameters, architecture notes, and test fixtures cite `file:line` with a masked preview (`AKIA****`), never the value. When credentials are found, a per-credential inventory (type, location, blast radius, rotation recommendation) is written to `analysis/<system>/SECRETS.local.md`, which the commands gitignore before writing; on non-git projects the quarantine file goes to `~/.modernize/<system>/` instead. `/modernize-harden` splits its remediation diff so credential-removal hunks (which necessarily contain the raw value) land in a gitignored `security_remediation.local.patch`, never the shareable patch. Pass `--show-secrets` to include raw values in the quarantine file (and only there). If you ran an earlier version of this plugin on a real system, check whether `analysis/` artifacts containing credentials were committed or shared, and rotate anything that was.
|
||||
|
||||
## Commands
|
||||
|
||||
The commands are designed to be run in order, but each produces a standalone artifact so you can stop, review, and resume.
|
||||
|
||||
@@ -29,6 +29,12 @@ For **transformed code**:
|
||||
- Does the test suite actually pin behavior, or just exercise code paths?
|
||||
- What would the on-call engineer need at 3am that isn't here?
|
||||
|
||||
## Secret handling (mandatory)
|
||||
|
||||
When a finding quotes code containing a credential, key, token, or
|
||||
connection string, mask the value (`'Pr0d****'`) and cite `file:line` —
|
||||
findings get appended verbatim to committed notes files.
|
||||
|
||||
## Output
|
||||
|
||||
Findings ranked **Blocker / High / Medium / Nit**. Each with: what, where,
|
||||
|
||||
@@ -40,6 +40,15 @@ of the technology, skip it.
|
||||
from structure/names), **Low** (ambiguous; needs SME).
|
||||
6. If confidence < High, write the exact question an SME must answer.
|
||||
|
||||
## Secret handling (mandatory)
|
||||
|
||||
Rule parameters sometimes *are* credentials — hardcoded passwords in auth
|
||||
checks, API keys in partner-service calls, connection strings in batch
|
||||
routines. Record the **rule**, never the **value**: write the parameter as
|
||||
`<credential — masked, see file:line>` with at most a 2–4 character
|
||||
preview. Rule cards flow into briefs and steering decks; a raw credential
|
||||
in a parameter list is a leak.
|
||||
|
||||
## Output format
|
||||
|
||||
One "Rule Card" per rule (see the format in the `/modernize-extract-rules`
|
||||
|
||||
@@ -32,6 +32,15 @@ and explain it in terms a modern engineer can act on.
|
||||
- **Note what's missing.** Unhandled error paths, TODO comments, commented-out
|
||||
blocks, magic numbers — these are signals about history and risk.
|
||||
|
||||
## Secret handling (mandatory)
|
||||
|
||||
Legacy code is full of live credentials, and your findings get copied into
|
||||
shareable reports. When the evidence for a finding — hardcoded config,
|
||||
dead code, debt, an interface payload — includes a credential, API key,
|
||||
token, connection string, or private key, **never reproduce the value**.
|
||||
Cite `file:line` with a masked preview (`VALUE 'Pr0d****'`,
|
||||
`password=****`). The finding is the practice, not the value.
|
||||
|
||||
## Output format
|
||||
|
||||
Default to structured markdown: tables for inventories, Mermaid for graphs,
|
||||
|
||||
@@ -39,7 +39,30 @@ terminal/screen items don't apply to a SPA. Work through what's relevant:
|
||||
|
||||
Use available SAST where it helps (npm audit, pip-audit, grep for known-bad
|
||||
patterns) but **read the code** — tools miss logic flaws. Show tool output
|
||||
verbatim, then add your manual findings.
|
||||
verbatim — except secret values, which you redact (see below) — then add
|
||||
your manual findings.
|
||||
|
||||
## Secret handling (mandatory)
|
||||
|
||||
Legacy codebases routinely contain live production credentials, and your
|
||||
findings get pasted into decks, tickets, and committed markdown. Copying a
|
||||
secret into a report multiplies the exposure you were hired to find.
|
||||
|
||||
When you discover a hardcoded credential, API key, token, connection
|
||||
string, or private key:
|
||||
|
||||
- **Never write the secret's value into any output** — no finding table,
|
||||
no report, no quoted code excerpt, no echoed tool output. Mask it to the
|
||||
first 2–4 identifying characters plus `****` (`AKIA****`,
|
||||
`postgres://app_user:****@db-prod…`). If a scanner prints a secret,
|
||||
redact it before including the excerpt.
|
||||
- Cite `file:line`. The source file is the canonical location — anyone who
|
||||
legitimately needs the value can open it there.
|
||||
- State what the credential appears to grant access to (database, queue,
|
||||
cloud account, third-party API) and whether it looks like a production
|
||||
or test credential.
|
||||
- Recommend rotation for anything that looks live — exposure in source
|
||||
means it is already compromised, independent of any modernization plan.
|
||||
|
||||
## Reporting standard
|
||||
|
||||
|
||||
@@ -28,6 +28,15 @@ someone thinks it should do) so that a rewrite can be proven equivalent.
|
||||
`@Disabled("pending RULE-NNN")` / `@pytest.mark.skip` / `it.todo()` — never
|
||||
deleted.
|
||||
|
||||
## Secret handling (mandatory)
|
||||
|
||||
Never copy credential-like literals — passwords, API keys, tokens,
|
||||
connection strings — from legacy code into test fixtures. Tests live in
|
||||
the deliverable codebase and get committed. Substitute clearly-fake values
|
||||
of the same shape and length and note the substitution in a comment.
|
||||
Anything a test genuinely needs live (e.g. a real database connection for
|
||||
a dual-run harness) is read from an environment variable, never inlined.
|
||||
|
||||
## Output
|
||||
|
||||
Idiomatic tests for the requested target stack (JUnit 5 / pytest / Vitest /
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
---
|
||||
description: Full discovery & portfolio analysis of a legacy system — inventory, complexity, debt, effort estimation
|
||||
argument-hint: <system-dir> | --portfolio <parent-dir>
|
||||
argument-hint: <system-dir> [--show-secrets] | --portfolio <parent-dir>
|
||||
---
|
||||
|
||||
**Mode select.** If `$ARGUMENTS` starts with `--portfolio`, run **Portfolio
|
||||
mode** against the directory that follows. Otherwise run **Single-system
|
||||
mode** against `legacy/$1`.
|
||||
mode** against the system dir. Parse flags positionally-independently:
|
||||
`--show-secrets` may appear before or after the system dir — the system
|
||||
dir is the first non-flag token.
|
||||
|
||||
---
|
||||
|
||||
@@ -108,12 +110,16 @@ Spawn three subagents **in parallel**:
|
||||
2. **legacy-analyst** — "Identify technical debt in legacy/$1: dead code,
|
||||
deprecated APIs, copy-paste duplication, god objects/programs, missing
|
||||
error handling, hardcoded config. Return the top 10 findings ranked by
|
||||
remediation value, each with file:line evidence."
|
||||
remediation value, each with file:line evidence. If evidence contains a
|
||||
credential value, mask it per your secret-handling rules — never quote
|
||||
it."
|
||||
|
||||
3. **security-auditor** — "Scan legacy/$1 for security vulnerabilities:
|
||||
injection, auth weaknesses, hardcoded secrets, vulnerable dependencies,
|
||||
missing input validation. Return findings in CWE-tagged table form with
|
||||
file:line evidence and severity."
|
||||
file:line evidence and severity. Mask every discovered credential value
|
||||
per your secret-handling rules — file:line plus a 2–4 character masked
|
||||
preview, never the value itself."
|
||||
|
||||
Wait for all three. Synthesize their findings.
|
||||
|
||||
@@ -141,6 +147,31 @@ need explained.
|
||||
|
||||
## Step 6 — Write the assessment
|
||||
|
||||
**Secrets quarantine first.** The assessment gets shared and committed —
|
||||
discovered credential values must never appear in it. If the
|
||||
security-auditor found any hardcoded credentials:
|
||||
|
||||
1. Ensure `analysis/.gitignore` exists and contains the lines
|
||||
`SECRETS.local.md` and `*.local.patch` (create or append as needed —
|
||||
the patch pattern is used by `/modernize-harden`; writing both now
|
||||
means the ignore set is complete from first contact). If the project is a
|
||||
git repo, verify with `git check-ignore -q analysis/$1/SECRETS.local.md`
|
||||
— do not write any findings until the check passes. If there is **no
|
||||
git repo** (check for `.svn`/`.hg`/`CVS` too — a `.gitignore` protects
|
||||
nothing under another VCS): refuse `--show-secrets` and write
|
||||
`SECRETS.local.md` to `~/.modernize/$1/` instead of the project tree,
|
||||
telling the user where it went and why.
|
||||
2. Write `SECRETS.local.md`: one row per credential — masked preview,
|
||||
`file:line`, credential type, what it grants access to,
|
||||
production/test guess, rotation recommendation. Only if the user passed
|
||||
`--show-secrets`, add the raw value column here — this file only, never
|
||||
ASSESSMENT.md.
|
||||
3. Masking applies to **every section of ASSESSMENT.md**, whichever agent
|
||||
produced the finding — the Technical Debt section quotes hardcoded
|
||||
config; those quotes follow the same masking rule as Security Findings.
|
||||
The Security Findings section adds a one-line pointer:
|
||||
"Credential inventory in SECRETS.local.md (gitignored; not for sharing)."
|
||||
|
||||
Create `analysis/$1/ASSESSMENT.md` with these sections:
|
||||
- **Executive Summary** (3-4 sentences: what it is, how big, how risky, headline recommendation)
|
||||
- **System Inventory** (the scc table + tech fingerprint)
|
||||
|
||||
@@ -46,7 +46,7 @@ Merge the three result sets. Deduplicate. For each distinct rule, write a
|
||||
When <trigger>
|
||||
Then <outcome>
|
||||
[And <additional outcome>]
|
||||
**Parameters:** <constants, rates, thresholds with their current values>
|
||||
**Parameters:** <constants, rates, thresholds with their current values — credentials masked: `<credential — masked, see file:line>`>
|
||||
**Edge cases handled:** <list>
|
||||
**Suspected defect:** <optional — legacy behavior that looks wrong; decide preserve-vs-fix during transform>
|
||||
**Confidence:** High | Medium | Low — <why; if < High, state the exact SME question>
|
||||
|
||||
@@ -1,14 +1,42 @@
|
||||
---
|
||||
description: Security vulnerability scan with a reviewable remediation patch — OWASP, CWE, CVE, secrets, injection
|
||||
argument-hint: <system-dir>
|
||||
argument-hint: <system-dir> [--show-secrets]
|
||||
---
|
||||
|
||||
Run a **security hardening pass** on `legacy/$1`: find vulnerabilities, rank
|
||||
them, and produce a reviewable patch for the critical ones.
|
||||
Run a **security hardening pass** on the legacy system: find
|
||||
vulnerabilities, rank them, and produce a reviewable patch for the
|
||||
critical ones. Parse arguments flag-independently: the system dir
|
||||
(referred to as `$1` below) is the first non-flag token in `$ARGUMENTS`;
|
||||
`--show-secrets` may appear anywhere.
|
||||
|
||||
This command never edits `legacy/` — it writes findings and a proposed patch
|
||||
to `analysis/$1/`. The user reviews and applies (or not).
|
||||
|
||||
## Step 0 — Secrets quarantine setup
|
||||
|
||||
Findings files get shared, committed, and pasted into decks — discovered
|
||||
credential values must never land in them. Before any scanning:
|
||||
|
||||
1. Ensure `analysis/.gitignore` exists and contains the lines
|
||||
`SECRETS.local.md` and `*.local.patch`. Create the file or append the
|
||||
missing lines.
|
||||
2. If the project is a git repo, verify with
|
||||
`git check-ignore -q analysis/$1/SECRETS.local.md` — if that exits
|
||||
non-zero, fix the ignore rule before proceeding. Do not write any
|
||||
findings until this check passes.
|
||||
3. **If there is no git repo** (check for `.svn`/`.hg`/`CVS` too — a
|
||||
`.gitignore` protects nothing under another VCS): refuse
|
||||
`--show-secrets`, and write `SECRETS.local.md` and any `.local.patch`
|
||||
file to `~/.modernize/$1/` instead of the project tree, telling the
|
||||
user where they went and why.
|
||||
|
||||
All secret values in every shareable artifact this command produces are
|
||||
**masked** (`AKIA****`, `password=****`) and cited by `file:line`. Raw
|
||||
values may appear in exactly two places, both gitignored: the
|
||||
`*.local.patch` remediation hunks (unavoidably — see Remediate) and, only
|
||||
with `--show-secrets`, `SECRETS.local.md`. Never in SECURITY_FINDINGS.md
|
||||
or patch commentary.
|
||||
|
||||
## Scan
|
||||
|
||||
Spawn the **security-auditor** subagent:
|
||||
@@ -20,7 +48,9 @@ hardcoded secrets, vulnerable dependency versions, missing input validation,
|
||||
path traversal. For each finding return: CWE ID, severity
|
||||
(Critical/High/Med/Low), file:line, one-sentence exploit scenario, and
|
||||
recommended fix. Run any available SAST tooling (npm audit, pip-audit,
|
||||
OWASP dependency-check) and include its raw output."
|
||||
OWASP dependency-check) and include its raw output. Mask every discovered
|
||||
credential value per your secret-handling rules — file:line plus a 2–4
|
||||
character masked preview, never the value itself."
|
||||
|
||||
## Triage
|
||||
|
||||
@@ -29,26 +59,50 @@ Write `analysis/$1/SECURITY_FINDINGS.md`:
|
||||
- Findings table sorted by severity
|
||||
- Dependency CVE table (package, installed version, CVE, fixed version)
|
||||
|
||||
If any hardcoded credentials were found, also write
|
||||
`analysis/$1/SECRETS.local.md` (the gitignored quarantine file from Step 0):
|
||||
one row per credential — masked preview, `file:line`, credential type, what
|
||||
it appears to grant access to, production/test guess, and a rotation
|
||||
recommendation. With `--show-secrets`, append the raw value column here —
|
||||
this file only. SECURITY_FINDINGS.md gets a one-line pointer:
|
||||
"N hardcoded credentials found — inventory in SECRETS.local.md (gitignored;
|
||||
not for sharing)."
|
||||
|
||||
## Remediate
|
||||
|
||||
For each **Critical** and **High** finding, draft a minimal, targeted fix.
|
||||
Do **not** edit `legacy/` — write all fixes as a single unified diff to
|
||||
`analysis/$1/security_remediation.patch`, with a comment line above each
|
||||
hunk citing the finding ID it addresses (`# SEC-001: parameterize the query`).
|
||||
Do **not** edit `legacy/` — write fixes as unified diffs with **paths
|
||||
relative to the project root** (`legacy/$1/...`), applied from the project
|
||||
root, with a comment line above each hunk citing the finding ID it
|
||||
addresses (`# SEC-001: parameterize the query`).
|
||||
|
||||
**Credential findings split into two files.** A diff that removes a
|
||||
hardcoded secret necessarily contains the raw value on its `-` and
|
||||
context lines — that cannot go in the shareable patch:
|
||||
|
||||
- `analysis/$1/security_remediation.patch` (shareable) — every
|
||||
non-credential hunk, plus for each credential finding a comment-only
|
||||
placeholder: `# SEC-NNN: credential remediation — hunk in
|
||||
security_remediation.local.patch (gitignored; not for sharing)`.
|
||||
- `analysis/$1/security_remediation.local.patch` (gitignored in Step 0) —
|
||||
the real, applyable hunks for credential findings only.
|
||||
|
||||
Add a **Remediation Log** section to SECURITY_FINDINGS.md mapping each
|
||||
finding ID → one-line summary of the proposed fix and the patch hunk that
|
||||
implements it.
|
||||
finding ID → one-line summary of the proposed fix and which patch file
|
||||
carries the hunk.
|
||||
|
||||
## Verify
|
||||
|
||||
Spawn the **security-auditor** again to **review the patch** against the
|
||||
original code:
|
||||
Spawn the **security-auditor** again to **review both patches** against
|
||||
the original code:
|
||||
|
||||
"Review analysis/$1/security_remediation.patch against legacy/$1. For each
|
||||
"Review analysis/$1/security_remediation.patch and
|
||||
analysis/$1/security_remediation.local.patch against legacy/$1. For each
|
||||
hunk: does it fully remediate the cited finding? Does it introduce new
|
||||
vulnerabilities or change behavior beyond the fix? Return one verdict per
|
||||
hunk: RESOLVES / PARTIAL / INTRODUCES-RISK, with a one-line reason."
|
||||
vulnerabilities or change behavior beyond the fix? Confirm no raw
|
||||
credential values appear anywhere in the shareable patch. Return one
|
||||
verdict per hunk: RESOLVES / PARTIAL / INTRODUCES-RISK, with a one-line
|
||||
reason."
|
||||
|
||||
Add a **Patch Review** section to SECURITY_FINDINGS.md with the verdicts.
|
||||
If any hunk is PARTIAL or INTRODUCES-RISK, revise the patch and re-review.
|
||||
@@ -57,8 +111,12 @@ If any hunk is PARTIAL or INTRODUCES-RISK, revise the patch and re-review.
|
||||
|
||||
Tell the user the artifacts are ready:
|
||||
- `analysis/$1/SECURITY_FINDINGS.md` — findings, remediation log, patch review
|
||||
- `analysis/$1/security_remediation.patch` — review, then apply if appropriate
|
||||
with `git -C legacy/$1 apply ../../analysis/$1/security_remediation.patch`
|
||||
- `analysis/$1/security_remediation.patch` — review, then apply **from the
|
||||
project root**: `git apply analysis/$1/security_remediation.patch`
|
||||
(if `legacy/$1` is a symlink, use `git apply --unsafe-paths` or apply
|
||||
with `patch -p0` from the project root)
|
||||
- `analysis/$1/security_remediation.local.patch` — the credential fixes;
|
||||
apply the same way, and rotate the affected credentials regardless
|
||||
- Re-run `/modernize-harden $1` after applying to confirm resolution
|
||||
|
||||
Suggest: `glow -p analysis/$1/SECURITY_FINDINGS.md`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "security-guidance",
|
||||
"version": "2.0.3",
|
||||
"version": "2.0.5",
|
||||
"description": "Security review for Claude-generated code. Pattern-based warnings on edits, LLM-powered diff review on Stop, and an agentic commit reviewer that catches injection, XSS, SSRF, hardcoded secrets, and 25+ other vulnerability classes.",
|
||||
"author": {
|
||||
"name": "David Dworken",
|
||||
|
||||
@@ -40,6 +40,15 @@ BUILD_FAILED = 3 # venv create or pip install raised/timed out
|
||||
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.
|
||||
# --target fallback: when `python -m venv` can't bootstrap pip (ensurepip
|
||||
# missing — Debian python3-venv not installed, or a python.org/pyenv build
|
||||
# without ensurepip), fall back to `pip install --target <dir>` which needs
|
||||
# only the system pip, not venv/ensurepip. Telemetry (v2.0.4 sdk_has_pip
|
||||
# probe) confirmed ~95% of venv_ensurepip_fail users HAVE pip, so this
|
||||
# recovers the agentic reviewer for them instead of degrading to pattern +
|
||||
# single-shot review. See #2154 follow-up.
|
||||
BUILT_TARGET = 7 # venv ensurepip failed → SDK pip-installed via --target
|
||||
NOOP_TARGET = 8 # --target libs already present and importable
|
||||
|
||||
|
||||
# Phase + err-kind integer encoding for sdk_bootstrap_phase / sdk_bootstrap_err.
|
||||
@@ -63,6 +72,7 @@ SDK_BOOTSTRAP_PHASE_CODES = {
|
||||
"venv": 2, # python -m venv --clear
|
||||
"pip": 3, # pip install
|
||||
"main": 4, # uncaught exception above main()
|
||||
"pip_target": 5, # `pip install --target` fallback (venv ensurepip failed)
|
||||
}
|
||||
SDK_BOOTSTRAP_ERR_CODES = {
|
||||
"pip_no_match": 1,
|
||||
@@ -102,6 +112,41 @@ SDK_BOOTSTRAP_ERR_CODES = {
|
||||
"_uncategorized": 99,
|
||||
}
|
||||
|
||||
# Exception-type encoding for the "exc:<TypeName>" err_kinds (the generic
|
||||
# `except Exception` path — venv/pip raised a Python exception rather than
|
||||
# a CalledProcessError with categorizable stderr).
|
||||
#
|
||||
# #2154 telemetry surfaced that the dominant remaining venv BUILD_FAILED
|
||||
# bucket (phase=venv, err=99) is ~99% `exc:` with stderr_sig=NULL — i.e.
|
||||
# exceptions, not stderr-bearing subprocess failures — so the stderr_sig
|
||||
# hash couldn't distinguish them. This maps the exception TYPE to a stable
|
||||
# code so BQ can tell FileNotFoundError (python/venv binary missing) from
|
||||
# PermissionError (read-only home) from a bare OSError, etc.
|
||||
#
|
||||
# All the FileNotFoundError/PermissionError/etc. entries are OSError
|
||||
# subclasses, so they ALSO carry an errno (see _encode_errno) — the type
|
||||
# code gives the Python class, errno gives the OS-level cause. APPEND-ONLY.
|
||||
SDK_BOOTSTRAP_EXC_CODES = {
|
||||
"FileNotFoundError": 1, # interpreter/venv path component missing
|
||||
"PermissionError": 2, # read-only home, sandboxed FS
|
||||
"NotADirectoryError": 3,
|
||||
"IsADirectoryError": 4,
|
||||
"FileExistsError": 5, # (sentinel race is handled separately; this
|
||||
# is FileExistsError from elsewhere in venv)
|
||||
"OSError": 6, # bare OSError — errno carries the real cause
|
||||
"BlockingIOError": 7,
|
||||
"BrokenPipeError": 8,
|
||||
"ConnectionError": 9,
|
||||
"TimeoutError": 10, # distinct from subprocess.TimeoutExpired
|
||||
"InterruptedError": 11,
|
||||
"MemoryError": 12,
|
||||
"UnicodeDecodeError": 13,
|
||||
"ValueError": 14,
|
||||
"RuntimeError": 15,
|
||||
# 16–98 reserved; APPEND-ONLY.
|
||||
"_other_exc": 99, # an exception type not in this map
|
||||
}
|
||||
|
||||
|
||||
def _encode_phase(s):
|
||||
"""Map err_phase string to its telemetry integer code, or 0 if unset.
|
||||
@@ -158,6 +203,145 @@ def _encode_stderr_sig(err_kind):
|
||||
return int.from_bytes(h[:2], "big") % 1000
|
||||
|
||||
|
||||
def _encode_exc_kind(err_kind):
|
||||
"""Map an "exc:<TypeName>[:errno]" err_kind to its exception-type code
|
||||
(SDK_BOOTSTRAP_EXC_CODES). Returns 0 for non-exc err_kinds (so the
|
||||
sdk_bootstrap_exc field auto-omits on stderr/categorized failures).
|
||||
Unmapped exception types → 99 (_other_exc)."""
|
||||
if not err_kind or not err_kind.startswith("exc:"):
|
||||
return 0
|
||||
# "exc:OSError:28" → "OSError"; "exc:RuntimeError" → "RuntimeError"
|
||||
name = err_kind[len("exc:"):].split(":", 1)[0].strip()
|
||||
if not name:
|
||||
return 0
|
||||
return SDK_BOOTSTRAP_EXC_CODES.get(name, SDK_BOOTSTRAP_EXC_CODES["_other_exc"])
|
||||
|
||||
|
||||
def _encode_errno(err_kind):
|
||||
"""Extract the OS errno from an "exc:<TypeName>:<errno>" err_kind.
|
||||
OSError-family exceptions embed their errno (ENOENT=2, EACCES=13,
|
||||
ENOSPC=28, …) — the OS-level cause is far more actionable than the
|
||||
Python class alone. Returns 0 when absent/non-numeric (field omitted)."""
|
||||
if not err_kind or not err_kind.startswith("exc:"):
|
||||
return 0
|
||||
parts = err_kind.split(":")
|
||||
if len(parts) < 3:
|
||||
return 0
|
||||
try:
|
||||
return int(parts[2])
|
||||
except (ValueError, IndexError):
|
||||
return 0
|
||||
|
||||
|
||||
def _probe_has_pip() -> bool:
|
||||
"""True iff the current interpreter can run pip (`-m pip --version`).
|
||||
|
||||
Probed only on the venv_ensurepip_fail path (see __main__), NOT on the
|
||||
happy path — it's an extra subprocess we only want when diagnosing a
|
||||
failure. The result decides whether a `pip install --target` fallback
|
||||
(Option A) is even viable for this machine: ensurepip/venv missing but
|
||||
pip present → --target would work; pip also missing → it wouldn't, and
|
||||
the user needs a system package (python3-venv / a complete Python)."""
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[sys.executable, "-m", "pip", "--version"],
|
||||
capture_output=True, timeout=10,
|
||||
)
|
||||
return r.returncode == 0
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _pip_err_from_stderr(stderr_b):
|
||||
"""Categorize a pip-install stderr into a known err_kind (the pip subset
|
||||
of SDK_BOOTSTRAP_ERR_CODES). Used by the --target fallback; mirrors the
|
||||
pip branches of main()'s inline categorizer. Kept as a sibling rather
|
||||
than extracting main()'s chain (which also has venv-phase branches) to
|
||||
avoid disturbing the working venv categorization."""
|
||||
if isinstance(stderr_b, bytes):
|
||||
s = stderr_b.decode("utf-8", errors="replace")
|
||||
else:
|
||||
s = str(stderr_b or "")
|
||||
low = s.lower()
|
||||
if "no matching distribution" in low or "could not find a version" in low:
|
||||
return "pip_no_match"
|
||||
if ("name or service not known" in low or "name resolution" in low
|
||||
or "nodename nor servname" in low or "temporary failure in name" in low):
|
||||
return "dns_fail"
|
||||
if "connection refused" in low or "connection reset" in low:
|
||||
return "conn_refused"
|
||||
if "ssl" in low and ("verify" in low or "certificate" in low):
|
||||
return "ssl_verify"
|
||||
if "permission denied" in low or "read-only file system" in low:
|
||||
return "perm_denied"
|
||||
if "no module named pip" in low or "no module named ensurepip" in low:
|
||||
return "no_pip"
|
||||
if "no space left" in low or "disk quota" in low:
|
||||
return "disk_full"
|
||||
if "proxy" in low and ("authent" in low or "tunnel" in low or "407" in low):
|
||||
return "proxy_auth"
|
||||
if "timeout" in low or "timed out" in low:
|
||||
return "stderr_timeout"
|
||||
tail = next((ln.strip() for ln in reversed(s.splitlines()) if ln.strip()), "")[:60]
|
||||
return f"other:{tail}" if tail else "other"
|
||||
|
||||
|
||||
def _target_dir(state_dir) -> Path:
|
||||
return Path(state_dir) / "agent-sdk-libs"
|
||||
|
||||
|
||||
def _target_sdk_importable(state_dir) -> bool:
|
||||
"""True iff the --target libs dir has an importable claude_agent_sdk,
|
||||
probed with THIS interpreter (the one llm.py will import it from) and the
|
||||
target dir prepended to sys.path. Cheap dir-check first to avoid a
|
||||
subprocess on the common no-target path."""
|
||||
target = _target_dir(state_dir)
|
||||
if not (target / "claude_agent_sdk").is_dir():
|
||||
return False
|
||||
try:
|
||||
r = subprocess.run(
|
||||
[sys.executable, "-c",
|
||||
"import sys; sys.path.insert(0, sys.argv[1]); import claude_agent_sdk",
|
||||
str(target)],
|
||||
capture_output=True, timeout=10,
|
||||
)
|
||||
return r.returncode == 0
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _build_via_target(state_dir) -> tuple[int, str, str]:
|
||||
"""Fallback install when `python -m venv` can't bootstrap pip (ensurepip
|
||||
missing — Debian python3-venv absent, or a python.org/pyenv build without
|
||||
ensurepip). `pip install --target <dir>` needs only the system pip, not
|
||||
venv/ensurepip. v2.0.4 telemetry (sdk_has_pip) confirmed ~95% of
|
||||
venv_ensurepip_fail users have pip. The consumer (llm.py) adds this flat
|
||||
dir to sys.path. Returns (outcome, err_phase, err_kind).
|
||||
|
||||
--upgrade so a stale/partial target dir from a prior failed attempt
|
||||
doesn't make pip refuse; --prefer-binary mirrors the venv path's wheel
|
||||
preference (ARM64 Windows cryptography)."""
|
||||
target = _target_dir(state_dir)
|
||||
try:
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "pip", "install",
|
||||
"--target", str(target), "--upgrade",
|
||||
"--disable-pip-version-check", "--prefer-binary",
|
||||
"claude-agent-sdk"],
|
||||
capture_output=True, timeout=120, check=True,
|
||||
)
|
||||
return BUILT_TARGET, "", ""
|
||||
except subprocess.CalledProcessError as e:
|
||||
return BUILD_FAILED, "pip_target", _pip_err_from_stderr(e.stderr)
|
||||
except subprocess.TimeoutExpired:
|
||||
return BUILD_FAILED, "pip_target", "subprocess_timeout"
|
||||
except Exception as e:
|
||||
errno = getattr(e, "errno", None)
|
||||
if isinstance(errno, int):
|
||||
return BUILD_FAILED, "pip_target", f"exc:{type(e).__name__}:{errno}"
|
||||
return BUILD_FAILED, "pip_target", f"exc:{type(e).__name__}"
|
||||
|
||||
|
||||
def _sdk_on_syspath() -> bool:
|
||||
# find_spec is ~10ms; actually importing the SDK pulls in
|
||||
# transitive deps and costs ~800ms — too heavy for a
|
||||
@@ -246,6 +430,12 @@ def main() -> tuple[int, str, str]:
|
||||
except Exception:
|
||||
pass # broken venv; rebuild below
|
||||
|
||||
# If a prior run installed the SDK via the --target fallback (ensurepip
|
||||
# path), reuse it. Only reached when there's no working venv, so healthy
|
||||
# NOOP_VENV users never pay for this probe.
|
||||
if _target_sdk_importable(state_dir):
|
||||
return NOOP_TARGET, "", ""
|
||||
|
||||
err_phase = ""
|
||||
err_kind = ""
|
||||
we_own_sentinel = False
|
||||
@@ -360,10 +550,27 @@ def main() -> tuple[int, str, str]:
|
||||
"",
|
||||
)[:60]
|
||||
err_kind = f"other:{tail}" if tail else "other"
|
||||
# venv couldn't bootstrap pip (ensurepip missing) but pip itself may
|
||||
# work — fall back to a flat `pip install --target`. Only this one
|
||||
# category falls through; every other venv/pip failure is terminal.
|
||||
# The finally block unlinks our sentinel first (so the target build
|
||||
# isn't blocked by it); _build_via_target does the target install.
|
||||
if err_kind == "venv_ensurepip_fail":
|
||||
if we_own_sentinel:
|
||||
sentinel.unlink(missing_ok=True)
|
||||
we_own_sentinel = False
|
||||
return _build_via_target(state_dir)
|
||||
return BUILD_FAILED, err_phase, err_kind
|
||||
except subprocess.TimeoutExpired:
|
||||
return BUILD_FAILED, err_phase, "subprocess_timeout"
|
||||
except Exception as e:
|
||||
# Embed errno for OSError-family exceptions ("exc:OSError:28") so
|
||||
# telemetry can decode the OS-level cause (ENOENT/EACCES/ENOSPC/…),
|
||||
# not just the Python class. #2154 follow-up: this is the dominant
|
||||
# remaining venv BUILD_FAILED bucket. See _encode_exc_kind/_encode_errno.
|
||||
errno = getattr(e, "errno", None)
|
||||
if isinstance(errno, int):
|
||||
return BUILD_FAILED, err_phase, f"exc:{type(e).__name__}:{errno}"
|
||||
return BUILD_FAILED, err_phase, f"exc:{type(e).__name__}"
|
||||
finally:
|
||||
# Only remove the sentinel if THIS process created it. The
|
||||
@@ -467,6 +674,30 @@ if __name__ == "__main__":
|
||||
sig = _encode_stderr_sig(err_kind)
|
||||
if sig:
|
||||
metrics["sdk_bootstrap_stderr_sig"] = sig
|
||||
# Exception-type + errno for the "exc:" bucket (the dominant
|
||||
# remaining venv BUILD_FAILED mode per #2154 telemetry). Both
|
||||
# auto-omit (0) on stderr/categorized failures.
|
||||
exc = _encode_exc_kind(err_kind)
|
||||
if exc:
|
||||
metrics["sdk_bootstrap_exc"] = exc
|
||||
exc_errno = _encode_errno(err_kind)
|
||||
if exc_errno:
|
||||
metrics["sdk_bootstrap_errno"] = exc_errno
|
||||
# venv_ensurepip_fail (code 11) is the top categorizable venv
|
||||
# failure, and telemetry shows it's NOT just Debian — macOS has the
|
||||
# most distinct affected users. Probe whether this interpreter has
|
||||
# pip so we know if a `pip install --target` fallback (Option A)
|
||||
# would actually help, vs the user needing a system package. Probed
|
||||
# only here (not on the happy path) to avoid an extra subprocess
|
||||
# per healthy session.
|
||||
if _encode_err_kind(err_kind) == 11:
|
||||
metrics["sdk_has_pip"] = _probe_has_pip()
|
||||
# Interpreter version (major*100 + minor, e.g. 309 / 312), emitted on
|
||||
# every bootstrap. Disambiguates the macOS cohort (Apple 3.9 vs a 3.10+
|
||||
# with broken ensurepip) for both venv_ensurepip_fail AND
|
||||
# HOOK_PY_INCOMPATIBLE (whose "py_3.9" err_kind otherwise collapses to
|
||||
# err=99, losing the version). Cheap — no subprocess, just sys.version_info.
|
||||
metrics["sdk_hook_py"] = sys.version_info[0] * 100 + sys.version_info[1]
|
||||
pv = _plugin_version_int()
|
||||
if pv:
|
||||
metrics["pv"] = pv
|
||||
|
||||
@@ -55,6 +55,12 @@ def _inject_agent_sdk_venv_into_syspath(state_dir):
|
||||
candidates = (
|
||||
glob.glob(os.path.join(venv_root, "lib", "python*", "site-packages"))
|
||||
+ glob.glob(os.path.join(venv_root, "Lib", "site-packages"))
|
||||
# `pip install --target` fallback (ensure_agent_sdk BUILT_TARGET, used
|
||||
# when venv can't bootstrap pip): a FLAT layout — packages sit directly
|
||||
# in agent-sdk-libs/, not under a site-packages subdir. See #2154
|
||||
# follow-up. The pywin32 .pth bootstrap below applies here too (target
|
||||
# installs don't process .pth at runtime, same as a manual venv insert).
|
||||
+ [os.path.join(state_dir, "agent-sdk-libs")]
|
||||
)
|
||||
added = False
|
||||
for sp in candidates:
|
||||
|
||||
Reference in New Issue
Block a user