Created
August 24, 2026 16:59
-
-
Save tonydzi/8a38b1467bbfd9dbb8c1dbc5532efdf2 to your computer and use it in GitHub Desktop.
Claude Desktop (Windows MSIX) repair ladder for 'Modified, NeedsRemediation' - field-tested 2026-08-24; never registers a healthy package (0x80070005 corruption path), lets Windows' own remediation run first, Register only when partially staged, clean-reinstall end state (login survives in %LOCALAPPDATA%)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Fix-ClaudeDesktopMSIX.ps1 | |
| # | |
| # Diagnose + repair ladder for Claude Desktop (Windows MSIX) stuck in | |
| # "Modified, NeedsRemediation" / refusing to launch. | |
| # | |
| # Field-tested 2026-08-24 on Windows 11 (build 26200) while debugging this class: | |
| # https://github.com/anthropics/claude-code/issues/84333 (and siblings) | |
| # | |
| # Key facts this script encodes (all reproduced live): | |
| # 1. Running `Add-AppxPackage -Register` on a HEALTHY package is a CORRUPTION | |
| # path: it can fail with 0x80070005 and flip the package Ok -> Modified, | |
| # NeedsRemediation, silently (no deployment operation logged). This script | |
| # therefore NEVER registers a healthy package. | |
| # 2. Windows' own activation-time remediation (triggered by launching the app) | |
| # heals what scripted Register breaks. Launch first, Register last. | |
| # 3. If the package flips back to Modified instantly even after a successful | |
| # Register, that is StateRepository rot: no repair holds. The only cure is | |
| # Remove-AppxPackage + clean reinstall from https://claude.com/download. | |
| # Your login and app config SURVIVE this (they live in %LOCALAPPDATA%\Claude, | |
| # outside the package container). | |
| # 4. The "Another program is currently using this file" dialog (0x80070020) can | |
| # lie: the real failure may be AppX *container creation* | |
| # (Microsoft-Windows-AppModel-Runtime/Admin, events 208/215) - that layer is | |
| # cured by a reboot, not by killing processes. | |
| # 5. Reinstall hitting 0x80073CF6 means: reboot first, then reinstall. | |
| # | |
| # Usage: powershell -ExecutionPolicy Bypass -File .\Fix-ClaudeDesktopMSIX.ps1 | |
| # (run from a normal interactive console, NOT via ssh/service - the app | |
| # window can only be created in your interactive desktop session) | |
| # | |
| # The script is safe by default: it only kills Claude processes and relaunches. | |
| # The destructive step (Remove-AppxPackage) always asks for confirmation. | |
| # No telemetry, no network calls. MIT-do-whatever-you-want. | |
| $ErrorActionPreference = 'SilentlyContinue' | |
| $AUMID = 'Claude_pzs8sxrjxfjjc!Claude' | |
| function Get-ClaudePkg { Get-AppxPackage -Name Claude | Select-Object -First 1 } | |
| function Show-Diag { | |
| Write-Host '' | |
| Write-Host '--- diagnostics ---------------------------------------------' | |
| $pkg = Get-ClaudePkg | |
| if ($pkg) { | |
| Write-Host ("package : {0} Status: {1}" -f $pkg.PackageFullName, $pkg.Status) | |
| $staged = ($pkg.PackageUserInformation | Where-Object { "$($_.InstallState)" -match 'Staged' }) | |
| if ($staged) { Write-Host 'staged : package is PARTIALLY STAGED for this user' -ForegroundColor Yellow } | |
| } else { | |
| Write-Host 'package : NOT INSTALLED (Get-AppxPackage -Name Claude returned nothing)' | |
| } | |
| $p = Get-Process claude -ErrorAction SilentlyContinue | |
| if ($p) { | |
| $sess = ($p | Select-Object -ExpandProperty SessionId -Unique) -join ',' | |
| $win = ($p | Where-Object { $_.MainWindowHandle -ne 0 }).Count | |
| Write-Host ("procs : {0} claude.exe sessions: {1} with-window: {2}" -f $p.Count, $sess, $win) | |
| if ($sess -eq '0') { Write-Host 'warning : all processes in session 0 (no desktop) - zombie state' -ForegroundColor Yellow } | |
| } else { Write-Host 'procs : none' } | |
| # last 24h of the log where the REAL container errors live (often silent elsewhere) | |
| $since = (Get-Date).AddDays(-1) | |
| $ev = Get-WinEvent -FilterHashtable @{ LogName='Microsoft-Windows-AppModel-Runtime/Admin'; StartTime=$since } -MaxEvents 5 -ErrorAction SilentlyContinue | | |
| Where-Object { $_.LevelDisplayName -in 'Error','Warning' -and $_.Message -match 'Claude' } | |
| if ($ev) { | |
| Write-Host 'AppModel-Runtime/Admin (last 24h, Claude-related):' -ForegroundColor Yellow | |
| $ev | ForEach-Object { Write-Host (" [{0}] id {1}: {2}" -f $_.TimeCreated.ToString('HH:mm'), $_.Id, ($_.Message -split "`n")[0]) } | |
| if ($ev | Where-Object { $_.Id -in 208,215 }) { | |
| Write-Host ' events 208/215 = AppX CONTAINER creation failure. Killing processes' -ForegroundColor Yellow | |
| Write-Host ' will NOT fix this layer - if the ladder below fails, REBOOT.' -ForegroundColor Yellow | |
| } | |
| } | |
| Write-Host '-------------------------------------------------------------' | |
| } | |
| Write-Host '' | |
| Write-Host '=== Claude Desktop MSIX repair ladder ===' | |
| Show-Diag | |
| $mySession = (Get-Process -Id $PID).SessionId | |
| if ($mySession -eq 0) { | |
| Write-Host '' | |
| Write-Host 'This console runs in session 0 (ssh/service). The app window cannot be' -ForegroundColor Red | |
| Write-Host 'created from here - run this script from a normal local console.' -ForegroundColor Red | |
| exit 1 | |
| } | |
| # Step 1: kill Claude processes (safe, always). | |
| Write-Host '' | |
| Write-Host 'Step 1: stopping claude/cowork processes...' | |
| Stop-Process -Name claude -Force -ErrorAction SilentlyContinue | |
| Get-Process | Where-Object { $_.Name -like 'cowork*' } | Stop-Process -Force -ErrorAction SilentlyContinue | |
| Start-Sleep -Seconds 4 | |
| $pkg = Get-ClaudePkg | |
| if (-not $pkg) { | |
| Write-Host 'Package is not installed. Install from https://claude.com/download and re-run.' -ForegroundColor Yellow | |
| exit 1 | |
| } | |
| # Step 2: if the package is HEALTHY - do NOT touch registration. Just relaunch. | |
| if ("$($pkg.Status)" -eq 'Ok') { | |
| Write-Host 'Step 2: package Status=Ok - NOT touching registration (re-registering a' | |
| Write-Host ' healthy package can corrupt it: 0x80070005 -> Modified). Relaunching...' | |
| Start-Process 'explorer.exe' "shell:AppsFolder\$AUMID" | |
| Start-Sleep -Seconds 15 | |
| Show-Diag | |
| $after = Get-Process claude -ErrorAction SilentlyContinue | |
| if ($after -and ($after | Where-Object { $_.MainWindowHandle -ne 0 })) { | |
| Write-Host 'DONE: app is up with a window.' -ForegroundColor Green; exit 0 | |
| } | |
| Write-Host 'App did not come up despite Status=Ok. Likely the container layer' -ForegroundColor Yellow | |
| Write-Host '(see 208/215 note above) - REBOOT, then try again.' -ForegroundColor Yellow | |
| exit 1 | |
| } | |
| # Step 3: package is Modified/NeedsRemediation. Let WINDOWS heal it first: | |
| # activation triggers Windows' own RepairAppRegistrationOption, which (unlike | |
| # scripted Register) actually works. | |
| Write-Host ("Step 3: package Status={0}. Launching the app so Windows' own" -f $pkg.Status) | |
| Write-Host ' activation-time remediation can run (this heals more often than' | |
| Write-Host ' any manual Register)...' | |
| Start-Process 'explorer.exe' "shell:AppsFolder\$AUMID" | |
| Start-Sleep -Seconds 20 | |
| $pkg = Get-ClaudePkg | |
| Write-Host (" after launch attempt: Status={0}" -f $pkg.Status) | |
| $after = Get-Process claude -ErrorAction SilentlyContinue | |
| if ("$($pkg.Status)" -eq 'Ok' -and $after) { | |
| Write-Host 'DONE: Windows remediation healed the package and the app is up.' -ForegroundColor Green | |
| exit 0 | |
| } | |
| # Step 4: Register - ONLY if partially staged (the one case where it belongs). | |
| $staged = ($pkg.PackageUserInformation | Where-Object { "$($_.InstallState)" -match 'Staged' }) | |
| if ($staged) { | |
| Write-Host 'Step 4: package is partially staged - this IS the legitimate Register case...' | |
| Add-AppxPackage -DisableDevelopmentMode -Register "$($pkg.InstallLocation)\AppXManifest.xml" -ForceApplicationShutdown | |
| Start-Sleep -Seconds 5 | |
| $pkg = Get-ClaudePkg | |
| Write-Host (" after Register: Status={0}" -f $pkg.Status) | |
| if ("$($pkg.Status)" -eq 'Ok') { | |
| Start-Process 'explorer.exe' "shell:AppsFolder\$AUMID" | |
| Write-Host 'DONE: registered and relaunched.' -ForegroundColor Green | |
| exit 0 | |
| } | |
| } else { | |
| Write-Host 'Step 4: package is NOT partially staged - skipping Register on purpose' | |
| Write-Host ' (registering here is the corruption path, not the cure).' | |
| } | |
| # Step 5: nothing held -> StateRepository rot. Clean reinstall is the only cure. | |
| Write-Host '' | |
| Write-Host 'Step 5: repair does not hold. This is the StateRepository-rot end state:' -ForegroundColor Yellow | |
| Write-Host ' the package files are fine, the registration DB is rotten, and only' | |
| Write-Host ' a clean reinstall cures it. Good news: your LOGIN AND SETTINGS' | |
| Write-Host ' SURVIVE (they live in %LOCALAPPDATA%\Claude, not in the package).' | |
| Write-Host '' | |
| $ans = Read-Host 'Remove the package now? Afterwards reinstall from https://claude.com/download [y/N]' | |
| if ($ans -match '^[yY]') { | |
| Get-AppxPackage -Name Claude | Remove-AppxPackage | |
| Start-Sleep -Seconds 3 | |
| if (Get-ClaudePkg) { | |
| Write-Host 'Removal did not complete - reboot, then remove again / reinstall.' -ForegroundColor Red | |
| exit 1 | |
| } | |
| Write-Host '' | |
| Write-Host 'Package removed. Now:' -ForegroundColor Green | |
| Write-Host ' 1. Download the installer from https://claude.com/download' | |
| Write-Host ' (optionally verify: Get-AuthenticodeSignature should show Anthropic, PBC / Valid)' | |
| Write-Host ' 2. If install fails with 0x80073CF6 - REBOOT first, then install.' | |
| Write-Host ' 3. Your login will still be there after reinstall.' | |
| Write-Host ' 4. If it corrupts again: audit ANYTHING that re-registers the package on a' | |
| Write-Host ' schedule (recovery scripts, forum one-liners in scheduled tasks, IT tooling).' | |
| Write-Host ' In our case our own nightly "repair" script was the disease.' | |
| } else { | |
| Write-Host 'Skipped removal. Manual path: Get-AppxPackage -Name Claude | Remove-AppxPackage' | |
| Write-Host 'then reinstall from https://claude.com/download (reboot if 0x80073CF6).' | |
| } | |
| exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment