Skip to content

Instantly share code, notes, and snippets.

@tonydzi
Created August 24, 2026 16:59
Show Gist options
  • Select an option

  • Save tonydzi/8a38b1467bbfd9dbb8c1dbc5532efdf2 to your computer and use it in GitHub Desktop.

Select an option

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%)
# 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