Skip to main content

systemprompt_cli/commands/plugins/
mod.rs

1//! `plugins` command group: discover and inspect compiled extensions.
2//!
3//! Covers listing and showing extensions, running CLI extension commands,
4//! validating dependencies and configuration, dumping config, summarising
5//! [`PluginsCommands::Capabilities`], and the [`mcp`] server-management
6//! subtree. [`types`] holds the shared serialisable output shapes.
7
8pub mod types;
9
10mod capabilities;
11mod config;
12mod list;
13mod run;
14mod show;
15mod validate;
16
17pub mod mcp;
18
19use anyhow::{Context, Result};
20use clap::Subcommand;
21use systemprompt_extension::ExtensionRegistry;
22
23use crate::CliConfig;
24use crate::descriptor::{CommandDescriptor, DescribeCommand};
25use crate::shared::render_result;
26
27fn discover_registry() -> ExtensionRegistry {
28    ExtensionRegistry::discover().unwrap_or_else(|e| {
29        tracing::error!(error = %e, "extension dependency cycle; using empty registry");
30        ExtensionRegistry::new()
31    })
32}
33
34#[derive(Debug, Subcommand)]
35pub enum PluginsCommands {
36    #[command(about = "List all discovered extensions")]
37    List(list::ListArgs),
38
39    #[command(about = "Show detailed extension information")]
40    Show(show::ShowArgs),
41
42    #[command(about = "Run a CLI extension command", trailing_var_arg = true)]
43    Run(run::RunArgs),
44
45    #[command(about = "Validate extension dependencies and configurations")]
46    Validate(validate::ValidateArgs),
47
48    #[command(about = "Show extension configuration")]
49    Config(config::ConfigArgs),
50
51    #[command(about = "List capabilities across all extensions")]
52    Capabilities(capabilities::CapabilitiesArgs),
53
54    #[command(subcommand, about = "MCP server management")]
55    Mcp(mcp::McpCommands),
56}
57
58impl DescribeCommand for PluginsCommands {
59    fn descriptor(&self) -> CommandDescriptor {
60        match self {
61            Self::Run(_) => CommandDescriptor::PROFILE_ONLY,
62            Self::Mcp(_) => CommandDescriptor::FULL,
63            _ => CommandDescriptor::PROFILE_ONLY.with_remote_eligible(),
64        }
65    }
66}
67
68pub async fn execute(cmd: PluginsCommands, config: &CliConfig) -> Result<()> {
69    match cmd {
70        PluginsCommands::List(args) => {
71            render_result(&list::execute(&args, config));
72            Ok(())
73        },
74        PluginsCommands::Show(args) => {
75            let result = show::execute(&args, config).context("Failed to show extension")?;
76            render_result(&result);
77            Ok(())
78        },
79        PluginsCommands::Run(args) => run::execute(args, config).await,
80        PluginsCommands::Validate(args) => {
81            render_result(&validate::execute(&args, config));
82            Ok(())
83        },
84        PluginsCommands::Config(args) => {
85            let result =
86                config::execute(&args, config).context("Failed to get extension config")?;
87            render_result(&result);
88            Ok(())
89        },
90        PluginsCommands::Capabilities(args) => {
91            capabilities::execute(args, config);
92            Ok(())
93        },
94        PluginsCommands::Mcp(cmd) => mcp::execute_with_config(cmd, config).await,
95    }
96}