From 77bfd8a620ee136fe206f0ec952a87a13360e978 Mon Sep 17 00:00:00 2001 From: terra tauri Date: Fri, 20 Feb 2026 01:52:46 -0800 Subject: [PATCH] fix: preserve existing plugin order, append new plugins at bottom Read existing marketplace.json to get current plugin order. Existing plugins keep their position, new plugins are appended at the end (sorted alphabetically among themselves). Produces clean additive diffs instead of noisy reordering. Co-Authored-By: Claude Opus 4.6 --- scripts/dist/discover-components.cjs | 21 ++++++++++++++++++- scripts/src/discover-components.js | 30 +++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/scripts/dist/discover-components.cjs b/scripts/dist/discover-components.cjs index 592e720..9c09264 100755 --- a/scripts/dist/discover-components.cjs +++ b/scripts/dist/discover-components.cjs @@ -7984,12 +7984,31 @@ function generateMarketplace(plugins, config) { category: plugin.category === "code" || plugin.category === "analysis" ? "development" : "productivity" }); } + const marketplacePath = path.join(".claude-plugin", "marketplace.json"); + let existingOrder = []; + try { + const existing = JSON.parse(fs.readFileSync(marketplacePath, "utf8")); + existingOrder = (existing.plugins || []).map((p) => p.source); + } catch { + } + const existingSet = new Set(existingOrder); + const pluginsBySource = new Map(marketplacePlugins.map((p) => [p.source, p])); + const ordered = []; + for (const source of existingOrder) { + if (pluginsBySource.has(source)) { + ordered.push(pluginsBySource.get(source)); + pluginsBySource.delete(source); + } + } + const newPlugins = Array.from(pluginsBySource.values()); + newPlugins.sort((a, b) => a.source.localeCompare(b.source)); + ordered.push(...newPlugins); return { "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", name, description, owner, - plugins: marketplacePlugins + plugins: ordered }; } function writePluginJsonFiles(plugins, config) { diff --git a/scripts/src/discover-components.js b/scripts/src/discover-components.js index c455a85..eed9f21 100644 --- a/scripts/src/discover-components.js +++ b/scripts/src/discover-components.js @@ -1296,12 +1296,40 @@ function generateMarketplace(plugins, config) { }); } + // Stable ordering: preserve existing order, append new plugins at the end. + // This keeps diffs clean — only additions/removals, never reordering. + const marketplacePath = path.join('.claude-plugin', 'marketplace.json'); + let existingOrder = []; + try { + const existing = JSON.parse(fs.readFileSync(marketplacePath, 'utf8')); + existingOrder = (existing.plugins || []).map(p => p.source); + } catch { + // No existing file or invalid JSON — all plugins are new + } + + const existingSet = new Set(existingOrder); + const pluginsBySource = new Map(marketplacePlugins.map(p => [p.source, p])); + + // Existing plugins in their original order (skip any that were removed) + const ordered = []; + for (const source of existingOrder) { + if (pluginsBySource.has(source)) { + ordered.push(pluginsBySource.get(source)); + pluginsBySource.delete(source); + } + } + + // New plugins appended at the end, sorted alphabetically among themselves + const newPlugins = Array.from(pluginsBySource.values()); + newPlugins.sort((a, b) => a.source.localeCompare(b.source)); + ordered.push(...newPlugins); + return { "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", name, description, owner, - plugins: marketplacePlugins + plugins: ordered }; }