marketplace

package
v0.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 4, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// CacheTTL is how long cached marketplace data remains valid (24 hours)
	CacheTTL = 24 * time.Hour

	// MaxMarketplaceNameLength limits marketplace name length for security
	MaxMarketplaceNameLength = 100
)
View Source
const (
	// DefaultBranch to fetch from
	DefaultBranch = "main"

	// HTTPTimeout for fetching marketplace files (reduced for better UX)
	HTTPTimeout = 15 * time.Second

	// MaxResponseBodySize limits HTTP response size to prevent DoS (10 MB)
	MaxResponseBodySize = 10 << 20

	// MaxRetries for transient network failures
	MaxRetries = 3
)
View Source
const (
	// GitHubStatsCacheTTL is how long cached GitHub stats remain valid (24 hours)
	GitHubStatsCacheTTL = 24 * time.Hour

	// GitHubAPIBase is the base URL for GitHub API v3
	GitHubAPIBase = "https://api.github.com"
)
View Source
const (
	// RegistryURL is the URL to the official marketplace registry
	RegistryURL = "https://raw.githubusercontent.com/itsdevcoffee/plum/main/marketplaces.json"

	// RegistryCacheName for storing the registry
	RegistryCacheName = "_registry"

	// RegistryCacheTTL is how often to check for registry updates (6 hours)
	RegistryCacheTTL = 6 * time.Hour
)
View Source
const (
	// MaxConcurrentFetches limits parallel marketplace downloads
	MaxConcurrentFetches = 5
)

Variables

