Claude Portable

7 min read Original article ↗
@echo off REM ===================================================================== REM InstallClaude.cmd - run ONCE, on a machine you trust. REM Downloads + verifies claude.exe, writes an INERT, self-elevating REM Claude.cmd plus config.txt, a field-IT CLAUDE.md, and a safe-fast REM settings.json, then opens Claude Code for a one-time login. REM Everything below the "#PS-PAYLOAD#" line is PowerShell, run by the REM line just below. cmd never runs it. It is not obfuscated - read it. REM ===================================================================== setlocal set "ROOT=%~dp0" set "BUCKET=https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases" md "%ROOT%bin" 2>nul & md "%ROOT%data" 2>nul & md "%ROOT%tmp" 2>nul & md "%ROOT%work" 2>nul powershell -NoProfile -ExecutionPolicy Bypass -Command "$t=[IO.File]::ReadAllText('%~f0'); iex $t.Substring($t.LastIndexOf([char]10+'#PS-PAYLOAD#'))" || (echo. & echo Install failed - nothing was kept. Run on a trusted machine with internet. & echo. & pause & exit /b 1) echo. echo Setup complete. Opening Claude Code so you can log in... echo After you log in, type /exit , then eject the stick. echo. set "CLAUDE_CONFIG_DIR=%ROOT%data" set "DISABLE_AUTOUPDATER=1" cd /d "%ROOT%work" "%ROOT%bin\claude.exe" exit /b 0 #PS-PAYLOAD# $ErrorActionPreference = 'Stop' $root = $env:ROOT $bucket = $env:BUCKET $plat = if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { 'win32-arm64' } else { 'win32-x64' } $exe = Join-Path $root 'bin\claude.exe' if (-not (Test-Path $exe)) { Write-Host " Downloading Claude Code ($plat)..." $ver = (Invoke-WebRequest "$bucket/latest" -UseBasicParsing).Content.Trim() $want = ((Invoke-WebRequest "$bucket/$ver/manifest.json" -UseBasicParsing).Content | ConvertFrom-Json).platforms.$plat.checksum Invoke-WebRequest "$bucket/$ver/$plat/claude.exe" -OutFile $exe -UseBasicParsing if ((Get-FileHash $exe -Algorithm SHA256).Hash.ToLower() -ne $want.ToLower()) { Remove-Item $exe; throw "SHA256 mismatch - aborted." } $sig = Get-AuthenticodeSignature $exe if ($sig.Status -ne 'Valid' -or $sig.SignerCertificate.Subject -notlike '*Anthropic*') { Remove-Item $exe; throw "Not signed by Anthropic - aborted." } Write-Host " Verified claude.exe v$ver - $($sig.SignerCertificate.Subject)" } else { Write-Host " claude.exe already present - skipping download." } function Write-IfAbsent($path, $text) { if (Test-Path $path) { Write-Host " kept existing $(Split-Path $path -Leaf)"; return } [IO.File]::WriteAllText($path, ($text -replace "`r?`n","`r`n"), [Text.Encoding]::ASCII) Write-Host " wrote $(Split-Path $path -Leaf)" } # --- config.txt (optional settings; docs inside the file) --- Write-IfAbsent (Join-Path $root 'config.txt') @' # ============================================================ # Claude Code Portable - config (OPTIONAL) # ============================================================ # Read by Claude.cmd at launch. Safe to leave fully commented # out - browser login needs nothing here. Edit any time. # Syntax: KEY=value (no spaces around =, no quotes, # = comment) # ============================================================ # API-key auth instead of browser login (get one at https://console.anthropic.com/) #ANTHROPIC_API_KEY=sk-ant-... # Route through a proxy/gateway. WARNING: sends every request AND your # credentials to the host you name. Only ever point it somewhere you own. #ANTHROPIC_BASE_URL=https://your-gateway.example.com # ------------------------------------------------------------ # Never run a stick - or a config file - given to you by # someone else. Both can silently redirect your credentials. # ------------------------------------------------------------ '@ # --- field-IT priming: loaded when Claude.cmd runs from work\ (the default) --- New-Item -ItemType Directory -Force (Join-Path $root 'work\.claude') | Out-Null Write-IfAbsent (Join-Path $root 'work\CLAUDE.md') @' # Windows break-fix technician You are an on-site Windows repair assistant running from a technician's USB stick. The technician is at the keyboard and approves actions. Work fast: diagnose, then fix. ## Rules - This is Windows. Use PowerShell (and cmd where simpler). Never assume bash / Unix tools. - Diagnose before you change. State the one-line cause you suspect, then act. - Prefer reversible fixes. Before disabling or removing anything, say in one line what it is and what breaks if you are wrong, then let the confirmation prompt do its job. - Batch read-only checks, then act. Report findings and changes briefly - no essays. - When done, give a 2-3 line summary of every change, so it can be undone. ## Do not, without the owner confirming - Touch business-critical software, its services, licensing, or database. - Open, copy, or move sensitive data (customer records, databases, personal files). You fix the machine, not the data on it. ## Playbooks (run the sequence, stop when fixed, confirm it worked) ### Printer will not print 1. Get-Service Spooler -- if stopped, Start-Service Spooler. 2. Stuck queue: stop Spooler, delete C:\Windows\System32\spool\PRINTERS\*, start Spooler. 3. Correct default? Get-Printer -- not defaulting to "Microsoft Print to PDF". 4. Offline flag: check PrinterStatus; clear "Use Printer Offline". 5. Driver: Get-PrinterDriver -- reinstall with pnputil / Add-PrinterDriver if missing. 6. Connection: USB replugged, or network printer reachable (Test-Connection <ip>). 7. Print a Windows test page. ### "The computer is slow" 1. Startup bloat: Get-CimInstance Win32_StartupCommand -- disable heavy non-essentials (confirm each; leave AV and business-critical apps alone). 2. Disk space: Get-PSDrive C -- if near full: cleanmgr, clear %TEMP%, empty Recycle Bin. 3. Resource hogs: Get-Process | Sort CPU -Descending | Select -First 10. 4. Pending reboot or a stuck update thrashing the disk -- reboot if so. 5. Malware check: Start-MpScan -ScanType QuickScan (Defender); review. 6. Browser toolbars / excess extensions -- remove with consent. 7. If it is a spinning HDD and thrashing, note that an SSD is the real fix. ### No internet 1. Get-NetAdapter (up?) and ipconfig /all (IP + gateway?). 2. Test-Connection 1.1.1.1 vs Test-Connection google.com to isolate DNS. 3. Clear-DnsClientCache; set a working resolver if theirs is dead. 4. ipconfig /release then /renew. If needed: netsh winsock reset (reboot after). 5. Adapter driver / Wi-Fi radio / cable as applicable. ### Unknown error Read the message verbatim, search the exact text, apply the known fix, verify. '@ # --- safe-fast permissions: read-only triage silent, changes still prompt --- Write-IfAbsent (Join-Path $root 'work\.claude\settings.json') @' { "$schema": "https://json.schemastore.org/claude-code-settings.json", "permissions": { "defaultMode": "default", "allow": [ "Bash(Get-Service:*)", "Bash(Get-Process:*)", "Bash(Get-Printer:*)", "Bash(Get-PrinterDriver:*)", "Bash(Get-CimInstance:*)", "Bash(Get-NetAdapter:*)", "Bash(Get-PSDrive:*)", "Bash(Test-Connection:*)", "Bash(systeminfo:*)", "Bash(ipconfig:*)" ], "deny": [ "Bash(format:*)", "Bash(diskpart:*)", "Bash(Clear-Disk:*)", "Bash(Format-Volume:*)", "Bash(bcdedit:*)" ], "disableBypassPermissionsMode": "disable" } } '@ # --- write the INERT, self-elevating launcher (no download path; that is the point) --- $launcher = @' @echo off REM Claude Code Portable - launcher (generated by InstallClaude.cmd). REM Inert by design: no download path. Self-elevates so admin fixes work. REM If bin\claude.exe is missing, re-run InstallClaude.cmd on a trusted machine. REM VERIFY=0 skips the publisher check. setlocal set "ROOT=%~dp0" set "VERIFY=1" REM --- self-elevate so admin fixes (spooler, drivers, services) work --- net session >nul 2>&1 if errorlevel 1 ( powershell -NoProfile -Command "try{Start-Process -FilePath '%~f0' -ArgumentList '%*' -Verb RunAs -ErrorAction Stop}catch{exit 1}" if not errorlevel 1 exit /b ) set "CLAUDE_CONFIG_DIR=%ROOT%data" set "CLAUDE_CODE_TMPDIR=%ROOT%tmp" set "DISABLE_AUTOUPDATER=1" set "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1" if exist "%ProgramFiles%\Git\bin\bash.exe" set "CLAUDE_CODE_GIT_BASH_PATH=%ProgramFiles%\Git\bin\bash.exe" if exist "%ROOT%config.txt" for /f "usebackq eol=# tokens=1,* delims==" %%A in ("%ROOT%config.txt") do set "%%A=%%B" set "BINEXE=%ROOT%bin\claude.exe" if not exist "%BINEXE%" goto :nobin md "%CLAUDE_CONFIG_DIR%" 2>nul & md "%CLAUDE_CODE_TMPDIR%" 2>nul & md "%ROOT%work" 2>nul if "%VERIFY%"=="1" powershell -NoProfile -Command "$s=Get-AuthenticodeSignature \"$env:BINEXE\"; if($s.Status -ne 'Valid' -or $s.SignerCertificate.Subject -notlike '*Anthropic*'){exit 1}" || goto :badsig REM --- stable virtual drive so sessions resume regardless of the stick's real letter --- REM Claude keys session history by the working-dir path (drive letter included), so an REM E: vs F: mount orphans your resumes. Map a fixed letter onto the stick so cwd never REM changes between machines. Override the letter with PORTABLE_DRIVE=X: in config.txt. set "VDRIVE=Q:" if defined PORTABLE_DRIVE set "VDRIVE=%PORTABLE_DRIVE%" set "MADEVDRIVE=" if not exist "%VDRIVE%\" ( subst %VDRIVE% "%ROOT:~0,-1%" >nul 2>&1 if not errorlevel 1 set "MADEVDRIVE=1" ) set "BASE=%ROOT%" if exist "%VDRIVE%\bin\claude.exe" (set "BASE=%VDRIVE%\") else echo [note] %VDRIVE% unavailable - using %ROOT%; sessions may not resume this time. set "WORK=%BASE%work" & set "ARGS=%*" if not "%~1"=="" if exist "%~1\" (set "WORK=%~f1" & set "ARGS=") cd /d "%WORK%" && "%BINEXE%" %ARGS% set "RC=%errorlevel%" if defined MADEVDRIVE subst %VDRIVE% /d >nul 2>&1 exit /b %RC% :nobin echo. echo bin\claude.exe is not on this stick, and this launcher never downloads. echo Re-run InstallClaude.cmd once on a machine you trust, then use this. echo. pause & exit /b 1 :badsig echo. echo *** PUBLISHER CHECK FAILED *** echo bin\claude.exe is not validly signed by Anthropic, PBC - or PowerShell is echo restricted on this host and the check could not run. Either way, stop and echo re-run InstallClaude.cmd from a clean copy on a machine you trust. echo. pause & exit /b 1 '@ [IO.File]::WriteAllText((Join-Path $root 'Claude.cmd'), ($launcher -replace "`r?`n","`r`n"), [Text.Encoding]::ASCII) Write-Host " wrote Claude.cmd (inert, self-elevating)"