In the previous chapter, CCR State Synchronization, we built a reliable "highway" ensuring our connection to the AI remains stable and synchronized.
Now that we have a stable connection, we want to make the AI more useful. A basic AI is like a fresh smartphone: it has a great operating system, but it becomes truly powerful when you install Apps.
In this project, these apps are called Plugins.
Imagine you want the AI to interact with your specific database or control your smart home lights. The AI model (in the cloud) doesn't know how to talk to your local lightbulbs natively.
We need a way to:
The Plugin Management system handles this lifecycle. It acts exactly like an "App Store" and "Package Manager" for the CLI.
Before we can install anything, we need to know where to look. We call these sources Marketplaces.
A Marketplace can be:
owner/cool-plugins)../my-plugins).
The handler marketplaceAddHandler takes a user's input (like a URL) and registers it as a valid source of plugins.
// handlers/plugins.ts (Simplified)
export async function marketplaceAddHandler(source: string, options: any) {
// 1. Parse the input (is it a URL? a path?)
const parsed = await parseMarketplaceInput(source);
// 2. Add it to the system and download the catalog
const { name } = await addMarketplaceSource(parsed, (msg) => console.log(msg));
// 3. Save this choice to the user's settings
saveMarketplaceToSettings(name, { source: parsed }, 'user');
console.log(`Successfully added marketplace: ${name}`);
}
Explanation: The code figures out if you gave it a GitHub link or a local folder. It then downloads the "catalog" (list of available plugins) and saves this source so it remembers it next time you restart.
When you run claude plugin install <name>, the CLI doesn't just blindly download files. It performs a safety check called Validation.
Plugins are defined by a manifest (usually a JSON file) that describes what the plugin does.
The pluginInstallHandler coordinates this process.
// handlers/plugins.ts (Simplified)
export async function pluginInstallHandler(plugin: string, options: any) {
// 1. Determine where to install (User vs Project scope)
const scope = options.scope || 'user';
// 2. Log analytics (tracking popularity of plugins)
logEvent('tengu_plugin_install_command', {
scope: scope
});
// 3. Trigger the heavy lifting
await installPlugin(plugin, scope);
}
Explanation: The handler is lightweight. It checks your preferences (Scope) and then delegates the complex work to installPlugin. This keeps the command-line interface responsive and clean.
Not all plugins should be available everywhere.
This logic is enforced during commands like enable, disable, and install.
// handlers/plugins.ts (Simplified Logic)
export async function pluginDisableHandler(plugin: string, options: any) {
// Check if the user wants to disable EVERYTHING
if (options.all) {
await disableAllPlugins();
return;
}
// Otherwise, disable just the specific plugin
await disablePlugin(plugin, options.scope || 'user');
}
Explanation: The system allows granular control. You can turn off a plugin globally (disableAllPlugins) if you suspect a bug, or just remove it from your current user profile.
How do you know what is installed? The plugin list command merges data from two sources:
This is crucial because a plugin might be installed but crashed.
// handlers/plugins.ts (Simplified)
export async function pluginListHandler(options: any) {
// 1. Get list of what is physically on disk
const installedData = loadInstalledPluginsV2();
// 2. Get list of what is actually running (or failed to load)
const { enabled, errors } = await loadAllPlugins();
// 3. Print the status for each
for (const pluginId of Object.keys(installedData.plugins)) {
console.log(`Plugin: ${pluginId}`);
// Check if it has errors
const hasError = errors.find(e => e.source === pluginId);
console.log(`Status: ${hasError ? 'Failed' : 'Active'}`);
}
}
Explanation: This handler is a "dashboard." It cross-references the list of files on your hard drive with the live status of the application to tell you if your plugins are healthy.
claude marketplace add owner/repoclaude plugin list --availableclaude plugin install weather-tooluser scope.Plugin Management turns the CLI from a simple chat interface into an extensible platform. It handles the logistics of finding, checking, and loading external code safely.
But waitβwhat exactly is the code inside a plugin? How does the plugin define "I can check the weather" in a way the AI understands?
Most plugins in this ecosystem use a standard called MCP (Model Context Protocol).
Generated by Code IQ