using ClaudeDo.Installer.Core;
namespace ClaudeDo.Installer.Checks;
/// Gates the CLI flags ClaudeArgsBuilder relies on โ blocking.
public sealed class ClaudeVersionCheck : IEnvironmentCheck
{
public const string CheckId = "claude-version";
///
/// Newest version confirmed to work end-to-end with every flag ClaudeDo uses (--permission-mode
/// auto, --effort, --agents, --json-schema, --append-system-prompt, --output-format stream-json
/// --verbose, --resume, mcp add --transport http --scope user). A verified floor, not a proven
/// theoretical minimum โ see docs/explore-notes/installer-preflight.md ยง3.
///
public static readonly Version MinimumVersion = new(2, 1, 220);
private readonly ClaudeCliLookup _lookup;
public ClaudeVersionCheck(ClaudeCliLookup lookup)
{
_lookup = lookup;
}
public string Id => CheckId;
public CheckSeverity Severity => CheckSeverity.Error;
public async Task RunAsync(InstallContext ctx, CancellationToken ct)
{
var lookup = await _lookup.ResolveAsync(ctx, ct);
if (lookup.Resolved is null)
{
return CheckResult.Unknown(Id, Severity, "checks.claudeVersion.title",
"The claude CLI was not found โ version could not be checked.");
}
if (lookup.ExitCode != 0 || lookup.ParsedVersion is null)
{
return CheckResult.Unknown(Id, Severity, "checks.claudeVersion.title",
$"Could not parse a version from '{lookup.Output.Trim()}'.");
}
if (lookup.ParsedVersion < MinimumVersion)
{
return CheckResult.Fail(Id, Severity, "checks.claudeVersion.title",
$"claude {lookup.ParsedVersion} is older than the required {MinimumVersion}.",
"checks.claudeVersion.hint");
}
return CheckResult.Ok(Id, Severity, "checks.claudeVersion.title",
$"claude {lookup.ParsedVersion} meets the minimum ({MinimumVersion}).");
}
}