From fe2b13a46a077cde32027b75fe3f508651efe22c Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 26 May 2026 07:03:14 +0900 Subject: [PATCH] fix(#719): plugins list now applies substring filter on plugin id, matching agents/skills parity --- ROADMAP.md | 2 ++ rust/crates/commands/src/lib.rs | 11 ++++++++++- rust/crates/rusty-claude-cli/src/main.rs | 21 ++++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index fafa2200..84a390c0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -7603,3 +7603,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed) 717. **`claw agents show ` missing — `handle_agents_slash_command_json` only accepted `list`; `show/info/describe` was unimplemented unlike skills which had parity** — dogfooded 2026-05-26 on `6a007344`. `claw agents show claw-code --output-format json` returned `unknown_agents_subcommand` error. Fix: added `show/info/describe` and `list ` arms to both `handle_agents_slash_command` and `handle_agents_slash_command_json`, mirroring the skills handler; renamed `render_agents_report_json` → `render_agents_report_json_with_action`; not-found path returns `{kind:"agents", action:"show", status:"error", error_kind:"agent_not_found", requested:""}` + Ok; added `classify_error_kind` branch for `agent_not_found`. Updated 2 tests. Source: Jobdori dogfood on `6a007344`, 2026-05-26. 718. **`claw plugins show ` unimplemented — unlike `agents show` and `skills show`, `/plugins show` returned `unknown_plugins_action` error** — dogfooded 2026-05-26 on `8d80f2ff`. Fix: added `show/info/describe` arm to `handle_plugins_slash_command` that filters installed plugins by name; `print_plugins` JSON path filters `payload.plugins` when action is `show/info/describe` and emits `{kind:"plugin", action:"show", status:"error", error_kind:"plugin_not_found", requested:""}` for missing names. Updated error message in catch-all to name `show` as supported. Source: Jobdori dogfood on `8d80f2ff`, 2026-05-26. + +719. **`plugins list ` silently returned all plugins instead of filtering — unlike `agents list ` and `skills list ` which do substring filter** — dogfooded 2026-05-26 on `556a598f`. `claw plugins list nonexistent-filter-xyz --output-format json` returned both installed plugins. Fix: `handle_plugins_slash_command` `list` arm now treats `target` as a substring filter; `print_plugins` JSON path applies `target` filter for `list` action. Source: Jobdori dogfood on `556a598f`, 2026-05-26. diff --git a/rust/crates/commands/src/lib.rs b/rust/crates/commands/src/lib.rs index 476ac569..22b5e555 100644 --- a/rust/crates/commands/src/lib.rs +++ b/rust/crates/commands/src/lib.rs @@ -2202,7 +2202,16 @@ pub fn handle_plugins_slash_command( match action { None | Some("list") => { let report = manager.installed_plugin_registry_report()?; - let plugins = report.summaries(); + let plugins: Vec<_> = if let Some(filter) = target { + let needle = filter.to_lowercase(); + report + .summaries() + .into_iter() + .filter(|p| p.metadata.id.to_lowercase().contains(&needle)) + .collect() + } else { + report.summaries().into_iter().collect() + }; let failures = report.failures(); Ok(PluginsCommandResult { message: render_plugins_report_with_failures(&plugins, failures), diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index 7c577fc8..af4209d5 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -5999,8 +5999,10 @@ impl LiveCli { CliOutputFormat::Text => println!("{}", payload.message), CliOutputFormat::Json => { let action_str = action.unwrap_or("list"); - // For show/info/describe, filter to the named plugin. + // For show/info/describe, filter to the named plugin (exact match). + // For list with a target, treat target as a substring filter. let is_show_action = matches!(action_str, "show" | "info" | "describe"); + let is_list_action = action_str == "list"; let filtered_plugins: Vec<_> = if is_show_action { if let Some(name) = target { let needle = name.to_lowercase(); @@ -6018,6 +6020,23 @@ impl LiveCli { } else { payload.plugins.clone() } + } else if is_list_action { + if let Some(filter) = target { + let needle = filter.to_lowercase(); + payload + .plugins + .iter() + .filter(|p| { + p.get("id") + .and_then(|v| v.as_str()) + .map(|id| id.to_lowercase().contains(&needle)) + .unwrap_or(false) + }) + .cloned() + .collect() + } else { + payload.plugins.clone() + } } else { payload.plugins.clone() };