Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified tools/autoclaw-blue-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/autoclaw-green-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/autoclaw-red-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/autoclaw-yellow-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/autoclaw2-blue-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/autoclaw2-green-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/autoclaw2-orange-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/autoclaw2-red-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/autoclaw2-yellow-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/cline-blue-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/cline-green-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/cline-orange-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/cline-red-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/cline-yellow-branding/tray_icon.ico
Binary file not shown.
19 changes: 17 additions & 2 deletions tools/install_autoclaw2_clone_shortcuts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ $ErrorActionPreference = 'Stop'

$scriptPath = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Definition }
$RepoRoot = Split-Path -Parent $scriptPath
# A relative $RepoRoot (bare-filename $MyInvocation fallback) once leaked a
# RELATIVE path into the .lnk IconLocation - Windows cannot resolve a relative
# icon path, so every shortcut rendered BLANK (live bug found 2026-10-29 on
# the Desktop/Start Menu/taskbar icons). Resolve against the current location
# and refuse to continue when the root is not absolute.
$RepoRoot = (Resolve-Path $RepoRoot).ProviderPath
if (-not [System.IO.Path]::IsPathRooted($RepoRoot)) {
throw "repo root resolved non-absolute: '$RepoRoot' - run the installer against the real repo folder"
}
$Launcher = Join-Path $RepoRoot 'src\windows\launch_autoclaw2_clone.ps1'
$Desktop = [Environment]::GetFolderPath('Desktop')
$StartMenu = Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs'
Expand Down Expand Up @@ -198,11 +207,17 @@ foreach ($id in $TargetIds) {

$chk = $sh.CreateShortcut($lnk)
$aumidBack = Get-ShortcutAumid $lnk
# Verify-after covers the icon too: "$path,index" -> the path must be
# ABSOLUTE and exist (a relative IconLocation renders a blank shortcut
# icon - the live bug this suite shipped with, fixed 2026-10-29).
$iconBack = ($chk.IconLocation -replace ',\d+$', '')
$iconOk = ($iconBack -ieq $iconPath) -and [System.IO.Path]::IsPathRooted($iconBack) -and (Test-Path -LiteralPath $iconBack)
$ok = ($chk.TargetPath -eq 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe') -and
($chk.Arguments -match "launch_autoclaw2_clone\.ps1.*-Instance $id") -and
($aumidBack -eq $aumid)
($aumidBack -eq $aumid) -and
$iconOk
if (-not $ok) { $script:Failed = $true }
Write-Host ("{0} : {1} aumid={2}" -f $(if ($ok) {'OK '} else {'FAIL'}), $lnk, $(if ($aumidBack) { $aumidBack } else { '<none>' }))
Write-Host ("{0} : {1} aumid={2} icon={3}" -f $(if ($ok) {'OK '} else {'FAIL'}), $lnk, $(if ($aumidBack) { $aumidBack } else { '<none>' }), $(if ($iconOk) { $iconBack } else { "BAD: $($chk.IconLocation)" }))
}
}

Expand Down
19 changes: 17 additions & 2 deletions tools/install_cline_clone_shortcuts.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ $ErrorActionPreference = 'Stop'

$scriptPath = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Definition }
$RepoRoot = Split-Path -Parent $scriptPath
# A relative $RepoRoot (bare-filename $MyInvocation fallback) once leaked a
# RELATIVE path into the .lnk IconLocation - Windows cannot resolve a relative
# icon path, so every shortcut rendered BLANK (live bug found 2026-10-29 on
# the Desktop/Start Menu/taskbar icons). Resolve against the current location
# and refuse to continue when the root is not absolute.
$RepoRoot = (Resolve-Path $RepoRoot).ProviderPath
if (-not [System.IO.Path]::IsPathRooted($RepoRoot)) {
throw "repo root resolved non-absolute: '$RepoRoot' - run the installer against the real repo folder"
}
$Launcher = Join-Path $RepoRoot 'src\windows\launch_cline_clone.ps1'
$ExePath = Join-Path $env:LOCALAPPDATA 'Cline\cline-app.exe'
$Desktop = [Environment]::GetFolderPath('Desktop')
Expand Down Expand Up @@ -196,10 +205,16 @@ foreach ($id in $TargetIds) {
try { Set-ShortcutAumid -LnkPath $lnk -Aumid $aumid } catch { Write-Warning "AUMID set failed on $lnk : $($_.Exception.Message)" }

$chk = $sh.CreateShortcut($lnk)
# Verify-after covers the icon too: "$path,index" -> the path must be
# ABSOLUTE and exist (a relative IconLocation renders a blank shortcut
# icon - the live bug this suite shipped with, fixed 2026-10-29).
$iconBack = ($chk.IconLocation -replace ',\d+$', '')
$iconOk = ($iconBack -ieq $iconPath) -and [System.IO.Path]::IsPathRooted($iconBack) -and (Test-Path -LiteralPath $iconBack)
$ok = ($chk.TargetPath -eq 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe') -and
($chk.Arguments -match "launch_cline_clone\.ps1.*-Instance $id")
($chk.Arguments -match "launch_cline_clone\.ps1.*-Instance $id") -and
$iconOk
$aumidBack = Get-ShortcutAumid $lnk
Write-Host ("{0} : {1} aumid={2}" -f $(if ($ok) {'OK '} else {'FAIL'}), $lnk, $(if ($aumidBack) { $aumidBack } else { '<none>' }))
Write-Host ("{0} : {1} aumid={2} icon={3}" -f $(if ($ok) {'OK '} else {'FAIL'}), $lnk, $(if ($aumidBack) { $aumidBack } else { '<none>' }), $(if ($iconOk) { $iconBack } else { "BAD: $($chk.IconLocation)" }))
}
}

Expand Down
61 changes: 55 additions & 6 deletions tools/make_clone_icon.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
(-EdgeInsetPercent, drops the soft drop-shadow halo) -> high-quality resample to a
1024 canvas -> optional -HueRotate (degrees; for derived clone colors such as a 4th
color) -> anti-aliased rounded-corner alpha mask (-CornerRadiusPercent) ->
PNG-compressed ICO entries for every size in -Sizes (16..256).
32-bit BMP (BGRA DIB) ICO entries for every size below 256 plus a PNG entry
for 256 - the only layout the Windows shell renders reliably. PNG frames are
officially valid at 256 ONLY: small PNG frames decode as noise or blank in
Explorer and System.Drawing (live bug found 2026-10-29 in EVERY suite this
generator produced - blank Desktop/Start Menu/taskbar shortcut icons; the
zcode ICOs were always correct because make_ghost_icon.ps1 writes DIBs).

Re-runs without -Source reuse the saved icon_windows.png when its corners are
transparent (already-masked master) - regeneration never depends on Downloads.
Expand Down Expand Up @@ -446,11 +451,51 @@ function Convert-MasterToPngBytes {
finally { $out.Dispose() }
}

