Public/Manage.ps1

# Creating a second profile on a machine that only has one, and renaming profiles
# whose name stopped matching what they hold.

function Assert-CcsProfileName {
    <# Shared validation for anything that names a new profile. #>
    param([Parameter(Mandatory)][string]$Name)

    if ($Name -notmatch '^[A-Za-z0-9._-]+$') {
        throw "Profile name '$Name' must contain only letters, digits, dot, dash or underscore"
    }
    if ($Name -in $script:CcsReservedNames) {
        throw "Profile name '$Name' collides with a ccs subcommand, so 'ccs $Name' could never reach it"
    }
}

function New-CcsBlankProfile {
    <#
    .SYNOPSIS
        Create an empty profile to log a different account into.
    .DESCRIPTION
        Unlike `capture`, this does not clone an existing login: it makes a config
        home whose settings carry your personal preferences but none of the
        provider wiring, so the first `ccs run <name>` asks you to sign in. That is
        how you add a subscription profile to a machine whose ~/.claude is already
        pointed at company Bedrock.
    .PARAMETER From
        Settings to inherit preferences from. Defaults to ~/.claude.
    .PARAMETER Blank
        Start from an empty settings.json instead of inheriting anything.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory)][string]$Name,
        [string]$From = (Get-CcsDefaultClaudeHome),
        [string]$Note = '',
        [switch]$Blank,
        [switch]$Force
    )

    Assert-CcsProfileName -Name $Name

    $target = Get-CcsProfileDir -Name $Name
    if ((Test-Path -LiteralPath $target) -and -not $Force) {
        throw "Profile directory already exists: $target (use -Force to overwrite its settings)"
    }

    $settings = [pscustomobject]@{}
    if (-not $Blank) {
        $sourcePath = Get-CcsSettingsPath -ProfileDir $From
        if (Test-Path -LiteralPath $sourcePath) {
            $settings = Remove-CcsProviderSettings -Settings (Read-CcsJson -Path $sourcePath)
        }
    }

    if (-not $PSCmdlet.ShouldProcess($target, "Create profile '$Name'")) { return }

    New-Item -ItemType Directory -Path $target -Force | Out-Null
    Write-CcsJson -Path (Get-CcsSettingsPath -ProfileDir $target) -Value $settings

    $config = Add-CcsConfigProfile -Config (Get-CcsConfig) -Name $Name -Dir $target -Note $Note
    Save-CcsConfig -Config $config

    Resolve-CcsProfile -Name $Name -Config $config
}

function Rename-CcsProfileEntry {
    <#
    .SYNOPSIS
        Rename a profile, moving its directory when the two names match.
    .DESCRIPTION
        A profile pointing at ~/.claude keeps its directory — only the label
        changes. One living under ~/.claude-profiles is moved so the folder name
        keeps matching the profile name.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory, Position = 0)][string]$Name,
        [Parameter(Mandatory, Position = 1)][string]$NewName
    )

    Assert-CcsProfileName -Name $NewName

    $config = Get-CcsConfig
    if ($config.profiles.PSObject.Properties[$NewName]) {
        throw "A profile named '$NewName' already exists"
    }
    $resolved = Resolve-CcsProfile -Name $Name -Config $config

    if (-not $PSCmdlet.ShouldProcess("$Name -> $NewName", 'Rename profile')) { return }

    $newDir = $resolved.Dir
    $managedDir = Get-CcsProfileDir -Name $Name
    if ((Resolve-CcsConfigDirValue $managedDir) -eq $resolved.Dir) {
        $newDir = Get-CcsProfileDir -Name $NewName
        if (Test-Path -LiteralPath $newDir) { throw "Cannot move profile: $newDir already exists" }
        Move-Item -LiteralPath $resolved.Dir -Destination $newDir
    }

    $stripped = Remove-CcsConfigProfile -Config $config -Name $Name
    $updated = Add-CcsConfigProfile -Config $stripped -Name $NewName -Dir $newDir -Note $resolved.Note
    Save-CcsConfig -Config $updated

    # A shell sitting on the moved directory would now point at nothing.
    if ($env:CLAUDE_CONFIG_DIR -and (Resolve-CcsConfigDirValue $env:CLAUDE_CONFIG_DIR) -eq $resolved.Dir) {
        $env:CLAUDE_CONFIG_DIR = Resolve-CcsConfigDirValue $newDir
    }

    Resolve-CcsProfile -Name $NewName -Config $updated
}