Plugin Marketplaces
A plugin marketplace is a plugin directory file used to distribute and manage CodeBuddy extensions. It is a JSON-formatted configuration file that lists available plugins and their source information.
Core Features
- Centralized Discovery: Browse plugins from multiple sources in one place
- Version Management: Automatically track and update plugin versions
- Auto-Update: Support enabling auto-update to periodically sync marketplace content
- Team Distribution: Share required plugins within organizations
- Flexible Sources: Support for Git repositories, GitHub repositories, local paths, and HTTP URLs
Runtime Projection and Management Ownership
Agent CLI's initial plugin projection is cache-first: the process reads only enabledPlugins from each settings scope, the installed_plugins.json registry, and the immutable plugin cache referenced by that registry. The initial projection does not scan marketplaces, access remote sources, or repair or migrate on-disk state. The dependency closure of enabled plugins is also resolved only from the same registry and cache.
An Agent CLI runtime with management permissions starts one background reconcile after the initial projection is committed. It synchronizes marketplaces, installs missing plugins, migrates legacy caches, applies policies, and cleans up orphaned state. After committing, it submits the active plugin snapshot through the same serialized transaction queue so that management and projection passes do not overlap. Within the transaction, MCP/LSP and Product projections are prepared in parallel; after the Product projection is committed, Command, Output Style, and Agent are rebuilt in parallel. If the active snapshot produced by the background reconcile is unchanged, downstream components are not reprojected; when it changes, only affected components are refreshed. After the initial projection assumes management ownership, a change to the persisted enabledPlugins or extraKnownMarketplaces content immediately queues a full configured reconcile in the same long-running runtime. Direct edits to settings files from outside the process are also handled by ConfigWatchService, which invalidates the cache and emits the same settings change. Repeated changes are coalesced through generation + single-flight, so cache materialization does not need to wait until the next task is created.
install and enable have different semantics. An explicit plugin install synchronously resolves dependencies, writes to the versioned cache/<marketplace>/<plugin>/<version>, commits installed_plugins.json, and writes the enabled state by standard default. plugin enable only declares desired state: even if the plugin can already be discovered from a Marketplace but has not yet been installed, the enable operation does not write the cache or registry. After a short-lived plugin enable command exits, the next regular Agent startup performs the reconcile; in a long-running Host, the settings-change reconcile described above immediately takes over materialization. This matches Claude Code's install/enable/startup boundary.
plugin update likewise follows the immutable semantics of the versioned cache. If the version declared by the Marketplace matches the currently installed version, it is treated as up to date without rewriting the cache, registry, or dependency state. When the declared version changes, a new version directory is written and the registry is switched atomically, while existing Sessions continue to reference the old directory. Only an unknown cache for which neither a declared version nor a Git SHA can actually be obtained may attempt an in-place refresh. If other Session markers still exist, the old contents and their payload metadata are retained and the refresh is deferred to a later update/reconcile; a safe deferral is not returned as HTTP 500. This matches Claude Code's update/cache boundary.
Long-running hosts can also call POST /api/v1/plugins/reconcile to idempotently materialize the complete configured state declared by Product/settings and rebuild the runtime projection afterward. This endpoint does not accept a host name, marketplace name, or local path, so it does not create a WorkBuddy-specific management branch. Concurrent requests share the same underlying pass. HTTP waiters have a fixed upper bound; a timeout or client disconnect ends only the current wait and does not cancel the underlying materialization, which remains protected by a cross-process lock. Later requests can still join or retry. Marketplace/cache state that was atomically committed before a strict aggregate failure is projected first as a partial/last-good state. When the same route receives a body containing requiredPluginIds, its semantics are the opposite: it only projects and strictly validates the already committed roots and dependency closure; it does not install plugins, update Marketplaces, or write cache/registry/settings. If a startup/settings producer is already running, validation may join that existing flight once and then recheck. Validation itself never creates a new management write merely because a task is starting.
Regular TUI, --print, headless, stream-json, ACP, and serve invocations share the same initial boundary: at startup they build the complete runtime projection from the committed registry/cache and wait for that projection to complete before the first actual Agent dispatch. They do not insert a foreground Marketplace download based on the protocol mode or defer downstream projection until a Session control request. A missing cache or load failure for one plugin only leaves that plugin absent and records a plugin error; other plugins and the Agent continue to run. The background reconcile restores the missing plugin and reprojects after committing it. Hosts such as WorkBuddy that declare explicit required roots for the current Session should prepare the cache during configuration/install/startup and perform only read-only validation before starting the worker. After the process starts, it consumes that committed state directly instead of repeating reconcile before session/new|load|resume. With explicit --no-plugin-management, Agent CLI builds the complete projection only from the existing registry/cache and performs no management writes.
A Directory Marketplace follows standard installation semantics: the marketplace registration record retains the source directory, but installed plugins still go through standard dependency resolution, are materialized into cache/<marketplace>/<plugin>/<version>, and are then committed to installed_plugins.json. At runtime, plugins are loaded only from that versioned snapshot; the mutable marketplace source is not treated directly as an installed plugin. Directory and remote marketplaces declared by Product reuse this flow, and processes with management permissions idempotently restore missing cache/registry state.
--no-plugin-management is a generic explicit read-only switch intended only for special runtimes where the host can already guarantee a complete registry/cache closure. In this mode, marketplace and plugin installation, update, removal, enablement, disablement, and repair APIs are rejected before any I/O. Regular CLI and Session runtimes retain standard management capabilities by default; Agent CLI does not switch to this mode automatically based on host branding or topology.
Marketplace write operations acquire cross-process locks by source → stable storage name. An add operation holds the source lock before any clone, download, or swap and checks again for duplicates by normalized source while holding the lock, closing the TOCTOU window between concurrent check and install operations. A remote add first writes to a separate staging directory and cleans up the old directory only after the registry commit succeeds. Concurrent updates in the same process share one remote synchronization, while cross-process update and remove operations follow the same lock order. Removing a marketplace cleans up all of its registry/settings records in user, project, and local scopes, along with orphaned caches, plugin configuration, and MCP OAuth credentials. Product-managed built-in marketplaces cannot be removed or replaced through ordinary operations.
Remote marketplaces also have a single lifecycle owned by Agent CLI: Product declares only source, url, and optional versionUrl and autoUpdate values. ZIP sources check freshness in the order versionUrl → ZIP URL version → ETag/Last-Modified; routine automatic updates do not clear this check metadata or force a download. ZIP freshness applies only when marketplace.json and every local plugin directory declared in it are complete. Any missing directory bypasses the version/ETag short-circuit and downloads a complete snapshot again. Both ZIP and URL sources finish downloading and fully validating their manifests in a separate directory before atomically replacing the live source. If any plugin manifest in a URL source fails validation, the entire refresh fails and no partial directory is published. Git sources likewise perform a shallow clone and full manifest validation next to the live checkout, then use backup + rename to promote it atomically only after a new commit is ready. The same commit is a no-op, and clone, authentication, network, or manifest failures preserve the old checkout. If any remote registry record points to a missing or incomplete local source snapshot, the background reconcile treats it as requiring rematerialization rather than considering it installed merely because the source metadata matches. If a declarative Directory source is temporarily unavailable, its registration record and existing plugin cache are conservatively retained instead of overwriting the last-good state with an empty directory. A failed refresh does not commit a new marketplace record or rewrite the installed registry/cache; the existing version continues to run as last-good. Installed plugins from a marketplace are rematerialized only when its source content actually changes. Declarative source replacement and recovery from interrupted state reuse the same materialization path instead of changing only marketplace metadata and leaving an old plugin cache behind. force is only for explicit user recovery or diagnostics, not an alternative host updater.
Stable marketplace names declared by Product take precedence over historical URL-derived aliases for the same source: the standard registration transaction retires an old alias after committing the new record. Agent CLI does not recognize WorkBuddy, Desktop, or any other platform brand; hosts should not maintain an additional version file, timer, or forced-refresh RPC.
Using Plugin Marketplaces
Prerequisites
- CodeBuddy installed and running
- Basic understanding of JSON file format
- For creating a marketplace: Git repository or local development environment
Adding a Plugin Marketplace
1. Add a GitHub Marketplace
bash
/plugin marketplace add owner/repoThe repository must contain a .codebuddy-plugin/marketplace.json file.
2. Add a Git Repository Marketplace
bash
# HTTPS format
/plugin marketplace add https://gitlab.com/company/plugins.git
# SSH format (git@)
/plugin marketplace add git@gitlab.com:company/plugins.git
# .git suffix format
/plugin marketplace add https://example.com/repo.git3. Add a Local Marketplace (for development)
bash
# Add a local directory containing .codebuddy-plugin/marketplace.json
/plugin marketplace add ./my-marketplace
# Directly add a marketplace.json file path
/plugin marketplace add ./path/to/marketplace.json4. Add an HTTP Marketplace
bash
# Add a remote marketplace.json via URL
/plugin marketplace add https://url.of/marketplace.jsonInstalling Plugins from a Marketplace
bash
# Install from a known marketplace
/plugin install plugin-name@marketplace-name
# Interactively browse available plugins
/pluginVerifying Marketplace Installation
- List Marketplaces: Run
/plugin marketplace listto confirm the marketplace was added - Browse Plugins: Use
/pluginto view available plugins in the marketplace - Test Installation: Try installing a plugin to verify the marketplace is working properly
Team Configuration
Automatically Install Team Marketplaces
Configure in .codebuddy/settings.json:
json
{
"extraKnownMarketplaces": {
"team-tools": {
"source": {
"source": "github",
"repo": "your-org/codebuddy-plugins"
}
},
"project-specific": {
"source": {
"source": "git",
"url": "https://git.company.com/project-plugins.git"
}
}
},
"enabledPlugins": {
"plugin-a@team-tools": true,
"plugin-b@team-tools": true
}
}When team members start CodeBuddy, the system automatically installs these marketplaces and the plugins specified in the enabledPlugins field.
Automatic Installation Flow
- Startup Detection: CodeBuddy automatically detects the configuration file on startup
- Marketplace Installation: Automatically installs marketplaces from
extraKnownMarketplacesthat are not yet installed - Plugin Installation: Automatically installs enabled plugins from
enabledPluginsthat are not yet installed - Background Execution: The installation process executes asynchronously in the background without blocking the startup flow
- Logging: The installation process logs detailed information, viewable with
--debug
Creating Your Own Marketplace
Prerequisites for Creation
- Git repository (GitHub, GitLab, or other git hosting service)
- Understanding of JSON file format
- One or more plugins to distribute
Creating the Marketplace File
Create .codebuddy-plugin/marketplace.json in the repository root:
json
{
"name": "company-tools",
"owner": {
"name": "DevTools Team",
"email": "[email protected]"
},
"plugins": [
{
"name": "code-formatter",
"source": "./plugins/formatter",
"description": "Automatic code formatting on save",
"version": "2.1.0"
},
{
"name": "deployment-tools",
"source": {
"source": "github",
"repo": "company/deploy-plugin"
},
"description": "Deployment automation tools"
}
]
}Marketplace Schema
Required Fields
| Field | Type | Description |
|---|---|---|
| name | string | Marketplace identifier (kebab-case, no spaces) |
| owner | object | Marketplace maintainer information |
| plugins | array | List of available plugins |
Optional Metadata Fields
| Field | Type | Description |
|---|---|---|
| description | string | Brief marketplace description |
| version | string | Marketplace version |
Plugin Entry Configuration
Required Fields
| Field | Type | Description |
|---|---|---|
| name | string | Plugin identifier (kebab-case, no spaces) |
| source | string/object | Plugin source location |
| description | string | Brief plugin description |
Optional Metadata Fields
| Field | Type | Description |
|---|---|---|
| version | string | Plugin version |
| author | object | Plugin author information |
| homepage | string | Plugin homepage or documentation URL |
| repository | string | Source code repository URL |
| license | string | SPDX license identifier (e.g., MIT, Apache-2.0) |
| keywords | array | Tags for plugin discovery and categorization |
| category | string | Plugin category |
| strict | boolean | Require plugin.json in plugin folder (default: true) |
Component Configuration Fields
| Field | Type | Description |
|---|---|---|
| commands | string/array | Custom path to command files or directories |
| agents | string/array | Custom path to agent files |
| skills | string/array | Custom path to skill files |
| hooks | string/object | Custom hooks configuration or hooks file path |
| mcpServers | string/object | MCP server configuration or MCP config path |
About the strict field:
strict: true(default): Plugin must contain aplugin.jsonmanifest file, marketplace fields supplement these valuesstrict: false:plugin.jsonis optional. If missing, the marketplace entry serves as the complete plugin manifest
Plugin Source Types
1. Relative Path (Local)
For plugins in the same repository:
json
{
"name": "my-plugin",
"source": "./plugins/my-plugin",
"description": "My local plugin"
}2. GitHub Repository
json
{
"name": "github-plugin",
"source": {
"source": "github",
"repo": "owner/plugin-repo"
},
"description": "Plugin from GitHub"
}3. Git URL
json
{
"name": "git-plugin",
"source": {
"source": "url",
"url": "https://gitlab.com/team/plugin.git"
},
"description": "Plugin from Git URL"
}Advanced Plugin Entry Example
json
{
"name": "enterprise-tools",
"source": {
"source": "github",
"repo": "company/enterprise-plugin"
},
"description": "Enterprise workflow automation tools",
"version": "2.1.0",
"author": {
"name": "Enterprise Team",
"email": "[email protected]"
},
"homepage": "https://docs.company.com/plugins/enterprise-tools",
"repository": "https://github.com/company/enterprise-plugin",
"license": "MIT",
"keywords": ["enterprise", "workflow", "automation"],
"category": "productivity",
"commands": [
"./commands/core/",
"./commands/enterprise/",
"./commands/experimental/preview.md"
],
"agents": [
"./agents/security-reviewer.md",
"./agents/compliance-checker.md"
],
"skills": [
"./skills/deployment.md",
"./skills/monitoring.md"
],
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "${CODEBUDDY_PLUGIN_ROOT}/scripts/validate.sh"
}]
}
]
},
"mcpServers": {
"enterprise-db": {
"command": "${CODEBUDDY_PLUGIN_ROOT}/servers/db-server",
"args": ["--config", "${CODEBUDDY_PLUGIN_ROOT}/config.json"]
}
},
"strict": false
}Note: ${CODEBUDDY_PLUGIN_ROOT} is an environment variable that resolves to the plugin's installation directory.
Hosting and Distributing Marketplaces
1. Hosting on GitHub (Recommended)
Steps:
- Create a repository: Set up a new repository for the marketplace
- Add the marketplace file: Create
.codebuddy-plugin/marketplace.jsonand define plugins - Share with your team: Team members add it using
/plugin marketplace add owner/repo
Advantages: Built-in version control, issue tracking, and team collaboration features
2. Hosting on Other Git Services
Any git hosting service can be used for marketplace distribution. For example, using GitLab:
bash
/plugin marketplace add https://gitlab.com/company/plugins.git3. Hosting via HTTP URL
You can host the marketplace.json file on any HTTP(S) server:
bash
/plugin marketplace add https://example.com/path/to/marketplace.json4. Using Local Marketplaces for Development
Test marketplaces locally before distribution:
bash
# Add a local marketplace for testing
/plugin marketplace add ./my-local-marketplace
# Test plugin installation
/plugin install test-plugin@my-local-marketplaceMarketplace Management Operations
List Known Marketplaces
bash
/plugin marketplace listDisplays all configured marketplaces along with their sources and status.
Update Marketplace Metadata
bash
/plugin marketplace update marketplace-nameRefreshes the plugin list and metadata from the marketplace source.
Remove a Marketplace
bash
/plugin marketplace remove marketplace-nameRemoves the marketplace from configuration.
⚠️ Warning: Removing a marketplace will uninstall all plugins installed from it.
Managing Auto-Updates
You can enable auto-update functionality for marketplaces, where CodeBuddy automatically checks and updates enabled marketplaces on startup.
How to Enable:
- Run the
/plugincommand to enter plugin management interface - Select "Marketplaces" to view the marketplace list
- Select the marketplace you want to configure
- Select "Enable auto-update" or "Disable auto-update" to toggle the status
Auto-Update Mechanism:
- Executed with a 5-second delay on startup, does not affect main flow
- Only updates marketplaces that haven't been updated in over 24 hours
- Updates between multiple marketplaces are spaced 2 seconds apart to avoid resource contention
- Update failures do not affect other marketplaces, errors are logged
Priority: The CODEBUDDY_AUTO_UPDATE_THIRD_PARTY_MARKETPLACES environment variable takes precedence over an individual marketplace's UI toggle.
Implementation Details
Marketplace Types
CodeBuddy supports the following marketplace types:
- Directory (Local Directory): Load plugins from the local filesystem
- GitHub: Clone and update plugins from GitHub repositories
- Git: Clone and update plugins from any Git repository
- URL (HTTP): Download marketplace.json from HTTP(S) URLs
Marketplace Factory Pattern
The MarketplaceFactory creates different marketplace instances based on configuration:
typescript
// Create the corresponding marketplace instance based on source type
switch (sourceType) {
case MarketplaceType.Directory:
marketplace = new DirectoryMarketplace();
break;
case MarketplaceType.Github:
case MarketplaceType.Git:
marketplace = new GithubMarketplace();
break;
case MarketplaceType.URL:
marketplace = new HttpMarketplace();
break;
default:
marketplace = new BaseMarketplace();
break;
}Installation Flow
- Parse Source: Determine marketplace type based on input string (local path, GitHub repo, Git URL, HTTP URL)
- Download/Clone: Download or clone marketplace content based on marketplace type
- Read Manifest: Parse the
.codebuddy-plugin/marketplace.jsonfile - Save Configuration: Save marketplace information to local storage
- Update Cache: Refresh plugin cache and marketplace list
Plugin Installers
CodeBuddy uses plugin installers (PluginInstaller) to handle different plugin source types:
- Local Installer: Handles relative path plugins
- Git Installer: Handles GitHub and Git URL plugins
Each installer implements the following methods:
support(source): Determine if this plugin source is supportedisInstalled(plugin, targetDir): Check if the plugin is already installedinstall(plugin, targetDir): Install the pluginupdate(plugin, installedPath): Update the plugin
Troubleshooting
Common Issues
1. Marketplace Fails to Load
Symptoms: Cannot add marketplace or cannot see its plugins
Solutions:
- Verify the marketplace URL is accessible
- Check that
.codebuddy-plugin/marketplace.jsonexists at the specified path - Ensure JSON syntax is valid
- For private repositories, confirm you have access permissions
2. Plugin Installation Fails
Symptoms: Marketplace displays but plugin installation fails
Solutions:
- Verify the plugin source URL is accessible
- Check that the plugin directory contains required files
- For GitHub sources, ensure the repository is public or you have access
- Manually test the plugin source by cloning/downloading
3. Git Operations Fail
Symptoms: Errors when cloning or pulling repositories
Solutions:
- Ensure Git is installed and available in the command line
- Check network connection and proxy settings
- Verify Git credentials are configured correctly
- Use the
--debugflag to view detailed logs
Relative Path Issues in URL-Based Marketplaces
A URL-based marketplace is a catalog distribution mechanism: Agent CLI fetches marketplace.json and fetches plugin.json for relative-path entries, but it cannot recursively mirror arbitrary plugin files through HTTP directory listings. Therefore, relative paths can be used only by plugins whose functionality is fully inlined in the manifest. Plugins that include skills, commands, hooks, or local code should declare a materializable remote source such as Git or NPM in their entries, or publish the entire marketplace through Git or ZIP. This makes the boundary between the catalog and plugin payload explicit and prevents a downloaded plugin.json from being mistaken for a complete plugin directory.
Debugging Tips
- Enable Debug Logging:
bash
codebuddy --debug- Manually Verify Marketplace File:
bash
# Check marketplace.json format
cat .codebuddy-plugin/marketplace.json | jq- Test Git Clone:
bash
# Manually test if Git clone succeeds
git clone https://github.com/owner/repo.git /tmp/test-cloneNext Steps
For Marketplace Users
- Discover community marketplaces: Search for CodeBuddy plugin collections on GitHub
- Contribute feedback: Report issues and suggest improvements to marketplace maintainers
- Share useful marketplaces: Help your team discover valuable plugin collections
For Marketplace Creators
- Build plugin collections: Create themed marketplaces around specific use cases
- Establish versioning: Implement clear versioning and update strategies
- Community engagement: Gather feedback and maintain an active marketplace community
- Documentation: Provide clear README files explaining marketplace contents
For Organizations
- Private marketplaces: Set up internal marketplaces for proprietary tools
- Governance policies: Establish plugin approval and security review guidelines
- Training resources: Help teams effectively discover and adopt useful plugins
Related Resources
- Plugin System - Plugin system overview
- Skills System - Creating and using skills
- Slash Commands - Creating custom commands
- Hooks - Creating event hooks
- Settings - Plugin configuration options