Public/Tools/Set-WingetSetting.ps1

function Set-WingetSetting {
    <#
    .SYNOPSIS
        Merges a curated set of client preferences into winget's user settings.
 
    .DESCRIPTION
        Writes the winget client settings the profile manages, delegating the actual read and write
        to Microsoft's first-party Microsoft.WinGet.Client module (Get-WinGetUserSetting /
        Set-WinGetUserSetting). It reads the current user settings, sets only the keys you pass into
        their nested objects (creating installBehavior / visual / preferences as needed), and writes
        the full object back, so unrelated settings and the $schema key are preserved. Only the
        parameters you pass are changed.
 
        The module is loaded on demand via Import-ModuleSafe (installed CurrentUser if absent), so it
        is not a hard dependency of profile startup. This is a user-invoked configuration command, but
        it is failure-tolerant by design: if the module can't be loaded or the write fails it emits a
        warning rather than throwing, so it can be called from profile setup without aborting it. It
        honors -WhatIf/-Confirm, so a preview makes no changes.
 
    .PARAMETER Scope
        Default install scope written to installBehavior.preferences.scope: 'user' or 'machine'.
        'user' prefers a per-user installer (no admin prompt) and falls back to machine when a package
        offers no per-user option — it does not hard-require user scope, so installs don't fail.
 
    .PARAMETER ProgressBar
        Progress-bar style written to visual.progressBar: 'accent', 'rainbow', 'retro', 'sixel', or
        'disabled'.
 
    .PARAMETER AnonymizePath
        Whether to set visual.anonymizeDisplayedPaths — replaces known folders with their environment
        variable names (e.g. %LOCALAPPDATA%) in winget output.
 
    .PARAMETER DisableInstallNote
        Whether to set installBehavior.disableInstallNotes — suppresses the notes some packages print
        after a successful install.
 
    .EXAMPLE
        Set-WingetSetting -Scope user -ProgressBar rainbow -AnonymizePath $true -DisableInstallNote $false
 
        Defaults new installs to user scope, keeps the rainbow progress bar, anonymizes displayed
        paths, and leaves install notes enabled — merging into the existing user settings.
 
    .EXAMPLE
        Set-WingetSetting -Scope machine -WhatIf
 
        Previews changing only the default scope to machine, without writing anything.
 
    .NOTES
        Pairs with Get-WingetSettingDefault, which reads the current values back for the install
        wizard's pre-fills. Both go through Microsoft.WinGet.Client.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter()]
        [ValidateSet('user', 'machine')]
        [string]$Scope,

        [Parameter()]
        [ValidateSet('accent', 'rainbow', 'retro', 'sixel', 'disabled')]
        [string]$ProgressBar,

        [Parameter()]
        [bool]$AnonymizePath,

        [Parameter()]
        [bool]$DisableInstallNote
    )

    try {
        Import-ModuleSafe Microsoft.WinGet.Client
        if (-not (Get-Command Set-WinGetUserSetting -ErrorAction SilentlyContinue)) {
            Write-Warning 'Set-WingetSetting: Microsoft.WinGet.Client is unavailable; no changes made.'
            return
        }

        # Read the current user settings (a nested hashtable incl. $schema) so we can write the full
        # object back — preserving every key we don't manage, regardless of merge semantics.
        $current = Get-WinGetUserSetting
        if ($current -isnot [System.Collections.IDictionary]) { $current = @{} }
        if (-not $current.Contains('$schema')) {
            $current['$schema'] = 'https://aka.ms/winget-settings.schema.json'
        }

        # Return (creating if needed) the nested dictionary at $key under $parent.
        $ensureNode = {
            param($parent, $key)
            if ($parent[$key] -isnot [System.Collections.IDictionary]) { $parent[$key] = @{} }
            $parent[$key]
        }

        if ($PSBoundParameters.ContainsKey('Scope')) {
            $prefs = & $ensureNode (& $ensureNode $current 'installBehavior') 'preferences'
            $prefs['scope'] = $Scope
        }
        if ($PSBoundParameters.ContainsKey('DisableInstallNote')) {
            (& $ensureNode $current 'installBehavior')['disableInstallNotes'] = $DisableInstallNote
        }
        if ($PSBoundParameters.ContainsKey('ProgressBar')) {
            (& $ensureNode $current 'visual')['progressBar'] = $ProgressBar
        }
        if ($PSBoundParameters.ContainsKey('AnonymizePath')) {
            (& $ensureNode $current 'visual')['anonymizeDisplayedPaths'] = $AnonymizePath
        }

        if ($PSCmdlet.ShouldProcess('winget user settings', 'Update')) {
            Set-WinGetUserSetting -UserSettings $current | Out-Null
        }
    }
    catch {
        Write-Warning "Set-WingetSetting: failed to update winget user settings: $($_.Exception.Message)"
    }
}