Skip to content

Instantly share code, notes, and snippets.

@Braunson
Created December 31, 2025 20:46
Show Gist options
  • Select an option

  • Save Braunson/2dd8da648fa3b744598504a37eaab78c to your computer and use it in GitHub Desktop.

Select an option

Save Braunson/2dd8da648fa3b744598504a37eaab78c to your computer and use it in GitHub Desktop.
VS Code Username Path Autofix (Windows)

VS Code Username Path Autofix (Windows)

Safely migrates hard-coded user paths (e.g. Users\geekybeaver) inside VS Code configuration, extensions, and state databases after moving to a new Windows user profile.

Designed for Windows 10/11 + PowerShell + sqlite3.

My use-case

I had Windows 11 become corrupt, backups and restore points didn't work, the repair option didn't work, it just wouldn't boot into anything other than safe mode which was useless. I however imaged the old C drive as I had some important stuff on there.

Next I reinstalled Win 11 fresh, and am now copying over my VS Code config/extensions (yes I'm aware of the VS Sync feature already). The issue now is my Window user is different from my old C drive to my new C drive so I copied the config and extension folders over already and needed to update all old user path references

What this script does

✅ Text files

  • Scans VS Code user config and extensions
  • Replaces:
    • Users\geekybeaver
    • Users/geekybeaver
  • Writes back without corrupting encoding
    • Preserves UTF-8 (with/without BOM), UTF-16 LE/BE
  • Touches only whitelisted text extensions
  • Creates a full backup of every modified file

✅ SQLite databases (VS Code state)

  • Detects SQLite DBs safely
  • Verifies DB is:
    • SQLite
    • Not locked
    • Matches known VS Code schemas
  • Targets VS Code state/storage DBs only (e.g. state.vscdb, storage.db)
  • Updates TEXT columns only (never raw binary/BLOBs)
  • Uses sqlite3 with transactions (BEGIN / COMMIT)
  • Backs up every DB before modification
  • Skips unknown or incompatible databases

❌ What it will NOT do

  • No blind binary search/replace
  • No raw hex editing
  • No touching random extension databases with unknown schemas
  • No deleting caches or state files
  • No modifying DBs that fail validation

Requirements

  • Windows 10 / 11
  • PowerShell 5.1+
  • sqlite3 on PATH Install via winget install SQLite.SQLite

Before Running

  1. Close VS Code completely
  2. Make sure the source paths actually exist (e.g. old username appears somewhere)
  3. Run PowerShell normally (Admin is fine but not required)

What gets scanned

Text roots

C:\Users\<NewUser>\AppData\Roaming\Code
C:\Users\<NewUser>\.vscode\extensions

Database roots

C:\Users\<NewUser>\AppData\Roaming\Code

Backups & Logging

Backups

Every changed file or DB is copied to:

C:\temp\vscode-autofix-backups-<timestamp>\

Filenames are path-encoded to avoid collisions.

Log file

C:\temp\vscode-autofix-<timestamp>.log

The log includes:

  • each modified file
  • backup location
  • skipped DBs
  • errors (if any)

Verifying database integrity

If the script reports DB errors or skips, that does NOT mean corruption.

The script only modifies a DB after:

  • confirming it’s SQLite
  • confirming expected tables exist
  • successfully starting a transaction

Manual DB health check

Run this on any VS Code DB you’re unsure about:

sqlite3 "C:\path\to\state.vscdb" "PRAGMA quick_check;"

Expected output:

ok

If you get ok, the DB is healthy.

Verifying no old paths remain

After the script completes, verify there are no remaining references to the old username.

PowerShell verification scan

Get-ChildItem @(
  "C:\Users\<NewUser>\AppData\Roaming\Code",
  "C:\Users\<NewUser>\.vscode\extensions"
) -Recurse -File -Force -ErrorAction SilentlyContinue |
Select-String -Pattern "Users\\geekybeaver" -SimpleMatch -ErrorAction SilentlyContinue |
Select-Object Path, LineNumber
  • No output -> migration is clean
  • Any hits shown -> inspect manuallly (often cache/state)

Common outcomes (normal)

  • Text: Changed > 0 = Expected, paths were fixed
  • DB: Updated = 0 = Normal if DBs didn't contain matching paths
  • DB: Skipped > 0 = Normal - DB didn't match known schema
  • DB: Errors > 0 = Ususally comand-level failure, not corruption

Recovery (if needed)

To restore any file or DB:

  1. Locate it in the backup directory
  2. Copy it back to over the original
  3. Restart VS Code.

No global rollback needed — backups are per-file.

Why is this approach safe?

  • Encoding-aware writes (no Set-Content corruption)
  • No dynamic SQL string building
  • No blind binary edits
  • Explicit schema checks
  • Transaction-based DB updates
  • Conservative skip-first behavior

License / Usage

Public domain / use at your own risk. Tested against real VS Code profiles with large extension sets.

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# ========= CONFIG =========
$oldUser = "geekybeaver"
$newUser = "Braunson"
$textRoots = @(
"C:\Users\Braunson\AppData\Roaming\Code",
"C:\Users\Braunson\.vscode\extensions"
)
$dbRoots = @(
"C:\Users\Braunson\AppData\Roaming\Code"
)
# Only edit these text extensions
$include = @(
"*.json","*.code-workspace","*.js","*.jsx","*.ts","*.tsx","*.css","*.html","*.htm","*.md","*.txt",
"*.yml","*.yaml","*.ini","*.cfg","*.conf","*.ps1","*.psm1","*.bat","*.cmd","*.sh","*.toml","*.xml"
)
# SQLite-ish extensions we will touch ONLY via sqlite3
$dbExt = @(".vscdb",".sqlite",".sqlite3",".db")
# ========= OUTPUT =========
$ts = Get-Date -Format "yyyyMMdd-HHmmss"
$logDir = "C:\temp"
$log = Join-Path $logDir "vscode-autofix-$ts.log"
$backupDir = Join-Path $logDir "vscode-autofix-backups-$ts"
New-Item -ItemType Directory -Force -Path $logDir | Out-Null
New-Item -ItemType Directory -Force -Path $backupDir | Out-Null
function Log([string]$msg) { $msg | Out-File $log -Append -Encoding UTF8 }
# Replace Users\old OR Users/old, case-insensitive
$pattern = "(?i)(Users[\\/])" + [Regex]::Escape($oldUser) + "\b"
$rx = [Regex]::new($pattern)
$replacement = "`$1$newUser"
function Backup-File([string]$fullPath) {
$safeName = ($fullPath -replace "[:\\]", "_")
$dest = Join-Path $backupDir $safeName
Copy-Item -LiteralPath $fullPath -Destination $dest -Force
return $dest
}
function Get-EncTag([byte[]]$bytes) {
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { return "utf8BOM" }
if ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE) { return "utf16LE" }
if ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFE -and $bytes[1] -eq 0xFF) { return "utf16BE" }
return "utf8NoBOM"
}
function Decode([byte[]]$bytes, [string]$tag) {
switch ($tag) {
"utf8BOM" { return [Text.Encoding]::UTF8.GetString($bytes) }
"utf16LE" { return [Text.Encoding]::Unicode.GetString($bytes) }
"utf16BE" { return [Text.Encoding]::BigEndianUnicode.GetString($bytes) }
default { return [Text.Encoding]::UTF8.GetString($bytes) }
}
}
function EncodeAndWrite([string]$path, [string]$text, [string]$tag) {
switch ($tag) {
"utf8BOM" {
$enc = [Text.UTF8Encoding]::new($true)
[IO.File]::WriteAllText($path, $text, $enc)
}
"utf16LE" {
[IO.File]::WriteAllText($path, $text, [Text.Encoding]::Unicode)
}
"utf16BE" {
[IO.File]::WriteAllText($path, $text, [Text.Encoding]::BigEndianUnicode)
}
default {
$enc = [Text.UTF8Encoding]::new($false)
[IO.File]::WriteAllText($path, $text, $enc)
}
}
}
# ========= START =========
"=== VS Code Autofix started: $(Get-Date) ===" | Out-File $log -Encoding UTF8
Log "Old: $oldUser"
Log "New: $newUser"
Log "BackupDir: $backupDir"
Log ""
Write-Host "Backups -> $backupDir"
Write-Host "Log -> $log"
Write-Host ""
# =========================
# PART A: TEXT FILES
# =========================
Log "=== PART A: Text files ==="
$changedText = 0
$errorsText = 0
$textFiles = Get-ChildItem -Path $textRoots -Recurse -File -Force -ErrorAction SilentlyContinue -Include $include
foreach ($f in $textFiles) {
try {
$bytes = [IO.File]::ReadAllBytes($f.FullName)
$tag = Get-EncTag $bytes
$content = Decode $bytes $tag
if (-not $rx.IsMatch($content)) { continue }
$newContent = $rx.Replace($content, $replacement)
if ($newContent -eq $content) { continue }
$bak = Backup-File $f.FullName
EncodeAndWrite $f.FullName $newContent $tag
Log "TEXT UPDATED: $($f.FullName)"
Log " Backup: $bak"
$changedText++
}
catch {
$errorsText++
Log "TEXT ERROR: $($f.FullName)"
Log " $($_.Exception.Message)"
}
}
Log "Text summary: Changed=$changedText Errors=$errorsText"
Log ""
Write-Host "Text: Changed=$changedText Errors=$errorsText"
# =========================
# PART B: SQLITE DBs (targeted)
# =========================
Log "=== PART B: SQLite DBs (targeted for VS Code schemas) ==="
# verify sqlite3
try {
$ver = & sqlite3 --version 2>$null
if ($LASTEXITCODE -ne 0) { throw "sqlite3 not runnable" }
Log "sqlite3: $ver"
} catch {
Log "ERROR: sqlite3 not found/runnable. Skipping DB updates."
throw
}
$changedDb = 0
$skippedDb = 0
$errorsDb = 0
$dbFiles = Get-ChildItem -Path $dbRoots -Recurse -File -Force -ErrorAction SilentlyContinue |
Where-Object { $dbExt -contains $_.Extension.ToLowerInvariant() }
foreach ($db in $dbFiles) {
try {
# Confirm SQLite + not locked
$probe = & sqlite3 $db.FullName "PRAGMA schema_version;" 2>$null
if ($LASTEXITCODE -ne 0) { $skippedDb++; continue }
# Only operate on DBs that actually have ItemTable (common VS Code state/storage)
$hasItemTable = & sqlite3 $db.FullName "SELECT 1 FROM sqlite_master WHERE type='table' AND name='ItemTable' LIMIT 1;" 2>$null
if ($LASTEXITCODE -ne 0 -or $hasItemTable -ne "1") { $skippedDb++; continue }
# Backup DB
$bak = Backup-File $db.FullName
# Apply replacements in key/value text columns (these exist in VS Code ItemTable)
$sql = @"
BEGIN;
UPDATE ItemTable
SET value = REPLACE(value, 'Users\\$oldUser', 'Users\\$newUser')
WHERE value LIKE '%Users\\$oldUser%';
UPDATE ItemTable
SET value = REPLACE(value, 'Users/$oldUser', 'Users/$newUser')
WHERE value LIKE '%Users/$oldUser%';
UPDATE ItemTable
SET key = REPLACE(key, 'Users\\$oldUser', 'Users\\$newUser')
WHERE key LIKE '%Users\\$oldUser%';
UPDATE ItemTable
SET key = REPLACE(key, 'Users/$oldUser', 'Users/$newUser')
WHERE key LIKE '%Users/$oldUser%';
COMMIT;
"@
# Feed SQL via stdin to avoid PowerShell quoting weirdness
$p = Start-Process -FilePath "sqlite3" -ArgumentList "`"$($db.FullName)`"" -NoNewWindow -PassThru -RedirectStandardInput "pipe" -RedirectStandardError "pipe" -RedirectStandardOutput "pipe"
$p.StandardInput.WriteLine($sql)
$p.StandardInput.Close()
$p.WaitForExit()
if ($p.ExitCode -ne 0) {
$err = $p.StandardError.ReadToEnd()
throw "sqlite3 error: $err"
}
# Optional: vacuum to compact
& sqlite3 $db.FullName "VACUUM;" 2>$null | Out-Null
Log "DB UPDATED: $($db.FullName)"
Log " Backup: $bak"
$changedDb++
}
catch {
$errorsDb++
Log "DB ERROR: $($db.FullName)"
Log " $($_.Exception.Message)"
}
}
Log "DB summary: Updated=$changedDb Skipped=$skippedDb Errors=$errorsDb"
Log "=== VS Code Autofix finished: $(Get-Date) ==="
Write-Host "DB: Updated=$changedDb Skipped=$skippedDb Errors=$errorsDb"
Write-Host "Done."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment