Skip to main content

xchecker_runner/claude/
version.rs

1use std::process::Stdio;
2
3use crate::error::RunnerError;
4use crate::types::RunnerMode;
5
6use super::exec::Runner;
7
8impl Runner {
9    /// Get the Claude CLI version synchronously, respecting runner mode
10    ///
11    /// This method is used during initialization to capture the Claude CLI version
12    /// without requiring an async runtime. It correctly routes through WSL when
13    /// the runner is configured for WSL mode.
14    ///
15    /// # Returns
16    ///
17    /// * `Ok(String)` - The version string (e.g., "0.8.1")
18    /// * `Err(RunnerError)` - Failed to execute or parse version
19    pub fn get_claude_version_sync(&self) -> Result<String, RunnerError> {
20        // Resolve Auto mode to actual mode
21        let actual_mode = match self.mode {
22            RunnerMode::Auto => Self::detect_auto()?,
23            mode => mode,
24        };
25
26        let output = match actual_mode {
27            RunnerMode::Native => self
28                .native_command_spec(&["--version".to_string()])
29                .to_command()
30                .stdout(Stdio::piped())
31                .stderr(Stdio::piped())
32                .output()
33                .map_err(|e| RunnerError::NativeExecutionFailed {
34                    reason: format!("Failed to execute 'claude --version': {e}"),
35                })?,
36            RunnerMode::Wsl => self
37                .wsl_command_spec(&["--version".to_string()])
38                .to_command()
39                .stdout(Stdio::piped())
40                .stderr(Stdio::piped())
41                .output()
42                .map_err(|e| RunnerError::WslExecutionFailed {
43                    reason: format!("Failed to execute WSL 'claude --version': {e}"),
44                })?,
45            RunnerMode::Auto => unreachable!("Auto mode resolved above"),
46        };
47
48        if !output.status.success() {
49            let reason = format!(
50                "'claude --version' failed with exit code: {}",
51                output.status.code().unwrap_or(-1)
52            );
53            return match actual_mode {
54                RunnerMode::Native => Err(RunnerError::NativeExecutionFailed { reason }),
55                RunnerMode::Wsl => Err(RunnerError::WslExecutionFailed { reason }),
56                RunnerMode::Auto => unreachable!("Auto mode resolved above"),
57            };
58        }
59
60        let stdout = String::from_utf8_lossy(&output.stdout);
61
62        // Extract version from output like "claude 0.8.1"
63        let version = stdout
64            .split_whitespace()
65            .last()
66            .unwrap_or("unknown")
67            .to_string();
68
69        Ok(version)
70    }
71}