Add marketplace command (#17087)

Added a new top-level `codex marketplace add` command for installing
plugin marketplaces into Codex’s local marketplace cache.

This change adds source parsing for local directories, GitHub shorthand,
and git URLs, supports optional `--ref` and git-only `--sparse` checkout
paths, stages the source in a temp directory, validates the marketplace
manifest, and installs it under
`$CODEX_HOME/marketplaces/<marketplace-name>`

Included tests cover local install behavior in the CLI and marketplace
discovery from installed roots in core. Scoped formatting and fix passes
were run, and targeted CLI/core tests passed.
This commit is contained in:
xli-oai authored and GitHub committed 2026-04-10 19:18:37 -07:00
1 parent 58933237cd
commit f9a8d1870f
15 files changed
+1330 -2

No files matched your search

+12 -2
View File
@@ -2,6 +2,7 @@ use super::LoadedPlugin;
use super::PluginLoadOutcome;
use super::PluginManifestPaths;
use super::curated_plugins_repo_path;
use super::installed_marketplaces::installed_marketplace_roots_from_config;
use super::load_plugin_manifest;
use super::manifest::PluginManifestInterface;
use super::marketplace::MarketplaceError;
@@ -874,7 +875,8 @@ impl PluginsManager {
}
let (installed_plugins, enabled_plugins) = self.configured_plugin_states(config);
let marketplace_outcome = list_marketplaces(&self.marketplace_roots(additional_roots))?;
let marketplace_outcome =
list_marketplaces(&self.marketplace_roots(config, additional_roots))?;
let mut seen_plugin_keys = HashSet::new();
let marketplaces = marketplace_outcome
.marketplaces
@@ -1218,10 +1220,18 @@ impl PluginsManager {
(installed_plugins, enabled_plugins)
}
fn marketplace_roots(&self, additional_roots: &[AbsolutePathBuf]) -> Vec<AbsolutePathBuf> {
fn marketplace_roots(
&self,
config: &Config,
additional_roots: &[AbsolutePathBuf],
) -> Vec<AbsolutePathBuf> {
// Treat the curated catalog as an extra marketplace root so plugin listing can surface it
// without requiring every caller to know where it is stored.
let mut roots = additional_roots.to_vec();
roots.extend(installed_marketplace_roots_from_config(
config,
self.codex_home.as_path(),
));
let curated_repo_root = curated_plugins_repo_path(self.codex_home.as_path());
if curated_repo_root.is_dir()
&& let Ok(curated_repo_root) = AbsolutePathBuf::try_from(curated_repo_root)