@@ -261,31 +261,40 @@ fn parse_mcp_list(output: &str) -> Vec<McpServer> {
261261/// Parse `claude plugin list` output to extract skill-based slash commands.
262262fn parse_plugin_skills ( output : & str ) -> Vec < SlashCommand > {
263263 let mut commands = Vec :: new ( ) ;
264+ let mut current_name = String :: new ( ) ;
265+ let mut current_enabled = true ;
264266
265267 for line in output. lines ( ) {
266- let line = line. trim ( ) ;
267- // Look for lines like "- skill-name@marketplace (enabled)"
268- if line. starts_with ( '-' ) || line. starts_with ( '•' ) {
269- let clean = line. trim_start_matches ( [ '-' , '•' , ' ' ] . as_ref ( ) ) . trim ( ) ;
270- if let Some ( ( name_part, _) ) = clean. split_once ( '@' ) {
271- let name = name_part. trim ( ) ;
268+ let trimmed = line. trim ( ) ;
269+
270+ // Entry header: "❯ name@source"
271+ if trimmed. starts_with ( '❯' ) || trimmed. starts_with ( '>' ) {
272+ // Save previous
273+ if !current_name. is_empty ( ) && current_enabled {
274+ // Extract skill name (before @)
275+ let skill_name = current_name. split ( '@' ) . next ( ) . unwrap_or ( & current_name) ;
272276 commands. push ( SlashCommand {
273- name : format ! ( "/{name }" ) ,
274- description : format ! ( "Plugin skill : {name}" ) ,
277+ name : format ! ( "/{skill_name }" ) ,
278+ description : format ! ( "Plugin: {}" , current_name ) ,
275279 source : "plugin" . to_string ( ) ,
276280 } ) ;
277- } else if let Some ( ( name_part, _) ) = clean. split_once ( ' ' ) {
278- let name = name_part. trim ( ) ;
279- if !name. is_empty ( ) {
280- commands. push ( SlashCommand {
281- name : format ! ( "/{name}" ) ,
282- description : "Plugin skill" . to_string ( ) ,
283- source : "plugin" . to_string ( ) ,
284- } ) ;
285- }
286281 }
282+ current_name = trimmed. trim_start_matches ( '❯' ) . trim_start_matches ( '>' ) . trim ( ) . to_string ( ) ;
283+ current_enabled = true ;
284+ } else if trimmed. starts_with ( "Status:" ) {
285+ current_enabled = trimmed. contains ( "enabled" ) || trimmed. contains ( "✔" ) ;
287286 }
288287 }
289288
289+ // Last entry
290+ if !current_name. is_empty ( ) && current_enabled {
291+ let skill_name = current_name. split ( '@' ) . next ( ) . unwrap_or ( & current_name) ;
292+ commands. push ( SlashCommand {
293+ name : format ! ( "/{skill_name}" ) ,
294+ description : format ! ( "Plugin: {}" , current_name) ,
295+ source : "plugin" . to_string ( ) ,
296+ } ) ;
297+ }
298+
290299 commands
291300}
0 commit comments