fix: Handle object plugin sources in marketplace.json
marketplace.json source field can be a relative path string or an
object (github, url, npm, pip). Pinch only supports relative paths
since it clones the marketplace repo; object sources now get a clear
error instead of a deserialization failure.
Assisted-by: Claude Opus 4.6 via pi
diff --git a/src/marketplace.rs b/src/marketplace.rs
index aff70ff..c6f0c1e 100644
--- a/src/marketplace.rs
+++ b/src/marketplace.rs
@@ -1,6 +1,6 @@
use std::path::Path;
-use color_eyre::eyre::{Context, Result, eyre};
+use color_eyre::eyre::{Context, Result, bail, eyre};
use serde::Deserialize;
const DEFAULT_PATH: &str = ".claude-plugin/marketplace.json";
@@ -13,7 +13,21 @@ pub struct Marketplace {
#[derive(Debug, Deserialize)]
pub struct MarketplacePlugin {
pub name: String,
- pub source: String,
+ pub source: PluginSource,
+}
+
+/// A plugin source in marketplace.json.
+///
+/// Can be a relative path string (e.g. `"./plugins/my-plugin"`) or an object
+/// describing an external source (github, git url, npm, pip). Pinch only
+/// supports relative paths since it clones the marketplace repo directly.
+#[derive(Debug, Deserialize)]
+#[serde(untagged)]
+pub enum PluginSource {
+ /// Relative path within the marketplace repo.
+ Path(String),
+ /// External source (github, url, npm, pip) — not supported by pinch.
+ External(serde_json::Value),
}
/// Find the source path for a plugin by name in the marketplace.json.
@@ -29,16 +43,26 @@ pub fn find_plugin_source(
let marketplace: Marketplace = serde_json::from_str(&contents)
.with_context(|| format!("failed to parse {}", manifest_path.display()))?;
- marketplace
+ let plugin = marketplace
.plugins
.iter()
.find(|mp| mp.name == plugin_name)
- .map(|mp| mp.source.clone())
.ok_or_else(|| {
eyre!(
"plugin '{}' not found in {}",
plugin_name,
manifest_path.display()
)
- })
+ })?;
+
+ match &plugin.source {
+ PluginSource::Path(path) => Ok(path.clone()),
+ PluginSource::External(value) => {
+ bail!(
+ "plugin '{}': external source {} — pinch only supports relative path sources",
+ plugin_name,
+ value
+ );
+ }
+ }
}