1use clap::Args;
4use std::path::PathBuf;
5
6use skm_core::SkillRegistry;
7
8#[derive(Args)]
9pub struct ListArgs {
10 #[arg(default_value = ".")]
12 paths: Vec<PathBuf>,
13
14 #[arg(short, long, default_value = "text")]
16 format: String,
17
18 #[arg(long)]
20 triggers: bool,
21
22 #[arg(long)]
24 tags: bool,
25
26 #[arg(long)]
28 tokens: bool,
29}
30
31pub async fn list(args: ListArgs) -> anyhow::Result<()> {
32 let registry = SkillRegistry::new(&args.paths).await?;
33 let catalog = registry.catalog().await;
34
35 match args.format.as_str() {
36 "json" => {
37 let skills: Vec<serde_json::Value> = catalog
38 .iter()
39 .map(|s| {
40 serde_json::json!({
41 "name": s.name.as_str(),
42 "description": s.description,
43 "triggers": s.triggers,
44 "tags": s.tags,
45 "estimated_tokens": s.estimated_tokens,
46 "source": s.source_path.display().to_string()
47 })
48 })
49 .collect();
50 println!("{}", serde_json::to_string_pretty(&skills)?);
51 }
52 "csv" => {
53 println!("name,description,triggers,tags,tokens");
54 for s in &catalog {
55 println!(
56 "{},{:?},{:?},{:?},{}",
57 s.name,
58 s.description,
59 s.triggers.join(";"),
60 s.tags.join(";"),
61 s.estimated_tokens
62 );
63 }
64 }
65 _ => {
66 println!("Found {} skills:\n", catalog.len());
67
68 for s in &catalog {
69 println!(" {} - {}", s.name, s.description);
70
71 if args.triggers && !s.triggers.is_empty() {
72 println!(" triggers: {}", s.triggers.join(", "));
73 }
74
75 if args.tags && !s.tags.is_empty() {
76 println!(" tags: {}", s.tags.join(", "));
77 }
78
79 if args.tokens {
80 println!(" tokens: ~{}", s.estimated_tokens);
81 }
82 }
83 }
84 }
85
86 Ok(())
87}