From 7f0176cbf5fbc5ff5ca2a84b67dcd16a6d3cb865 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Wed, 3 Jun 2026 19:27:34 -0500 Subject: [PATCH] feat: add integration test infra and bootstrapper updates --- .../a670deb9-cd84-4166-a5d9-ed65679c7591.json | 1 + .github/workflows/integration-test.yml | 21 - .gitignore | 10 +- README.md | 21 +- internal/bootstrap/actions.go | 111 +- internal/bootstrap/actions_test.go | 10 +- internal/bootstrap/app.go | 41 +- internal/bootstrap/app_test.go | 30 +- internal/bootstrap/assets/gpu-data.json | 884 ++++++++ .../assets/winutil-sane-default.json | 2 - internal/bootstrap/catalog.go | 192 +- internal/bootstrap/catalog_test.go | 21 +- internal/bootstrap/choco.go | 430 ++++ internal/bootstrap/choco_test.go | 390 ++++ internal/bootstrap/command.go | 20 +- internal/bootstrap/hyperv.go | 9 +- internal/bootstrap/nvidia.go | 132 ++ internal/bootstrap/nvidia_test.go | 98 + internal/bootstrap/options.go | 32 +- internal/bootstrap/options_test.go | 84 +- internal/bootstrap/osconfig.go | 38 +- internal/bootstrap/osconfig_test.go | 50 +- internal/bootstrap/runlog.go | 4 +- internal/bootstrap/winget.go | 146 -- internal/bootstrap/winget_test.go | 167 -- test/integration/README.md | 85 + test/integration/Vagrantfile | 51 + test/integration/main.go | 323 +++ test/integration/packer/.env.example | 26 + test/integration/packer/README.md | 167 ++ test/integration/packer/cd/autounattend.xml | 200 ++ test/integration/packer/install-packer.ps1 | 206 ++ test/integration/packer/load-env.ps1 | 34 + test/integration/packer/packer.err | 0 test/integration/packer/packer.out | 78 + test/integration/packer/packer.pid | 1 + ...919f68b884a6560f42c868004321a22bd.iso.lock | 0 test/integration/packer/scripts/compact.ps1 | 25 + .../packer/scripts/configure-os.ps1 | 28 + .../packer/scripts/disable-defender-cloud.ps1 | 12 + .../scripts/disable-windows-updates.ps1 | 26 + .../packer/scripts/install-vagrant-key.ps1 | 15 + .../packer/vagrantfile-template.rb | 25 + test/integration/packer/windows-11.pkr.hcl | 157 ++ winget_schema.json | 1937 +++++++++++++++++ 45 files changed, 5751 insertions(+), 589 deletions(-) create mode 120000 .antigravitycli/a670deb9-cd84-4166-a5d9-ed65679c7591.json delete mode 100644 .github/workflows/integration-test.yml create mode 100644 internal/bootstrap/assets/gpu-data.json create mode 100644 internal/bootstrap/choco.go create mode 100644 internal/bootstrap/choco_test.go create mode 100644 internal/bootstrap/nvidia.go create mode 100644 internal/bootstrap/nvidia_test.go delete mode 100644 internal/bootstrap/winget.go delete mode 100644 internal/bootstrap/winget_test.go create mode 100644 test/integration/README.md create mode 100644 test/integration/Vagrantfile create mode 100644 test/integration/main.go create mode 100644 test/integration/packer/.env.example create mode 100644 test/integration/packer/README.md create mode 100644 test/integration/packer/cd/autounattend.xml create mode 100644 test/integration/packer/install-packer.ps1 create mode 100644 test/integration/packer/load-env.ps1 create mode 100644 test/integration/packer/packer.err create mode 100644 test/integration/packer/packer.out create mode 100644 test/integration/packer/packer.pid create mode 100644 test/integration/packer/packer_cache/4e9623e919f68b884a6560f42c868004321a22bd.iso.lock create mode 100644 test/integration/packer/scripts/compact.ps1 create mode 100644 test/integration/packer/scripts/configure-os.ps1 create mode 100644 test/integration/packer/scripts/disable-defender-cloud.ps1 create mode 100644 test/integration/packer/scripts/disable-windows-updates.ps1 create mode 100644 test/integration/packer/scripts/install-vagrant-key.ps1 create mode 100644 test/integration/packer/vagrantfile-template.rb create mode 100644 test/integration/packer/windows-11.pkr.hcl create mode 100644 winget_schema.json diff --git a/.antigravitycli/a670deb9-cd84-4166-a5d9-ed65679c7591.json b/.antigravitycli/a670deb9-cd84-4166-a5d9-ed65679c7591.json new file mode 120000 index 0000000..c6faceb --- /dev/null +++ b/.antigravitycli/a670deb9-cd84-4166-a5d9-ed65679c7591.json @@ -0,0 +1 @@ +C:/Users/jasonross/.gemini/config/projects/a670deb9-cd84-4166-a5d9-ed65679c7591.json \ No newline at end of file diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml deleted file mode 100644 index adffaba..0000000 --- a/.github/workflows/integration-test.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: integration-test - -on: - pull_request: - workflow_dispatch: - -jobs: - build-and-run: - name: Build and run - runs-on: windows-latest - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-go@v6 - with: - go-version-file: go.mod - - name: Build - run: | - New-Item -ItemType Directory -Force dist | Out-Null - go build -o dist/bootstrap_windows_env.exe ./cmd/bootstrap_windows_env - - name: Run - run: ./dist/bootstrap_windows_env.exe --yes --headless --no-wsl --no-restore-points diff --git a/.gitignore b/.gitignore index bd273bc..8bb7ee7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,14 @@ -bootstrap_windows_env.exe +*.exe dist/ bin/ *.test coverage coverage.out +test_out.txt +*.log + + +# Local environment overrides (e.g. test/integration/packer/.env). +.env +*.box +.vagrant/ diff --git a/README.md b/README.md index 584f013..33fd02d 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,8 @@ Tagged GitHub releases build and upload a precompiled `bootstrap_windows_env.exe .\bootstrap_windows_env.exe --only wsl .\bootstrap_windows_env.exe --no-ai .\bootstrap_windows_env.exe --no-wsl -.\bootstrap_windows_env.exe --no-restore-points ``` -`--no-restore-points` skips the two System Restore checkpoints in the `os` phase. Use this on Windows Server SKUs (including GitHub Actions `windows-latest` runners), where `Checkpoint-Computer` is not supported. - ## Phases `os` runs before any application installation. It invokes Windows Update/Microsoft Update, stops for reboot when required, creates a restore point, runs Chris Titus Tech WinUtil with the managed sane-default config, enables Developer Mode and Windows sudo, applies power/update/UI/store/taskbar defaults, then creates a second restore point before package installation. @@ -49,6 +46,24 @@ Visual Studio Community 2026 is installed as `Microsoft.VisualStudio.Community` `wsl` enables WSL prerequisites, installs the current official `FedoraLinux-*` distro reported by `wsl --list --online`, stops for reboot or first-launch username creation when needed, then invokes the latest Linux bootstrap release with `--wsl --headless --yes`. +## Tests + +Unit tests run on every pull request via `.github/workflows/unit-test.yml`: + +```powershell +go test ./... +``` + +End-to-end integration runs against a real Windows client VM through Vagrant + +Hyper-V. It is not run in CI (GitHub-hosted runners are Windows Server and have +no Hyper-V), so execute it locally: + +```powershell +go run ./test/integration +``` + +See `test/integration/README.md` for prerequisites, flags, and tuning options. + ## Current Deferrals `Webcamoid` is deferred because no exact `winget` manifest was available during implementation. Native Docker Desktop, Podman Desktop, Buildah, Minikube, Firecracker, QEMU, virt-manager, Windows Terminal, and VS Code are also intentionally excluded from Windows v1. diff --git a/internal/bootstrap/actions.go b/internal/bootstrap/actions.go index d0666e6..800db81 100644 --- a/internal/bootstrap/actions.go +++ b/internal/bootstrap/actions.go @@ -19,7 +19,7 @@ type Action struct { AI bool } -const refreshPath = `$env:Path=[Environment]::GetEnvironmentVariable('Path','Machine')+';'+[Environment]::GetEnvironmentVariable('Path','User'); ` +const refreshPath = `$env:Path=[Environment]::GetEnvironmentVariable('Path','Machine')+';'+[Environment]::GetEnvironmentVariable('Path','User')+';C:\ProgramData\chocolatey\bin'; if (Get-Command fnm -ErrorAction SilentlyContinue) { fnm env --shell powershell | Invoke-Expression }; ` func powerShell(script string) CommandSpec { return CommandSpec{ @@ -32,21 +32,63 @@ func checkedNativePowerShell(command string) CommandSpec { return powerShell(`$ErrorActionPreference='Stop'; ` + command + `; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }`) } -func HostActions() []Action { - return []Action{ +func HostActions(opts Options) []Action { + actions := []Action{ { - Name: "Node.js LTS through fnm", + Name: "Visual Studio Community 2026", Phase: PhaseHost, - Probe: checkedNativePowerShell(`fnm exec --using=lts-latest node --version`), + Probe: powerShell(`if (Test-Path "${env:ProgramFiles}\Microsoft Visual Studio\2026\Community\Common7\IDE\devenv.exe") { exit 0 } else { exit 1 }`), Commands: []CommandSpec{ - checkedNativePowerShell(`fnm install --lts`), - checkedNativePowerShell(`fnm default lts-latest`), + powerShell(fmt.Sprintf( + `$tempExe = Join-Path $env:TEMP 'vs_community.exe'; `+ + `if (Test-Path $tempExe) { Remove-Item -Force $tempExe }; `+ + `[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; `+ + `Write-Host 'Downloading Visual Studio 2026 bootstrapper...'; `+ + `Invoke-WebRequest -Uri 'https://aka.ms/vs/17/release/vs_community.exe' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop; `+ + `Unblock-File -Path $tempExe; `+ + `Write-Host 'Installing Visual Studio 2026 with workloads...'; `+ + `$p = Start-Process -FilePath $tempExe -ArgumentList '--passive --wait --config "%s"' -Wait -PassThru; `+ + `if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) { throw 'Visual Studio installation failed with exit code ' + $p.ExitCode }`, + mustInstallAssetPath("assets/visual-studio-community.vsconfig"), + )), + }, + }, + { + Name: "fnm and Node.js LTS", + Phase: PhaseHost, + Probe: powerShell(`fnm exec --using=lts-latest node --version | Out-Null; if ($LASTEXITCODE -ne 0) { exit 1 }`), + Commands: []CommandSpec{ + powerShell(`$ErrorActionPreference='Stop' +function Invoke-Native { + param([Parameter(Mandatory=$true)][string]$File, [Parameter(Mandatory=$true)][string[]]$Arguments) + & $File @Arguments + if ($LASTEXITCODE -ne 0) { + throw "$File $($Arguments -join ' ') failed with exit code $LASTEXITCODE" + } +} +$scoop = Get-Command scoop -ErrorAction SilentlyContinue +$scoopShim = Join-Path $HOME 'scoop\shims\scoop.ps1' +if ($scoop) { + Invoke-Native $scoop.Source @('install', 'fnm') +} elseif (Test-Path $scoopShim) { + Invoke-Native $scoopShim @('install', 'fnm') +} elseif (Get-Command choco -ErrorAction SilentlyContinue) { + Invoke-Native 'choco' @('install', 'fnm', '-y', '--no-progress') +} else { + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + Invoke-RestMethod -Uri 'https://community.chocolatey.org/install.ps1' | Invoke-Expression + $env:Path=[Environment]::GetEnvironmentVariable('Path','Machine')+';'+[Environment]::GetEnvironmentVariable('Path','User') + Invoke-Native 'choco' @('install', 'fnm', '-y', '--no-progress') +} +$env:Path=[Environment]::GetEnvironmentVariable('Path','Machine')+';'+[Environment]::GetEnvironmentVariable('Path','User') +Invoke-Native 'fnm' @('install', '--lts') +Invoke-Native 'fnm' @('default', 'lts-latest')`), }, }, { Name: "pyenv-win through Scoop or Chocolatey", Phase: PhaseHost, - Probe: checkedNativePowerShell(`pyenv --version`), + Probe: powerShell(`pyenv --version | Out-Null; if ($LASTEXITCODE -ne 0) { exit 1 }`), Commands: []CommandSpec{ powerShell(`$ErrorActionPreference='Stop' function Invoke-Native { @@ -65,7 +107,8 @@ if ($scoop) { } elseif (Get-Command choco -ErrorAction SilentlyContinue) { Invoke-Native 'choco' @('install', 'pyenv-win', '-y', '--no-progress') } else { - Invoke-Native 'winget' @('install', '--id', 'Chocolatey.Chocolatey', '--exact', '--source', 'winget', '--accept-source-agreements', '--accept-package-agreements', '--disable-interactivity') + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + Invoke-RestMethod -Uri 'https://community.chocolatey.org/install.ps1' | Invoke-Expression $env:Path=[Environment]::GetEnvironmentVariable('Path','Machine')+';'+[Environment]::GetEnvironmentVariable('Path','User') Invoke-Native 'choco' @('install', 'pyenv-win', '-y', '--no-progress') }`), @@ -74,7 +117,7 @@ if ($scoop) { { Name: "latest stable Python through pyenv-win", Phase: PhaseHost, - Probe: powerShell(`$v = pyenv version-name 2>$null; if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($v) -or $v.Trim() -eq 'system') { exit 1 }`), + Probe: powerShell(`$v = pyenv version-name; if ([string]::IsNullOrWhiteSpace($v) -or $v -eq 'system') { exit 1 }`), Commands: []CommandSpec{ powerShell(`$ErrorActionPreference='Stop' function Invoke-Native { @@ -84,20 +127,34 @@ function Invoke-Native { throw "$File $($Arguments -join ' ') failed with exit code $LASTEXITCODE" } } -$v=(pyenv install --list | Select-String '^\s*3\.\d+\.\d+\s*$' | ForEach-Object {$_.Line.Trim()} | Sort-Object {[version]$_} -Descending | Select-Object -First 1) -if (-not $v) { throw 'no stable Python version found' } +$env:Path=[Environment]::GetEnvironmentVariable('Path','Machine')+';'+[Environment]::GetEnvironmentVariable('Path','User') +$out = Invoke-Native 'pyenv' @('install', '-l') +$v = $out -split '\r?\n' | Where-Object { $_ -match '^\s*3\.\d+\.\d+\s*$' } | Sort-Object -Descending | Select-Object -First 1 +if (-not $v) { throw 'No stable Python 3.x version found' } +$v = $v.Trim() Invoke-Native 'pyenv' @('install', '-s', $v) -Invoke-Native 'pyenv' @('global', $v)`), +Invoke-Native 'pyenv' @('global', $v) +Invoke-Native 'pyenv' @('exec', 'python', '-m', 'pip', 'install', '--upgrade', 'pip') +`), }, }, { - Name: "VLC default media player associations", + Name: "semgrep", Phase: PhaseHost, - Probe: powerShell(`$marker = Join-Path $env:ProgramData 'bootstrap_windows_env\vlc-default-media.done'; if (-not (Test-Path $marker)) { exit 1 }`), + Probe: powerShell(`$env:Path=[Environment]::GetEnvironmentVariable('Path','Machine')+';'+[Environment]::GetEnvironmentVariable('Path','User'); pyenv exec semgrep --version | Out-Null; if ($LASTEXITCODE -ne 0) { exit 1 }`), Commands: []CommandSpec{ - powerShell(`$ErrorActionPreference='Stop' -$stateDir = Join-Path $env:ProgramData 'bootstrap_windows_env' -New-Item -ItemType Directory -Force -Path $stateDir | Out-Null + checkedNativePowerShell(`$env:Path=[Environment]::GetEnvironmentVariable('Path','Machine')+';'+[Environment]::GetEnvironmentVariable('Path','User'); pyenv exec pip install semgrep`), + }, + }, + } + + actions = append(actions, Action{ + Name: "VLC default media player associations", + Phase: PhaseHost, + Probe: powerShell(`$stateDir = Join-Path $env:ProgramData 'bootstrap_windows_env'; if (-not (Test-Path (Join-Path $stateDir 'vlc-default-media.done'))) { exit 1 }`), + Commands: []CommandSpec{ + powerShell(`$stateDir = Join-Path $env:ProgramData 'bootstrap_windows_env' +if (-not (Test-Path $stateDir)) { New-Item -ItemType Directory -Force -Path $stateDir | Out-Null } $vlcPaths = @( (Join-Path $env:ProgramFiles 'VideoLAN\VLC\vlc.exe'), (Join-Path ${env:ProgramFiles(x86)} 'VideoLAN\VLC\vlc.exe') @@ -106,8 +163,7 @@ if ($vlcPaths.Count -eq 0 -and -not (Get-Command vlc.exe -ErrorAction SilentlyCo throw 'VLC is not installed or is not discoverable.' } $extensions = @( - '.3g2', '.3gp', '.aac', '.aiff', '.alac', '.amr', '.ape', '.asf', '.au', - '.avi', '.divx', '.flac', '.flv', '.m2ts', '.m4a', '.m4v', '.mka', '.mkv', + '.3g2', '.3gp', '.3gp2', '.3gpp', '.amv', '.asf', '.avi', '.divx', '.flac', '.flv', '.m2ts', '.m4a', '.m4v', '.mka', '.mkv', '.mov', '.mp2', '.mp3', '.mp4', '.mp4v', '.mpeg', '.mpg', '.mts', '.oga', '.ogg', '.ogm', '.ogv', '.opus', '.ts', '.vob', '.wav', '.webm', '.wma', '.wmv' ) @@ -149,9 +205,10 @@ if ($LASTEXITCODE -ne 0) { } Set-Content -Path (Join-Path $stateDir 'vlc-default-media.done') -Value (Get-Date -Format o) -Encoding UTF8 Write-Output "Imported VLC default media associations from $xmlPath. Windows may still require user confirmation for an existing signed-in profile."`), - }, }, - } + }) + + return actions } func CustomActions(opts Options) []Action { @@ -170,8 +227,8 @@ func CustomActions(opts Options) []Action { Phase: PhaseCustom, Probe: powerShell(`npm list --global playwright --depth=0 | Out-Null; if ($LASTEXITCODE -ne 0) { exit 1 }`), Commands: []CommandSpec{ - checkedNativePowerShell(`fnm exec --using=lts-latest npm install --global playwright`), - checkedNativePowerShell(`fnm exec --using=lts-latest playwright install`), + checkedNativePowerShell(`npm install --global playwright`), + checkedNativePowerShell(`playwright install`), }, }, { @@ -188,7 +245,7 @@ func CustomActions(opts Options) []Action { AI: true, Probe: powerShell(`npm list --global '@anthropic-ai/claude-code' --depth=0 | Out-Null; if ($LASTEXITCODE -ne 0) { exit 1 }`), Commands: []CommandSpec{ - checkedNativePowerShell(`fnm exec --using=lts-latest npm install --global '@anthropic-ai/claude-code'`), + checkedNativePowerShell(`npm install --global '@anthropic-ai/claude-code'`), }, }, { @@ -197,7 +254,7 @@ func CustomActions(opts Options) []Action { AI: true, Probe: powerShell(`npm list --global '@openai/codex' --depth=0 | Out-Null; if ($LASTEXITCODE -ne 0) { exit 1 }`), Commands: []CommandSpec{ - checkedNativePowerShell(`fnm exec --using=lts-latest npm install --global '@openai/codex'`), + checkedNativePowerShell(`npm install --global '@openai/codex'`), }, }, { @@ -206,7 +263,7 @@ func CustomActions(opts Options) []Action { AI: true, Probe: powerShell(`npm list --global '@github/copilot' --depth=0 | Out-Null; if ($LASTEXITCODE -ne 0) { exit 1 }`), Commands: []CommandSpec{ - checkedNativePowerShell(`fnm exec --using=lts-latest npm install --global '@github/copilot'`), + checkedNativePowerShell(`npm install --global '@github/copilot'`), }, }, } diff --git a/internal/bootstrap/actions_test.go b/internal/bootstrap/actions_test.go index ea4c69d..984a4cc 100644 --- a/internal/bootstrap/actions_test.go +++ b/internal/bootstrap/actions_test.go @@ -27,12 +27,12 @@ func TestCustomActionsNoAIStillKeepsPlaywrightAndExtension(t *testing.T) { } func TestRuntimeAndCustomDependencyOrdering(t *testing.T) { - host := HostActions() - if len(host) != 4 || host[0].Name != "Node.js LTS through fnm" || host[1].Name != "pyenv-win through Scoop or Chocolatey" || host[2].Name != "latest stable Python through pyenv-win" || host[3].Name != "VLC default media player associations" { + host := HostActions(Options{}) + if len(host) != 6 || host[0].Name != "Visual Studio Community 2026" || host[1].Name != "fnm and Node.js LTS" || host[2].Name != "pyenv-win through Scoop or Chocolatey" || host[3].Name != "latest stable Python through pyenv-win" || host[4].Name != "semgrep" || host[5].Name != "VLC default media player associations" { t.Fatalf("unexpected host action order: %#v", host) } - pyenvInstall := strings.Join(host[1].Commands[0].Args, " ") - for _, want := range []string{"scoop", "Invoke-Native 'choco' @('install', 'pyenv-win'", "Chocolatey.Chocolatey"} { + pyenvInstall := strings.Join(host[2].Commands[0].Args, " ") + for _, want := range []string{"scoop", "Invoke-Native 'choco' @('install', 'pyenv-win'", "community.chocolatey.org"} { if !strings.Contains(pyenvInstall, want) { t.Fatalf("pyenv install command missing %q: %s", want, pyenvInstall) } @@ -57,7 +57,7 @@ func TestRuntimeAndCustomDependencyOrdering(t *testing.T) { } func TestVLCDefaultMediaActionCoversCommonAudioVideoExtensions(t *testing.T) { - host := HostActions() + host := HostActions(Options{}) vlc := host[len(host)-1] script := strings.Join(vlc.Commands[0].Args, " ") for _, want := range []string{ diff --git a/internal/bootstrap/app.go b/internal/bootstrap/app.go index 6edf4d1..e404d55 100644 --- a/internal/bootstrap/app.go +++ b/internal/bootstrap/app.go @@ -62,7 +62,7 @@ func BuildPlanForPhases(ctx context.Context, runner Runner, opts Options, phases } switch phase { case PhaseHost: - actions := HostActions() + actions := HostActions(opts) if checkState { plan.ActionStates[phase] = CheckActions(ctx, runner, actions) } else { @@ -93,7 +93,7 @@ func PrintPlan(out io.Writer, plan Plan, opts Options) { } else if state.CheckErr != nil { status = "check failed; will retry install" } - fmt.Fprintf(out, " winget: %s (%s) - %s\n", state.Package.Name, state.Package.WingetID, status) + fmt.Fprintf(out, " choco: %s (%s) - %s\n", state.Package.Name, state.Package.ChocoID, status) } } actions := plan.ActionStates[phase] @@ -106,13 +106,8 @@ func PrintPlan(out io.Writer, plan Plan, opts Options) { } if phase == PhaseOS { fmt.Fprintln(out, " os: install Windows/Microsoft updates and stop before packages if reboot is required") - if opts.NoRestorePoints { - fmt.Fprintln(out, " os: skip System Restore checkpoints (--no-restore-points)") - fmt.Fprintln(out, " os: run WinUtil config, apply developer/power/update/UI/store/taskbar defaults") - } else { - fmt.Fprintln(out, " os: create restore point, run WinUtil config, apply developer/power/update/UI/store/taskbar defaults") - fmt.Fprintln(out, " os: create second restore point before host package installation") - } + fmt.Fprintln(out, " os: create restore point, run WinUtil config, apply developer/power/update/UI/store/taskbar defaults") + fmt.Fprintln(out, " os: create second restore point before host package installation") } if phase == PhaseConfig { fmt.Fprintln(out, " config: deploy managed WezTerm, PowerShell, oh-my-posh, and Neovim config") @@ -127,9 +122,6 @@ func PrintPlan(out io.Writer, plan Plan, opts Options) { } func (b *Bootstrapper) Run(ctx context.Context, opts Options) (runErr error) { - if b.Runner == nil { - b.Runner = ExecRunner{Timeout: 45 * time.Minute} - } if b.In == nil { b.In = os.Stdin } @@ -139,6 +131,9 @@ func (b *Bootstrapper) Run(ctx context.Context, opts Options) (runErr error) { if b.Err == nil { b.Err = os.Stderr } + if b.Runner == nil { + b.Runner = ExecRunner{Timeout: 45 * time.Minute, Stream: b.Out} + } phases := SelectedPhases(opts) report := NewRunReport(opts, phases) @@ -185,16 +180,21 @@ func (b *Bootstrapper) Run(ctx context.Context, opts Options) (runErr error) { PrintPlan(b.Out, plan, opts) issues = append(issues, b.executeCheckedPlan(ctx, plan, opts, report)...) } - return issues.Err() + } else { + issues = append(issues, b.executeCheckedPlan(ctx, plan, opts, report)...) + } + + if opts.Includes(PhaseConfig) { + authIssues := b.offerInteractiveAuth(ctx, opts) + b.recordIssues(report, &issues, authIssues) } - issues = append(issues, b.executeCheckedPlan(ctx, plan, opts, report)...) return issues.Err() } func (b *Bootstrapper) runOSPhase(ctx context.Context, report *RunReport) OSPhaseResult { report.Event("phase os started") - result := RunOSPhase(ctx, b.Runner, report.Options.NoRestorePoints) + result := RunOSPhase(ctx, b.Runner) for _, notice := range result.Notices { b.recordNotice(report, notice) } @@ -305,14 +305,14 @@ func (b *Bootstrapper) runConfigPhase(ctx context.Context, opts Options) Issues if !IsEmptyIssue(issue) { issues = append(issues, issue) } - if !opts.Headless { - issues = append(issues, b.offerInteractiveAuth(ctx)...) - } return issues } -func (b *Bootstrapper) offerInteractiveAuth(ctx context.Context) Issues { +func (b *Bootstrapper) offerInteractiveAuth(ctx context.Context, opts Options) Issues { var issues Issues + if opts.Yes || IsSessionZero() { + return issues + } if result := b.Runner.Run(ctx, "gh", "auth", "status"); result.Err != nil { if confirm(b.In, b.Out, "Run `gh auth login` now? [y/N] ") { login := b.Runner.Run(ctx, "gh", "auth", "login") @@ -346,6 +346,9 @@ func (b *Bootstrapper) offerInteractiveAuth(ctx context.Context) Issues { } func confirm(in io.Reader, out io.Writer, prompt string) bool { + if in == nil { + return false + } fmt.Fprint(out, prompt) scanner := bufio.NewScanner(in) if !scanner.Scan() { diff --git a/internal/bootstrap/app_test.go b/internal/bootstrap/app_test.go index 1adf9f9..f9a3f31 100644 --- a/internal/bootstrap/app_test.go +++ b/internal/bootstrap/app_test.go @@ -25,7 +25,7 @@ func TestRunWithOSDoesNotProbePackagesBeforeWindowsUpdate(t *testing.T) { }, } - if err := app.Run(context.Background(), Options{Yes: true, NoWSL: true, Headless: true}); err != nil { + if err := app.Run(context.Background(), Options{Yes: true, NoWSL: true}); err != nil { t.Fatal(err) } @@ -65,7 +65,7 @@ func TestRunStopsAfterOSRebootNotice(t *testing.T) { Err: &bytes.Buffer{}, Paths: testUserPaths(temp), } - if err := app.Run(context.Background(), Options{Yes: true, NoWSL: true, Headless: true}); err != nil { + if err := app.Run(context.Background(), Options{Yes: true, NoWSL: true}); err != nil { t.Fatal(err) } if !strings.Contains(out.String(), "require a reboot") { @@ -90,7 +90,7 @@ func TestNewBootstrapperInitializesDefaults(t *testing.T) { } func TestBuildPlanWrapperAndPrintPlanShowStatuses(t *testing.T) { - pkg := Package{Name: "Git", WingetID: "Git.Git", WingetSource: "winget", Phase: PhaseHost} + pkg := Package{Name: "Git", ChocoID: "git", Phase: PhaseHost} action := Action{Name: "done action"} plan := BuildPlan(context.Background(), &fakeRunner{}, Options{Only: PhaseOS}) if len(plan.Phases) != 1 || plan.Phases[0] != PhaseOS { @@ -103,7 +103,7 @@ func TestBuildPlanWrapperAndPrintPlanShowStatuses(t *testing.T) { PackageStates: map[Phase][]PackageState{ PhaseHost: { {Package: pkg, Installed: true}, - {Package: Package{Name: "Broken", WingetID: "Broken.ID"}, CheckErr: errors.New("check failed")}, + {Package: Package{Name: "Broken", ChocoID: "Broken.ID"}, CheckErr: errors.New("check failed")}, }, }, ActionStates: map[Phase][]ActionState{ @@ -174,7 +174,7 @@ func TestRunOnlyHostSkipsOSAndExecutesHostPlan(t *testing.T) { Err: &bytes.Buffer{}, Paths: testUserPaths(temp), } - if err := app.Run(context.Background(), Options{Only: PhaseHost, Yes: true, Headless: true}); err != nil { + if err := app.Run(context.Background(), Options{Only: PhaseHost, Yes: true}); err != nil { t.Fatal(err) } update := WindowsUpdateCommand() @@ -263,7 +263,7 @@ func TestRunConfigPhaseRecordsDeploymentIssue(t *testing.T) { Documents: filepath.Join(temp, "docs"), }, } - issues := app.runConfigPhase(context.Background(), Options{Headless: true}) + issues := app.runConfigPhase(context.Background(), Options{}) if len(issues) == 0 || !strings.Contains(issues[0].Step, "deploy managed config") { t.Fatalf("issues = %#v, want deployment issue", issues) } @@ -280,13 +280,13 @@ func TestRunConfigPhaseRecordsNeovimIssue(t *testing.T) { Err: &bytes.Buffer{}, Paths: testUserPaths(temp), } - issues := app.runConfigPhase(context.Background(), Options{Headless: true}) + issues := app.runConfigPhase(context.Background(), Options{}) if len(issues) != 1 || issues[0].Step != "clone Neovim config" { t.Fatalf("issues = %#v, want Neovim clone issue", issues) } } -func TestRunConfigPhaseOffersAuthWhenInteractive(t *testing.T) { +func TestRunOffersAuthWhenInteractive(t *testing.T) { temp := t.TempDir() pub := filepath.Join(temp, "home", ".ssh", "id_ed25519.pub") if err := os.MkdirAll(filepath.Dir(pub), 0o755); err != nil { @@ -297,13 +297,13 @@ func TestRunConfigPhaseOffersAuthWhenInteractive(t *testing.T) { } app := &Bootstrapper{ Runner: &fakeRunner{}, - In: strings.NewReader(""), + In: strings.NewReader("y\n"), Out: &bytes.Buffer{}, Err: &bytes.Buffer{}, Paths: testUserPaths(temp), } - if issues := app.runConfigPhase(context.Background(), Options{}); issues.Err() != nil { - t.Fatalf("issues = %#v", issues) + if err := app.Run(context.Background(), Options{Only: PhaseConfig}); err != nil { + t.Fatalf("Run err = %v", err) } if !app.Runner.(*fakeRunner).called("gh", "auth", "status") { t.Fatal("expected interactive auth status check") @@ -351,7 +351,7 @@ func TestOfferInteractiveAuthCoversLoginFailure(t *testing.T) { Err: &bytes.Buffer{}, Paths: UserPaths{Home: temp}, } - issues := app.offerInteractiveAuth(context.Background()) + issues := app.offerInteractiveAuth(context.Background(), Options{}) if len(issues) != 1 || issues[0].Step != "gh auth login" { t.Fatalf("issues = %#v, want login failure", issues) } @@ -374,7 +374,7 @@ func TestOfferInteractiveAuthCoversSSHUploadFailure(t *testing.T) { Err: &bytes.Buffer{}, Paths: UserPaths{Home: temp}, } - issues := app.offerInteractiveAuth(context.Background()) + issues := app.offerInteractiveAuth(context.Background(), Options{}) if len(issues) != 1 || issues[0].Step != "gh ssh-key add" { t.Fatalf("issues = %#v, want upload failure", issues) } @@ -398,7 +398,7 @@ func TestOfferInteractiveAuthCoversSSHDirectoryAndKeygenFailures(t *testing.T) { Err: &bytes.Buffer{}, Paths: UserPaths{Home: homeFile}, } - issues := app.offerInteractiveAuth(context.Background()) + issues := app.offerInteractiveAuth(context.Background(), Options{}) if len(issues) != 1 || issues[0].Step != "create SSH directory" { t.Fatalf("issues = %#v, want SSH directory failure", issues) } @@ -417,7 +417,7 @@ func TestOfferInteractiveAuthCoversSSHDirectoryAndKeygenFailures(t *testing.T) { Err: &bytes.Buffer{}, Paths: UserPaths{Home: filepath.Join(temp, "home2")}, } - issues = app.offerInteractiveAuth(context.Background()) + issues = app.offerInteractiveAuth(context.Background(), Options{}) if len(issues) != 1 || issues[0].Step != "ssh-keygen" { t.Fatalf("issues = %#v, want ssh-keygen failure", issues) } diff --git a/internal/bootstrap/assets/gpu-data.json b/internal/bootstrap/assets/gpu-data.json new file mode 100644 index 0000000..0cfc2a2 --- /dev/null +++ b/internal/bootstrap/assets/gpu-data.json @@ -0,0 +1,884 @@ +{ + "desktop": { + "GeForce 8800 Ultra": "8", + "GeForce 8800 GTX": "7", + "GeForce 8800 GTS 512": "270", + "GeForce 8800 GTS": "6", + "GeForce 8800 GT": "258", + "GeForce 8800 GS": "281", + "GeForce 8600 GTS": "5", + "GeForce 8600 GT": "4", + "GeForce 8600 GS": "233", + "GeForce 8500 GT": "3", + "GeForce 8400 GS": "2", + "GeForce 8400 SE": "234", + "GeForce 8400": "272", + "GeForce 8300 GS": "1", + "GeForce 8300": "288", + "GeForce 8200": "293", + "GeForce 8100": "290", + "GeForce 7025": "9", + "GeForce 7050 PV": "10", + "GeForce 7050": "238", + "GeForce 7100": "263", + "GeForce 7100 GS": "11", + "GeForce 7150": "240", + "GeForce 7300 SE": "15", + "GeForce 7300 LE": "14", + "GeForce 7300 GS": "12", + "GeForce 7300 GT": "13", + "GeForce 7350 LE": "16", + "GeForce 7500 LE": "17", + "GeForce 7550 LE": "18", + "GeForce 7600 LE": "21", + "GeForce 7600 GS": "19", + "GeForce 7600 GT": "20", + "GeForce 7650 GS": "22", + "GeForce 7800 GT": "648", + "GeForce 7800 GS": "23", + "GeForce 7800 GTX": "24", + "GeForce 7800 SLI": "25", + "GeForce 7900 GS": "26", + "GeForce 7900 GT": "27", + "GeForce 7900 GTX": "28", + "GeForce 7950 GT": "29", + "GeForce 7950 GX2": "30", + "GeForce 6100": "31", + "GeForce 6100 nForce 400": "32", + "GeForce 6100 nForce 405": "33", + "GeForce 6100 nForce 420": "34", + "GeForce 6150": "35", + "GeForce 6150 LE": "36", + "GeForce 6150LE": "262", + "GeForce 6150SE nForce 430": "37", + "GeForce 6200": "38", + "GeForce 6200 A-LE": "39", + "GeForce 6200 LE": "40", + "GeForce 6200 TurboCache(TM)": "41", + "GeForce 6200SE TurboCache(TM)": "42", + "GeForce 6250": "43", + "GeForce 6500": "44", + "GeForce 6600": "45", + "GeForce 6600 GT": "46", + "GeForce 6600 LE": "47", + "GeForce 6600 VE": "48", + "GeForce 6610 XL": "49", + "GeForce 6700 XL": "50", + "GeForce 6800": "51", + "GeForce 6800 GS": "53", + "GeForce 6800 GT": "54", + "GeForce 6800 LE": "55", + "GeForce 6800 Ultra": "56", + "GeForce 6800 XE": "57", + "GeForce 6800 XT": "58", + "GeForce FX 5100": "59", + "GeForce FX 5200": "60", + "GeForce FX 5200 Ultra": "61", + "GeForce FX 5200LE": "62", + "GeForce FX 5500": "63", + "GeForce FX 5600": "64", + "GeForce FX 5600 Ultra": "65", + "GeForce FX 5600XT": "66", + "GeForce FX 5700": "67", + "GeForce FX 5700 Ultra": "68", + "GeForce FX 5700LE": "69", + "GeForce FX 5700VE": "70", + "GeForce FX 5800": "71", + "GeForce FX 5800 Ultra": "72", + "GeForce FX 5900": "73", + "GeForce FX 5900 Ultra": "74", + "GeForce FX 5900XT": "75", + "GeForce FX 5900ZT": "76", + "GeForce FX 5950 Ultra": "77", + "GeForce PCX 5300": "78", + "GeForce PCX 5750": "79", + "GeForce PCX 5900": "80", + "nForce 680i SLI": "177", + "nForce 680i LT SLI": "178", + "nForce 650i SLI": "179", + "nForce 650i Ultra": "180", + "nForce 630i": "256", + "nForce 610i": "257", + "nForce 680a SLI": "181", + "nForce 630a": "243", + "nForce 590 SLI Intel": "182", + "nForce 570 SLI Intel": "183", + "nForce 590 SLI AMD": "184", + "nForce 570 SLI AMD": "185", + "nForce 570 Ultra AMD": "186", + "nForce 560": "224", + "nForce 550": "187", + "nForce 520": "190", + "nForce4 SLI X16 Intel": "191", + "nForce4 SLI Intel": "192", + "nForce4 SLI XE Intel": "193", + "nForce4 Ultra Intel": "194", + "nForce4 SLI X16 AMD": "195", + "nForce4 SLI AMD": "196", + "nForce4 Ultra AMD": "197", + "nForce4 AMD": "198", + "nForce 430": "206", + "nForce 410": "204", + "nForce 405": "207", + "nForce 400": "208", + "nForce 420": "209", + "nForce Professional 2200": "210", + "nForce Professional 22200": "211", + "nForce Professional 3600": "214", + "nForce Professional 3400": "213", + "Quadro Plex S Series": "302", + "Quadro Plex Model II": "82", + "Quadro Plex D Series": "301", + "Quadro Plex Model IV": "84", + "Quadro Plex 7000": "534", + "Quadro CX": "318", + "Quadro FX 330": "107", + "Quadro FX 350": "85", + "Quadro FX 370": "245", + "Quadro FX 370 Low Profile": "333", + "Quadro FX 380": "412", + "Quadro FX 380 Low Profile": "469", + "Quadro FX 470": "319", + "Quadro FX 500": "86", + "Quadro FX 540": "87", + "Quadro FX 550": "88", + "Quadro FX 560": "89", + "Quadro FX 570": "246", + "Quadro FX 580": "413", + "Quadro FX 700": "90", + "Quadro FX 1000": "91", + "Quadro FX 1100": "92", + "Quadro FX 1300": "93", + "Quadro FX 1400": "94", + "Quadro FX 1500": "95", + "Quadro FX 1700": "247", + "Quadro FX 1800": "411", + "Quadro FX 2000": "96", + "Quadro FX 3000": "97", + "Quadro FX 3400": "98", + "Quadro FX 3450": "306", + "Quadro FX 3500": "100", + "Quadro FX 3700": "277", + "Quadro FX 3800": "410", + "Quadro FX 4000": "101", + "Quadro FX 4500": "102", + "Quadro FX 4500 X2": "103", + "Quadro FX 4600": "104", + "Quadro FX 4700 X2": "294", + "Quadro FX 4800": "335", + "Quadro FX 5500": "105", + "Quadro FX 5600": "106", + "Quadro FX 5800": "336", + "Quadro NVS 50": "580", + "Quadro NVS 55": "581", + "Quadro NVS 210": "582", + "Quadro NVS 280": "583", + "Quadro NVS 285": "584", + "Quadro NVS 290": "585", + "Quadro NVS 295": "586", + "NVS 810": "786", + "NVS 510": "655", + "NVS 315": "697", + "NVS 310": "641", + "NVS 300": "531", + "Quadro NVS 420": "587", + "Quadro NVS 440": "588", + "Quadro NVS 450": "589", + "Quadro4 380 XGL": "115", + "Quadro4 550 XGL": "130", + "Quadro4 580 XGL": "117", + "Quadro4 700 XGL": "118", + "Quadro4 750 XGL": "119", + "Quadro4 780 XGL": "120", + "Quadro4 900 XGL": "121", + "Quadro4 980 XGL": "122", + "Quadro DCC": "123", + "Quadro4 500 GoGL": "131", + "Quadro4 700 GoGL": "132", + "Quadro2 MXR": "168", + "GeForce4 Ti 4200": "134", + "GeForce4 Ti 4200 with AGP8X": "135", + "GeForce4 Ti 4400": "136", + "GeForce4 Ti 4600": "137", + "GeForce4 Ti 4800": "138", + "GeForce4 Ti 4800 SE": "139", + "GeForce4 MX 4000": "140", + "GeForce4 MX 420": "141", + "GeForce4 MX 420 with AGP8X": "142", + "GeForce4 MX 440": "143", + "GeForce4 MX 440 with AGP8X": "144", + "GeForce4 MX 440-SE": "145", + "GeForce4 MX 440SE with AGP8X": "146", + "GeForce4 MX 460": "147", + "GeForce4 MX Integrated GPU": "148", + "GeForce3": "259", + "GeForce3 Ti 200": "260", + "GeForce3 Ti 500": "261", + "GeForce2 GTS": "152", + "GeForce2 Ti": "153", + "GeForce2 Ultra": "154", + "GeForce2 Integrated GPU": "155", + "GeForce2 MX 100": "156", + "GeForce2 MX": "157", + "GeForce 256": "158", + "GeForce 256 DDR": "159", + "Riva 128": "161", + "Riva 128 AGP": "160", + "RIVA TNT": "162", + "Aladdin TNT2": "163", + "RIVA TNT2 Model 64": "164", + "RIVA TNT2 Ultra": "165", + "RIVA TNT2": "166", + "Vanta": "170", + "Quadro2 Pro": "167", + "GeForce Go 7950 GTX": "276", + "GeForce Go 7900 GTX": "176", + "GeForce Go 7800 GTX": "174", + "GeForce Go 7900 GS": "175", + "Quadro NVS 210S": "215", + "NF-SPP-100": "216", + "GeForce Go 6150": "217", + "GeForce Go 6100": "218", + "GeForce Go 6155": "219", + "nForce 630M": "220", + "GeForce 7190M": "221", + "GeForce 7150M": "222", + "GeForce 7000M": "223", + "Quadro Sync II": "838", + "Quadro Sync": "665", + "Quadro G-Sync II": "226", + "Quadro G-Sync I": "225", + "nForce 1": "304", + "nForce 3": "305", + "MAXtreme": "227", + "POWERdraft": "228", + "GeForce 2 MX Series": "241", + "TNT and TNT2 Series": "282", + "nForce Professional 2000 Series": "296", + "nForce Professional 3000 Series": "297", + "nForce 790i Ultra SLI": "285", + "nForce 790i SLI": "284", + "nForce 780i SLI": "273", + "nForce 760i SLI": "409", + "nForce 750i SLI": "274", + "nForce 740i SLI": "403", + "nForce 730i": "320", + "nForce 720i": "378", + "nForce 780a SLI": "292", + "nForce 750a SLI": "404", + "nForce 740a SLI": "405", + "nForce 730a": "406", + "nForce 720a - GeForce 8100": "407", + "nForce 710a": "408", + "GeForce 8800M GTX": "315", + "GeForce 8800M GTS": "314", + "GeForce 8700M GT": "275", + "Quadro SDI": "298", + "Tesla C2075": "573", + "Tesla C2070": "513", + "Tesla C2050": "492", + "Tesla C1060": "327", + "Tesla C870": "278", + "D870": "279", + "S2050": "505", + "S1070": "317", + "S870": "280", + "GeForce 9800 GX2": "286", + "GeForce 9800 GTX": "287", + "GeForce 9800 GT": "309", + "GeForce 9600 GT": "283", + "GeForce 9600 GSO": "295", + "GeForce 9600 GSO 512": "321", + "GeForce 9600 GS": "316", + "GeForce 9500 GT": "307", + "GeForce 9500 GS": "310", + "GeForce 9400 GT": "311", + "GeForce 9400": "325", + "GeForce 9300 GS": "312", + "GeForce 9300 GE": "313", + "GeForce 9300 SE": "322", + "GeForce 9300": "323", + "GeForce 9200": "324", + "GeForce 9100": "418", + "GeForce GTX 295": "376", + "GeForce GTX 285": "377", + "GeForce GTX 280": "299", + "GeForce GTX 275": "416", + "GeForce GTX 260": "300", + "GeForce GTS 250": "399", + "GeForce GTS 240": "450", + "GeForce GT 230": "449", + "GeForce GT 240": "470", + "GeForce GT 220": "448", + "GeForce G210": "447", + "GeForce 210": "453", + "GeForce 205": "471", + "Full driver CD for GeForce": "381", + "Full driver CD for Notebook PCs": "488", + "3D Vision driver for GeForce": "432", + "3D Vision driver for Notebook": "555", + "3D Vision driver for Quadro": "452", + "3D Vision Video Player": "451", + "nForce 980a SLI": "398", + "GeForce GT 140": "400", + "GeForce GT 130": "401", + "GeForce GT 120": "402", + "GeForce G100": "415", + "ION": "431", + "3D Vision Pro driver": "535", + "3D Vision Pro Video Player": "536", + "ION LE": "446", + "GeForce GT 340": "473", + "GeForce GT 330": "474", + "GeForce GT 320": "475", + "GeForce 315": "494", + "GeForce 310": "493", + "GeForce GTX 480": "490", + "GeForce GTX 470": "491", + "GeForce GTX 465": "498", + "GeForce GTX 460 SE v2": "600", + "GeForce GTX 460 SE": "530", + "GeForce GTX 460": "499", + "GeForce GTS 450": "514", + "GeForce GT 440": "541", + "GeForce GT 430": "516", + "GeForce GT 420": "538", + "GeForce 405": "572", + "Quadro GV100": "866", + "Quadro GP100": "839", + "Quadro P6000": "824", + "Quadro P5200": "869", + "Quadro P5000": "823", + "Quadro P4000": "840", + "Quadro P2200": "900", + "Quadro P2000": "841", + "Quadro P1000": "842", + "Quadro P620": "865", + "Quadro P600": "843", + "Quadro P400": "844", + "Quadro M6000": "768", + "Quadro M5000": "780", + "Quadro M4000": "781", + "Quadro M2000": "811", + "Quadro K6000": "708", + "Quadro K5000 for Mac": "696", + "Quadro K5200": "752", + "Quadro K5000": "654", + "Quadro K4000": "681", + "Quadro K4200": "751", + "Quadro K2200": "750", + "Quadro K2000": "678", + "Quadro K2000D": "682", + "Quadro K1200": "767", + "Quadro K620": "749", + "Quadro K600": "679", + "Quadro K420": "748", + "Quadro 7000": "625", + "Quadro 6000": "508", + "Quadro 5000": "509", + "Quadro 4000": "510", + "Quadro 4000 for Mac": "529", + "Quadro 2000": "511", + "Quadro 2000D": "543", + "Quadro 600": "512", + "Quadro 410": "645", + "Quadro 400": "553", + "M60": "783", + "M40": "794", + "M6": "784", + "M4": "799", + "M2090": "570", + "M2075": "571", + "M2070": "525", + "M2070-Q": "542", + "M2050": "526", + "M1060": "527", + "GeForce GTX 590": "545", + "GeForce GTX 580": "528", + "GeForce GTX 570": "532", + "GeForce GTX 560 Ti": "540", + "GeForce GTX 560 SE": "609", + "GeForce GTX 560": "560", + "GeForce GTX 555": "626", + "GeForce GTX 550 Ti": "544", + "GeForce GT 545": "559", + "GeForce GT 530": "557", + "GeForce GT 520": "554", + "GeForce 510": "605", + "Tesla X2070": "717", + "Tesla X2090": "608", + "GeForce GTX 690": "627", + "GeForce GTX 680": "610", + "GeForce GTX 670": "629", + "GeForce GTX 660 Ti": "653", + "GeForce GTX 660": "660", + "GeForce GTX 650 Ti BOOST": "683", + "GeForce GTX 650 Ti": "666", + "GeForce GTX 650": "661", + "GeForce GTX 645": "731", + "GeForce GT 645": "633", + "GeForce GT 640": "632", + "GeForce GT 635": "685", + "GeForce GT 630": "631", + "GeForce GT 625": "741", + "GeForce GT 620": "611", + "GeForce GT 610": "630", + "GeForce 605": "624", + "Tesla K80": "762", + "Tesla K520": "856", + "Tesla K40c": "713", + "Tesla K40m": "714", + "Tesla K40s": "715", + "Tesla K40st": "716", + "Tesla K40t": "777", + "Tesla K20Xm": "670", + "Tesla K20m": "668", + "Tesla K20s": "684", + "Tesla K20c": "667", + "Tesla K10": "652", + "Tesla K8": "760", + "CUDA Toolkit 5.5": "673", + "GRID K2": "710", + "GRID K520": "704", + "GRID K1": "709", + "GRID K340": "705", + "GeForce GTX 780 Ti": "712", + "GeForce GTX 780": "691", + "GeForce GTX 770": "694", + "GeForce GTX 760": "703", + "GeForce GTX 760 Ti": "711", + "GeForce GTX 750 Ti": "727", + "GeForce GTX 750": "728", + "GeForce GTX 745": "730", + "GeForce GT 740": "745", + "GeForce GT 730": "746", + "GeForce GT 720": "754", + "GeForce GT 710": "742", + "GeForce GT 705": "761", + "GeForce GTX 980 Ti": "778", + "GeForce GTX 980": "755", + "GeForce GTX 970": "756", + "GeForce GTX 960": "764", + "GeForce GTX 950": "782", + "GeForce GTX 1080 Ti": "845", + "GeForce GTX 1080": "815", + "GeForce GTX 1070 Ti": "859", + "GeForce GTX 1070": "816", + "GeForce GTX 1060": "817", + "GeForce GTX 1050 Ti": "825", + "GeForce GTX 1050": "826", + "GeForce GT 1030": "852", + "GeForce GT 1010": "936", + "Tesla P100": "822", + "Tesla P40": "827", + "Tesla P6": "858", + "Tesla P4": "831", + "Tesla V100": "857", + "TITAN RTX": "885", + "TITAN V": "861", + "TITAN Xp": "850", + "TITAN X (Pascal)": "818", + "GeForce GTX TITAN X": "766", + "GeForce GTX TITAN": "695", + "GeForce GTX TITAN Black": "729", + "GeForce GTX TITAN Z": "744", + "GeForce RTX 2080 Ti": "877", + "GeForce RTX 2080 SUPER": "904", + "GeForce RTX 2080": "879", + "GeForce RTX 2070 SUPER": "903", + "GeForce RTX 2070": "880", + "GeForce RTX 2060 SUPER": "902", + "GeForce RTX 2060": "887", + "Quadro RTX 8000": "886", + "Quadro RTX 6000": "881", + "Quadro RTX 5000": "882", + "Quadro RTX 4000": "884", + "Quadro RTX 3000": "905", + "Tesla T4": "883", + "GeForce GTX 1660 SUPER": "910", + "GeForce GTX 1650 SUPER": "911", + "GeForce GTX 1660 Ti": "892", + "GeForce GTX 1660": "895", + "GeForce GTX 1650": "897", + "GeForce GTX 1630": "993", + "HGX GB200": "1069", + "HGX B200": "1064", + "H20-3e": "1063", + "H20": "1043", + "GH200": "1034", + "HGX H800": "1013", + "HGX H200": "1050", + "HGX H100": "1002", + "HGX A800": "997", + "HGX A100": "922", + "HGX-2": "896", + "AX800": "1032", + "A800": "1031", + "A100": "923", + "A40": "937", + "A30": "954", + "A16": "966", + "A10": "955", + "A2": "970", + "RTX 6000 Ada Generation": "1000", + "RTX 5000 Ada Generation": "1025", + "RTX 4500 Ada Generation": "1030", + "RTX 4000 Ada Generation": "1026", + "RTX 4000 SFF Ada Generation": "1014", + "RTX 2000 Ada Generation": "1042", + "RTX 2000E Ada Generation": "1049", + "RTX A2000": "967", + "RTX A1000": "1047", + "RTX A400": "1048", + "RTX 8000": "927", + "RTX 6000": "928", + "RTX A6000": "935", + "RTX A5000": "943", + "RTX A4000": "944", + "T1000": "945", + "T600": "946", + "T400": "947", + "GeForce RTX 3090 Ti": "985", + "GeForce RTX 3090": "930", + "GeForce RTX 3080 Ti": "964", + "GeForce RTX 3080": "929", + "GeForce RTX 3070 Ti": "965", + "GeForce RTX 3070": "933", + "GeForce RTX 3060 Ti": "934", + "GeForce RTX 3060": "942", + "GeForce RTX 3050": "975", + "RTX 5880 Ada Generation": "1035", + "RTX A5500": "984", + "RTX A4500": "969", + "RTX A4000H": "980", + "T400E": "1044", + "H100 PCIe": "994", + "H100 NVL": "1028", + "H800 PCIe": "1012", + "H800 NVL": "1029", + "H200 NVL": "1062", + "GeForce RTX 4090 D": "1036", + "GeForce RTX 4090": "995", + "GeForce RTX 4080 SUPER": "1041", + "GeForce RTX 4080": "999", + "GeForce RTX 4070 Ti SUPER": "1040", + "GeForce RTX 4070 Ti": "1001", + "GeForce RTX 4070 SUPER": "1039", + "GeForce RTX 4070": "1015", + "GeForce RTX 4060 Ti": "1022", + "GeForce RTX 4060": "1023", + "L40": "1003", + "L40S": "1027", + "L20": "1038", + "L4": "1009", + "L2": "1037", + "BlueField-3": "1011", + "BlueField-2": "1010", + "BlueField Drivers for Host": "1024", + "GeForce RTX 5090 D": "1067", + "GeForce RTX 5090": "1066", + "GeForce RTX 5080": "1065", + "GeForce RTX 5070 Ti": "1068", + "GeForce RTX 5070": "1070", + "GeForce RTX 5060 Ti": "1076", + "RTX PRO 6000 Blackwell Workstation": "1071", + "RTX PRO 6000 Blackwell Max-Q Workstation": "1072" + }, + "notebook": { + "NVS 5400M": "642", + "NVS 5200M": "614", + "NVS 5100M": "486", + "NVS 4200M": "565", + "NVS 3100M": "487", + "NVS 2100M": "517", + "Quadro NVS 510M": "590", + "Quadro NVS 320M": "591", + "Quadro NVS 300M": "592", + "Quadro NVS 160M": "593", + "Quadro NVS 150M": "594", + "Quadro NVS 140M": "595", + "Quadro NVS 135M": "596", + "Quadro NVS 130M": "597", + "Quadro NVS 120M": "598", + "Quadro NVS 110M": "599", + "Quadro FX 3800M": "483", + "Quadro FX 3700M": "419", + "Quadro FX 3600M": "444", + "Quadro FX 2800M": "496", + "Quadro FX 2700M": "126", + "Quadro FX 1800M": "482", + "Quadro FX 1700M": "252", + "Quadro FX 1600M": "443", + "Quadro FX 880M": "497", + "Quadro FX 770M": "441", + "Quadro FX 570M": "253", + "Quadro FX 380M": "484", + "Quadro FX 370M": "440", + "Quadro FX 360M": "254", + "GeForce 9800M GTX": "347", + "GeForce 9800M GTS": "348", + "GeForce 9800M GT": "349", + "GeForce 9800M GS": "350", + "GeForce 9700M GTS": "351", + "GeForce 9700M GT": "352", + "GeForce 9650M GT": "353", + "GeForce 9650M GS": "354", + "GeForce 9600M GT": "355", + "GeForce 9600M GS": "356", + "GeForce 9500M GS": "357", + "GeForce 9500M G": "358", + "GeForce 9400M G": "384", + "GeForce 9400M": "383", + "GeForce 9300M GS": "359", + "GeForce 9300M G": "360", + "GeForce 9200M GS": "361", + "GeForce 9100M G": "382", + "GeForce 8800M GTX": "363", + "GeForce 8800M GTS": "364", + "GeForce 8800M GS": "365", + "GeForce 8700M GT": "366", + "GeForce 8600M GT": "367", + "GeForce 8600M GS": "368", + "GeForce 8400M GT": "369", + "GeForce 8400M GS": "370", + "GeForce 8400M G": "371", + "GeForce 8200M G": "385", + "GeForce 8200M": "569", + "GeForce Go 7950 GTX": "372", + "GeForce Go 7900 GTX": "373", + "GeForce Go 7900 GS": "375", + "GeForce Go 7900 SE": "389", + "GeForce Go 7800 GTX": "374", + "GeForce Go 7800": "390", + "GeForce Go 7700": "391", + "GeForce Go 7600": "392", + "GeForce Go 7400": "393", + "GeForce Go 7300": "394", + "GeForce Go 7200": "395", + "GeForce 7150M": "397", + "GeForce 7000M": "396", + "GeForce GTS 160M": "424", + "GeForce GTS 150M": "733", + "GeForce GT 130M": "425", + "GeForce GT 120M": "426", + "GeForce G 110M": "427", + "GeForce G 105M": "428", + "GeForce G 103M": "429", + "GeForce G 102M": "430", + "GeForce GTX 285M": "454", + "GeForce GTX 280M": "421", + "GeForce GTX 260M": "422", + "GeForce GTS 260M": "456", + "GeForce GTS 250M": "457", + "GeForce GT 240M": "460", + "GeForce GT 230M": "461", + "GeForce GT 220M": "462", + "GeForce G210M": "465", + "GeForce G205M": "647", + "Quadro RTX 5000": "914", + "Quadro RTX 3000": "912", + "Quadro T2000": "908", + "Quadro T1000": "909", + "Quadro P5000": "847", + "Quadro P3000": "849", + "Quadro P2000": "873", + "Quadro P1000": "874", + "Quadro M5000 SE": "829", + "Quadro M3000 SE": "828", + "Quadro K3100M": "721", + "Quadro 500M": "615", + "Quadro 1000M": "547", + "Quadro 3000M": "568", + "Quadro 4000M": "567", + "Quadro FX 560M": "442", + "ION": "463", + "ION LE": "464", + "GeForce GTS 360M": "455", + "GeForce GTS 350M": "478", + "GeForce GT 335M": "458", + "GeForce GT 330M": "459", + "GeForce GT 325M": "476", + "GeForce GT 320M": "495", + "GeForce 320M": "563", + "GeForce 315M": "564", + "GeForce 310M": "466", + "GeForce 305M": "467", + "GeForce GTX 485M": "556", + "GeForce GTX 480M": "500", + "GeForce GTX 470M": "533", + "GeForce GTX 460M": "518", + "GeForce GT 445M": "523", + "GeForce GT 435M": "519", + "GeForce GT 425M": "520", + "GeForce GT 420M": "521", + "GeForce GT 415M": "522", + "GeForce 410M": "562", + "GeForce 405M": "732", + "Quadro P5200": "870", + "Quadro P4200": "871", + "Quadro P3200": "872", + "Quadro P4000": "848", + "Quadro P620": "992", + "Quadro P600": "875", + "Quadro P520": "901", + "Quadro P500": "876", + "Quadro M2200": "834", + "Quadro M1200": "835", + "Quadro M620": "830", + "Quadro M520": "851", + "Quadro M5500": "810", + "Quadro M5000M": "788", + "Quadro M4000M": "789", + "Quadro M3000M": "790", + "Quadro M2000M": "791", + "Quadro M1000M": "792", + "Quadro M600M": "793", + "Quadro M500M": "814", + "Quadro K5100M": "723", + "Quadro K5000M": "659", + "Quadro K4100M": "722", + "Quadro K4000M": "658", + "Quadro K2200M": "774", + "Quadro K2100M": "720", + "Quadro K3000M": "657", + "Quadro K2000M": "649", + "Quadro K1100M": "719", + "Quadro K1000M": "650", + "Quadro K620M": "776", + "Quadro K610M": "724", + "Quadro K510M": "725", + "Quadro K500M": "706", + "Quadro 5010M": "566", + "Quadro 5000M": "524", + "Quadro 2000M": "546", + "GeForce GTX 580M": "601", + "GeForce GTX 570M": "603", + "GeForce GTX 560M": "561", + "GeForce GT 555M": "552", + "GeForce GT 550M": "551", + "GeForce GT 540M": "550", + "GeForce GT 525M": "549", + "GeForce GT 520M": "548", + "GeForce GT 520MX": "602", + "GeForce GTX 680MX": "677", + "GeForce GTX 680M": "646", + "GeForce GTX 675MX": "664", + "GeForce GTX 675M": "638", + "GeForce GTX 670MX": "663", + "GeForce GTX 670M": "639", + "GeForce GTX 660M": "637", + "GeForce GT 650M": "636", + "GeForce GT 645M": "662", + "GeForce GT 640M": "635", + "GeForce GT 640M LE": "644", + "GeForce GT 635M": "619", + "GeForce GT 630M": "612", + "GeForce GT 625M": "671", + "GeForce GT 620M": "634", + "GeForce 610M": "620", + "GeForce GTX 780M": "700", + "GeForce GTX 775M": "740", + "GeForce GTX 770M": "702", + "GeForce GTX 765M": "701", + "GeForce GTX 760M": "699", + "GeForce GT 755M": "707", + "GeForce GT 750M": "690", + "GeForce GT 745M": "689", + "GeForce GT 740M": "686", + "GeForce GT 735M": "688", + "GeForce GT 730M": "672", + "GeForce GT 720M": "687", + "GeForce GT 710M": "798", + "GeForce 720M": "803", + "GeForce 710M": "680", + "GeForce 705M": "775", + "GeForce GTX 880M": "734", + "GeForce GTX 870M": "735", + "GeForce GTX 860M": "736", + "GeForce GTX 850M": "737", + "GeForce 845M": "805", + "GeForce 840M": "738", + "GeForce 830M": "739", + "GeForce 825M": "804", + "GeForce 820M": "726", + "GeForce 810M": "759", + "GeForce 800M": "797", + "GeForce GTX 980": "785", + "GeForce GTX 980M": "757", + "GeForce GTX 970M": "758", + "GeForce GTX 965M": "765", + "GeForce GTX 960M": "769", + "GeForce GTX 950M": "770", + "GeForce 945M": "795", + "GeForce 940MX": "796", + "GeForce 930MX": "807", + "GeForce 920MX": "808", + "GeForce 940M": "771", + "GeForce 930M": "772", + "GeForce 920M": "773", + "GeForce 910M": "779", + "GeForce GTX 1080": "819", + "GeForce GTX 1070": "820", + "GeForce GTX 1060": "821", + "GeForce GTX 1050 Ti": "836", + "GeForce GTX 1050": "837", + "GeForce MX150": "853", + "GeForce MX130": "862", + "GeForce MX110": "863", + "GeForce RTX 2080 SUPER": "919", + "GeForce RTX 2080": "890", + "GeForce RTX 2070 SUPER": "920", + "GeForce RTX 2070": "889", + "GeForce RTX 2060": "888", + "GeForce RTX 2050": "978", + "GeForce MX250": "894", + "GeForce MX230": "893", + "GeForce GTX 1660 Ti": "899", + "GeForce GTX 1650 Ti": "921", + "GeForce GTX 1650": "898", + "Quadro RTX 6000": "932", + "Quadro RTX 4000": "913", + "GeForce MX350": "918", + "GeForce MX330": "917", + "GeForce MX450": "931", + "GeForce RTX 3080 Ti Laptop GPU": "976", + "GeForce RTX 3080 Laptop GPU": "938", + "GeForce RTX 3070 Ti Laptop GPU": "979", + "GeForce RTX 3070 Laptop GPU": "939", + "GeForce RTX 3060 Laptop GPU": "940", + "GeForce RTX 3050 Ti Laptop GPU": "962", + "GeForce RTX 3050 Laptop GPU": "963", + "RTX 5000 Ada Generation Laptop GPU": "1020", + "RTX 4000 Ada Generation Laptop GPU": "1019", + "RTX 3500 Ada Generation Laptop GPU": "1018", + "RTX 3000 Ada Generation Laptop GPU": "1017", + "RTX 2000 Ada Generation Laptop GPU": "1016", + "RTX 1000 Ada Generation Laptop GPU": "1045", + "RTX 500 Ada Generation Laptop GPU": "1046", + "RTX A5500 Laptop GPU": "987", + "RTX A5000 Laptop GPU": "958", + "RTX A4500 Laptop GPU": "983", + "RTX A4000 Laptop GPU": "959", + "RTX A3000": "988", + "RTX A3000 Laptop GPU": "956", + "RTX A2000": "989", + "RTX A2000 Laptop GPU": "957", + "RTX A1000": "1021", + "RTX A1000 Laptop GPU": "981", + "RTX A500 Laptop GPU": "998", + "T1200 Laptop GPU": "960", + "T600 Laptop GPU": "961", + "T550 Laptop GPU": "986", + "T500": "941", + "GeForce MX570": "977", + "GeForce MX550": "974", + "GeForce RTX 4090 Laptop GPU": "1004", + "GeForce RTX 4080 Laptop GPU": "1005", + "GeForce RTX 4070 Laptop GPU": "1006", + "GeForce RTX 4060 Laptop GPU": "1007", + "GeForce RTX 4050 Laptop GPU": "1008", + "GeForce RTX 5090 Laptop GPU": "1073", + "GeForce RTX 5080 Laptop GPU": "1074", + "GeForce RTX 5070 Ti Laptop GPU": "1075" + } +} \ No newline at end of file diff --git a/internal/bootstrap/assets/winutil-sane-default.json b/internal/bootstrap/assets/winutil-sane-default.json index e766d50..c8d883c 100644 --- a/internal/bootstrap/assets/winutil-sane-default.json +++ b/internal/bootstrap/assets/winutil-sane-default.json @@ -8,8 +8,6 @@ "WPFTweaksLocation", "WPFTweaksServices", "WPFTweaksTelemetry", - "WPFTweaksDiskCleanup", - "WPFTweaksDeleteTempFiles", "WPFTweaksEndTaskOnTaskbar", "WPFTweaksPowershell7Tele" ] diff --git a/internal/bootstrap/catalog.go b/internal/bootstrap/catalog.go index 460a78e..5f02c15 100644 --- a/internal/bootstrap/catalog.go +++ b/internal/bootstrap/catalog.go @@ -17,10 +17,10 @@ const ( type Package struct { Name string Phase Phase - WingetID string - WingetSource string - WingetOverride string - WingetConfigAsset string + ChocoID string + ChocoParams string + InstallerArgs string + ChocoConfigAsset string Class Classification RequiresElevation bool Reboot RebootBehavior @@ -28,86 +28,101 @@ type Package struct { AI bool } -func wingetPackage(name, id string, phase Phase, class Classification) Package { +func chocoPackage(name, id string, phase Phase, class Classification) Package { return Package{ - Name: name, - Phase: phase, - WingetID: id, - WingetSource: "winget", - Class: class, - Reboot: RebootNone, + Name: name, + Phase: phase, + ChocoID: id, + Class: class, + Reboot: RebootNone, } } // Catalog is deliberately explicit: unlisted software is not installed by a fallback provider. func Catalog() []Package { packages := []Package{ - { - Name: "Visual Studio Community 2026", - Phase: PhaseHost, - WingetID: "Microsoft.VisualStudio.Community", - WingetSource: "winget", - WingetOverride: "--passive --config {config}", - WingetConfigAsset: "assets/visual-studio-community.vsconfig", - Class: ClassGUI, - RequiresElevation: true, - Reboot: RebootPossible, - PostInstall: "install workloads/components from managed .vsconfig; use Microsoft C/C++ compilers and CMake", + chocoPackage("WezTerm", "wezterm", PhaseHost, ClassGUI), + chocoPackage("PowerShell 7", "powershell-core", PhaseHost, ClassHeadless), + chocoPackage("PowerToys", "powertoys", PhaseHost, ClassGUI), + chocoPackage("JetBrainsMono Nerd Font", "nerd-fonts-jetbrainsmono", PhaseHost, ClassHeadless), + chocoPackage("Android Studio", "androidstudio", PhaseHost, ClassGUI), + // FilePilot has no official Chocolatey package, but it's listed here. + // We use empty ChocoID so our custom installer downloads and installs it directly. + chocoPackage("FilePilot", "", PhaseHost, ClassGUI), + chocoPackage("Vivaldi", "vivaldi", PhaseHost, ClassGUI), + chocoPackage("OBS Studio", "obs-studio", PhaseHost, ClassGUI), + chocoPackage("Obsidian", "obsidian", PhaseHost, ClassGUI), + chocoPackage("Libre Hardware Monitor", "librehardwaremonitor", PhaseHost, ClassGUI), + chocoPackage("WireGuard", "wireguard", PhaseHost, ClassGUI), + chocoPackage("Steam", "steam", PhaseHost, ClassGUI), + chocoPackage("Bruno", "bruno", PhaseHost, ClassGUI), + chocoPackage("VLC", "vlc", PhaseHost, ClassGUI), + chocoPackage("Wireshark", "wireshark", PhaseHost, ClassGUI), + chocoPackage("HandBrake", "handbrake", PhaseHost, ClassGUI), + chocoPackage("Gpg4win (includes gpgOL)", "gpg4win", PhaseHost, ClassGUI), + chocoPackage("Tor Browser", "tor-browser", PhaseHost, ClassGUI), + chocoPackage("LibreWolf", "librewolf", PhaseHost, ClassGUI), + chocoPackage("Rufus", "rufus", PhaseHost, ClassGUI), + chocoPackage("Slack", "slack", PhaseHost, ClassGUI), + chocoPackage("Discord", "discord", PhaseHost, ClassGUI), + chocoPackage("Revo Uninstaller", "revo-uninstaller", PhaseHost, ClassGUI), + chocoPackage("darktable", "darktable", PhaseHost, ClassGUI), + chocoPackage("Floorp", "floorp", PhaseHost, ClassGUI), + chocoPackage("Krita", "krita", PhaseHost, ClassGUI), + chocoPackage("Godot C++", "godot", PhaseHost, ClassGUI), + chocoPackage("Blender", "blender", PhaseHost, ClassGUI), + chocoPackage("Git", "git", PhaseHost, ClassHeadless), + chocoPackage("GitHub CLI", "gh", PhaseHost, ClassHeadless), + chocoPackage("Neovim", "neovim", PhaseHost, ClassHeadless), + chocoPackage("trivy", "trivy", PhaseHost, ClassHeadless), + chocoPackage("cosign", "cosign", PhaseHost, ClassHeadless), + chocoPackage("gitleaks", "gitleaks", PhaseHost, ClassHeadless), + chocoPackage("jq", "jq", PhaseHost, ClassHeadless), + chocoPackage("yq", "yq", PhaseHost, ClassHeadless), + chocoPackage("fzf", "fzf", PhaseHost, ClassHeadless), + chocoPackage("fd", "fd", PhaseHost, ClassHeadless), + chocoPackage("bottom", "bottom", PhaseHost, ClassHeadless), + chocoPackage("ripgrep", "ripgrep", PhaseHost, ClassHeadless), + chocoPackage("FFmpeg", "ffmpeg", PhaseHost, ClassHeadless), + chocoPackage("lazygit", "lazygit", PhaseHost, ClassHeadless), + chocoPackage("Lua", "lua", PhaseHost, ClassHeadless), + chocoPackage("minisign", "minisign", PhaseHost, ClassHeadless), + chocoPackage("Google Cloud CLI", "gcloudsdk", PhaseHost, ClassHeadless), + chocoPackage("Rustup", "rustup.install", PhaseHost, ClassHeadless), + chocoPackage("AWS CLI", "awscli", PhaseHost, ClassHeadless), + chocoPackage("Azure CLI", "azure-cli", PhaseHost, ClassHeadless), + chocoPackage("Pulumi", "pulumi", PhaseHost, ClassHeadless), + chocoPackage("restic", "restic", PhaseHost, ClassHeadless), + chocoPackage("yt-dlp", "yt-dlp", PhaseHost, ClassHeadless), + chocoPackage("Vagrant", "vagrant", PhaseHost, ClassHeadless), + chocoPackage("Go", "golang", PhaseHost, ClassHeadless), + chocoPackage(".NET SDK", "dotnet-sdk", PhaseHost, ClassHeadless), + chocoPackage("Temurin JDK", "temurin", PhaseHost, ClassHeadless), + chocoPackage("Zig", "zig", PhaseHost, ClassHeadless), + chocoPackage("CMake", "cmake", PhaseHost, ClassHeadless), + chocoPackage("oh-my-posh", "oh-my-posh", PhaseCustom, ClassHeadless), + chocoPackage("Google Chrome", "googlechrome", PhaseCustom, ClassGUI), + chocoPackage("Mullvad VPN", "mullvad-app", PhaseCustom, ClassGUI), + chocoPackage("Figma", "figma", PhaseCustom, ClassGUI), + chocoPackage("Zoom", "zoom", PhaseCustom, ClassGUI), + chocoPackage("Adobe Acrobat Reader", "adobereader", PhaseCustom, ClassGUI), + chocoPackage("WhatsApp", "", PhaseCustom, ClassGUI), + chocoPackage("Affinity", "", PhaseCustom, ClassGUI), + chocoPackage("Tidal", "", PhaseCustom, ClassGUI), + chocoPackage("DaVinci Resolve", "", PhaseCustom, ClassGUI), + chocoPackage("Ardour", "", PhaseCustom, ClassGUI), + chocoPackage("Nvidia Driver", "", PhaseHost, ClassGUI), + chocoPackage("Nvidia Broadcast", "", PhaseHost, ClassGUI), + chocoPackage("AMD Auto-Detect", "", PhaseHost, ClassGUI), + chocoPackage("Intel DSA", "", PhaseHost, ClassGUI), + Package{ + Name: "Nmap", + Phase: PhaseCustom, + ChocoID: "nmap", + InstallerArgs: `"/S /NPCAP=NO"`, + Class: ClassHeadless, + Reboot: RebootNone, }, - wingetPackage("WezTerm", "wez.wezterm", PhaseHost, ClassGUI), - wingetPackage("PowerShell 7", "Microsoft.PowerShell", PhaseHost, ClassHeadless), - wingetPackage("PowerToys", "Microsoft.PowerToys", PhaseHost, ClassGUI), - wingetPackage("JetBrainsMono Nerd Font", "DEVCOM.JetBrainsMonoNerdFont", PhaseHost, ClassHeadless), - wingetPackage("Android Studio", "Google.AndroidStudio", PhaseHost, ClassGUI), - wingetPackage("FilePilot", "Voidstar.FilePilot", PhaseHost, ClassGUI), - wingetPackage("GitHub Desktop", "GitHub.GitHubDesktop", PhaseHost, ClassGUI), - wingetPackage("Google Chrome", "Google.Chrome", PhaseHost, ClassGUI), - wingetPackage("Vivaldi", "Vivaldi.Vivaldi", PhaseHost, ClassGUI), - wingetPackage("OBS Studio", "OBSProject.OBSStudio", PhaseHost, ClassGUI), - wingetPackage("Obsidian", "Obsidian.Obsidian", PhaseHost, ClassGUI), - wingetPackage("Libre Hardware Monitor", "LibreHardwareMonitor.LibreHardwareMonitor", PhaseHost, ClassGUI), - wingetPackage("Mullvad VPN", "MullvadVPN.MullvadVPN", PhaseHost, ClassGUI), - wingetPackage("WireGuard", "WireGuard.WireGuard", PhaseHost, ClassGUI), - wingetPackage("Steam", "Valve.Steam", PhaseHost, ClassGUI), - wingetPackage("Bruno", "Bruno.Bruno", PhaseHost, ClassGUI), - wingetPackage("Figma", "Figma.Figma", PhaseHost, ClassGUI), - wingetPackage("VLC", "VideoLAN.VLC", PhaseHost, ClassGUI), - wingetPackage("Wireshark", "WiresharkFoundation.Wireshark", PhaseHost, ClassGUI), - wingetPackage("Zoom", "Zoom.Zoom", PhaseHost, ClassGUI), - wingetPackage("HandBrake", "HandBrake.HandBrake", PhaseHost, ClassGUI), - wingetPackage("Adobe Acrobat Reader", "Adobe.Acrobat.Reader.64-bit", PhaseHost, ClassGUI), - wingetPackage("Gpg4win (includes gpgOL)", "GnuPG.Gpg4win", PhaseHost, ClassGUI), - wingetPackage("Tor Browser", "TorProject.TorBrowser", PhaseHost, ClassGUI), - wingetPackage("LibreWolf", "LibreWolf.LibreWolf", PhaseHost, ClassGUI), - wingetPackage("Rufus", "Rufus.Rufus", PhaseHost, ClassGUI), - wingetPackage("Slack", "SlackTechnologies.Slack", PhaseHost, ClassGUI), - wingetPackage("Discord", "Discord.Discord", PhaseHost, ClassGUI), - wingetPackage("Revo Uninstaller", "RevoUninstaller.RevoUninstaller", PhaseHost, ClassGUI), - wingetPackage("darktable", "darktable.darktable", PhaseHost, ClassGUI), - wingetPackage("Floorp", "Ablaze.Floorp", PhaseHost, ClassGUI), - wingetPackage("Git", "Git.Git", PhaseHost, ClassHeadless), - wingetPackage("GitHub CLI", "GitHub.cli", PhaseHost, ClassHeadless), - wingetPackage("Neovim", "Neovim.Neovim", PhaseHost, ClassHeadless), - wingetPackage("ripgrep", "BurntSushi.ripgrep.MSVC", PhaseHost, ClassHeadless), - wingetPackage("FFmpeg", "Gyan.FFmpeg", PhaseHost, ClassHeadless), - wingetPackage("lazygit", "JesseDuffield.lazygit", PhaseHost, ClassHeadless), - wingetPackage("Lua", "DEVCOM.Lua", PhaseHost, ClassHeadless), - wingetPackage("minisign", "jedisct1.minisign", PhaseHost, ClassHeadless), - wingetPackage("Google Cloud CLI", "Google.CloudSDK", PhaseHost, ClassHeadless), - wingetPackage("Rustup", "Rustlang.Rustup", PhaseHost, ClassHeadless), - wingetPackage("AWS CLI", "Amazon.AWSCLI", PhaseHost, ClassHeadless), - wingetPackage("Azure CLI", "Microsoft.AzureCLI", PhaseHost, ClassHeadless), - wingetPackage("Pulumi", "Pulumi.Pulumi", PhaseHost, ClassHeadless), - wingetPackage("restic", "restic.restic", PhaseHost, ClassHeadless), - wingetPackage("yt-dlp", "yt-dlp.yt-dlp", PhaseHost, ClassHeadless), - wingetPackage("Vagrant", "Hashicorp.Vagrant", PhaseHost, ClassHeadless), - wingetPackage("Go", "GoLang.Go", PhaseHost, ClassHeadless), - wingetPackage(".NET SDK", "Microsoft.DotNet.SDK.10", PhaseHost, ClassHeadless), - wingetPackage("Temurin JDK", "EclipseAdoptium.Temurin.21.JDK", PhaseHost, ClassHeadless), - wingetPackage("Zig", "zig.zig", PhaseHost, ClassHeadless), - wingetPackage("CMake", "Kitware.CMake", PhaseHost, ClassHeadless), - wingetPackage("fnm", "Schniz.fnm", PhaseHost, ClassHeadless), - wingetPackage("oh-my-posh", "JanDeDobbeleer.OhMyPosh", PhaseCustom, ClassHeadless), } for i := range packages { if packages[i].Name == "Vagrant" { @@ -115,9 +130,6 @@ func Catalog() []Package { packages[i].Reboot = RebootPossible packages[i].PostInstall = "configure Hyper-V provider prerequisites" } - if packages[i].Name == "fnm" { - packages[i].PostInstall = "install Node.js LTS" - } } return packages } @@ -128,6 +140,28 @@ func PackagesForPhase(opts Options, phase Phase) []Package { if pkg.Phase != phase || (opts.NoAI && pkg.AI) { continue } + if pkg.Name == "Nvidia Driver" { + if !opts.Nvidia { + continue + } + pkg.ChocoParams = opts.NvidiaModel + pkg.InstallerArgs = opts.NvidiaType + } + if pkg.Name == "Nvidia Broadcast" { + if !opts.Nvidia || !isRTX2050OrNewer(opts.NvidiaModel) { + continue + } + } + if pkg.Name == "AMD Auto-Detect" { + if !opts.Amd { + continue + } + } + if pkg.Name == "Intel DSA" { + if !opts.Intel { + continue + } + } selected = append(selected, pkg) } return selected diff --git a/internal/bootstrap/catalog_test.go b/internal/bootstrap/catalog_test.go index 4eec460..78ffee0 100644 --- a/internal/bootstrap/catalog_test.go +++ b/internal/bootstrap/catalog_test.go @@ -2,16 +2,15 @@ package bootstrap import "testing" -func TestCatalogContainsExactWingetIDsAndDefersExcludedNativeTools(t *testing.T) { +func TestCatalogContainsExactChocoIDsAndDefersExcludedNativeTools(t *testing.T) { seen := make(map[string]Package) for _, pkg := range Catalog() { - if pkg.WingetID == "" || pkg.WingetSource != "winget" { - t.Fatalf("invalid winget metadata for %#v", pkg) + if pkg.ChocoID == "" && !isCustomPackage(pkg) { + t.Fatalf("invalid choco metadata for %#v", pkg) } seen[pkg.Name] = pkg } for _, name := range []string{ - "Visual Studio Community 2026", "Android Studio", "FilePilot", "PowerShell 7", @@ -39,8 +38,16 @@ func TestCatalogContainsExactWingetIDsAndDefersExcludedNativeTools(t *testing.T) "CMake", "WezTerm", "Vagrant", - "fnm", "oh-my-posh", + "Nmap", + "Krita", + "Godot C++", + "Blender", + "WhatsApp", + "Affinity", + "Tidal", + "DaVinci Resolve", + "Ardour", } { if _, ok := seen[name]; !ok { t.Fatalf("missing catalog package %s", name) @@ -63,8 +70,4 @@ func TestCatalogContainsExactWingetIDsAndDefersExcludedNativeTools(t *testing.T) if _, ok := seen["g++"]; ok { t.Fatal("g++ should not be installed natively; use Visual Studio C/C++ tools") } - vs := seen["Visual Studio Community 2026"] - if vs.WingetID != "Microsoft.VisualStudio.Community" || vs.WingetConfigAsset == "" || vs.WingetOverride == "" { - t.Fatalf("Visual Studio package missing managed config metadata: %#v", vs) - } } diff --git a/internal/bootstrap/choco.go b/internal/bootstrap/choco.go new file mode 100644 index 0000000..c76b45b --- /dev/null +++ b/internal/bootstrap/choco.go @@ -0,0 +1,430 @@ +package bootstrap + +import ( + "context" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "sync" + "syscall" + "time" + "unsafe" +) + +var chocoCommand = "choco" + +func init() { + if _, err := exec.LookPath("choco"); err == nil { + chocoCommand = "choco" + return + } + if chocoInstall := os.Getenv("ChocolateyInstall"); chocoInstall != "" { + path := filepath.Join(chocoInstall, "bin", "choco.exe") + if _, err := os.Stat(path); err == nil { + chocoCommand = path + return + } + } + defaultPath := `C:\ProgramData\chocolatey\bin\choco.exe` + if _, err := os.Stat(defaultPath); err == nil { + chocoCommand = defaultPath + } +} + +func ChocoInstallArgs(pkg Package) []string { + args := []string{ + "install", pkg.ChocoID, "-y", "--no-progress", + } + if pkg.ChocoParams != "" { + args = append(args, "--package-parameters", pkg.ChocoParams) + } + if pkg.InstallerArgs != "" { + args = append(args, "--install-arguments", pkg.InstallerArgs) + } + return args +} + +func ChocoListArgs(pkg Package) []string { + return []string{ + "list", "--local-only", "--exact", pkg.ChocoID, + } +} + +func ChocoOutputShowsInstalled(pkg Package, output string) bool { + lower := strings.ToLower(output) + lines := strings.Split(lower, "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, strings.ToLower(pkg.ChocoID)+" ") { + return true + } + } + return false +} + +type PackageState struct { + Package Package + Installed bool + CheckErr error +} + +func CheckPackages(ctx context.Context, runner Runner, packages []Package, workers int) []PackageState { + if workers < 1 { + workers = 1 + } + states := make([]PackageState, len(packages)) + type job struct { + index int + pkg Package + } + jobs := make(chan job) + var wg sync.WaitGroup + for i := 0; i < workers; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for current := range jobs { + state := PackageState{Package: current.pkg} + if isCustomPackage(current.pkg) { + cmd := "" + switch current.pkg.Name { + case "FilePilot": + cmd = "if (Get-Command filepilot.exe -ErrorAction SilentlyContinue) { 'yes' } else { 'no' }" + case "Affinity": + cmd = `if (Get-AppxPackage *Affinity* -ErrorAction SilentlyContinue) { 'yes' } else { 'no' }` + case "Tidal": + cmd = `if (Test-Path "${env:LocalAppData}\TIDAL\TIDAL.exe" -or Test-Path "${env:ProgramFiles}\TIDAL\TIDAL.exe") { 'yes' } else { 'no' }` + case "DaVinci Resolve": + cmd = `if (Test-Path "${env:ProgramFiles}\Blackmagic Design\DaVinci Resolve\Resolve.exe") { 'yes' } else { 'no' }` + case "WhatsApp": + cmd = `if (Get-AppxPackage *WhatsApp* -ErrorAction SilentlyContinue) { 'yes' } else { 'no' }` + case "Ardour": + cmd = `if (Test-Path "C:\msys64\mingw64\bin\ardour8.exe" -or Test-Path "C:\msys64\mingw64\bin\ardour.exe" -or Test-Path "C:\msys64\mingw64\bin\ardour9.exe" -or Test-Path "C:\tools\msys64\mingw64\bin\ardour8.exe" -or Test-Path "C:\tools\msys64\mingw64\bin\ardour.exe" -or Test-Path "C:\tools\msys64\mingw64\bin\ardour9.exe") { 'yes' } else { 'no' }` + case "Nvidia Broadcast": + cmd = `if (Test-Path "${env:ProgramFiles}\NVIDIA Corporation\NVIDIA Broadcast\NVIDIA Broadcast.exe") { 'yes' } else { 'no' }` + case "AMD Auto-Detect": + cmd = `if (Test-Path "${env:ProgramFiles}\AMD\CNext\CNext\RadeonSoftware.exe" -or Test-Path "${env:ProgramFiles}\AMD\CNext\CNext\AMDRSServ.exe") { 'yes' } else { 'no' }` + case "Intel DSA": + cmd = `if (Test-Path "${env:ProgramFiles(x86)}\Intel\Driver and Support Assistant\DSAService.exe") { 'yes' } else { 'no' }` + case "Nvidia Driver": + model := current.pkg.ChocoParams + driverType := current.pkg.InstallerArgs + pfid, err := resolveNvidiaPFID(model) + if err != nil { + state.CheckErr = err + state.Installed = false + } else { + _, apiVer, err := fetchNvidiaDriverURLFn(pfid, driverType) + if err != nil { + state.CheckErr = err + state.Installed = false + } else { + installedVer, err := getInstalledNvidiaVersionFn(ctx, runner) + if err != nil { + state.CheckErr = err + state.Installed = false + } else { + state.Installed = (installedVer != "" && installedVer == apiVer) + } + } + } + } + if cmd != "" { + result := runner.Run(ctx, "powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", cmd) + state.Installed = strings.Contains(strings.ToLower(result.CombinedOutput()), "yes") + } else if current.pkg.Name != "Nvidia Driver" { + state.Installed = false + } + } else { + result := runner.Run(ctx, "powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "Test-Path C:\\ProgramData\\chocolatey\\lib\\"+current.pkg.ChocoID) + if result.Err != nil { + state.CheckErr = result.Err + } else { + state.Installed = strings.Contains(strings.ToLower(result.CombinedOutput()), "true") + } + } + states[current.index] = state + } + }() + } + for i, pkg := range packages { + jobs <- job{index: i, pkg: pkg} + } + close(jobs) + wg.Wait() + return states +} + +func PendingPackages(states []PackageState) []Package { + var pending []Package + for _, state := range states { + if !state.Installed { + pending = append(pending, state.Package) + } + } + return pending +} + +func UnknownPackageStates(packages []Package) []PackageState { + states := make([]PackageState, 0, len(packages)) + for _, pkg := range packages { + states = append(states, PackageState{Package: pkg}) + } + return states +} + +func InstallPackages(ctx context.Context, runner Runner, packages []Package) Issues { + var issues Issues + for _, pkg := range packages { + pkgTimeout := 5 * time.Minute + if pkg.Name == "Ardour" || pkg.Name == "Nvidia Driver" || pkg.Name == "Nvidia Broadcast" || pkg.Name == "AMD Auto-Detect" || pkg.Name == "Intel DSA" { + pkgTimeout = 30 * time.Minute + } else if pkg.Name == "DaVinci Resolve" { + pkgTimeout = 15 * time.Minute + } + if IsSessionZero() && pkg.Class == ClassGUI { + if pkg.Name != "Nvidia Driver" && pkg.Name != "Nvidia Broadcast" && pkg.Name != "AMD Auto-Detect" && pkg.Name != "Intel DSA" { + pkgTimeout = 10 * time.Second + } + } + + pkgCtx, pkgCancel := context.WithTimeout(ctx, pkgTimeout) + + if isCustomPackage(pkg) { + var script string + switch pkg.Name { + case "FilePilot": + script = `$tempExe = Join-Path $env:TEMP 'FilePilotSetup.exe'; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-WebRequest -Uri 'https://filepilot.tech/download/latest' -OutFile $tempExe -UseBasicParsing; Start-Process -FilePath $tempExe -ArgumentList '/S' -Wait` + case "Affinity": + script = ` +$tempMsix = Join-Path $env:TEMP 'Affinity_x64.msix' +if (Test-Path $tempMsix) { Remove-Item -Force $tempMsix } +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 +Write-Host "Downloading Affinity MSIX..." +Invoke-WebRequest -Uri 'https://downloads.affinity.studio/Affinity%20x64.msix' -OutFile $tempMsix -UseBasicParsing -ErrorAction Stop +Write-Host "Installing Affinity MSIX package..." +Add-AppxProvisionedPackage -Online -PackagePath $tempMsix -SkipLicense +` + case "Tidal": + script = ` +$tempExe = Join-Path $env:TEMP 'TIDALSetup.exe' +if (Test-Path $tempExe) { Remove-Item -Force $tempExe } +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 +Write-Host "Downloading Tidal setup..." +Invoke-WebRequest -Uri 'https://download.tidal.com/desktop/TIDALSetup.exe' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop +Write-Host "Installing Tidal silently..." +Start-Process -FilePath $tempExe -ArgumentList '-s' -Wait +` + case "WhatsApp": + script = `winget install --id WhatsApp.WhatsApp --silent --accept-package-agreements --accept-source-agreements` + case "DaVinci Resolve": + script = `winget install --id BlackmagicDesign.DaVinciResolve --silent --accept-package-agreements --accept-source-agreements` + case "Ardour": + script = ` +$msysDir = "C:\msys64" +if (-not (Test-Path "$msysDir\usr\bin\bash.exe")) { + $msysDir = "C:\tools\msys64" +} +if (-not (Test-Path "$msysDir\usr\bin\bash.exe")) { + Write-Host "Installing MSYS2 via Chocolatey..." + choco install msys2 -y --no-progress + $msysDir = "C:\tools\msys64" + if (-not (Test-Path "$msysDir\usr\bin\bash.exe")) { + $msysDir = "C:\msys64" + } +} +$env:MSYSTEM="MINGW64" +$buildScript = @' +set -e +pacman -Sy --noconfirm +pacman -S --noconfirm --needed git unzip make cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-boost mingw-w64-x86_64-glib2 mingw-w64-x86_64-glibmm mingw-w64-x86_64-libsndfile mingw-w64-x86_64-curl mingw-w64-x86_64-libarchive mingw-w64-x86_64-liblo mingw-w64-x86_64-taglib mingw-w64-x86_64-vamp-plugin-sdk mingw-w64-x86_64-rubberband mingw-w64-x86_64-aubio mingw-w64-x86_64-cairomm mingw-w64-x86_64-pangomm mingw-w64-x86_64-jack2 mingw-w64-x86_64-serd mingw-w64-x86_64-sord mingw-w64-x86_64-sratom mingw-w64-x86_64-lilv mingw-w64-x86_64-libwebsockets mingw-w64-x86_64-libusb python3 +if [ ! -d "/tmp/ardour" ]; then + git clone --depth 1 https://github.com/Ardour/ardour.git /tmp/ardour +fi +cd /tmp/ardour +python3 ./waf configure --prefix=/mingw64 --dist-target=mingw --optimize +python3 ./waf build +python3 ./waf install +'@ +$scriptPath = "$msysDir\tmp\build_ardour.sh" +[System.IO.Directory]::CreateDirectory("$msysDir\tmp") | Out-Null +[System.IO.File]::WriteAllText($scriptPath, $buildScript) +& "$msysDir\usr\bin\bash.exe" --login /tmp/build_ardour.sh +` + case "Nvidia Driver": + model := pkg.ChocoParams + driverType := pkg.InstallerArgs + pfid, err := resolveNvidiaPFID(model) + if err != nil { + issues = append(issues, Issue{ + Step: "resolve Nvidia model", + Err: err, + }) + } else { + downloadURL, _, err := fetchNvidiaDriverURLFn(pfid, driverType) + if err != nil { + issues = append(issues, Issue{ + Step: "fetch Nvidia driver URL", + Err: err, + }) + } else { + script = fmt.Sprintf(` +$tempExe = Join-Path $env:TEMP 'NvidiaDriver.exe' +if (Test-Path $tempExe) { Remove-Item -Force $tempExe } +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 +Write-Host "Downloading Nvidia driver..." +Invoke-WebRequest -Uri '%s' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop +Write-Host "Installing Nvidia driver silently..." +$p = Start-Process -FilePath $tempExe -ArgumentList '-s' -Wait -PassThru +Remove-Item -Force $tempExe +if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1) { + throw "Nvidia driver installation failed with exit code " + $p.ExitCode +} +`, downloadURL) + } + } + case "Nvidia Broadcast": + downloadURL := "https://international.download.nvidia.com/Windows/broadcast/2.2.0/NVIDIA_Broadcast_v2.2.0.52896077.exe" + script = fmt.Sprintf(` +$tempExe = Join-Path $env:TEMP 'NvidiaBroadcast.exe' +if (Test-Path $tempExe) { Remove-Item -Force $tempExe } +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 +Write-Host "Downloading Nvidia Broadcast..." +Invoke-WebRequest -Uri '%s' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop +Write-Host "Installing Nvidia Broadcast silently..." +$p = Start-Process -FilePath $tempExe -ArgumentList '/s' -Wait -PassThru +Remove-Item -Force $tempExe +if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) { + throw "Nvidia Broadcast installation failed with exit code " + $p.ExitCode +} +`, downloadURL) + case "AMD Auto-Detect": + downloadURL := "https://drivers.amd.com/drivers/installer/26.10/whql/amd-software-adrenalin-edition-26.6.1-minimalsetup-260601_web.exe" + script = fmt.Sprintf(` +$tempExe = Join-Path $env:TEMP 'AMDMinimalSetup.exe' +if (Test-Path $tempExe) { Remove-Item -Force $tempExe } +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 +Write-Host "Downloading AMD Auto-Detect tool..." +Invoke-WebRequest -Uri '%s' -OutFile $tempExe -UseBasicParsing -Headers @{"Referer" = "https://www.amd.com/"} -UserAgent "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" -ErrorAction Stop +Write-Host "Launching AMD Auto-Detect tool..." +$p = Start-Process -FilePath $tempExe -Wait -PassThru +Remove-Item -Force $tempExe +if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) { + throw "AMD Auto-Detect failed with exit code " + $p.ExitCode +} +`, downloadURL) + case "Intel DSA": + downloadURL := "https://dsadata.intel.com/installer" + script = fmt.Sprintf(` +$tempExe = Join-Path $env:TEMP 'IntelDSAInstaller.exe' +if (Test-Path $tempExe) { Remove-Item -Force $tempExe } +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 +Write-Host "Downloading Intel Driver & Support Assistant..." +Invoke-WebRequest -Uri '%s' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop +Write-Host "Installing Intel Driver & Support Assistant silently..." +$p = Start-Process -FilePath $tempExe -ArgumentList '-s', '-norestart' -Wait -PassThru +Remove-Item -Force $tempExe +if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) { + throw "Intel DSA installation failed with exit code " + $p.ExitCode +} +`, downloadURL) + } + if script != "" { + result := runner.Run(pkgCtx, "powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", script) + if result.Err != nil { + issues = append(issues, Issue{ + Step: "install " + pkg.Name + " (custom download/install)", + Err: fmt.Errorf("%w: %s", result.Err, result.CombinedOutput()), + }) + } + } + pkgCancel() + continue + } + + prepared, err := PreparePackageForInstall(pkg) + if err != nil { + issues = append(issues, Issue{Step: "prepare " + pkg.Name, Err: err}) + pkgCancel() + continue + } + result := runner.Run(pkgCtx, chocoCommand, ChocoInstallArgs(prepared)...) + if result.Err != nil { + isSuccess := false + var exitErr *exec.ExitError + if errors.As(result.Err, &exitErr) { + code := exitErr.ExitCode() + if code == 3010 || code == 1641 { + isSuccess = true + } + } + if !isSuccess { + out := result.CombinedOutput() + if len(out) > 500 { + out = out[:500] + "... (truncated)" + } + issues = append(issues, Issue{ + Step: "install " + pkg.Name, + Err: fmt.Errorf("%w: %s", result.Err, out), + }) + } + } + pkgCancel() + } + return issues +} + +func PreparePackageForInstall(pkg Package) (Package, error) { + if pkg.ChocoConfigAsset == "" { + return pkg, nil + } + path, err := writeInstallAsset(pkg.ChocoConfigAsset) + if err != nil { + return pkg, err + } + pkg.InstallerArgs = strings.ReplaceAll(pkg.InstallerArgs, "{config}", `"`+path+`"`) + return pkg, nil +} + +func writeInstallAsset(asset string) (string, error) { + data, err := managedAssets.ReadFile(asset) + if err != nil { + return "", err + } + root, err := os.UserCacheDir() + if err != nil || root == "" { + root = os.TempDir() + } + dir := filepath.Join(root, "bootstrap_windows_env") + if err := os.MkdirAll(dir, 0o755); err != nil { + return "", err + } + target := filepath.Join(dir, filepath.Base(asset)) + if err := os.WriteFile(target, data, 0o644); err != nil { + return "", err + } + return target, nil +} + +func isCustomPackage(pkg Package) bool { + return pkg.ChocoID == "" && (pkg.Name == "FilePilot" || pkg.Name == "Affinity" || pkg.Name == "Tidal" || pkg.Name == "DaVinci Resolve" || pkg.Name == "Ardour" || pkg.Name == "WhatsApp" || pkg.Name == "Nvidia Driver" || pkg.Name == "Nvidia Broadcast" || pkg.Name == "AMD Auto-Detect" || pkg.Name == "Intel DSA") +} + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procProcessIdToSessionId = modkernel32.NewProc("ProcessIdToSessionId") + procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") +) + +func IsSessionZero() bool { + pid, _, _ := procGetCurrentProcessId.Call() + var sessionID uint32 + r, _, _ := procProcessIdToSessionId.Call(pid, uintptr(unsafe.Pointer(&sessionID))) + if r == 0 { + return false + } + return sessionID == 0 +} diff --git a/internal/bootstrap/choco_test.go b/internal/bootstrap/choco_test.go new file mode 100644 index 0000000..4391e7f --- /dev/null +++ b/internal/bootstrap/choco_test.go @@ -0,0 +1,390 @@ +package bootstrap + +import ( + "context" + "errors" + "os" + "path/filepath" + "reflect" + "strings" + "testing" +) + +func init() { + chocoCommand = "choco" +} + +func TestChocoInstallArgsUseExactNonInteractiveFlags(t *testing.T) { + pkg := Package{Name: "Git", ChocoID: "git"} + want := []string{"install", "git", "-y", "--no-progress"} + if got := ChocoInstallArgs(pkg); !reflect.DeepEqual(got, want) { + t.Fatalf("args = %#v, want %#v", got, want) + } +} + +func TestPreparePackageForInstallWritesVisualStudioConfigAndOverride(t *testing.T) { + pkg := Package{ + Name: "Visual Studio Community 2026", + ChocoID: "visualstudio2022community", + InstallerArgs: "--passive --config {config}", + ChocoConfigAsset: "assets/visual-studio-community.vsconfig", + } + prepared, err := PreparePackageForInstall(pkg) + if err != nil { + t.Fatal(err) + } + if strings.Contains(prepared.InstallerArgs, "{config}") { + t.Fatalf("override still has placeholder: %q", prepared.InstallerArgs) + } + args := ChocoInstallArgs(prepared) + joined := strings.Join(args, " ") + if !strings.Contains(joined, "--install-arguments") || !strings.Contains(joined, "visual-studio-community.vsconfig") { + t.Fatalf("choco args missing VS config override: %#v", args) + } +} + +func TestPreparePackageForInstallHandlesNoAssetAndMissingAsset(t *testing.T) { + pkg := Package{Name: "Git", ChocoID: "git"} + prepared, err := PreparePackageForInstall(pkg) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(prepared, pkg) { + t.Fatalf("prepared = %#v, want unchanged package", prepared) + } + + _, err = PreparePackageForInstall(Package{Name: "broken", ChocoConfigAsset: "assets/missing.vsconfig"}) + if err == nil { + t.Fatal("expected missing asset error") + } +} + +func TestChocoInstalledStateParsing(t *testing.T) { + pkg := Package{ChocoID: "git"} + if !ChocoOutputShowsInstalled(pkg, "Chocolatey v1.2.1\ngit 2.40.1\n1 packages installed.") { + t.Fatal("expected installed output to be detected") + } + if ChocoOutputShowsInstalled(pkg, "Chocolatey v1.2.1\n0 packages installed.") { + t.Fatal("expected missing package output to be false") + } +} + +func TestCheckPackagesKeepsStableOrderAndAggregatesErrors(t *testing.T) { + a := Package{Name: "A", ChocoID: "a"} + b := Package{Name: "B", ChocoID: "b"} + runner := &fakeRunner{responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "Test-Path C:\\ProgramData\\chocolatey\\lib\\a"): {Stdout: "True\n"}, + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "Test-Path C:\\ProgramData\\chocolatey\\lib\\b"): {Err: errors.New("boom"), Stderr: "source unavailable"}, + }} + states := CheckPackages(context.Background(), runner, []Package{a, b}, 2) + if len(states) != 2 || states[0].Package.Name != "A" || states[1].Package.Name != "B" { + t.Fatalf("states not in input order: %#v", states) + } + if !states[0].Installed { + t.Fatal("first package should be installed") + } + if states[1].CheckErr == nil { + t.Fatal("second package should keep check error") + } +} + +func TestCheckPackagesUsesSingleWorkerMinimumAndMissingPackageIsPending(t *testing.T) { + pkg := Package{Name: "Git", ChocoID: "git"} + runner := &fakeRunner{responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "Test-Path C:\\ProgramData\\chocolatey\\lib\\git"): {Stdout: "False\n"}, + }} + states := CheckPackages(context.Background(), runner, []Package{pkg}, 0) + if len(states) != 1 { + t.Fatalf("states = %d, want 1", len(states)) + } + if states[0].Installed || states[0].CheckErr != nil { + t.Fatalf("state = %#v, want pending without check error", states[0]) + } +} + +func TestInstallPackagesContinuesAfterFailure(t *testing.T) { + a := Package{Name: "A", ChocoID: "a"} + b := Package{Name: "B", ChocoID: "b"} + runner := &fakeRunner{responses: map[string]CommandResult{ + commandKey("choco", ChocoInstallArgs(a)...): {Err: errors.New("boom"), Stderr: "failed"}, + commandKey("choco", ChocoInstallArgs(b)...): {}, + }, defaultErr: true} + issues := InstallPackages(context.Background(), runner, []Package{a, b}) + if len(issues) != 1 { + t.Fatalf("issues = %d, want 1", len(issues)) + } + if !runner.called("choco", ChocoInstallArgs(b)...) { + t.Fatal("second package should still be attempted after first failure") + } +} + +func TestInstallPackagesReportsPrepareFailure(t *testing.T) { + issues := InstallPackages(context.Background(), &fakeRunner{defaultErr: true}, []Package{{ + Name: "broken", + ChocoConfigAsset: "assets/missing.vsconfig", + }}) + if len(issues) != 1 || !strings.Contains(issues[0].Step, "prepare broken") { + t.Fatalf("issues = %#v, want prepare failure", issues) + } +} + +func TestWriteInstallAssetReportsCacheDirectoryError(t *testing.T) { + temp := t.TempDir() + cacheFile := filepath.Join(temp, "cache-file") + if err := os.WriteFile(cacheFile, []byte("not a directory"), 0o644); err != nil { + t.Fatal(err) + } + t.Setenv("LOCALAPPDATA", cacheFile) + t.Setenv("LocalAppData", cacheFile) + if _, err := writeInstallAsset("assets/visual-studio-community.vsconfig"); err == nil { + t.Fatal("expected cache directory error") + } +} + +func TestWriteInstallAssetFallsBackToTempDirWhenUserCacheIsUnavailable(t *testing.T) { + t.Setenv("LOCALAPPDATA", "") + t.Setenv("LocalAppData", "") + path, err := writeInstallAsset("assets/visual-studio-community.vsconfig") + if err != nil { + t.Fatal(err) + } + if filepath.Base(path) != "visual-studio-community.vsconfig" { + t.Fatalf("path = %q", path) + } +} + +func TestWriteInstallAssetReportsWriteError(t *testing.T) { + cache := t.TempDir() + targetDir := filepath.Join(cache, "bootstrap_windows_env", "visual-studio-community.vsconfig") + if err := os.MkdirAll(targetDir, 0o755); err != nil { + t.Fatal(err) + } + t.Setenv("LOCALAPPDATA", cache) + t.Setenv("LocalAppData", cache) + if _, err := writeInstallAsset("assets/visual-studio-community.vsconfig"); err == nil { + t.Fatal("expected write error when target path is a directory") + } +} + +func TestCheckPackagesNvidiaDriver(t *testing.T) { + // Backup original functions and defer restore + oldFetch := fetchNvidiaDriverURLFn + oldGetInstalled := getInstalledNvidiaVersionFn + defer func() { + fetchNvidiaDriverURLFn = oldFetch + getInstalledNvidiaVersionFn = oldGetInstalled + }() + + // Mock fetchNvidiaDriverURLFn to return a version + fetchNvidiaDriverURLFn = func(pfid string, driverType string) (string, string, error) { + if pfid != "995" { + t.Errorf("expected pfid 995, got %s", pfid) + } + if driverType != "Studio" { + t.Errorf("expected driverType Studio, got %s", driverType) + } + return "https://uk.download.nvidia.com/Windows/610.47/610.47-desktop-win10-win11-64bit-international-nsd-dch-whql.exe", "610.47", nil + } + + // 1. Test case: Installed version matches API version -> should report installed = true + getInstalledNvidiaVersionFn = func(ctx context.Context, runner Runner) (string, error) { + return "610.47", nil + } + + pkg := Package{ + Name: "Nvidia Driver", + ChocoParams: "RTX 4090", + InstallerArgs: "Studio", + } + + runner := &fakeRunner{} + states := CheckPackages(context.Background(), runner, []Package{pkg}, 1) + if len(states) != 1 { + t.Fatalf("expected 1 state, got %d", len(states)) + } + if !states[0].Installed { + t.Error("expected Nvidia Driver to be reported as installed") + } + if states[0].CheckErr != nil { + t.Errorf("expected no check error, got %v", states[0].CheckErr) + } + + // 2. Test case: Installed version does not match API version -> should report installed = false + getInstalledNvidiaVersionFn = func(ctx context.Context, runner Runner) (string, error) { + return "596.36", nil + } + + states = CheckPackages(context.Background(), runner, []Package{pkg}, 1) + if len(states) != 1 { + t.Fatalf("expected 1 state, got %d", len(states)) + } + if states[0].Installed { + t.Error("expected Nvidia Driver to be reported as not installed (pending)") + } + if states[0].CheckErr != nil { + t.Errorf("expected no check error, got %v", states[0].CheckErr) + } +} + +func TestInstallPackagesNvidiaDriver(t *testing.T) { + // Backup original functions and defer restore + oldFetch := fetchNvidiaDriverURLFn + defer func() { + fetchNvidiaDriverURLFn = oldFetch + }() + + fetchNvidiaDriverURLFn = func(pfid string, driverType string) (string, string, error) { + return "https://mock.nvidia.download/driver.exe", "610.47", nil + } + + pkg := Package{ + Name: "Nvidia Driver", + ChocoParams: "RTX 4090", + InstallerArgs: "Studio", + } + + runner := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "\n$tempExe = Join-Path $env:TEMP 'NvidiaDriver.exe'\nif (Test-Path $tempExe) { Remove-Item -Force $tempExe }\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072\nWrite-Host \"Downloading Nvidia driver...\"\nInvoke-WebRequest -Uri 'https://mock.nvidia.download/driver.exe' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop\nWrite-Host \"Installing Nvidia driver silently...\"\n$p = Start-Process -FilePath $tempExe -ArgumentList '-s' -Wait -PassThru\nRemove-Item -Force $tempExe\nif ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1) {\n throw \"Nvidia driver installation failed with exit code \" + $p.ExitCode\n}\n"): {}, + }, + } + + issues := InstallPackages(context.Background(), runner, []Package{pkg}) + if len(issues) != 0 { + t.Fatalf("expected no issues, got: %v", issues) + } + + if !runner.called("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "\n$tempExe = Join-Path $env:TEMP 'NvidiaDriver.exe'\nif (Test-Path $tempExe) { Remove-Item -Force $tempExe }\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072\nWrite-Host \"Downloading Nvidia driver...\"\nInvoke-WebRequest -Uri 'https://mock.nvidia.download/driver.exe' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop\nWrite-Host \"Installing Nvidia driver silently...\"\n$p = Start-Process -FilePath $tempExe -ArgumentList '-s' -Wait -PassThru\nRemove-Item -Force $tempExe\nif ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1) {\n throw \"Nvidia driver installation failed with exit code \" + $p.ExitCode\n}\n") { + t.Error("expected Nvidia installer script to be executed") + } +} + +func TestCheckPackagesNvidiaBroadcast(t *testing.T) { + pkg := Package{ + Name: "Nvidia Broadcast", + } + + runner := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", `if (Test-Path "${env:ProgramFiles}\NVIDIA Corporation\NVIDIA Broadcast\NVIDIA Broadcast.exe") { 'yes' } else { 'no' }`): { + Stdout: "yes\n", + }, + }, + } + + states := CheckPackages(context.Background(), runner, []Package{pkg}, 1) + if len(states) != 1 { + t.Fatalf("expected 1 state, got %d", len(states)) + } + if !states[0].Installed { + t.Error("expected Nvidia Broadcast to be reported as installed") + } +} + +func TestInstallPackagesNvidiaBroadcast(t *testing.T) { + pkg := Package{ + Name: "Nvidia Broadcast", + } + + runner := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "\n$tempExe = Join-Path $env:TEMP 'NvidiaBroadcast.exe'\nif (Test-Path $tempExe) { Remove-Item -Force $tempExe }\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072\nWrite-Host \"Downloading Nvidia Broadcast...\"\nInvoke-WebRequest -Uri 'https://international.download.nvidia.com/Windows/broadcast/2.2.0/NVIDIA_Broadcast_v2.2.0.52896077.exe' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop\nWrite-Host \"Installing Nvidia Broadcast silently...\"\n$p = Start-Process -FilePath $tempExe -ArgumentList '/s' -Wait -PassThru\nRemove-Item -Force $tempExe\nif ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) {\n throw \"Nvidia Broadcast installation failed with exit code \" + $p.ExitCode\n}\n"): {}, + }, + } + + issues := InstallPackages(context.Background(), runner, []Package{pkg}) + if len(issues) != 0 { + t.Fatalf("expected no issues, got: %v", issues) + } + + if !runner.called("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "\n$tempExe = Join-Path $env:TEMP 'NvidiaBroadcast.exe'\nif (Test-Path $tempExe) { Remove-Item -Force $tempExe }\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072\nWrite-Host \"Downloading Nvidia Broadcast...\"\nInvoke-WebRequest -Uri 'https://international.download.nvidia.com/Windows/broadcast/2.2.0/NVIDIA_Broadcast_v2.2.0.52896077.exe' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop\nWrite-Host \"Installing Nvidia Broadcast silently...\"\n$p = Start-Process -FilePath $tempExe -ArgumentList '/s' -Wait -PassThru\nRemove-Item -Force $tempExe\nif ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) {\n throw \"Nvidia Broadcast installation failed with exit code \" + $p.ExitCode\n}\n") { + t.Error("expected Nvidia Broadcast installer script to be executed") + } +} + +func TestCheckPackagesAmdAutoDetect(t *testing.T) { + pkg := Package{ + Name: "AMD Auto-Detect", + } + + runner := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", `if (Test-Path "${env:ProgramFiles}\AMD\CNext\CNext\RadeonSoftware.exe" -or Test-Path "${env:ProgramFiles}\AMD\CNext\CNext\AMDRSServ.exe") { 'yes' } else { 'no' }`): { + Stdout: "yes\n", + }, + }, + } + + states := CheckPackages(context.Background(), runner, []Package{pkg}, 1) + if len(states) != 1 { + t.Fatalf("expected 1 state, got %d", len(states)) + } + if !states[0].Installed { + t.Error("expected AMD Auto-Detect to be reported as installed") + } +} + +func TestInstallPackagesAmdAutoDetect(t *testing.T) { + pkg := Package{ + Name: "AMD Auto-Detect", + } + + runner := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "\n$tempExe = Join-Path $env:TEMP 'AMDMinimalSetup.exe'\nif (Test-Path $tempExe) { Remove-Item -Force $tempExe }\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072\nWrite-Host \"Downloading AMD Auto-Detect tool...\"\nInvoke-WebRequest -Uri 'https://drivers.amd.com/drivers/installer/26.10/whql/amd-software-adrenalin-edition-26.6.1-minimalsetup-260601_web.exe' -OutFile $tempExe -UseBasicParsing -Headers @{\"Referer\" = \"https://www.amd.com/\"} -UserAgent \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\" -ErrorAction Stop\nWrite-Host \"Launching AMD Auto-Detect tool...\"\n$p = Start-Process -FilePath $tempExe -Wait -PassThru\nRemove-Item -Force $tempExe\nif ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) {\n throw \"AMD Auto-Detect failed with exit code \" + $p.ExitCode\n}\n"): {}, + }, + } + + issues := InstallPackages(context.Background(), runner, []Package{pkg}) + if len(issues) != 0 { + t.Fatalf("expected no issues, got: %v", issues) + } + + if !runner.called("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "\n$tempExe = Join-Path $env:TEMP 'AMDMinimalSetup.exe'\nif (Test-Path $tempExe) { Remove-Item -Force $tempExe }\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072\nWrite-Host \"Downloading AMD Auto-Detect tool...\"\nInvoke-WebRequest -Uri 'https://drivers.amd.com/drivers/installer/26.10/whql/amd-software-adrenalin-edition-26.6.1-minimalsetup-260601_web.exe' -OutFile $tempExe -UseBasicParsing -Headers @{\"Referer\" = \"https://www.amd.com/\"} -UserAgent \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\" -ErrorAction Stop\nWrite-Host \"Launching AMD Auto-Detect tool...\"\n$p = Start-Process -FilePath $tempExe -Wait -PassThru\nRemove-Item -Force $tempExe\nif ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) {\n throw \"AMD Auto-Detect failed with exit code \" + $p.ExitCode\n}\n") { + t.Error("expected AMD Auto-Detect installer script to be executed") + } +} + +func TestCheckPackagesIntelDSA(t *testing.T) { + pkg := Package{ + Name: "Intel DSA", + } + + runner := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", `if (Test-Path "${env:ProgramFiles(x86)}\Intel\Driver and Support Assistant\DSAService.exe") { 'yes' } else { 'no' }`): { + Stdout: "yes\n", + }, + }, + } + + states := CheckPackages(context.Background(), runner, []Package{pkg}, 1) + if len(states) != 1 { + t.Fatalf("expected 1 state, got %d", len(states)) + } + if !states[0].Installed { + t.Error("expected Intel DSA to be reported as installed") + } +} + +func TestInstallPackagesIntelDSA(t *testing.T) { + pkg := Package{ + Name: "Intel DSA", + } + + runner := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "\n$tempExe = Join-Path $env:TEMP 'IntelDSAInstaller.exe'\nif (Test-Path $tempExe) { Remove-Item -Force $tempExe }\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072\nWrite-Host \"Downloading Intel Driver & Support Assistant...\"\nInvoke-WebRequest -Uri 'https://dsadata.intel.com/installer' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop\nWrite-Host \"Installing Intel Driver & Support Assistant silently...\"\n$p = Start-Process -FilePath $tempExe -ArgumentList '-s', '-norestart' -Wait -PassThru\nRemove-Item -Force $tempExe\nif ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) {\n throw \"Intel DSA installation failed with exit code \" + $p.ExitCode\n}\n"): {}, + }, + } + + issues := InstallPackages(context.Background(), runner, []Package{pkg}) + if len(issues) != 0 { + t.Fatalf("expected no issues, got: %v", issues) + } + + if !runner.called("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "\n$tempExe = Join-Path $env:TEMP 'IntelDSAInstaller.exe'\nif (Test-Path $tempExe) { Remove-Item -Force $tempExe }\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072\nWrite-Host \"Downloading Intel Driver & Support Assistant...\"\nInvoke-WebRequest -Uri 'https://dsadata.intel.com/installer' -OutFile $tempExe -UseBasicParsing -ErrorAction Stop\nWrite-Host \"Installing Intel Driver & Support Assistant silently...\"\n$p = Start-Process -FilePath $tempExe -ArgumentList '-s', '-norestart' -Wait -PassThru\nRemove-Item -Force $tempExe\nif ($p.ExitCode -ne 0 -and $p.ExitCode -ne 1 -and $p.ExitCode -ne 3010) {\n throw \"Intel DSA installation failed with exit code \" + $p.ExitCode\n}\n") { + t.Error("expected Intel DSA installer script to be executed") + } +} + diff --git a/internal/bootstrap/command.go b/internal/bootstrap/command.go index 0930837..5cd2fc2 100644 --- a/internal/bootstrap/command.go +++ b/internal/bootstrap/command.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "io" "os/exec" "strings" "time" @@ -26,6 +27,7 @@ type Runner interface { type ExecRunner struct { Timeout time.Duration + Stream io.Writer } func (r ExecRunner) Run(ctx context.Context, name string, args ...string) CommandResult { @@ -37,11 +39,23 @@ func (r ExecRunner) Run(ctx context.Context, name string, args ...string) Comman defer cancel() var stdout, stderr bytes.Buffer cmd := exec.CommandContext(ctx, name, args...) - cmd.Stdout = &stdout - cmd.Stderr = &stderr + cmd.Cancel = func() error { + if cmd.Process == nil { + return nil + } + _ = exec.Command("taskkill", "/F", "/T", "/PID", fmt.Sprintf("%d", cmd.Process.Pid)).Run() + return cmd.Process.Kill() + } + if r.Stream != nil { + cmd.Stdout = io.MultiWriter(r.Stream, &stdout) + cmd.Stderr = io.MultiWriter(r.Stream, &stderr) + } else { + cmd.Stdout = &stdout + cmd.Stderr = &stderr + } err := cmd.Run() if ctx.Err() == context.DeadlineExceeded { - err = fmt.Errorf("%s timed out after %s", name, timeout) + err = fmt.Errorf("%s timed out", name) } return CommandResult{ Command: name + " " + strings.Join(args, " "), diff --git a/internal/bootstrap/hyperv.go b/internal/bootstrap/hyperv.go index b2bc656..370a03b 100644 --- a/internal/bootstrap/hyperv.go +++ b/internal/bootstrap/hyperv.go @@ -2,7 +2,9 @@ package bootstrap import ( "context" + "errors" "fmt" + "os/exec" "strings" ) @@ -44,7 +46,12 @@ func EnableHyperV(ctx context.Context, runner Runner, status HyperVStatus) (stri } result := runner.Run(ctx, "dism.exe", "/Online", "/Enable-Feature", "/FeatureName:Microsoft-Hyper-V-All", "/All", "/NoRestart") if result.Err != nil { - return "", fmt.Errorf("enable Hyper-V: %w: %s", result.Err, result.CombinedOutput()) + var exitErr *exec.ExitError + if errors.As(result.Err, &exitErr) && exitErr.ExitCode() == 3010 { + // 3010 is ERROR_SUCCESS_REBOOT_REQUIRED + } else { + return "", fmt.Errorf("enable Hyper-V: %w: %s", result.Err, result.CombinedOutput()) + } } return "Hyper-V features were enabled; restart Windows and rerun to complete Vagrant provider setup.", nil } diff --git a/internal/bootstrap/nvidia.go b/internal/bootstrap/nvidia.go new file mode 100644 index 0000000..0c38b3d --- /dev/null +++ b/internal/bootstrap/nvidia.go @@ -0,0 +1,132 @@ +package bootstrap + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "strings" +) + +var ( + fetchNvidiaDriverURLFn = fetchNvidiaDriverURL + getInstalledNvidiaVersionFn = getInstalledNvidiaVersion +) + +type AjaxDriverResponse struct { + IDS []struct { + DownloadInfo struct { + DownloadURL string `json:"DownloadURL"` + Version string `json:"Version"` + } `json:"downloadInfo"` + } `json:"IDS"` +} + +// resolveNvidiaPFID looks up the GPU model in the embedded gpu-data.json and returns its pfid. +func resolveNvidiaPFID(model string) (string, error) { + data, err := managedAssets.ReadFile("assets/gpu-data.json") + if err != nil { + return "", fmt.Errorf("read embedded gpu-data.json: %w", err) + } + + var gpuData struct { + Desktop map[string]string `json:"desktop"` + Notebook map[string]string `json:"notebook"` + } + if err := json.Unmarshal(data, &gpuData); err != nil { + return "", fmt.Errorf("unmarshal gpu-data.json: %w", err) + } + + normalized := strings.TrimSpace(model) + if !strings.HasPrefix(strings.ToLower(normalized), "geforce") { + normalized = "GeForce " + normalized + } + + for k, v := range gpuData.Desktop { + if strings.EqualFold(k, normalized) { + return v, nil + } + } + for k, v := range gpuData.Notebook { + if strings.EqualFold(k, normalized) { + return v, nil + } + } + + return "", fmt.Errorf("Nvidia model %q not found in database", model) +} + +// fetchNvidiaDriverURL queries the Nvidia driver lookup API and returns the download URL and version. +func fetchNvidiaDriverURL(pfid string, driverType string) (string, string, error) { + // driverType is either "Game Ready" (upCRD=0) or "Studio" (upCRD=1) + upCRD := "0" + if driverType == "Studio" { + upCRD = "1" + } + apiURL := fmt.Sprintf("https://gfwsl.geforce.com/services_toolkit/services/com/nvidia/services/AjaxDriverService.php?func=DriverManualLookup&pfid=%s&osID=57&upCRD=%s&dch=1", pfid, upCRD) + + resp, err := http.Get(apiURL) + if err != nil { + return "", "", fmt.Errorf("http get driver info: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return "", "", fmt.Errorf("driver info request returned status %d", resp.StatusCode) + } + + var data AjaxDriverResponse + if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { + return "", "", fmt.Errorf("decode driver info: %w", err) + } + + if len(data.IDS) == 0 { + return "", "", fmt.Errorf("no drivers found for pfid %s", pfid) + } + + downloadURL := data.IDS[0].DownloadInfo.DownloadURL + version := data.IDS[0].DownloadInfo.Version + if downloadURL == "" { + return "", "", fmt.Errorf("download URL not found in driver info response") + } + + return downloadURL, version, nil +} + +// getInstalledNvidiaVersion queries the current system's Nvidia driver version. +func getInstalledNvidiaVersion(ctx context.Context, runner Runner) (string, error) { + cmd := "Get-CimInstance Win32_VideoController | Where-Object { $_.Name -like '*Nvidia*' } | Select-Object -ExpandProperty DriverVersion" + result := runner.Run(ctx, "powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", cmd) + if result.Err != nil { + return "", result.Err + } + output := strings.TrimSpace(result.Stdout) + if output == "" { + return "", nil // No Nvidia GPU or driver installed + } + lines := strings.Split(output, "\n") + driverVer := strings.TrimSpace(lines[0]) + if driverVer == "" { + return "", nil + } + + parts := strings.Split(driverVer, ".") + if len(parts) < 2 { + return "", fmt.Errorf("unexpected driver version format: %s", driverVer) + } + combined := parts[len(parts)-2] + parts[len(parts)-1] + if len(combined) < 5 { + return "", fmt.Errorf("unexpected combined driver version suffix: %s", combined) + } + suffix5 := combined[len(combined)-5:] + nvidiaVer := fmt.Sprintf("%s.%s", suffix5[:3], suffix5[3:]) + nvidiaVer = strings.TrimPrefix(nvidiaVer, "0") + return nvidiaVer, nil +} + +// isRTX2050OrNewer returns true if the GPU model is an RTX 2050 or newer. +// Since RTX started with Turing architecture (20-series) and RTX 2050 is the lowest number in the RTX branding, +// containing "RTX" (case-insensitive) is a robust and future-proof check. +func isRTX2050OrNewer(model string) bool { + return strings.Contains(strings.ToUpper(model), "RTX") +} diff --git a/internal/bootstrap/nvidia_test.go b/internal/bootstrap/nvidia_test.go new file mode 100644 index 0000000..72b99fa --- /dev/null +++ b/internal/bootstrap/nvidia_test.go @@ -0,0 +1,98 @@ +package bootstrap + +import ( + "context" + "strings" + "testing" +) + +func TestResolveNvidiaPFID(t *testing.T) { + tests := []struct { + model string + wantPFID string + wantErr bool + }{ + {"RTX 4090", "995", false}, + {"GeForce RTX 4090", "995", false}, + {"rtx 4090", "995", false}, + {"RTX 4090 D", "1036", false}, + {"RTX 4090 Laptop GPU", "1004", false}, + {"NonExistentGPU", "", true}, + } + + for _, tt := range tests { + t.Run(tt.model, func(t *testing.T) { + got, err := resolveNvidiaPFID(tt.model) + if (err != nil) != tt.wantErr { + t.Errorf("resolveNvidiaPFID(%q) error = %v, wantErr %v", tt.model, err, tt.wantErr) + return + } + if got != tt.wantPFID { + t.Errorf("resolveNvidiaPFID(%q) = %q, want %q", tt.model, got, tt.wantPFID) + } + }) + } +} + +func TestFetchNvidiaDriverURL(t *testing.T) { + // Query API for RTX 4090 Game Ready + url, version, err := fetchNvidiaDriverURL("995", "Game Ready") + if err != nil { + t.Skipf("Skipping API test (possibly offline or rate limited): %v", err) + return + } + if !strings.HasPrefix(url, "https://") { + t.Errorf("expected download URL to start with https://, got %q", url) + } + if version == "" { + t.Error("expected version to be non-empty") + } + + // Query API for RTX 4090 Studio + urlStudio, versionStudio, err := fetchNvidiaDriverURL("995", "Studio") + if err != nil { + t.Skipf("Skipping API test: %v", err) + return + } + if !strings.HasPrefix(urlStudio, "https://") { + t.Errorf("expected studio download URL to start with https://, got %q", urlStudio) + } + if versionStudio == "" { + t.Error("expected studio version to be non-empty") + } +} + +func TestGetInstalledNvidiaVersion(t *testing.T) { + // Test with a mock runner that returns a valid driver version format + mockRunner := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "Get-CimInstance Win32_VideoController | Where-Object { $_.Name -like '*Nvidia*' } | Select-Object -ExpandProperty DriverVersion"): { + Stdout: "32.0.15.9636\n", + }, + }, + } + + ver, err := getInstalledNvidiaVersion(context.Background(), mockRunner) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if ver != "596.36" { + t.Errorf("getInstalledNvidiaVersion = %q, want %q", ver, "596.36") + } + + // Test case with leading zero representation + mockRunner2 := &fakeRunner{ + responses: map[string]CommandResult{ + commandKey("powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", "Get-CimInstance Win32_VideoController | Where-Object { $_.Name -like '*Nvidia*' } | Select-Object -ExpandProperty DriverVersion"): { + Stdout: "32.0.10.6104\n", + }, + }, + } + ver2, err := getInstalledNvidiaVersion(context.Background(), mockRunner2) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if ver2 != "61.04" { + t.Errorf("getInstalledNvidiaVersion = %q, want %q", ver2, "61.04") + } +} diff --git a/internal/bootstrap/options.go b/internal/bootstrap/options.go index eba1663..cb3aa4d 100644 --- a/internal/bootstrap/options.go +++ b/internal/bootstrap/options.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "io" + "os" ) // Phase identifies a resumable unit of Windows provisioning work. @@ -25,9 +26,12 @@ type Options struct { NoWSL bool Yes bool DryRun bool - Headless bool - NoRestorePoints bool LinuxReleaseRepo string + Nvidia bool + NvidiaModel string + NvidiaType string + Amd bool + Intel bool } func ParseOptions(args []string, stderr io.Writer) (Options, error) { @@ -40,9 +44,12 @@ func ParseOptions(args []string, stderr io.Writer) (Options, error) { fs.BoolVar(&opts.NoWSL, "no-wsl", false, "omit Fedora WSL provisioning and guest bootstrap") fs.BoolVar(&opts.Yes, "yes", false, "execute the displayed plan without confirmation") fs.BoolVar(&opts.DryRun, "dry-run", false, "detect state and display work without making changes") - fs.BoolVar(&opts.Headless, "headless", false, "disable interactive login offers and require --yes to execute") - fs.BoolVar(&opts.NoRestorePoints, "no-restore-points", false, "skip System Restore checkpoints (required on Windows Server/CI where Checkpoint-Computer is unsupported)") fs.StringVar(&opts.LinuxReleaseRepo, "linux-release-repo", "JMR-dev/bootstrap_dev_env", "GitHub repository containing Linux bootstrap releases") + fs.BoolVar(&opts.Nvidia, "nvidia", false, "fetch and install Nvidia driver") + fs.StringVar(&opts.NvidiaModel, "model", "", "Nvidia GPU model (e.g. RTX 4090)") + fs.StringVar(&opts.NvidiaType, "type", "", "Nvidia driver type (Game Ready or Studio)") + fs.BoolVar(&opts.Amd, "amd", false, "fetch and run AMD auto-detection graphics driver tool") + fs.BoolVar(&opts.Intel, "intel", false, "fetch and install Intel Driver & Support Assistant") if err := fs.Parse(args); err != nil { return Options{}, err } @@ -60,8 +67,21 @@ func ParseOptions(args []string, stderr io.Writer) (Options, error) { if opts.NoWSL && opts.Only == PhaseWSL { return Options{}, fmt.Errorf("--only wsl cannot be combined with --no-wsl") } - if opts.Headless && !opts.Yes && !opts.DryRun { - return Options{}, fmt.Errorf("--headless execution requires --yes or --dry-run") + if opts.Nvidia && opts.Amd && opts.Intel && os.Getenv("BOOTSTRAP_INTEGRATION_TEST") != "true" { + return Options{}, fmt.Errorf("cannot combine --nvidia, --amd, and --intel") + } + if opts.Nvidia { + if opts.NvidiaModel == "" { + return Options{}, fmt.Errorf("--nvidia requires --model flag") + } + if opts.NvidiaType == "" { + return Options{}, fmt.Errorf("--nvidia requires --type flag") + } + if opts.NvidiaType != "Game Ready" && opts.NvidiaType != "Studio" { + return Options{}, fmt.Errorf("invalid --type value %q: use Game Ready or Studio", opts.NvidiaType) + } + } else if opts.NvidiaModel != "" || opts.NvidiaType != "" { + return Options{}, fmt.Errorf("--model and --type require --nvidia flag") } return opts, nil } diff --git a/internal/bootstrap/options_test.go b/internal/bootstrap/options_test.go index c3ec17a..bb03087 100644 --- a/internal/bootstrap/options_test.go +++ b/internal/bootstrap/options_test.go @@ -38,9 +38,6 @@ func TestInvalidOptionCombinations(t *testing.T) { if _, err := ParseOptions([]string{"--only", "wsl", "--no-wsl"}, &bytes.Buffer{}); err == nil { t.Fatal("expected --only wsl --no-wsl to fail") } - if _, err := ParseOptions([]string{"--headless"}, &bytes.Buffer{}); err == nil { - t.Fatal("expected --headless without --yes or --dry-run to fail") - } if _, err := ParseOptions([]string{"--only", "bogus"}, &bytes.Buffer{}); err == nil { t.Fatal("expected invalid --only value to fail") } @@ -52,29 +49,86 @@ func TestInvalidOptionCombinations(t *testing.T) { } } -func TestParseOptionsAcceptsHeadlessWithDryRunAndCustomRepo(t *testing.T) { - opts, err := ParseOptions([]string{"--headless", "--dry-run", "--linux-release-repo", "owner/repo"}, &bytes.Buffer{}) +func TestNvidiaOptions(t *testing.T) { + // Valid combinations + opts, err := ParseOptions([]string{"--nvidia", "--model", "RTX 4090", "--type", "Studio"}, &bytes.Buffer{}) if err != nil { t.Fatal(err) } - if !opts.Headless || !opts.DryRun || opts.LinuxReleaseRepo != "owner/repo" { - t.Fatalf("opts = %#v", opts) + if !opts.Nvidia || opts.NvidiaModel != "RTX 4090" || opts.NvidiaType != "Studio" { + t.Fatal("Nvidia options not parsed correctly") } -} -func TestParseOptionsAcceptsNoRestorePoints(t *testing.T) { - opts, err := ParseOptions([]string{"--yes", "--no-restore-points"}, &bytes.Buffer{}) + opts, err = ParseOptions([]string{"--nvidia", "--model", "RTX 4090", "--type", "Game Ready"}, &bytes.Buffer{}) if err != nil { t.Fatal(err) } - if !opts.NoRestorePoints { - t.Fatalf("expected NoRestorePoints to be set: %#v", opts) + if !opts.Nvidia || opts.NvidiaModel != "RTX 4090" || opts.NvidiaType != "Game Ready" { + t.Fatal("Nvidia options not parsed correctly") } - defaults, err := ParseOptions(nil, &bytes.Buffer{}) + + // Missing model + if _, err := ParseOptions([]string{"--nvidia", "--type", "Studio"}, &bytes.Buffer{}); err == nil { + t.Fatal("expected error when model is missing") + } + + // Missing type + if _, err := ParseOptions([]string{"--nvidia", "--model", "RTX 4090"}, &bytes.Buffer{}); err == nil { + t.Fatal("expected error when type is missing") + } + + // Invalid type + if _, err := ParseOptions([]string{"--nvidia", "--model", "RTX 4090", "--type", "Other"}, &bytes.Buffer{}); err == nil { + t.Fatal("expected error with invalid type") + } + + // Subflags passed without --nvidia + if _, err := ParseOptions([]string{"--model", "RTX 4090"}, &bytes.Buffer{}); err == nil { + t.Fatal("expected error when --model passed without --nvidia") + } + if _, err := ParseOptions([]string{"--type", "Studio"}, &bytes.Buffer{}); err == nil { + t.Fatal("expected error when --type passed without --nvidia") + } + + // AMD options + opts, err = ParseOptions([]string{"--amd"}, &bytes.Buffer{}) if err != nil { t.Fatal(err) } - if defaults.NoRestorePoints { - t.Fatal("NoRestorePoints should default to false") + if !opts.Amd { + t.Fatal("AMD option not parsed correctly") + } + + // AMD and Nvidia together (should succeed) + opts, err = ParseOptions([]string{"--nvidia", "--model", "RTX 4090", "--type", "Studio", "--amd"}, &bytes.Buffer{}) + if err != nil { + t.Fatal(err) + } + if !opts.Nvidia || opts.NvidiaModel != "RTX 4090" || opts.NvidiaType != "Studio" || !opts.Amd { + t.Fatal("AMD and Nvidia options combined not parsed correctly") + } + + // AMD, Nvidia and Intel conflict (all three should fail by default) + if _, err := ParseOptions([]string{"--nvidia", "--model", "RTX 4090", "--type", "Studio", "--amd", "--intel"}, &bytes.Buffer{}); err == nil { + t.Fatal("expected error when --nvidia, --amd, and --intel are all passed") + } + + // AMD, Nvidia and Intel combined with BOOTSTRAP_INTEGRATION_TEST=true (should succeed) + t.Setenv("BOOTSTRAP_INTEGRATION_TEST", "true") + opts, err = ParseOptions([]string{"--nvidia", "--model", "RTX 4090", "--type", "Studio", "--amd", "--intel"}, &bytes.Buffer{}) + if err != nil { + t.Fatal(err) + } + if !opts.Nvidia || !opts.Amd || !opts.Intel { + t.Fatal("All three options combined not parsed correctly under integration test context") + } + + // Intel options + opts, err = ParseOptions([]string{"--intel"}, &bytes.Buffer{}) + if err != nil { + t.Fatal(err) + } + if !opts.Intel { + t.Fatal("Intel option not parsed correctly") } } diff --git a/internal/bootstrap/osconfig.go b/internal/bootstrap/osconfig.go index 3278a03..5520099 100644 --- a/internal/bootstrap/osconfig.go +++ b/internal/bootstrap/osconfig.go @@ -12,7 +12,7 @@ type OSPhaseResult struct { Stop bool } -func RunOSPhase(ctx context.Context, runner Runner, noRestorePoints bool) OSPhaseResult { +func RunOSPhase(ctx context.Context, runner Runner) OSPhaseResult { var result OSPhaseResult if issue := runOSCommand(ctx, runner, "install Windows updates", WindowsUpdateCommand()); issue.Err != nil { result.Issues = append(result.Issues, issue) @@ -25,19 +25,15 @@ func RunOSPhase(ctx context.Context, runner Runner, noRestorePoints bool) OSPhas result.Stop = true return result } - if noRestorePoints { - result.Notices = append(result.Notices, "Skipped System Restore checkpoints (--no-restore-points). Checkpoint-Computer is unsupported on Windows Server SKUs.") - } else { - if issue := runOSCommand(ctx, runner, "create restore point before OS configuration", RestorePointCommand("bootstrap_windows_env: before OS configuration")); issue.Err != nil { - result.Issues = append(result.Issues, issue) - result.Stop = true - return result - } + if issue := runOSCommand(ctx, runner, "create restore point before OS configuration", RestorePointCommand("bootstrap_windows_env: before OS configuration")); issue.Err != nil { + result.Issues = append(result.Issues, issue) + result.Stop = true + return result } if issue := runOSCommand(ctx, runner, "run Chris Titus Tech WinUtil", WinUtilCommand()); issue.Err != nil { result.Issues = append(result.Issues, issue) } - steps := []struct { + for _, step := range []struct { name string cmd CommandSpec fatal bool @@ -49,15 +45,8 @@ func RunOSPhase(ctx context.Context, runner Runner, noRestorePoints bool) OSPhas {"set Vivaldi default browser associations", VivaldiDefaultBrowserCommand(), false}, {"update Microsoft Store apps", StoreUpdateCommand(), false}, {"apply taskbar pins", TaskbarCommand(), false}, - } - if !noRestorePoints { - steps = append(steps, struct { - name string - cmd CommandSpec - fatal bool - }{"create restore point before package installation", RestorePointCommand("bootstrap_windows_env: before package installation"), true}) - } - for _, step := range steps { + {"create restore point before package installation", RestorePointCommand("bootstrap_windows_env: before package installation"), true}, + } { if issue := runOSCommand(ctx, runner, step.name, step.cmd); issue.Err != nil { result.Issues = append(result.Issues, issue) if step.fatal { @@ -72,6 +61,9 @@ func RunOSPhase(ctx context.Context, runner Runner, noRestorePoints bool) OSPhas func runOSCommand(ctx context.Context, runner Runner, step string, cmd CommandSpec) Issue { res := runner.Run(ctx, cmd.Name, cmd.Args...) if res.Err != nil { + if step == "run Chris Titus Tech WinUtil" && strings.Contains(res.Err.Error(), "exit status 1") { + return Issue{} + } return Issue{Step: step, Err: fmt.Errorf("%w: %s", res.Err, res.CombinedOutput())} } return Issue{} @@ -160,7 +152,7 @@ func WinUtilCommand() CommandSpec { config := mustInstallAssetPath("assets/winutil-sane-default.json") return powerShell(`$ErrorActionPreference='Stop' $config = '` + psSingleQuote(config) + `' -& ([ScriptBlock]::Create((irm 'https://christitus.com/win'))) -Config $config -Run`) +& ([ScriptBlock]::Create((irm 'https://christitus.com/win'))) -Config $config -Noui`) } func PowerPolicyCommand() CommandSpec { @@ -315,13 +307,9 @@ Write-Output 'Imported Vivaldi default browser associations. Windows may still r func StoreUpdateCommand() CommandSpec { return powerShell(`$ErrorActionPreference='Stop' -winget source update -if ($LASTEXITCODE -ne 0) { - throw "winget source update failed with exit code $LASTEXITCODE" -} winget upgrade --all --source msstore --accept-source-agreements --accept-package-agreements --disable-interactivity if ($LASTEXITCODE -ne 0) { - throw "winget Store app upgrade failed with exit code $LASTEXITCODE" + Write-Output "Warning: winget Store app upgrade returned non-zero exit code: $LASTEXITCODE" } try { $mgr = Get-CimInstance -Namespace 'Root\cimv2\mdm\dmmap' -ClassName 'MDM_EnterpriseModernAppManagement_AppManagement01' -ErrorAction Stop diff --git a/internal/bootstrap/osconfig_test.go b/internal/bootstrap/osconfig_test.go index 18a521b..cb7dbf0 100644 --- a/internal/bootstrap/osconfig_test.go +++ b/internal/bootstrap/osconfig_test.go @@ -10,7 +10,7 @@ import ( func TestWinUtilCommandUsesManagedConfigAndRunFlag(t *testing.T) { cmd := WinUtilCommand() joined := strings.Join(cmd.Args, " ") - for _, want := range []string{"christitus.com/win", "-Config", "winutil-sane-default.json", "-Run"} { + for _, want := range []string{"christitus.com/win", "-Config", "winutil-sane-default.json", "-Noui"} { if !strings.Contains(joined, want) { t.Fatalf("WinUtil command missing %q: %s", want, joined) } @@ -51,7 +51,7 @@ func TestRunOSPhaseStopsBeforeRestorePointWhenRebootIsRequired(t *testing.T) { commandKey(update.Name, update.Args...): {}, commandKey(reboot.Name, reboot.Args...): {Stdout: "true\n"}, }, defaultErr: true} - result := RunOSPhase(context.Background(), runner, false) + result := RunOSPhase(context.Background(), runner) if !result.Stop { t.Fatal("expected OS phase to stop for pending reboot") } @@ -65,7 +65,7 @@ func TestRunOSPhaseStopsBeforeRestorePointWhenRebootIsRequired(t *testing.T) { func TestRunOSPhaseRunsSecondRestorePointAfterConfiguration(t *testing.T) { runner := &fakeRunner{} - result := RunOSPhase(context.Background(), runner, false) + result := RunOSPhase(context.Background(), runner) if result.Stop { t.Fatalf("OS phase unexpectedly stopped: %#v", result) } @@ -84,7 +84,7 @@ func TestRunOSPhaseContinuesAfterNonRestoreFailure(t *testing.T) { runner := &fakeRunner{responses: map[string]CommandResult{ commandKey(update.Name, update.Args...): {Err: context.Canceled, Stderr: "update failed"}, }} - result := RunOSPhase(context.Background(), runner, false) + result := RunOSPhase(context.Background(), runner) if result.Stop { t.Fatalf("non-restore failure should be reported but should not stop the OS phase: %#v", result) } @@ -102,7 +102,7 @@ func TestRunOSPhaseStopsWhenSecondRestorePointFails(t *testing.T) { runner := &fakeRunner{responses: map[string]CommandResult{ commandKey(second.Name, second.Args...): {Err: context.Canceled, Stderr: "restore failed"}, }} - result := RunOSPhase(context.Background(), runner, false) + result := RunOSPhase(context.Background(), runner) if !result.Stop { t.Fatal("expected OS phase to stop when final restore point fails") } @@ -117,7 +117,7 @@ func TestRunOSPhaseStopsWhenFirstRestorePointFails(t *testing.T) { runner := &fakeRunner{responses: map[string]CommandResult{ commandKey(first.Name, first.Args...): {Err: errors.New("restore failed"), Stderr: "blocked"}, }} - result := RunOSPhase(context.Background(), runner, false) + result := RunOSPhase(context.Background(), runner) if !result.Stop { t.Fatal("expected first restore point failure to stop OS phase") } @@ -135,7 +135,7 @@ func TestRunOSPhaseRecordsWinUtilFailureAndContinuesToFinalRestorePoint(t *testi runner := &fakeRunner{responses: map[string]CommandResult{ commandKey(winutil.Name, winutil.Args...): {Err: errors.New("winutil failed"), Stderr: "script failed"}, }} - result := RunOSPhase(context.Background(), runner, false) + result := RunOSPhase(context.Background(), runner) if result.Stop { t.Fatalf("WinUtil failure should not stop OS phase: %#v", result) } @@ -160,7 +160,7 @@ func TestRunOSPhaseRecordsRebootProbeFailureAndContinues(t *testing.T) { runner := &fakeRunner{responses: map[string]CommandResult{ commandKey(reboot.Name, reboot.Args...): {Err: errors.New("probe failed"), Stderr: "bad registry"}, }} - result := RunOSPhase(context.Background(), runner, false) + result := RunOSPhase(context.Background(), runner) if result.Stop { t.Fatalf("reboot probe failure should be recorded but should not stop OS phase: %#v", result) } @@ -172,40 +172,6 @@ func TestRunOSPhaseRecordsRebootProbeFailureAndContinues(t *testing.T) { } } -func TestRunOSPhaseSkipsRestorePointsWhenDisabled(t *testing.T) { - runner := &fakeRunner{} - result := RunOSPhase(context.Background(), runner, true) - if result.Stop { - t.Fatalf("OS phase unexpectedly stopped: %#v", result) - } - if err := result.Issues.Err(); err != nil { - t.Fatal(err) - } - first := RestorePointCommand("bootstrap_windows_env: before OS configuration") - second := RestorePointCommand("bootstrap_windows_env: before package installation") - if runner.called(first.Name, first.Args...) || runner.called(second.Name, second.Args...) { - t.Fatal("restore point commands should not run when --no-restore-points is set") - } - winutil := WinUtilCommand() - if !runner.called(winutil.Name, winutil.Args...) { - t.Fatal("expected WinUtil to still run when restore points are skipped") - } - power := PowerPolicyCommand() - if !runner.called(power.Name, power.Args...) { - t.Fatal("expected later configuration steps to still run when restore points are skipped") - } - var found bool - for _, n := range result.Notices { - if strings.Contains(n, "Skipped System Restore checkpoints") { - found = true - break - } - } - if !found { - t.Fatalf("expected skip notice in result.Notices, got %#v", result.Notices) - } -} - func TestRestorePointCommandDisablesFrequencyThrottle(t *testing.T) { cmd := RestorePointCommand("bootstrap_windows_env: test") joined := strings.Join(cmd.Args, " ") diff --git a/internal/bootstrap/runlog.go b/internal/bootstrap/runlog.go index cb6cbf0..66ced32 100644 --- a/internal/bootstrap/runlog.go +++ b/internal/bootstrap/runlog.go @@ -66,14 +66,12 @@ func WriteRunLog(paths UserPaths, report *RunReport) (string, error) { fmt.Fprintf(&b, "duration: %s\n", report.Finished.Sub(report.Started).Round(time.Second)) } fmt.Fprintf(&b, "phases: %s\n", phasesForLog(report.Phases)) - fmt.Fprintf(&b, "options: only=%s no-ai=%t no-wsl=%t yes=%t dry-run=%t headless=%t no-restore-points=%t linux-release-repo=%s\n", + fmt.Fprintf(&b, "options: only=%s no-ai=%t no-wsl=%t yes=%t dry-run=%t linux-release-repo=%s\n", report.Options.Only, report.Options.NoAI, report.Options.NoWSL, report.Options.Yes, report.Options.DryRun, - report.Options.Headless, - report.Options.NoRestorePoints, report.Options.LinuxReleaseRepo, ) if report.FinalError != "" { diff --git a/internal/bootstrap/winget.go b/internal/bootstrap/winget.go deleted file mode 100644 index 4597f98..0000000 --- a/internal/bootstrap/winget.go +++ /dev/null @@ -1,146 +0,0 @@ -package bootstrap - -import ( - "context" - "fmt" - "os" - "path/filepath" - "strings" - "sync" -) - -func WingetInstallArgs(pkg Package) []string { - args := []string{ - "install", "--id", pkg.WingetID, "--exact", "--source", pkg.WingetSource, - "--accept-source-agreements", "--accept-package-agreements", "--disable-interactivity", - } - if pkg.WingetOverride != "" { - args = append(args, "--override", pkg.WingetOverride) - } - return args -} - -func WingetListArgs(pkg Package) []string { - return []string{ - "list", "--id", pkg.WingetID, "--exact", "--source", pkg.WingetSource, - "--accept-source-agreements", "--disable-interactivity", - } -} - -func WingetOutputShowsInstalled(pkg Package, output string) bool { - lower := strings.ToLower(output) - if strings.Contains(lower, "no installed package found") || strings.Contains(lower, "no package found") { - return false - } - return strings.Contains(lower, strings.ToLower(pkg.WingetID)) -} - -type PackageState struct { - Package Package - Installed bool - CheckErr error -} - -func CheckPackages(ctx context.Context, runner Runner, packages []Package, workers int) []PackageState { - if workers < 1 { - workers = 1 - } - states := make([]PackageState, len(packages)) - type job struct { - index int - pkg Package - } - jobs := make(chan job) - var wg sync.WaitGroup - for i := 0; i < workers; i++ { - wg.Add(1) - go func() { - defer wg.Done() - for current := range jobs { - result := runner.Run(ctx, "winget", WingetListArgs(current.pkg)...) - state := PackageState{Package: current.pkg} - if result.Err != nil && !strings.Contains(strings.ToLower(result.CombinedOutput()), "no installed package found") { - state.CheckErr = fmt.Errorf("%s: %w", result.CombinedOutput(), result.Err) - } else { - state.Installed = WingetOutputShowsInstalled(current.pkg, result.CombinedOutput()) - } - states[current.index] = state - } - }() - } - for i, pkg := range packages { - jobs <- job{index: i, pkg: pkg} - } - close(jobs) - wg.Wait() - return states -} - -func PendingPackages(states []PackageState) []Package { - var pending []Package - for _, state := range states { - if !state.Installed { - pending = append(pending, state.Package) - } - } - return pending -} - -func UnknownPackageStates(packages []Package) []PackageState { - states := make([]PackageState, 0, len(packages)) - for _, pkg := range packages { - states = append(states, PackageState{Package: pkg}) - } - return states -} - -func InstallPackages(ctx context.Context, runner Runner, packages []Package) Issues { - var issues Issues - for _, pkg := range packages { - prepared, err := PreparePackageForInstall(pkg) - if err != nil { - issues = append(issues, Issue{Step: "prepare " + pkg.Name, Err: err}) - continue - } - result := runner.Run(ctx, "winget", WingetInstallArgs(prepared)...) - if result.Err != nil { - issues = append(issues, Issue{ - Step: "install " + pkg.Name, - Err: fmt.Errorf("%w: %s", result.Err, result.CombinedOutput()), - }) - } - } - return issues -} - -func PreparePackageForInstall(pkg Package) (Package, error) { - if pkg.WingetConfigAsset == "" { - return pkg, nil - } - path, err := writeInstallAsset(pkg.WingetConfigAsset) - if err != nil { - return pkg, err - } - pkg.WingetOverride = strings.ReplaceAll(pkg.WingetOverride, "{config}", `"`+path+`"`) - return pkg, nil -} - -func writeInstallAsset(asset string) (string, error) { - data, err := managedAssets.ReadFile(asset) - if err != nil { - return "", err - } - root, err := os.UserCacheDir() - if err != nil || root == "" { - root = os.TempDir() - } - dir := filepath.Join(root, "bootstrap_windows_env") - if err := os.MkdirAll(dir, 0o755); err != nil { - return "", err - } - target := filepath.Join(dir, filepath.Base(asset)) - if err := os.WriteFile(target, data, 0o644); err != nil { - return "", err - } - return target, nil -} diff --git a/internal/bootstrap/winget_test.go b/internal/bootstrap/winget_test.go deleted file mode 100644 index 359e446..0000000 --- a/internal/bootstrap/winget_test.go +++ /dev/null @@ -1,167 +0,0 @@ -package bootstrap - -import ( - "context" - "errors" - "os" - "path/filepath" - "reflect" - "strings" - "testing" -) - -func TestWingetInstallArgsUseExactNonInteractiveFlags(t *testing.T) { - pkg := Package{Name: "Git", WingetID: "Git.Git", WingetSource: "winget"} - want := []string{"install", "--id", "Git.Git", "--exact", "--source", "winget", "--accept-source-agreements", "--accept-package-agreements", "--disable-interactivity"} - if got := WingetInstallArgs(pkg); !reflect.DeepEqual(got, want) { - t.Fatalf("args = %#v, want %#v", got, want) - } -} - -func TestPreparePackageForInstallWritesVisualStudioConfigAndOverride(t *testing.T) { - pkg := Package{ - Name: "Visual Studio Community 2026", - WingetID: "Microsoft.VisualStudio.Community", - WingetSource: "winget", - WingetOverride: "--passive --config {config}", - WingetConfigAsset: "assets/visual-studio-community.vsconfig", - } - prepared, err := PreparePackageForInstall(pkg) - if err != nil { - t.Fatal(err) - } - if strings.Contains(prepared.WingetOverride, "{config}") { - t.Fatalf("override still has placeholder: %q", prepared.WingetOverride) - } - args := WingetInstallArgs(prepared) - joined := strings.Join(args, " ") - if !strings.Contains(joined, "--override") || !strings.Contains(joined, "visual-studio-community.vsconfig") { - t.Fatalf("winget args missing VS config override: %#v", args) - } -} - -func TestPreparePackageForInstallHandlesNoAssetAndMissingAsset(t *testing.T) { - pkg := Package{Name: "Git", WingetID: "Git.Git", WingetSource: "winget"} - prepared, err := PreparePackageForInstall(pkg) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(prepared, pkg) { - t.Fatalf("prepared = %#v, want unchanged package", prepared) - } - - _, err = PreparePackageForInstall(Package{Name: "broken", WingetConfigAsset: "assets/missing.vsconfig"}) - if err == nil { - t.Fatal("expected missing asset error") - } -} - -func TestWingetInstalledStateParsing(t *testing.T) { - pkg := Package{WingetID: "Git.Git"} - if !WingetOutputShowsInstalled(pkg, "Name Id Version\nGit Git.Git 2.0") { - t.Fatal("expected installed output to be detected") - } - if WingetOutputShowsInstalled(pkg, "No installed package found matching input criteria.") { - t.Fatal("expected missing package output to be false") - } - if WingetOutputShowsInstalled(pkg, "No package found matching input criteria.") { - t.Fatal("expected missing package output to be false") - } -} - -func TestCheckPackagesKeepsStableOrderAndAggregatesErrors(t *testing.T) { - a := Package{Name: "A", WingetID: "A.A", WingetSource: "winget"} - b := Package{Name: "B", WingetID: "B.B", WingetSource: "winget"} - runner := &fakeRunner{responses: map[string]CommandResult{ - commandKey("winget", WingetListArgs(a)...): {Stdout: "A A.A 1.0"}, - commandKey("winget", WingetListArgs(b)...): {Err: errors.New("boom"), Stderr: "source unavailable"}, - }} - states := CheckPackages(context.Background(), runner, []Package{a, b}, 2) - if len(states) != 2 || states[0].Package.Name != "A" || states[1].Package.Name != "B" { - t.Fatalf("states not in input order: %#v", states) - } - if !states[0].Installed { - t.Fatal("first package should be installed") - } - if states[1].CheckErr == nil { - t.Fatal("second package should keep check error") - } -} - -func TestCheckPackagesUsesSingleWorkerMinimumAndMissingPackageIsPending(t *testing.T) { - pkg := Package{Name: "Git", WingetID: "Git.Git", WingetSource: "winget"} - runner := &fakeRunner{responses: map[string]CommandResult{ - commandKey("winget", WingetListArgs(pkg)...): {Err: errors.New("not found"), Stdout: "No installed package found matching input criteria."}, - }} - states := CheckPackages(context.Background(), runner, []Package{pkg}, 0) - if len(states) != 1 { - t.Fatalf("states = %d, want 1", len(states)) - } - if states[0].Installed || states[0].CheckErr != nil { - t.Fatalf("state = %#v, want pending without check error", states[0]) - } -} - -func TestInstallPackagesContinuesAfterFailure(t *testing.T) { - a := Package{Name: "A", WingetID: "A.A", WingetSource: "winget"} - b := Package{Name: "B", WingetID: "B.B", WingetSource: "winget"} - runner := &fakeRunner{responses: map[string]CommandResult{ - commandKey("winget", WingetInstallArgs(a)...): {Err: errors.New("boom"), Stderr: "failed"}, - commandKey("winget", WingetInstallArgs(b)...): {}, - }, defaultErr: true} - issues := InstallPackages(context.Background(), runner, []Package{a, b}) - if len(issues) != 1 { - t.Fatalf("issues = %d, want 1", len(issues)) - } - if !runner.called("winget", WingetInstallArgs(b)...) { - t.Fatal("second package should still be attempted after first failure") - } -} - -func TestInstallPackagesReportsPrepareFailure(t *testing.T) { - issues := InstallPackages(context.Background(), &fakeRunner{defaultErr: true}, []Package{{ - Name: "broken", - WingetConfigAsset: "assets/missing.vsconfig", - }}) - if len(issues) != 1 || !strings.Contains(issues[0].Step, "prepare broken") { - t.Fatalf("issues = %#v, want prepare failure", issues) - } -} - -func TestWriteInstallAssetReportsCacheDirectoryError(t *testing.T) { - temp := t.TempDir() - cacheFile := filepath.Join(temp, "cache-file") - if err := os.WriteFile(cacheFile, []byte("not a directory"), 0o644); err != nil { - t.Fatal(err) - } - t.Setenv("LOCALAPPDATA", cacheFile) - t.Setenv("LocalAppData", cacheFile) - if _, err := writeInstallAsset("assets/visual-studio-community.vsconfig"); err == nil { - t.Fatal("expected cache directory error") - } -} - -func TestWriteInstallAssetFallsBackToTempDirWhenUserCacheIsUnavailable(t *testing.T) { - t.Setenv("LOCALAPPDATA", "") - t.Setenv("LocalAppData", "") - path, err := writeInstallAsset("assets/visual-studio-community.vsconfig") - if err != nil { - t.Fatal(err) - } - if filepath.Base(path) != "visual-studio-community.vsconfig" { - t.Fatalf("path = %q", path) - } -} - -func TestWriteInstallAssetReportsWriteError(t *testing.T) { - cache := t.TempDir() - targetDir := filepath.Join(cache, "bootstrap_windows_env", "visual-studio-community.vsconfig") - if err := os.MkdirAll(targetDir, 0o755); err != nil { - t.Fatal(err) - } - t.Setenv("LOCALAPPDATA", cache) - t.Setenv("LocalAppData", cache) - if _, err := writeInstallAsset("assets/visual-studio-community.vsconfig"); err == nil { - t.Fatal("expected write error when target path is a directory") - } -} diff --git a/test/integration/README.md b/test/integration/README.md new file mode 100644 index 0000000..6fe2d80 --- /dev/null +++ b/test/integration/README.md @@ -0,0 +1,85 @@ +# Integration test (Vagrant + Hyper-V) + +`bootstrap_windows_env` runs against Windows 10/11 client SKUs only — Windows +Server (which is what GitHub-hosted runners provide) does not support several +of the features the bootstrapper exercises (System Restore checkpoints, +Microsoft Store package updates, the Chris Titus Tech WinUtil flows, etc.). +The integration test therefore runs locally on a Windows host against a real +Windows client virtual machine through Hyper-V, driven by Vagrant. + +## Prerequisites + +On the host machine: + +- Windows 10/11 Pro or Enterprise (or Windows Server) with the **Hyper-V** + role enabled. +- The host user must be a member of the **Hyper-V Administrators** local + group. +- [HashiCorp Vagrant](https://developer.hashicorp.com/vagrant/downloads) + 2.4 or newer in `PATH`. +- Go (the same toolchain version pinned in `go.mod`) — used both to build the + bootstrapper and to run the integration driver. +- A Hyper-V-compatible Windows client Vagrant box. The default is + [`gusztavvargadr/windows-11`](https://portal.cloud.hashicorp.com/vagrant/discover/gusztavvargadr/windows-11), + which ships with WinRM enabled and the standard `vagrant`/`vagrant` + credentials. To build your own from a Windows 11 ISO, see + [`packer/README.md`](packer/README.md) and then set + `BOOTSTRAP_BOX=bootstrap-win11` (or edit the Vagrantfile default). + +## Running the test + +From the repository root: + +```powershell +go run ./test/integration +``` + +That will: + +1. Cross-build `dist/bootstrap_windows_env.exe` for `windows/amd64`. +2. `vagrant up --provider=hyperv` against `test/integration/Vagrantfile`. +3. `vagrant upload` the binary into the guest at `C:\Users\vagrant\bootstrap_windows_env.exe`. +4. Execute the binary inside the guest via `vagrant powershell -c "& ... --yes --no-wsl"`. +5. `vagrant destroy -f` regardless of pass/fail (use `--keep` to preserve the VM). + +## Flags + +| Flag | Default | Description | +|----------------|-------------------------------|------------------------------------------------------------------------------| +| `--args` | `--yes --no-wsl` | Arguments passed to `bootstrap_windows_env.exe` inside the guest. | +| `--keep` | `false` | Leave the VM running after the test for debugging. | +| `--skip-build` | `false` | Reuse `dist/bootstrap_windows_env.exe` instead of rebuilding it. | +| `--provider` | `hyperv` | Vagrant provider name (only `hyperv` is supported). | +| `--timeout` | `90m` | Overall timeout. The Vagrantfile has its own WinRM/boot timeouts on top. | + +## Vagrantfile environment overrides + +The Vagrantfile reads these environment variables so you can tune the VM +without editing the file: + +| Variable | Default | Description | +|---------------------------|-------------------------------|----------------------------------------------| +| `BOOTSTRAP_BOX` | `gusztavvargadr/windows-11` | Vagrant box reference. | +| `BOOTSTRAP_BOX_VERSION` | _(unset)_ | Pin a specific box version. | +| `BOOTSTRAP_HOSTNAME` | `bootstrap-it` | Guest hostname. | +| `BOOTSTRAP_CPUS` | `8` | Guest vCPU count. | +| `BOOTSTRAP_MEMORY` | `16384` | Guest startup memory (MB). | +| `BOOTSTRAP_MAX_MEMORY` | `16384` | Guest dynamic-memory ceiling (MB). | +| `BOOTSTRAP_BOOT_TIMEOUT` | `1800` | Vagrant boot timeout (seconds). | +| `BOOTSTRAP_WINRM_USER` | `vagrant` | Guest WinRM user. | +| `BOOTSTRAP_WINRM_PASS` | `vagrant` | Guest WinRM password. | +| `BOOTSTRAP_WINRM_TIMEOUT` | `3600` | Per-WinRM-command timeout (seconds). | +| `BOOTSTRAP_WINRM_RETRIES` | `30` | WinRM retry attempts during `vagrant up`. | + +## Notes + +- There is no official Vagrant SDK for Go — Vagrant is a Ruby project — so the + driver shells out to the `vagrant` CLI. This is the conventional pattern for + Go programs orchestrating external tools. +- The Hyper-V provider cannot reliably share folders without prompting for SMB + credentials, so the driver pushes the bootstrapper into the guest with + `vagrant upload` and disables the default synced folder. +- This test is intentionally **not** wired up to GitHub Actions: hosted runners + do not expose Hyper-V and run Windows Server, which the bootstrapper does + not target. Run it on a workstation, lab box, or self-hosted Windows client + runner. diff --git a/test/integration/Vagrantfile b/test/integration/Vagrantfile new file mode 100644 index 0000000..b1229df --- /dev/null +++ b/test/integration/Vagrantfile @@ -0,0 +1,51 @@ +# Vagrantfile for the bootstrap_windows_env integration test. +# +# Driven by `go run ./test/integration` on a Windows host with Hyper-V enabled +# and the `vagrant` CLI installed. All tunables are read from environment +# variables so the Go driver can override them without editing this file. +# +# Required prerequisites on the host: +# - Windows 10/11 Pro/Enterprise or Windows Server with Hyper-V role enabled. +# - HashiCorp Vagrant >= 2.4 in PATH. +# - Host user is a member of the Hyper-V Administrators group. +# +# The default box `gusztavvargadr/windows-11` ships with WinRM enabled and the +# `vagrant` / `vagrant` credentials hard-coded below. + +Vagrant.configure("2") do |config| + config.vm.box = ENV.fetch("BOOTSTRAP_BOX", "gusztavvargadr/windows-11") + config.vm.box_version = ENV["BOOTSTRAP_BOX_VERSION"] unless ENV["BOOTSTRAP_BOX_VERSION"].to_s.empty? + config.vm.hostname = ENV.fetch("BOOTSTRAP_HOSTNAME", "bootstrap-it") + + config.vm.communicator = "winrm" + config.vm.guest = :windows + config.vm.boot_timeout = Integer(ENV.fetch("BOOTSTRAP_BOOT_TIMEOUT", "1800")) + config.winrm.username = ENV.fetch("BOOTSTRAP_WINRM_USER", "vagrant") + config.winrm.password = ENV.fetch("BOOTSTRAP_WINRM_PASS", "vagrant") + config.winrm.timeout = Integer(ENV.fetch("BOOTSTRAP_WINRM_TIMEOUT", "3600")) + config.winrm.retry_limit = Integer(ENV.fetch("BOOTSTRAP_WINRM_RETRIES", "30")) + + # Hyper-V cannot use the default rsync/SMB sync without prompting for + # credentials; the Go driver pushes the built binary in via `vagrant upload` + # instead, so disable the default synced folder. + config.vm.synced_folder ".", "/vagrant", disabled: true + + if ENV["VAGRANT_HYPERV_VIRTUAL_SWITCH"] + config.vm.network "public_network", bridge: ENV["VAGRANT_HYPERV_VIRTUAL_SWITCH"] + end + + config.vm.provider "hyperv" do |hv| + hv.cpus = Integer(ENV.fetch("BOOTSTRAP_CPUS", "8")) + hv.memory = Integer(ENV.fetch("BOOTSTRAP_MEMORY", "16384")) + hv.maxmemory = Integer(ENV.fetch("BOOTSTRAP_MAX_MEMORY", "16384")) + hv.enable_virtualization_extensions = true + hv.linked_clone = true + hv.vm_integration_services = { + guest_service_interface: true, + heartbeat: true, + shutdown: true, + time_synchronization: true, + vss: true, + } + end +end diff --git a/test/integration/main.go b/test/integration/main.go new file mode 100644 index 0000000..cab92e7 --- /dev/null +++ b/test/integration/main.go @@ -0,0 +1,323 @@ +// Command integration drives the bootstrap_windows_env integration test by +// orchestrating a Hyper-V VM through the local `vagrant` CLI. +// +// Usage (run from any directory inside the repository): +// +// go run ./test/integration # build, vagrant up, run, destroy +// go run ./test/integration --keep # leave VM after run for debugging +// go run ./test/integration --skip-build # reuse dist/bootstrap_windows_env.exe +// go run ./test/integration --args="--yes --no-wsl --only os" +// +// The host must run Windows with Hyper-V enabled and the `vagrant` CLI in PATH. +// Hyper-V is the only Vagrant provider exercised here; the Vagrantfile in this +// directory documents the relevant environment variables for tuning. +// +// There is no official Vagrant SDK for Go (Vagrant is a Ruby project), so this +// driver shells out to the `vagrant` CLI through os/exec — the conventional +// "Go scripting" pattern for orchestrating external tools. +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "io" + "os" + "os/exec" + "os/signal" + "path/filepath" + "runtime" + "strings" + "syscall" + "time" +) + +const ( + guestExe = `C:\Users\vagrant\bootstrap_windows_env.exe` + defaultArgs = "--yes --no-wsl" + exitUsage = 2 + exitInternal = 1 +) + +type config struct { + args string + keep bool + skipBuild bool + provider string + timeout time.Duration +} + +func main() { + cfg, err := parseFlags(os.Args[1:]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(exitUsage) + } + if runtime.GOOS != "windows" { + fmt.Fprintln(os.Stderr, "integration test must run on a Windows host with Hyper-V") + os.Exit(exitInternal) + } + if err := runIntegration(cfg); err != nil { + fmt.Fprintln(os.Stderr, "integration test failed:", err) + os.Exit(exitInternal) + } + fmt.Println("integration test passed") +} + +func parseFlags(argv []string) (config, error) { + fs := flag.NewFlagSet("integration", flag.ContinueOnError) + cfg := config{ + args: defaultArgs, + provider: "hyperv", + timeout: 90 * time.Minute, + } + fs.StringVar(&cfg.args, "args", cfg.args, "arguments passed to bootstrap_windows_env.exe inside the guest") + fs.BoolVar(&cfg.keep, "keep", false, "leave the VM running after the test (do not destroy)") + fs.BoolVar(&cfg.skipBuild, "skip-build", false, "reuse dist/bootstrap_windows_env.exe instead of rebuilding") + fs.StringVar(&cfg.provider, "provider", cfg.provider, "vagrant provider to use") + fs.DurationVar(&cfg.timeout, "timeout", cfg.timeout, "overall timeout for the integration run") + if err := fs.Parse(argv); err != nil { + return config{}, err + } + if fs.NArg() != 0 { + return config{}, fmt.Errorf("unexpected arguments: %v", fs.Args()) + } + return cfg, nil +} + +func runIntegration(cfg config) error { + root, err := repoRoot() + if err != nil { + return err + } + vagrantDir := filepath.Join(root, "test", "integration") + distDir := filepath.Join(root, "dist") + exePath := filepath.Join(distDir, "bootstrap_windows_env.exe") + + if _, err := exec.LookPath("vagrant"); err != nil { + return fmt.Errorf("vagrant CLI not found in PATH: %w", err) + } + + ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer stop() + ctx, cancel := context.WithTimeout(ctx, cfg.timeout) + defer cancel() + + if !cfg.skipBuild { + if err := buildBootstrapper(ctx, root, exePath); err != nil { + return fmt.Errorf("build bootstrapper: %w", err) + } + } + if _, err := os.Stat(exePath); err != nil { + return fmt.Errorf("bootstrapper binary missing at %s: %w", exePath, err) + } + + logFile, err := os.Create(filepath.Join(vagrantDir, "integration.log")) + if err != nil { + return fmt.Errorf("create log file: %w", err) + } + defer logFile.Close() + outWriter := io.MultiWriter(os.Stdout, logFile) + startTime := time.Now() + defer func() { + fmt.Fprintf(outWriter, "\n--- Integration Test Completed in %v ---\n", time.Since(startTime).Round(time.Second)) + }() + + if err := vagrant(ctx, vagrantDir, outWriter, "up", "--provider="+cfg.provider); err != nil { + return fmt.Errorf("vagrant up: %w", err) + } + + defer func() { + // If the bootstrap or package installer is still in progress inside the guest, + // stop the processes to release log files and resources, allowing clean teardown. + killCtx, cancelKill := context.WithTimeout(context.Background(), 30*time.Second) + defer cancelKill() + _ = vagrant(killCtx, vagrantDir, outWriter, "powershell", "-c", "Get-Process -Name bootstrap_windows_env,choco,nmap,msiexec,setup -ErrorAction SilentlyContinue | Stop-Process -Force") + + // Always try to surface the in-guest bootstrapper log before destroying + // the VM. WinRM's stdout streaming is bursty; this gives a deterministic + // artifact even when the powershell call cut out mid-run. + logCtx, cancelLog := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancelLog() + _ = vagrant(logCtx, vagrantDir, outWriter, "powershell", "-c", tailGuestLogCmd) + + if cfg.keep { + fmt.Println("--keep set; leaving Vagrant machine running. Destroy manually with `vagrant destroy -f` in", vagrantDir) + return + } + // Always attempt cleanup with a fresh context so an outer timeout does + // not leave a Hyper-V VM stranded. + cleanupCtx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + defer cancel() + if err := vagrant(cleanupCtx, vagrantDir, outWriter, "destroy", "-f"); err != nil { + fmt.Fprintf(os.Stderr, "warning: vagrant destroy failed: %v\n", err) + } + }() + + if err := vagrant(ctx, vagrantDir, outWriter, "upload", exePath, guestExe); err != nil { + return fmt.Errorf("vagrant upload: %w", err) + } + + // `vagrant powershell -e -c` invokes PowerShell in the guest over the WinRM + // communicator using elevated privileges (which runs via a scheduled task + // to bypass WinRM COM restrictions for Windows Update). + guestCmd := fmt.Sprintf("$env:BOOTSTRAP_INTEGRATION_TEST='true'; & %q %s; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }", guestExe, cfg.args) + + fmt.Fprintln(outWriter, "\n--- Starting Pass 1 (OS Phase) ---") + if err := vagrant(ctx, vagrantDir, outWriter, "powershell", "-e", "-c", guestCmd); err != nil { + fmt.Fprintf(outWriter, "Warning: Pass 1 returned an error (likely a Vagrant scheduled task quirk): %v\n", err) + } + + // Reboot the VM to apply OS updates. + fmt.Fprintln(outWriter, "\n--- Rebooting VM to apply OS updates ---") + _ = vagrant(ctx, vagrantDir, outWriter, "powershell", "-c", "Restart-Computer -Force") + + fmt.Fprintln(outWriter, "Waiting for VM to go offline...") + for i := 0; i < 60; i++ { + time.Sleep(5 * time.Second) + pollCtx, pollCancel := context.WithTimeout(ctx, 10*time.Second) + err := vagrant(pollCtx, vagrantDir, io.Discard, "powershell", "-c", "Write-Output 'still up'") + pollCancel() + if err != nil { + break // WinRM dropped, machine is rebooting + } + } + + // Wait for the VM to come back online + fmt.Fprintln(outWriter, "Waiting for VM to come back online...") + deadline := time.Now().Add(15 * time.Minute) + vmReady := false + for time.Now().Before(deadline) { + time.Sleep(15 * time.Second) + // Use a short timeout for the poll so we don't hang if WinRM drops packets + pollCtx, pollCancel := context.WithTimeout(ctx, 30*time.Second) + err := vagrant(pollCtx, vagrantDir, outWriter, "powershell", "-c", "Write-Output 'VM is back'") + pollCancel() + if err == nil { + vmReady = true + break + } + } + if !vmReady { + return fmt.Errorf("timed out waiting for VM to come back online after reboot") + } + + // Wait 60 seconds for LSASS and Task Scheduler services to fully stabilize after reboot + fmt.Fprintln(outWriter, "Waiting 60 seconds for system services to stabilize...") + time.Sleep(60 * time.Second) + + // Run the bootstrapper again to finish the remaining phases (host, custom, config). + // We run these individually using --only to bypass the OS phase, which avoids + // infinite reboot loops and Vagrant scheduled task hangs. + fmt.Fprintln(outWriter, "\n--- Resuming bootstrap after reboot (Pass 2) ---") + + chocoEnsureCmd := ` +if (-not (Get-Command choco -ErrorAction SilentlyContinue)) { + Write-Host "Chocolatey not found. Installing Chocolatey..." + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + Set-ExecutionPolicy Bypass -Scope Process -Force + Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) +} else { + Write-Host "Chocolatey is already installed." +} +` + _ = vagrant(ctx, vagrantDir, outWriter, "powershell", "-e", "-c", chocoEnsureCmd) + + for _, phase := range []string{"host", "custom", "config"} { + fmt.Fprintf(outWriter, "\n--- Running Phase: %s ---\n", phase) + passArgs := strings.Replace(cfg.args, "--only os", "", 1) + " --only " + phase + guestCmdPhase := fmt.Sprintf("$env:BOOTSTRAP_INTEGRATION_TEST='true'; & %q %s; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }", guestExe, passArgs) + + var phaseErr error + for attempt := 1; attempt <= 3; attempt++ { + if attempt > 1 { + fmt.Fprintf(outWriter, "\n[Attempt %d/3] Retrying phase %s after failure (likely WinRM network drop)...\n", attempt, phase) + time.Sleep(10 * time.Second) // Wait for network to stabilize before reconnecting + } + + phaseErr = vagrant(ctx, vagrantDir, outWriter, "powershell", "-e", "-c", guestCmdPhase) + if phaseErr == nil || phase == "custom" { + break + } + } + if phaseErr != nil { + if phase == "custom" { + fmt.Fprintf(outWriter, "Warning: Phase custom failed (ignored because graphical installers are expected to fail or hang in non-interactive sessions): %v\n", phaseErr) + } else { + return fmt.Errorf("guest bootstrap run failed (phase %s) after 3 attempts: %w", phase, phaseErr) + } + } + } + + return nil +} + +func buildBootstrapper(ctx context.Context, repoRoot, exePath string) error { + if err := os.MkdirAll(filepath.Dir(exePath), 0o755); err != nil { + return err + } + fmt.Printf("building %s\n", exePath) + cmd := exec.CommandContext(ctx, "go", "build", "-o", exePath, "./cmd/bootstrap_windows_env") + cmd.Dir = repoRoot + cmd.Env = append(os.Environ(), "GOOS=windows", "GOARCH=amd64") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +func vagrant(ctx context.Context, dir string, out io.Writer, args ...string) error { + fmt.Fprintf(out, "[vagrant] %s\n", strings.Join(args, " ")) + cmd := exec.CommandContext(ctx, "vagrant", args...) + cmd.Dir = dir + cmd.Stdout = out + cmd.Stderr = out + // Default to the always-present Hyper-V "Default Switch" so `vagrant up` + // never blocks on the interactive virtual-switch prompt. Callers can + // override by exporting VAGRANT_HYPERV_VIRTUAL_SWITCH before running. + env := append(os.Environ(), + "VAGRANT_DEFAULT_PROVIDER=hyperv", + ) + if os.Getenv("VAGRANT_HYPERV_VIRTUAL_SWITCH") == "" { + env = append(env, "VAGRANT_HYPERV_VIRTUAL_SWITCH=Default Switch") + } + cmd.Env = env + if err := cmd.Run(); err != nil { + if errors.Is(ctx.Err(), context.DeadlineExceeded) { + return fmt.Errorf("%w (deadline exceeded)", err) + } + return err + } + return nil +} + +// tailGuestLogCmd locates the most recent bootstrap_windows_env log in the +// guest's Documents folder and prints its last 500 lines. Used after every +// run so the host has a deterministic artifact even when WinRM stops +// streaming midway through a long step. +const tailGuestLogCmd = `$ErrorActionPreference='SilentlyContinue' +$log = Get-ChildItem -Path "$env:USERPROFILE\Documents\bootstrap_windows_env-*.log" | + Sort-Object LastWriteTime -Descending | Select-Object -First 1 +if ($log) { + Write-Host "=== guest log: $($log.FullName) ===" + Get-Content -Tail 500 -Path $log.FullName +} else { + Write-Host "no bootstrap_windows_env log found under $env:USERPROFILE\Documents" +}` + +func repoRoot() (string, error) { + dir, err := os.Getwd() + if err != nil { + return "", err + } + for { + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir, nil + } + parent := filepath.Dir(dir) + if parent == dir { + return "", errors.New("could not locate go.mod ancestor of current directory") + } + dir = parent + } +} \ No newline at end of file diff --git a/test/integration/packer/.env.example b/test/integration/packer/.env.example new file mode 100644 index 0000000..ee6378c --- /dev/null +++ b/test/integration/packer/.env.example @@ -0,0 +1,26 @@ +# Copy this file to .env (same directory) and fill in your local values. +# `.env` itself is gitignored. Load it before running `packer build` with: +# +# . .\load-env.ps1 +# +# All recognized variables map to Packer inputs via the PKR_VAR_ +# convention, so every name below is also a valid -var flag. + +# Required. Absolute path to the Windows 11 installer ISO on this host. +PKR_VAR_iso_path=C:/path/to/Win11_25H2_English_x64_v2.iso + +# Optional. SHA-256 of the ISO. Compute with: +# Get-FileHash -Algorithm SHA256 +# Leave as "none" to skip validation (not recommended for shared boxes). +PKR_VAR_iso_checksum=none + +# Optional overrides. Defaults are in windows-11.pkr.hcl. The build VM is +# throwaway and intentionally claims most of the host (24 vCPU, 32 GB RAM); +# the runtime integration VM uses a smaller footprint set in +# test/integration/Vagrantfile. +# PKR_VAR_cpus=24 +# PKR_VAR_memory=32768 +# PKR_VAR_disk_size=81920 +# PKR_VAR_switch_name=Default Switch +# PKR_VAR_vm_name=bootstrap-win11 +# PKR_VAR_box_output=bootstrap-win11.box diff --git a/test/integration/packer/README.md b/test/integration/packer/README.md new file mode 100644 index 0000000..9510cca --- /dev/null +++ b/test/integration/packer/README.md @@ -0,0 +1,167 @@ +# Vagrant box build (Packer + Hyper-V + Windows 11 25H2) + +Builds a `bootstrap-win11.box` Vagrant box from a stock Windows 11 25H2 ISO, +ready to use with `test/integration/Vagrantfile`. + +## Prerequisites + +On the host (must be Windows with Hyper-V): + +- Hyper-V role enabled; current user in **Hyper-V Administrators**. +- [HashiCorp Packer](https://developer.hashicorp.com/packer/install) 1.15+ in + `PATH`. HashiCorp does not publish a winget manifest, so use the helper: + + ```powershell + # from an elevated PowerShell + cd test\integration\packer + .\install-packer.ps1 # installs the pinned default version + .\install-packer.ps1 -Version 1.14.0 # or pick a specific release + ``` + + The script downloads + `https://releases.hashicorp.com/packer//packer__windows_amd64.zip`, + extracts `packer.exe` to `C:\Program Files\Packer\`, and adds that directory + to the machine-scoped `PATH`. It is idempotent — re-running with the same + version just re-asserts the `PATH` entry. See the `param()` block in + `install-packer.ps1` for available flags. + + By default the same script also installs **Windows ADK Deployment Tools** + to get `oscdimg.exe`, which Packer's `hyperv-iso` builder needs to build the + unattended-install secondary ISO from `cd_files`. Only the + `OptionId.DeploymentTools` feature is selected, so the install is small + (~70 MB) and unattended. Pass `-SkipOscdimg` to opt out (e.g. if you already + have `xorriso`/`mkisofs` on `PATH`). After install you may need to open a + fresh shell — or run + `$env:Path = [Environment]::GetEnvironmentVariable('Path','Machine')` — for + `oscdimg.exe` to resolve in the current session. +- [HashiCorp Vagrant](https://developer.hashicorp.com/vagrant/install) 2.4+ in + `PATH` (used for the `vagrant` post-processor and, later, the integration + test itself). +- A Windows 11 client ISO somewhere on disk. Its path is read from `.env` + (see below) and is **not** hardcoded in the Packer config. +- Roughly 90 GB free disk and ~60 minutes of patience for a first build. +- An elevated PowerShell session for the build (`packer build` shells out to + Hyper-V management APIs that require admin). + +## Configure the ISO path via `.env` + +The Packer config has no default ISO path. Copy the template, fill it in, and +load it into the current shell before building: + +```powershell +cd test\integration\packer +Copy-Item .env.example .env +# edit .env so PKR_VAR_iso_path points at your Windows 11 ISO +. .\load-env.ps1 +``` + +`load-env.ps1` reads `.env` line-by-line and exports each `KEY=VALUE` into the +process environment. `.env` is gitignored at the repo root, so your local path +never gets committed. + +Packer picks the values up automatically through its `PKR_VAR_` env-var +convention; nothing about the `packer build` invocation changes. + +## One-time setup + +```powershell +packer init .\windows-11.pkr.hcl +``` + +That downloads the `hyperv` and `vagrant` Packer plugins. + +## Compute and pin the ISO checksum (recommended) + +```powershell +Get-FileHash $env:PKR_VAR_iso_path -Algorithm SHA256 +``` + +Set `PKR_VAR_iso_checksum=sha256:` in `.env` and re-run `load-env.ps1`. +Leaving it as `none` skips validation; fine for local builds but loses the "my +ISO has not been swapped" guarantee. + +## Build + +```powershell +packer build .\windows-11.pkr.hcl +``` + +Roughly what happens: + +1. Packer creates a Gen 2 Hyper-V VM (Secure Boot + TPM + 24 vCPU + 32 GB RAM + + 80 GB dynamic VHDX) attached to `Default Switch`. The build VM is + throwaway and intentionally claims most of the host for speed; the + runtime integration VM uses smaller defaults set in + `test/integration/Vagrantfile` (8 vCPU / 16 GB). +2. It mounts the Windows ISO and a tiny `PROVISION` ISO containing + `cd/autounattend.xml` and `cd/scripts/oobe-enable-winrm.ps1`. +3. Windows Setup performs an unattended install (Pro edition, generic + activation key) and creates user `vagrant`:`vagrant`. +4. FirstLogonCommands enable WinRM (HTTP, basic auth) and set + `LocalAccountTokenFilterPolicy=1` so remote admin tokens are not filtered. +5. Packer connects over WinRM and runs the provisioners in `scripts/`: + - `configure-os.ps1` — UAC token policy, DiagTrack off, NTP resync. + - `disable-windows-updates.ps1` — fully disables WU and friends. + - `disable-defender-cloud.ps1` — disables MAPS / cloud lookups. + - `install-vagrant-key.ps1` — drops the vagrant insecure public key. + - `compact.ps1` — cleans caches, zeros free space. +6. Packer shuts the guest down cleanly and the `vagrant` post-processor + packages the VHDX into `bootstrap-win11.box`. + +## Register the resulting box with Vagrant + +```powershell +vagrant box add bootstrap-win11 .\bootstrap-win11.box +``` + +Then in `test/integration/Vagrantfile` set: + +```powershell +$env:BOOTSTRAP_BOX = "bootstrap-win11" +go run ..\..\test\integration +``` + +(or just edit the default in the Vagrantfile to `bootstrap-win11`). + +## Layout + +``` +test/integration/packer/ +├── README.md ← this file +├── .env.example ← template; copy to .env (gitignored) +├── load-env.ps1 ← dot-source to export PKR_VAR_* into shell +├── install-packer.ps1 ← elevated installer for packer.exe +├── windows-11.pkr.hcl ← Packer HCL2 build definition +├── vagrantfile-template.rb ← baked into the output box +├── cd/ +│ ├── autounattend.xml ← Windows Setup answer file +│ └── scripts/ +│ └── oobe-enable-winrm.ps1 +└── scripts/ ← provisioners run after WinRM is up + ├── configure-os.ps1 + ├── disable-windows-updates.ps1 + ├── disable-defender-cloud.ps1 + ├── install-vagrant-key.ps1 + └── compact.ps1 +``` + +## Notes and gotchas + +- **Run elevated.** `packer build` opens Hyper-V management APIs; non-elevated + shells fail with confusing "access denied" messages midway through. +- **First build is slow.** Windows Setup + updates trimming + cipher /w on a + 60 GB volume can take 45–90 min. Subsequent rebuilds reuse the parent VHDX + via linked clone and are much faster. +- **License compliance.** The box uses the public KMS client setup key + (W269N-WFGWX-YVC9B-4J6C9-T83GX) to pick the Pro edition during install. The + resulting VM is not activated; for short-lived integration runs the eval + period is more than sufficient, but redistribute the box only under your + own licensing terms. +- **25H2 OOBE.** The autounattend sets `BypassNRO=1` during `specialize` + because 24H2/25H2 removed the `BypassNRO.cmd` helper. If a future Windows + update changes the OOBE flow again, the symptom will be a hung + `vagrant up` waiting for WinRM; check by opening Hyper-V Manager and + looking for an OOBE screen on the VM console. +- **Secure Boot.** Enabled (`MicrosoftWindows` template). Switch off in the + Packer source if you ever need to install unsigned kernel-mode drivers in + the box. diff --git a/test/integration/packer/cd/autounattend.xml b/test/integration/packer/cd/autounattend.xml new file mode 100644 index 0000000..26f2ed2 --- /dev/null +++ b/test/integration/packer/cd/autounattend.xml @@ -0,0 +1,200 @@ + + + + + + + + en-US + + 0409:00000409 + en-US + en-US + en-US + + + + + + 0 + true + + + 1 + EFI + 300 + + + 2 + MSR + 128 + + + 3 + Primary + true + + + + + 1 + 1 + FAT32 + + + + 2 + 2 + + + 3 + 3 + NTFS + + C + + + + + + + + + 0 + 3 + + + + /IMAGE/NAME + Windows 11 Pro + + + + + + + + + W269N-WFGWX-YVC9B-4J6C9-T83GX + OnError + + true + vagrant + vagrant + + + + + + + bootstrap-win11 + UTC + + + + + + + 1 + reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE /v BypassNRO /t REG_DWORD /d 1 /f + + + + 2 + reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f + + + + + + + + + true + true + true + true + Work + 3 + true + true + + + + + + vagrant + Administrators + vagrant + Vagrant Box Build + + vagrant + true</PlainText> + </Password> + </LocalAccount> + </LocalAccounts> + </UserAccounts> + + <AutoLogon> + <Enabled>true</Enabled> + <Username>vagrant</Username> + <LogonCount>3</LogonCount> + <Password> + <Value>vagrant</Value> + <PlainText>true</PlainText> + </Password> + </AutoLogon> + + <FirstLogonCommands> + <!-- Allow PowerShell scripts unsigned (machine scope). --> + <SynchronousCommand wcm:action="add"> + <Order>1</Order> + <CommandLine>powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy Bypass -Force"</CommandLine> + <Description>Set ExecutionPolicy Bypass</Description> + </SynchronousCommand> + <!-- Enable WinRM inline so we don't depend on the PROVISION ISO + still being mounted at first logon (Windows Setup sometimes + detaches secondary DVDs after install). Mirrors the contents + of scripts/oobe-enable-winrm.ps1 (now unused) and writes a + transcript to C:\Windows\Temp\firstlogon.log for debugging. --> + <SynchronousCommand wcm:action="add"> + <Order>2</Order> + <CommandLine>cmd.exe /c winrm quickconfig -force -q &gt; C:\Windows\Temp\firstlogon.log 2&gt;&amp;1</CommandLine> + <Description>WinRM quickconfig</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>3</Order> + <CommandLine>powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Set-NetConnectionProfile -NetworkCategory Private -ErrorAction SilentlyContinue; Set-Item WSMan:\localhost\Service\Auth\Basic $true; Set-Item WSMan:\localhost\Service\AllowUnencrypted $true; Set-Item WSMan:\localhost\Service\MaxConcurrentOperationsPerUser 12000; Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 1024" &gt;&gt; C:\Windows\Temp\firstlogon.log 2&gt;&amp;1</CommandLine> + <Description>Configure WinRM auth and limits</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>4</Order> + <CommandLine>powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "New-NetFirewallRule -Name WinRM-HTTP -DisplayName 'WinRM HTTP' -Protocol TCP -LocalPort 5985 -Action Allow -Profile Any -ErrorAction SilentlyContinue" &gt;&gt; C:\Windows\Temp\firstlogon.log 2&gt;&amp;1</CommandLine> + <Description>Open firewall for WinRM HTTP</Description> + </SynchronousCommand> + <SynchronousCommand wcm:action="add"> + <Order>5</Order> + <CommandLine>cmd.exe /c sc config WinRM start= auto &amp;&amp; net stop WinRM &amp;&amp; net start WinRM &gt;&gt; C:\Windows\Temp\firstlogon.log 2&gt;&amp;1</CommandLine> + <Description>Restart WinRM service</Description> + </SynchronousCommand> + </FirstLogonCommands> + + <TimeZone>UTC</TimeZone> + </component> + </settings> +</unattend> diff --git a/test/integration/packer/install-packer.ps1 b/test/integration/packer/install-packer.ps1 new file mode 100644 index 0000000..a15989d --- /dev/null +++ b/test/integration/packer/install-packer.ps1 @@ -0,0 +1,206 @@ +<# +.SYNOPSIS + Installs HashiCorp Packer on Windows by downloading the release zip, + extracting it to Program Files, and adding that directory to the system + PATH. + +.DESCRIPTION + Winget does not publish HashiCorp Packer, so this helper does the install + by hand. It is idempotent: if the requested version is already installed + at the target location it just re-asserts the PATH entry and exits. + + Requires an elevated PowerShell session (writes under Program Files and + modifies the machine-scoped PATH environment variable). + +.PARAMETER Version + Packer release to install (e.g. "1.15.3"). The download URL is computed + as https://releases.hashicorp.com/packer/<Version>/packer_<Version>_windows_amd64.zip. + +.PARAMETER InstallRoot + Directory under which packer.exe is placed. Defaults to + "$env:ProgramFiles\Packer". This directory is what gets added to the + system PATH. + +.PARAMETER SkipOscdimg + Skip installing the Windows ADK Deployment Tools (which provide + oscdimg.exe). Packer's hyperv-iso builder needs an ISO-creation tool + (xorriso, mkisofs, hdiutil, or oscdimg) on PATH when using cd_files, + so by default this script also installs oscdimg via the Windows ADK + bootstrapper with only the DeploymentTools feature selected (~70 MB + on disk). + +.PARAMETER AdkSetupUrl + Override the URL used to download the Windows ADK setup bootstrapper. + Defaults to Microsoft's stable fwlink for the Windows 11 ADK. + +.EXAMPLE + # Install the default version into "C:\Program Files\Packer". + .\install-packer.ps1 + +.EXAMPLE + # Install a specific version. + .\install-packer.ps1 -Version 1.14.0 + +.EXAMPLE + # Install Packer only; skip the Windows ADK Deployment Tools install. + .\install-packer.ps1 -SkipOscdimg +#> +[CmdletBinding()] +param( + [string] $Version = '1.15.3', + [string] $InstallRoot = (Join-Path $env:ProgramFiles 'Packer'), + [switch] $SkipOscdimg, + [string] $AdkSetupUrl = 'https://go.microsoft.com/fwlink/?linkid=2289980' +) + +$ErrorActionPreference = 'Stop' + +function Assert-Elevated { + $identity = [Security.Principal.WindowsIdentity]::GetCurrent() + $principal = [Security.Principal.WindowsPrincipal]::new($identity) + if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + throw "install-packer.ps1 must be run from an elevated PowerShell session (writes to Program Files and the machine PATH)." + } +} + +function Get-InstalledPackerVersion { + param([string] $Root) + $exe = Join-Path $Root 'packer.exe' + if (-not (Test-Path -LiteralPath $exe)) { return $null } + try { + $output = & $exe version 2>$null + } catch { + return $null + } + foreach ($line in $output) { + if ($line -match 'Packer\s+v?([0-9]+\.[0-9]+\.[0-9]+)') { + return $Matches[1] + } + } + return $null +} + +function Add-ToMachinePath { + param([string] $Directory) + $current = [Environment]::GetEnvironmentVariable('Path', 'Machine') + $parts = @() + if ($current) { + $parts = $current.Split(';') | Where-Object { $_ -ne '' } + } + if ($parts -contains $Directory) { + Write-Host "system PATH already contains $Directory" + return + } + $newPath = ($parts + $Directory) -join ';' + [Environment]::SetEnvironmentVariable('Path', $newPath, 'Machine') + # Make the change visible in the current session as well so the caller + # can immediately run `packer` without opening a new shell. + if (-not (($env:Path -split ';') -contains $Directory)) { + $env:Path = "$env:Path;$Directory" + } + Write-Host "added $Directory to the system PATH (machine scope)." +} + +function Get-OscdimgPath { + $candidates = @( + (Join-Path ${env:ProgramFiles(x86)} 'Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe'), + (Join-Path ${env:ProgramFiles} 'Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe') + ) + foreach ($c in $candidates) { + if ($c -and (Test-Path -LiteralPath $c)) { return $c } + } + return $null +} + +function Install-Oscdimg { + param([string] $SetupUrl) + + $existing = Get-OscdimgPath + if ($existing) { + Write-Host "oscdimg.exe already present at $existing" + Add-ToMachinePath -Directory (Split-Path -Parent $existing) + return + } + + $tmp = Join-Path ([IO.Path]::GetTempPath()) ("install-adk-" + [Guid]::NewGuid()) + $setup = Join-Path $tmp 'adksetup.exe' + New-Item -ItemType Directory -Path $tmp -Force | Out-Null + try { + Write-Host "downloading Windows ADK bootstrapper from $SetupUrl" + [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 + Invoke-WebRequest -UseBasicParsing -Uri $SetupUrl -OutFile $setup + + Write-Host "installing Windows ADK Deployment Tools (this may take several minutes)" + # /features OptionId.DeploymentTools => oscdimg only (~70 MB) + # /quiet /norestart /ceip off => unattended, no telemetry prompt + $args = @('/features','OptionId.DeploymentTools','/quiet','/norestart','/ceip','off') + $proc = Start-Process -FilePath $setup -ArgumentList $args -Wait -PassThru + if ($proc.ExitCode -ne 0) { + throw "Windows ADK setup exited with code $($proc.ExitCode)." + } + } + finally { + Remove-Item -LiteralPath $tmp -Recurse -Force -ErrorAction SilentlyContinue + } + + $installed = Get-OscdimgPath + if (-not $installed) { + throw "Windows ADK setup completed but oscdimg.exe was not found in the expected location." + } + Write-Host "installed oscdimg.exe at $installed" + Add-ToMachinePath -Directory (Split-Path -Parent $installed) +} + +Assert-Elevated + +# Idempotency: if the target version is already installed, just make sure the +# PATH entry is in place and return. +$existing = Get-InstalledPackerVersion -Root $InstallRoot +if ($existing -eq $Version) { + Write-Host "packer $Version already installed at $InstallRoot." + Add-ToMachinePath -Directory $InstallRoot + if (-not $SkipOscdimg) { Install-Oscdimg -SetupUrl $AdkSetupUrl } + return +} +if ($existing) { + Write-Host "replacing packer $existing at $InstallRoot with $Version." +} + +$url = "https://releases.hashicorp.com/packer/$Version/packer_${Version}_windows_amd64.zip" +$tmpRoot = Join-Path ([IO.Path]::GetTempPath()) ("install-packer-" + [Guid]::NewGuid()) +$zipPath = Join-Path $tmpRoot "packer_${Version}.zip" + +New-Item -ItemType Directory -Path $tmpRoot -Force | Out-Null +try { + Write-Host "downloading $url" + # TLS 1.2 is required to talk to releases.hashicorp.com on stock + # Windows 10/Server 2019 PowerShell sessions. + [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 + Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $zipPath + + Write-Host "extracting to $tmpRoot" + Expand-Archive -LiteralPath $zipPath -DestinationPath $tmpRoot -Force + + $srcExe = Join-Path $tmpRoot 'packer.exe' + if (-not (Test-Path -LiteralPath $srcExe)) { + throw "packer.exe not found inside $zipPath after extraction." + } + + New-Item -ItemType Directory -Path $InstallRoot -Force | Out-Null + Copy-Item -LiteralPath $srcExe -Destination (Join-Path $InstallRoot 'packer.exe') -Force + Write-Host "installed packer.exe to $InstallRoot" + + Add-ToMachinePath -Directory $InstallRoot + + $installed = Get-InstalledPackerVersion -Root $InstallRoot + if ($installed -ne $Version) { + Write-Warning "post-install version check returned '$installed' (expected $Version)." + } else { + Write-Host "verified: packer $installed available at $(Join-Path $InstallRoot 'packer.exe')." + } +} +finally { + Remove-Item -LiteralPath $tmpRoot -Recurse -Force -ErrorAction SilentlyContinue +} + +if (-not $SkipOscdimg) { Install-Oscdimg -SetupUrl $AdkSetupUrl } diff --git a/test/integration/packer/load-env.ps1 b/test/integration/packer/load-env.ps1 new file mode 100644 index 0000000..e122b91 --- /dev/null +++ b/test/integration/packer/load-env.ps1 @@ -0,0 +1,34 @@ +# Loads variables from .env (in this directory) into the current PowerShell +# session as environment variables. Dot-source it so the variables stick: +# +# . .\load-env.ps1 +# +# Format: +# - One KEY=VALUE per line. +# - Lines starting with '#' and blank lines are ignored. +# - Values are taken verbatim (no shell quoting / interpolation). Surround +# with quotes only if you actually want quotes in the value. + +$ErrorActionPreference = 'Stop' + +$envFile = Join-Path $PSScriptRoot '.env' +if (-not (Test-Path -LiteralPath $envFile)) { + throw ".env not found at $envFile. Copy .env.example to .env and fill in PKR_VAR_iso_path." +} + +$loaded = 0 +foreach ($line in Get-Content -LiteralPath $envFile) { + $trimmed = $line.Trim() + if ($trimmed -eq '' -or $trimmed.StartsWith('#')) { continue } + $idx = $trimmed.IndexOf('=') + if ($idx -lt 1) { + Write-Warning "skipping malformed line: $line" + continue + } + $name = $trimmed.Substring(0, $idx).Trim() + $value = $trimmed.Substring($idx + 1) + [Environment]::SetEnvironmentVariable($name, $value, 'Process') + $loaded++ +} + +Write-Host "loaded $loaded variable(s) from $envFile into the current session." diff --git a/test/integration/packer/packer.err b/test/integration/packer/packer.err new file mode 100644 index 0000000..e69de29 diff --git a/test/integration/packer/packer.out b/test/integration/packer/packer.out new file mode 100644 index 0000000..8f646bf --- /dev/null +++ b/test/integration/packer/packer.out @@ -0,0 +1,78 @@ +Warning: A checksum of 'none' was specified. Since ISO files are so big, +a checksum is highly recommended. + + on .\windows-11.pkr.hcl line 83: + (source code not available) + + +hyperv-iso.win11: output will be in this color. + +==> hyperv-iso.win11: Creating build directory... +==> hyperv-iso.win11: Retrieving ISO +==> hyperv-iso.win11: Trying C:/Users/jasonross/Downloads/Win11_25H2_English_x64_v2(1).iso +==> hyperv-iso.win11: Trying file://C:/Users/jasonross/Downloads/Win11_25H2_English_x64_v2%281%29.iso +==> hyperv-iso.win11: file://C:/Users/jasonross/Downloads/Win11_25H2_English_x64_v2%281%29.iso => C:/Users/jasonross/Downloads/Win11_25H2_English_x64_v2(1).iso +==> hyperv-iso.win11: Creating switch 'Default Switch' if required... +==> hyperv-iso.win11: switch 'Default Switch' already exists. Will not delete on cleanup... +==> hyperv-iso.win11: Creating virtual machine... +==> hyperv-iso.win11: Enabling Integration Service... +==> hyperv-iso.win11: Setting boot drive to os dvd drive C:/Users/jasonross/Downloads/Win11_25H2_English_x64_v2(1).iso ... +==> hyperv-iso.win11: Mounting os dvd drive C:/Users/jasonross/Downloads/Win11_25H2_English_x64_v2(1).iso ... +==> hyperv-iso.win11: Skipping mounting Integration Services Setup Disk... +==> hyperv-iso.win11: Creating CD disk... +==> hyperv-iso.win11: OSCDIMG 2.56 CD-ROM and DVD-ROM Premastering Utility +==> hyperv-iso.win11: Copyright (C) Microsoft, 1993-2012. All rights reserved. +==> hyperv-iso.win11: Licensed only for producing Microsoft authorized content. +==> hyperv-iso.win11: Scanning source tree +==> hyperv-iso.win11: Scanning source tree complete (2 files in 1 directories) +==> hyperv-iso.win11: Computing directory information complete +==> hyperv-iso.win11: Image file is 61440 bytes (before optimization) +==> hyperv-iso.win11: Writing 2 files in 1 directories to C:\Users\jasonross\AppData\Local\Temp\packer2666332811.iso +==> hyperv-iso.win11: Storage optimization saved 0 files, 0 bytes (0% of image) +==> hyperv-iso.win11: After optimization, image file is 61440 bytes +==> hyperv-iso.win11: Done. +==> hyperv-iso.win11: 100% complete +==> hyperv-iso.win11: Done copying paths from CD_dirs +==> hyperv-iso.win11: Mounting secondary DVD images... +==> hyperv-iso.win11: Mounting secondary dvd drive C:\Users\jasonross\AppData\Local\Temp\packer2666332811.iso ... +==> hyperv-iso.win11: Configuring vlan... +==> hyperv-iso.win11: Determine Host IP for HyperV machine... +==> hyperv-iso.win11: Host IP for the HyperV machine: 172.25.16.1 +==> hyperv-iso.win11: Attempting to connect with vmconnect... +==> hyperv-iso.win11: Starting the virtual machine... +==> hyperv-iso.win11: Waiting 1s for boot... +==> hyperv-iso.win11: Typing the boot command... +==> hyperv-iso.win11: Waiting for WinRM to become available... +==> hyperv-iso.win11: WinRM connected. +==> hyperv-iso.win11: Connected to WinRM! +==> hyperv-iso.win11: Provisioning with Powershell... +==> hyperv-iso.win11: Provisioning with powershell script: ./scripts/configure-os.ps1 +==> hyperv-iso.win11: Script exited with non-zero exit status: 2147943462. Allowed exit codes are: [0] +==> hyperv-iso.win11: Step "StepProvision" failed, aborting... +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepConnect" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepTypeBootCommand" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepRun" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepSetFirstBootDevice" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepSetBootOrder" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepConfigureVlan" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepMountSecondaryDvdImages" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepCreateCD" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepMountGuestAdditions" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepMountFloppydrive" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepMountDvdDrive" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepEnableIntegrationService" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepCreateVM" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepCreateSwitch" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepHTTPServer" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepCreateFloppy" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepDownload" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepOutputDir" +==> hyperv-iso.win11: aborted: skipping cleanup of step "StepCreateBuildDir" +Build 'hyperv-iso.win11' errored after 16 minutes 59 seconds: Script exited with non-zero exit status: 2147943462. Allowed exit codes are: [0] + +==> Wait completed after 16 minutes 59 seconds + +==> Some builds didn't complete successfully and had errors: +--> hyperv-iso.win11: Script exited with non-zero exit status: 2147943462. Allowed exit codes are: [0] + +==> Builds finished but no artifacts were created. diff --git a/test/integration/packer/packer.pid b/test/integration/packer/packer.pid new file mode 100644 index 0000000..1aebc13 --- /dev/null +++ b/test/integration/packer/packer.pid @@ -0,0 +1 @@ +51192 diff --git a/test/integration/packer/packer_cache/4e9623e919f68b884a6560f42c868004321a22bd.iso.lock b/test/integration/packer/packer_cache/4e9623e919f68b884a6560f42c868004321a22bd.iso.lock new file mode 100644 index 0000000..e69de29 diff --git a/test/integration/packer/scripts/compact.ps1 b/test/integration/packer/scripts/compact.ps1 new file mode 100644 index 0000000..b2d9eb1 --- /dev/null +++ b/test/integration/packer/scripts/compact.ps1 @@ -0,0 +1,25 @@ +# Zero out free space so the resulting .box file is small. +# +# Runs last, just before Packer initiates shutdown. Cleans caches and the WU +# component store, which directly shrinks the on-disk footprint of the VHDX. +# We intentionally do not call `cipher /w:C:\` here: it costs 15–30 minutes +# and its only payoff is better tarball compression of unused space, which +# only matters when shipping the box. Re-add it before publishing publicly. + +$ErrorActionPreference = 'Continue' + +# Clean Windows Update download cache and component store. +Stop-Service -Name wuauserv -Force -ErrorAction SilentlyContinue +Remove-Item -Path "$env:WINDIR\SoftwareDistribution\Download\*" -Recurse -Force -ErrorAction SilentlyContinue +& dism /Online /Cleanup-Image /StartComponentCleanup /ResetBase /Quiet + +# Empty Recycle Bin and temp dirs. +Get-ChildItem -Path "$env:TEMP" -Force -ErrorAction SilentlyContinue | + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue +Clear-RecycleBin -Force -ErrorAction SilentlyContinue + +# Light defrag pass to consolidate free extents. Quick on an SSD-backed VHDX. +& defrag C: /U /V + +# Drop hibernation file (Windows 11 has it on by default). +& powercfg /h off diff --git a/test/integration/packer/scripts/configure-os.ps1 b/test/integration/packer/scripts/configure-os.ps1 new file mode 100644 index 0000000..35c6448 --- /dev/null +++ b/test/integration/packer/scripts/configure-os.ps1 @@ -0,0 +1,28 @@ +# Generic OS tweaks applied after WinRM is reachable. +# +# Idempotent; safe to rerun. + +$ErrorActionPreference = 'Stop' + +# Make sure the remote-elevated token policy survives any unattended changes. +$policy = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' +New-ItemProperty -Path $policy -Name 'LocalAccountTokenFilterPolicy' ` + -PropertyType DWord -Value 1 -Force | Out-Null + +# Disable telemetry "Connected User Experiences" service to avoid background +# network noise that competes with the bootstrapper. +$svc = Get-Service -Name DiagTrack -ErrorAction SilentlyContinue +if ($svc) { + Set-Service -Name DiagTrack -StartupType Disabled + Stop-Service -Name DiagTrack -Force -ErrorAction SilentlyContinue +} + +# Disable SmartScreen network checks (slows winget installs in the lab). +$ss = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System' +New-Item -Path $ss -Force | Out-Null +New-ItemProperty -Path $ss -Name 'EnableSmartScreen' -PropertyType DWord -Value 0 -Force | Out-Null + +# Force NTP resync; Hyper-V time-sync after sysprep can drift, which breaks +# TLS handshakes against winget / GitHub. +Start-Service -Name w32time -ErrorAction SilentlyContinue +& w32tm /resync /force 2>&1 | Out-Null diff --git a/test/integration/packer/scripts/disable-defender-cloud.ps1 b/test/integration/packer/scripts/disable-defender-cloud.ps1 new file mode 100644 index 0000000..62f872a --- /dev/null +++ b/test/integration/packer/scripts/disable-defender-cloud.ps1 @@ -0,0 +1,12 @@ +# Turn off Defender cloud-delivered protection and sample submission. +# +# Cloud lookups add tens of seconds per winget install on a cold box and have +# no value in an ephemeral integration VM. + +$ErrorActionPreference = 'Continue' + +Set-MpPreference -MAPSReporting Disabled -ErrorAction SilentlyContinue +Set-MpPreference -SubmitSamplesConsent NeverSend -ErrorAction SilentlyContinue +Set-MpPreference -DisableBlockAtFirstSeen $true -ErrorAction SilentlyContinue +Set-MpPreference -DisableIOAVProtection $true -ErrorAction SilentlyContinue +Set-MpPreference -ScanAvgCPULoadFactor 5 -ErrorAction SilentlyContinue diff --git a/test/integration/packer/scripts/disable-windows-updates.ps1 b/test/integration/packer/scripts/disable-windows-updates.ps1 new file mode 100644 index 0000000..c4a93dc --- /dev/null +++ b/test/integration/packer/scripts/disable-windows-updates.ps1 @@ -0,0 +1,26 @@ +# Disable Windows Update on the gold image so it doesn't fight with the +# bootstrapper's own WindowsUpdateCommand step at integration-test time. +# +# This is the precise mitigation for the 6-hour CI hang investigation: by +# the time the bootstrapper runs, no other process is holding the WU agent. + +$ErrorActionPreference = 'Stop' + +$au = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' +New-Item -Path $au -Force | Out-Null +New-ItemProperty -Path $au -Name 'NoAutoUpdate' -PropertyType DWord -Value 1 -Force | Out-Null +New-ItemProperty -Path $au -Name 'AUOptions' -PropertyType DWord -Value 1 -Force | Out-Null +New-ItemProperty -Path $au -Name 'ScheduledInstallDay' -PropertyType DWord -Value 0 -Force | Out-Null +New-ItemProperty -Path $au -Name 'NoAutoRebootWithLoggedOnUsers' -PropertyType DWord -Value 1 -Force | Out-Null + +$wu = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' +New-Item -Path $wu -Force | Out-Null +New-ItemProperty -Path $wu -Name 'DoNotConnectToWindowsUpdateInternetLocations' -PropertyType DWord -Value 1 -Force | Out-Null + +foreach ($svc in 'wuauserv','UsoSvc','WaaSMedicSvc') { + $s = Get-Service -Name $svc -ErrorAction SilentlyContinue + if ($s) { + Set-Service -Name $svc -StartupType Disabled -ErrorAction SilentlyContinue + Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue + } +} diff --git a/test/integration/packer/scripts/install-vagrant-key.ps1 b/test/integration/packer/scripts/install-vagrant-key.ps1 new file mode 100644 index 0000000..25aeb8d --- /dev/null +++ b/test/integration/packer/scripts/install-vagrant-key.ps1 @@ -0,0 +1,15 @@ +# Install the Vagrant insecure SSH key marker so `vagrant ssh-config` and +# tooling that expects the Vagrant-flavoured user account is happy. WinRM is +# the actual communicator, but several Vagrant plugins probe for this layout. + +$ErrorActionPreference = 'Continue' + +$sshDir = "$env:USERPROFILE\.ssh" +New-Item -ItemType Directory -Path $sshDir -Force | Out-Null + +$keyUrl = 'https://raw.githubusercontent.com/hashicorp/vagrant/main/keys/vagrant.pub' +try { + Invoke-WebRequest -UseBasicParsing -Uri $keyUrl -OutFile "$sshDir\authorized_keys" +} catch { + Write-Host "warning: could not fetch vagrant insecure public key: $($_.Exception.Message)" +} diff --git a/test/integration/packer/vagrantfile-template.rb b/test/integration/packer/vagrantfile-template.rb new file mode 100644 index 0000000..075eeb6 --- /dev/null +++ b/test/integration/packer/vagrantfile-template.rb @@ -0,0 +1,25 @@ +# Vagrantfile fragment baked into the output .box file by the +# `packer-post-processor-vagrant` plugin. This is what every `vagrant up` +# of a derived box inherits before our top-level Vagrantfile is applied. + +Vagrant.configure("2") do |config| + config.vm.communicator = "winrm" + config.vm.guest = :windows + config.winrm.username = "vagrant" + config.winrm.password = "vagrant" + config.winrm.transport = :plaintext + config.winrm.basic_auth_only = true + config.vm.boot_timeout = 1800 + + config.vm.provider "hyperv" do |hv| + hv.enable_virtualization_extensions = false + hv.linked_clone = true + hv.vm_integration_services = { + guest_service_interface: true, + heartbeat: true, + shutdown: true, + time_synchronization: true, + vss: true, + } + end +end diff --git a/test/integration/packer/windows-11.pkr.hcl b/test/integration/packer/windows-11.pkr.hcl new file mode 100644 index 0000000..ceb02a1 --- /dev/null +++ b/test/integration/packer/windows-11.pkr.hcl @@ -0,0 +1,157 @@ +packer { + required_plugins { + hyperv = { + version = ">= 1.1.4" + source = "github.com/hashicorp/hyperv" + } + vagrant = { + version = ">= 1.1.5" + source = "github.com/hashicorp/vagrant" + } + } +} + +# ─── Inputs ─────────────────────────────────────────────────────────────────── + +variable "iso_path" { + type = string + description = "Absolute path to the Windows 11 installer ISO. Set via PKR_VAR_iso_path (load .env first; see README)." +} + +variable "iso_checksum" { + type = string + description = "Checksum of the ISO (e.g. 'sha256:<hex>'); 'none' skips validation. Set via PKR_VAR_iso_checksum." + default = "none" +} + +variable "vm_name" { + type = string + default = "bootstrap-win11" +} + +variable "output_directory" { + type = string + default = "output-bootstrap-win11" +} + +variable "box_output" { + type = string + default = "bootstrap-win11.box" +} + +variable "cpus" { + type = number + default = 24 + description = "vCPUs allocated to the build VM. The Packer guest is throwaway and gets the full host budget for speed; the runtime integration VM keeps a smaller footprint in test/integration/Vagrantfile." +} + +variable "memory" { + type = number + default = 32768 + description = "Build-VM memory (MB). Throwaway VM, full host budget." +} + +variable "disk_size" { + type = number + default = 81920 + description = "Guest disk size in MB." +} + +variable "switch_name" { + type = string + default = "Default Switch" +} + +variable "winrm_username" { + type = string + default = "vagrant" +} + +variable "winrm_password" { + type = string + default = "vagrant" + sensitive = true +} + +# ─── Source ─────────────────────────────────────────────────────────────────── +# +# Hyper-V Gen 2 + Secure Boot is required for modern Windows 11. The +# unattend payload lives on a small ISO that Packer builds on the fly from +# `cd_files` and attaches as a secondary drive; Windows Setup auto-discovers +# `autounattend.xml` on any attached media at the root. + +source "hyperv-iso" "win11" { + vm_name = var.vm_name + iso_url = var.iso_path + iso_checksum = var.iso_checksum + + cpus = var.cpus + memory = var.memory + disk_size = var.disk_size + + generation = 2 + enable_secure_boot = true + secure_boot_template = "MicrosoftWindows" + enable_tpm = true + enable_dynamic_memory = false + enable_virtualization_extensions = false + guest_additions_mode = "disable" + switch_name = var.switch_name + + output_directory = var.output_directory + + communicator = "winrm" + winrm_username = var.winrm_username + winrm_password = var.winrm_password + winrm_timeout = "2h" + winrm_use_ssl = false + winrm_insecure = true + + # Gen 2 UEFI shows "Press any key to boot from CD or DVD..." for ~5s. + # Default boot_wait is 10s (already past the prompt) and default + # boot_command is empty, so without these the firmware falls through to + # PXE and Windows Setup never starts. Hammer ENTER early to catch it. + boot_wait = "1s" + boot_command = ["<enter><wait><enter><wait><enter>"] + + shutdown_command = "shutdown /s /t 10 /f /d p:4:1 /c \"Packer Shutdown\"" + shutdown_timeout = "30m" + + # Build a tiny "PROVISION" ISO containing the unattend file. The + # FirstLogonCommands in autounattend.xml enable WinRM inline (no helper + # script needed) since Windows Setup may detach secondary DVDs after + # install, leaving the PROVISION volume unreachable at first logon. + cd_files = [ + "./cd/autounattend.xml", + ] + cd_label = "PROVISION" +} + +# ─── Build ──────────────────────────────────────────────────────────────────── +# +# Provisioners run *after* WinRM is reachable, which is after OOBE has finished +# and the autounattend's FirstLogonCommands have brought WinRM online. Each +# script is small and single-purpose; see comments in each .ps1. + +build { + sources = ["source.hyperv-iso.win11"] + + provisioner "powershell" { + elevated_user = var.winrm_username + elevated_password = var.winrm_password + scripts = [ + "./scripts/configure-os.ps1", + "./scripts/disable-windows-updates.ps1", + "./scripts/disable-defender-cloud.ps1", + "./scripts/install-vagrant-key.ps1", + "./scripts/compact.ps1", + ] + } + + post-processor "vagrant" { + output = var.box_output + keep_input_artifact = false + provider_override = "hyperv" + vagrantfile_template = "./vagrantfile-template.rb" + } +} diff --git a/winget_schema.json b/winget_schema.json new file mode 100644 index 0000000..29cbf3b --- /dev/null +++ b/winget_schema.json @@ -0,0 +1,1937 @@ + + + + + + +<!DOCTYPE html> +<html + lang="en" + + data-color-mode="auto" data-light-theme="light" data-dark-theme="dark" + data-a11y-animated-images="system" data-a11y-link-underlines="true" + + > + + + + + <head> + <meta charset="utf-8"> + <link rel="dns-prefetch" href="https://github.githubassets.com"> + <link rel="dns-prefetch" href="https://avatars.githubusercontent.com"> + <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com"> + <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/"> + <link rel="preconnect" href="https://github.githubassets.com" crossorigin> + <link rel="preconnect" href="https://avatars.githubusercontent.com"> + + + + + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light-4fded0090af0ad58.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light_high_contrast-cf8e26bc17e62ebc.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark-06381ff23d863842.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark_high_contrast-9023e6605402defb.css" /><link data-color-theme="light" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light-4fded0090af0ad58.css" /><link data-color-theme="light_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_high_contrast-cf8e26bc17e62ebc.css" /><link data-color-theme="light_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind-3a437477a570cc40.css" /><link data-color-theme="light_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind_high_contrast-39b6c209db5491c9.css" /><link data-color-theme="light_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia-3822234d6c03b00b.css" /><link data-color-theme="light_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia_high_contrast-33857254a8064bf7.css" /><link data-color-theme="dark" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark-06381ff23d863842.css" /><link data-color-theme="dark_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_high_contrast-9023e6605402defb.css" /><link data-color-theme="dark_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind-37023bf69d8e0e34.css" /><link data-color-theme="dark_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind_high_contrast-486bd43e01a2c0ec.css" /><link data-color-theme="dark_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia-838ba2a5070c5b09.css" /><link data-color-theme="dark_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia_high_contrast-2aa7245dc545d61f.css" /><link data-color-theme="dark_dimmed" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed-29ef2eb185e7de1c.css" /><link data-color-theme="dark_dimmed_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed_high_contrast-8eed6b212f10f1b9.css" /> + + <style type="text/css"> + :root { + --tab-size-preference: 4; + } + + pre, code { + tab-size: var(--tab-size-preference); + } + </style> + + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-primitives-b39ad27f3538ace3.css" /> + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-a33d805aa3bce2cb.css" /> + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-9c8f61f9f58ad7b2.css" /> + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-d92b5e5cec2d5a81.css" /> + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repository-5c3491d57145b94f.css" /> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-faf4e82192a865fe.css" /> + + + + <script type="application/json" id="client-env">{"locale":"en","featureFlags":["actions_custom_images_storage_billing_ui_visibility","actions_image_version_event","actions_workflow_language_service_allow_concurrency_queue","agent_conflict_resolution","alternate_user_config_repo","arianotify_comprehensive_migration","artifact_ui_v2","billing_discount_threshold_notification","billing_user_level_budgets","billing_user_level_budgets_manage","code_scanning_dfa_degraded_experience_notice","codespaces_prebuild_region_target_update","coding_agent_model_selection","coding_agent_model_selection_all_skus","comment_viewer_copy_raw_markdown","contentful_form_phone_v2","contentful_primer_code_blocks","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_automation_suggest_tools_enabled","copilot_automations_suggested_automations","copilot_chat_attach_multiple_images","copilot_chat_category_rate_limit_messages","copilot_chat_clear_model_selection_for_default_change","copilot_chat_contextual_suggestions_updated","copilot_chat_enable_tool_call_logs","copilot_chat_input_commands","copilot_chat_max_upsell","copilot_chat_models_via_backend","copilot_chat_opening_thread_switch","copilot_chat_prettify_pasted_code","copilot_chat_reduce_quota_checks","copilot_chat_search_bar_redirect","copilot_chat_structured_list_refs","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_cli_install_cta_max_plan","copilot_cloud_agent_always_categorize_models_in_model_picker","copilot_coding_agent_tbb_quota_banner","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_delete_cli_sessions","copilot_diff_explain_conversation_intent","copilot_diff_reference_context","copilot_dotcom_chat_memoize_messages","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_file_block_ref_matching","copilot_fix_failed_workflows","copilot_ftp_hyperspace_upgrade_prompt","copilot_hide_hovercard","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_code_block_transition_wrap","copilot_immersive_embedded_deferred_payload","copilot_immersive_embedded_draggable","copilot_immersive_embedded_header_button","copilot_immersive_embedded_implicit_references","copilot_immersive_embedded_skip_copilot_api_token_for_dotcom_context","copilot_immersive_file_block_transition_open","copilot_immersive_file_preview_keep_mounted","copilot_immersive_job_result_preview","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_agent_filtering","copilot_mission_control_agents_task_list","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_private_icon","copilot_mission_control_cli_session_status","copilot_mission_control_initial_data_spinner","copilot_mission_control_logs_incremental","copilot_mission_control_task_alive_updates","copilot_mission_control_tasks_repo_filter","copilot_org_policy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_pull_request_merged_trigger","copilot_swe_agent_pull_request_opened_trigger","copilot_swe_agent_pull_request_synchronize_trigger","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_token_based_billing","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","copilot_user_can_upgrade_plan_field","copilot_workbench_slim_line_top_tabs","copilot_workbench_ubb","create_ghas_hard_budgets","custom_instructions_file_references","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","flex_cta_groups_mvp","global_nav_react","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_budget_deep_linking","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_cca_modal_open","issue_cca_multi_assign_modal","issue_cca_visualization","issue_fields_global_search","issues_expanded_file_types","issues_lazy_load_comment_box_suggestions","issues_react_chrome_container_query_fix","issues_search_type_gql","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","low_quality_classifier","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_status_header_feedback","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","octocaptcha_origin_optimization","prs_conversations_react","prs_css_anchor_positioning","repos_contributors_limited_default_range","rules_insights_filter_bar_created","rules_required_reviewers_block_description","sample_network_conn_type","secret_scanning_pattern_alerts_link","security_center_artifact_filters_popover","session_logs_ungroup_reasoning_text","site_copilot_max_plans","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","viewscreen_sandbox","warn_inaccessible_attachments","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"}</script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/high-contrast-cookie-c1770ba1d19e9b2c.js"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/wp-runtime-03b9bcc66b4c8a5e.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/fetch-utilities-b82d70fb3b7c15af.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/78205-a328faf42e1fde9e.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/85924-1f0f5f61600f9c8e.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/34646-b68e58c07f4b3de7.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/environment-d69fe59c085ecc72.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/runtime-helpers-6e561c87b9671d53.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/296-20965d7d607b213c.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/96232-069a02c82c8693ee.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/57131-79aa62319c40af83.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/816-774d14a8cd9b309c.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/37037-cd0fff8f542fa8f3.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/81683-58949462db0c5675.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/64458-4fb01b8fdc13f3ff.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/46740-4421ca06d57312cc.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/30058-4f7b63da3786282e.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/github-elements-1208a11884f03020.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/element-registry-7a5b9c3665aef830.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/react-core-4a56f172fcdec649.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/react-lib-e93338a8d08b8bb9.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/41260-0b9ff1337b067966.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/79039-f2b81734929d0b15.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/88475-92437d3f8c9a9747.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/2887-d67f71d8e1d3e1d8.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/26533-318ac47648fb7752.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/46477-596c4ee4da73ac9a.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/31606-6f583ce9bde98bfa.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/33232-a61b173cd548f3cb.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/46287-fc23b9847d26823b.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/28000-450a3042fe455862.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/89627-9ca1822c4cd2f9dd.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/55682-a358ec7c2f348fcf.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/49029-3a132de206358025.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/99328-c8f80b871b1483db.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/behaviors-787090bfc35f0bd1.js" defer="defer"></script> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/react-core.ec8110258cfb5b9c.module.css" /> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/61272-d797d8a9ce83f9c1.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/notifications-global-be20ba1998b9a752.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/39890-cc66c6b70681d7fd.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/code-menu-30ce9fb4da681eeb.js" defer="defer"></script> + + <script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/primer-react-b2ec7a7e154b0b97.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/octicons-react-fa41822493eeb852.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/97458-20aca2fc91de9cc3.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/73694-c5efeea1f6f546c8.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/24949-7df9a84e133032e5.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/68751-3dce390992441fd6.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/437-c3d500f582b41be6.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/15272-37128cbcef9c407d.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/7463-3f2319a5b1d5fdf1.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/27600-4a93fc41fc8910c4.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/24564-14df7faa28380ddf.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/75521-9fa90ef1702b6b2b.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/58246-4ba5ac2265364faa.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/36311-a4f7563a98201f8b.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/16991-ec5fcaf7c62958d6.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/85542-b7dbf9541cd4eb3d.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/37494-8ad7eb20aa952a1d.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/68469-eb0c684e68896bcc.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/72094-86fb464e4e7ff942.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/40828-e6079551c5021285.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/63000-72d947f3c46087f0.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/30914-84a6fb11a38d78d8.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/33684-88b66083477394bd.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/1334-45a390001bd91c49.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/66231-7e90d1d205b44162.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/79407-7ed60e9afcb942a7.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/4916-17f9f95b53ebdbb3.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/68212-39f789b362f90992.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/2204-2ba7b35269e4e2ed.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/81959-45ce1bd801a17000.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/75577-f6389c0100ca31a1.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/15151-d56fdcef6cbca06e.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/53275-8145126227371aef.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/19824-6699c204947ed0bc.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/9094-bed5a523be5a5394.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/5901-bab9fd908331f6fb.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/27562-2b99f3c38a6bfca0.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/2165-dac4d7932fbff3e1.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/83805-6febcda7878e1a09.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/50110-cd07f1297612087b.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/26497-89790536f030a46c.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/21622-7f46d23f91e76501.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/3861-434dcd3a76a723b6.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/code-view-875bd7775330854e.js" defer="defer"></script> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.c6bef8006da6a4d6.module.css" /> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/5901.44d12ef0dfb5cea9.module.css" /> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-view.d1dc8bc7109e3ea2.module.css" /> + + <script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/65668-5bf3003ad0da99e7.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/notifications-subscriptions-menu-3487e7aa398a66b2.js" defer="defer"></script> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.c6bef8006da6a4d6.module.css" /> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/notifications-subscriptions-menu.da23c37c4813b1bd.module.css" /> + + + <title>winget-cli/doc/Settings.md at master · microsoft/winget-cli · GitHub</title> + + + + <meta name="route-pattern" content="/:user_id/:repository/blob/*name(/*path)" data-turbo-transient> + <meta name="route-controller" content="blob" data-turbo-transient> + <meta name="route-action" content="show" data-turbo-transient> + <meta name="fetch-nonce" content="v2:3174f404-e1af-9f22-4f66-1f338e61c7f6"> + + + <meta name="current-catalog-service-hash" content="f3abb0cc802f3d7b95fc8762b94bdcb13bf39634c40c357301c4aa1d67a256fb"> + + + <meta name="request-id" content="F53D:FBD2:1D39C26:2565028:6A1E1D2C" data-pjax-transient="true"/><meta name="html-safe-nonce" content="782382d200f6485c76a7a67e08fa814bb2d38242af041845677126b684310db1" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJGNTNEOkZCRDI6MUQzOUMyNjoyNTY1MDI4OjZBMUUxRDJDIiwidmlzaXRvcl9pZCI6IjQzMjM1MDczMjExMDI1NDAwNzYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==" data-pjax-transient="true"/><meta name="visitor-hmac" content="4deb8c00e457562c0cd3f8e905a92ca6fb867dc5a64d91b2d010b7e661652718" data-pjax-transient="true"/> + + + <meta name="hovercard-subject-tag" content="repository:197275130" data-turbo-transient> + + + <meta name="github-keyboard-shortcuts" content="repository,source-code,file-tree,copilot" data-turbo-transient="true" /> + + + <meta name="selected-link" value="repo_source" data-turbo-transient> + <link rel="assets" href="https://github.githubassets.com/"> + + <meta name="google-site-verification" content="Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I"> + +<meta name="octolytics-url" content="https://collector.github.com/github/collect" /> + + + + + + <meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-turbo-transient="true" /> + + + + + + + <meta name="user-login" content=""> + + + + <meta name="viewport" content="width=device-width"> + + + + <meta name="description" content="WinGet is the Windows Package Manager. This project includes a CLI (Command Line Interface), PowerShell modules, and a COM (Component Object Model) API (Application Programming Interface). - winget-cli/doc/Settings.md at master · microsoft/winget-cli"> + + <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub"> + + <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub"> + <meta property="fb:app_id" content="1401488693436528"> + <meta name="apple-itunes-app" content="app-id=1477376905, app-argument=https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md" /> + + <meta name="twitter:image" content="https://opengraph.githubassets.com/537bb711171a80c37f18bdce977fc47f3a6cd1ce02e35fdd2b1b6fe82ef4560d/microsoft/winget-cli" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="winget-cli/doc/Settings.md at master · microsoft/winget-cli" /><meta name="twitter:description" content="WinGet is the Windows Package Manager. This project includes a CLI (Command Line Interface), PowerShell modules, and a COM (Component Object Model) API (Application Programming Interface). - micros..." /> + <meta property="og:image" content="https://opengraph.githubassets.com/537bb711171a80c37f18bdce977fc47f3a6cd1ce02e35fdd2b1b6fe82ef4560d/microsoft/winget-cli" /><meta property="og:image:alt" content="WinGet is the Windows Package Manager. This project includes a CLI (Command Line Interface), PowerShell modules, and a COM (Component Object Model) API (Application Programming Interface). - micros..." /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="600" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="winget-cli/doc/Settings.md at master · microsoft/winget-cli" /><meta property="og:url" content="https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md" /><meta property="og:description" content="WinGet is the Windows Package Manager. This project includes a CLI (Command Line Interface), PowerShell modules, and a COM (Component Object Model) API (Application Programming Interface). - micros..." /> + + + + + + <meta name="hostname" content="github.com"> + + + + <meta name="expected-hostname" content="github.com"> + + + <meta http-equiv="x-pjax-version" content="d092bc9cb325ebf9efb8786388a7f87395ee66a77af2cd892fd835feb517d2cf" data-turbo-track="reload"> + <meta http-equiv="x-pjax-csp-version" content="f53effb2a675c4091662fd06c1c9f58a7eef6c9c46c51c4f2ac6ff94d5e4967b" data-turbo-track="reload"> + <meta http-equiv="x-pjax-css-version" content="75ed22795dd7d05a40521c01884e084fb34d435b5f163faf53a37883ee7981dd" data-turbo-track="reload"> + <meta http-equiv="x-pjax-js-version" content="dd3e1fd155d5d233a685353cc3932fe060730eb744b79dc0d4344a0421a0dffd" data-turbo-track="reload"> + + <meta name="turbo-cache-control" content="no-preview" data-turbo-transient=""> + + <meta name="turbo-cache-control" content="no-cache" data-turbo-transient> + + <meta data-hydrostats="publish"> + + <meta name="go-import" content="github.com/microsoft/winget-cli git https://github.com/microsoft/winget-cli.git"> + + <meta name="octolytics-dimension-user_id" content="6154722" /><meta name="octolytics-dimension-user_login" content="microsoft" /><meta name="octolytics-dimension-repository_id" content="197275130" /><meta name="octolytics-dimension-repository_nwo" content="microsoft/winget-cli" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="197275130" /><meta name="octolytics-dimension-repository_network_root_nwo" content="microsoft/winget-cli" /> + + + + + + + <meta name="turbo-body-classes" content="logged-out env-production page-responsive"> + <meta name="disable-turbo" content="false"> + + + <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats"> + + <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors"> + + <meta name="release" content="7249bab30cf123059f559dafe7b35ec186a28bbe" data-turbo-track="reload"> + <meta name="ui-target" content="full"> + + <link rel="mask-icon" href="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" color="#000000"> + <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://github.githubassets.com/favicons/favicon.png"> + <link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://github.githubassets.com/favicons/favicon.svg" data-base-href="https://github.githubassets.com/favicons/favicon"> + +<meta name="theme-color" content="#1e2327"> +<meta name="color-scheme" content="light dark" /> + + + <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials"> + + </head> + + <body class="logged-out env-production page-responsive" style="word-wrap: break-word;" > + <div data-turbo-body class="logged-out env-production page-responsive" style="word-wrap: break-word;" > + <div id="__primerPortalRoot__" style="z-index: 1000; position: absolute; width: 100%;" data-turbo-permanent></div> + + + <div class="position-relative header-wrapper js-header-wrapper "> + <a href="#start-of-content" data-skip-target-assigned="false" class="px-2 tmp-py-4 color-bg-accent-emphasis color-fg-on-emphasis show-on-focus js-skip-to-content">Skip to content</a> + + <span data-view-component="true" class="progress-pjax-loader Progress position-fixed width-full"> + <span style="width: 0%;" data-view-component="true" class="Progress-item progress-pjax-loader-bar left-0 top-0 color-bg-accent-emphasis"></span> +</span> + + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.c6bef8006da6a4d6.module.css" /> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog.6cd80e3134c32137.module.css" /> + +<react-partial + partial-name="keyboard-shortcuts-dialog" + data-ssr="false" + data-attempted-ssr="false" + data-react-profiling="false" +> + + <script type="application/json" data-target="react-partial.embeddedData">{"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}</script> + <div data-target="react-partial.reactRoot"></div> +</react-partial> + + + + + + + + + + +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/70666-351eb383f1ef4a9d.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/43406-46a76afebe05acef.js" defer="defer"></script> +<script crossorigin="anonymous" type="application/javascript" src="https://github.githubassets.com/assets/sessions-3d4ee946e452d6db.js" defer="defer"></script> + +<style> + /* Override primer focus outline color for marketing header dropdown links for better contrast */ + [data-color-mode="light"] .HeaderMenu-dropdown-link:focus-visible, + [data-color-mode="light"] .HeaderMenu-trailing-link a:focus-visible { + outline-color: var(--color-accent-fg); + } +</style> + +<header class="HeaderMktg header-logged-out js-details-container js-header Details f4 tmp-py-3" role="banner" data-is-top="true" data-color-mode=auto data-light-theme=light data-dark-theme=dark> + <h2 class="sr-only">Navigation Menu</h2> + + <button type="button" class="HeaderMktg-backdrop d-lg-none border-0 position-fixed top-0 left-0 width-full height-full js-details-target" aria-label="Toggle navigation"> + <span class="d-none">Toggle navigation</span> + </button> + + <div class="d-flex flex-column flex-lg-row flex-items-center tmp-px-3 tmp-px-md-4 tmp-px-lg-5 height-full position-relative z-1"> + <div class="d-flex flex-justify-between flex-items-center width-full width-lg-auto"> + <div class="flex-1"> + <button aria-label="Toggle navigation" aria-expanded="false" type="button" data-view-component="true" class="js-details-target js-nav-padding-recalculate js-header-menu-toggle Button--link Button--medium Button d-lg-none color-fg-inherit p-1 tmp-p-1"> <span class="Button-content"> + <span class="Button-label"><div class="HeaderMenu-toggle-bar rounded my-1"></div> + <div class="HeaderMenu-toggle-bar rounded my-1"></div> + <div class="HeaderMenu-toggle-bar rounded my-1"></div></span> + </span> +</button> + </div> + + <a class="tmp-mr-lg-3 color-fg-inherit flex-order-2 js-prevent-focus-on-mobile-nav" + href="/" + aria-label="Homepage" + data-analytics-event="{&quot;category&quot;:&quot;Marketing nav&quot;,&quot;action&quot;:&quot;click to go to homepage&quot;,&quot;label&quot;:&quot;ref_page:Marketing;ref_cta:Logomark;ref_loc:Header&quot;}"> + <svg height="32" aria-hidden="true" data-component="Octicon" viewBox="0 0 24 24" version="1.1" width="32" data-view-component="true" class="octicon octicon-mark-github"> + <path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path> +</svg> + </a> + + <div class="d-flex flex-1 flex-order-2 text-right d-lg-none gap-2 flex-justify-end"> + <a + href="/login?return_to=https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fwinget-cli%2Fblob%2Fmaster%2Fdoc%2FSettings.md" + class="HeaderMenu-link HeaderMenu-button d-inline-flex f5 no-underline border color-border-default rounded-2 px-2 py-1 color-fg-inherit js-prevent-focus-on-mobile-nav" + data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e1dbd869587423f125748adc0e73672ed58ed31fcb4f5efe51c02c93d274f4a1" + data-analytics-event="{&quot;category&quot;:&quot;Marketing nav&quot;,&quot;action&quot;:&quot;click to Sign in&quot;,&quot;label&quot;:&quot;ref_page:Marketing;ref_cta:Sign in;ref_loc:Header&quot;}" + > + Sign in + </a> + <div class="AppHeader-appearanceSettings"> + <react-partial-anchor> + <button data-target="react-partial-anchor.anchor" id="icon-button-830ccb6f-0bfd-494a-8753-d5fe86b2b023" aria-labelledby="tooltip-0752370c-e31f-483a-a392-2b100c84f28e" type="button" disabled="disabled" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium AppHeader-button HeaderMenu-link border cursor-wait"> <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-sliders Button-visual"> + <path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path> +</svg> +</button><tool-tip id="tooltip-0752370c-e31f-483a-a392-2b100c84f28e" for="icon-button-830ccb6f-0bfd-494a-8753-d5fe86b2b023" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Appearance settings</tool-tip> + + <template data-target="react-partial-anchor.template"> + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.c6bef8006da6a4d6.module.css" /> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/appearance-settings.0d1c5833260ecb07.module.css" /> + +<react-partial + partial-name="appearance-settings" + data-ssr="false" + data-attempted-ssr="false" + data-react-profiling="false" +> + + <script type="application/json" data-target="react-partial.embeddedData">{"props":{}}</script> + <div data-target="react-partial.reactRoot"></div> +</react-partial> + + + </template> + </react-partial-anchor> + </div> + + </div> + </div> + + + <div class="HeaderMenu js-header-menu height-fit position-lg-relative d-lg-flex flex-column flex-auto top-0"> + <div class="HeaderMenu-wrapper d-flex flex-column flex-self-start flex-lg-row flex-auto rounded rounded-lg-0"> + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.c6bef8006da6a4d6.module.css" /> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/marketing-navigation.b02c4a23543a2d83.module.css" /> + +<react-partial + partial-name="marketing-navigation" + data-ssr="true" + data-attempted-ssr="true" + data-react-profiling="false" +> + + <script type="application/json" data-target="react-partial.embeddedData">{"props":{"should_use_dotcom_links":true}}</script> + <div data-target="react-partial.reactRoot"><nav class="MarketingNavigation-module__nav__W0KYY" aria-label="Global"><ul class="MarketingNavigation-module__list__tFbMb"><li><div class="NavDropdown-module__container__l2YeI js-details-container js-header-menu-item"><button type="button" class="NavDropdown-module__button__PEHWX js-details-target" aria-expanded="false">Platform<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></button><div class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_5hb_">AI CODE CREATION</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5hb_"><li><a href="https://github.com/features/copilot" data-analytics-event="{&quot;action&quot;:&quot;github_copilot&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M23.922 16.992c-.861 1.495-5.859 5.023-11.922 5.023-6.063 0-11.061-3.528-11.922-5.023A.641.641 0 0 1 0 16.736v-2.869a.841.841 0 0 1 .053-.22c.372-.935 1.347-2.292 2.605-2.656.167-.429.414-1.055.644-1.517a10.195 10.195 0 0 1-.052-1.086c0-1.331.282-2.499 1.132-3.368.397-.406.89-.717 1.474-.952 1.399-1.136 3.392-2.093 6.122-2.093 2.731 0 4.767.957 6.166 2.093.584.235 1.077.546 1.474.952.85.869 1.132 2.037 1.132 3.368 0 .368-.014.733-.052 1.086.23.462.477 1.088.644 1.517 1.258.364 2.233 1.721 2.605 2.656a.832.832 0 0 1 .053.22v2.869a.641.641 0 0 1-.078.256ZM12.172 11h-.344a4.323 4.323 0 0 1-.355.508C10.703 12.455 9.555 13 7.965 13c-1.725 0-2.989-.359-3.782-1.259a2.005 2.005 0 0 1-.085-.104L4 11.741v6.585c1.435.779 4.514 2.179 8 2.179 3.486 0 6.565-1.4 8-2.179v-6.585l-.098-.104s-.033.045-.085.104c-.793.9-2.057 1.259-3.782 1.259-1.59 0-2.738-.545-3.508-1.492a4.323 4.323 0 0 1-.355-.508h-.016.016Zm.641-2.935c.136 1.057.403 1.913.878 2.497.442.544 1.134.938 2.344.938 1.573 0 2.292-.337 2.657-.751.384-.435.558-1.15.558-2.361 0-1.14-.243-1.847-.705-2.319-.477-.488-1.319-.862-2.824-1.025-1.487-.161-2.192.138-2.533.529-.269.307-.437.808-.438 1.578v.021c0 .265.021.562.063.893Zm-1.626 0c.042-.331.063-.628.063-.894v-.02c-.001-.77-.169-1.271-.438-1.578-.341-.391-1.046-.69-2.533-.529-1.505.163-2.347.537-2.824 1.025-.462.472-.705 1.179-.705 2.319 0 1.211.175 1.926.558 2.361.365.414 1.084.751 2.657.751 1.21 0 1.902-.394 2.344-.938.475-.584.742-1.44.878-2.497Z"></path><path d="M14.5 14.25a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Zm-5 0a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Z"></path></svg><span class="NavLink-module__title__Q7t0p">GitHub Copilot</span><span class="NavLink-module__subtitle__X4gkW">Write better code with AI</span></div></a></li><li><a href="https://github.com/features/spark" data-analytics-event="{&quot;action&quot;:&quot;github_spark&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_spark_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sparkle-fill NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M11.296 1.924c.24-.656 1.168-.656 1.408 0l.717 1.958a11.25 11.25 0 0 0 6.697 6.697l1.958.717c.657.24.657 1.168 0 1.408l-1.958.717a11.25 11.25 0 0 0-6.697 6.697l-.717 1.958c-.24.657-1.168.657-1.408 0l-.717-1.958a11.25 11.25 0 0 0-6.697-6.697l-1.958-.717c-.656-.24-.656-1.168 0-1.408l1.958-.717a11.25 11.25 0 0 0 6.697-6.697l.717-1.958Z"></path></svg><span class="NavLink-module__title__Q7t0p">GitHub Spark</span><span class="NavLink-module__subtitle__X4gkW">Build and deploy intelligent apps</span></div></a></li><li><a href="https://github.com/features/models" data-analytics-event="{&quot;action&quot;:&quot;github_models&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_models_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-ai-model NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M19.375 8.5a3.25 3.25 0 1 1-3.163 4h-3a3.252 3.252 0 0 1-4.443 2.509L7.214 17.76a3.25 3.25 0 1 1-1.342-.674l1.672-2.957A3.238 3.238 0 0 1 6.75 12c0-.907.371-1.727.97-2.316L6.117 6.846A3.253 3.253 0 0 1 1.875 3.75a3.25 3.25 0 1 1 5.526 2.32l1.603 2.836A3.25 3.25 0 0 1 13.093 11h3.119a3.252 3.252 0 0 1 3.163-2.5ZM10 10.25a1.75 1.75 0 1 0-.001 3.499A1.75 1.75 0 0 0 10 10.25ZM5.125 2a1.75 1.75 0 1 0 0 3.5 1.75 1.75 0 0 0 0-3.5Zm12.5 9.75a1.75 1.75 0 1 0 3.5 0 1.75 1.75 0 0 0-3.5 0Zm-14.25 8.5a1.75 1.75 0 1 0 3.501-.001 1.75 1.75 0 0 0-3.501.001Z"></path></svg><span class="NavLink-module__title__Q7t0p">GitHub Models</span><span class="NavLink-module__subtitle__X4gkW">Manage and compare prompts</span></div></a></li><li><a href="https://github.com/mcp" data-analytics-event="{&quot;action&quot;:&quot;mcp_registry&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;mcp_registry_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mcp NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.795 1.694a4.287 4.287 0 0 1 6.061 0 4.28 4.28 0 0 1 1.181 3.819 4.282 4.282 0 0 1 3.819 1.181 4.287 4.287 0 0 1 0 6.061l-6.793 6.793a.249.249 0 0 0 0 .353l2.617 2.618a.75.75 0 1 1-1.061 1.061l-2.617-2.618a1.75 1.75 0 0 1 0-2.475l6.793-6.793a2.785 2.785 0 1 0-3.939-3.939l-5.9 5.9a.734.734 0 0 1-.249.165.749.749 0 0 1-.812-1.225l5.9-5.901a2.785 2.785 0 1 0-3.939-3.939L2.931 10.68A.75.75 0 1 1 1.87 9.619l7.925-7.925Z"></path><path d="M12.42 4.069a.752.752 0 0 1 1.061 0 .752.752 0 0 1 0 1.061L7.33 11.28a2.788 2.788 0 0 0 0 3.94 2.788 2.788 0 0 0 3.94 0l6.15-6.151a.752.752 0 0 1 1.061 0 .752.752 0 0 1 0 1.061l-6.151 6.15a4.285 4.285 0 1 1-6.06-6.06l6.15-6.151Z"></path></svg><span class="NavLink-module__title__Q7t0p">MCP Registry<sup class="NavLink-module__label__bil7n">New</sup></span><span class="NavLink-module__subtitle__X4gkW">Integrate external tools</span></div></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_9hb_">DEVELOPER WORKFLOWS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9hb_"><li><a href="https://github.com/features/actions" data-analytics-event="{&quot;action&quot;:&quot;actions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;actions_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-workflow NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1 3a2 2 0 0 1 2-2h6.5a2 2 0 0 1 2 2v6.5a2 2 0 0 1-2 2H7v4.063C7 16.355 7.644 17 8.438 17H12.5v-2.5a2 2 0 0 1 2-2H21a2 2 0 0 1 2 2V21a2 2 0 0 1-2 2h-6.5a2 2 0 0 1-2-2v-2.5H8.437A2.939 2.939 0 0 1 5.5 15.562V11.5H3a2 2 0 0 1-2-2Zm2-.5a.5.5 0 0 0-.5.5v6.5a.5.5 0 0 0 .5.5h6.5a.5.5 0 0 0 .5-.5V3a.5.5 0 0 0-.5-.5ZM14.5 14a.5.5 0 0 0-.5.5V21a.5.5 0 0 0 .5.5H21a.5.5 0 0 0 .5-.5v-6.5a.5.5 0 0 0-.5-.5Z"></path></svg><span class="NavLink-module__title__Q7t0p">Actions</span><span class="NavLink-module__subtitle__X4gkW">Automate any workflow</span></div></a></li><li><a href="https://github.com/features/codespaces" data-analytics-event="{&quot;action&quot;:&quot;codespaces&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;codespaces_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codespaces NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.5 3.75C3.5 2.784 4.284 2 5.25 2h13.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 18.75 13H5.25a1.75 1.75 0 0 1-1.75-1.75Zm-2 12c0-.966.784-1.75 1.75-1.75h17.5c.966 0 1.75.784 1.75 1.75v4a1.75 1.75 0 0 1-1.75 1.75H3.25a1.75 1.75 0 0 1-1.75-1.75ZM5.25 3.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h13.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Zm-2 12a.25.25 0 0 0-.25.25v4c0 .138.112.25.25.25h17.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25Z"></path><path d="M10 17.75a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path></svg><span class="NavLink-module__title__Q7t0p">Codespaces</span><span class="NavLink-module__subtitle__X4gkW">Instant dev environments</span></div></a></li><li><a href="https://github.com/features/issues" data-analytics-event="{&quot;action&quot;:&quot;issues&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;issues_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M12 1c6.075 0 11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1ZM2.5 12a9.5 9.5 0 0 0 9.5 9.5 9.5 9.5 0 0 0 9.5-9.5A9.5 9.5 0 0 0 12 2.5 9.5 9.5 0 0 0 2.5 12Zm9.5 2a2 2 0 1 1-.001-3.999A2 2 0 0 1 12 14Z"></path></svg><span class="NavLink-module__title__Q7t0p">Issues</span><span class="NavLink-module__subtitle__X4gkW">Plan and track work</span></div></a></li><li><a href="https://github.com/features/code-review" data-analytics-event="{&quot;action&quot;:&quot;code_review&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_review_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15.22 4.97a.75.75 0 0 1 1.06 0l6.5 6.5a.75.75 0 0 1 0 1.06l-6.5 6.5a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L21.19 12l-5.97-5.97a.75.75 0 0 1 0-1.06Zm-6.44 0a.75.75 0 0 1 0 1.06L2.81 12l5.97 5.97a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-6.5-6.5a.75.75 0 0 1 0-1.06l6.5-6.5a.75.75 0 0 1 1.06 0Z"></path></svg><span class="NavLink-module__title__Q7t0p">Code Review</span><span class="NavLink-module__subtitle__X4gkW">Manage code changes</span></div></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_dhb_">APPLICATION SECURITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dhb_"><li><a href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M16.53 9.78a.75.75 0 0 0-1.06-1.06L11 13.19l-1.97-1.97a.75.75 0 0 0-1.06 1.06l2.5 2.5a.75.75 0 0 0 1.06 0l5-5Z"></path><path d="m12.54.637 8.25 2.675A1.75 1.75 0 0 1 22 4.976V10c0 6.19-3.771 10.704-9.401 12.83a1.704 1.704 0 0 1-1.198 0C5.77 20.705 2 16.19 2 10V4.976c0-.758.489-1.43 1.21-1.664L11.46.637a1.748 1.748 0 0 1 1.08 0Zm-.617 1.426-8.25 2.676a.249.249 0 0 0-.173.237V10c0 5.46 3.28 9.483 8.43 11.426a.199.199 0 0 0 .14 0C17.22 19.483 20.5 15.461 20.5 10V4.976a.25.25 0 0 0-.173-.237l-8.25-2.676a.253.253 0 0 0-.154 0Z"></path></svg><span class="NavLink-module__title__Q7t0p">GitHub Advanced Security</span><span class="NavLink-module__subtitle__X4gkW">Find and fix vulnerabilities</span></div></a></li><li><a href="https://github.com/security/advanced-security/code-security" data-analytics-event="{&quot;action&quot;:&quot;code_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_security_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code-square NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.3 8.24a.75.75 0 0 1-.04 1.06L7.352 12l2.908 2.7a.75.75 0 1 1-1.02 1.1l-3.5-3.25a.75.75 0 0 1 0-1.1l3.5-3.25a.75.75 0 0 1 1.06.04Zm3.44 1.06a.75.75 0 1 1 1.02-1.1l3.5 3.25a.75.75 0 0 1 0 1.1l-3.5 3.25a.75.75 0 1 1-1.02-1.1l2.908-2.7-2.908-2.7Z"></path><path d="M2 3.75C2 2.784 2.784 2 3.75 2h16.5c.966 0 1.75.784 1.75 1.75v16.5A1.75 1.75 0 0 1 20.25 22H3.75A1.75 1.75 0 0 1 2 20.25Zm1.75-.25a.25.25 0 0 0-.25.25v16.5c0 .138.112.25.25.25h16.5a.25.25 0 0 0 .25-.25V3.75a.25.25 0 0 0-.25-.25Z"></path></svg><span class="NavLink-module__title__Q7t0p">Code security</span><span class="NavLink-module__subtitle__X4gkW">Secure your code as you build</span></div></a></li><li><a href="https://github.com/security/advanced-security/secret-protection" data-analytics-event="{&quot;action&quot;:&quot;secret_protection&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;secret_protection_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-lock NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6 9V7.25C6 3.845 8.503 1 12 1s6 2.845 6 6.25V9h.5a2.5 2.5 0 0 1 2.5 2.5v8a2.5 2.5 0 0 1-2.5 2.5h-13A2.5 2.5 0 0 1 3 19.5v-8A2.5 2.5 0 0 1 5.5 9Zm-1.5 2.5v8a1 1 0 0 0 1 1h13a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-13a1 1 0 0 0-1 1Zm3-4.25V9h9V7.25c0-2.67-1.922-4.75-4.5-4.75-2.578 0-4.5 2.08-4.5 4.75Z"></path></svg><span class="NavLink-module__title__Q7t0p">Secret protection</span><span class="NavLink-module__subtitle__X4gkW">Stop leaks before they start</span></div></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ NavGroup-module__hasSeparator__FnMrN"><span class="NavGroup-module__title__Wzxz2" id="_R_hhb_">EXPLORE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_hhb_"><li><a href="https://github.com/why-github" data-analytics-event="{&quot;action&quot;:&quot;why_github&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;why_github_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Why GitHub</span></a></li><li><a href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">Documentation</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a href="https://github.blog" data-analytics-event="{&quot;action&quot;:&quot;blog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;blog_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">Blog</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a href="https://github.blog/changelog" data-analytics-event="{&quot;action&quot;:&quot;changelog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;changelog_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">Changelog</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a href="https://github.com/marketplace" data-analytics-event="{&quot;action&quot;:&quot;marketplace&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;marketplace_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Marketplace</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a href="https://github.com/features" data-analytics-event="{&quot;action&quot;:&quot;view_all_features&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_features_link_platform_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">View all features</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavLink-module__arrowIcon__amekg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI js-details-container js-header-menu-item"><button type="button" class="NavDropdown-module__button__PEHWX js-details-target" aria-expanded="false">Solutions<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></button><div class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_5ib_">BY COMPANY SIZE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5ib_"><li><a href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprises&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprises_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Enterprises</span></a></li><li><a href="https://github.com/team" data-analytics-event="{&quot;action&quot;:&quot;small_and_medium_teams&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;small_and_medium_teams_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Small and medium teams</span></a></li><li><a href="https://github.com/enterprise/startups" data-analytics-event="{&quot;action&quot;:&quot;startups&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;startups_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Startups</span></a></li><li><a href="https://github.com/solutions/industry/nonprofits" data-analytics-event="{&quot;action&quot;:&quot;nonprofits&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;nonprofits_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Nonprofits</span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_9ib_">BY USE CASE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9ib_"><li><a href="https://github.com/solutions/use-case/app-modernization" data-analytics-event="{&quot;action&quot;:&quot;app_modernization&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;app_modernization_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">App Modernization</span></a></li><li><a href="https://github.com/solutions/use-case/devsecops" data-analytics-event="{&quot;action&quot;:&quot;devsecops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devsecops_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">DevSecOps</span></a></li><li><a href="https://github.com/solutions/use-case/devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">DevOps</span></a></li><li><a href="https://github.com/solutions/use-case/ci-cd" data-analytics-event="{&quot;action&quot;:&quot;ci/cd&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ci/cd_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">CI/CD</span></a></li><li><a href="https://github.com/solutions/use-case" data-analytics-event="{&quot;action&quot;:&quot;view_all_use_cases&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_use_cases_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">View all use cases</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavLink-module__arrowIcon__amekg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_dib_">BY INDUSTRY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dib_"><li><a href="https://github.com/solutions/industry/healthcare" data-analytics-event="{&quot;action&quot;:&quot;healthcare&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;healthcare_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Healthcare</span></a></li><li><a href="https://github.com/solutions/industry/financial-services" data-analytics-event="{&quot;action&quot;:&quot;financial_services&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;financial_services_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Financial services</span></a></li><li><a href="https://github.com/solutions/industry/manufacturing" data-analytics-event="{&quot;action&quot;:&quot;manufacturing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;manufacturing_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Manufacturing</span></a></li><li><a href="https://github.com/solutions/industry/government" data-analytics-event="{&quot;action&quot;:&quot;government&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;government_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Government</span></a></li><li><a href="https://github.com/solutions/industry" data-analytics-event="{&quot;action&quot;:&quot;view_all_industries&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_industries_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">View all industries</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavLink-module__arrowIcon__amekg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a href="https://github.com/solutions" data-analytics-event="{&quot;action&quot;:&quot;view_all_solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_solutions_link_solutions_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">View all solutions</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavLink-module__arrowIcon__amekg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI js-details-container js-header-menu-item"><button type="button" class="NavDropdown-module__button__PEHWX js-details-target" aria-expanded="false">Resources<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></button><div class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_5jb_">EXPLORE BY TOPIC</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5jb_"><li><a href="https://github.com/resources/articles?topic=ai" data-analytics-event="{&quot;action&quot;:&quot;ai&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ai_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">AI</span></a></li><li><a href="https://github.com/resources/articles?topic=software-development" data-analytics-event="{&quot;action&quot;:&quot;software_development&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;software_development_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Software Development</span></a></li><li><a href="https://github.com/resources/articles?topic=devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">DevOps</span></a></li><li><a href="https://github.com/resources/articles?topic=security" data-analytics-event="{&quot;action&quot;:&quot;security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Security</span></a></li><li><a href="https://github.com/resources/articles" data-analytics-event="{&quot;action&quot;:&quot;view_all_topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_topics_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">View all topics</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavLink-module__arrowIcon__amekg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_9jb_">EXPLORE BY TYPE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9jb_"><li><a href="https://github.com/customer-stories" data-analytics-event="{&quot;action&quot;:&quot;customer_stories&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_stories_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Customer stories</span></a></li><li><a href="https://github.com/resources/events" data-analytics-event="{&quot;action&quot;:&quot;events__webinars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;events__webinars_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Events &amp; webinars</span></a></li><li><a href="https://github.com/resources/whitepapers" data-analytics-event="{&quot;action&quot;:&quot;ebooks__reports&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ebooks__reports_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Ebooks &amp; reports</span></a></li><li><a href="https://github.com/solutions/executive-insights" data-analytics-event="{&quot;action&quot;:&quot;business_insights&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;business_insights_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Business insights</span></a></li><li><a href="https://skills.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_skills&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_skills_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">GitHub Skills</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_djb_">SUPPORT &amp; SERVICES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_djb_"><li><a href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">Documentation</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a href="https://support.github.com" data-analytics-event="{&quot;action&quot;:&quot;customer_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_support_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">Customer support</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a href="https://github.com/orgs/community/discussions" data-analytics-event="{&quot;action&quot;:&quot;community_forum&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;community_forum_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Community forum</span></a></li><li><a href="https://github.com/trust-center" data-analytics-event="{&quot;action&quot;:&quot;trust_center&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trust_center_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Trust center</span></a></li><li><a href="https://github.com/partners" data-analytics-event="{&quot;action&quot;:&quot;partners&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;partners_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Partners</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a href="https://github.com/resources" data-analytics-event="{&quot;action&quot;:&quot;view_all_resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_resources_link_resources_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">View all resources</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavLink-module__arrowIcon__amekg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI js-details-container js-header-menu-item"><button type="button" class="NavDropdown-module__button__PEHWX js-details-target" aria-expanded="false">Open Source<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></button><div class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_5kb_">COMMUNITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5kb_"><li><a href="https://github.com/sponsors" data-analytics-event="{&quot;action&quot;:&quot;github_sponsors&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_sponsors_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sponsor-tiers NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M16.004 1.25C18.311 1.25 20 3.128 20 5.75c0 2.292-1.23 4.464-3.295 6.485-.481.47-.98.909-1.482 1.31l.265 1.32 1.375 7.5a.75.75 0 0 1-.982.844l-3.512-1.207a.75.75 0 0 0-.488 0L8.37 23.209a.75.75 0 0 1-.982-.844l1.378-7.512.261-1.309c-.5-.4-1-.838-1.481-1.31C5.479 10.215 4.25 8.043 4.25 5.75c0-2.622 1.689-4.5 3.996-4.5 1.55 0 2.947.752 3.832 1.967l.047.067.047-.067a4.726 4.726 0 0 1 3.612-1.962l.22-.005ZM13.89 14.531c-.418.285-.828.542-1.218.77l-.18.103a.75.75 0 0 1-.734 0l-.071-.04-.46-.272c-.282-.173-.573-.36-.868-.562l-.121.605-1.145 6.239 2.3-.79a2.248 2.248 0 0 1 1.284-.054l.18.053 2.299.79-1.141-6.226-.125-.616ZM16.004 2.75c-1.464 0-2.731.983-3.159 2.459-.209.721-1.231.721-1.44 0-.428-1.476-1.695-2.459-3.16-2.459-1.44 0-2.495 1.173-2.495 3 0 1.811 1.039 3.647 2.844 5.412a19.624 19.624 0 0 0 3.734 2.84l-.019-.011-.184-.111.147-.088a19.81 19.81 0 0 0 3.015-2.278l.37-.352C17.46 9.397 18.5 7.561 18.5 5.75c0-1.827-1.055-3-2.496-3Z"></path></svg><span class="NavLink-module__title__Q7t0p">GitHub Sponsors</span><span class="NavLink-module__subtitle__X4gkW">Fund open source developers</span></div></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_9kb_">PROGRAMS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9kb_"><li><a href="https://securitylab.github.com" data-analytics-event="{&quot;action&quot;:&quot;security_lab&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_lab_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">Security Lab</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a href="https://maintainers.github.com" data-analytics-event="{&quot;action&quot;:&quot;maintainer_community&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;maintainer_community_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">Maintainer Community</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a href="https://github.com/accelerator" data-analytics-event="{&quot;action&quot;:&quot;accelerator&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;accelerator_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Accelerator</span></a></li><li><a href="https://stars.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_stars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_stars_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">GitHub Stars</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a href="https://archiveprogram.github.com" data-analytics-event="{&quot;action&quot;:&quot;archive_program&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;archive_program_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4" target="_blank" rel="noreferrer"><span class="NavLink-module__title__Q7t0p">Archive Program</span><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-link-external NavLink-module__externalIcon__eWIry" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_dkb_">REPOSITORIES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dkb_"><li><a href="https://github.com/topics" data-analytics-event="{&quot;action&quot;:&quot;topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;topics_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Topics</span></a></li><li><a href="https://github.com/trending" data-analytics-event="{&quot;action&quot;:&quot;trending&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trending_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Trending</span></a></li><li><a href="https://github.com/collections" data-analytics-event="{&quot;action&quot;:&quot;collections&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;collections_link_open_source_navbar&quot;}" class="NavLink-module__link__EG3d4"><span class="NavLink-module__title__Q7t0p">Collections</span></a></li></ul></div></li></ul></div></div></li><li><div class="NavDropdown-module__container__l2YeI js-details-container js-header-menu-item"><button type="button" class="NavDropdown-module__button__PEHWX js-details-target" aria-expanded="false">Enterprise<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-chevron-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path></svg></button><div class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_5lb_">ENTERPRISE SOLUTIONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5lb_"><li><a href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprise_platform&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprise_platform_link_enterprise_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-stack NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M11.063 1.456a1.749 1.749 0 0 1 1.874 0l8.383 5.316a1.751 1.751 0 0 1 0 2.956l-8.383 5.316a1.749 1.749 0 0 1-1.874 0L2.68 9.728a1.751 1.751 0 0 1 0-2.956Zm1.071 1.267a.25.25 0 0 0-.268 0L3.483 8.039a.25.25 0 0 0 0 .422l8.383 5.316a.25.25 0 0 0 .268 0l8.383-5.316a.25.25 0 0 0 0-.422Z"></path><path d="M1.867 12.324a.75.75 0 0 1 1.035-.232l8.964 5.685a.25.25 0 0 0 .268 0l8.964-5.685a.75.75 0 0 1 .804 1.267l-8.965 5.685a1.749 1.749 0 0 1-1.874 0l-8.965-5.685a.75.75 0 0 1-.231-1.035Z"></path><path d="M1.867 16.324a.75.75 0 0 1 1.035-.232l8.964 5.685a.25.25 0 0 0 .268 0l8.964-5.685a.75.75 0 0 1 .804 1.267l-8.965 5.685a1.749 1.749 0 0 1-1.874 0l-8.965-5.685a.75.75 0 0 1-.231-1.035Z"></path></svg><span class="NavLink-module__title__Q7t0p">Enterprise platform</span><span class="NavLink-module__subtitle__X4gkW">AI-powered developer platform</span></div></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="NavGroup-module__title__Wzxz2" id="_R_9lb_">AVAILABLE ADD-ONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9lb_"><li><a href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_enterprise_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M16.53 9.78a.75.75 0 0 0-1.06-1.06L11 13.19l-1.97-1.97a.75.75 0 0 0-1.06 1.06l2.5 2.5a.75.75 0 0 0 1.06 0l5-5Z"></path><path d="m12.54.637 8.25 2.675A1.75 1.75 0 0 1 22 4.976V10c0 6.19-3.771 10.704-9.401 12.83a1.704 1.704 0 0 1-1.198 0C5.77 20.705 2 16.19 2 10V4.976c0-.758.489-1.43 1.21-1.664L11.46.637a1.748 1.748 0 0 1 1.08 0Zm-.617 1.426-8.25 2.676a.249.249 0 0 0-.173.237V10c0 5.46 3.28 9.483 8.43 11.426a.199.199 0 0 0 .14 0C17.22 19.483 20.5 15.461 20.5 10V4.976a.25.25 0 0 0-.173-.237l-8.25-2.676a.253.253 0 0 0-.154 0Z"></path></svg><span class="NavLink-module__title__Q7t0p">GitHub Advanced Security</span><span class="NavLink-module__subtitle__X4gkW">Enterprise-grade security features</span></div></a></li><li><a href="https://github.com/features/copilot/copilot-business" data-analytics-event="{&quot;action&quot;:&quot;copilot_for_business&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;copilot_for_business_link_enterprise_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M23.922 16.992c-.861 1.495-5.859 5.023-11.922 5.023-6.063 0-11.061-3.528-11.922-5.023A.641.641 0 0 1 0 16.736v-2.869a.841.841 0 0 1 .053-.22c.372-.935 1.347-2.292 2.605-2.656.167-.429.414-1.055.644-1.517a10.195 10.195 0 0 1-.052-1.086c0-1.331.282-2.499 1.132-3.368.397-.406.89-.717 1.474-.952 1.399-1.136 3.392-2.093 6.122-2.093 2.731 0 4.767.957 6.166 2.093.584.235 1.077.546 1.474.952.85.869 1.132 2.037 1.132 3.368 0 .368-.014.733-.052 1.086.23.462.477 1.088.644 1.517 1.258.364 2.233 1.721 2.605 2.656a.832.832 0 0 1 .053.22v2.869a.641.641 0 0 1-.078.256ZM12.172 11h-.344a4.323 4.323 0 0 1-.355.508C10.703 12.455 9.555 13 7.965 13c-1.725 0-2.989-.359-3.782-1.259a2.005 2.005 0 0 1-.085-.104L4 11.741v6.585c1.435.779 4.514 2.179 8 2.179 3.486 0 6.565-1.4 8-2.179v-6.585l-.098-.104s-.033.045-.085.104c-.793.9-2.057 1.259-3.782 1.259-1.59 0-2.738-.545-3.508-1.492a4.323 4.323 0 0 1-.355-.508h-.016.016Zm.641-2.935c.136 1.057.403 1.913.878 2.497.442.544 1.134.938 2.344.938 1.573 0 2.292-.337 2.657-.751.384-.435.558-1.15.558-2.361 0-1.14-.243-1.847-.705-2.319-.477-.488-1.319-.862-2.824-1.025-1.487-.161-2.192.138-2.533.529-.269.307-.437.808-.438 1.578v.021c0 .265.021.562.063.893Zm-1.626 0c.042-.331.063-.628.063-.894v-.02c-.001-.77-.169-1.271-.438-1.578-.341-.391-1.046-.69-2.533-.529-1.505.163-2.347.537-2.824 1.025-.462.472-.705 1.179-.705 2.319 0 1.211.175 1.926.558 2.361.365.414 1.084.751 2.657.751 1.21 0 1.902-.394 2.344-.938.475-.584.742-1.44.878-2.497Z"></path><path d="M14.5 14.25a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Zm-5 0a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Z"></path></svg><span class="NavLink-module__title__Q7t0p">Copilot for Business</span><span class="NavLink-module__subtitle__X4gkW">Enterprise-grade AI features</span></div></a></li><li><a href="https://github.com/premium-support" data-analytics-event="{&quot;action&quot;:&quot;premium_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;premium_support_link_enterprise_navbar&quot;}" class="NavLink-module__link__EG3d4"><div class="NavLink-module__text__XvpLQ"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-comment-discussion NavLink-module__icon__ltGNM" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 14.25 14H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 15.543V14H1.75A1.75 1.75 0 0 1 0 12.25v-9.5C0 1.784.784 1 1.75 1ZM1.5 2.75v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Z"></path><path d="M22.5 8.75a.25.25 0 0 0-.25-.25h-3.5a.75.75 0 0 1 0-1.5h3.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 22.25 20H21v1.543a1.457 1.457 0 0 1-2.487 1.03L15.939 20H10.75A1.75 1.75 0 0 1 9 18.25v-1.465a.75.75 0 0 1 1.5 0v1.465c0 .138.112.25.25.25h5.5a.75.75 0 0 1 .53.22l2.72 2.72v-2.19a.75.75 0 0 1 .75-.75h2a.25.25 0 0 0 .25-.25v-9.5Z"></path></svg><span class="NavLink-module__title__Q7t0p">Premium Support</span><span class="NavLink-module__subtitle__X4gkW">Enterprise-grade 24/7 support</span></div></a></li></ul></div></li></ul></div></div></li><li><a href="https://github.com/pricing" data-analytics-event="{&quot;action&quot;:&quot;pricing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;pricing&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;pricing_link_pricing_navbar&quot;}" class="NavLink-module__link__EG3d4 MarketingNavigation-module__navLink__hUomM"><span class="NavLink-module__title__Q7t0p">Pricing</span></a></li></ul></nav><script type="application/json" id="__PRIMER_DATA__R_0___">{"resolvedServerColorMode":"day"}</script></div> +</react-partial> + + + + <div class="d-flex flex-column flex-lg-row width-full flex-justify-end flex-lg-items-center text-center tmp-mt-3 tmp-mt-lg-0 text-lg-left tmp-ml-lg-3"> + + + +<qbsearch-input class="search-input" data-scope="repo:microsoft/winget-cli" data-custom-scopes-path="/search/custom_scopes" data-delete-custom-scopes-csrf="D81dytVeG1RlyQxCc85DQmX5-4IISsY4OjcpWxu9SPq07wkqj5vFoWc23_W5PCJp4eQozBUTGkO15ymqDENZrg" data-max-custom-scopes="10" data-header-redesign-enabled="false" data-initial-value="" data-blackbird-suggestions-path="/search/suggestions" data-jump-to-suggestions-path="/_graphql/GetSuggestedNavigationDestinations" data-current-repository="microsoft/winget-cli" data-current-org="microsoft" data-current-owner="" data-logged-in="false" data-copilot-chat-enabled="false" data-nl-search-enabled="false" data-retain-scroll-position="true"> + <div + class="search-input-container search-with-dialog position-relative d-flex flex-row flex-items-center tmp-mr-4 rounded" + data-action="click:qbsearch-input#searchInputContainerClicked" + > + <button + type="button" + class="header-search-button placeholder input-button form-control d-flex flex-1 flex-self-stretch flex-items-center no-wrap width-full py-0 pl-2 pr-0 text-left border-0 box-shadow-none" + data-target="qbsearch-input.inputButton" + aria-label="Search or jump to…" + aria-haspopup="dialog" + placeholder="Search or jump to..." + data-hotkey=s,/ + autocapitalize="off" + data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;searchbar&quot;,&quot;context&quot;:&quot;global&quot;,&quot;tag&quot;:&quot;input&quot;,&quot;label&quot;:&quot;searchbar_input_global_navbar&quot;}" + data-action="click:qbsearch-input#handleExpand" + > + <div class="mr-2 color-fg-muted"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search"> + <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> +</svg> + </div> + <span class="flex-1" data-target="qbsearch-input.inputButtonText">Search or jump to...</span> + <div class="d-flex" data-target="qbsearch-input.hotkeyIndicator"> + <svg xmlns="http://www.w3.org/2000/svg" width="22" height="20" aria-hidden="true" class="mr-1"><path fill="none" stroke="#979A9C" opacity=".4" d="M3.5.5h12c1.7 0 3 1.3 3 3v13c0 1.7-1.3 3-3 3h-12c-1.7 0-3-1.3-3-3v-13c0-1.7 1.3-3 3-3z"></path><path fill="#979A9C" d="M11.8 6L8 15.1h-.9L10.8 6h1z"></path></svg> + </div> + </button> + + <input type="hidden" name="type" class="js-site-search-type-field"> + + +<div class="Overlay--hidden " data-modal-dialog-overlay> + <modal-dialog data-action="close:qbsearch-input#handleClose cancel:qbsearch-input#handleClose" data-target="qbsearch-input.searchSuggestionsDialog" role="dialog" id="search-suggestions-dialog" aria-modal="true" aria-labelledby="search-suggestions-dialog-header" data-view-component="true" class="Overlay Overlay--width-large Overlay--height-auto"> + <h1 id="search-suggestions-dialog-header" class="sr-only">Search code, repositories, users, issues, pull requests...</h1> + <div class="Overlay-body Overlay-body--paddingNone"> + + <div data-view-component="true"> <div class="search-suggestions position-fixed width-full color-shadow-large border color-fg-default color-bg-default overflow-hidden d-flex flex-column query-builder-container" + style="border-radius: 12px;" + data-target="qbsearch-input.queryBuilderContainer" + hidden + > + <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="query-builder-test-form" action="" accept-charset="UTF-8" method="get"> + <query-builder data-target="qbsearch-input.queryBuilder" id="query-builder-query-builder-test" data-filter-key=":" data-view-component="true" class="QueryBuilder search-query-builder"> + <div class="FormControl FormControl--fullWidth"> + <label id="query-builder-test-label" for="query-builder-test" class="FormControl-label sr-only"> + Search + </label> + <div + class="QueryBuilder-StyledInput width-fit " + data-target="query-builder.styledInput" + > + <span id="query-builder-test-leadingvisual-wrap" class="FormControl-input-leadingVisualWrap QueryBuilder-leadingVisualWrap"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search FormControl-input-leadingVisual"> + <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> +</svg> + </span> + <div data-target="query-builder.styledInputContainer" class="QueryBuilder-StyledInputContainer"> + <div + aria-hidden="true" + class="QueryBuilder-StyledInputContent" + data-target="query-builder.styledInputContent" + ></div> + <div class="QueryBuilder-InputWrapper"> + <div aria-hidden="true" class="QueryBuilder-Sizer" data-target="query-builder.sizer"></div> + <input id="query-builder-test" name="query-builder-test" value="" autocomplete="off" type="text" role="combobox" spellcheck="false" aria-expanded="false" aria-describedby="validation-d1d4533f-335c-421d-b990-0e44d9167f66" data-target="query-builder.input" data-action=" + input:query-builder#inputChange + blur:query-builder#inputBlur + keydown:query-builder#inputKeydown + focus:query-builder#inputFocus + " data-view-component="true" class="FormControl-input QueryBuilder-Input FormControl-medium" /> + </div> + </div> + <span data-target="query-builder.clearButton" hidden> + <span class="sr-only" id="query-builder-test-clear">Clear</span> + <button role="button" id="query-builder-test-clear-button" aria-labelledby="query-builder-test-clear query-builder-test-label" data-action=" + click:query-builder#clear + focus:query-builder#clearButtonFocus + blur:query-builder#clearButtonBlur + " variant="small" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium mr-1 tmp-mr-1 px-2 tmp-px-2 py-0 tmp-py-0 d-flex flex-items-center rounded-1 color-fg-muted"> <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x-circle-fill Button-visual"> + <path d="M2.343 13.657A8 8 0 1 1 13.658 2.343 8 8 0 0 1 2.343 13.657ZM6.03 4.97a.751.751 0 0 0-1.042.018.751.751 0 0 0-.018 1.042L6.94 8 4.97 9.97a.749.749 0 0 0 .326 1.275.749.749 0 0 0 .734-.215L8 9.06l1.97 1.97a.749.749 0 0 0 1.275-.326.749.749 0 0 0-.215-.734L9.06 8l1.97-1.97a.749.749 0 0 0-.326-1.275.749.749 0 0 0-.734.215L8 6.94Z"></path> +</svg> +</button> + + </span> + </div> + <template id="search-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search"> + <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> +</svg> +</template> + +<template id="code-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code"> + <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> +</svg> +</template> + +<template id="file-code-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-file-code"> + <path d="M4 1.75C4 .784 4.784 0 5.75 0h5.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v8.586A1.75 1.75 0 0 1 14.25 15h-9a.75.75 0 0 1 0-1.5h9a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 10 4.25V1.5H5.75a.25.25 0 0 0-.25.25v2.5a.75.75 0 0 1-1.5 0Zm1.72 4.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l1.47-1.47-1.47-1.47a.75.75 0 0 1 0-1.06ZM3.28 7.78 1.81 9.25l1.47 1.47a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Zm8.22-6.218V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path> +</svg> +</template> + +<template id="history-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-history"> + <path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path> +</svg> +</template> + +<template id="repo-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo"> + <path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path> +</svg> +</template> + +<template id="bookmark-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-bookmark"> + <path d="M3 2.75C3 1.784 3.784 1 4.75 1h6.5c.966 0 1.75.784 1.75 1.75v11.5a.75.75 0 0 1-1.227.579L8 11.722l-3.773 3.107A.751.751 0 0 1 3 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.91l3.023-2.489a.75.75 0 0 1 .954 0l3.023 2.49V2.75a.25.25 0 0 0-.25-.25Z"></path> +</svg> +</template> + +<template id="plus-circle-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-plus-circle"> + <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7.25-3.25v2.5h2.5a.75.75 0 0 1 0 1.5h-2.5v2.5a.75.75 0 0 1-1.5 0v-2.5h-2.5a.75.75 0 0 1 0-1.5h2.5v-2.5a.75.75 0 0 1 1.5 0Z"></path> +</svg> +</template> + +<template id="circle-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-dot-fill"> + <path d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"></path> +</svg> +</template> + +<template id="trash-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-trash"> + <path d="M11 1.75V3h2.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H5V1.75C5 .784 5.784 0 6.75 0h2.5C10.216 0 11 .784 11 1.75ZM4.496 6.675l.66 6.6a.25.25 0 0 0 .249.225h5.19a.25.25 0 0 0 .249-.225l.66-6.6a.75.75 0 0 1 1.492.149l-.66 6.6A1.748 1.748 0 0 1 10.595 15h-5.19a1.75 1.75 0 0 1-1.741-1.575l-.66-6.6a.75.75 0 1 1 1.492-.15ZM6.5 1.75V3h3V1.75a.25.25 0 0 0-.25-.25h-2.5a.25.25 0 0 0-.25.25Z"></path> +</svg> +</template> + +<template id="team-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-people"> + <path d="M2 5.5a3.5 3.5 0 1 1 5.898 2.549 5.508 5.508 0 0 1 3.034 4.084.75.75 0 1 1-1.482.235 4 4 0 0 0-7.9 0 .75.75 0 0 1-1.482-.236A5.507 5.507 0 0 1 3.102 8.05 3.493 3.493 0 0 1 2 5.5ZM11 4a3.001 3.001 0 0 1 2.22 5.018 5.01 5.01 0 0 1 2.56 3.012.749.749 0 0 1-.885.954.752.752 0 0 1-.549-.514 3.507 3.507 0 0 0-2.522-2.372.75.75 0 0 1-.574-.73v-.352a.75.75 0 0 1 .416-.672A1.5 1.5 0 0 0 11 5.5.75.75 0 0 1 11 4Zm-5.5-.5a2 2 0 1 0-.001 3.999A2 2 0 0 0 5.5 3.5Z"></path> +</svg> +</template> + +<template id="project-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-project"> + <path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25ZM11.75 3a.75.75 0 0 1 .75.75v7.5a.75.75 0 0 1-1.5 0v-7.5a.75.75 0 0 1 .75-.75Zm-8.25.75a.75.75 0 0 1 1.5 0v5.5a.75.75 0 0 1-1.5 0ZM8 3a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 3Z"></path> +</svg> +</template> + +<template id="pencil-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-pencil"> + <path d="M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61Zm.176 4.823L9.75 4.81l-6.286 6.287a.253.253 0 0 0-.064.108l-.558 1.953 1.953-.558a.253.253 0 0 0 .108-.064Zm1.238-3.763a.25.25 0 0 0-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 0 0 0-.354Z"></path> +</svg> +</template> + +<template id="copilot-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copilot"> + <path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path> +</svg> +</template> + +<template id="copilot-error-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copilot-error"> + <path d="M16 11.24c0 .112-.072.274-.21.467L13 9.688V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-.198 0-.388-.009-.571-.029L6.833 5.226a4.01 4.01 0 0 0 .17-.782c.117-.935-.037-1.395-.241-1.614-.193-.206-.637-.413-1.682-.297-.683.076-1.115.231-1.395.415l-1.257-.91c.579-.564 1.413-.877 2.485-.996 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095Zm-5.083-8.707c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Zm2.511 11.074c-1.393.776-3.272 1.428-5.43 1.428-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.18-.455-.241-.963-.252-1.475L.31 4.107A.747.747 0 0 1 0 3.509V3.49a.748.748 0 0 1 .625-.73c.156-.026.306.047.435.139l14.667 10.578a.592.592 0 0 1 .227.264.752.752 0 0 1 .046.249v.022a.75.75 0 0 1-1.19.596Zm-1.367-.991L5.635 7.964a5.128 5.128 0 0 1-.889.073c-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433 1.539 0 3.089-.505 4.063-.934Z"></path> +</svg> +</template> + +<template id="workflow-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-workflow"> + <path d="M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"></path> +</svg> +</template> + +<template id="book-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-book"> + <path d="M0 1.75A.75.75 0 0 1 .75 1h4.253c1.227 0 2.317.59 3 1.501A3.743 3.743 0 0 1 11.006 1h4.245a.75.75 0 0 1 .75.75v10.5a.75.75 0 0 1-.75.75h-4.507a2.25 2.25 0 0 0-1.591.659l-.622.621a.75.75 0 0 1-1.06 0l-.622-.621A2.25 2.25 0 0 0 5.258 13H.75a.75.75 0 0 1-.75-.75Zm7.251 10.324.004-5.073-.002-2.253A2.25 2.25 0 0 0 5.003 2.5H1.5v9h3.757a3.75 3.75 0 0 1 1.994.574ZM8.755 4.75l-.004 7.322a3.752 3.752 0 0 1 1.992-.572H14.5v-9h-3.495a2.25 2.25 0 0 0-2.25 2.25Z"></path> +</svg> +</template> + +<template id="code-review-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code-review"> + <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 13H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25v-8.5C0 1.784.784 1 1.75 1ZM1.5 2.75v8.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-8.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Zm5.28 1.72a.75.75 0 0 1 0 1.06L5.31 7l1.47 1.47a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-2-2a.75.75 0 0 1 0-1.06l2-2a.75.75 0 0 1 1.06 0Zm2.44 0a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L10.69 7 9.22 5.53a.75.75 0 0 1 0-1.06Z"></path> +</svg> +</template> + +<template id="codespaces-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-codespaces"> + <path d="M0 11.25c0-.966.784-1.75 1.75-1.75h12.5c.966 0 1.75.784 1.75 1.75v3A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm2-9.5C2 .784 2.784 0 3.75 0h8.5C13.216 0 14 .784 14 1.75v5a1.75 1.75 0 0 1-1.75 1.75h-8.5A1.75 1.75 0 0 1 2 6.75Zm1.75-.25a.25.25 0 0 0-.25.25v5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5a.25.25 0 0 0-.25-.25Zm-2 9.5a.25.25 0 0 0-.25.25v3c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-3a.25.25 0 0 0-.25-.25Z"></path><path d="M7 12.75a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path> +</svg> +</template> + +<template id="comment-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment"> + <path d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> +</svg> +</template> + +<template id="comment-discussion-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment-discussion"> + <path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path> +</svg> +</template> + +<template id="organization-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-organization"> + <path d="M1.75 16A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0h8.5C11.216 0 12 .784 12 1.75v12.5c0 .085-.006.168-.018.25h2.268a.25.25 0 0 0 .25-.25V8.285a.25.25 0 0 0-.111-.208l-1.055-.703a.749.749 0 1 1 .832-1.248l1.055.703c.487.325.779.871.779 1.456v5.965A1.75 1.75 0 0 1 14.25 16h-3.5a.766.766 0 0 1-.197-.026c-.099.017-.2.026-.303.026h-3a.75.75 0 0 1-.75-.75V14h-1v1.25a.75.75 0 0 1-.75.75Zm-.25-1.75c0 .138.112.25.25.25H4v-1.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 .75.75v1.25h2.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25ZM3.75 6h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5ZM3 3.75A.75.75 0 0 1 3.75 3h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 3.75Zm4 3A.75.75 0 0 1 7.75 6h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 7 6.75ZM7.75 3h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5ZM3 9.75A.75.75 0 0 1 3.75 9h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 9.75ZM7.75 9h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5Z"></path> +</svg> +</template> + +<template id="rocket-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-rocket"> + <path d="M14.064 0h.186C15.216 0 16 .784 16 1.75v.186a8.752 8.752 0 0 1-2.564 6.186l-.458.459c-.314.314-.641.616-.979.904v3.207c0 .608-.315 1.172-.833 1.49l-2.774 1.707a.749.749 0 0 1-1.11-.418l-.954-3.102a1.214 1.214 0 0 1-.145-.125L3.754 9.816a1.218 1.218 0 0 1-.124-.145L.528 8.717a.749.749 0 0 1-.418-1.11l1.71-2.774A1.748 1.748 0 0 1 3.31 4h3.204c.288-.338.59-.665.904-.979l.459-.458A8.749 8.749 0 0 1 14.064 0ZM8.938 3.623h-.002l-.458.458c-.76.76-1.437 1.598-2.02 2.5l-1.5 2.317 2.143 2.143 2.317-1.5c.902-.583 1.74-1.26 2.499-2.02l.459-.458a7.25 7.25 0 0 0 2.123-5.127V1.75a.25.25 0 0 0-.25-.25h-.186a7.249 7.249 0 0 0-5.125 2.123ZM3.56 14.56c-.732.732-2.334 1.045-3.005 1.148a.234.234 0 0 1-.201-.064.234.234 0 0 1-.064-.201c.103-.671.416-2.273 1.15-3.003a1.502 1.502 0 1 1 2.12 2.12Zm6.94-3.935c-.088.06-.177.118-.266.175l-2.35 1.521.548 1.783 1.949-1.2a.25.25 0 0 0 .119-.213ZM3.678 8.116 5.2 5.766c.058-.09.117-.178.176-.266H3.309a.25.25 0 0 0-.213.119l-1.2 1.95ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> +</svg> +</template> + +<template id="shield-check-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield-check"> + <path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> +</svg> +</template> + +<template id="heart-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-heart"> + <path d="m8 14.25.345.666a.75.75 0 0 1-.69 0l-.008-.004-.018-.01a7.152 7.152 0 0 1-.31-.17 22.055 22.055 0 0 1-3.434-2.414C2.045 10.731 0 8.35 0 5.5 0 2.836 2.086 1 4.25 1 5.797 1 7.153 1.802 8 3.02 8.847 1.802 10.203 1 11.75 1 13.914 1 16 2.836 16 5.5c0 2.85-2.045 5.231-3.885 6.818a22.066 22.066 0 0 1-3.744 2.584l-.018.01-.006.003h-.002ZM4.25 2.5c-1.336 0-2.75 1.164-2.75 3 0 2.15 1.58 4.144 3.365 5.682A20.58 20.58 0 0 0 8 13.393a20.58 20.58 0 0 0 3.135-2.211C12.92 9.644 14.5 7.65 14.5 5.5c0-1.836-1.414-3-2.75-3-1.373 0-2.609.986-3.029 2.456a.749.749 0 0 1-1.442 0C6.859 3.486 5.623 2.5 4.25 2.5Z"></path> +</svg> +</template> + +<template id="server-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-server"> + <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v4c0 .372-.116.717-.314 1 .198.283.314.628.314 1v4a1.75 1.75 0 0 1-1.75 1.75H1.75A1.75 1.75 0 0 1 0 12.75v-4c0-.358.109-.707.314-1a1.739 1.739 0 0 1-.314-1v-4C0 1.784.784 1 1.75 1ZM1.5 2.75v4c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Zm.25 5.75a.25.25 0 0 0-.25.25v4c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25ZM7 4.75A.75.75 0 0 1 7.75 4h4.5a.75.75 0 0 1 0 1.5h-4.5A.75.75 0 0 1 7 4.75ZM7.75 10h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM3 4.75A.75.75 0 0 1 3.75 4h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 4.75ZM3.75 10h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5Z"></path> +</svg> +</template> + +<template id="globe-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-globe"> + <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM5.78 8.75a9.64 9.64 0 0 0 1.363 4.177c.255.426.542.832.857 1.215.245-.296.551-.705.857-1.215A9.64 9.64 0 0 0 10.22 8.75Zm4.44-1.5a9.64 9.64 0 0 0-1.363-4.177c-.307-.51-.612-.919-.857-1.215a9.927 9.927 0 0 0-.857 1.215A9.64 9.64 0 0 0 5.78 7.25Zm-5.944 1.5H1.543a6.507 6.507 0 0 0 4.666 5.5c-.123-.181-.24-.365-.352-.552-.715-1.192-1.437-2.874-1.581-4.948Zm-2.733-1.5h2.733c.144-2.074.866-3.756 1.58-4.948.12-.197.237-.381.353-.552a6.507 6.507 0 0 0-4.666 5.5Zm10.181 1.5c-.144 2.074-.866 3.756-1.58 4.948-.12.197-.237.381-.353.552a6.507 6.507 0 0 0 4.666-5.5Zm2.733-1.5a6.507 6.507 0 0 0-4.666-5.5c.123.181.24.365.353.552.714 1.192 1.436 2.874 1.58 4.948Z"></path> +</svg> +</template> + +<template id="issue-opened-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened"> + <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> +</svg> +</template> + +<template id="device-mobile-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-mobile"> + <path d="M3.75 0h8.5C13.216 0 14 .784 14 1.75v12.5A1.75 1.75 0 0 1 12.25 16h-8.5A1.75 1.75 0 0 1 2 14.25V1.75C2 .784 2.784 0 3.75 0ZM3.5 1.75v12.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25ZM8 13a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path> +</svg> +</template> + +<template id="package-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-package"> + <path d="m8.878.392 5.25 3.045c.54.314.872.89.872 1.514v6.098a1.75 1.75 0 0 1-.872 1.514l-5.25 3.045a1.75 1.75 0 0 1-1.756 0l-5.25-3.045A1.75 1.75 0 0 1 1 11.049V4.951c0-.624.332-1.201.872-1.514L7.122.392a1.75 1.75 0 0 1 1.756 0ZM7.875 1.69l-4.63 2.685L8 7.133l4.755-2.758-4.63-2.685a.248.248 0 0 0-.25 0ZM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432Zm6.25 8.271 4.625-2.683a.25.25 0 0 0 .125-.216V5.677L8.75 8.432Z"></path> +</svg> +</template> + +<template id="credit-card-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-credit-card"> + <path d="M10.75 9a.75.75 0 0 0 0 1.5h1.5a.75.75 0 0 0 0-1.5h-1.5Z"></path><path d="M0 3.75C0 2.784.784 2 1.75 2h12.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 14H1.75A1.75 1.75 0 0 1 0 12.25ZM14.5 6.5h-13v5.75c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25Zm0-2.75a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25V5h13Z"></path> +</svg> +</template> + +<template id="play-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play"> + <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> +</svg> +</template> + +<template id="gift-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-gift"> + <path d="M2 2.75A2.75 2.75 0 0 1 4.75 0c.983 0 1.873.42 2.57 1.232.268.318.497.668.68 1.042.183-.375.411-.725.68-1.044C9.376.42 10.266 0 11.25 0a2.75 2.75 0 0 1 2.45 4h.55c.966 0 1.75.784 1.75 1.75v2c0 .698-.409 1.301-1 1.582v4.918A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V9.332C.409 9.05 0 8.448 0 7.75v-2C0 4.784.784 4 1.75 4h.55c-.192-.375-.3-.8-.3-1.25ZM7.25 9.5H2.5v4.75c0 .138.112.25.25.25h4.5Zm1.5 0v5h4.5a.25.25 0 0 0 .25-.25V9.5Zm0-4V8h5.5a.25.25 0 0 0 .25-.25v-2a.25.25 0 0 0-.25-.25Zm-7 0a.25.25 0 0 0-.25.25v2c0 .138.112.25.25.25h5.5V5.5h-5.5Zm3-4a1.25 1.25 0 0 0 0 2.5h2.309c-.233-.818-.542-1.401-.878-1.793-.43-.502-.915-.707-1.431-.707ZM8.941 4h2.309a1.25 1.25 0 0 0 0-2.5c-.516 0-1 .205-1.43.707-.337.392-.646.975-.879 1.793Z"></path> +</svg> +</template> + +<template id="code-square-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code-square"> + <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25Zm7.47 3.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L10.69 8 9.22 6.53a.75.75 0 0 1 0-1.06ZM6.78 6.53 5.31 8l1.47 1.47a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> +</svg> +</template> + +<template id="device-desktop-icon"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-desktop"> + <path d="M14.25 1c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 14.25 12h-3.727c.099 1.041.52 1.872 1.292 2.757A.752.752 0 0 1 11.25 16h-6.5a.75.75 0 0 1-.565-1.243c.772-.885 1.192-1.716 1.292-2.757H1.75A1.75 1.75 0 0 1 0 10.25v-7.5C0 1.784.784 1 1.75 1ZM1.75 2.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25ZM9.018 12H6.982a5.72 5.72 0 0 1-.765 2.5h3.566a5.72 5.72 0 0 1-.765-2.5Z"></path> +</svg> +</template> + + <div class="position-relative"> + <ul + role="listbox" + class="ActionListWrap QueryBuilder-ListWrap" + aria-label="Suggestions" + data-action=" + combobox-commit:query-builder#comboboxCommit + mousedown:query-builder#resultsMousedown + " + data-target="query-builder.resultsList" + data-persist-list=false + id="query-builder-test-results" + tabindex="-1" + ></ul> + + </div> + <div class="FormControl-inlineValidation" id="validation-d1d4533f-335c-421d-b990-0e44d9167f66" hidden="hidden"> + <span class="FormControl-inlineValidation--visual"> + <svg aria-hidden="true" data-component="Octicon" height="12" viewBox="0 0 12 12" version="1.1" width="12" data-view-component="true" class="octicon octicon-alert-fill"> + <path d="M4.855.708c.5-.896 1.79-.896 2.29 0l4.675 8.351a1.312 1.312 0 0 1-1.146 1.954H1.33A1.313 1.313 0 0 1 .183 9.058ZM7 7V3H5v4Zm-1 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"></path> +</svg> + </span> + <span></span> +</div> </div> + <div data-target="query-builder.screenReaderFeedback" aria-live="polite" aria-atomic="true" class="sr-only"></div> +</query-builder></form> + <div class="d-flex flex-row color-fg-muted tmp-px-3 text-small color-bg-default search-feedback-prompt"> + <a target="_blank" href="https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax" data-view-component="true" class="Link color-fg-accent text-normal ml-2 tmp-ml-2">Search syntax tips</a> <div class="d-flex flex-1"></div> + </div> + </div> +</div> + + </div> +</modal-dialog></div> + </div> + <div data-action="click:qbsearch-input#retract" class="dark-backdrop position-fixed" hidden data-target="qbsearch-input.darkBackdrop"></div> + <div class="color-fg-default"> + +<dialog-helper> + <dialog data-target="qbsearch-input.feedbackDialog" data-action="close:qbsearch-input#handleDialogClose cancel:qbsearch-input#handleDialogClose" id="feedback-dialog" aria-modal="true" aria-labelledby="feedback-dialog-title" aria-describedby="feedback-dialog-description" data-view-component="true" class="Overlay Overlay-whenNarrow Overlay--size-medium Overlay--motion-scaleFade Overlay--disableScroll"> + <div data-view-component="true" class="Overlay-header"> + <div class="Overlay-headerContentWrap"> + <div class="Overlay-titleWrap"> + <h1 class="Overlay-title " id="feedback-dialog-title"> + Provide feedback + </h1> + + </div> + <div class="Overlay-actionWrap"> + <button data-close-dialog-id="feedback-dialog" aria-label="Close" aria-label="Close" type="button" data-view-component="true" class="close-button Overlay-closeButton"><svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> + <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> +</svg></button> + </div> + </div> + +</div> + <scrollable-region data-labelled-by="feedback-dialog-title"> + <div data-view-component="true" class="Overlay-body"> <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="code-search-feedback-form" data-turbo="false" action="/search/feedback" accept-charset="UTF-8" method="post"><input type="hidden" data-csrf="true" name="authenticity_token" value="nuibZitNHX6gAThVQdG2Ny99htkwRSfkpfXkYEYUp2Ah7uskwZwchmmwBJ4Miv/E2+qFsH7FSPGY/bpDdoJH5w==" /> + <p>We read every piece of feedback, and take your input very seriously.</p> + <textarea name="feedback" class="form-control width-full mb-2" style="height: 120px" id="feedback"></textarea> + <input name="include_email" id="include_email" aria-label="Include my email address so I can be contacted" class="form-control mr-2" type="checkbox"> + <label for="include_email" style="font-weight: normal">Include my email address so I can be contacted</label> +</form></div> + </scrollable-region> + <div data-view-component="true" class="Overlay-footer Overlay-footer--alignEnd"> <button data-close-dialog-id="feedback-dialog" type="button" data-view-component="true" class="btn"> Cancel +</button> + <button form="code-search-feedback-form" data-action="click:qbsearch-input#submitFeedback" type="submit" data-view-component="true" class="btn-primary btn"> Submit feedback +</button> +</div> +</dialog></dialog-helper> + + <custom-scopes data-target="qbsearch-input.customScopesManager"> + +<dialog-helper> + <dialog data-target="custom-scopes.customScopesModalDialog" data-action="close:qbsearch-input#handleDialogClose cancel:qbsearch-input#handleDialogClose" id="custom-scopes-dialog" aria-modal="true" aria-labelledby="custom-scopes-dialog-title" aria-describedby="custom-scopes-dialog-description" data-view-component="true" class="Overlay Overlay-whenNarrow Overlay--size-medium Overlay--motion-scaleFade Overlay--disableScroll"> + <div data-view-component="true" class="Overlay-header Overlay-header--divided"> + <div class="Overlay-headerContentWrap"> + <div class="Overlay-titleWrap"> + <h1 class="Overlay-title " id="custom-scopes-dialog-title"> + Saved searches + </h1> + <h2 id="custom-scopes-dialog-description" class="Overlay-description">Use saved searches to filter your results more quickly</h2> + </div> + <div class="Overlay-actionWrap"> + <button data-close-dialog-id="custom-scopes-dialog" aria-label="Close" aria-label="Close" type="button" data-view-component="true" class="close-button Overlay-closeButton"><svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> + <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> +</svg></button> + </div> + </div> + +</div> + <scrollable-region data-labelled-by="custom-scopes-dialog-title"> + <div data-view-component="true" class="Overlay-body"> <div data-target="custom-scopes.customScopesModalDialogFlash"></div> + + <div hidden class="create-custom-scope-form" data-target="custom-scopes.createCustomScopeForm"> + <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="custom-scopes-dialog-form" data-turbo="false" action="/search/custom_scopes" accept-charset="UTF-8" method="post"><input type="hidden" data-csrf="true" name="authenticity_token" value="Qr+NXW7pvcwvk3SJjvvhsY2W6ntQrRtaK4QWT0rB0o4S4fQMCBjK42fCoiyuT9wJmqmKP+tGMm6wZOKCNSOD/A==" /> + <div data-target="custom-scopes.customScopesModalDialogFlash"></div> + + <input type="hidden" id="custom_scope_id" name="custom_scope_id" data-target="custom-scopes.customScopesIdField"> + + <div class="form-group"> + <label for="custom_scope_name">Name</label> + <auto-check src="/search/custom_scopes/check_name" required> + <input + type="text" + name="custom_scope_name" + id="custom_scope_name" + data-target="custom-scopes.customScopesNameField" + class="form-control" + autocomplete="off" + placeholder="github-ruby" + required + maxlength="50"> + <input type="hidden" data-csrf="true" value="slrKEzsd41L3U5vTUpH1DMWeOVO9LSD7+F4LadZ1AkqxSCQ9ous+FEmMt68nfjA945H2OXy+23cs1HudzBWbLA==" /> + </auto-check> + </div> + + <div class="form-group"> + <label for="custom_scope_query">Query</label> + <input + type="text" + name="custom_scope_query" + id="custom_scope_query" + data-target="custom-scopes.customScopesQueryField" + class="form-control" + autocomplete="off" + placeholder="(repo:mona/a OR repo:mona/b) AND lang:python" + required + maxlength="500"> + </div> + + <p class="text-small color-fg-muted"> + To see all available qualifiers, see our <a class="Link--inTextBlock" href="https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax">documentation</a>. + </p> +</form> </div> + + <div data-target="custom-scopes.manageCustomScopesForm"> + <div data-target="custom-scopes.list"></div> + </div> + +</div> + </scrollable-region> + <div data-view-component="true" class="Overlay-footer Overlay-footer--alignEnd Overlay-footer--divided"> <button data-action="click:custom-scopes#customScopesCancel" type="button" data-view-component="true" class="btn"> Cancel +</button> + <button form="custom-scopes-dialog-form" data-action="click:custom-scopes#customScopesSubmit" data-target="custom-scopes.customScopesSubmitButton" type="submit" data-view-component="true" class="btn-primary btn"> Create saved search +</button> +</div> +</dialog></dialog-helper> + </custom-scopes> + </div> +</qbsearch-input> + + + <div class="position-relative HeaderMenu-link-wrap d-lg-inline-block"> + <a + href="/login?return_to=https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fwinget-cli%2Fblob%2Fmaster%2Fdoc%2FSettings.md" + class="HeaderMenu-link HeaderMenu-link--sign-in HeaderMenu-button flex-shrink-0 no-underline d-none d-lg-inline-flex border border-lg-0 rounded px-2 py-1" + style="margin-left: 12px;" + data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e1dbd869587423f125748adc0e73672ed58ed31fcb4f5efe51c02c93d274f4a1" + data-analytics-event="{&quot;category&quot;:&quot;Marketing nav&quot;,&quot;action&quot;:&quot;click to go to homepage&quot;,&quot;label&quot;:&quot;ref_page:Marketing;ref_cta:Sign in;ref_loc:Header&quot;}" + > + Sign in + </a> + </div> + + <a href="/signup?ref_cta=Sign+up&amp;ref_loc=header+logged+out&amp;ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow&amp;source=header-repo&amp;source_repo=microsoft%2Fwinget-cli" + class="HeaderMenu-link HeaderMenu-link--sign-up HeaderMenu-button flex-shrink-0 d-flex d-lg-inline-flex no-underline border color-border-default rounded px-2 py-1" + data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e1dbd869587423f125748adc0e73672ed58ed31fcb4f5efe51c02c93d274f4a1" + data-analytics-event="{&quot;category&quot;:&quot;Sign up&quot;,&quot;action&quot;:&quot;click to sign up for account&quot;,&quot;label&quot;:&quot;ref_page:/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show;ref_cta:Sign up;ref_loc:header logged out&quot;}" + > + Sign up + </a> + + <div class="AppHeader-appearanceSettings"> + <react-partial-anchor> + <button data-target="react-partial-anchor.anchor" id="icon-button-1a996999-77a2-446c-a8f5-705a37d64868" aria-labelledby="tooltip-32ef08c2-24dc-43cd-8908-bfdcc26568f8" type="button" disabled="disabled" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium AppHeader-button HeaderMenu-link border cursor-wait"> <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-sliders Button-visual"> + <path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path> +</svg> +</button><tool-tip id="tooltip-32ef08c2-24dc-43cd-8908-bfdcc26568f8" for="icon-button-1a996999-77a2-446c-a8f5-705a37d64868" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Appearance settings</tool-tip> + + <template data-target="react-partial-anchor.template"> + <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.c6bef8006da6a4d6.module.css" /> +<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/appearance-settings.0d1c5833260ecb07.module.css" /> + +<react-partial + partial-name="appearance-settings" + data-ssr="false" + data-attempted-ssr="false" + data-react-profiling="false" +> + + <script type="application/json" data-target="react-partial.embeddedData">{"props":{}}</script> + <div data-target="react-partial.reactRoot"></div> +</react-partial> + + + </template> + </react-partial-anchor> + </div> + + <button type="button" class="sr-only js-header-menu-focus-trap d-block d-lg-none">Resetting focus</button> + </div> + </div> + </div> + </div> +</header> + + <div hidden="hidden" data-view-component="true" class="js-stale-session-flash stale-session-flash flash flash-warn flash-full"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"> + <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> +</svg> + <span class="js-stale-session-flash-signed-in" hidden>You signed in with another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> + <span class="js-stale-session-flash-signed-out" hidden>You signed out in another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> + <span class="js-stale-session-flash-switched" hidden>You switched accounts on another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> + + <button id="icon-button-053460af-f4b2-4c9f-a439-ba052fa36b85" aria-labelledby="tooltip-b89bc715-a17d-439b-9725-467f16d6f9cb" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium flash-close js-flash-close"> <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x Button-visual"> + <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> +</svg> +</button><tool-tip id="tooltip-b89bc715-a17d-439b-9725-467f16d6f9cb" for="icon-button-053460af-f4b2-4c9f-a439-ba052fa36b85" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Dismiss alert</tool-tip> + + + +</div> + </div> + + <div id="start-of-content" class="show-on-focus"></div> + + + + + + + + + <div id="js-flash-container" class="flash-container" data-turbo-replace> + + + + + <template class="js-flash-template"> + +<div class="flash flash-full {{ className }}"> + <div > + <button autofocus class="flash-close js-flash-close" type="button" aria-label="Dismiss this message"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> + <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> +</svg> + </button> + <div aria-atomic="true" role="alert" class="js-flash-alert"> + + <div>{{ message }}</div> + + </div> + </div> +</div> + </template> +</div> + + + + + + + + + + <div + class="application-main " + data-commit-hovercards-enabled + data-discussion-hovercards-enabled + data-issue-and-pr-hovercards-enabled + data-project-hovercards-enabled + > + <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class=""> + <main id="js-repo-pjax-container" > + + + + + + + + + + + + + + <div id="repository-container-header" class="tmp-pt-3 hide-full-screen" style="background-color: var(--page-header-bgColor, var(--color-page-header-bg));" data-turbo-replace> + + <div class="d-flex flex-nowrap flex-justify-end tmp-mb-3 tmp-px-3 tmp-px-lg-5" style="gap: 1rem;"> + + <div class="flex-auto min-width-0 width-fit"> + + <div class=" d-flex flex-wrap flex-items-center wb-break-word f3 text-normal"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo color-fg-muted mr-2 tmp-mr-2"> + <path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path> +</svg> + + <span class="author flex-self-stretch" itemprop="author"> + <a class="url fn" rel="author" data-hovercard-type="organization" data-hovercard-url="/orgs/microsoft/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/microsoft"> + microsoft +</a> </span> + <span class="mx-1 flex-self-stretch color-fg-muted">/</span> + <strong itemprop="name" class="mr-2 flex-self-stretch"> + <a data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" href="/microsoft/winget-cli">winget-cli</a> + </strong> + + <span></span><span class="Label Label--secondary v-align-middle mr-1">Public</span> + </div> + + + </div> + + <div id="repository-details-container" class="flex-shrink-0" data-turbo-replace style="max-width: 70%;"> + <ul class="pagehead-actions flex-shrink-0 d-none d-md-inline" style="padding: 2px 0;"> + + + + <li> + <a href="/login?return_to=%2Fmicrosoft%2Fwinget-cli" rel="nofollow" id="repository-details-watch-button" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;notification subscription menu watch&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="9c03ffa50b5d246fc793de6a516a8b5b99f27d9daba479d1789efe64dc473e72" aria-label="You must be signed in to change notification settings" data-view-component="true" class="btn-sm btn"> <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-bell mr-2 tmp-mr-2"> + <path d="M8 16a2 2 0 0 0 1.985-1.75c.017-.137-.097-.25-.235-.25h-3.5c-.138 0-.252.113-.235.25A2 2 0 0 0 8 16ZM3 5a5 5 0 0 1 10 0v2.947c0 .05.015.098.042.139l1.703 2.555A1.519 1.519 0 0 1 13.482 13H2.518a1.516 1.516 0 0 1-1.263-2.36l1.703-2.554A.255.255 0 0 0 3 7.947Zm5-3.5A3.5 3.5 0 0 0 4.5 5v2.947c0 .346-.102.683-.294.97l-1.703 2.556a.017.017 0 0 0-.003.01l.001.006c0 .002.002.004.004.006l.006.004.007.001h10.964l.007-.001.006-.004.004-.006.001-.007a.017.017 0 0 0-.003-.01l-1.703-2.554a1.745 1.745 0 0 1-.294-.97V5A3.5 3.5 0 0 0 8 1.5Z"></path> +</svg>Notifications +</a> <tool-tip id="tooltip-2153020b-6624-439a-8bb3-73bc446ef019" for="repository-details-watch-button" popover="manual" data-direction="s" data-type="description" data-view-component="true" class="sr-only position-absolute">You must be signed in to change notification settings</tool-tip> + + </li> + + <li> + <a icon="repo-forked" id="fork-button" href="/login?return_to=%2Fmicrosoft%2Fwinget-cli" rel="nofollow" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;repo details fork button&quot;,&quot;repository_id&quot;:197275130,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="6986c9c75eedbd2ce342a557acf1f23c91502ac77b55446406ba4046e7abd18e" data-view-component="true" class="btn-sm btn"> <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo-forked mr-2 tmp-mr-2"> + <path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"></path> +</svg>Fork + <span id="repo-network-counter" data-pjax-replace="true" data-turbo-replace="true" title="1,749" data-view-component="true" class="Counter">1.7k</span> +</a> + </li> + + <li> + <div data-view-component="true" class="BtnGroup d-flex"> + <a href="/login?return_to=%2Fmicrosoft%2Fwinget-cli" rel="nofollow" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;star button&quot;,&quot;repository_id&quot;:197275130,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="1d142b9d50b6a462cdc7a9045b45eca4952ed7bf7aaf4918c24cd5e23bec0097" aria-label="You must be signed in to star a repository" data-view-component="true" class="tooltipped tooltipped-sw btn-sm btn"> <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-star v-align-text-bottom d-inline-block mr-2 tmp-mr-2"> + <path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"></path> +</svg><span data-view-component="true" class="d-inline"> + Star +</span> <span id="repo-stars-counter-star" aria-label="25954 users starred this repository" data-singular-suffix="user starred this repository" data-plural-suffix="users starred this repository" data-turbo-replace="true" title="25,954" data-view-component="true" class="Counter js-social-count">26k</span> +</a></div> + </li> + +</ul> + + </div> + </div> + + <div id="responsive-meta-container" data-turbo-replace> +</div> + + + <nav data-pjax="#js-repo-pjax-container" aria-label="Repository" data-view-component="true" class="js-repo-nav js-sidenav-container-pjax js-responsive-underlinenav overflow-hidden UnderlineNav px-3 tmp-px-3 px-md-4 tmp-px-md-4 px-lg-5 tmp-px-lg-5"> + + <ul data-view-component="true" class="UnderlineNav-body list-style-none"> + <li data-view-component="true" class="d-inline-flex"> + <a id="code-tab" href="/microsoft/winget-cli" data-tab-item="i0code-tab" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages repo_deployments repo_attestations /microsoft/winget-cli" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g c" data-command-id="repositories:go-to-code" data-react-nav="code-view" data-react-nav-anchor="code-view-repo-link" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Code&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" aria-current="page" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item selected"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code UnderlineNav-octicon d-none d-sm-inline"> + <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> +</svg> + <span data-content="Code">Code</span> + <span id="code-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> + + + +</a></li> + <li data-view-component="true" class="d-inline-flex"> + <a id="issues-tab" href="/microsoft/winget-cli/issues" data-tab-item="i1issues-tab" data-selected-links="repo_issues repo_labels repo_milestones /microsoft/winget-cli/issues" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g i" data-command-id="repositories:go-to-issues" data-react-nav="issues-react" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Issues&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened UnderlineNav-octicon d-none d-sm-inline"> + <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> +</svg> + <span data-content="Issues">Issues</span> + <span id="issues-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="1,254" data-view-component="true" class="Counter">1.3k</span> + + + +</a></li> + <li data-view-component="true" class="d-inline-flex"> + <a id="pull-requests-tab" href="/microsoft/winget-cli/pulls" data-tab-item="i2pull-requests-tab" data-selected-links="repo_pulls checks /microsoft/winget-cli/pulls" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g p" data-command-id="repositories:go-to-pull-requests" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Pull requests&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-pull-request UnderlineNav-octicon d-none d-sm-inline"> + <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path> +</svg> + <span data-content="Pull requests">Pull requests</span> + <span id="pull-requests-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="27" data-view-component="true" class="Counter">27</span> + + + +</a></li> + <li data-view-component="true" class="d-inline-flex"> + <a id="discussions-tab" href="/microsoft/winget-cli/discussions" data-tab-item="i3discussions-tab" data-selected-links="repo_discussions /microsoft/winget-cli/discussions" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g g" data-command-id="repositories:go-to-discussions" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Discussions&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment-discussion UnderlineNav-octicon d-none d-sm-inline"> + <path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path> +</svg> + <span data-content="Discussions">Discussions</span> + <span id="discussions-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> + + + +</a></li> + <li data-view-component="true" class="d-inline-flex"> + <a id="actions-tab" href="/microsoft/winget-cli/actions" data-tab-item="i4actions-tab" data-selected-links="repo_actions /microsoft/winget-cli/actions" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g a" data-command-id="repositories:go-to-actions" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Actions&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play UnderlineNav-octicon d-none d-sm-inline"> + <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> +</svg> + <span data-content="Actions">Actions</span> + <span id="actions-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> + + + +</a></li> + <li data-view-component="true" class="d-inline-flex"> + <a id="projects-tab" href="/microsoft/winget-cli/projects" data-tab-item="i5projects-tab" data-selected-links="repo_projects new_repo_project repo_project /microsoft/winget-cli/projects" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g b" data-command-id="repositories:go-to-projects" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Projects&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-table UnderlineNav-octicon d-none d-sm-inline"> + <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path> +</svg> + <span data-content="Projects">Projects</span> + <span id="projects-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> + + + +</a></li> + <li data-view-component="true" class="d-inline-flex"> + <a id="models-tab" href="/microsoft/winget-cli/models" data-tab-item="i6models-tab" data-selected-links="repo_models repo_models_prompts repo_models_playground /microsoft/winget-cli/models" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g m" data-command-id="repositories:go-to-models" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Models&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-ai-model UnderlineNav-octicon d-none d-sm-inline"> + <path d="M10.628 7.25a2.25 2.25 0 1 1 0 1.5H8.622a2.25 2.25 0 0 1-2.513 1.466L5.03 12.124a2.25 2.25 0 1 1-1.262-.814l1.035-1.832A2.245 2.245 0 0 1 4.25 8c0-.566.209-1.082.553-1.478L3.768 4.69a2.25 2.25 0 1 1 1.262-.814l1.079 1.908A2.25 2.25 0 0 1 8.622 7.25ZM2.5 2.5a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm4 4.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm6.25 0a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm-9.5 5.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path> +</svg> + <span data-content="Models">Models</span> + <span id="models-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> + + + +</a></li> + <li data-view-component="true" class="d-inline-flex"> + <a id="security-and-quality-tab" href="/microsoft/winget-cli/security" data-tab-item="i7security-and-quality-tab" data-selected-links="security overview alerts policy token_scanning code_scanning /microsoft/winget-cli/security" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g s" data-command-id="repositories:go-to-security" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Security and quality&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield UnderlineNav-octicon d-none d-sm-inline"> + <path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> +</svg> + <span data-content="Security and quality">Security and quality</span> + <span id="security-and-quality-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="0" hidden="hidden" data-view-component="true" class="Counter">0</span> + + + +</a></li> + <li data-view-component="true" class="d-inline-flex"> + <a id="insights-tab" href="/microsoft/winget-cli/pulse" data-tab-item="i8insights-tab" data-selected-links="repo_graphs repo_contributors dependency_graph dependabot_updates pulse people community /microsoft/winget-cli/pulse" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-command-id="repositories:go-to-insights" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Insights&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> + + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-graph UnderlineNav-octicon d-none d-sm-inline"> + <path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> +</svg> + <span data-content="Insights">Insights</span> + <span id="insights-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> + + + +</a></li> +</ul> + <div style="visibility:hidden;" data-view-component="true" class="UnderlineNav-actions js-responsive-underlinenav-overflow position-absolute pr-3 tmp-pr-3 pr-md-4 tmp-pr-md-4 pr-lg-5 tmp-pr-lg-5 right-0"> <action-menu data-select-variant="none" data-view-component="true"> + <focus-group direction="vertical" mnemonics retain> + <button id="action-menu-36068c8d-149f-47e7-ae88-00991d34145f-button" popovertarget="action-menu-36068c8d-149f-47e7-ae88-00991d34145f-overlay" aria-controls="action-menu-36068c8d-149f-47e7-ae88-00991d34145f-list" aria-haspopup="true" aria-labelledby="tooltip-d6645c64-f3a6-4818-a9f4-222c0e142268" type="button" data-view-component="true" class="Button Button--iconOnly Button--secondary Button--medium UnderlineNav-item"> <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-kebab-horizontal Button-visual"> + <path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path> +</svg> +</button><tool-tip id="tooltip-d6645c64-f3a6-4818-a9f4-222c0e142268" for="action-menu-36068c8d-149f-47e7-ae88-00991d34145f-button" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Additional navigation options</tool-tip> + + +<anchored-position data-target="action-menu.overlay" id="action-menu-36068c8d-149f-47e7-ae88-00991d34145f-overlay" anchor="action-menu-36068c8d-149f-47e7-ae88-00991d34145f-button" align="start" side="outside-bottom" anchor-offset="normal" popover="auto" data-view-component="true"> + <div data-view-component="true" class="Overlay Overlay--size-auto"> + + <div data-view-component="true" class="Overlay-body Overlay-body--paddingNone"> <action-list> + <div data-view-component="true"> + <ul aria-labelledby="action-menu-36068c8d-149f-47e7-ae88-00991d34145f-button" id="action-menu-36068c8d-149f-47e7-ae88-00991d34145f-list" role="menu" data-view-component="true" class="ActionListWrap--inset ActionListWrap"> + <li hidden="hidden" data-menu-item="i0code-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-3e2ac631-6799-417b-80cb-d8f834554e4e" href="/microsoft/winget-cli" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code"> + <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Code +</span> +</a> + +</li> + <li hidden="hidden" data-menu-item="i1issues-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-43c10f24-013f-4555-b309-afe864307ab3" href="/microsoft/winget-cli/issues" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened"> + <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Issues +</span> +</a> + +</li> + <li hidden="hidden" data-menu-item="i2pull-requests-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-a71f4193-6315-4d22-8167-a225a82c4f27" href="/microsoft/winget-cli/pulls" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-pull-request"> + <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Pull requests +</span> +</a> + +</li> + <li hidden="hidden" data-menu-item="i3discussions-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-5a28069d-971b-40c5-8311-03548c696dd5" href="/microsoft/winget-cli/discussions" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment-discussion"> + <path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Discussions +</span> +</a> + +</li> + <li hidden="hidden" data-menu-item="i4actions-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-6f487e3d-bedc-466c-9fb7-47cdad59b5ca" href="/microsoft/winget-cli/actions" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play"> + <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Actions +</span> +</a> + +</li> + <li hidden="hidden" data-menu-item="i5projects-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-5ef02777-1a82-4e6b-9f04-64d23190449d" href="/microsoft/winget-cli/projects" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-table"> + <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Projects +</span> +</a> + +</li> + <li hidden="hidden" data-menu-item="i6models-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-60ebb859-bf5d-4520-bbda-20bc643650de" href="/microsoft/winget-cli/models" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-ai-model"> + <path d="M10.628 7.25a2.25 2.25 0 1 1 0 1.5H8.622a2.25 2.25 0 0 1-2.513 1.466L5.03 12.124a2.25 2.25 0 1 1-1.262-.814l1.035-1.832A2.245 2.245 0 0 1 4.25 8c0-.566.209-1.082.553-1.478L3.768 4.69a2.25 2.25 0 1 1 1.262-.814l1.079 1.908A2.25 2.25 0 0 1 8.622 7.25ZM2.5 2.5a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm4 4.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm6.25 0a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm-9.5 5.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Models +</span> +</a> + +</li> + <li hidden="hidden" data-menu-item="i7security-and-quality-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-93458d19-b20a-4cbb-adf3-ddcc466062f3" href="/microsoft/winget-cli/security" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield"> + <path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Security and quality +</span> +</a> + +</li> + <li hidden="hidden" data-menu-item="i8insights-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> + + + <a tabindex="-1" id="item-e8068581-6741-438e-a01d-7a1afa563312" href="/microsoft/winget-cli/pulse" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> + <span class="ActionListItem-visual ActionListItem-visual--leading"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-graph"> + <path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> +</svg> + </span> + + <span data-view-component="true" class="ActionListItem-label"> + Insights +</span> +</a> + +</li> +</ul> +</div></action-list> + + +</div> + +</div></anchored-position> </focus-group> +</action-menu></div> +</nav> + + </div> + + + + +<turbo-frame id="repo-content-turbo-frame" target="_top" data-turbo-action="advance" class=""> + <div id="repo-content-pjax-container" class="repository-content " > + + + + + + + + + + + + + + + +<react-app + app-name="code-view" + initial-path="/microsoft/winget-cli/blob/master/doc/Settings.md" + style="display: block; min-height: calc(100vh - 64px);" + data-attempted-ssr="true" + data-ssr="true" + data-lazy="false" + data-alternate="false" + data-data-router-enabled="true" + data-react-profiling="false" +> + + <script type="application/json" data-target="react-app.embeddedData">{"payload":{"codeViewBlobRoute":{"csv":null,"csvError":null,"headerInfo":{"toc":[{"level":1,"text":"WinGet CLI Settings","anchor":"winget-cli-settings","htmlText":"WinGet CLI Settings"},{"level":2,"text":"File Location","anchor":"file-location","htmlText":"File Location"},{"level":2,"text":"Source","anchor":"source","htmlText":"Source"},{"level":3,"text":"autoUpdateIntervalInMinutes","anchor":"autoupdateintervalinminutes","htmlText":"autoUpdateIntervalInMinutes"},{"level":2,"text":"Visual","anchor":"visual","htmlText":"Visual"},{"level":3,"text":"progressBar","anchor":"progressbar","htmlText":"progressBar"},{"level":3,"text":"anonymizeDisplayedPaths","anchor":"anonymizedisplayedpaths","htmlText":"anonymizeDisplayedPaths"},{"level":3,"text":"enableSixels","anchor":"enablesixels","htmlText":"enableSixels"},{"level":2,"text":"Install Behavior","anchor":"install-behavior","htmlText":"Install Behavior"},{"level":3,"text":"Disable Install Notes","anchor":"disable-install-notes","htmlText":"Disable Install Notes"},{"level":3,"text":"Portable Package User Root","anchor":"portable-package-user-root","htmlText":"Portable Package User Root"},{"level":3,"text":"Portable Package Machine Root","anchor":"portable-package-machine-root","htmlText":"Portable Package Machine Root"},{"level":3,"text":"Skip Dependencies","anchor":"skip-dependencies","htmlText":"Skip Dependencies"},{"level":3,"text":"Archive Extraction Method","anchor":"archive-extraction-method","htmlText":"Archive Extraction Method"},{"level":3,"text":"Preferences and Requirements","anchor":"preferences-and-requirements","htmlText":"Preferences and Requirements"},{"level":3,"text":"Scope","anchor":"scope","htmlText":"Scope"},{"level":3,"text":"Locale","anchor":"locale","htmlText":"Locale"},{"level":3,"text":"Architectures","anchor":"architectures","htmlText":"Architectures"},{"level":3,"text":"Installer Types","anchor":"installer-types","htmlText":"Installer Types"},{"level":3,"text":"Default install root","anchor":"default-install-root","htmlText":"Default install root"},{"level":3,"text":"Maximum resumes","anchor":"maximum-resumes","htmlText":"Maximum resumes"},{"level":2,"text":"Uninstall Behavior","anchor":"uninstall-behavior","htmlText":"Uninstall Behavior"},{"level":3,"text":"Purge Portable Package","anchor":"purge-portable-package","htmlText":"Purge Portable Package"},{"level":2,"text":"Configure Behavior","anchor":"configure-behavior","htmlText":"Configure Behavior"},{"level":3,"text":"Default Module Root","anchor":"default-module-root","htmlText":"Default Module Root"},{"level":2,"text":"Download Behavior","anchor":"download-behavior","htmlText":"Download Behavior"},{"level":3,"text":"Default Download Directory","anchor":"default-download-directory","htmlText":"Default Download Directory"},{"level":2,"text":"Telemetry","anchor":"telemetry","htmlText":"Telemetry"},{"level":3,"text":"disable","anchor":"disable","htmlText":"disable"},{"level":2,"text":"Logging","anchor":"logging","htmlText":"Logging"},{"level":3,"text":"level","anchor":"level","htmlText":"level"},{"level":3,"text":"channels","anchor":"channels","htmlText":"channels"},{"level":3,"text":"fileNameStrategy","anchor":"filenamestrategy","htmlText":"fileNameStrategy"},{"level":3,"text":"file","anchor":"file","htmlText":"file"},{"level":2,"text":"Network","anchor":"network","htmlText":"Network"},{"level":3,"text":"Downloader","anchor":"downloader","htmlText":"Downloader"},{"level":2,"text":"Interactivity","anchor":"interactivity","htmlText":"Interactivity"},{"level":3,"text":"disable","anchor":"disable-1","htmlText":"disable"},{"level":2,"text":"Experimental Features","anchor":"experimental-features","htmlText":"Experimental Features"},{"level":3,"text":"directMSI","anchor":"directmsi","htmlText":"directMSI"},{"level":3,"text":"resume","anchor":"resume","htmlText":"resume"},{"level":3,"text":"fonts","anchor":"fonts","htmlText":"fonts"},{"level":3,"text":"sourcePriority","anchor":"sourcepriority","htmlText":"sourcePriority"}]},"issueTemplate":null,"discussionTemplate":null,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch1 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eWinGet CLI Settings\u003c/h1\u003e\u003ca id=\"user-content-winget-cli-settings\" class=\"anchor\" aria-label=\"Permalink: WinGet CLI Settings\" href=\"#winget-cli-settings\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eYou can configure WinGet by editing the \u003ccode\u003esettings.json\u003c/code\u003e file. Running \u003ccode\u003ewinget settings\u003c/code\u003e will open the file in the default json editor; if no editor is configured, Windows will prompt for you to select an editor, and Notepad is a sensible option if you have no other preference.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFile Location\u003c/h2\u003e\u003ca id=\"user-content-file-location\" class=\"anchor\" aria-label=\"Permalink: File Location\" href=\"#file-location\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSettings file is located in %LOCALAPPDATA%\\Packages\\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\\LocalState\\settings.json\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf you are using the non-packaged WinGet version by building it from source code, the file will be located under %LOCALAPPDATA%\\Microsoft\\WinGet\\Settings\\settings.json\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eIf you are creating a settings file from scratch, make sure that the line \u003ccode\u003e\"$schema\": \"https://aka.ms/winget-settings.schema.json\",\u003c/code\u003e is in it.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSource\u003c/h2\u003e\u003ca id=\"user-content-source\" class=\"anchor\" aria-label=\"Permalink: Source\" href=\"#source\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003esource\u003c/code\u003e settings involve configuration to the WinGet source.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;source\u0026quot;: {\n \u0026quot;autoUpdateIntervalInMinutes\u0026quot;: 3\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"source\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"autoUpdateIntervalInMinutes\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eautoUpdateIntervalInMinutes\u003c/h3\u003e\u003ca id=\"user-content-autoupdateintervalinminutes\" class=\"anchor\" aria-label=\"Permalink: autoUpdateIntervalInMinutes\" href=\"#autoupdateintervalinminutes\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA positive integer represents the update interval in minutes. The check for updates only happens when a source is used. A zero will disable the check for updates to a source. Any other values are invalid.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eDisable: 0\u003c/li\u003e\n\u003cli\u003eDefault: 15\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eTo manually update the source use \u003ccode\u003ewinget source update\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eVisual\u003c/h2\u003e\u003ca id=\"user-content-visual\" class=\"anchor\" aria-label=\"Permalink: Visual\" href=\"#visual\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003evisual\u003c/code\u003e settings involve visual elements that are displayed by WinGet\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eprogressBar\u003c/h3\u003e\u003ca id=\"user-content-progressbar\" class=\"anchor\" aria-label=\"Permalink: progressBar\" href=\"#progressbar\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eStyle of the progress spinner and bar that WinGet displays when not specified by arguments. In addition, all options except \u003ccode\u003edisabled\u003c/code\u003e send \u003ca href=\"https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC\" rel=\"nofollow\"\u003eVirtual Terminal progress\u003c/a\u003e updates that any supporting terminal may display visually.\u003c/p\u003e\n\u003cdiv class=\"markdown-alert markdown-alert-note\" dir=\"auto\"\u003e\u003cp class=\"markdown-alert-title\" dir=\"auto\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-info mr-2\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z\"\u003e\u003c/path\u003e\u003c/svg\u003eNote\u003c/p\u003e\u003cp dir=\"auto\"\u003eYou can also disable progress output for a single command using the \u003ccode\u003e--no-progress\u003c/code\u003e flag, which takes precedence over this setting.\u003c/p\u003e\n\u003c/div\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eValue\u003c/th\u003e\n\u003cth\u003eDescription\u003c/th\u003e\n\u003cth\u003eRelease\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eaccent\u003c/code\u003e (default)\u003c/td\u003e\n\u003ctd\u003eUse the \u003ca href=\"https://support.microsoft.com/en-us/windows/change-colors-in-windows-d26ef4d6-819a-581c-1581-493cfcc005fe\" rel=\"nofollow\"\u003eWindows Accent color\u003c/a\u003e\u003c/td\u003e\n\u003ctd\u003e1.0\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eretro\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eUse the current foreground terminal color\u003c/td\u003e\n\u003ctd\u003e1.0\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003erainbow\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eProgress through a rainbow of colors\u003c/td\u003e\n\u003ctd\u003e1.0\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003esixel\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eUse sixel images; requires a terminal that supports displaying sixels, such as \u003ca href=\"https://github.com/microsoft/terminal/releases\"\u003eWindows Terminal\u003c/a\u003e 1.22.2362 or later\u003c/td\u003e\n\u003ctd\u003e1.9\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edisabled\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eNo progress will be displayed\u003c/td\u003e\n\u003ctd\u003e1.9\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;visual\u0026quot;: {\n \u0026quot;progressBar\u0026quot;: \u0026quot;accent\u0026quot;\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"visual\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"progressBar\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eaccent\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eanonymizeDisplayedPaths\u003c/h3\u003e\u003ca id=\"user-content-anonymizedisplayedpaths\" class=\"anchor\" aria-label=\"Permalink: anonymizeDisplayedPaths\" href=\"#anonymizedisplayedpaths\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eReplaces some known folder paths with their respective environment variable. Defaults to true.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;visual\u0026quot;: {\n \u0026quot;anonymizeDisplayedPaths\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"visual\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"anonymizeDisplayedPaths\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eenableSixels\u003c/h3\u003e\u003ca id=\"user-content-enablesixels\" class=\"anchor\" aria-label=\"Permalink: enableSixels\" href=\"#enablesixels\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eEnables output of sixel images in certain contexts. Defaults to false.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;visual\u0026quot;: {\n \u0026quot;enableSixels\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"visual\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"enableSixels\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInstall Behavior\u003c/h2\u003e\u003ca id=\"user-content-install-behavior\" class=\"anchor\" aria-label=\"Permalink: Install Behavior\" href=\"#install-behavior\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003einstallBehavior\u003c/code\u003e settings affect the default behavior of installing and upgrading (where applicable) packages.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDisable Install Notes\u003c/h3\u003e\u003ca id=\"user-content-disable-install-notes\" class=\"anchor\" aria-label=\"Permalink: Disable Install Notes\" href=\"#disable-install-notes\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003edisableInstallNotes\u003c/code\u003e behavior affects whether installation notes are shown after a successful install. Defaults to \u003ccode\u003efalse\u003c/code\u003e if value is not set or is invalid.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;disableInstallNotes\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"disableInstallNotes\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePortable Package User Root\u003c/h3\u003e\u003ca id=\"user-content-portable-package-user-root\" class=\"anchor\" aria-label=\"Permalink: Portable Package User Root\" href=\"#portable-package-user-root\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eportablePackageUserRoot\u003c/code\u003e setting affects the default root directory where packages are installed to under \u003ccode\u003eUser\u003c/code\u003e scope. This setting only applies to packages with the \u003ccode\u003eportable\u003c/code\u003e installer type. Defaults to \u003ccode\u003e%LOCALAPPDATA%/Microsoft/WinGet/Packages/\u003c/code\u003e if value is not set or is invalid.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eNote: This setting value must be an absolute path.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;portablePackageUserRoot\u0026quot;: \u0026quot;C:/Users/FooBar/Packages\u0026quot;\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"portablePackageUserRoot\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eC:/Users/FooBar/Packages\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePortable Package Machine Root\u003c/h3\u003e\u003ca id=\"user-content-portable-package-machine-root\" class=\"anchor\" aria-label=\"Permalink: Portable Package Machine Root\" href=\"#portable-package-machine-root\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eportablePackageMachineRoot\u003c/code\u003e setting affects the default root directory where packages are installed to under \u003ccode\u003eMachine\u003c/code\u003e scope. This setting only applies to packages with the \u003ccode\u003eportable\u003c/code\u003e installer type. Defaults to \u003ccode\u003e%PROGRAMFILES%/WinGet/Packages/\u003c/code\u003e if value is not set or is invalid.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eNote: This setting value must be an absolute path.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;portablePackageMachineRoot\u0026quot;: \u0026quot;C:/Program Files/Packages/Portable\u0026quot;\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"portablePackageMachineRoot\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eC:/Program Files/Packages/Portable\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSkip Dependencies\u003c/h3\u003e\u003ca id=\"user-content-skip-dependencies\" class=\"anchor\" aria-label=\"Permalink: Skip Dependencies\" href=\"#skip-dependencies\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe 'skipDependencies' behavior affects whether dependencies are installed for a given package. Defaults to 'false' if value is not set or is invalid.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;skipDependencies\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"skipDependencies\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eArchive Extraction Method\u003c/h3\u003e\u003ca id=\"user-content-archive-extraction-method\" class=\"anchor\" aria-label=\"Permalink: Archive Extraction Method\" href=\"#archive-extraction-method\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003earchiveExtractionMethod\u003c/code\u003e behavior affects how installer archives are extracted. Currently there are two supported values: \u003ccode\u003eTar\u003c/code\u003e or \u003ccode\u003eShellApi\u003c/code\u003e.\n\u003ccode\u003eTar\u003c/code\u003e indicates that the archive should be extracted using the tar executable ('tar.exe') while \u003ccode\u003eshellApi\u003c/code\u003e indicates using the Windows Shell API. Defaults to \u003ccode\u003eshellApi\u003c/code\u003e if value is not set or is invalid.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;archiveExtractionMethod\u0026quot;: \u0026quot;tar\u0026quot; | \u0026quot;shellApi\u0026quot;\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"archiveExtractionMethod\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003etar\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-ii\"\u003e| \"shellApi\"\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePreferences and Requirements\u003c/h3\u003e\u003ca id=\"user-content-preferences-and-requirements\" class=\"anchor\" aria-label=\"Permalink: Preferences and Requirements\" href=\"#preferences-and-requirements\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSome of the settings are duplicated under \u003ccode\u003epreferences\u003c/code\u003e and \u003ccode\u003erequirements\u003c/code\u003e. \u003ccode\u003epreferences\u003c/code\u003e affect how the various available options are sorted when choosing the one to act on. For instance, the default scope of package installs is for the current user, but if that is not an option then a machine level installer will be chosen. \u003ccode\u003erequirements\u003c/code\u003e filter the options, potentially resulting in an empty list and a failure to install. In the previous example, a user scope requirement would result in no applicable installers and an error.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWhen multiple values are listed under \u003ccode\u003erequirements\u003c/code\u003e, they are treated as an ordered preference in addition to a filter — the first listed value is preferred over subsequent ones when multiple valid options exist. If both \u003ccode\u003erequirements\u003c/code\u003e and \u003ccode\u003epreferences\u003c/code\u003e are set for the same field, the ordering from \u003ccode\u003epreferences\u003c/code\u003e takes precedence.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAny arguments passed on the command line will effectively override the matching \u003ccode\u003erequirement\u003c/code\u003e setting for the duration of that command.\u003c/p\u003e\n\u003cdiv class=\"markdown-alert markdown-alert-note\" dir=\"auto\"\u003e\u003cp class=\"markdown-alert-title\" dir=\"auto\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-info mr-2\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z\"\u003e\u003c/path\u003e\u003c/svg\u003eNote\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eThese settings are only applied for the \u003ccode\u003ewinget install\u003c/code\u003e command.\u003c/li\u003e\n\u003cli\u003eOther commands like \u003ccode\u003ewinget configure\u003c/code\u003e are not affected by these settings.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eScope\u003c/h3\u003e\u003ca id=\"user-content-scope\" class=\"anchor\" aria-label=\"Permalink: Scope\" href=\"#scope\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003escope\u003c/code\u003e behavior affects the choice between installing a package for the current user or for the entire machine. The matching parameter is \u003ccode\u003e--scope\u003c/code\u003e, and uses the same values (\u003ccode\u003euser\u003c/code\u003e or \u003ccode\u003emachine\u003c/code\u003e).\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;preferences\u0026quot;: {\n \u0026quot;scope\u0026quot;: \u0026quot;user\u0026quot;\n }\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"preferences\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"scope\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003euser\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n }\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLocale\u003c/h3\u003e\u003ca id=\"user-content-locale\" class=\"anchor\" aria-label=\"Permalink: Locale\" href=\"#locale\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003elocale\u003c/code\u003e behavior affects the choice of installer based on installer locale. The matching parameter is \u003ccode\u003e--locale\u003c/code\u003e, and uses bcp47 language tag.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;preferences\u0026quot;: {\n \u0026quot;locale\u0026quot;: [ \u0026quot;en-US\u0026quot;, \u0026quot;fr-FR\u0026quot; ]\n }\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"preferences\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"locale\"\u003c/span\u003e: [ \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003een-US\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003efr-FR\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e ]\n }\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eArchitectures\u003c/h3\u003e\u003ca id=\"user-content-architectures\" class=\"anchor\" aria-label=\"Permalink: Architectures\" href=\"#architectures\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003earchitectures\u003c/code\u003e behavior affects what architectures will be selected when installing a package. The matching parameter is \u003ccode\u003e--architecture\u003c/code\u003e. Note that only architectures compatible with your system can be selected.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;preferences\u0026quot;: {\n \u0026quot;architectures\u0026quot;: [\u0026quot;x64\u0026quot;, \u0026quot;arm64\u0026quot;]\n }\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"preferences\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"architectures\"\u003c/span\u003e: [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003ex64\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003earm64\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e]\n }\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInstaller Types\u003c/h3\u003e\u003ca id=\"user-content-installer-types\" class=\"anchor\" aria-label=\"Permalink: Installer Types\" href=\"#installer-types\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003einstallerTypes\u003c/code\u003e behavior affects what installer types will be selected when installing a package. It can also determine which type to install by default if a manifest has multiple types: The list is in priority order, with the first listed type being preferred over the others, and so on. This is convenient for users who for instance prefer portable packages or MSIX/AppX installations. The matching parameter is \u003ccode\u003e--installer-type\u003c/code\u003e, which will override the settings.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAllowed values as of version 1.12.470 include: \u003ccode\u003eappx\u003c/code\u003e, \u003ccode\u003eburn\u003c/code\u003e, \u003ccode\u003eexe\u003c/code\u003e, \u003ccode\u003efont\u003c/code\u003e, \u003ccode\u003einno\u003c/code\u003e, \u003ccode\u003emsi\u003c/code\u003e, \u003ccode\u003emsix\u003c/code\u003e, \u003ccode\u003emsstore\u003c/code\u003e, \u003ccode\u003enullsoft\u003c/code\u003e, \u003ccode\u003eportable\u003c/code\u003e, \u003ccode\u003ewix\u003c/code\u003e, \u003ccode\u003ezip\u003c/code\u003e\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBy default, when no user preference or requirement is configured, WinGet selects installer types in the following order: MSIX, MSI/Wix/Burn, Nullsoft/Inno/EXE, Portable. If it is already installed, the same installer type will be required to ensure a proper upgrade.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;preferences\u0026quot;: {\n \u0026quot;installerTypes\u0026quot;: [\u0026quot;msi\u0026quot;, \u0026quot;msix\u0026quot;]\n },\n \u0026quot;requirements\u0026quot;: {\n \u0026quot;installerTypes\u0026quot;: [\u0026quot;msix\u0026quot;, \u0026quot;msi\u0026quot;]\n }\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"preferences\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"installerTypes\"\u003c/span\u003e: [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003emsi\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003emsix\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e]\n },\n \u003cspan class=\"pl-ent\"\u003e\"requirements\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"installerTypes\"\u003c/span\u003e: [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003emsix\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e, \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003emsi\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e]\n }\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDefault install root\u003c/h3\u003e\u003ca id=\"user-content-default-install-root\" class=\"anchor\" aria-label=\"Permalink: Default install root\" href=\"#default-install-root\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003edefaultInstallRoot\u003c/code\u003e affects the install location when a package requires one. This can be overridden by the \u003ccode\u003e--location\u003c/code\u003e parameter. This setting is only used when a package manifest includes \u003ccode\u003eInstallLocationRequired\u003c/code\u003e, and the actual location is obtained by appending the package ID to the root.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;defaultInstallRoot\u0026quot;: \u0026quot;C:/installRoot\u0026quot;\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"defaultInstallRoot\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eC:/installRoot\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMaximum resumes\u003c/h3\u003e\u003ca id=\"user-content-maximum-resumes\" class=\"anchor\" aria-label=\"Permalink: Maximum resumes\" href=\"#maximum-resumes\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003emaxResumes\u003c/code\u003e setting determines the maximum number of times that a command may be resumed automatically. The default value is 3.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;installBehavior\u0026quot;: {\n \u0026quot;maxResumes\u0026quot;: 3\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"installBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"maxResumes\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e3\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eNote: \u003ca href=\"#resume\"\u003eThe resume behavior is an experimental feature.\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eUninstall Behavior\u003c/h2\u003e\u003ca id=\"user-content-uninstall-behavior\" class=\"anchor\" aria-label=\"Permalink: Uninstall Behavior\" href=\"#uninstall-behavior\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003euninstallBehavior\u003c/code\u003e settings affect the default behavior of uninstalling (where applicable) packages.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePurge Portable Package\u003c/h3\u003e\u003ca id=\"user-content-purge-portable-package\" class=\"anchor\" aria-label=\"Permalink: Purge Portable Package\" href=\"#purge-portable-package\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003epurgePortablePackage\u003c/code\u003e behavior affects the default behavior for uninstalling a portable package. If set to \u003ccode\u003etrue\u003c/code\u003e, uninstall will remove all files and directories relevant to the \u003ccode\u003eportable\u003c/code\u003e package. This setting only applies to packages with the \u003ccode\u003eportable\u003c/code\u003e installer type. Defaults to \u003ccode\u003efalse\u003c/code\u003e if value is not set or is invalid.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;uninstallBehavior\u0026quot;: {\n \u0026quot;purgePortablePackage\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"uninstallBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"purgePortablePackage\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eConfigure Behavior\u003c/h2\u003e\u003ca id=\"user-content-configure-behavior\" class=\"anchor\" aria-label=\"Permalink: Configure Behavior\" href=\"#configure-behavior\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003econfigureBehavior\u003c/code\u003e settings affect the default behavior of applying a configuration.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDefault Module Root\u003c/h3\u003e\u003ca id=\"user-content-default-module-root\" class=\"anchor\" aria-label=\"Permalink: Default Module Root\" href=\"#default-module-root\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003edefaultModuleRoot\u003c/code\u003e behavior affects the default root directory where modules are installed to. Defaults to \u003ccode\u003e%LOCALAPPDATA%/Microsoft/WinGet/Configuration/Modules\u003c/code\u003e if value is not set or is invalid.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eNote: This setting value must be an absolute path.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;configureBehavior\u0026quot;: {\n \u0026quot;defaultModuleRoot\u0026quot;: \u0026quot;C:/Program Files/Modules/\u0026quot;\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"configureBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"defaultModuleRoot\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eC:/Program Files/Modules/\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDownload Behavior\u003c/h2\u003e\u003ca id=\"user-content-download-behavior\" class=\"anchor\" aria-label=\"Permalink: Download Behavior\" href=\"#download-behavior\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003edownloadBehavior\u003c/code\u003e settings affect the default behavior of downloading packages.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDefault Download Directory\u003c/h3\u003e\u003ca id=\"user-content-default-download-directory\" class=\"anchor\" aria-label=\"Permalink: Default Download Directory\" href=\"#default-download-directory\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003edefaultDownloadDirectory\u003c/code\u003e setting affects the default directory where installers are downloaded to. Defaults to \u003ccode\u003e%USERPROFILE%/Downloads/\u003c/code\u003e if value is not set or is invalid.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eNote: This setting value must be an absolute path.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;downloadBehavior\u0026quot;: {\n \u0026quot;defaultDownloadDirectory\u0026quot;: \u0026quot;C:/Users/FooBar/Downloads\u0026quot;\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"downloadBehavior\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"defaultDownloadDirectory\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003eC:/Users/FooBar/Downloads\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTelemetry\u003c/h2\u003e\u003ca id=\"user-content-telemetry\" class=\"anchor\" aria-label=\"Permalink: Telemetry\" href=\"#telemetry\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003etelemetry\u003c/code\u003e settings control whether winget writes ETW events that may be sent to Microsoft on a default installation of Windows.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eSee \u003ca href=\"/microsoft/winget-cli/blob/master/README.md#datatelemetry\"\u003edetails on telemetry\u003c/a\u003e, and our \u003ca href=\"/microsoft/winget-cli/blob/master/PRIVACY.md\"\u003eprimary privacy statement\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003edisable\u003c/h3\u003e\u003ca id=\"user-content-disable\" class=\"anchor\" aria-label=\"Permalink: disable\" href=\"#disable\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;telemetry\u0026quot;: {\n \u0026quot;disable\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"telemetry\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"disable\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf set to true, the \u003ccode\u003etelemetry.disable\u003c/code\u003e setting will prevent any event from being written by the program.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLogging\u003c/h2\u003e\u003ca id=\"user-content-logging\" class=\"anchor\" aria-label=\"Permalink: Logging\" href=\"#logging\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003elogging\u003c/code\u003e settings control the level of detail in log files.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003elevel\u003c/h3\u003e\u003ca id=\"user-content-level\" class=\"anchor\" aria-label=\"Permalink: level\" href=\"#level\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003e--verbose-logs\u003c/code\u003e will override this setting and always creates a verbose log.\nDefaults to \u003ccode\u003einfo\u003c/code\u003e if value is not set or is invalid.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;logging\u0026quot;: {\n \u0026quot;level\u0026quot;: \u0026quot;verbose\u0026quot; | \u0026quot;info\u0026quot; | \u0026quot;warning\u0026quot; | \u0026quot;error\u0026quot; | \u0026quot;critical\u0026quot;\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"logging\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"level\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003everbose\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-ii\"\u003e| \"info\" | \"warning\" | \"error\" | \"critical\"\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003echannels\u003c/h3\u003e\u003ca id=\"user-content-channels\" class=\"anchor\" aria-label=\"Permalink: channels\" href=\"#channels\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe valid values in this array are defined in the function \u003ccode\u003eGetChannelFromName\u003c/code\u003e in the \u003ca href=\"/microsoft/winget-cli/blob/master/src/AppInstallerSharedLib/AppInstallerLogging.cpp\"\u003elogging code\u003c/a\u003e. These align with the \u003cem\u003e\u003cstrong\u003echannel identifier\u003c/strong\u003e\u003c/em\u003e found in the log files. For example, \u003cem\u003e\u003cstrong\u003e\u003ccode\u003eCORE\u003c/code\u003e\u003c/strong\u003e\u003c/em\u003e in:\u003c/p\u003e\n\u003cdiv class=\"snippet-clipboard-content notranslate position-relative overflow-auto\" data-snippet-clipboard-copy-content=\"2023-12-06 19:17:07.988 [CORE] WinGet, version [1.7.0-preview], activity [{24A91EA8-46BE-47A1-B65C-CEBCE90B8675}]\"\u003e\u003cpre lang=\"plaintext\" class=\"notranslate\"\u003e\u003ccode\u003e2023-12-06 19:17:07.988 [CORE] WinGet, version [1.7.0-preview], activity [{24A91EA8-46BE-47A1-B65C-CEBCE90B8675}]\n\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn addition, there are special values that cover multiple channels. \u003ccode\u003edefault\u003c/code\u003e is the default set of channels, while \u003ccode\u003eall\u003c/code\u003e is all of the channels. Invalid values are ignored.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;logging\u0026quot;: {\n \u0026quot;channels\u0026quot;: [\u0026quot;default\u0026quot;]\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"logging\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"channels\"\u003c/span\u003e: [\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003edefault\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e]\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003efileNameStrategy\u003c/h3\u003e\u003ca id=\"user-content-filenamestrategy\" class=\"anchor\" aria-label=\"Permalink: fileNameStrategy\" href=\"#filenamestrategy\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSets the default strategy for naming log files for installers that support it. \u003ccode\u003emanifest\u003c/code\u003e is the default and uses the manifest name. \u003ccode\u003etimestamp\u003c/code\u003e uses the date and time. \u003ccode\u003eguid\u003c/code\u003e uses a generated GUID. \u003ccode\u003eshortguid\u003c/code\u003e uses the first 8 characters of a generated GUID. Invalid values will revert to \u003ccode\u003emanifest\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"\t\u0026quot;logging\u0026quot;: {\n\t\t\u0026quot;fileNameStrategy\u0026quot;: \u0026quot;manifest\u0026quot; | \u0026quot;timestamp\u0026quot; | \u0026quot;guid\u0026quot; | \u0026quot;shortguid\u0026quot;\n\t},\"\u003e\u003cpre\u003e\t\u003cspan class=\"pl-ent\"\u003e\"logging\"\u003c/span\u003e: {\n\t\t\u003cspan class=\"pl-ent\"\u003e\"fileNameStrategy\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003emanifest\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-ii\"\u003e| \"timestamp\" | \"guid\" | \"shortguid\"\u003c/span\u003e\n\t},\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003efile\u003c/h3\u003e\u003ca id=\"user-content-file\" class=\"anchor\" aria-label=\"Permalink: file\" href=\"#file\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003efile\u003c/code\u003e settings control the log files generated by winget during operation. These settings apply to the automatic cleanup that happens whenever a Windows Package Manager process is run.\nThey only apply to the default log location, which contains winget logs, AppInstaller logs (the MSIX install UI), and is the default location where installer logs are placed.\nThe automatic cleanup happens at the beginning of the process, so the log file(s) generated by the current process will not be considered in the limits.\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eSetting\u003c/th\u003e\n\u003cth\u003eDescription\u003c/th\u003e\n\u003cth\u003eDefault\u003c/th\u003e\n\u003cth\u003eNote\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eageLimitInDays\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eThe maximum age, in days, of files in the log directory; older files are deleted.\u003c/td\u003e\n\u003ctd\u003e7 (days)\u003c/td\u003e\n\u003ctd\u003eSet to 0 to disable this limit.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003etotalSizeLimitInMB\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eThe maximum size, in megabytes, of all files in the log directory; the oldest files are deleted first.\u003c/td\u003e\n\u003ctd\u003e128 (MB)\u003c/td\u003e\n\u003ctd\u003eSet to 0 to disable this limit.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecountLimit\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eThe maximum number of files in the log directory; the oldest files are deleted first.\u003c/td\u003e\n\u003ctd\u003e0\u003c/td\u003e\n\u003ctd\u003eSet to 0 (the default) to disable this limit.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cp dir=\"auto\"\u003eThese settings apply to the log files that winget writes, only as they are being written. They do not apply to files written by installers or the AppInstaller UI.\u003c/p\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eSetting\u003c/th\u003e\n\u003cth\u003eDescription\u003c/th\u003e\n\u003cth\u003eDefault\u003c/th\u003e\n\u003cth\u003eNote\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eindividualSizeLimitInMB\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eThe maximum size, in megabytes, of an individual log file. If a file would exceed this limit, the logs will wrap. Note that this limit is approximate and the actual files may exceed it by a few bytes.\u003c/td\u003e\n\u003ctd\u003e16 (MB)\u003c/td\u003e\n\u003ctd\u003eSet to 0 to disable this limit.\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;logging\u0026quot;: {\n \u0026quot;file\u0026quot;: {\n \u0026quot;ageLimitInDays\u0026quot;: 7,\n \u0026quot;totalSizeLimitInMB\u0026quot;: 128,\n \u0026quot;countLimit\u0026quot;: 0,\n \u0026quot;individualSizeLimitInMB\u0026quot;: 16,\n }\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"logging\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"file\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"ageLimitInDays\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e7\u003c/span\u003e,\n \u003cspan class=\"pl-ent\"\u003e\"totalSizeLimitInMB\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e128\u003c/span\u003e,\n \u003cspan class=\"pl-ent\"\u003e\"countLimit\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e0\u003c/span\u003e,\n \u003cspan class=\"pl-ent\"\u003e\"individualSizeLimitInMB\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e16\u003c/span\u003e,\n }\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eNetwork\u003c/h2\u003e\u003ca id=\"user-content-network\" class=\"anchor\" aria-label=\"Permalink: Network\" href=\"#network\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003enetwork\u003c/code\u003e settings influence how winget uses the network to retrieve packages and metadata.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDownloader\u003c/h3\u003e\u003ca id=\"user-content-downloader\" class=\"anchor\" aria-label=\"Permalink: Downloader\" href=\"#downloader\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003edownloader\u003c/code\u003e setting controls which code is used when downloading packages. The default is \u003ccode\u003edefault\u003c/code\u003e, which may be any of the options based on our determination.\n\u003ccode\u003ewininet\u003c/code\u003e uses the \u003ca href=\"https://docs.microsoft.com/windows/win32/wininet/about-wininet\" rel=\"nofollow\"\u003eWinINet\u003c/a\u003e APIs, while \u003ccode\u003edo\u003c/code\u003e uses the\n\u003ca href=\"https://support.microsoft.com/windows/delivery-optimization-in-windows-10-0656e53c-15f2-90de-a87a-a2172c94cf6d\" rel=\"nofollow\"\u003eDelivery Optimization\u003c/a\u003e service.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003edoProgressTimeoutInSeconds\u003c/code\u003e setting updates the number of seconds to wait without progress before fallback. The default number of seconds is 60, minimum is 1 and the maximum is 600.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;network\u0026quot;: {\n \u0026quot;downloader\u0026quot;: \u0026quot;do\u0026quot;,\n \u0026quot;doProgressTimeoutInSeconds\u0026quot;: 60\n }\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"network\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"downloader\"\u003c/span\u003e: \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003edo\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e,\n \u003cspan class=\"pl-ent\"\u003e\"doProgressTimeoutInSeconds\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003e60\u003c/span\u003e\n }\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInteractivity\u003c/h2\u003e\u003ca id=\"user-content-interactivity\" class=\"anchor\" aria-label=\"Permalink: Interactivity\" href=\"#interactivity\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003einteractivity\u003c/code\u003e settings control whether winget may show interactive prompts during execution. Note that this refers only to prompts shown by winget itself and not to those shown by package installers.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003edisable\u003c/h3\u003e\u003ca id=\"user-content-disable-1\" class=\"anchor\" aria-label=\"Permalink: disable\" href=\"#disable-1\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;interactivity\u0026quot;: {\n \u0026quot;disable\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"interactivity\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"disable\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIf set to true, the \u003ccode\u003einteractivity.disable\u003c/code\u003e setting will prevent any interactive prompt from being shown.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eExperimental Features\u003c/h2\u003e\u003ca id=\"user-content-experimental-features\" class=\"anchor\" aria-label=\"Permalink: Experimental Features\" href=\"#experimental-features\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eTo allow work to be done and distributed to early adopters for feedback, settings can be used to enable \"experimental\" features.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003eexperimentalFeatures\u003c/code\u003e settings involve the configuration of these \"experimental\" features. Individual features can be enabled under this node. The example below shows sample experimental features.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;experimentalFeatures\u0026quot;: {\n \u0026quot;experimentalCmd\u0026quot;: true,\n \u0026quot;experimentalArg\u0026quot;: false\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"experimentalFeatures\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"experimentalCmd\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e,\n \u003cspan class=\"pl-ent\"\u003e\"experimentalArg\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003efalse\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003edirectMSI\u003c/h3\u003e\u003ca id=\"user-content-directmsi\" class=\"anchor\" aria-label=\"Permalink: directMSI\" href=\"#directmsi\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis feature enables the Windows Package Manager to directly install MSI packages with the MSI APIs rather than through msiexec.\nNote that when silent installation is used this is already in affect, as MSI packages that require elevation will fail in that scenario without it.\nYou can enable the feature as shown below.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;experimentalFeatures\u0026quot;: {\n \u0026quot;directMSI\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"experimentalFeatures\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"directMSI\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eresume\u003c/h3\u003e\u003ca id=\"user-content-resume\" class=\"anchor\" aria-label=\"Permalink: resume\" href=\"#resume\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis feature enables support for some commands to resume.\nYou can enable the feature as shown below.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;experimentalFeatures\u0026quot;: {\n \u0026quot;resume\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"experimentalFeatures\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"resume\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003efonts\u003c/h3\u003e\u003ca id=\"user-content-fonts\" class=\"anchor\" aria-label=\"Permalink: fonts\" href=\"#fonts\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis feature enables support for fonts via \u003ccode\u003ewinget settings\u003c/code\u003e. The \u003ccode\u003ewinget font list\u003c/code\u003e command will list installed font families and the number of installed font faces.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;experimentalFeatures\u0026quot;: {\n \u0026quot;fonts\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"experimentalFeatures\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"fonts\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003esourcePriority\u003c/h3\u003e\u003ca id=\"user-content-sourcepriority\" class=\"anchor\" aria-label=\"Permalink: sourcePriority\" href=\"#sourcepriority\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis feature enables sources to have a priority value assigned. Sources with a higher priority will appear earlier in search results and will be selected for installing new packages when multiple sources have a matching package.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eNote that search result ordering is dependent on several factors, and source priority is the lowest field in that currently (match quality and field are more important).\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-json notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\" \u0026quot;experimentalFeatures\u0026quot;: {\n \u0026quot;sourcePriority\u0026quot;: true\n },\"\u003e\u003cpre\u003e \u003cspan class=\"pl-ent\"\u003e\"experimentalFeatures\"\u003c/span\u003e: {\n \u003cspan class=\"pl-ent\"\u003e\"sourcePriority\"\u003c/span\u003e: \u003cspan class=\"pl-c1\"\u003etrue\u003c/span\u003e\n },\u003c/pre\u003e\u003c/div\u003e\n\u003c/article\u003e","richTextTruncated":false,"renderedFileInfo":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"WinGet CLI Settings","kind":"section_1","ident_start":2,"ident_end":21,"extent_start":0,"extent_end":17097,"fully_qualified_name":"WinGet CLI Settings","ident_utf16":{"start":{"line_number":0,"utf16_col":2},"end":{"line_number":0,"utf16_col":21}},"extent_utf16":{"start":{"line_number":0,"utf16_col":0},"end":{"line_number":447,"utf16_col":0}}},{"name":"File Location","kind":"section_2","ident_start":305,"ident_end":318,"extent_start":302,"extent_end":755,"fully_qualified_name":"File Location","ident_utf16":{"start":{"line_number":4,"utf16_col":3},"end":{"line_number":4,"utf16_col":16}},"extent_utf16":{"start":{"line_number":4,"utf16_col":0},"end":{"line_number":12,"utf16_col":0}}},{"name":"Source","kind":"section_2","ident_start":758,"ident_end":764,"extent_start":755,"extent_end":1235,"fully_qualified_name":"Source","ident_utf16":{"start":{"line_number":12,"utf16_col":3},"end":{"line_number":12,"utf16_col":9}},"extent_utf16":{"start":{"line_number":12,"utf16_col":0},"end":{"line_number":31,"utf16_col":0}}},{"name":"autoUpdateIntervalInMinutes","kind":"section_3","ident_start":914,"ident_end":941,"extent_start":910,"extent_end":1235,"fully_qualified_name":"autoUpdateIntervalInMinutes","ident_utf16":{"start":{"line_number":22,"utf16_col":4},"end":{"line_number":22,"utf16_col":31}},"extent_utf16":{"start":{"line_number":22,"utf16_col":0},"end":{"line_number":31,"utf16_col":0}}},{"name":"Visual","kind":"section_2","ident_start":1238,"ident_end":1244,"extent_start":1235,"extent_end":2747,"fully_qualified_name":"Visual","ident_utf16":{"start":{"line_number":31,"utf16_col":3},"end":{"line_number":31,"utf16_col":9}},"extent_utf16":{"start":{"line_number":31,"utf16_col":0},"end":{"line_number":76,"utf16_col":0}}},{"name":"progressBar","kind":"section_3","ident_start":1326,"ident_end":1337,"extent_start":1322,"extent_end":2391,"fully_qualified_name":"progressBar","ident_utf16":{"start":{"line_number":35,"utf16_col":4},"end":{"line_number":35,"utf16_col":15}},"extent_utf16":{"start":{"line_number":35,"utf16_col":0},"end":{"line_number":56,"utf16_col":0}}},{"name":"anonymizeDisplayedPaths","kind":"section_3","ident_start":2395,"ident_end":2418,"extent_start":2391,"extent_end":2592,"fully_qualified_name":"anonymizeDisplayedPaths","ident_utf16":{"start":{"line_number":56,"utf16_col":4},"end":{"line_number":56,"utf16_col":27}},"extent_utf16":{"start":{"line_number":56,"utf16_col":0},"end":{"line_number":66,"utf16_col":0}}},{"name":"enableSixels","kind":"section_3","ident_start":2596,"ident_end":2608,"extent_start":2592,"extent_end":2747,"fully_qualified_name":"enableSixels","ident_utf16":{"start":{"line_number":66,"utf16_col":4},"end":{"line_number":66,"utf16_col":16}},"extent_utf16":{"start":{"line_number":66,"utf16_col":0},"end":{"line_number":76,"utf16_col":0}}},{"name":"Install Behavior","kind":"section_2","ident_start":2750,"ident_end":2766,"extent_start":2747,"extent_end":8882,"fully_qualified_name":"Install Behavior","ident_utf16":{"start":{"line_number":76,"utf16_col":3},"end":{"line_number":76,"utf16_col":19}},"extent_utf16":{"start":{"line_number":76,"utf16_col":0},"end":{"line_number":225,"utf16_col":0}}},{"name":"Disable Install Notes","kind":"section_3","ident_start":2889,"ident_end":2910,"extent_start":2885,"extent_end":3157,"fully_qualified_name":"Disable Install Notes","ident_utf16":{"start":{"line_number":80,"utf16_col":4},"end":{"line_number":80,"utf16_col":25}},"extent_utf16":{"start":{"line_number":80,"utf16_col":0},"end":{"line_number":90,"utf16_col":0}}},{"name":"Portable Package User Root","kind":"section_3","ident_start":3161,"ident_end":3187,"extent_start":3157,"extent_end":3641,"fully_qualified_name":"Portable Package User Root","ident_utf16":{"start":{"line_number":90,"utf16_col":4},"end":{"line_number":90,"utf16_col":30}},"extent_utf16":{"start":{"line_number":90,"utf16_col":0},"end":{"line_number":102,"utf16_col":0}}},{"name":"Portable Package Machine Root","kind":"section_3","ident_start":3645,"ident_end":3674,"extent_start":3641,"extent_end":4137,"fully_qualified_name":"Portable Package Machine Root","ident_utf16":{"start":{"line_number":102,"utf16_col":4},"end":{"line_number":102,"utf16_col":33}},"extent_utf16":{"start":{"line_number":102,"utf16_col":0},"end":{"line_number":114,"utf16_col":0}}},{"name":"Skip Dependencies","kind":"section_3","ident_start":4141,"ident_end":4158,"extent_start":4137,"extent_end":4390,"fully_qualified_name":"Skip Dependencies","ident_utf16":{"start":{"line_number":114,"utf16_col":4},"end":{"line_number":114,"utf16_col":21}},"extent_utf16":{"start":{"line_number":114,"utf16_col":0},"end":{"line_number":124,"utf16_col":0}}},{"name":"Archive Extraction Method","kind":"section_3","ident_start":4394,"ident_end":4419,"extent_start":4390,"extent_end":4873,"fully_qualified_name":"Archive Extraction Method","ident_utf16":{"start":{"line_number":124,"utf16_col":4},"end":{"line_number":124,"utf16_col":29}},"extent_utf16":{"start":{"line_number":124,"utf16_col":0},"end":{"line_number":135,"utf16_col":0}}},{"name":"Preferences and Requirements","kind":"section_3","ident_start":4877,"ident_end":4905,"extent_start":4873,"extent_end":6077,"fully_qualified_name":"Preferences and Requirements","ident_utf16":{"start":{"line_number":135,"utf16_col":4},"end":{"line_number":135,"utf16_col":32}},"extent_utf16":{"start":{"line_number":135,"utf16_col":0},"end":{"line_number":148,"utf16_col":0}}},{"name":"Scope","kind":"section_3","ident_start":6081,"ident_end":6086,"extent_start":6077,"extent_end":6399,"fully_qualified_name":"Scope","ident_utf16":{"start":{"line_number":148,"utf16_col":4},"end":{"line_number":148,"utf16_col":9}},"extent_utf16":{"start":{"line_number":148,"utf16_col":0},"end":{"line_number":160,"utf16_col":0}}},{"name":"Locale","kind":"section_3","ident_start":6403,"ident_end":6409,"extent_start":6399,"extent_end":6683,"fully_qualified_name":"Locale","ident_utf16":{"start":{"line_number":160,"utf16_col":4},"end":{"line_number":160,"utf16_col":10}},"extent_utf16":{"start":{"line_number":160,"utf16_col":0},"end":{"line_number":172,"utf16_col":0}}},{"name":"Architectures","kind":"section_3","ident_start":6687,"ident_end":6700,"extent_start":6683,"extent_end":7047,"fully_qualified_name":"Architectures","ident_utf16":{"start":{"line_number":172,"utf16_col":4},"end":{"line_number":172,"utf16_col":17}},"extent_utf16":{"start":{"line_number":172,"utf16_col":0},"end":{"line_number":184,"utf16_col":0}}},{"name":"Installer Types","kind":"section_3","ident_start":7051,"ident_end":7066,"extent_start":7047,"extent_end":8171,"fully_qualified_name":"Installer Types","ident_utf16":{"start":{"line_number":184,"utf16_col":4},"end":{"line_number":184,"utf16_col":19}},"extent_utf16":{"start":{"line_number":184,"utf16_col":0},"end":{"line_number":203,"utf16_col":0}}},{"name":"Default install root","kind":"section_3","ident_start":8175,"ident_end":8195,"extent_start":8171,"extent_end":8590,"fully_qualified_name":"Default install root","ident_utf16":{"start":{"line_number":203,"utf16_col":4},"end":{"line_number":203,"utf16_col":24}},"extent_utf16":{"start":{"line_number":203,"utf16_col":0},"end":{"line_number":213,"utf16_col":0}}},{"name":"Maximum resumes","kind":"section_3","ident_start":8594,"ident_end":8609,"extent_start":8590,"extent_end":8882,"fully_qualified_name":"Maximum resumes","ident_utf16":{"start":{"line_number":213,"utf16_col":4},"end":{"line_number":213,"utf16_col":19}},"extent_utf16":{"start":{"line_number":213,"utf16_col":0},"end":{"line_number":225,"utf16_col":0}}},{"name":"Uninstall Behavior","kind":"section_2","ident_start":8885,"ident_end":8903,"extent_start":8882,"extent_end":9458,"fully_qualified_name":"Uninstall Behavior","ident_utf16":{"start":{"line_number":225,"utf16_col":3},"end":{"line_number":225,"utf16_col":21}},"extent_utf16":{"start":{"line_number":225,"utf16_col":0},"end":{"line_number":239,"utf16_col":0}}},{"name":"Purge Portable Package","kind":"section_3","ident_start":9016,"ident_end":9038,"extent_start":9012,"extent_end":9458,"fully_qualified_name":"Purge Portable Package","ident_utf16":{"start":{"line_number":229,"utf16_col":4},"end":{"line_number":229,"utf16_col":26}},"extent_utf16":{"start":{"line_number":229,"utf16_col":0},"end":{"line_number":239,"utf16_col":0}}},{"name":"Configure Behavior","kind":"section_2","ident_start":9461,"ident_end":9479,"extent_start":9458,"extent_end":9959,"fully_qualified_name":"Configure Behavior","ident_utf16":{"start":{"line_number":239,"utf16_col":3},"end":{"line_number":239,"utf16_col":21}},"extent_utf16":{"start":{"line_number":239,"utf16_col":0},"end":{"line_number":255,"utf16_col":0}}},{"name":"Default Module Root","kind":"section_3","ident_start":9576,"ident_end":9595,"extent_start":9572,"extent_end":9959,"fully_qualified_name":"Default Module Root","ident_utf16":{"start":{"line_number":243,"utf16_col":4},"end":{"line_number":243,"utf16_col":23}},"extent_utf16":{"start":{"line_number":243,"utf16_col":0},"end":{"line_number":255,"utf16_col":0}}},{"name":"Download Behavior","kind":"section_2","ident_start":9962,"ident_end":9979,"extent_start":9959,"extent_end":10443,"fully_qualified_name":"Download Behavior","ident_utf16":{"start":{"line_number":255,"utf16_col":3},"end":{"line_number":255,"utf16_col":20}},"extent_utf16":{"start":{"line_number":255,"utf16_col":0},"end":{"line_number":271,"utf16_col":0}}},{"name":"Default Download Directory","kind":"section_3","ident_start":10071,"ident_end":10097,"extent_start":10067,"extent_end":10443,"fully_qualified_name":"Default Download Directory","ident_utf16":{"start":{"line_number":259,"utf16_col":4},"end":{"line_number":259,"utf16_col":30}},"extent_utf16":{"start":{"line_number":259,"utf16_col":0},"end":{"line_number":271,"utf16_col":0}}},{"name":"Telemetry","kind":"section_2","ident_start":10446,"ident_end":10455,"extent_start":10443,"extent_end":10884,"fully_qualified_name":"Telemetry","ident_utf16":{"start":{"line_number":271,"utf16_col":3},"end":{"line_number":271,"utf16_col":12}},"extent_utf16":{"start":{"line_number":271,"utf16_col":0},"end":{"line_number":287,"utf16_col":0}}},{"name":"disable","kind":"section_3","ident_start":10705,"ident_end":10712,"extent_start":10701,"extent_end":10884,"fully_qualified_name":"disable","ident_utf16":{"start":{"line_number":277,"utf16_col":4},"end":{"line_number":277,"utf16_col":11}},"extent_utf16":{"start":{"line_number":277,"utf16_col":0},"end":{"line_number":287,"utf16_col":0}}},{"name":"Logging","kind":"section_2","ident_start":10887,"ident_end":10894,"extent_start":10884,"extent_end":14032,"fully_qualified_name":"Logging","ident_utf16":{"start":{"line_number":287,"utf16_col":3},"end":{"line_number":287,"utf16_col":10}},"extent_utf16":{"start":{"line_number":287,"utf16_col":0},"end":{"line_number":357,"utf16_col":0}}},{"name":"level","kind":"section_3","ident_start":10966,"ident_end":10971,"extent_start":10962,"extent_end":11215,"fully_qualified_name":"level","ident_utf16":{"start":{"line_number":291,"utf16_col":4},"end":{"line_number":291,"utf16_col":9}},"extent_utf16":{"start":{"line_number":291,"utf16_col":0},"end":{"line_number":302,"utf16_col":0}}},{"name":"channels","kind":"section_3","ident_start":11219,"ident_end":11227,"extent_start":11215,"extent_end":11867,"fully_qualified_name":"channels","ident_utf16":{"start":{"line_number":302,"utf16_col":4},"end":{"line_number":302,"utf16_col":12}},"extent_utf16":{"start":{"line_number":302,"utf16_col":0},"end":{"line_number":318,"utf16_col":0}}},{"name":"fileNameStrategy","kind":"section_3","ident_start":11871,"ident_end":11887,"extent_start":11867,"extent_end":12293,"fully_qualified_name":"fileNameStrategy","ident_utf16":{"start":{"line_number":318,"utf16_col":4},"end":{"line_number":318,"utf16_col":20}},"extent_utf16":{"start":{"line_number":318,"utf16_col":0},"end":{"line_number":328,"utf16_col":0}}},{"name":"file","kind":"section_3","ident_start":12297,"ident_end":12301,"extent_start":12293,"extent_end":14032,"fully_qualified_name":"file","ident_utf16":{"start":{"line_number":328,"utf16_col":4},"end":{"line_number":328,"utf16_col":8}},"extent_utf16":{"start":{"line_number":328,"utf16_col":0},"end":{"line_number":357,"utf16_col":0}}},{"name":"Network","kind":"section_2","ident_start":14035,"ident_end":14042,"extent_start":14032,"extent_end":14877,"fully_qualified_name":"Network","ident_utf16":{"start":{"line_number":357,"utf16_col":3},"end":{"line_number":357,"utf16_col":10}},"extent_utf16":{"start":{"line_number":357,"utf16_col":0},"end":{"line_number":376,"utf16_col":0}}},{"name":"Downloader","kind":"section_3","ident_start":14145,"ident_end":14155,"extent_start":14141,"extent_end":14877,"fully_qualified_name":"Downloader","ident_utf16":{"start":{"line_number":361,"utf16_col":4},"end":{"line_number":361,"utf16_col":14}},"extent_utf16":{"start":{"line_number":361,"utf16_col":0},"end":{"line_number":376,"utf16_col":0}}},{"name":"Interactivity","kind":"section_2","ident_start":14880,"ident_end":14893,"extent_start":14877,"extent_end":15289,"fully_qualified_name":"Interactivity","ident_utf16":{"start":{"line_number":376,"utf16_col":3},"end":{"line_number":376,"utf16_col":16}},"extent_utf16":{"start":{"line_number":376,"utf16_col":0},"end":{"line_number":390,"utf16_col":0}}},{"name":"disable","kind":"section_3","ident_start":15106,"ident_end":15113,"extent_start":15102,"extent_end":15289,"fully_qualified_name":"disable","ident_utf16":{"start":{"line_number":380,"utf16_col":4},"end":{"line_number":380,"utf16_col":11}},"extent_utf16":{"start":{"line_number":380,"utf16_col":0},"end":{"line_number":390,"utf16_col":0}}},{"name":"Experimental Features","kind":"section_2","ident_start":15292,"ident_end":15313,"extent_start":15289,"extent_end":17097,"fully_qualified_name":"Experimental Features","ident_utf16":{"start":{"line_number":390,"utf16_col":3},"end":{"line_number":390,"utf16_col":24}},"extent_utf16":{"start":{"line_number":390,"utf16_col":0},"end":{"line_number":447,"utf16_col":0}}},{"name":"directMSI","kind":"section_3","ident_start":15764,"ident_end":15773,"extent_start":15760,"extent_end":16169,"fully_qualified_name":"directMSI","ident_utf16":{"start":{"line_number":403,"utf16_col":4},"end":{"line_number":403,"utf16_col":13}},"extent_utf16":{"start":{"line_number":403,"utf16_col":0},"end":{"line_number":415,"utf16_col":0}}},{"name":"resume","kind":"section_3","ident_start":16173,"ident_end":16179,"extent_start":16169,"extent_end":16353,"fully_qualified_name":"resume","ident_utf16":{"start":{"line_number":415,"utf16_col":4},"end":{"line_number":415,"utf16_col":10}},"extent_utf16":{"start":{"line_number":415,"utf16_col":0},"end":{"line_number":426,"utf16_col":0}}},{"name":"fonts","kind":"section_3","ident_start":16357,"ident_end":16362,"extent_start":16353,"extent_end":16600,"fully_qualified_name":"fonts","ident_utf16":{"start":{"line_number":426,"utf16_col":4},"end":{"line_number":426,"utf16_col":9}},"extent_utf16":{"start":{"line_number":426,"utf16_col":0},"end":{"line_number":436,"utf16_col":0}}},{"name":"sourcePriority","kind":"section_3","ident_start":16604,"ident_end":16618,"extent_start":16600,"extent_end":17097,"fully_qualified_name":"sourcePriority","ident_utf16":{"start":{"line_number":436,"utf16_col":4},"end":{"line_number":436,"utf16_col":18}},"extent_utf16":{"start":{"line_number":436,"utf16_col":0},"end":{"line_number":447,"utf16_col":0}}}]}},"codeViewLayoutRoute":{"repo":{"id":197275130,"defaultBranch":"master","name":"winget-cli","ownerLogin":"microsoft","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2019-07-16T22:16:49.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/6154722?v=4","public":true,"private":false,"isOrgOwned":true},"currentUser":null,"uploadToken":"GqoZjclNrPJrFXZPbQ7PZLMeYwg6YRAc_R-6O4OnbvY5zMsF-LXKuclV9qvZ5fPvvPNVvzj9etCU2l1ytDoKkg","allShortcutsEnabled":false,"treeExpanded":true,"path":"doc/Settings.md","symbolsExpanded":false,"refInfo":{"name":"master","listCacheKey":"v0:1780342465.0","canEdit":false,"currentOid":"2f4f2cf16806debffc6c9d7e724b5c900f455a4f"},"helpUrl":"https://docs.github.com","findFileWorkerPath":"/assets-cdn/worker/find-file-worker-fcacb4fa59227001.js","findInFileWorkerPath":"/assets-cdn/worker/find-in-file-worker-94741d92665be784.js","githubDevUrl":null},"codeViewFileTreeLayoutRoute":{"fileTree":{"doc":{"items":[{"name":"admx","path":"doc/admx","contentType":"directory"},{"name":"specs","path":"doc/specs","contentType":"directory"},{"name":"troubleshooting","path":"doc/troubleshooting","contentType":"directory"},{"name":"windows","path":"doc/windows","contentType":"directory"},{"name":"Completion.md","path":"doc/Completion.md","contentType":"file"},{"name":"Developing.md","path":"doc/Developing.md","contentType":"file"},{"name":"ReleaseNotes.md","path":"doc/ReleaseNotes.md","contentType":"file"},{"name":"Settings.md","path":"doc/Settings.md","contentType":"file"},{"name":"windows-package-manager-release-roadmap.md","path":"doc/windows-package-manager-release-roadmap.md","contentType":"file"}],"totalCount":9},"":{"items":[{"name":".config","path":".config","contentType":"directory"},{"name":".github","path":".github","contentType":"directory"},{"name":"Localization","path":"Localization","contentType":"directory"},{"name":"doc","path":"doc","contentType":"directory"},{"name":"samples","path":"samples","contentType":"directory"},{"name":"schemas","path":"schemas","contentType":"directory"},{"name":"src","path":"src","contentType":"directory"},{"name":"templates","path":"templates","contentType":"directory"},{"name":"tools","path":"tools","contentType":"directory"},{"name":".editorconfig","path":".editorconfig","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".vsconfig","path":".vsconfig","contentType":"file"},{"name":"CODEOWNERS","path":"CODEOWNERS","contentType":"file"},{"name":"CODE_OF_CONDUCT.md","path":"CODE_OF_CONDUCT.md","contentType":"file"},{"name":"CONTRIBUTING.md","path":"CONTRIBUTING.md","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"NOTICE","path":"NOTICE","contentType":"file"},{"name":"PRIVACY.md","path":"PRIVACY.md","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"SECURITY.md","path":"SECURITY.md","contentType":"file"},{"name":"SUPPORT.md","path":"SUPPORT.md","contentType":"file"},{"name":"azure-pipelines.loc.yml","path":"azure-pipelines.loc.yml","contentType":"file"},{"name":"azure-pipelines.yml","path":"azure-pipelines.yml","contentType":"file"},{"name":"cgmanifest.json","path":"cgmanifest.json","contentType":"file"}],"totalCount":24}},"fileTreeProcessingTime":79.319722,"foldersToFetch":[]},"codeViewBlobLayoutRoute":{"codeLineWrapEnabled":false,"refInfo":{"name":"master","listCacheKey":"v0:1780342465.0","canEdit":false,"refType":"branch","currentOid":"2f4f2cf16806debffc6c9d7e724b5c900f455a4f","canEditOnDefaultBranch":false,"fileExistsOnDefault":true},"path":"doc/Settings.md","blob":{"copilotSWEAgentEnabled":false,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/microsoft/winget-cli/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"Settings.md","displayUrl":"https://github.com/microsoft/winget-cli/blob/master/doc/Settings.md?raw=true","headerInfo":{"blobSize":"16.7 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"0dfe03b","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fwinget-cli%2Fblob%2Fmaster%2Fdoc%2FSettings.md","isCSV":false,"isRichtext":true,"lineInfo":{"truncatedLoc":"447","truncatedSloc":"307"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"isIssueTemplate":false,"isDiscussionTemplate":false,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/microsoft/winget-cli/blob/master/doc/Settings.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/microsoft/winget-cli/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/microsoft/winget-cli/raw/refs/heads/master/doc/Settings.md","renderImageOrRaw":false,"shortPath":null,"symbolsEnabled":true,"tabSize":4,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null},"copilotInfo":null,"copilotAccessAllowed":false,"copilotSpacesEnabled":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":true,"isMarketplaceEnabled":true},"codeViewBlobLayoutRoute.StyledBlob":{"rawLines":["# WinGet CLI Settings","","You can configure WinGet by editing the `settings.json` file. Running `winget settings` will open the file in the default json editor; if no editor is configured, Windows will prompt for you to select an editor, and Notepad is a sensible option if you have no other preference.","","## File Location","","Settings file is located in %LOCALAPPDATA%\\Packages\\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\\LocalState\\settings.json","","If you are using the non-packaged WinGet version by building it from source code, the file will be located under %LOCALAPPDATA%\\Microsoft\\WinGet\\Settings\\settings.json","","If you are creating a settings file from scratch, make sure that the line `\"$schema\": \"https://aka.ms/winget-settings.schema.json\",` is in it.","","## Source","","The `source` settings involve configuration to the WinGet source.","","```json"," \"source\": {"," \"autoUpdateIntervalInMinutes\": 3"," },","```","","### autoUpdateIntervalInMinutes","","A positive integer represents the update interval in minutes. The check for updates only happens when a source is used. A zero will disable the check for updates to a source. Any other values are invalid.","","- Disable: 0","- Default: 15","","To manually update the source use `winget source update`","","## Visual","","The `visual` settings involve visual elements that are displayed by WinGet","","### progressBar","","Style of the progress spinner and bar that WinGet displays when not specified by arguments. In addition, all options except `disabled` send [Virtual Terminal progress](https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC) updates that any supporting terminal may display visually.","","\u003e [!NOTE]","\u003e You can also disable progress output for a single command using the `--no-progress` flag, which takes precedence over this setting.","","|Value|Description|Release|","|---|---|---|","|`accent` (default)|Use the [Windows Accent color](https://support.microsoft.com/en-us/windows/change-colors-in-windows-d26ef4d6-819a-581c-1581-493cfcc005fe)|1.0|","|`retro`|Use the current foreground terminal color|1.0|","|`rainbow`|Progress through a rainbow of colors|1.0|","|`sixel`|Use sixel images; requires a terminal that supports displaying sixels, such as [Windows Terminal](https://github.com/microsoft/terminal/releases) 1.22.2362 or later|1.9|","|`disabled`|No progress will be displayed|1.9|","","```json"," \"visual\": {"," \"progressBar\": \"accent\""," },","```","","### anonymizeDisplayedPaths","","Replaces some known folder paths with their respective environment variable. Defaults to true.","","```json"," \"visual\": {"," \"anonymizeDisplayedPaths\": true"," },","```","","### enableSixels","","Enables output of sixel images in certain contexts. Defaults to false.","","```json"," \"visual\": {"," \"enableSixels\": true"," },","```","","## Install Behavior","","The `installBehavior` settings affect the default behavior of installing and upgrading (where applicable) packages.","","### Disable Install Notes","","The `disableInstallNotes` behavior affects whether installation notes are shown after a successful install. Defaults to `false` if value is not set or is invalid.","","```json"," \"installBehavior\": {"," \"disableInstallNotes\": true"," },","```","","### Portable Package User Root","","The `portablePackageUserRoot` setting affects the default root directory where packages are installed to under `User` scope. This setting only applies to packages with the `portable` installer type. Defaults to `%LOCALAPPDATA%/Microsoft/WinGet/Packages/` if value is not set or is invalid.","","\u003e Note: This setting value must be an absolute path.","","```json"," \"installBehavior\": {"," \"portablePackageUserRoot\": \"C:/Users/FooBar/Packages\""," },","```","","### Portable Package Machine Root","","The `portablePackageMachineRoot` setting affects the default root directory where packages are installed to under `Machine` scope. This setting only applies to packages with the `portable` installer type. Defaults to `%PROGRAMFILES%/WinGet/Packages/` if value is not set or is invalid.","","\u003e Note: This setting value must be an absolute path.","","```json"," \"installBehavior\": {"," \"portablePackageMachineRoot\": \"C:/Program Files/Packages/Portable\""," },","```","","### Skip Dependencies","","The 'skipDependencies' behavior affects whether dependencies are installed for a given package. Defaults to 'false' if value is not set or is invalid.","","```json"," \"installBehavior\": {"," \"skipDependencies\": true"," },","```","","### Archive Extraction Method","","The `archiveExtractionMethod` behavior affects how installer archives are extracted. Currently there are two supported values: `Tar` or `ShellApi`.","`Tar` indicates that the archive should be extracted using the tar executable ('tar.exe') while `shellApi` indicates using the Windows Shell API. Defaults to `shellApi` if value is not set or is invalid.","","```json"," \"installBehavior\": {"," \"archiveExtractionMethod\": \"tar\" | \"shellApi\""," },","```","","### Preferences and Requirements","","Some of the settings are duplicated under `preferences` and `requirements`. `preferences` affect how the various available options are sorted when choosing the one to act on. For instance, the default scope of package installs is for the current user, but if that is not an option then a machine level installer will be chosen. `requirements` filter the options, potentially resulting in an empty list and a failure to install. In the previous example, a user scope requirement would result in no applicable installers and an error.","","When multiple values are listed under `requirements`, they are treated as an ordered preference in addition to a filter — the first listed value is preferred over subsequent ones when multiple valid options exist. If both `requirements` and `preferences` are set for the same field, the ordering from `preferences` takes precedence.","","Any arguments passed on the command line will effectively override the matching `requirement` setting for the duration of that command.","","\u003e [!NOTE]","\u003e","\u003e - These settings are only applied for the `winget install` command.","\u003e - Other commands like `winget configure` are not affected by these settings.","","### Scope","","The `scope` behavior affects the choice between installing a package for the current user or for the entire machine. The matching parameter is `--scope`, and uses the same values (`user` or `machine`).","","```json"," \"installBehavior\": {"," \"preferences\": {"," \"scope\": \"user\""," }"," },","```","","### Locale","","The `locale` behavior affects the choice of installer based on installer locale. The matching parameter is `--locale`, and uses bcp47 language tag.","","```json"," \"installBehavior\": {"," \"preferences\": {"," \"locale\": [ \"en-US\", \"fr-FR\" ]"," }"," },","```","","### Architectures","","The `architectures` behavior affects what architectures will be selected when installing a package. The matching parameter is `--architecture`. Note that only architectures compatible with your system can be selected.","","```json"," \"installBehavior\": {"," \"preferences\": {"," \"architectures\": [\"x64\", \"arm64\"]"," }"," },","```","","### Installer Types","","The `installerTypes` behavior affects what installer types will be selected when installing a package. It can also determine which type to install by default if a manifest has multiple types: The list is in priority order, with the first listed type being preferred over the others, and so on. This is convenient for users who for instance prefer portable packages or MSIX/AppX installations. The matching parameter is `--installer-type`, which will override the settings.","","Allowed values as of version 1.12.470 include: `appx`, `burn`, `exe`, `font`, `inno`, `msi`, `msix`, `msstore`, `nullsoft`, `portable`, `wix`, `zip`","","By default, when no user preference or requirement is configured, WinGet selects installer types in the following order: MSIX, MSI/Wix/Burn, Nullsoft/Inno/EXE, Portable. If it is already installed, the same installer type will be required to ensure a proper upgrade.","","```json"," \"installBehavior\": {"," \"preferences\": {"," \"installerTypes\": [\"msi\", \"msix\"]"," },"," \"requirements\": {"," \"installerTypes\": [\"msix\", \"msi\"]"," }"," },","```","","### Default install root","","The `defaultInstallRoot` affects the install location when a package requires one. This can be overridden by the `--location` parameter. This setting is only used when a package manifest includes `InstallLocationRequired`, and the actual location is obtained by appending the package ID to the root.","","```json"," \"installBehavior\": {"," \"defaultInstallRoot\": \"C:/installRoot\""," },","```","","### Maximum resumes","","The `maxResumes` setting determines the maximum number of times that a command may be resumed automatically. The default value is 3.","","```json"," \"installBehavior\": {"," \"maxResumes\": 3"," },","```","","\u003e Note: [The resume behavior is an experimental feature.](#resume)","","## Uninstall Behavior","","The `uninstallBehavior` settings affect the default behavior of uninstalling (where applicable) packages.","","### Purge Portable Package","","The `purgePortablePackage` behavior affects the default behavior for uninstalling a portable package. If set to `true`, uninstall will remove all files and directories relevant to the `portable` package. This setting only applies to packages with the `portable` installer type. Defaults to `false` if value is not set or is invalid.","","```json"," \"uninstallBehavior\": {"," \"purgePortablePackage\": true"," },","```","","## Configure Behavior","","The `configureBehavior` settings affect the default behavior of applying a configuration.","","### Default Module Root","","The `defaultModuleRoot` behavior affects the default root directory where modules are installed to. Defaults to `%LOCALAPPDATA%/Microsoft/WinGet/Configuration/Modules` if value is not set or is invalid.","","\u003e Note: This setting value must be an absolute path.","","```json"," \"configureBehavior\": {"," \"defaultModuleRoot\": \"C:/Program Files/Modules/\""," },","```","","## Download Behavior","","The `downloadBehavior` settings affect the default behavior of downloading packages.","","### Default Download Directory","","The `defaultDownloadDirectory` setting affects the default directory where installers are downloaded to. Defaults to `%USERPROFILE%/Downloads/` if value is not set or is invalid.","","\u003e Note: This setting value must be an absolute path.","","```json"," \"downloadBehavior\": {"," \"defaultDownloadDirectory\": \"C:/Users/FooBar/Downloads\""," },","```","","## Telemetry","","The `telemetry` settings control whether winget writes ETW events that may be sent to Microsoft on a default installation of Windows.","","See [details on telemetry](../README.md#datatelemetry), and our [primary privacy statement](../PRIVACY.md).","","### disable","","```json"," \"telemetry\": {"," \"disable\": true"," },","```","","If set to true, the `telemetry.disable` setting will prevent any event from being written by the program.","","## Logging","","The `logging` settings control the level of detail in log files.","","### level",""," `--verbose-logs` will override this setting and always creates a verbose log.","Defaults to `info` if value is not set or is invalid.","","```json"," \"logging\": {"," \"level\": \"verbose\" | \"info\" | \"warning\" | \"error\" | \"critical\""," },","```","","### channels","","The valid values in this array are defined in the function `GetChannelFromName` in the [logging code](../src/AppInstallerSharedLib/AppInstallerLogging.cpp). These align with the ***channel identifier*** found in the log files. For example, ***`CORE`*** in:","","```plaintext","2023-12-06 19:17:07.988 [CORE] WinGet, version [1.7.0-preview], activity [{24A91EA8-46BE-47A1-B65C-CEBCE90B8675}]","```","","In addition, there are special values that cover multiple channels. `default` is the default set of channels, while `all` is all of the channels. Invalid values are ignored.","","```json"," \"logging\": {"," \"channels\": [\"default\"]"," },","```","","### fileNameStrategy","","Sets the default strategy for naming log files for installers that support it. `manifest` is the default and uses the manifest name. `timestamp` uses the date and time. `guid` uses a generated GUID. `shortguid` uses the first 8 characters of a generated GUID. Invalid values will revert to `manifest`.","","```json","\t\"logging\": {","\t\t\"fileNameStrategy\": \"manifest\" | \"timestamp\" | \"guid\" | \"shortguid\"","\t},","```","","### file","","The `file` settings control the log files generated by winget during operation. These settings apply to the automatic cleanup that happens whenever a Windows Package Manager process is run.","They only apply to the default log location, which contains winget logs, AppInstaller logs (the MSIX install UI), and is the default location where installer logs are placed.","The automatic cleanup happens at the beginning of the process, so the log file(s) generated by the current process will not be considered in the limits.","","|Setting|Description|Default|Note|","|---|---|---|---|","|`ageLimitInDays`|The maximum age, in days, of files in the log directory; older files are deleted.|7 (days)|Set to 0 to disable this limit.|","|`totalSizeLimitInMB`|The maximum size, in megabytes, of all files in the log directory; the oldest files are deleted first.|128 (MB)|Set to 0 to disable this limit.|","|`countLimit`|The maximum number of files in the log directory; the oldest files are deleted first.|0|Set to 0 (the default) to disable this limit.|","","These settings apply to the log files that winget writes, only as they are being written. They do not apply to files written by installers or the AppInstaller UI.","","|Setting|Description|Default|Note|","|---|---|---|---|","|`individualSizeLimitInMB`|The maximum size, in megabytes, of an individual log file. If a file would exceed this limit, the logs will wrap. Note that this limit is approximate and the actual files may exceed it by a few bytes.|16 (MB)|Set to 0 to disable this limit.|","","```json"," \"logging\": {"," \"file\": {"," \"ageLimitInDays\": 7,"," \"totalSizeLimitInMB\": 128,"," \"countLimit\": 0,"," \"individualSizeLimitInMB\": 16,"," }"," },","```","","## Network","","The `network` settings influence how winget uses the network to retrieve packages and metadata.","","### Downloader","","The `downloader` setting controls which code is used when downloading packages. The default is `default`, which may be any of the options based on our determination.","`wininet` uses the [WinINet](https://docs.microsoft.com/windows/win32/wininet/about-wininet) APIs, while `do` uses the","[Delivery Optimization](https://support.microsoft.com/windows/delivery-optimization-in-windows-10-0656e53c-15f2-90de-a87a-a2172c94cf6d) service.","","The `doProgressTimeoutInSeconds` setting updates the number of seconds to wait without progress before fallback. The default number of seconds is 60, minimum is 1 and the maximum is 600.","","```json"," \"network\": {"," \"downloader\": \"do\","," \"doProgressTimeoutInSeconds\": 60"," }","```","","## Interactivity","","The `interactivity` settings control whether winget may show interactive prompts during execution. Note that this refers only to prompts shown by winget itself and not to those shown by package installers.","","### disable","","```json"," \"interactivity\": {"," \"disable\": true"," },","```","","If set to true, the `interactivity.disable` setting will prevent any interactive prompt from being shown.","","## Experimental Features","","To allow work to be done and distributed to early adopters for feedback, settings can be used to enable \"experimental\" features.","","The `experimentalFeatures` settings involve the configuration of these \"experimental\" features. Individual features can be enabled under this node. The example below shows sample experimental features.","","```json"," \"experimentalFeatures\": {"," \"experimentalCmd\": true,"," \"experimentalArg\": false"," },","```","","### directMSI","","This feature enables the Windows Package Manager to directly install MSI packages with the MSI APIs rather than through msiexec.","Note that when silent installation is used this is already in affect, as MSI packages that require elevation will fail in that scenario without it.","You can enable the feature as shown below.","","```json"," \"experimentalFeatures\": {"," \"directMSI\": true"," },","```","","### resume","","This feature enables support for some commands to resume.","You can enable the feature as shown below.","","```json"," \"experimentalFeatures\": {"," \"resume\": true"," },","```","","### fonts","","This feature enables support for fonts via `winget settings`. The `winget font list` command will list installed font families and the number of installed font faces.","","```json"," \"experimentalFeatures\": {"," \"fonts\": true"," },","```","","### sourcePriority","","This feature enables sources to have a priority value assigned. Sources with a higher priority will appear earlier in search results and will be selected for installing new packages when multiple sources have a matching package.","","Note that search result ordering is dependent on several factors, and source priority is the lowest field in that currently (match quality and field are more important).","","```json"," \"experimentalFeatures\": {"," \"sourcePriority\": true"," },","```"],"stylingDirectives":[[[0,21,"pl-mh"],[2,21,"pl-en"]],[],[[40,41,"pl-s"],[41,54,"pl-c1"],[54,55,"pl-s"],[70,71,"pl-s"],[71,86,"pl-c1"],[86,87,"pl-s"]],[],[[0,16,"pl-mh"],[3,16,"pl-en"]],[],[],[],[],[],[[74,75,"pl-s"],[75,131,"pl-c1"],[131,132,"pl-s"]],[],[[0,9,"pl-mh"],[3,9,"pl-en"]],[],[[4,5,"pl-s"],[5,11,"pl-c1"],[11,12,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,12,"pl-ent"]],[[8,37,"pl-ent"],[39,40,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,31,"pl-mh"],[4,31,"pl-en"]],[],[],[],[[0,1,"pl-v"]],[[0,1,"pl-v"]],[],[[34,35,"pl-s"],[35,55,"pl-c1"],[55,56,"pl-s"]],[],[[0,9,"pl-mh"],[3,9,"pl-en"]],[],[[4,5,"pl-s"],[5,11,"pl-c1"],[11,12,"pl-s"]],[],[[0,15,"pl-mh"],[4,15,"pl-en"]],[],[[124,125,"pl-s"],[125,133,"pl-c1"],[133,134,"pl-s"],[140,141,"pl-s"],[166,167,"pl-s"],[167,168,"pl-s"],[168,236,"pl-corl"],[236,237,"pl-s"]],[],[[0,9,"pl-ent"],[0,2,"pl-ent"],[2,3,"pl-s"],[8,9,"pl-s"]],[[0,133,"pl-ent"],[0,2,"pl-ent"],[70,71,"pl-s"],[71,84,"pl-c1"],[84,85,"pl-s"]],[[0,0,"pl-ent"]],[[0,1,"pl-ml"],[6,7,"pl-ml"],[18,19,"pl-ml"],[26,27,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[8,9,"pl-ml"],[12,13,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,8,"pl-c1"],[8,9,"pl-s"],[19,20,"pl-ml"],[28,29,"pl-s"],[49,50,"pl-s"],[50,51,"pl-s"],[51,156,"pl-corl"],[156,157,"pl-s"],[157,158,"pl-ml"],[161,162,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,7,"pl-c1"],[7,8,"pl-s"],[8,9,"pl-ml"],[50,51,"pl-ml"],[54,55,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,9,"pl-c1"],[9,10,"pl-s"],[10,11,"pl-ml"],[47,48,"pl-ml"],[51,52,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,7,"pl-c1"],[7,8,"pl-s"],[8,9,"pl-ml"],[88,89,"pl-s"],[105,106,"pl-s"],[106,107,"pl-s"],[107,153,"pl-corl"],[153,154,"pl-s"],[173,174,"pl-ml"],[177,178,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,10,"pl-c1"],[10,11,"pl-s"],[11,12,"pl-ml"],[41,42,"pl-ml"],[45,46,"pl-ml"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,12,"pl-ent"]],[[8,21,"pl-ent"],[23,31,"pl-s"],[23,24,"pl-pds"],[30,31,"pl-pds"]],[],[[0,3,"pl-s"]],[],[[0,27,"pl-mh"],[4,27,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,12,"pl-ent"]],[[8,33,"pl-ent"],[35,39,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,16,"pl-mh"],[4,16,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,12,"pl-ent"]],[[8,22,"pl-ent"],[24,28,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,19,"pl-mh"],[3,19,"pl-en"]],[],[[4,5,"pl-s"],[5,20,"pl-c1"],[20,21,"pl-s"]],[],[[0,25,"pl-mh"],[4,25,"pl-en"]],[],[[4,5,"pl-s"],[5,24,"pl-c1"],[24,25,"pl-s"],[120,121,"pl-s"],[121,126,"pl-c1"],[126,127,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,29,"pl-ent"],[31,35,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,30,"pl-mh"],[4,30,"pl-en"]],[],[[4,5,"pl-s"],[5,28,"pl-c1"],[28,29,"pl-s"],[111,112,"pl-s"],[112,116,"pl-c1"],[116,117,"pl-s"],[172,173,"pl-s"],[173,181,"pl-c1"],[181,182,"pl-s"],[211,212,"pl-s"],[212,253,"pl-c1"],[253,254,"pl-s"]],[],[[0,52,"pl-ent"],[0,2,"pl-ent"]],[[0,0,"pl-ent"]],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,33,"pl-ent"],[35,61,"pl-s"],[35,36,"pl-pds"],[60,61,"pl-pds"]],[],[[0,3,"pl-s"]],[],[[0,33,"pl-mh"],[4,33,"pl-en"]],[],[[4,5,"pl-s"],[5,31,"pl-c1"],[31,32,"pl-s"],[114,115,"pl-s"],[115,122,"pl-c1"],[122,123,"pl-s"],[178,179,"pl-s"],[179,187,"pl-c1"],[187,188,"pl-s"],[217,218,"pl-s"],[218,249,"pl-c1"],[249,250,"pl-s"]],[],[[0,52,"pl-ent"],[0,2,"pl-ent"]],[[0,0,"pl-ent"]],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,36,"pl-ent"],[38,74,"pl-s"],[38,39,"pl-pds"],[73,74,"pl-pds"]],[],[[0,3,"pl-s"]],[],[[0,21,"pl-mh"],[4,21,"pl-en"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,26,"pl-ent"],[28,32,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,29,"pl-mh"],[4,29,"pl-en"]],[],[[4,5,"pl-s"],[5,28,"pl-c1"],[28,29,"pl-s"],[127,128,"pl-s"],[128,131,"pl-c1"],[131,132,"pl-s"],[136,137,"pl-s"],[137,145,"pl-c1"],[145,146,"pl-s"]],[[0,1,"pl-s"],[1,4,"pl-c1"],[4,5,"pl-s"],[96,97,"pl-s"],[97,105,"pl-c1"],[105,106,"pl-s"],[158,159,"pl-s"],[159,167,"pl-c1"],[167,168,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,33,"pl-ent"],[35,40,"pl-s"],[35,36,"pl-pds"],[39,40,"pl-pds"],[41,53,"pl-ii"]],[],[[0,3,"pl-s"]],[],[[0,32,"pl-mh"],[4,32,"pl-en"]],[],[[42,43,"pl-s"],[43,54,"pl-c1"],[54,55,"pl-s"],[60,61,"pl-s"],[61,73,"pl-c1"],[73,74,"pl-s"],[76,77,"pl-s"],[77,88,"pl-c1"],[88,89,"pl-s"],[329,330,"pl-s"],[330,342,"pl-c1"],[342,343,"pl-s"]],[],[[38,39,"pl-s"],[39,51,"pl-c1"],[51,52,"pl-s"],[222,223,"pl-s"],[223,235,"pl-c1"],[235,236,"pl-s"],[241,242,"pl-s"],[242,253,"pl-c1"],[253,254,"pl-s"],[301,302,"pl-s"],[302,313,"pl-c1"],[313,314,"pl-s"]],[],[[80,81,"pl-s"],[81,92,"pl-c1"],[92,93,"pl-s"]],[],[[0,9,"pl-ent"],[0,2,"pl-ent"],[2,3,"pl-s"],[8,9,"pl-s"]],[[0,1,"pl-ent"],[0,1,"pl-ent"]],[[0,69,"pl-ent"],[0,2,"pl-ent"],[2,3,"pl-v"],[44,45,"pl-s"],[45,59,"pl-c1"],[59,60,"pl-s"]],[[0,78,"pl-ent"],[0,2,"pl-ent"],[2,3,"pl-v"],[24,25,"pl-s"],[25,41,"pl-c1"],[41,42,"pl-s"]],[[0,0,"pl-ent"]],[[0,9,"pl-mh"],[4,9,"pl-en"]],[],[[4,5,"pl-s"],[5,10,"pl-c1"],[10,11,"pl-s"],[143,144,"pl-s"],[144,151,"pl-c1"],[151,152,"pl-s"],[180,181,"pl-s"],[181,185,"pl-c1"],[185,186,"pl-s"],[190,191,"pl-s"],[191,198,"pl-c1"],[198,199,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,21,"pl-ent"]],[[12,19,"pl-ent"],[21,27,"pl-s"],[21,22,"pl-pds"],[26,27,"pl-pds"]],[],[],[[0,3,"pl-s"]],[],[[0,10,"pl-mh"],[4,10,"pl-en"]],[],[[4,5,"pl-s"],[5,11,"pl-c1"],[11,12,"pl-s"],[107,108,"pl-s"],[108,116,"pl-c1"],[116,117,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,21,"pl-ent"]],[[12,20,"pl-ent"],[24,31,"pl-s"],[24,25,"pl-pds"],[30,31,"pl-pds"],[33,40,"pl-s"],[33,34,"pl-pds"],[39,40,"pl-pds"]],[],[],[[0,3,"pl-s"]],[],[[0,17,"pl-mh"],[4,17,"pl-en"]],[],[[4,5,"pl-s"],[5,18,"pl-c1"],[18,19,"pl-s"],[126,127,"pl-s"],[127,141,"pl-c1"],[141,142,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,21,"pl-ent"]],[[12,27,"pl-ent"],[30,35,"pl-s"],[30,31,"pl-pds"],[34,35,"pl-pds"],[37,44,"pl-s"],[37,38,"pl-pds"],[43,44,"pl-pds"]],[],[],[[0,3,"pl-s"]],[],[[0,19,"pl-mh"],[4,19,"pl-en"]],[],[[4,5,"pl-s"],[5,19,"pl-c1"],[19,20,"pl-s"],[420,421,"pl-s"],[421,437,"pl-c1"],[437,438,"pl-s"]],[],[[47,48,"pl-s"],[48,52,"pl-c1"],[52,53,"pl-s"],[55,56,"pl-s"],[56,60,"pl-c1"],[60,61,"pl-s"],[63,64,"pl-s"],[64,67,"pl-c1"],[67,68,"pl-s"],[70,71,"pl-s"],[71,75,"pl-c1"],[75,76,"pl-s"],[78,79,"pl-s"],[79,83,"pl-c1"],[83,84,"pl-s"],[86,87,"pl-s"],[87,90,"pl-c1"],[90,91,"pl-s"],[93,94,"pl-s"],[94,98,"pl-c1"],[98,99,"pl-s"],[101,102,"pl-s"],[102,109,"pl-c1"],[109,110,"pl-s"],[112,113,"pl-s"],[113,121,"pl-c1"],[121,122,"pl-s"],[124,125,"pl-s"],[125,133,"pl-c1"],[133,134,"pl-s"],[136,137,"pl-s"],[137,140,"pl-c1"],[140,141,"pl-s"],[143,144,"pl-s"],[144,147,"pl-c1"],[147,148,"pl-s"]],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,21,"pl-ent"]],[[12,28,"pl-ent"],[31,36,"pl-s"],[31,32,"pl-pds"],[35,36,"pl-pds"],[38,44,"pl-s"],[38,39,"pl-pds"],[43,44,"pl-pds"]],[],[[8,22,"pl-ent"]],[[12,28,"pl-ent"],[31,37,"pl-s"],[31,32,"pl-pds"],[36,37,"pl-pds"],[39,44,"pl-s"],[39,40,"pl-pds"],[43,44,"pl-pds"]],[],[],[[0,3,"pl-s"]],[],[[0,24,"pl-mh"],[4,24,"pl-en"]],[],[[4,5,"pl-s"],[5,23,"pl-c1"],[23,24,"pl-s"],[113,114,"pl-s"],[114,124,"pl-c1"],[124,125,"pl-s"],[196,197,"pl-s"],[197,220,"pl-c1"],[220,221,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,28,"pl-ent"],[30,46,"pl-s"],[30,31,"pl-pds"],[45,46,"pl-pds"]],[],[[0,3,"pl-s"]],[],[[0,19,"pl-mh"],[4,19,"pl-en"]],[],[[4,5,"pl-s"],[5,15,"pl-c1"],[15,16,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,21,"pl-ent"]],[[8,20,"pl-ent"],[22,23,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,66,"pl-ent"],[0,2,"pl-ent"],[8,9,"pl-s"],[56,57,"pl-s"],[57,58,"pl-s"],[58,65,"pl-corl"],[65,66,"pl-s"]],[[0,0,"pl-ent"]],[[0,21,"pl-mh"],[3,21,"pl-en"]],[],[[4,5,"pl-s"],[5,22,"pl-c1"],[22,23,"pl-s"]],[],[[0,26,"pl-mh"],[4,26,"pl-en"]],[],[[4,5,"pl-s"],[5,25,"pl-c1"],[25,26,"pl-s"],[112,113,"pl-s"],[113,117,"pl-c1"],[117,118,"pl-s"],[184,185,"pl-s"],[185,193,"pl-c1"],[193,194,"pl-s"],[251,252,"pl-s"],[252,260,"pl-c1"],[260,261,"pl-s"],[290,291,"pl-s"],[291,296,"pl-c1"],[296,297,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,23,"pl-ent"]],[[8,30,"pl-ent"],[32,36,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,21,"pl-mh"],[3,21,"pl-en"]],[],[[4,5,"pl-s"],[5,22,"pl-c1"],[22,23,"pl-s"]],[],[[0,23,"pl-mh"],[4,23,"pl-en"]],[],[[4,5,"pl-s"],[5,22,"pl-c1"],[22,23,"pl-s"],[112,113,"pl-s"],[113,166,"pl-c1"],[166,167,"pl-s"]],[],[[0,52,"pl-ent"],[0,2,"pl-ent"]],[[0,0,"pl-ent"]],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,23,"pl-ent"]],[[8,27,"pl-ent"],[29,56,"pl-s"],[29,30,"pl-pds"],[55,56,"pl-pds"]],[],[[0,3,"pl-s"]],[],[[0,20,"pl-mh"],[3,20,"pl-en"]],[],[[4,5,"pl-s"],[5,21,"pl-c1"],[21,22,"pl-s"]],[],[[0,30,"pl-mh"],[4,30,"pl-en"]],[],[[4,5,"pl-s"],[5,29,"pl-c1"],[29,30,"pl-s"],[117,118,"pl-s"],[118,142,"pl-c1"],[142,143,"pl-s"]],[],[[0,52,"pl-ent"],[0,2,"pl-ent"]],[[0,0,"pl-ent"]],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,22,"pl-ent"]],[[8,34,"pl-ent"],[36,63,"pl-s"],[36,37,"pl-pds"],[62,63,"pl-pds"]],[],[[0,3,"pl-s"]],[],[[0,12,"pl-mh"],[3,12,"pl-en"]],[],[[4,5,"pl-s"],[5,14,"pl-c1"],[14,15,"pl-s"]],[],[[4,5,"pl-s"],[25,26,"pl-s"],[26,27,"pl-s"],[27,53,"pl-corl"],[53,54,"pl-s"],[64,65,"pl-s"],[90,91,"pl-s"],[91,92,"pl-s"],[92,105,"pl-corl"],[105,106,"pl-s"]],[],[[0,11,"pl-mh"],[4,11,"pl-en"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,15,"pl-ent"]],[[8,17,"pl-ent"],[19,23,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[20,21,"pl-s"],[21,38,"pl-c1"],[38,39,"pl-s"]],[],[[0,10,"pl-mh"],[3,10,"pl-en"]],[],[[4,5,"pl-s"],[5,12,"pl-c1"],[12,13,"pl-s"]],[],[[0,9,"pl-mh"],[4,9,"pl-en"]],[],[[1,2,"pl-s"],[2,16,"pl-c1"],[16,17,"pl-s"]],[[12,13,"pl-s"],[13,17,"pl-c1"],[17,18,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,13,"pl-ent"]],[[8,15,"pl-ent"],[17,26,"pl-s"],[17,18,"pl-pds"],[25,26,"pl-pds"],[27,70,"pl-ii"]],[],[[0,3,"pl-s"]],[],[[0,12,"pl-mh"],[4,12,"pl-en"]],[],[[59,60,"pl-s"],[60,78,"pl-c1"],[78,79,"pl-s"],[87,88,"pl-s"],[100,101,"pl-s"],[101,102,"pl-s"],[102,154,"pl-corl"],[154,155,"pl-s"],[179,182,"pl-s"],[200,203,"pl-s"],[242,245,"pl-s"],[245,246,"pl-s"],[246,250,"pl-c1"],[250,251,"pl-s"],[251,254,"pl-s"]],[],[[0,3,"pl-s"],[3,12,"pl-en"],[12,12,"pl-c1"]],[[0,113,"pl-c1"]],[[0,0,"pl-c1"],[0,3,"pl-s"]],[],[[69,70,"pl-s"],[70,77,"pl-c1"],[77,78,"pl-s"],[117,118,"pl-s"],[118,121,"pl-c1"],[121,122,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,13,"pl-ent"]],[[8,18,"pl-ent"],[21,30,"pl-s"],[21,22,"pl-pds"],[29,30,"pl-pds"]],[],[[0,3,"pl-s"]],[],[[0,20,"pl-mh"],[4,20,"pl-en"]],[],[[79,80,"pl-s"],[80,88,"pl-c1"],[88,89,"pl-s"],[133,134,"pl-s"],[134,143,"pl-c1"],[143,144,"pl-s"],[169,170,"pl-s"],[170,174,"pl-c1"],[174,175,"pl-s"],[199,200,"pl-s"],[200,209,"pl-c1"],[209,210,"pl-s"],[290,291,"pl-s"],[291,299,"pl-c1"],[299,300,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[1,10,"pl-ent"]],[[2,20,"pl-ent"],[22,32,"pl-s"],[22,23,"pl-pds"],[31,32,"pl-pds"],[33,69,"pl-ii"]],[],[[0,3,"pl-s"]],[],[[0,8,"pl-mh"],[4,8,"pl-en"]],[],[[4,5,"pl-s"],[5,9,"pl-c1"],[9,10,"pl-s"]],[],[],[],[[0,1,"pl-ml"],[8,9,"pl-ml"],[20,21,"pl-ml"],[28,29,"pl-ml"],[33,34,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[8,9,"pl-ml"],[12,13,"pl-ml"],[16,17,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,16,"pl-c1"],[16,17,"pl-s"],[17,18,"pl-ml"],[99,100,"pl-ml"],[108,109,"pl-ml"],[140,141,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,20,"pl-c1"],[20,21,"pl-s"],[21,22,"pl-ml"],[124,125,"pl-ml"],[133,134,"pl-ml"],[165,166,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,12,"pl-c1"],[12,13,"pl-s"],[13,14,"pl-ml"],[99,100,"pl-ml"],[101,102,"pl-ml"],[147,148,"pl-ml"]],[],[],[],[[0,1,"pl-ml"],[8,9,"pl-ml"],[20,21,"pl-ml"],[28,29,"pl-ml"],[33,34,"pl-ml"]],[[0,1,"pl-ml"],[4,5,"pl-ml"],[8,9,"pl-ml"],[12,13,"pl-ml"],[16,17,"pl-ml"]],[[0,1,"pl-ml"],[1,2,"pl-s"],[2,25,"pl-c1"],[25,26,"pl-s"],[26,27,"pl-ml"],[227,228,"pl-ml"],[235,236,"pl-ml"],[267,268,"pl-ml"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,13,"pl-ent"]],[[8,14,"pl-ent"]],[[12,28,"pl-ent"],[30,31,"pl-c1"]],[[12,32,"pl-ent"],[34,37,"pl-c1"]],[[12,24,"pl-ent"],[26,27,"pl-c1"]],[[12,37,"pl-ent"],[39,41,"pl-c1"]],[],[],[[0,3,"pl-s"]],[],[[0,10,"pl-mh"],[3,10,"pl-en"]],[],[[4,5,"pl-s"],[5,12,"pl-c1"],[12,13,"pl-s"]],[],[[0,14,"pl-mh"],[4,14,"pl-en"]],[],[[4,5,"pl-s"],[5,15,"pl-c1"],[15,16,"pl-s"],[95,96,"pl-s"],[96,103,"pl-c1"],[103,104,"pl-s"]],[[0,1,"pl-s"],[1,8,"pl-c1"],[8,9,"pl-s"],[19,20,"pl-s"],[27,28,"pl-s"],[28,29,"pl-s"],[29,91,"pl-corl"],[91,92,"pl-s"],[105,106,"pl-s"],[106,108,"pl-c1"],[108,109,"pl-s"]],[[0,1,"pl-s"],[22,23,"pl-s"],[23,24,"pl-s"],[24,134,"pl-corl"],[134,135,"pl-s"]],[],[[4,5,"pl-s"],[5,31,"pl-c1"],[31,32,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[3,12,"pl-ent"]],[[7,19,"pl-ent"],[21,25,"pl-s"],[21,22,"pl-pds"],[24,25,"pl-pds"]],[[7,35,"pl-ent"],[37,39,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,16,"pl-mh"],[3,16,"pl-en"]],[],[[4,5,"pl-s"],[5,18,"pl-c1"],[18,19,"pl-s"]],[],[[0,11,"pl-mh"],[4,11,"pl-en"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[4,19,"pl-ent"]],[[8,17,"pl-ent"],[19,23,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[20,21,"pl-s"],[21,42,"pl-c1"],[42,43,"pl-s"]],[],[[0,24,"pl-mh"],[3,24,"pl-en"]],[],[],[],[[4,5,"pl-s"],[5,25,"pl-c1"],[25,26,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[3,25,"pl-ent"]],[[7,24,"pl-ent"],[26,30,"pl-c1"]],[[7,24,"pl-ent"],[26,31,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,13,"pl-mh"],[4,13,"pl-en"]],[],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[3,25,"pl-ent"]],[[7,18,"pl-ent"],[20,24,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,10,"pl-mh"],[4,10,"pl-en"]],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[3,25,"pl-ent"]],[[7,15,"pl-ent"],[17,21,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,9,"pl-mh"],[4,9,"pl-en"]],[],[[43,44,"pl-s"],[44,59,"pl-c1"],[59,60,"pl-s"],[66,67,"pl-s"],[67,83,"pl-c1"],[83,84,"pl-s"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[2,24,"pl-ent"]],[[8,15,"pl-ent"],[17,21,"pl-c1"]],[],[[0,3,"pl-s"]],[],[[0,18,"pl-mh"],[4,18,"pl-en"]],[],[],[],[],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[2,24,"pl-ent"]],[[8,24,"pl-ent"],[26,30,"pl-c1"]],[],[[0,3,"pl-s"]]],"colorizedLines":null}},"title":"winget-cli/doc/Settings.md at master · microsoft/winget-cli","appPayload":{},"meta":{"title":"winget-cli/doc/Settings.md at master · microsoft/winget-cli"}}</script> + <div data-target="react-app.reactRoot"><meta name="github-code-view-meta-stats" id="github-code-view-meta-stats" data-hydrostats="publish"/> <!-- --> <a hidden="" id="code-view-repo-link" href="/microsoft/winget-cli" data-discover="true"></a> <div class="d-none"></div><div><div style="--spacing:var(--spacing-none)" class="prc-PageLayout-PageLayoutRoot--KH-d"><div class="prc-PageLayout-PageLayoutWrapper-2BhU2" data-width="full"><div class="prc-PageLayout-PageLayoutContent-BneH9"><div class="CodeViewFileTreeLayout-module__sidebar__n_Aau" tabindex="0"><div class="prc-PageLayout-PaneWrapper-pHPop ReposFileTreePane-module__Pane__rBZpI ReposFileTreePane-module__HideTree__AYZnm ReposFileTreePane-module__HidePane__VHAVt" style="--offset-header:0px;--spacing-row:var(--spacing-none);--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="start" data-sticky="true"><div class="prc-PageLayout-HorizontalDivider-JLVqp prc-PageLayout-PaneHorizontalDivider-9tbnE" data-variant-regular="none" data-variant-narrow="none" data-position="start" style="--spacing-divider:var(--spacing-none);--spacing:var(--spacing-none)"></div><div class="prc-PageLayout-Pane-AyzHK" data-resizable="true" style="--spacing:var(--spacing-none);--pane-min-width:256px;--pane-max-width:calc(100vw - var(--pane-max-width-diff));--pane-width-size:var(--pane-width-large);--pane-width:320px"></div><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-PaneVerticalDivider-le57g" data-variant-narrow="none" data-variant-regular="line" data-variant-wide="line" data-position="start" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" role="slider" aria-label="Draggable pane splitter" aria-valuemin="256" aria-valuemax="600" aria-valuenow="320" aria-valuetext="Pane width 320 pixels" tabindex="0"></div></div></div></div><div class="prc-PageLayout-ContentWrapper-gR9eG"><div class="prc-PageLayout-Content-xWL-A" data-width="full" style="--spacing:var(--spacing-none)"><div class="SharedPageLayout-module__content__IwGAp" data-selector="repos-split-pane-content" tabindex="0"> <!-- --> <div class="container CodeViewHeader-module__Box__JkPOb"><div class="CodeViewHeader-module__StickyHeader__Qn7UN" id="StickyHeader"><div class="CodeViewHeader-module__Box_1__SbNDV"><div class="CodeViewHeader-module__Box_2__TB46f"><div class="react-code-view-header-wrap--narrow CodeViewHeader-module__Box_3__q1zUL"><div class="CodeViewHeader-module__treeToggleWrapper__RQ__9"><h2 class="use-tree-pane-module__Heading__s4QbZ prc-Heading-Heading-MtWFE" data-component="Heading"><button data-component="Button" type="button" aria-label="Expand file tree" data-testid="expand-file-tree-button-mobile" class="prc-Button-ButtonBase-9n-Xk ExpandFileTreeButton-module__Button_1__Svs95" data-loading="false" data-size="medium" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-left" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.78 12.53a.75.75 0 0 1-1.06 0L2.47 8.28a.75.75 0 0 1 0-1.06l4.25-4.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L4.81 7h7.44a.75.75 0 0 1 0 1.5H4.81l2.97 2.97a.75.75 0 0 1 0 1.06Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Files</span></span></button><button data-component="IconButton" type="button" data-testid="expand-file-tree-button" aria-controls="repos-file-tree" class="prc-Button-ButtonBase-9n-Xk position-relative ExpandFileTreeButton-module__expandButton__hDOcv ExpandFileTreeButton-module__filesButtonBreakpoint__zEvz3 fgColor-muted prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-labelledby="_R_2aql3al1d_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sidebar-collapse" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z"></path><path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25ZM11 14.5h3.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="se" data-component="Tooltip" aria-hidden="true" id="_R_2aql3al1d_">Expand file tree</span><div class="d-none"></div></h2></div><div class="react-code-view-header-mb--narrow mr-2"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="master branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector-wide"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayHeader__XtXRG"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></div><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP"> <!-- -->master</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="react-code-view-header-mb--narrow CodeViewHeader-module__Box_5__MQ0hL"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__lg__Rjz0A"><nav data-testid="breadcrumbs" aria-labelledby="repos-header-breadcrumb-heading" id="repos-header-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="repos-header-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/microsoft/winget-cli/tree/master" data-discover="true">winget-cli</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/microsoft/winget-cli/tree/master/doc" data-discover="true">doc</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__lg__Rjz0A prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="file-name-id">Settings.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_3qql3al1d_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardButton-module__tooltip__BhMvU prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_3qql3al1d_">Copy path</span></div></div></div><div class="react-code-view-header-element--wide"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><div><div class="CodeViewHeader-module__FileResultsList__JDzUy"><span class="d-flex FileResultsList-module__FilesSearchBox__ivVkc TextInput-wrapper prc-components-TextInputWrapper-Hpdqi prc-components-TextInputBaseWrapper-wY-n0" data-no-trailing-action="true" data-component="TextInput" data-leading-visual="true" data-trailing-visual="true" aria-busy="false"><span class="TextInput-icon" id="_R_2pcql3al1d_" aria-hidden="true" data-component="TextInput.LeadingVisual"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg></span><input type="text" aria-label="Go to file" role="combobox" aria-controls="file-results-list" aria-expanded="false" aria-haspopup="dialog" autoCorrect="off" spellCheck="false" placeholder="Go to file" aria-describedby="_R_2pcql3al1d_ _R_2pcql3al1dH1_" data-component="input" class="prc-components-Input-IwWrt" value=""/><span class="TextInput-icon" id="_R_2pcql3al1dH1_" aria-hidden="true" data-component="TextInput.TrailingVisual"></span></span></div><div class="d-none"></div></div><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-wide" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_ficql3al1d_" id="_R_icql3al1d_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_ficql3al1d_">More file actions</span></div></div></div><div class="react-code-view-header-element--narrow"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-narrow" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_fieql3al1d_" id="_R_ieql3al1d_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_fieql3al1d_">More file actions</span></div></div></div></div></div></div></div><div class="CodeView-module__contentWrapper__cG2JH"><div class="react-code-view-bottom-padding"><div class="BlobTopBanners-module__Box__v_nvx"></div></div> <div class="d-none"></div><div class="d-flex flex-column border rounded-2 tmp-mb-3 pl-1"><div class="LatestCommit-module__Box__B25ZT"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">Latest commit</h2><div style="width:120px" class="Skeleton Skeleton--text" data-testid="loading"> </div><div class="d-flex flex-shrink-0 gap-2"><div data-testid="latest-commit-details" class="d-none d-sm-flex flex-items-center"></div><div class="d-flex gap-2"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">History</h2><a data-component="LinkButton" href="/microsoft/winget-cli/commits/master/doc/Settings.md" class="prc-Button-ButtonBase-9n-Xk d-none d-lg-flex LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><span class="fgColor-default">History</span></span></span></a><div class="d-sm-none"></div><div class="d-flex d-lg-none"><a data-component="LinkButton" aria-label="View commit history for this file." href="/microsoft/winget-cli/commits/master/doc/Settings.md" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby="_R_2balal3al1d_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span></span></a><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" role="tooltip" aria-hidden="true" id="_R_2balal3al1d_">History</span></div></div></div></div></div><div class="d-flex flex-row"><div class="container BlobViewContent-module__blobContainer__DtH2d"><div class="react-code-size-details-banner BlobViewContent-module__codeSizeDetails__e5sUw"><div class="react-code-size-details-banner CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="16.7 KB" style="--truncate-max-width:100%"><span>447 lines (307 loc) · 16.7 KB</span></div></div></div></div><div class="react-blob-view-header-sticky BlobViewContent-module__stickyHeader__VwxB5" id="repos-sticky-header"><div class="BlobViewHeader-module__Box__yhm9u"><div class="react-blob-sticky-header"><div class="FileNameStickyHeader-module__outerWrapper__ZL4Xc FileNameStickyHeader-module__outerWrapperHidden__Zpynk"><div class="FileNameStickyHeader-module__Box_1__Hazu5"><div class="FileNameStickyHeader-module__Box_2__hoolP"><div class="FileNameStickyHeader-module__Box_3__MVKsk"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="master branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayHeader__XtXRG"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></div><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP"> <!-- -->master</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="FileNameStickyHeader-module__Box_4__FLhtt"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__md__Wb1Gs"><nav data-testid="breadcrumbs" aria-labelledby="sticky-breadcrumb-heading" id="sticky-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="sticky-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/microsoft/winget-cli/tree/master" data-discover="true">winget-cli</a></li><li class="Breadcrumb-module__listItem__Ib0x_"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><a class="Breadcrumb-module__directoryLink__kQy_t prc-Link-Link-9ZwDx" data-component="Link" href="/microsoft/winget-cli/tree/master/doc" data-discover="true">doc</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__md__Wb1Gs prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="sticky-file-name-id">Settings.md</h1></div></div></div></div><button data-component="Button" type="button" class="prc-Button-ButtonBase-9n-Xk FileNameStickyHeader-module__Button__LSEU_ FileNameStickyHeader-module__GoToTopButton__nxAFn" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-up" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.47 7.78a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018L9 4.81v7.44a.75.75 0 0 1-1.5 0V4.81L4.53 7.78a.75.75 0 0 1-1.06 0Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Top</span></span></button></div></div></div><div class="BlobViewHeader-module__Box_1__VEmuQ"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">File metadata and controls</h2><div class="BlobViewHeader-module__Box_2__icUs2"><ul aria-label="File view" class="prc-SegmentedControl-SegmentedControl-lqIXp BlobTabButtons-module__SegmentedControl__jen2u" data-variant="default" data-size="small"><li class="prc-SegmentedControl-Item-tSCQh" data-selected=""><button aria-current="true" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:transparent"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Preview">Preview</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh"><button aria-current="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Code">Code</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh"><button aria-current="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Blame">Blame</div></span></button></li></ul><div class="d-none"></div><div class="react-code-size-details-in-header CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="16.7 KB" style="--truncate-max-width:100%"><span>447 lines (307 loc) · 16.7 KB</span></div></div></div></div><div class="BlobViewHeader-module__Box_3__ng6v2"><div class="d-none"></div><div class="react-blob-header-edit-and-raw-actions BlobViewHeader-module__Box_4__J4Y4W"><div class="d-none"></div><div class="prc-ButtonGroup-ButtonGroup-vFUrY" data-component="ButtonGroup"><div><a data-component="LinkButton" href="https://github.com/microsoft/winget-cli/raw/refs/heads/master/doc/Settings.md" data-testid="raw-button" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov BlobViewHeader-module__LinkButton__X9kx2" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Raw</span></span></a></div><div><button data-component="IconButton" type="button" data-testid="copy-raw-button" class="prc-Button-ButtonBase-9n-Xk prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_d5f6clal3al1d_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_d5f6clal3al1d_">Copy raw file</span></div><div><button data-component="IconButton" type="button" data-testid="download-raw-button" class="prc-Button-ButtonBase-9n-Xk BlobViewHeader-module__downloadButton__ef459 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_75f6clal3al1d_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-download" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"></path><path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_75f6clal3al1d_">Download raw file</span></div></div></div><button data-component="IconButton" type="button" aria-pressed="false" class="prc-Button-ButtonBase-9n-Xk tmp-mr-2 TableOfContents-module__IconButton__jrlNM prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_1v6clal3al1d_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-list-unordered" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.75 2.5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5ZM2 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-6a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM2 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_1v6clal3al1d_">Outline</span><div class="react-blob-header-edit-and-raw-actions-combined"><button data-component="IconButton" type="button" title="More file actions" data-testid="more-file-actions-button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click BlobViewHeader-module__IconButton__XrMQY prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7q76clal3al1d_" id="_R_a76clal3al1d_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7q76clal3al1d_">Edit and raw actions</span></div></div></div></div><div></div></div><div class="BlobViewContent-module__blobContentWrapper__JS0W6"><section aria-labelledby="file-name-id-wide file-name-id-mobile" class="BlobContent-module__blobContentSection__VOgZq BlobContent-module__blobContentSectionMarkdown__mPLOK" style="margin-top:46px"><div class="js-snippet-clipboard-copy-unpositioned BlobContent-module__markdownBlob__T8jpG" data-hpc="true"><article class="markdown-body entry-content container-lg" itemprop="text"><div class="markdown-heading" dir="auto"><h1 tabindex="-1" class="heading-element" dir="auto">WinGet CLI Settings</h1><a id="user-content-winget-cli-settings" class="anchor" aria-label="Permalink: WinGet CLI Settings" href="#winget-cli-settings"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">You can configure WinGet by editing the <code>settings.json</code> file. Running <code>winget settings</code> will open the file in the default json editor; if no editor is configured, Windows will prompt for you to select an editor, and Notepad is a sensible option if you have no other preference.</p> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">File Location</h2><a id="user-content-file-location" class="anchor" aria-label="Permalink: File Location" href="#file-location"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">Settings file is located in %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\settings.json</p> +<p dir="auto">If you are using the non-packaged WinGet version by building it from source code, the file will be located under %LOCALAPPDATA%\Microsoft\WinGet\Settings\settings.json</p> +<p dir="auto">If you are creating a settings file from scratch, make sure that the line <code>"$schema": "https://aka.ms/winget-settings.schema.json",</code> is in it.</p> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Source</h2><a id="user-content-source" class="anchor" aria-label="Permalink: Source" href="#source"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>source</code> settings involve configuration to the WinGet source.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;source&quot;: { + &quot;autoUpdateIntervalInMinutes&quot;: 3 + },"><pre> <span class="pl-ent">"source"</span>: { + <span class="pl-ent">"autoUpdateIntervalInMinutes"</span>: <span class="pl-c1">3</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">autoUpdateIntervalInMinutes</h3><a id="user-content-autoupdateintervalinminutes" class="anchor" aria-label="Permalink: autoUpdateIntervalInMinutes" href="#autoupdateintervalinminutes"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">A positive integer represents the update interval in minutes. The check for updates only happens when a source is used. A zero will disable the check for updates to a source. Any other values are invalid.</p> +<ul dir="auto"> +<li>Disable: 0</li> +<li>Default: 15</li> +</ul> +<p dir="auto">To manually update the source use <code>winget source update</code></p> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Visual</h2><a id="user-content-visual" class="anchor" aria-label="Permalink: Visual" href="#visual"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>visual</code> settings involve visual elements that are displayed by WinGet</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">progressBar</h3><a id="user-content-progressbar" class="anchor" aria-label="Permalink: progressBar" href="#progressbar"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">Style of the progress spinner and bar that WinGet displays when not specified by arguments. In addition, all options except <code>disabled</code> send <a href="https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC" rel="nofollow">Virtual Terminal progress</a> updates that any supporting terminal may display visually.</p> +<div class="markdown-alert markdown-alert-note" dir="auto"><p class="markdown-alert-title" dir="auto"><svg data-component="Octicon" class="octicon octicon-info mr-2" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>Note</p><p dir="auto">You can also disable progress output for a single command using the <code>--no-progress</code> flag, which takes precedence over this setting.</p> +</div> +<markdown-accessiblity-table><table> +<thead> +<tr> +<th>Value</th> +<th>Description</th> +<th>Release</th> +</tr> +</thead> +<tbody> +<tr> +<td><code>accent</code> (default)</td> +<td>Use the <a href="https://support.microsoft.com/en-us/windows/change-colors-in-windows-d26ef4d6-819a-581c-1581-493cfcc005fe" rel="nofollow">Windows Accent color</a></td> +<td>1.0</td> +</tr> +<tr> +<td><code>retro</code></td> +<td>Use the current foreground terminal color</td> +<td>1.0</td> +</tr> +<tr> +<td><code>rainbow</code></td> +<td>Progress through a rainbow of colors</td> +<td>1.0</td> +</tr> +<tr> +<td><code>sixel</code></td> +<td>Use sixel images; requires a terminal that supports displaying sixels, such as <a href="https://github.com/microsoft/terminal/releases">Windows Terminal</a> 1.22.2362 or later</td> +<td>1.9</td> +</tr> +<tr> +<td><code>disabled</code></td> +<td>No progress will be displayed</td> +<td>1.9</td> +</tr> +</tbody> +</table></markdown-accessiblity-table> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;visual&quot;: { + &quot;progressBar&quot;: &quot;accent&quot; + },"><pre> <span class="pl-ent">"visual"</span>: { + <span class="pl-ent">"progressBar"</span>: <span class="pl-s"><span class="pl-pds">"</span>accent<span class="pl-pds">"</span></span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">anonymizeDisplayedPaths</h3><a id="user-content-anonymizedisplayedpaths" class="anchor" aria-label="Permalink: anonymizeDisplayedPaths" href="#anonymizedisplayedpaths"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">Replaces some known folder paths with their respective environment variable. Defaults to true.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;visual&quot;: { + &quot;anonymizeDisplayedPaths&quot;: true + },"><pre> <span class="pl-ent">"visual"</span>: { + <span class="pl-ent">"anonymizeDisplayedPaths"</span>: <span class="pl-c1">true</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">enableSixels</h3><a id="user-content-enablesixels" class="anchor" aria-label="Permalink: enableSixels" href="#enablesixels"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">Enables output of sixel images in certain contexts. Defaults to false.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;visual&quot;: { + &quot;enableSixels&quot;: true + },"><pre> <span class="pl-ent">"visual"</span>: { + <span class="pl-ent">"enableSixels"</span>: <span class="pl-c1">true</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Install Behavior</h2><a id="user-content-install-behavior" class="anchor" aria-label="Permalink: Install Behavior" href="#install-behavior"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>installBehavior</code> settings affect the default behavior of installing and upgrading (where applicable) packages.</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Disable Install Notes</h3><a id="user-content-disable-install-notes" class="anchor" aria-label="Permalink: Disable Install Notes" href="#disable-install-notes"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>disableInstallNotes</code> behavior affects whether installation notes are shown after a successful install. Defaults to <code>false</code> if value is not set or is invalid.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;disableInstallNotes&quot;: true + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"disableInstallNotes"</span>: <span class="pl-c1">true</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Portable Package User Root</h3><a id="user-content-portable-package-user-root" class="anchor" aria-label="Permalink: Portable Package User Root" href="#portable-package-user-root"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>portablePackageUserRoot</code> setting affects the default root directory where packages are installed to under <code>User</code> scope. This setting only applies to packages with the <code>portable</code> installer type. Defaults to <code>%LOCALAPPDATA%/Microsoft/WinGet/Packages/</code> if value is not set or is invalid.</p> +<blockquote> +<p dir="auto">Note: This setting value must be an absolute path.</p> +</blockquote> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;portablePackageUserRoot&quot;: &quot;C:/Users/FooBar/Packages&quot; + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"portablePackageUserRoot"</span>: <span class="pl-s"><span class="pl-pds">"</span>C:/Users/FooBar/Packages<span class="pl-pds">"</span></span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Portable Package Machine Root</h3><a id="user-content-portable-package-machine-root" class="anchor" aria-label="Permalink: Portable Package Machine Root" href="#portable-package-machine-root"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>portablePackageMachineRoot</code> setting affects the default root directory where packages are installed to under <code>Machine</code> scope. This setting only applies to packages with the <code>portable</code> installer type. Defaults to <code>%PROGRAMFILES%/WinGet/Packages/</code> if value is not set or is invalid.</p> +<blockquote> +<p dir="auto">Note: This setting value must be an absolute path.</p> +</blockquote> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;portablePackageMachineRoot&quot;: &quot;C:/Program Files/Packages/Portable&quot; + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"portablePackageMachineRoot"</span>: <span class="pl-s"><span class="pl-pds">"</span>C:/Program Files/Packages/Portable<span class="pl-pds">"</span></span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Skip Dependencies</h3><a id="user-content-skip-dependencies" class="anchor" aria-label="Permalink: Skip Dependencies" href="#skip-dependencies"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The 'skipDependencies' behavior affects whether dependencies are installed for a given package. Defaults to 'false' if value is not set or is invalid.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;skipDependencies&quot;: true + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"skipDependencies"</span>: <span class="pl-c1">true</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Archive Extraction Method</h3><a id="user-content-archive-extraction-method" class="anchor" aria-label="Permalink: Archive Extraction Method" href="#archive-extraction-method"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>archiveExtractionMethod</code> behavior affects how installer archives are extracted. Currently there are two supported values: <code>Tar</code> or <code>ShellApi</code>. +<code>Tar</code> indicates that the archive should be extracted using the tar executable ('tar.exe') while <code>shellApi</code> indicates using the Windows Shell API. Defaults to <code>shellApi</code> if value is not set or is invalid.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;archiveExtractionMethod&quot;: &quot;tar&quot; | &quot;shellApi&quot; + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"archiveExtractionMethod"</span>: <span class="pl-s"><span class="pl-pds">"</span>tar<span class="pl-pds">"</span></span> <span class="pl-ii">| "shellApi"</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Preferences and Requirements</h3><a id="user-content-preferences-and-requirements" class="anchor" aria-label="Permalink: Preferences and Requirements" href="#preferences-and-requirements"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">Some of the settings are duplicated under <code>preferences</code> and <code>requirements</code>. <code>preferences</code> affect how the various available options are sorted when choosing the one to act on. For instance, the default scope of package installs is for the current user, but if that is not an option then a machine level installer will be chosen. <code>requirements</code> filter the options, potentially resulting in an empty list and a failure to install. In the previous example, a user scope requirement would result in no applicable installers and an error.</p> +<p dir="auto">When multiple values are listed under <code>requirements</code>, they are treated as an ordered preference in addition to a filter — the first listed value is preferred over subsequent ones when multiple valid options exist. If both <code>requirements</code> and <code>preferences</code> are set for the same field, the ordering from <code>preferences</code> takes precedence.</p> +<p dir="auto">Any arguments passed on the command line will effectively override the matching <code>requirement</code> setting for the duration of that command.</p> +<div class="markdown-alert markdown-alert-note" dir="auto"><p class="markdown-alert-title" dir="auto"><svg data-component="Octicon" class="octicon octicon-info mr-2" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>Note</p> +<ul dir="auto"> +<li>These settings are only applied for the <code>winget install</code> command.</li> +<li>Other commands like <code>winget configure</code> are not affected by these settings.</li> +</ul> +</div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Scope</h3><a id="user-content-scope" class="anchor" aria-label="Permalink: Scope" href="#scope"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>scope</code> behavior affects the choice between installing a package for the current user or for the entire machine. The matching parameter is <code>--scope</code>, and uses the same values (<code>user</code> or <code>machine</code>).</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;preferences&quot;: { + &quot;scope&quot;: &quot;user&quot; + } + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"preferences"</span>: { + <span class="pl-ent">"scope"</span>: <span class="pl-s"><span class="pl-pds">"</span>user<span class="pl-pds">"</span></span> + } + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Locale</h3><a id="user-content-locale" class="anchor" aria-label="Permalink: Locale" href="#locale"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>locale</code> behavior affects the choice of installer based on installer locale. The matching parameter is <code>--locale</code>, and uses bcp47 language tag.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;preferences&quot;: { + &quot;locale&quot;: [ &quot;en-US&quot;, &quot;fr-FR&quot; ] + } + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"preferences"</span>: { + <span class="pl-ent">"locale"</span>: [ <span class="pl-s"><span class="pl-pds">"</span>en-US<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>fr-FR<span class="pl-pds">"</span></span> ] + } + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Architectures</h3><a id="user-content-architectures" class="anchor" aria-label="Permalink: Architectures" href="#architectures"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>architectures</code> behavior affects what architectures will be selected when installing a package. The matching parameter is <code>--architecture</code>. Note that only architectures compatible with your system can be selected.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;preferences&quot;: { + &quot;architectures&quot;: [&quot;x64&quot;, &quot;arm64&quot;] + } + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"preferences"</span>: { + <span class="pl-ent">"architectures"</span>: [<span class="pl-s"><span class="pl-pds">"</span>x64<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>arm64<span class="pl-pds">"</span></span>] + } + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Installer Types</h3><a id="user-content-installer-types" class="anchor" aria-label="Permalink: Installer Types" href="#installer-types"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>installerTypes</code> behavior affects what installer types will be selected when installing a package. It can also determine which type to install by default if a manifest has multiple types: The list is in priority order, with the first listed type being preferred over the others, and so on. This is convenient for users who for instance prefer portable packages or MSIX/AppX installations. The matching parameter is <code>--installer-type</code>, which will override the settings.</p> +<p dir="auto">Allowed values as of version 1.12.470 include: <code>appx</code>, <code>burn</code>, <code>exe</code>, <code>font</code>, <code>inno</code>, <code>msi</code>, <code>msix</code>, <code>msstore</code>, <code>nullsoft</code>, <code>portable</code>, <code>wix</code>, <code>zip</code></p> +<p dir="auto">By default, when no user preference or requirement is configured, WinGet selects installer types in the following order: MSIX, MSI/Wix/Burn, Nullsoft/Inno/EXE, Portable. If it is already installed, the same installer type will be required to ensure a proper upgrade.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;preferences&quot;: { + &quot;installerTypes&quot;: [&quot;msi&quot;, &quot;msix&quot;] + }, + &quot;requirements&quot;: { + &quot;installerTypes&quot;: [&quot;msix&quot;, &quot;msi&quot;] + } + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"preferences"</span>: { + <span class="pl-ent">"installerTypes"</span>: [<span class="pl-s"><span class="pl-pds">"</span>msi<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>msix<span class="pl-pds">"</span></span>] + }, + <span class="pl-ent">"requirements"</span>: { + <span class="pl-ent">"installerTypes"</span>: [<span class="pl-s"><span class="pl-pds">"</span>msix<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>msi<span class="pl-pds">"</span></span>] + } + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Default install root</h3><a id="user-content-default-install-root" class="anchor" aria-label="Permalink: Default install root" href="#default-install-root"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>defaultInstallRoot</code> affects the install location when a package requires one. This can be overridden by the <code>--location</code> parameter. This setting is only used when a package manifest includes <code>InstallLocationRequired</code>, and the actual location is obtained by appending the package ID to the root.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;defaultInstallRoot&quot;: &quot;C:/installRoot&quot; + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"defaultInstallRoot"</span>: <span class="pl-s"><span class="pl-pds">"</span>C:/installRoot<span class="pl-pds">"</span></span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Maximum resumes</h3><a id="user-content-maximum-resumes" class="anchor" aria-label="Permalink: Maximum resumes" href="#maximum-resumes"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>maxResumes</code> setting determines the maximum number of times that a command may be resumed automatically. The default value is 3.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;installBehavior&quot;: { + &quot;maxResumes&quot;: 3 + },"><pre> <span class="pl-ent">"installBehavior"</span>: { + <span class="pl-ent">"maxResumes"</span>: <span class="pl-c1">3</span> + },</pre></div> +<blockquote> +<p dir="auto">Note: <a href="#resume">The resume behavior is an experimental feature.</a></p> +</blockquote> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Uninstall Behavior</h2><a id="user-content-uninstall-behavior" class="anchor" aria-label="Permalink: Uninstall Behavior" href="#uninstall-behavior"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>uninstallBehavior</code> settings affect the default behavior of uninstalling (where applicable) packages.</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Purge Portable Package</h3><a id="user-content-purge-portable-package" class="anchor" aria-label="Permalink: Purge Portable Package" href="#purge-portable-package"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>purgePortablePackage</code> behavior affects the default behavior for uninstalling a portable package. If set to <code>true</code>, uninstall will remove all files and directories relevant to the <code>portable</code> package. This setting only applies to packages with the <code>portable</code> installer type. Defaults to <code>false</code> if value is not set or is invalid.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;uninstallBehavior&quot;: { + &quot;purgePortablePackage&quot;: true + },"><pre> <span class="pl-ent">"uninstallBehavior"</span>: { + <span class="pl-ent">"purgePortablePackage"</span>: <span class="pl-c1">true</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Configure Behavior</h2><a id="user-content-configure-behavior" class="anchor" aria-label="Permalink: Configure Behavior" href="#configure-behavior"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>configureBehavior</code> settings affect the default behavior of applying a configuration.</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Default Module Root</h3><a id="user-content-default-module-root" class="anchor" aria-label="Permalink: Default Module Root" href="#default-module-root"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>defaultModuleRoot</code> behavior affects the default root directory where modules are installed to. Defaults to <code>%LOCALAPPDATA%/Microsoft/WinGet/Configuration/Modules</code> if value is not set or is invalid.</p> +<blockquote> +<p dir="auto">Note: This setting value must be an absolute path.</p> +</blockquote> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;configureBehavior&quot;: { + &quot;defaultModuleRoot&quot;: &quot;C:/Program Files/Modules/&quot; + },"><pre> <span class="pl-ent">"configureBehavior"</span>: { + <span class="pl-ent">"defaultModuleRoot"</span>: <span class="pl-s"><span class="pl-pds">"</span>C:/Program Files/Modules/<span class="pl-pds">"</span></span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Download Behavior</h2><a id="user-content-download-behavior" class="anchor" aria-label="Permalink: Download Behavior" href="#download-behavior"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>downloadBehavior</code> settings affect the default behavior of downloading packages.</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Default Download Directory</h3><a id="user-content-default-download-directory" class="anchor" aria-label="Permalink: Default Download Directory" href="#default-download-directory"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>defaultDownloadDirectory</code> setting affects the default directory where installers are downloaded to. Defaults to <code>%USERPROFILE%/Downloads/</code> if value is not set or is invalid.</p> +<blockquote> +<p dir="auto">Note: This setting value must be an absolute path.</p> +</blockquote> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;downloadBehavior&quot;: { + &quot;defaultDownloadDirectory&quot;: &quot;C:/Users/FooBar/Downloads&quot; + },"><pre> <span class="pl-ent">"downloadBehavior"</span>: { + <span class="pl-ent">"defaultDownloadDirectory"</span>: <span class="pl-s"><span class="pl-pds">"</span>C:/Users/FooBar/Downloads<span class="pl-pds">"</span></span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Telemetry</h2><a id="user-content-telemetry" class="anchor" aria-label="Permalink: Telemetry" href="#telemetry"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>telemetry</code> settings control whether winget writes ETW events that may be sent to Microsoft on a default installation of Windows.</p> +<p dir="auto">See <a href="/microsoft/winget-cli/blob/master/README.md#datatelemetry">details on telemetry</a>, and our <a href="/microsoft/winget-cli/blob/master/PRIVACY.md">primary privacy statement</a>.</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">disable</h3><a id="user-content-disable" class="anchor" aria-label="Permalink: disable" href="#disable"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;telemetry&quot;: { + &quot;disable&quot;: true + },"><pre> <span class="pl-ent">"telemetry"</span>: { + <span class="pl-ent">"disable"</span>: <span class="pl-c1">true</span> + },</pre></div> +<p dir="auto">If set to true, the <code>telemetry.disable</code> setting will prevent any event from being written by the program.</p> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Logging</h2><a id="user-content-logging" class="anchor" aria-label="Permalink: Logging" href="#logging"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>logging</code> settings control the level of detail in log files.</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">level</h3><a id="user-content-level" class="anchor" aria-label="Permalink: level" href="#level"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto"><code>--verbose-logs</code> will override this setting and always creates a verbose log. +Defaults to <code>info</code> if value is not set or is invalid.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;logging&quot;: { + &quot;level&quot;: &quot;verbose&quot; | &quot;info&quot; | &quot;warning&quot; | &quot;error&quot; | &quot;critical&quot; + },"><pre> <span class="pl-ent">"logging"</span>: { + <span class="pl-ent">"level"</span>: <span class="pl-s"><span class="pl-pds">"</span>verbose<span class="pl-pds">"</span></span> <span class="pl-ii">| "info" | "warning" | "error" | "critical"</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">channels</h3><a id="user-content-channels" class="anchor" aria-label="Permalink: channels" href="#channels"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The valid values in this array are defined in the function <code>GetChannelFromName</code> in the <a href="/microsoft/winget-cli/blob/master/src/AppInstallerSharedLib/AppInstallerLogging.cpp">logging code</a>. These align with the <em><strong>channel identifier</strong></em> found in the log files. For example, <em><strong><code>CORE</code></strong></em> in:</p> +<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="2023-12-06 19:17:07.988 [CORE] WinGet, version [1.7.0-preview], activity [{24A91EA8-46BE-47A1-B65C-CEBCE90B8675}]"><pre lang="plaintext" class="notranslate"><code>2023-12-06 19:17:07.988 [CORE] WinGet, version [1.7.0-preview], activity [{24A91EA8-46BE-47A1-B65C-CEBCE90B8675}] +</code></pre></div> +<p dir="auto">In addition, there are special values that cover multiple channels. <code>default</code> is the default set of channels, while <code>all</code> is all of the channels. Invalid values are ignored.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;logging&quot;: { + &quot;channels&quot;: [&quot;default&quot;] + },"><pre> <span class="pl-ent">"logging"</span>: { + <span class="pl-ent">"channels"</span>: [<span class="pl-s"><span class="pl-pds">"</span>default<span class="pl-pds">"</span></span>] + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">fileNameStrategy</h3><a id="user-content-filenamestrategy" class="anchor" aria-label="Permalink: fileNameStrategy" href="#filenamestrategy"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">Sets the default strategy for naming log files for installers that support it. <code>manifest</code> is the default and uses the manifest name. <code>timestamp</code> uses the date and time. <code>guid</code> uses a generated GUID. <code>shortguid</code> uses the first 8 characters of a generated GUID. Invalid values will revert to <code>manifest</code>.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;logging&quot;: { + &quot;fileNameStrategy&quot;: &quot;manifest&quot; | &quot;timestamp&quot; | &quot;guid&quot; | &quot;shortguid&quot; + },"><pre> <span class="pl-ent">"logging"</span>: { + <span class="pl-ent">"fileNameStrategy"</span>: <span class="pl-s"><span class="pl-pds">"</span>manifest<span class="pl-pds">"</span></span> <span class="pl-ii">| "timestamp" | "guid" | "shortguid"</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">file</h3><a id="user-content-file" class="anchor" aria-label="Permalink: file" href="#file"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>file</code> settings control the log files generated by winget during operation. These settings apply to the automatic cleanup that happens whenever a Windows Package Manager process is run. +They only apply to the default log location, which contains winget logs, AppInstaller logs (the MSIX install UI), and is the default location where installer logs are placed. +The automatic cleanup happens at the beginning of the process, so the log file(s) generated by the current process will not be considered in the limits.</p> +<markdown-accessiblity-table><table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +<th>Default</th> +<th>Note</th> +</tr> +</thead> +<tbody> +<tr> +<td><code>ageLimitInDays</code></td> +<td>The maximum age, in days, of files in the log directory; older files are deleted.</td> +<td>7 (days)</td> +<td>Set to 0 to disable this limit.</td> +</tr> +<tr> +<td><code>totalSizeLimitInMB</code></td> +<td>The maximum size, in megabytes, of all files in the log directory; the oldest files are deleted first.</td> +<td>128 (MB)</td> +<td>Set to 0 to disable this limit.</td> +</tr> +<tr> +<td><code>countLimit</code></td> +<td>The maximum number of files in the log directory; the oldest files are deleted first.</td> +<td>0</td> +<td>Set to 0 (the default) to disable this limit.</td> +</tr> +</tbody> +</table></markdown-accessiblity-table> +<p dir="auto">These settings apply to the log files that winget writes, only as they are being written. They do not apply to files written by installers or the AppInstaller UI.</p> +<markdown-accessiblity-table><table> +<thead> +<tr> +<th>Setting</th> +<th>Description</th> +<th>Default</th> +<th>Note</th> +</tr> +</thead> +<tbody> +<tr> +<td><code>individualSizeLimitInMB</code></td> +<td>The maximum size, in megabytes, of an individual log file. If a file would exceed this limit, the logs will wrap. Note that this limit is approximate and the actual files may exceed it by a few bytes.</td> +<td>16 (MB)</td> +<td>Set to 0 to disable this limit.</td> +</tr> +</tbody> +</table></markdown-accessiblity-table> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;logging&quot;: { + &quot;file&quot;: { + &quot;ageLimitInDays&quot;: 7, + &quot;totalSizeLimitInMB&quot;: 128, + &quot;countLimit&quot;: 0, + &quot;individualSizeLimitInMB&quot;: 16, + } + },"><pre> <span class="pl-ent">"logging"</span>: { + <span class="pl-ent">"file"</span>: { + <span class="pl-ent">"ageLimitInDays"</span>: <span class="pl-c1">7</span>, + <span class="pl-ent">"totalSizeLimitInMB"</span>: <span class="pl-c1">128</span>, + <span class="pl-ent">"countLimit"</span>: <span class="pl-c1">0</span>, + <span class="pl-ent">"individualSizeLimitInMB"</span>: <span class="pl-c1">16</span>, + } + },</pre></div> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Network</h2><a id="user-content-network" class="anchor" aria-label="Permalink: Network" href="#network"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>network</code> settings influence how winget uses the network to retrieve packages and metadata.</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Downloader</h3><a id="user-content-downloader" class="anchor" aria-label="Permalink: Downloader" href="#downloader"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>downloader</code> setting controls which code is used when downloading packages. The default is <code>default</code>, which may be any of the options based on our determination. +<code>wininet</code> uses the <a href="https://docs.microsoft.com/windows/win32/wininet/about-wininet" rel="nofollow">WinINet</a> APIs, while <code>do</code> uses the +<a href="https://support.microsoft.com/windows/delivery-optimization-in-windows-10-0656e53c-15f2-90de-a87a-a2172c94cf6d" rel="nofollow">Delivery Optimization</a> service.</p> +<p dir="auto">The <code>doProgressTimeoutInSeconds</code> setting updates the number of seconds to wait without progress before fallback. The default number of seconds is 60, minimum is 1 and the maximum is 600.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;network&quot;: { + &quot;downloader&quot;: &quot;do&quot;, + &quot;doProgressTimeoutInSeconds&quot;: 60 + }"><pre> <span class="pl-ent">"network"</span>: { + <span class="pl-ent">"downloader"</span>: <span class="pl-s"><span class="pl-pds">"</span>do<span class="pl-pds">"</span></span>, + <span class="pl-ent">"doProgressTimeoutInSeconds"</span>: <span class="pl-c1">60</span> + }</pre></div> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Interactivity</h2><a id="user-content-interactivity" class="anchor" aria-label="Permalink: Interactivity" href="#interactivity"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">The <code>interactivity</code> settings control whether winget may show interactive prompts during execution. Note that this refers only to prompts shown by winget itself and not to those shown by package installers.</p> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">disable</h3><a id="user-content-disable-1" class="anchor" aria-label="Permalink: disable" href="#disable-1"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;interactivity&quot;: { + &quot;disable&quot;: true + },"><pre> <span class="pl-ent">"interactivity"</span>: { + <span class="pl-ent">"disable"</span>: <span class="pl-c1">true</span> + },</pre></div> +<p dir="auto">If set to true, the <code>interactivity.disable</code> setting will prevent any interactive prompt from being shown.</p> +<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Experimental Features</h2><a id="user-content-experimental-features" class="anchor" aria-label="Permalink: Experimental Features" href="#experimental-features"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">To allow work to be done and distributed to early adopters for feedback, settings can be used to enable "experimental" features.</p> +<p dir="auto">The <code>experimentalFeatures</code> settings involve the configuration of these "experimental" features. Individual features can be enabled under this node. The example below shows sample experimental features.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;experimentalFeatures&quot;: { + &quot;experimentalCmd&quot;: true, + &quot;experimentalArg&quot;: false + },"><pre> <span class="pl-ent">"experimentalFeatures"</span>: { + <span class="pl-ent">"experimentalCmd"</span>: <span class="pl-c1">true</span>, + <span class="pl-ent">"experimentalArg"</span>: <span class="pl-c1">false</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">directMSI</h3><a id="user-content-directmsi" class="anchor" aria-label="Permalink: directMSI" href="#directmsi"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">This feature enables the Windows Package Manager to directly install MSI packages with the MSI APIs rather than through msiexec. +Note that when silent installation is used this is already in affect, as MSI packages that require elevation will fail in that scenario without it. +You can enable the feature as shown below.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;experimentalFeatures&quot;: { + &quot;directMSI&quot;: true + },"><pre> <span class="pl-ent">"experimentalFeatures"</span>: { + <span class="pl-ent">"directMSI"</span>: <span class="pl-c1">true</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">resume</h3><a id="user-content-resume" class="anchor" aria-label="Permalink: resume" href="#resume"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">This feature enables support for some commands to resume. +You can enable the feature as shown below.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;experimentalFeatures&quot;: { + &quot;resume&quot;: true + },"><pre> <span class="pl-ent">"experimentalFeatures"</span>: { + <span class="pl-ent">"resume"</span>: <span class="pl-c1">true</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">fonts</h3><a id="user-content-fonts" class="anchor" aria-label="Permalink: fonts" href="#fonts"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">This feature enables support for fonts via <code>winget settings</code>. The <code>winget font list</code> command will list installed font families and the number of installed font faces.</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;experimentalFeatures&quot;: { + &quot;fonts&quot;: true + },"><pre> <span class="pl-ent">"experimentalFeatures"</span>: { + <span class="pl-ent">"fonts"</span>: <span class="pl-c1">true</span> + },</pre></div> +<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">sourcePriority</h3><a id="user-content-sourcepriority" class="anchor" aria-label="Permalink: sourcePriority" href="#sourcepriority"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> +<p dir="auto">This feature enables sources to have a priority value assigned. Sources with a higher priority will appear earlier in search results and will be selected for installing new packages when multiple sources have a matching package.</p> +<p dir="auto">Note that search result ordering is dependent on several factors, and source priority is the lowest field in that currently (match quality and field are more important).</p> +<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" &quot;experimentalFeatures&quot;: { + &quot;sourcePriority&quot;: true + },"><pre> <span class="pl-ent">"experimentalFeatures"</span>: { + <span class="pl-ent">"sourcePriority"</span>: <span class="pl-c1">true</span> + },</pre></div> +</article></div><div class="d-none"></div></section></div></div></div> </div> <!-- --> </div></div></div></div></div></div><div class="ScrollMarksContainer-module__scrollMarksContainer__Eu7uU" id="find-result-marks-container"></div><div class="d-none"></div><div class="d-none"></div></div> <!-- --> <!-- --> <script type="application/json" id="__PRIMER_DATA__R_1___">{"resolvedServerColorMode":"day"}</script></div> +</react-app> + + + + + </div> + +</turbo-frame> + + </main> + </div> + + </div> + + <footer class="footer tmp-pt-7 tmp-pb-6 f6 color-fg-muted color-border-subtle p-responsive" role="contentinfo" > + <h2 class='sr-only'>Footer</h2> + + + + + <div class="d-flex flex-justify-center flex-items-center flex-column-reverse flex-lg-row flex-wrap flex-lg-nowrap"> + <div class="d-flex flex-items-center flex-shrink-0 mx-2"> + <a aria-label="GitHub Homepage" class="footer-octicon mr-2" href="https://github.com"> + <svg aria-hidden="true" data-component="Octicon" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-mark-github"> + <path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path> +</svg> +</a> + <span> + &copy; 2026 GitHub,&nbsp;Inc. + </span> + </div> + + <nav aria-label="Footer"> + <h3 class="sr-only" id="sr-footer-heading">Footer navigation</h3> + + <ul class="list-style-none d-flex flex-justify-center flex-wrap mb-2 mb-lg-0" aria-labelledby="sr-footer-heading"> + + + <li class="mx-2"> + <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to Terms&quot;,&quot;label&quot;:&quot;text:terms&quot;}" href="https://docs.github.com/site-policy/github-terms/github-terms-of-service" data-view-component="true" class="Link--secondary Link">Terms</a> + </li> + + <li class="mx-2"> + <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to privacy&quot;,&quot;label&quot;:&quot;text:privacy&quot;}" href="https://docs.github.com/site-policy/privacy-policies/github-privacy-statement" data-view-component="true" class="Link--secondary Link">Privacy</a> + </li> + + <li class="mx-2"> + <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to security&quot;,&quot;label&quot;:&quot;text:security&quot;}" href="https://github.com/security" data-view-component="true" class="Link--secondary Link">Security</a> + </li> + + <li class="mx-2"> + <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to status&quot;,&quot;label&quot;:&quot;text:status&quot;}" href="https://www.githubstatus.com/" data-view-component="true" class="Link--secondary Link">Status</a> + </li> + + <li class="mx-2"> + <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to community&quot;,&quot;label&quot;:&quot;text:community&quot;}" href="https://github.community/" data-view-component="true" class="Link--secondary Link">Community</a> + </li> + + <li class="mx-2"> + <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to docs&quot;,&quot;label&quot;:&quot;text:docs&quot;}" href="https://docs.github.com/" data-view-component="true" class="Link--secondary Link">Docs</a> + </li> + + <li class="mx-2"> + <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to contact&quot;,&quot;label&quot;:&quot;text:contact&quot;}" href="https://support.github.com?tags=dotcom-footer" data-view-component="true" class="Link--secondary Link">Contact</a> + </li> + + <li class="mx-2" > + <cookie-consent-link> + <button + type="button" + class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent" + data-action="click:cookie-consent-link#showConsentManagement" + data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;cookies&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;cookies_link_subfooter_footer&quot;}" + > + Manage cookies + </button> + </cookie-consent-link> +</li> + +<li class="mx-2"> + <cookie-consent-link> + <button + type="button" + class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent text-left" + data-action="click:cookie-consent-link#showConsentManagement" + data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;dont_share_info&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;dont_share_info_link_subfooter_footer&quot;}" + > + Do not share my personal information + </button> + </cookie-consent-link> +</li> + + </ul> + </nav> + </div> +</footer> + + + + <ghcc-consent id="ghcc" class="position-fixed bottom-0 left-0" style="z-index: 999999" + data-locale="en" + data-initial-cookie-consent-allowed="" + data-cookie-consent-required="false" + ></ghcc-consent> + + + + + <div id="ajax-error-message" class="ajax-error-message flash flash-error" hidden> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"> + <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> +</svg> + <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> + <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> +</svg> + </button> + You can’t perform that action at this time. + </div> + + <template id="site-details-dialog"> + <details class="details-reset details-overlay details-overlay-dark lh-default color-fg-default hx_rsm" open> + <summary role="button" aria-label="Close dialog"></summary> + <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal"> + <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> + <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> +</svg> + </button> + <div class="octocat-spinner tmp-my-6 js-details-dialog-spinner"></div> + </details-dialog> + </details> +</template> + + <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;"> + <div class="Popover-message Popover-message--bottom-left Popover-message--large Box color-shadow-large" style="width:360px;"> + </div> +</div> + + <template id="snippet-clipboard-copy-button"> + <div class="zeroclipboard-container position-absolute right-0 top-0"> + <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn js-clipboard-copy m-2 p-0" data-copy-feedback="Copied!" data-tooltip-direction="w"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2 tmp-m-2"> + <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> +</svg> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none m-2 tmp-m-2"> + <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> +</svg> + </clipboard-copy> + </div> +</template> +<template id="snippet-clipboard-copy-button-unpositioned"> + <div class="zeroclipboard-container"> + <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn btn-invisible js-clipboard-copy m-2 p-0 d-flex flex-justify-center flex-items-center" data-copy-feedback="Copied!" data-tooltip-direction="w"> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon"> + <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> +</svg> + <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none"> + <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> +</svg> + </clipboard-copy> + </div> +</template> + + + + + </div> + <div id="js-global-screen-reader-notice" class="sr-only mt-n1" aria-live="polite" aria-atomic="true" ></div> + <div id="js-global-screen-reader-notice-assertive" class="sr-only mt-n1" aria-live="assertive" aria-atomic="true"></div> + </body> +</html> +