# BMP (BGRA DIB) frame for every size below 256: BITMAPINFOHEADER + bottom-up
# BGRA rows + an all-zero AND mask (the alpha channel in the XOR plane governs).
# This is the frame format make_ghost_icon.ps1 has always written and the only
# one Explorer renders at small sizes.
function Convert-MasterToDibBytes {
param([System.Drawing.Bitmap]$M, [int]$S)
$out = New-Object System.Drawing.Bitmap ($S), ($S)
try {
$g = [System.Drawing.Graphics]::FromImage($out)
$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
$g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality
$g.DrawImage($M, 0, 0, $S, $S)
$g.Dispose()
$rect = New-Object System.Drawing.Rectangle 0, 0, $S, $S
$data = $out.LockBits($rect, [System.Drawing.Imaging.ImageLockMode]::ReadOnly, [System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
$stride = $data.Stride
$px = New-Object byte[] ($stride * $S)
[System.Runtime.InteropServices.Marshal]::Copy($data.Scan0, $px, 0, $px.Length)
$out.UnlockBits($data)
$ms = New-Object System.IO.MemoryStream
$bw2 = New-Object System.IO.BinaryWriter($ms)
$bw2.Write([uint32]40); $bw2.Write([int32]$S); $bw2.Write([int32]($S * 2))
$bw2.Write([uint16]1); $bw2.Write([uint16]32)
$bw2.Write([uint32]0); $bw2.Write([uint32]($S * $S * 4))
$bw2.Write([int32]0); $bw2.Write([int32]0); $bw2.Write([uint32]0); $bw2.Write([uint32]0)
for ($y = $S - 1; $y -ge 0; $y--) { $bw2.Write($px, $y * $stride, $S * 4) }
$maskStride = [int]([Math]::Ceiling([Math]::Ceiling($S / 8.0) / 4.0) * 4)
$bw2.Write((New-Object byte[] ($maskStride * $S)))
$bw2.Flush()
return ,$ms.ToArray()
}
finally { $out.Dispose() }
}

# --------------------------------------------------------------- write the .ico
Write-Host '[4/5] Writing ICO container...'
$sorted = @($Sizes | Sort-Object)
$pngs = @()
foreach ($s in $sorted) { $pngs += ,(Convert-MasterToPngBytes -M $master -S $s) }
$frames = @()
foreach ($s in $sorted) {
# 256 is the one PNG-legal size; every smaller frame must be a BMP DIB or
# Explorer renders the shortcut icon blank (live bug 2026-10-29).
if ($s -ge 256) { $frames += ,(Convert-MasterToPngBytes -M $master -S $s) }
else { $frames += ,(Convert-MasterToDibBytes -M $master -S $s) }
}

$icoMs = New-Object System.IO.MemoryStream
$bw = New-Object System.IO.BinaryWriter($icoMs)
Expand All @@ -464,11 +509,11 @@ for ($i = 0; $i -lt $sorted.Count; $i++) {
$bw.Write([byte]$dim); $bw.Write([byte]$dim)
$bw.Write([byte]0); $bw.Write([byte]0) # palette, reserved
$bw.Write([uint16]1); $bw.Write([uint16]32) # planes, bpp
$bw.Write([uint32]$pngs[$i].Length)
$bw.Write([uint32]$frames[$i].Length)
$bw.Write([uint32]$offset)
$offset += $pngs[$i].Length
$offset += $frames[$i].Length
}
foreach ($p in $pngs) { $bw.Write($p) }
foreach ($p in $frames) { $bw.Write($p) }
$bw.Flush()
[System.IO.File]::WriteAllBytes($IcoPath, $icoMs.ToArray())
$bw.Dispose(); $icoMs.Dispose()
Expand All @@ -488,6 +533,10 @@ for ($i = 0; $i -lt $vCount; $i++) {
$len = [BitConverter]::ToUInt32($check, 6 + 16 * $i + 8)
$off = [BitConverter]::ToUInt32($check, 6 + 16 * $i + 12)
if ($off + $len -gt $check.Length) { throw ("FAILED: ico entry {0} overruns file" -f $i) }
# frame-format gate: DIB (BITMAPINFOHEADER) below 256, PNG signature at 256
$sig = ('{0:X2} {1:X2} {2:X2} {3:X2}' -f $check[$off], $check[$off + 1], $check[$off + 2], $check[$off + 3])
$want = $(if ($sorted[$i] -ge 256) { '89 50 4E 47' } else { '28 00 00 00' })
if ($sig -ne $want) { throw ("FAILED: ico entry {0} (size {1}) frame sig {2}, expected {3} - shell would render it blank" -f $i, $sorted[$i], $sig, $want) }
$total += $len
}
Write-Host (" [ok] {0} ({1} KB, {2} images: {3}, {4} KB image data)" -f `
Expand Down
Binary file modified tools/opencode-blue-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/opencode-green-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/opencode-orange-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/opencode-red-branding/tray_icon.ico
Binary file not shown.
Binary file modified tools/opencode-yellow-branding/tray_icon.ico
Binary file not shown.
Loading