claude_code_toolkit/cli/commands/
org.rs

1use crate::{ config::manager::ConfigurationManager, error::*, providers::github::GitHubManager };
2use console::{ Emoji, style };
3
4static SUCCESS: Emoji<'_, '_> = Emoji("✅ ", "");
5#[allow(dead_code)]
6static WARNING: Emoji<'_, '_> = Emoji("⚠️ ", "");
7static INFO: Emoji<'_, '_> = Emoji("ℹ️ ", "");
8
9pub async fn handle_add_org(name: String) -> Result<()> {
10  println!("{}Adding organization {} for Claude secret sync", INFO, style(&name).bold());
11
12  // Verify GitHub access
13  let github_manager = GitHubManager::new();
14
15  if !github_manager.check_gh_cli().await? {
16    eprintln!("{}", style("GitHub CLI (gh) is not installed. Please install it first.").red());
17    std::process::exit(1);
18  }
19
20  if !github_manager.check_authentication().await? {
21    eprintln!(
22      "{}",
23      style("GitHub CLI is not authenticated. Please run 'gh auth login' first.").red()
24    );
25    std::process::exit(1);
26  }
27
28  // Add to config
29  let config_manager = ConfigurationManager::new()?;
30  config_manager.add_organization(name.clone()).await?;
31
32  println!("{}Successfully added organization {}", SUCCESS, style(&name).bold());
33  // Show which secrets will be synced from config
34  let config = config_manager.load_config().await?;
35  let secret_names: Vec<String> = config.credentials.field_mappings.values().cloned().collect();
36  println!("{}", style(format!("Will sync: {}", secret_names.join(", "))).dim());
37  println!("{}", style("Run 'claude-code sync now' to sync immediately").dim());
38
39  Ok(())
40}
41
42pub async fn handle_remove_org(name: String) -> Result<()> {
43  println!("{}Removing organization {}", INFO, style(&name).bold());
44
45  let config_manager = ConfigurationManager::new()?;
46  config_manager.remove_organization(&name).await?;
47
48  println!("{}Successfully removed organization {}", SUCCESS, style(&name).bold());
49
50  Ok(())
51}
52
53pub async fn handle_list_orgs() -> Result<()> {
54  let config_manager = ConfigurationManager::new()?;
55  let config = config_manager.load_config().await?;
56
57  if config.github.organizations.is_empty() {
58    println!("{}", style("No organizations configured").yellow());
59    println!("{}", style("Use 'claude-code org add <name>' to add an organization").dim());
60    return Ok(());
61  }
62
63  println!("{}", style("Configured Organizations:").bold());
64  println!();
65
66  for org in &config.github.organizations {
67    println!("  {}", style(&org.name).cyan());
68    let secret_names: Vec<String> = config.credentials.field_mappings.values().cloned().collect();
69    println!("    Secrets: {}", style(secret_names.join(", ")).dim());
70  }
71
72  println!();
73
74  // Show available organizations from GitHub
75  println!("{}", style("Available Organizations from GitHub:").bold());
76  println!();
77
78  let github_manager = GitHubManager::new();
79
80  match github_manager.list_organizations().await {
81    Ok(available_orgs) => {
82      if available_orgs.is_empty() {
83        println!("  {}", style("No organizations found").dim());
84      } else {
85        for org in available_orgs {
86          let is_configured = config.github.organizations.iter().any(|o| o.name == org);
87          if is_configured {
88            println!("  {} {}", style("✓").green(), org);
89          } else {
90            println!("  {} {}", style("○").dim(), org);
91          }
92        }
93      }
94    }
95    Err(e) => {
96      println!("  {}", style(format!("Error fetching organizations: {}", e)).red());
97    }
98  }
99
100  Ok(())
101}