public/Get-WtwList.ps1

function Get-WtwList {
    <#
    .SYNOPSIS
        List all registered repos and worktrees.
    .DESCRIPTION
        Displays a table of all repos and their worktrees with ANSI-colored
        swatches. Detailed mode shows a card layout with clickable file links
        and settings file paths.
    .PARAMETER Repo
        Filter the listing to a specific repo by name or alias.
    .PARAMETER Detailed
        Show card-style output with clickable file links and settings paths.
    .EXAMPLE
        wtw list -d
        Show all repos and worktrees in detailed card layout.
    #>

    [CmdletBinding()]
    param(
        [string] $Repo,

        [Alias('d')]
        [switch] $Detailed
    )

    $registry = Get-WtwRegistry
    $repoNames = $registry.repos.PSObject.Properties.Name

    if (-not $repoNames -or $repoNames.Count -eq 0) {
        Write-Host ' No repos registered. Run "wtw init" inside a repo.' -ForegroundColor Yellow
        return
    }

    $items = @()

    foreach ($name in $repoNames) {
        $repoEntry = $registry.repos.$name
        $aliases = Get-WtwRepoAliases $repoEntry
        if ($Repo -and $Repo -notin $aliases -and $name -ne $Repo) { continue }

        $wsFile = $repoEntry.templateWorkspace
        $wsDisplay = if ($wsFile -and (Test-Path $wsFile)) { Split-Path $wsFile -Leaf } else { '-' }

        # Main entry
        $items += [PSCustomObject]@{
            Kind      = 'repo'
            Repo      = $name
            Aliases   = ($aliases -join ', ')
            Branch    = (git -C $repoEntry.mainPath branch --show-current 2>$null) ?? '?'
            Color     = (Get-WtwColors).assignments."$name/main" ?? '-'
            Path      = $repoEntry.mainPath
            Workspace = $wsDisplay
        }

        # Worktrees
        if ($repoEntry.worktrees) {
            foreach ($taskName in $repoEntry.worktrees.PSObject.Properties.Name) {
                $wt = $repoEntry.worktrees.$taskName
                $exists = Test-Path $wt.path
                $wtWsDisplay = if ($wt.workspace -and (Test-Path $wt.workspace)) { Split-Path $wt.workspace -Leaf } else { '-' }
                $wtAliases = ($aliases | ForEach-Object { "$_-$taskName" }) -join ', '
                $pathDisplay = if ($exists) { $wt.path } else { "$($wt.path) (MISSING)" }

                $items += [PSCustomObject]@{
                    Kind      = ' wt'
                    Repo      = ''
                    Aliases   = $wtAliases
                    Branch    = $wt.branch
                    Color     = $wt.color ?? '-'
                    Path      = $pathDisplay
                    Workspace = $wtWsDisplay
                }
            }
        }
    }

    if ($Detailed) {
        Format-WtwDetailedList $items
    } else {
        Write-Host ''
        Format-WtwTable $items @('Kind', 'Repo', 'Aliases', 'Branch', 'Color', 'Path', 'Workspace')
        Write-Host ''
    }
}

function Format-WtwDetailedList {
    param([array] $Items)

    $esc = [char]27

    Write-Host ''
    Write-Host ' ╔══════════════════════════════════════════╗' -ForegroundColor DarkGray
    Write-Host ' ║ wtw — Worktree & Workspace Registry ║' -ForegroundColor DarkGray
    Write-Host ' ╚══════════════════════════════════════════╝' -ForegroundColor DarkGray
    Write-Host ''

    foreach ($item in $Items) {
        $color = $item.Color
        $isRepo = $item.Kind -eq 'repo'

        if ($isRepo) {
            # Repo header with color swatch
            $swatch = ''
            if ($color -match '^#[0-9a-fA-F]{6}$') {
                $r = [convert]::ToInt32($color.Substring(1, 2), 16)
                $g = [convert]::ToInt32($color.Substring(3, 2), 16)
                $b = [convert]::ToInt32($color.Substring(5, 2), 16)
                $fg = Get-ContrastForeground $color
                $fr = [convert]::ToInt32($fg.Substring(1, 2), 16)
                $fg2 = [convert]::ToInt32($fg.Substring(3, 2), 16)
                $fb = [convert]::ToInt32($fg.Substring(5, 2), 16)
                $swatch = "${esc}[38;2;${fr};${fg2};${fb}m${esc}[48;2;${r};${g};${b}m $($item.Repo) ${esc}[0m"
            } else {
                $swatch = " $($item.Repo)"
            }
            Write-Host " $swatch" -NoNewline
            Write-Host " $($item.Branch)" -ForegroundColor Yellow
            Write-Host " Aliases : $($item.Aliases)" -ForegroundColor Gray
            Write-Host " Path : ${esc}]8;;file://$($item.Path)${esc}\$($item.Path)${esc}]8;;${esc}\" -ForegroundColor Gray
            Write-Host " Workspace : $($item.Workspace)" -ForegroundColor Gray
            Write-Host ''
        } else {
            # Worktree entry (indented)
            $swatch = ''
            if ($color -match '^#[0-9a-fA-F]{6}$') {
                $r = [convert]::ToInt32($color.Substring(1, 2), 16)
                $g = [convert]::ToInt32($color.Substring(3, 2), 16)
                $b = [convert]::ToInt32($color.Substring(5, 2), 16)
                $swatch = "${esc}[48;2;${r};${g};${b}m ${esc}[0m"
            } else {
                $swatch = ' '
            }
            Write-Host " ${swatch} " -NoNewline
            Write-Host "$($item.Branch)" -ForegroundColor Yellow
            Write-Host " Aliases : $($item.Aliases)" -ForegroundColor DarkGray
            Write-Host " Path : ${esc}]8;;file://$($item.Path)${esc}\$($item.Path)${esc}]8;;${esc}\" -ForegroundColor DarkGray
            Write-Host " Workspace : $($item.Workspace)" -ForegroundColor DarkGray
            Write-Host ''
        }
    }

    # Settings file links
    $wtwDir = Join-Path $HOME '.wtw'
    $registryFile = Join-Path $wtwDir 'registry.json'
    $colorsFile = Join-Path $wtwDir 'colors.json'
    $configFile = Join-Path $wtwDir 'config.json'

    Write-Host ' ─── Settings ───' -ForegroundColor DarkGray
    if (Test-Path $registryFile) {
        Write-Host " Registry : ${esc}]8;;file://${registryFile}${esc}\${registryFile}${esc}]8;;${esc}\"  -ForegroundColor DarkCyan
    }
    if (Test-Path $colorsFile) {
        Write-Host " Colors : ${esc}]8;;file://${colorsFile}${esc}\${colorsFile}${esc}]8;;${esc}\" -ForegroundColor DarkCyan
    }
    if (Test-Path $configFile) {
        Write-Host " Config : ${esc}]8;;file://${configFile}${esc}\${configFile}${esc}]8;;${esc}\" -ForegroundColor DarkCyan
    }
    Write-Host ''
}