From 347128de9f1358b6183576c87718414d81baca51 Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 14:05:59 +0200 Subject: [PATCH 01/10] #1866: Add ClaudeUrlUpdater for Claude Code CLI --- .../ide/url/tool/claude/ClaudeUrlUpdater.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java new file mode 100644 index 0000000000..83a31d966c --- /dev/null +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java @@ -0,0 +1,58 @@ +package com.devonfw.tools.ide.url.tool.claude; + +import com.devonfw.tools.ide.url.model.folder.UrlVersion; +import com.devonfw.tools.ide.url.updater.GithubUrlTagUpdater; +import com.devonfw.tools.ide.version.VersionIdentifier; + +/** + * {@link GithubUrlTagUpdater} for GitHub Claude Code CLI. + *

+ * Follows the official installation structure from GitHub's claude-code repository: https://github.com/anthropics/claude-code. Download URL pattern: + * Download URL pattern: https://github.com/anthropics/claude-code/releases/download/v${VERSION}/claude-${PLATFORM}-${ARCH}.tar.gz + */ +public class ClaudeUrlUpdater extends GithubUrlTagUpdater { + + private static final VersionIdentifier MIN_CLAUDE_VID = VersionIdentifier.of("2.0.73"); + + + @Override + public String getTool() { + return "claude"; + } + + @Override + protected String getGithubOrganization() { + return "anthropics"; + } + + @Override + protected String getGithubRepository() { + return "claude-code"; + } + + @Override + protected void addVersion(UrlVersion urlVersion) { + String baseUrl = createGithubReleaseDownloadUrl("v${version}", "claude-"); + VersionIdentifier vid = urlVersion.getVersionIdentifier(); + + if (vid.compareVersion(MIN_CLAUDE_VID).isGreater()) { + + doAddVersion(urlVersion, baseUrl + "linux-x64.tar.gz", LINUX, X64); + doAddVersion(urlVersion, baseUrl + "linux-x64-musl.tar.gz", LINUX, X64); + doAddVersion(urlVersion, baseUrl + "linux-arm64.tar.gz", LINUX, ARM64); + doAddVersion(urlVersion, baseUrl + "linux-arm64-musl.tar.gz", LINUX, ARM64); + + doAddVersion(urlVersion, baseUrl + "darwin-x64.tar.gz", MAC, X64); + doAddVersion(urlVersion, baseUrl + "darwin-arm64.tar.gz", MAC, ARM64); + + doAddVersion(urlVersion, baseUrl + "win32-x64.zip", WINDOWS, X64); + doAddVersion(urlVersion, baseUrl + "win32-arm64.zip", WINDOWS, ARM64); + } + } + + @Override + protected String getVersionPrefixToRemove() { + return "v"; + } +} From 455cc804ca83dfb517096a4fae52d29d24f94d38 Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 14:06:47 +0200 Subject: [PATCH 02/10] #1866: Add mock and tests for ClaudeUrlUpdater using WireMock --- .../url/tool/claude/ClaudeUrlUpdaterMock.java | 31 +++++++++++ .../url/tool/claude/ClaudeUrlUpdaterTest.java | 53 +++++++++++++++++++ .../ClaudeUrlUpdater/claude-tags.json | 9 ++++ 3 files changed, 93 insertions(+) create mode 100644 url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterMock.java create mode 100644 url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java create mode 100644 url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json diff --git a/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterMock.java b/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterMock.java new file mode 100644 index 0000000000..7deacb8d50 --- /dev/null +++ b/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterMock.java @@ -0,0 +1,31 @@ +package com.devonfw.tools.ide.url.tool.claude; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; + +/** + * Mock of {@link ClaudeUrlUpdater} to allow integration testing with wiremock. + */ +public class ClaudeUrlUpdaterMock extends ClaudeUrlUpdater { + + private final String baseUrl; + + private final WireMockRuntimeInfo wmRuntimeInfo; + + ClaudeUrlUpdaterMock(WireMockRuntimeInfo wireMockRuntimeInfo) { + super(); + this.wmRuntimeInfo = wireMockRuntimeInfo; + this.baseUrl = wireMockRuntimeInfo.getHttpBaseUrl(); + } + + @Override + protected String getDownloadBaseUrl() { + return this.baseUrl; + } + + @Override + protected String doGetVersionUrl() { + return this.baseUrl + "/repos/" + getGithubOrganization() + "/" + getGithubRepository() + "/git/refs/tags"; + } +} + + diff --git a/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java b/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java new file mode 100644 index 0000000000..88f3ece8f0 --- /dev/null +++ b/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java @@ -0,0 +1,53 @@ +package com.devonfw.tools.ide.url.tool.claude; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.any; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; + +import java.io.IOException; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import com.devonfw.tools.ide.url.model.folder.UrlRepository; +import com.devonfw.tools.ide.url.updater.AbstractUrlUpdaterTest; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; + +/** + * Test of {@link ClaudeUrlUpdater}. + */ +@WireMockTest +class ClaudeUrlUpdaterTest extends AbstractUrlUpdaterTest { + + /** + * Test of {@link ClaudeUrlUpdater} for the creation of download URLs and checksums. + * + * @param tempDir Path to a temporary directory + * @param wmRuntimeInfo the {@link WireMockRuntimeInfo}. + * @throws IOException test fails + */ + @Test + void testClaudeUrlUpdater(@TempDir Path tempDir, WireMockRuntimeInfo wmRuntimeInfo) throws IOException { + // arrange + stubFor(get(urlMatching("/repos/anthropics/claude-code/git/refs/tags")).willReturn(aResponse().withStatus(200) + .withBody(readAndResolve(PATH_INTEGRATION_TEST.resolve("ClaudeUrlUpdater").resolve("claude-tags.json"), wmRuntimeInfo)))); + + stubFor(any(urlMatching("/anthropics/claude-code/releases/download/.*")).willReturn(aResponse().withStatus(200).withBody(DOWNLOAD_CONTENT))); + + UrlRepository urlRepository = UrlRepository.load(tempDir); + ClaudeUrlUpdaterMock updater = new ClaudeUrlUpdaterMock(wmRuntimeInfo); + + // act + updater.update(urlRepository); + + // assert + Path claudeDir = tempDir.resolve("claude").resolve("claude"); + assertUrlVersionOsX64(claudeDir.resolve("2.1.110")); + } +} + + diff --git a/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json b/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json new file mode 100644 index 0000000000..469d103008 --- /dev/null +++ b/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json @@ -0,0 +1,9 @@ +[ + { + "ref": "refs/tags/v2.1.110" + }, + { + "ref": "refs/tags/v2.1.110-rc1" + } +] + From 2f442066635c871074efe3b1de7b2b42530ce84a Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 14:07:00 +0200 Subject: [PATCH 03/10] #1866: Add ClaudeUrlUpdater to UpdateManager # Conflicts: # url-updater/src/main/java/com/devonfw/tools/ide/url/updater/UpdateManager.java --- .../java/com/devonfw/tools/ide/url/updater/UpdateManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/updater/UpdateManager.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/updater/UpdateManager.java index fcadcb2121..067098b97f 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/updater/UpdateManager.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/updater/UpdateManager.java @@ -12,6 +12,7 @@ import com.devonfw.tools.ide.url.tool.androidstudio.AndroidStudioUrlUpdater; import com.devonfw.tools.ide.url.tool.aws.AwsUrlUpdater; import com.devonfw.tools.ide.url.tool.az.AzureUrlUpdater; +import com.devonfw.tools.ide.url.tool.claude.ClaudeUrlUpdater; import com.devonfw.tools.ide.url.tool.copilot.CopilotUrlUpdater; import com.devonfw.tools.ide.url.tool.corepack.CorepackUrlUpdater; import com.devonfw.tools.ide.url.tool.docker.DockerDesktopUrlUpdater; @@ -68,7 +69,7 @@ public class UpdateManager extends AbstractProcessorWithTimeout { private final UrlFinalReport urlFinalReport; private final List updaters = List.of( - new AndroidStudioUrlUpdater(), new AwsUrlUpdater(), new AzureUrlUpdater(), new CopilotUrlUpdater(), new CorepackUrlUpdater(), + new AndroidStudioUrlUpdater(), new AwsUrlUpdater(), new AzureUrlUpdater(), new ClaudeUrlUpdater(), new CopilotUrlUpdater(), new CorepackUrlUpdater(), new DockerDesktopUrlUpdater(), new DotNetUrlUpdater(), new EclipseCppUrlUpdater(), new EclipseJeeUrlUpdater(), new EclipseJavaUrlUpdater(), new GCloudUrlUpdater(), From 591de4c727a539d62a213a889eda4ecb36c9333c Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 14:51:51 +0200 Subject: [PATCH 04/10] #1685: Add CPE vendor and product methods to CopilotUrlUpdater --- .../tools/ide/url/tool/copilot/CopilotUrlUpdater.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/copilot/CopilotUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/copilot/CopilotUrlUpdater.java index df515df082..3f1d8a1054 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/copilot/CopilotUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/copilot/CopilotUrlUpdater.java @@ -53,4 +53,14 @@ protected String getVersionPrefixToRemove() { return "v"; } + @Override + public String getCpeVendor() { + return "claude-code"; + } + + @Override + public String getCpeProduct() { + return "claude-code"; + } + } From 51a2102b11712d4ec8e964a775845e62fce1434a Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 14:57:23 +0200 Subject: [PATCH 05/10] Revert "#1685: Add CPE vendor and product methods to CopilotUrlUpdater" This reverts commit a3bc10ed5844a90170998afe36de8e7d6d333c97. --- .../tools/ide/url/tool/copilot/CopilotUrlUpdater.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/copilot/CopilotUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/copilot/CopilotUrlUpdater.java index 3f1d8a1054..df515df082 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/copilot/CopilotUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/copilot/CopilotUrlUpdater.java @@ -53,14 +53,4 @@ protected String getVersionPrefixToRemove() { return "v"; } - @Override - public String getCpeVendor() { - return "claude-code"; - } - - @Override - public String getCpeProduct() { - return "claude-code"; - } - } From d76b081e3ba5b2919841ec99246a420b73723718 Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 14:59:10 +0200 Subject: [PATCH 06/10] #1866: Add CPE vendor and product methods to ClaudeUrlUpdater --- .../tools/ide/url/tool/claude/ClaudeUrlUpdater.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java index 83a31d966c..773f7ec550 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java @@ -55,4 +55,14 @@ protected void addVersion(UrlVersion urlVersion) { protected String getVersionPrefixToRemove() { return "v"; } + + @Override + public String getCpeVendor() { + return "claude-code"; + } + + @Override + public String getCpeProduct() { + return "claude-code"; + } } From 803146b75fe52fa37c7dd70bafe9e4a33e9e4e4e Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 15:12:33 +0200 Subject: [PATCH 07/10] #1866: Fix documentation URL in ClaudeUrlUpdater --- .../com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java index 773f7ec550..e8b1b5f496 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java @@ -7,7 +7,7 @@ /** * {@link GithubUrlTagUpdater} for GitHub Claude Code CLI. *