View Source
var (
	// GitHubRawBase is the base URL for GitHub raw content (variable for testing)
	GitHubRawBase = "https://raw.githubusercontent.com"
)
View Source
var PopularMarketplaces = []PopularMarketplace{
	{
		Name:        "claude-code-plugins-plus",
		DisplayName: "Claude Code Plugins Plus",
		Repo:        "https://github.com/jeremylongshore/claude-code-plugins-plus-skills",
		Description: "The largest collection with 313 plugins and Agent Skills",
		StaticStats: &GitHubStats{
			Stars:        1242,
			Forks:        154,
			LastPushedAt: mustParseTime("2026-02-01T05:24:47Z"),
			OpenIssues:   0,
		},
	},
	{
		Name:        "claude-code-marketplace",
		DisplayName: "Claude Code Marketplace",
		Repo:        "https://github.com/ananddtyagi/cc-marketplace",
		Description: "Community-driven marketplace with 119 plugins",
		StaticStats: &GitHubStats{
			Stars:        634,
			Forks:        52,
			LastPushedAt: mustParseTime("2026-01-18T17:50:15Z"),
			OpenIssues:   6,
		},
	},
	{
		Name:        "claude-code-plugins",
		DisplayName: "Claude Code Plugins",
		Repo:        "https://github.com/anthropics/claude-code",
		Description: "Official Anthropic plugins with 13 plugins maintained by the Claude Code team",
		StaticStats: &GitHubStats{
			Stars:        63817,
			Forks:        4823,
			LastPushedAt: mustParseTime("2026-02-04T00:44:13Z"),
			OpenIssues:   6056,
		},
	},
	{
		Name:        "mag-claude-plugins",
		DisplayName: "MAG Claude Plugins",
		Repo:        "https://github.com/MadAppGang/claude-code",
		Description: "Battle-tested workflows with 8 specialized plugins",
		StaticStats: &GitHubStats{
			Stars:        221,
			Forks:        21,
			LastPushedAt: mustParseTime("2026-02-03T07:52:27Z"),
			OpenIssues:   2,
		},
	},
	{
		Name:        "dev-gom-plugins",
		DisplayName: "Dev-GOM Plugins",
		Repo:        "https://github.com/Dev-GOM/claude-code-marketplace",
		Description: "Automation-focused collection with 14 plugins",
		StaticStats: &GitHubStats{
			Stars:        58,
			Forks:        5,
			LastPushedAt: mustParseTime("2026-01-17T16:54:15Z"),
			OpenIssues:   0,
		},
	},
	{
		Name:        "feedmob-claude-plugins",
		DisplayName: "FeedMob Plugins",
		Repo:        "https://github.com/feed-mob/claude-code-marketplace",
		Description: "Productivity and workflow tools with 7 specialized plugins",
		StaticStats: &GitHubStats{
			Stars:        2,
			Forks:        1,
			LastPushedAt: mustParseTime("2025-12-22T09:15:58Z"),
			OpenIssues:   0,
		},
	},
	{
		Name:        "claude-plugins-official",
		DisplayName: "Claude Plugins Official",
		Repo:        "https://github.com/anthropics/claude-plugins-official",
		Description: "Official Anthropic marketplace with 51 plugins",
		StaticStats: &GitHubStats{
			Stars:        6397,
			Forks:        616,
			LastPushedAt: mustParseTime("2026-01-30T06:58:05Z"),
			OpenIssues:   171,
		},
	},
	{
		Name:        "anthropic-agent-skills",
		DisplayName: "Anthropic Agent Skills",
		Repo:        "https://github.com/anthropics/skills",
		Description: "Official Anthropic Agent Skills reference repository with 2 skills",
		StaticStats: &GitHubStats{
			Stars:        62390,
			Forks:        6119,
			LastPushedAt: mustParseTime("2026-02-04T02:20:55Z"),
			OpenIssues:   229,
		},
	},
	{
		Name:        "wshobson-agents",
		DisplayName: "Hobson's Agent Collection",
		Repo:        "https://github.com/wshobson/agents",
		Description: "Comprehensive production system with 71 plugins and multi-agent orchestration",
		StaticStats: &GitHubStats{
			Stars:        27707,
			Forks:        3055,
			LastPushedAt: mustParseTime("2026-02-02T02:06:12Z"),
			OpenIssues:   12,
		},
	},
	{
		Name:        "docker-plugins",
		DisplayName: "Docker Official Plugins",
		Repo:        "https://github.com/docker/claude-plugins",
		Description: "Official Docker Inc. marketplace with 1 plugin for Docker Desktop MCP",
		StaticStats: &GitHubStats{
			Stars:        13,
			Forks:        6,
			LastPushedAt: mustParseTime("2026-01-30T16:26:32Z"),
			OpenIssues:   1,
		},
	},
	{
		Name:        "claude-mem",
		DisplayName: "Claude-Mem",
		Repo:        "https://github.com/thedotmack/claude-mem",
		Description: "Persistent memory compression system for Claude Code with context preservation",
		StaticStats: &GitHubStats{
			Stars:        20789,
			Forks:        1404,
			LastPushedAt: mustParseTime("2026-02-04T02:09:03Z"),
			OpenIssues:   212,
		},
	},
}

PopularMarketplaces is the hardcoded list from README.md with static GitHub stats Stats snapshot: 2026-02-04 (updated with fresh data including timestamps)

Functions

func ClearCache

func ClearCache() error

ClearCache removes all cached marketplace data

func ClearCacheEntry added in v0.4.0

func ClearCacheEntry(marketplaceName string) error

ClearCacheEntry removes a specific marketplace from cache

func DeriveSource added in v0.3.0

func DeriveSource(repoURL string) (string, error)

DeriveSource converts a repo URL to Claude Code CLI source format GitHub: https://github.com/owner/repo → owner/repo Others: https://gitlab.com/company/pluginshttps://gitlab.com/company/plugins (full URL)

func DiscoverPopularMarketplaces

func DiscoverPopularMarketplaces() (map[string]*DiscoveredMarketplace, error)

DiscoverPopularMarketplaces fetches and returns manifests for popular marketplaces Uses cached registry if available (from Shift+U), otherwise hardcoded list Uses cache when available, fetches from GitHub otherwise Returns partial results on partial failures (best-effort)

func DiscoverWithRegistry

