Skip to main content

hh_cli/cli/
mod.rs

1pub mod agent_init;
2pub mod chat;
3pub mod commands;
4pub mod render;
5pub mod tui;
6
7use crate::cli::commands::{Cli, Commands, ConfigCommand};
8use crate::cli::render::LiveRender;
9use crate::config::{load_settings, write_default_project_config};
10use clap::Parser;
11
12pub async fn run() -> anyhow::Result<()> {
13    let cli = Cli::parse();
14    let cwd = std::env::current_dir()?;
15
16    match cli.command.unwrap_or(Commands::Chat {
17        max_turns: None,
18        agent: None,
19    }) {
20        Commands::Chat { max_turns, agent } => {
21            let settings = load_settings(&cwd, agent)?;
22            let settings = apply_max_turns(settings, max_turns);
23            chat::run_chat(settings, &cwd).await
24        }
25        Commands::Run {
26            prompt,
27            max_turns,
28            agent,
29        } => {
30            let settings = load_settings(&cwd, agent)?;
31            let settings = apply_max_turns(settings, max_turns);
32            let render = LiveRender::new();
33            render.begin_turn();
34            chat::run_single_prompt_with_events(settings, &cwd, prompt, render).await?;
35            Ok(())
36        }
37        Commands::Tools => {
38            let settings = load_settings(&cwd, None)?;
39            let registry = crate::tool::registry::ToolRegistry::new(&settings, &cwd);
40            for name in registry.names() {
41                println!("{}", name);
42            }
43            Ok(())
44        }
45        Commands::Config { command } => match command {
46            ConfigCommand::Init => {
47                let path = write_default_project_config(&cwd)?;
48                println!("wrote {}", path.display());
49                Ok(())
50            }
51            ConfigCommand::Show => {
52                let settings = load_settings(&cwd, None)?;
53                let txt = serde_json::to_string_pretty(&settings)?;
54                println!("{}", txt);
55                Ok(())
56            }
57        },
58        Commands::Agents => {
59            let loader = crate::agent::AgentLoader::new()?;
60            let agents = loader.load_agents()?;
61            let registry = crate::agent::AgentRegistry::new(agents);
62
63            println!("Available agents:");
64            for agent in registry.list_agents() {
65                let mode = if agent.mode == crate::agent::AgentMode::Primary {
66                    "primary"
67                } else {
68                    "subagent"
69                };
70                println!(
71                    "  {} ({}) - {} - {}",
72                    agent.name, agent.display_name, mode, agent.description
73                );
74            }
75            Ok(())
76        }
77    }
78}
79
80fn apply_max_turns(
81    mut settings: crate::config::Settings,
82    max_turns: Option<usize>,
83) -> crate::config::Settings {
84    if let Some(max_turns) = max_turns {
85        settings.agent.max_steps = max_turns;
86    }
87    settings
88}