- * Follows the official installation structure from GitHub's claude-code repository: https://github.com/anthropics/claude-code. Download URL pattern: * Download URL pattern: https://github.com/anthropics/claude-code/releases/download/v${VERSION}/claude-${PLATFORM}-${ARCH}.tar.gz */ From 67884302b70f64271ffe8d92a99e3db0bc8a085b Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 16:03:55 +0200 Subject: [PATCH 08/10] #1866: Update minimum Claude version identifier to 2.1.118 in ClaudeUrlUpdater --- .../com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java index e8b1b5f496..8fff7a6ba2 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java @@ -13,7 +13,7 @@ */ public class ClaudeUrlUpdater extends GithubUrlTagUpdater { - private static final VersionIdentifier MIN_CLAUDE_VID = VersionIdentifier.of("2.0.73"); + private static final VersionIdentifier MIN_CLAUDE_VID = VersionIdentifier.of("2.1.118"); @Override From ead103809bbbf15992a92dd26abe1622db1c2438 Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Tue, 28 Apr 2026 16:26:20 +0200 Subject: [PATCH 09/10] #1866: Update Claude version references to 2.1.119 in claude-tags.json and tests --- .../tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java | 2 +- .../integrationtest/ClaudeUrlUpdater/claude-tags.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java b/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java index 88f3ece8f0..291137e52f 100644 --- a/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java +++ b/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java @@ -46,7 +46,7 @@ void testClaudeUrlUpdater(@TempDir Path tempDir, WireMockRuntimeInfo wmRuntimeIn // assert Path claudeDir = tempDir.resolve("claude").resolve("claude"); - assertUrlVersionOsX64(claudeDir.resolve("2.1.110")); + assertUrlVersionOsX64(claudeDir.resolve("2.1.119")); } } diff --git a/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json b/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json index 469d103008..39da2e604c 100644 --- a/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json +++ b/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json @@ -1,9 +1,9 @@ [ { - "ref": "refs/tags/v2.1.110" + "ref": "refs/tags/v2.1.119" }, { - "ref": "refs/tags/v2.1.110-rc1" + "ref": "refs/tags/v2.1.119-rc1" } ] From d2d9bc2afa4e249632ebd39c3eaaf242d3058626 Mon Sep 17 00:00:00 2001 From: AdemZarrouki Date: Wed, 29 Apr 2026 13:08:36 +0200 Subject: [PATCH 10/10] #1866: exclude version 2.1.120 from claude and adapt MIN_CLAUDE_VID to 2.1.117 and exclude musl builds --- .../tools/ide/url/tool/claude/ClaudeUrlUpdater.java | 7 +++---- .../tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java | 2 +- .../integrationtest/ClaudeUrlUpdater/claude-tags.json | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java index 8fff7a6ba2..77cfc2c790 100644 --- a/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java +++ b/url-updater/src/main/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdater.java @@ -13,7 +13,8 @@ */ public class ClaudeUrlUpdater extends GithubUrlTagUpdater { - private static final VersionIdentifier MIN_CLAUDE_VID = VersionIdentifier.of("2.1.118"); + private static final VersionIdentifier MIN_CLAUDE_VID = VersionIdentifier.of("2.1.117"); + private static final VersionIdentifier EXCLUDED_VERSION = VersionIdentifier.of("2.1.120"); @Override @@ -36,12 +37,10 @@ protected void addVersion(UrlVersion urlVersion) { String baseUrl = createGithubReleaseDownloadUrl("v${version}", "claude-"); VersionIdentifier vid = urlVersion.getVersionIdentifier(); - if (vid.compareVersion(MIN_CLAUDE_VID).isGreater()) { + if (vid.compareVersion(MIN_CLAUDE_VID).isGreater() && !vid.compareVersion(EXCLUDED_VERSION).isEqual()) { doAddVersion(urlVersion, baseUrl + "linux-x64.tar.gz", LINUX, X64); - doAddVersion(urlVersion, baseUrl + "linux-x64-musl.tar.gz", LINUX, X64); doAddVersion(urlVersion, baseUrl + "linux-arm64.tar.gz", LINUX, ARM64); - doAddVersion(urlVersion, baseUrl + "linux-arm64-musl.tar.gz", LINUX, ARM64); doAddVersion(urlVersion, baseUrl + "darwin-x64.tar.gz", MAC, X64); doAddVersion(urlVersion, baseUrl + "darwin-arm64.tar.gz", MAC, ARM64); diff --git a/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java b/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java index 291137e52f..6c406901a3 100644 --- a/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java +++ b/url-updater/src/test/java/com/devonfw/tools/ide/url/tool/claude/ClaudeUrlUpdaterTest.java @@ -46,7 +46,7 @@ void testClaudeUrlUpdater(@TempDir Path tempDir, WireMockRuntimeInfo wmRuntimeIn // assert Path claudeDir = tempDir.resolve("claude").resolve("claude"); - assertUrlVersionOsX64(claudeDir.resolve("2.1.119")); + assertUrlVersionOsX64(claudeDir.resolve("2.1.118")); } } diff --git a/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json b/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json index 39da2e604c..4507c653ab 100644 --- a/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json +++ b/url-updater/src/test/resources/integrationtest/ClaudeUrlUpdater/claude-tags.json @@ -1,9 +1,9 @@ [ { - "ref": "refs/tags/v2.1.119" + "ref": "refs/tags/v2.1.118" }, { - "ref": "refs/tags/v2.1.119-rc1" + "ref": "refs/tags/v2.1.118-rc1" } ]