func DiscoverWithRegistry() (map[string]*MarketplaceManifest, error)

DiscoverWithRegistry fetches marketplaces using the latest registry This is called when user presses Shift+U to update

func IsGitHubRepo added in v0.3.0

func IsGitHubRepo(repoURL string) bool

IsGitHubRepo checks if a repo URL is from GitHub

func PlumCacheDir

func PlumCacheDir() (string, error)

PlumCacheDir returns the path to plum's cache directory (~/.plum/cache/marketplaces/)

func RefreshAll

func RefreshAll() error

RefreshAll clears cache and re-fetches all marketplaces using latest registry

func SaveStatsToCache added in v0.3.0

func SaveStatsToCache(marketplaceName string, stats *GitHubStats) error

SaveStatsToCache saves GitHub stats to cache with atomic write

func SaveToCache

func SaveToCache(marketplaceName string, manifest *MarketplaceManifest) error

SaveToCache saves a marketplace manifest to cache using atomic write

Types

type Author

type Author struct {
	Name    string `json:"name"`
	Email   string `json:"email"`
	URL     string `json:"url"`
	Company string `json:"company"`
}

Author represents author information

type CacheEntry

type CacheEntry struct {
	Manifest  *MarketplaceManifest `json:"manifest"`
	FetchedAt time.Time            `json:"fetchedAt"`
	Source    string               `json:"source"`
}

CacheEntry represents a cached marketplace manifest with metadata

type DiscoveredMarketplace added in v0.3.0

type DiscoveredMarketplace struct {
	Manifest *MarketplaceManifest
	Repo     string // Full repo URL for display
	Source   string // Derived CLI source (owner/repo for GitHub, full URL for others)
}

DiscoveredMarketplace contains a marketplace manifest with source information

type GitHubStats added in v0.3.0

type GitHubStats struct {
	Stars        int       `json:"stargazers_count"`
	Forks        int       `json:"forks_count"`
	LastPushedAt time.Time `json:"pushed_at"`
	OpenIssues   int       `json:"open_issues_count"`
}

GitHubStats represents repository statistics from GitHub API

func FetchGitHubStats added in v0.3.0

func FetchGitHubStats(repoURL string) (*GitHubStats, error)

FetchGitHubStats fetches repository statistics from GitHub API v3 repoURL format: "https://github.com/owner/repo" or "owner/repo" Returns nil (not error) on failure to allow graceful degradation

func LoadStatsFromCache added in v0.3.0

func LoadStatsFromCache(marketplaceName string) (*GitHubStats, error)

LoadStatsFromCache loads GitHub stats from cache if valid Returns nil if cache miss or expired (not an error)

type GitHubStatsCacheEntry added in v0.3.0

type GitHubStatsCacheEntry struct {
	Stats     *GitHubStats `json:"stats"`
	FetchedAt time.Time    `json:"fetchedAt"`
	Repo      string       `json:"repo"`
}

GitHubStatsCacheEntry represents cached GitHub stats with metadata

type MarketplaceManifest

type MarketplaceManifest struct {
	Name     string              `json:"name"`
	Owner    MarketplaceOwner    `json:"owner"`
	Metadata MarketplaceMetadata `json:"metadata"`
	Plugins  []MarketplacePlugin `json:"plugins"`
}

MarketplaceManifest represents the marketplace.json structure

func FetchManifestFromGitHub

func FetchManifestFromGitHub(repoURL string) (*MarketplaceManifest, error)

FetchManifestFromGitHub fetches marketplace.json from a GitHub repo with retries repoURL format: "https://github.com/owner/repo-name" or "owner/repo-name" (legacy) Returns the parsed manifest or error

func LoadFromCache

func LoadFromCache(marketplaceName string) (*MarketplaceManifest, error)

LoadFromCache loads a marketplace manifest from cache if valid Returns nil if cache miss or expired (no error)

type MarketplaceMetadata

