Documentation
¶
Index ¶
- Constants
- Variables
- func ClearCache() error
- func DeriveSource(repoURL string) (string, error)
- func DiscoverPopularMarketplaces() (map[string]*DiscoveredMarketplace, error)
- func DiscoverWithRegistry() (map[string]*MarketplaceManifest, error)
- func IsGitHubRepo(repoURL string) bool
- func PlumCacheDir() (string, error)
- func RefreshAll() error
- func SaveStatsToCache(marketplaceName string, stats *GitHubStats) error
- func SaveToCache(marketplaceName string, manifest *MarketplaceManifest) error
- type Author
- type CacheEntry
- type DiscoveredMarketplace
- type GitHubStats
- type GitHubStatsCacheEntry
- type MarketplaceManifest
- type MarketplaceMetadata
- type MarketplaceOwner
- type MarketplacePlugin
- type MarketplaceRegistry
- type PopularMarketplace
- type RegistryCacheEntry
Constants ¶
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 )
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 )
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" )
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 )
const (
// MaxConcurrentFetches limits parallel marketplace downloads
MaxConcurrentFetches = 5
)
Variables ¶
var (
// GitHubRawBase is the base URL for GitHub raw content (variable for testing)
GitHubRawBase = "https://raw.githubusercontent.com"
)
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 280 plugins and 185 Agent Skills", StaticStats: &GitHubStats{ Stars: 939, Forks: 114, LastPushedAt: mustParseTime("2026-01-11T01:39:29Z"), OpenIssues: 9, }, }, { Name: "claude-code-marketplace", DisplayName: "Claude Code Marketplace", Repo: "https://github.com/ananddtyagi/cc-marketplace", Description: "Community-driven marketplace with 117 plugins", StaticStats: &GitHubStats{ Stars: 599, Forks: 50, LastPushedAt: mustParseTime("2025-12-14T22:31:07Z"), OpenIssues: 7, }, }, { 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: 54841, Forks: 3968, LastPushedAt: mustParseTime("2026-01-11T00:28:28Z"), OpenIssues: 4669, }, }, { Name: "mag-claude-plugins", DisplayName: "MAG Claude Plugins", Repo: "https://github.com/MadAppGang/claude-code", Description: "Battle-tested workflows with 10 specialized plugins", StaticStats: &GitHubStats{ Stars: 204, Forks: 19, LastPushedAt: mustParseTime("2026-01-10T13:40:21Z"), 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: 46, Forks: 5, LastPushedAt: mustParseTime("2025-12-02T03:56:32Z"), 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 44 plugins", StaticStats: &GitHubStats{ Stars: 2732, Forks: 305, LastPushedAt: mustParseTime("2026-01-09T22:48:32Z"), OpenIssues: 108, }, }, { 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: 37240, Forks: 3373, LastPushedAt: mustParseTime("2025-12-20T18:09:45Z"), OpenIssues: 136, }, }, { Name: "wshobson-agents", DisplayName: "Hobson's Agent Collection", Repo: "https://github.com/wshobson/agents", Description: "Comprehensive production system with 68 plugins and multi-agent orchestration", StaticStats: &GitHubStats{ Stars: 24965, Forks: 2750, LastPushedAt: mustParseTime("2026-01-09T15:41:06Z"), OpenIssues: 9, }, }, { 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: 4, LastPushedAt: mustParseTime("2025-12-19T19:10:46Z"), OpenIssues: 0, }, }, { Name: "ccplugins-marketplace", DisplayName: "CC Plugins Curated", Repo: "https://github.com/ccplugins/marketplace", Description: "Curated collection with 118 plugins across 13 categories", StaticStats: &GitHubStats{ Stars: 11, Forks: 7, LastPushedAt: mustParseTime("2025-10-14T03:38:20Z"), OpenIssues: 2, }, }, { 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: 13076, Forks: 825, LastPushedAt: mustParseTime("2026-01-10T23:24:37Z"), OpenIssues: 57, }, }, }
PopularMarketplaces is the hardcoded list from README.md with static GitHub stats Stats snapshot: 2026-01-11 (updated with fresh data including timestamps)
Functions ¶
func DeriveSource ¶ added in v0.3.0
DeriveSource converts a repo URL to Claude Code CLI source format GitHub: https://github.com/owner/repo → owner/repo Others: https://gitlab.com/company/plugins → https://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
IsGitHubRepo checks if a repo URL is from GitHub
func PlumCacheDir ¶
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"`
}
MarketplacePlugin represents a plugin entry in a marketplace manifest
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. 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