claudex_cli/commands/
prs.rs1use anyhow::Result;
2
3use crate::cli::ResolvedFilter;
4use crate::ui;
5use claudex::index::IndexStore;
6use claudex::providers::enabled_default;
7use claudex::store::short_name;
8
9pub fn run(project: Option<&str>, limit: usize, json: bool, filter: &ResolvedFilter) -> Result<()> {
10 let providers: Vec<_> = enabled_default()?
11 .into_iter()
12 .filter(|p| filter.includes_provider(p.id()))
13 .collect();
14 let mut idx = IndexStore::open()?;
15 idx.ensure_fresh(&providers)?;
16 idx.ensure_pr_links_fresh(&providers)?;
17
18 let rows = idx.query_pr_links(project, filter, limit)?;
19
20 if json {
21 let output: Vec<_> = rows
22 .iter()
23 .map(|r| {
24 serde_json::json!({
25 "provider": r.provider,
26 "project": r.project,
27 "session_id": r.session_id,
28 "pr_number": r.pr_number,
29 "pr_url": r.pr_url,
30 "pr_repository": r.pr_repository,
31 "timestamp": r.timestamp,
32 })
33 })
34 .collect();
35 println!("{}", serde_json::to_string_pretty(&output)?);
36 return Ok(());
37 }
38
39 if rows.is_empty() {
40 println!("No PR links found.");
41 return Ok(());
42 }
43
44 let mut table = ui::table();
45 table.set_header(ui::header(["Project", "PR #", "Repository", "URL"]));
46 ui::right_align(&mut table, &[1]);
47 for r in &rows {
48 let sid: String = r
49 .session_id
50 .as_deref()
51 .unwrap_or("-")
52 .chars()
53 .take(8)
54 .collect();
55 let repo = if r.pr_repository.is_empty() {
56 sid
57 } else {
58 r.pr_repository.clone()
59 };
60 table.add_row([
61 ui::cell_project(&short_name(&r.project)),
62 ui::cell_plain(format!("#{}", ui::fmt_count(r.pr_number as u64))),
63 ui::cell_dim(&repo),
64 ui::cell_plain(r.pr_url.clone()),
65 ]);
66 }
67 println!("{table}");
68 Ok(())
69}