type MarketplaceMetadata struct {
	Description string `json:"description"`
	Version     string `json:"version"`
	PluginRoot  string `json:"pluginRoot"`
}

MarketplaceMetadata represents marketplace metadata

type MarketplaceOwner

type MarketplaceOwner struct {
	Name    string `json:"name"`
	Email   string `json:"email"`
	Company string `json:"company"`
}

MarketplaceOwner represents the owner of a marketplace

type MarketplacePlugin

type MarketplacePlugin struct {
	Name        string   `json:"name"`
	Source      string   `json:"source"`
	Description string   `json:"description"`
	Version     string   `json:"version"`
	Author      Author   `json:"author"`
	Category    string   `json:"category"`
	Homepage    string   `json:"homepage"`
	Repository  string   `json:"repository"`
	License     string   `json:"license"`
	Keywords    []string `json:"keywords"`
	Tags        []string `json:"tags"`
	Strict      bool     `json:"strict"`

	// Installability tracking (set during unmarshaling or validation)
	HasLSPServers bool `json:"-"` // True if plugin has lspServers config (built into Claude Code)
	IsExternalURL bool `json:"-"` // True if source points to external Git repo
	IsIncomplete  bool `json:"-"` // True if plugin is missing required files (e.g., .claude-plugin/plugin.json)
}

MarketplacePlugin represents a plugin entry in a marketplace manifest

func (*MarketplacePlugin) InstallabilityReason added in v0.4.1

func (mp *MarketplacePlugin) InstallabilityReason() string

InstallabilityReason returns a human-readable reason why the plugin is not installable. Returns empty string if the plugin is installable.

func (*MarketplacePlugin) InstallabilityTag added in v0.4.1

func (mp *MarketplacePlugin) InstallabilityTag() string

InstallabilityTag returns a short tag for display purposes. Returns empty string if the plugin is installable.

func (*MarketplacePlugin) Installable added in v0.4.1

func (mp *MarketplacePlugin) Installable() bool

Installable returns true if the plugin can be installed via plum. Plugins with LSP servers, external URLs, or missing files require different installation methods.

func (*MarketplacePlugin) UnmarshalJSON added in v0.3.3

func (mp *MarketplacePlugin) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom JSON unmarshaling for MarketplacePlugin to handle the "source" field which can be either a string or an object with Git URL. Also detects LSP plugins and external URL sources for installability tracking. Required for claude-plugins-official compatibility (Atlassian, Figma, Vercel, etc.)

type MarketplaceRegistry

type MarketplaceRegistry struct {
	Version      string               `json:"version"`
	LastUpdated  string               `json:"lastUpdated"`
	Description  string               `json:"description"`
	Marketplaces []PopularMarketplace `json:"marketplaces"`
}

MarketplaceRegistry represents the registry structure

type PopularMarketplace

type PopularMarketplace struct {
	Name        string       `json:"name"`
	DisplayName string       `json:"displayName"`
	Repo        string       `json:"repo"` // Full repo URL (e.g., https://github.com/owner/repo)
	Description string       `json:"description"`
	StaticStats *GitHubStats `json:"staticStats,omitempty"` // Static GitHub stats snapshot (fallback if cache empty)
}

PopularMarketplace represents a hardcoded popular marketplace

func FetchRegistry

func FetchRegistry() ([]PopularMarketplace, error)

FetchRegistry fetches the marketplace registry from GitHub Falls back to hardcoded PopularMarketplaces on failure

func FetchRegistryWithComparison

func FetchRegistryWithComparison(current []PopularMarketplace) ([]PopularMarketplace, int, error)

FetchRegistryWithComparison fetches registry and compares with current Returns new marketplaces count and the full list Compares against CACHED registry if available, otherwise uses provided list

type RegistryCacheEntry

type RegistryCacheEntry struct {
	Registry  *MarketplaceRegistry `json:"registry"`
	FetchedAt time.Time            `json:"fetchedAt"`
}

RegistryCacheEntry represents a cached registry with metadata

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL