|
| 1 | +# IntelliJ Extension Point Explorer |
| 2 | + |
| 3 | +Use this skill to find plugins that implement a given IntelliJ extension point and to get GitHub source code search URLs for usage examples. |
| 4 | + |
| 5 | +This skill also covers **downloading any plugin for decompilation and feature investigation** — see Section 3. |
| 6 | + |
| 7 | +> **Important:** Extension point names are **case-sensitive** (e.g., `com.intellij.psi.referenceContributor` ≠ `com.intellij.psi.ReferenceContributor`). Use the exact name as declared in `plugin.xml`. |
| 8 | +
|
| 9 | +--- |
| 10 | + |
| 11 | +## 1. Search for extension points by keyword |
| 12 | + |
| 13 | +Before querying for plugins, find the **exact extension point name** by searching the JetBrains Marketplace extension point registry. Search is **case-insensitive** (the filtering is done client-side with `grep -i`), but the name you pass to Step 1 must be **exact and case-sensitive**. |
| 14 | + |
| 15 | +```bash |
| 16 | +# Partial search — find all extension points containing a keyword |
| 17 | +KEYWORD="completion" |
| 18 | + |
| 19 | +curl -s "https://plugins.jetbrains.com/api/extension-points" \ |
| 20 | + | jq -r '.[].implementationName' \ |
| 21 | + | grep -i "$KEYWORD" \ |
| 22 | + | sort |
| 23 | +``` |
| 24 | + |
| 25 | +Examples: |
| 26 | +- `KEYWORD="contributor"` → lists all `*contributor*` extension points |
| 27 | +- `KEYWORD="completion.contributor"` → narrows to completion contributors |
| 28 | +- `KEYWORD="inspection"` → lists all inspection-related extension points |
| 29 | + |
| 30 | +Once you have the exact name (e.g., `com.intellij.completion.contributor`), use it in Step 2. |
| 31 | + |
| 32 | +--- |
| 33 | + |
| 34 | +## 2. Find plugins implementing an extension point |
| 35 | + |
| 36 | +Query the JetBrains Plugin Repository GraphQL API to find open-source plugins that use a specific extension point: |
| 37 | + |
| 38 | +```bash |
| 39 | +EXTENSION_POINT="com.intellij.psi.referenceContributor" |
| 40 | + |
| 41 | +curl -s -X POST "https://plugins.jetbrains.com/api/search/graphql" \ |
| 42 | + -H "Content-Type: application/json" \ |
| 43 | + -d "{\"query\":\"{ plugins(search: { max: 24, offset: 0, filters: [{ field: \\\"fields.extensionPoints\\\", value: \\\"${EXTENSION_POINT}\\\" }, { field: \\\"hasSource\\\", value: \\\"true\\\" }, { field: \\\"family\\\", value: \\\"intellij\\\" }], sortBy: DOWNLOADS }) { total, plugins { id, name, downloads, sourceCodeUrl, lastUpdateDate, organization { id, verified } } } }\"}" \ |
| 44 | + | jq -r --arg ep "$EXTENSION_POINT" ' |
| 45 | + .data.plugins | |
| 46 | + "Total plugins found: \(.total)\n", |
| 47 | + (.plugins[] | select(.sourceCodeUrl != null and .sourceCodeUrl != "") | |
| 48 | + "Plugin: \(.name)", |
| 49 | + "ID: \(.id)", |
| 50 | + "Downloads: \(.downloads)", |
| 51 | + "Source: \(.sourceCodeUrl)", |
| 52 | + "Updated: \(.lastUpdateDate)", |
| 53 | + "Verified: \(.organization.verified // false)", |
| 54 | + "Marketplace: https://plugins.jetbrains.com/plugin/\(.id)", |
| 55 | + "Search: \("https://github.com/search?q=" + ("repo:" + (.sourceCodeUrl | ltrimstr("https://github.com/") | rtrimstr("/")) + " " + $ep | @uri) + "&type=code")", |
| 56 | + "---" |
| 57 | + ) |
| 58 | + ' |
| 59 | +``` |
| 60 | + |
| 61 | +## 3. Download a plugin for decompilation and feature investigation |
| 62 | + |
| 63 | +> **Note:** This section is **not** limited to extension point research. Use it any time you want to download a plugin JAR/ZIP for decompilation, reverse engineering, or feature investigation — regardless of how you found the plugin ID. |
| 64 | +
|
| 65 | +The plugin ID can come from: |
| 66 | +- **Step 2** results (`ID: 7219`) |
| 67 | +- A Marketplace URL: `https://plugins.jetbrains.com/plugin/<ID>` |
| 68 | + |
| 69 | +The `sourceCodeUrl` (GitHub URL) from Step 2 gives you two options: |
| 70 | +- **Search the repo** for usage examples → use the `Search:` URL from Step 2 output, or browse `https://github.com/<owner>/<repo>` |
| 71 | +- **Download the latest release** for decompilation → use the Marketplace API below to get the direct ZIP URL |
| 72 | + |
| 73 | +Given a plugin ID, fetch its metadata and the direct ZIP download URL of the latest release: |
| 74 | + |
| 75 | +```bash |
| 76 | +PLUGIN_ID="7219" |
| 77 | + |
| 78 | +# Plugin metadata |
| 79 | +curl -s "https://plugins.jetbrains.com/api/plugins/${PLUGIN_ID}" \ |
| 80 | + | jq '{ |
| 81 | + id: .id, |
| 82 | + name: .name, |
| 83 | + xmlId: .xmlId, |
| 84 | + downloads: .downloads, |
| 85 | + source: .urls.sourceCodeUrl, |
| 86 | + marketplace: ("https://plugins.jetbrains.com/plugin/" + (.id | tostring)) |
| 87 | + }' |
| 88 | + |
| 89 | +# Latest release — includes direct ZIP download URL |
| 90 | +curl -s "https://plugins.jetbrains.com/api/plugins/${PLUGIN_ID}/updates?size=1" \ |
| 91 | + | jq '.[0] | { |
| 92 | + version: .version, |
| 93 | + date: (.cdate | tonumber / 1000 | strftime("%Y-%m-%d")), |
| 94 | + downloads: .downloads, |
| 95 | + size_kb: (.size / 1024 | floor), |
| 96 | + channel: (if .channel == "" then "stable" else .channel end), |
| 97 | + download_url: ("https://plugins.jetbrains.com/files/" + .file), |
| 98 | + notes: (.notes | gsub("<[^>]+>"; "") | gsub(">"; ">") | gsub("<"; "<") | gsub("&"; "&") | split("\n") | map(select(length > 0)) | .[:5] | join("\n")) |
| 99 | + }' |
| 100 | +``` |
| 101 | + |
| 102 | +Once you have the ZIP URL, download and decompile with **vineflower** (see [`references.md`](./references.md)): |
| 103 | +```bash |
| 104 | +curl -L -o plugin.zip "https://plugins.jetbrains.com/files/7219/974671/Symfony_Plugin-2026.1.289.zip" |
| 105 | +unzip plugin.zip -d plugin-extracted/ |
| 106 | +java -jar decompiled/vineflower.jar plugin-extracted/lib/plugin.jar decompiled-src/ |
| 107 | +``` |
| 108 | + |
| 109 | +--- |
| 110 | + |
| 111 | +## Notes |
| 112 | + |
| 113 | +- **Case sensitivity:** `com.intellij.completion.contributor` ≠ `com.intellij.CompletionContributor` — always verify the exact name in `plugin.xml` or IntelliJ SDK docs. |
| 114 | +- The API returns max 24 results per request; use `offset` to paginate. |
| 115 | +- `sortBy` options: `DOWNLOADS`, `UPDATE_DATE`, `RATING`. |
| 116 | +- Only plugins with `hasSource: true` and a non-empty `sourceCodeUrl` are useful for code examples. |
| 117 | +- `jq` and `curl` are required; `jq` must support `@uri` (version ≥ 1.6). |
| 118 | +- For decompilation tooling and API references, see [`references.md`](./references.md). |
0 commit comments