opencode-cloud 25.1.3

CLI for managing opencode as a persistent cloud service
Documentation
//! Container-mode status command implementation.

use crate::commands::container::{exec_command_with_status, systemd_available};
use crate::commands::runtime_shared::backend::{ContainerBackend, default_container_port};
use crate::commands::runtime_shared::collect_status_view;
use crate::commands::runtime_shared::status_model::{
    OpencodeHealthStatus, format_broker_health_label,
};
use crate::output::{format_service_url, state_style};
use anyhow::Result;
use console::style;
use opencode_cloud_core::docker::get_cli_version;

const STATUS_LABEL_WIDTH: usize = 15;

pub async fn cmd_status_container(
    _args: &crate::commands::StatusArgs,
    quiet: bool,
    _verbose: u8,
) -> Result<()> {
    let systemd = systemd_available();

    let opencode_running = if systemd {
        systemd_service_active("opencode.service").await?
    } else {
        process_running("pgrep", &["-f", "/opt/opencode/bin/opencode"]).await?
    };

    if quiet {
        if opencode_running {
            std::process::exit(0);
        } else {
            std::process::exit(1);
        }
    }

    let backend = ContainerBackend::new(systemd);
    let host_port = default_container_port();
    let status_view =
        collect_status_view(&backend, opencode_running, "127.0.0.1", host_port).await?;

    let state_label = if opencode_running {
        match status_view.opencode_health {
            Some(OpencodeHealthStatus::Healthy) | None => "running".to_string(),
            Some(OpencodeHealthStatus::Starting) => "starting".to_string(),
            Some(OpencodeHealthStatus::Unhealthy(_)) => "unhealthy".to_string(),
            Some(OpencodeHealthStatus::CheckFailed) => "unknown".to_string(),
        }
    } else {
        "stopped".to_string()
    };

    println!("{}", format_kv("State:", state_style(&state_label)));
    println!(
        "{}",
        format_kv(
            "URL:",
            style(format_service_url(None, "127.0.0.1", host_port)).cyan()
        )
    );

    let opencode_display =
        format_opencode_display(&status_view.opencode_version, &status_view.opencode_commit);
    println!("{}", format_kv("Opencode:", opencode_display));

    println!(
        "{}",
        format_kv(
            "Broker:",
            format_broker_health_label(status_view.broker_health)
        )
    );

    let runtime = if status_view
        .capabilities
        .systemd_available
        .unwrap_or(systemd)
    {
        "systemd"
    } else {
        "tini"
    };
    println!("{}", format_kv("Runtime:", runtime));
    println!("{}", format_kv("Image:", &status_view.image_version));

    let cli_version = get_cli_version();
    println!("{}", format_kv("CLI:", format!("v{cli_version}")));

    Ok(())
}

async fn systemd_service_active(service: &str) -> Result<bool> {
    let (_output, status) = exec_command_with_status("systemctl", &["is-active", service]).await?;
    Ok(status == 0)
}

async fn process_running(cmd: &str, args: &[&str]) -> Result<bool> {
    let (_output, status) = exec_command_with_status(cmd, args).await?;
    Ok(status == 0)
}

fn format_opencode_display(version: &str, commit: &str) -> String {
    match (version, commit) {
        ("unknown", "unknown") => "unknown".to_string(),
        ("unknown", commit) => format!("unknown ({commit})"),
        (version, "unknown") => version.to_string(),
        (version, commit) => format!("{version} ({commit})"),
    }
}

fn format_kv(label: &str, value: impl std::fmt::Display) -> String {
    format!("{label:<STATUS_LABEL_WIDTH$} {value}")
}