claude-code-status-line 1.3.1

A configurable status line for Claude Code with powerline arrows, context tracking, and quota monitoring
Documentation
use std::io::{self, Read};

use claude_code_status_line::app::{parse_claude_input, render_statusline_with_width};
use claude_code_status_line::commands::{self, InstallOutcome};
use claude_code_status_line::config::load_config;
use claude_code_status_line::setup;
use claude_code_status_line::utils::{get_claude_config_dir, get_terminal_width};

fn main() {
    const VERSION: &str = env!("CARGO_PKG_VERSION");
    const PKG_NAME: &str = env!("CARGO_PKG_NAME");

    if std::env::args().any(|a| a == "--version" || a == "-V") {
        println!("{} {}", PKG_NAME, VERSION);
        return;
    }

    if std::env::args().any(|a| a == "--help" || a == "-h") {
        println!(
            "{} {} - Beautiful statusline for Claude Code",
            PKG_NAME, VERSION
        );
        println!("\nUsage:");
        println!(
            "  Receives JSON on stdin from Claude Code, outputs formatted statusline to stdout"
        );
        println!("\nCommands:");
        println!("  setup [--yes]        Install this binary to ~/.claude/statusline/bin/,");
        println!("                       install the slash commands and point Claude Code's");
        println!("                       statusLine at it (--yes: don't ask before editing");
        println!("                       Claude Code's settings.json)");
        println!("\nOptions:");
        println!("  --version, -V        Show version");
        println!(
            "  --install-commands   Install/update slash commands in ~/.claude/commands/ (honours CLAUDE_CONFIG_DIR)"
        );
        println!("  --help, -h           Show this help");
        println!("\nConfiguration:");
        println!("  ~/.claude/statusline/settings.json   - Statusline settings");
        println!("  ~/.claude/statusline/colors.json     - Color customization");
        println!("\nSlash Commands:");
        println!("  /install-statusline     - Interactive installation wizard");
        println!("  /update-statusline      - Update to latest version");
        println!("  /customize-statusline   - Interactive configuration wizard");
        println!("  /uninstall-statusline   - Remove the statusline");
        println!("\nDocumentation:");
        println!("  https://www.npmjs.com/package/@ndave92/claude-code-status-line");
        println!("  https://crates.io/crates/claude-code-status-line");
        println!("  https://ndave92.github.io/claude-code-status-line/");
        return;
    }

    if std::env::args().nth(1).as_deref() == Some("setup") {
        let yes = std::env::args().skip(2).any(|a| a == "--yes" || a == "-y");
        std::process::exit(setup::run(yes));
    }

    if std::env::args().any(|a| a == "--install-commands") {
        std::process::exit(install_commands());
    }

    let config = load_config();

    let mut input_str = String::new();
    if io::stdin().read_to_string(&mut input_str).is_err() {
        eprintln!("statusline error: failed to read stdin");
        println!();
        return;
    }

    let input = match parse_claude_input(&input_str) {
        Ok(input) => input,
        Err(_) => {
            eprintln!("statusline error: invalid JSON");
            println!();
            return;
        }
    };

    let term_width = get_terminal_width(&config);

    if std::env::var("STATUSLINE_DEBUG").is_ok() {
        eprintln!("Debug: term_width detected as {}", term_width);
    }

    let lines = render_statusline_with_width(&input, &config, term_width);

    for line in lines {
        println!("{}", line);
    }
}

fn install_commands() -> i32 {
    // Claude Code reads commands from CLAUDE_CONFIG_DIR when it is set.
    let Some(config_dir) = get_claude_config_dir() else {
        eprintln!("error: could not determine home directory");
        return 1;
    };
    let dir = config_dir.join("commands");

    match commands::install_commands(&dir) {
        Ok(results) => {
            for (name, outcome) in results {
                match outcome {
                    InstallOutcome::Installed => println!("installed  {}", name),
                    InstallOutcome::UpToDate => println!("up to date {}", name),
                    InstallOutcome::Updated { backup } => {
                        println!(
                            "updated    {} (previous saved to {})",
                            name,
                            backup.display()
                        )
                    }
                }
            }
            println!("Commands directory: {}", dir.display());
            0
        }
        Err(err) => {
            eprintln!(
                "error: failed to install commands into {}: {}",
                dir.display(),
                err
            );
            1
        }
    }
}