feat(cli): add plugin reload command

This commit is contained in:
Casey Chow
2026-05-19 12:53:21 -04:00
parent c280fcc7ed
commit 7f078f3a84
9 changed files with 131 additions and 2 deletions
+21
View File
@@ -957,6 +957,12 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
prepend_config_flags(&mut marketplace_cli.config_overrides, config_overrides);
marketplace_cli.run().await?;
}
PluginSubcommand::Reload(args) => {
let overrides = config_overrides
.parse_overrides()
.map_err(anyhow::Error::msg)?;
plugin_cmd::run_plugin_reload(overrides, args).await?;
}
PluginSubcommand::Remove(args) => {
let overrides = config_overrides
.parse_overrides()
@@ -2540,6 +2546,21 @@ mod tests {
assert!(matches!(cli.subcommand, Some(Subcommand::Plugin(_))));
}
#[test]
fn plugin_reload_parses_under_plugin() {
let cli = MultitoolCli::try_parse_from(["codex", "plugin", "reload"]).expect("parse");
assert!(matches!(cli.subcommand, Some(Subcommand::Plugin(_))));
}
#[test]
fn plugins_still_parses_as_prompt_text() {
let cli = MultitoolCli::try_parse_from(["codex", "plugins"]).expect("parse");
assert!(cli.subcommand.is_none());
assert_eq!(cli.interactive.prompt.as_deref(), Some("plugins"));
}
#[test]
fn update_parses_as_update_subcommand() {
let cli = MultitoolCli::try_parse_from(["codex", "update"]).expect("parse");
+34 -1
View File
@@ -1,6 +1,5 @@
use anyhow::Context;
use anyhow::Result;
use anyhow::bail;
use clap::Parser;
use codex_core::config::Config;
use codex_core::config::find_codex_home;
@@ -12,6 +11,7 @@ use codex_core_plugins::installed_marketplaces::marketplace_install_root;
use codex_core_plugins::installed_marketplaces::resolve_configured_marketplace_root;
use codex_core_plugins::marketplace::MarketplaceListError;
use codex_core_plugins::marketplace::find_marketplace_manifest_path;
use codex_core_skills::SkillsManager;
use codex_plugin::PluginId;
use codex_plugin::validate_plugin_segment;
use codex_utils_cli::CliConfigOverrides;
@@ -43,6 +43,9 @@ pub enum PluginSubcommand {
/// Add, list, upgrade, or remove configured plugin marketplaces.
Marketplace(MarketplaceCli),
/// Reload Codex's local installed-plugin state from disk/cache and refresh plugin-backed runtime state.
Reload(ReloadPluginsArgs),
/// Remove an installed plugin from local config and cache.
///
/// Pass either `PLUGIN@MARKETPLACE` or pass `PLUGIN` with
@@ -91,6 +94,14 @@ pub struct RemovePluginArgs {
marketplace_name: Option<String>,
}
#[derive(Debug, Parser)]
#[command(
bin_name = "codex plugin reload",
about = "Reload Codex's local installed-plugin state from marketplaces",
after_help = "What this does:\n Clears Codex's local plugin and skill caches so the next local load re-scans installed plugin state from disk/cache.\n\nWhat happens next:\n Updated plugin context is picked up in new CLI sessions and other fresh loads.\n Existing app-server-backed threads are not refreshed.\n Plugin instructions and skills already loaded into an existing thread are not reread."
)]
pub struct ReloadPluginsArgs;
pub async fn run_plugin_add(
overrides: Vec<(String, toml::Value)>,
args: AddPluginArgs,
@@ -203,6 +214,28 @@ pub async fn run_plugin_remove(
Ok(())
}
pub async fn run_plugin_reload(
overrides: Vec<(String, toml::Value)>,
_: ReloadPluginsArgs,
) -> Result<()> {
let config = Config::load_with_cli_overrides(overrides)
.await
.context("failed to load configuration")?;
let codex_home = find_codex_home().context("failed to resolve CODEX_HOME")?;
let plugins_manager = PluginsManager::new(codex_home.to_path_buf());
let skills_manager = SkillsManager::new(codex_home, config.bundled_skills_enabled());
plugins_manager.clear_cache();
skills_manager.clear_cache();
println!("Cleared Codex's local plugin and skill caches.");
println!("Updated plugin context will be picked up in new CLI sessions and other fresh loads.");
println!("Existing app-server-backed threads are not refreshed.");
println!("Plugin instructions and skills already loaded into an existing thread stay as-is.");
Ok(())
}
struct PluginCommandContext {
codex_home: PathBuf,
plugins_input: PluginsConfigInput,