@echo off setlocal enabledelayedexpansion REM Claude Code Windows CMD Bootstrap Script REM Installs Claude Code for environments where PowerShell is not available REM Parse command line argument set "TARGET=%~1" if "!TARGET!"=="" set "TARGET=stable" REM Validate target parameter if /i "!TARGET!"=="stable" goto :target_valid if /i "!TARGET!"=="latest" goto :target_valid echo !TARGET! | findstr /r "^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*" >nul if !ERRORLEVEL! equ 0 goto :target_valid echo Usage: %0 [stable^|latest^|VERSION] >&2 echo Example: %0 1.0.58 >&2 exit /b 1 :target_valid REM Check for 64-bit Windows if /i "%PROCESSOR_ARCHITECTURE%"=="AMD64" goto :arch_valid if /i "%PROCESSOR_ARCHITECTURE%"=="ARM64" goto :arch_valid if /i "%PROCESSOR_ARCHITEW6432%"=="AMD64" goto :arch_valid if /i "%PROCESSOR_ARCHITEW6432%"=="ARM64" goto :arch_valid echo Claude Code does not support 32-bit Windows. Please use a 64-bit version of Windows. >&2 exit /b 1 :arch_valid REM Set constants set "GCS_BUCKET=https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases" set "DOWNLOAD_DIR=%USERPROFILE%\.claude\downloads" set "PLATFORM=win32-x64" REM Create download directory if not exist "!DOWNLOAD_DIR!" mkdir "!DOWNLOAD_DIR!" REM Check for curl availability curl --version >nul 2>&1 if !ERRORLEVEL! neq 0 ( echo curl is required but not available. Please install curl or use PowerShell installer. >&2 exit /b 1 ) REM Always download stable version (which has the most up-to-date installer) call :download_file "!GCS_BUCKET!/stable" "!DOWNLOAD_DIR!\stable" if !ERRORLEVEL! neq 0 ( echo Failed to get stable version >&2 exit /b 1 ) REM Read version from file set /p VERSION=<"!DOWNLOAD_DIR!\stable" del "!DOWNLOAD_DIR!\stable" REM Download manifest call :download_file "!GCS_BUCKET!/!VERSION!/manifest.json" "!DOWNLOAD_DIR!\manifest.json" if !ERRORLEVEL! neq 0 ( echo Failed to get manifest >&2 exit /b 1 ) REM Extract checksum from manifest call :parse_manifest "!DOWNLOAD_DIR!\manifest.json" "!PLATFORM!" if !ERRORLEVEL! neq 0 ( echo Platform !PLATFORM! not found in manifest >&2 del "!DOWNLOAD_DIR!\manifest.json" 2>nul exit /b 1 ) del "!DOWNLOAD_DIR!\manifest.json" REM Download binary set "BINARY_PATH=!DOWNLOAD_DIR!\claude-!VERSION!-!PLATFORM!.exe" call :download_file "!GCS_BUCKET!/!VERSION!/!PLATFORM!/claude.exe" "!BINARY_PATH!" if !ERRORLEVEL! neq 0 ( echo Failed to download binary >&2 if exist "!BINARY_PATH!" del "!BINARY_PATH!" exit /b 1 ) REM Verify checksum call :verify_checksum "!BINARY_PATH!" "!EXPECTED_CHECKSUM!" if !ERRORLEVEL! neq 0 ( echo Checksum verification failed >&2 del "!BINARY_PATH!" exit /b 1 ) REM Run claude install to set up launcher and shell integration echo Setting up Claude Code... if "!TARGET!"=="stable" ( "!BINARY_PATH!" install ) else ( "!BINARY_PATH!" install "!TARGET!" ) set "INSTALL_RESULT=!ERRORLEVEL!" REM Clean up downloaded file REM Wait a moment for any file handles to be released timeout /t 1 /nobreak >nul 2>&1 del /f "!BINARY_PATH!" >nul 2>&1 if exist "!BINARY_PATH!" ( echo Warning: Could not remove temporary file: !BINARY_PATH! ) if !INSTALL_RESULT! neq 0 ( echo Installation failed >&2 exit /b 1 ) echo. echo Installation complete^^! echo. exit /b 0 REM ============================================================================ REM SUBROUTINES REM ============================================================================ :download_file REM Downloads a file using curl REM Args: %1=URL, %2=OutputPath set "URL=%~1" set "OUTPUT=%~2" curl -fsSL "!URL!" -o "!OUTPUT!" exit /b !ERRORLEVEL! :parse_manifest REM Parse JSON manifest to extract checksum for platform REM Args: %1=ManifestPath, %2=Platform set "MANIFEST_PATH=%~1" set "PLATFORM_NAME=%~2" set "EXPECTED_CHECKSUM=" REM Use findstr to find platform section, then look for checksum set "FOUND_PLATFORM=" set "IN_PLATFORM_SECTION=" REM Read the manifest line by line for /f "usebackq tokens=*" %%i in ("!MANIFEST_PATH!") do ( set "LINE=%%i" REM Check if this line contains our platform echo !LINE! | findstr /c:"\"%PLATFORM_NAME%\":" >nul if !ERRORLEVEL! equ 0 ( set "IN_PLATFORM_SECTION=1" ) REM If we're in the platform section, look for checksum if defined IN_PLATFORM_SECTION ( echo !LINE! | findstr /c:"\"checksum\":" >nul if !ERRORLEVEL! equ 0 ( REM Extract checksum value for /f "tokens=2 delims=:" %%j in ("!LINE!") do ( set "CHECKSUM_PART=%%j" REM Remove quotes, whitespace, and comma set "CHECKSUM_PART=!CHECKSUM_PART: =!" set "CHECKSUM_PART=!CHECKSUM_PART:"=!" set "CHECKSUM_PART=!CHECKSUM_PART:,=!" REM Check if it looks like a SHA256 (64 hex chars) if not "!CHECKSUM_PART!"=="" ( call :check_length "!CHECKSUM_PART!" 64 if !ERRORLEVEL! equ 0 ( set "EXPECTED_CHECKSUM=!CHECKSUM_PART!" exit /b 0 ) ) ) ) REM Check if we've left the platform section (closing brace) echo !LINE! | findstr /c:"}" >nul if !ERRORLEVEL! equ 0 set "IN_PLATFORM_SECTION=" ) ) if "!EXPECTED_CHECKSUM!"=="" exit /b 1 exit /b 0 :check_length REM Check if string length equals expected length REM Args: %1=String, %2=ExpectedLength set "STR=%~1" set "EXPECTED_LEN=%~2" set "LEN=0" :count_loop if "!STR:~%LEN%,1!"=="" goto :count_done set /a LEN+=1 goto :count_loop :count_done if %LEN%==%EXPECTED_LEN% exit /b 0 exit /b 1 :verify_checksum REM Verify file checksum using certutil REM Args: %1=FilePath, %2=ExpectedChecksum set "FILE_PATH=%~1" set "EXPECTED=%~2" for /f "skip=1 tokens=*" %%i in ('certutil -hashfile "!FILE_PATH!" SHA256') do ( set "ACTUAL=%%i" set "ACTUAL=!ACTUAL: =!" if "!ACTUAL!"=="CertUtil:Thecommandcompletedsuccessfully." goto :verify_done if "!ACTUAL!" neq "" ( if /i "!ACTUAL!"=="!EXPECTED!" ( exit /b 0 ) else ( exit /b 1 ) ) ) :verify_done exit /b 1