codewiki-cli 0.1.0

CLI for Google Code Wiki — query GitHub repo wikis (structure, full markdown, Q&A) without a browser. Built for LLM coding agents and humans.
mod boq;
mod cli;
mod client;
mod output;
mod spinner;
mod wiki;

use anyhow::Result;
use clap::Parser;
use cli::{Cli, Command};
use client::CodeWikiClient;
use spinner::Spinner;

#[tokio::main]
async fn main() {
    if let Err(e) = run().await {
        eprintln!("Error: {:#}", e);
        std::process::exit(1);
    }
}

async fn run() -> Result<()> {
    let cli = Cli::parse();
    let (repo, query_type) = repo_and_query_type(&cli.command);

    if let Ok(mock_text) = std::env::var("CODEWIKI_MOCK_TEXT") {
        println!(
            "{}",
            output::format_for_claude(&mock_text, repo, query_type)
        );
        return Ok(());
    }

    let spinner = Spinner::start("Bootstrapping Code Wiki...");
    let client = CodeWikiClient::connect().await?;

    spinner.set_message(&command_spinner_message(&cli.command));
    let text = match &cli.command {
        Command::Ask { repo, question } => {
            let raw = client.ask(repo, question).await?;
            wiki::resolve_links(&raw)
        }
        Command::Structure { repo } => {
            let w = client.read_wiki(repo).await?;
            wiki::render_structure(&w)
        }
        Command::Read { repo } => {
            let w = client.read_wiki(repo).await?;
            wiki::render_markdown(&w)
        }
    };
    spinner.finish();

    println!("{}", output::format_for_claude(&text, repo, query_type));
    Ok(())
}

fn command_spinner_message(command: &Command) -> String {
    match command {
        Command::Ask { repo, .. } => format!("Asking Code Wiki about {}...", repo),
        Command::Structure { repo } => format!("Fetching wiki structure for {}...", repo),
        Command::Read { repo } => format!("Reading wiki contents for {}...", repo),
    }
}

fn repo_and_query_type(command: &Command) -> (&str, &str) {
    match command {
        Command::Ask { repo, .. } => (repo, "ask"),
        Command::Structure { repo } => (repo, "structure"),
        Command::Read { repo } => (repo, "read"),
    }
}