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})."); } }