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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions windows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Windows configuration

Live on the `windows` branch. Branches from `main`, so shared configs under
`config/` (nvim, tmux, etc.) are reusable — `setup.ps1` symlinks them into
their Windows locations.

## Layout

```
windows/
├── powershell/
│ ├── Microsoft.PowerShell_profile.ps1 # used by both pwsh 7 and PS 5.1
│ └── Modules/
│ └── KrisTools/ # personal cmdlets (see below)
├── windows-terminal/
│ └── settings.json
├── git/
│ ├── .gitconfig
│ └── ignore # global gitignore
├── scoop/
│ ├── config.json
│ └── apps.json # `scoop export`
├── winget/
│ └── apps.json # `winget export`
└── setup.ps1
```

## Bootstrap a new machine

1. Install [scoop](https://scoop.sh) and/or ensure winget is present.
2. Install git and pwsh:
```powershell
scoop install git pwsh
```
3. Clone:
```powershell
git clone -b windows https://github.com/kriswill/dotfiles "$HOME\src\dotfiles"
cd "$HOME\src\dotfiles"
```
4. Allow symlink creation via **one** of:
- **Elevated shell** (simplest on a fresh box): right-click Windows
Terminal / PowerShell → *Run as administrator*. Works from either
Windows PowerShell 5.1 or pwsh 7 — confirmed working on Win11.
- **Developer Mode on** (no admin needed per run): Settings → Privacy
& security → For developers → **Developer Mode = On**.
5. Run setup (from the elevated shell, if you went that route):
```powershell
pwsh -ExecutionPolicy Bypass -File .\windows\setup.ps1 -InstallApps
```
If pwsh isn't installed yet, the script also runs fine under Windows
PowerShell 5.1:
```powershell
powershell -ExecutionPolicy Bypass -File .\windows\setup.ps1 -InstallApps
```

`setup.ps1` backs up any existing file to `<path>.bak-<timestamp>` before
replacing it with a symlink. Safe to re-run.

## Custom commands (KrisTools module)

Personal utilities are packaged as a PowerShell module rather than a
`bin/` directory of loose scripts — it's the idiomatic Windows answer:
approved verbs, `Get-Help`, tab completion, in-process invocation, no
`PATHEXT` tricks.

Layout:

```
powershell/Modules/KrisTools/
├── KrisTools.psd1 # manifest
├── KrisTools.psm1 # loader (dot-sources Public/*.ps1)
└── Public/
└── Show-DisplayInfo.ps1 # function + Set-Alias display-info
```

`setup.ps1` symlinks the `KrisTools` directory into the user's
`Documents\PowerShell\Modules\` (and the 5.1 and OneDrive-redirected
variants). PowerShell auto-discovers modules on `$env:PSModulePath` so
no config changes are needed beyond `Import-Module KrisTools` in the
profile.

### Adding a new command

1. Create `powershell/Modules/KrisTools/Public/Verb-Noun.ps1` using an
[approved verb](https://learn.microsoft.com/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands):
```powershell
function Verb-Noun {
[CmdletBinding()]
param()
# ...
}
Set-Alias -Name short-name -Value Verb-Noun
```
2. That's it — `KrisTools.psm1` auto-loads every `Public\*.ps1` on
`Import-Module`, and the manifest exports all functions and aliases.
3. Re-run `setup.ps1` only if you added a *new module directory*.

### Current commands

| Command | Alias | What it does |
| --------------- | -------------- | ---------------------------------- |
| `Show-DisplayInfo` | `display-info` | Styled GPU & monitor report |

## Related guides

- [nerdfont-setup.md](./nerdfont-setup.md) — install pwsh 7, the
`NerdFonts` PSGallery module, JetBrainsMono Nerd Font, and wire it into
Windows Terminal as the default profile + font.

## Capturing changes back to the repo

Because targets are symlinks, edits made in Windows Terminal / PowerShell
/ `.gitconfig` land directly in the repo — just `git add` + commit.

The scoop import currently includes `gh` (GitHub CLI), `lazygit`, and
`pwsh`. Add more by `scoop install <name>` then re-exporting.

Refresh app lists after installing something new:

```powershell
scoop export > windows\scoop\apps.json
winget export -o windows\winget\apps.json
```
10 changes: 10 additions & 0 deletions windows/git/.gitconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[filter "lfs"]
required = true
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process
[user]
name = Kris Williams
email = 115474+kriswill@users.noreply.github.com
[safe]
directory = C:/Program Files (x86)/World of Warcraft/_retail_
1 change: 1 addition & 0 deletions windows/git/ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/.claude\settings.local.json
117 changes: 117 additions & 0 deletions windows/nerdfont-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Nerd Font setup on Windows (PowerShell only)

End state: PowerShell 7 installed, `JetBrainsMono Nerd Font` installed, Windows Terminal using it as default with a PowerShell 7 profile as default.

## 1. Install PowerShell 7

From **Windows PowerShell 5.1** (run as your user, not admin):

```powershell
winget install --id Microsoft.PowerShell --source winget --accept-source-agreements --accept-package-agreements
```

Alternative if you use scoop:

```powershell
scoop install pwsh
```

Close this shell. Everything from here on runs in **pwsh** (PowerShell 7).

## 2. Launch pwsh and bootstrap PSGallery

Open a new `pwsh` session:

```powershell
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
```

Notes:
- The `NerdFonts` module uses PowerShell 7.3+ syntax (`clean {}` block). It will **not** load under Windows PowerShell 5.1 despite what its manifest claims. That's why step 1 installs pwsh first.

## 3. Install the NerdFonts module

```powershell
Install-Module -Name NerdFonts -Scope CurrentUser -Force
Import-Module NerdFonts
Get-Command -Module NerdFonts # should show Get-NerdFont, Install-NerdFont
```

## 4. Install JetBrainsMono Nerd Font

```powershell
Get-NerdFont | Where-Object Name -like 'JetBrains*' # confirm name
Install-NerdFont -Name 'JetBrainsMono'
```

Use `-Scope AllUsers` (admin required) to install system-wide instead of per-user. Verify:

```powershell
(New-Object System.Drawing.Text.InstalledFontCollection).Families |
Where-Object Name -like '*JetBrains*'
```

You should see `JetBrainsMono Nerd Font` (and possibly `JetBrainsMono Nerd Font Mono`, `…Propo`).

## 5. Auto-import on future sessions (optional)

Create the pwsh profile:

```powershell
New-Item -ItemType File -Path $PROFILE -Force
@'
if (-not (Get-Module -ListAvailable -Name NerdFonts)) {
Install-Module -Name NerdFonts -Scope CurrentUser -Force -ErrorAction SilentlyContinue
}
Import-Module NerdFonts -ErrorAction SilentlyContinue
'@ | Set-Content -Path $PROFILE -Encoding UTF8
```

## 6. Configure Windows Terminal

Locate settings.json:

```powershell
$wtSettings = "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
```

Open it in your editor and:

**a.** Set the font for all profiles — add a `font.face` entry inside `profiles.defaults`:

```json
"defaults": {
"font": { "face": "JetBrainsMono Nerd Font" }
}
```

**b.** Add a PowerShell 7 profile to `profiles.list` (adjust `commandline` if pwsh is not on PATH — e.g. scoop installs at `%USERPROFILE%\scoop\apps\pwsh\current\pwsh.exe`):

```json
{
"guid": "{2d8e4a3f-7c91-4e5b-a6f2-8b1c5d9e3a7b}",
"name": "PowerShell 7",
"commandline": "pwsh.exe -NoLogo",
"startingDirectory": "%USERPROFILE%",
"hidden": false
}
```

Generate your own GUID with `[guid]::NewGuid()` if you prefer.

**c.** Set it as default — change the top-level `defaultProfile` to match the GUID above:

```json
"defaultProfile": "{2d8e4a3f-7c91-4e5b-a6f2-8b1c5d9e3a7b}"
```

Open a new Windows Terminal tab — it should launch pwsh 7 with JetBrainsMono Nerd Font.

## Troubleshooting

- **`Get-NerdFont` not found** — module didn't install. Re-run step 2, then `Install-Module NerdFonts -Force -Verbose` and read the error.
- **Font not showing in Terminal** — face name mismatch. Run the `InstalledFontCollection` check above and use the exact `Name` value.
- **`clean {}` parser error** — you're in Windows PowerShell 5.1. Switch to pwsh.
- **OneDrive-redirected Documents** — `$PROFILE` will resolve to `…\OneDrive\Documents\PowerShell\…`. That's fine; `Install-Module` installs to `…\Documents\PowerShell\Modules\` (same root), so pwsh finds it.
10 changes: 10 additions & 0 deletions windows/powershell/Microsoft.PowerShell_profile.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
if (-not (Get-Module -ListAvailable -Name NerdFonts)) {
try {
Install-Module -Name NerdFonts -Scope CurrentUser -Force -AcceptLicense -ErrorAction Stop
} catch {
Write-Warning "Failed to install NerdFonts module: $_"
}
}
Import-Module NerdFonts -ErrorAction SilentlyContinue

Import-Module KrisTools -ErrorAction SilentlyContinue
12 changes: 12 additions & 0 deletions windows/powershell/Modules/KrisTools/KrisTools.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@{
RootModule = 'KrisTools.psm1'
ModuleVersion = '0.1.0'
GUID = 'a9e1c6d4-0b27-4f3c-9c5a-7f2d8e4b1a03'
Author = 'Kris Williams'
Description = 'Personal PowerShell utilities (dotfiles/windows).'
PowerShellVersion = '5.1'
FunctionsToExport = '*'
AliasesToExport = '*'
CmdletsToExport = @()
VariablesToExport = @()
}
7 changes: 7 additions & 0 deletions windows/powershell/Modules/KrisTools/KrisTools.psm1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$Public = @(Get-ChildItem -Path "$PSScriptRoot\Public\*.ps1" -ErrorAction SilentlyContinue)

foreach ($file in $Public) {
. $file.FullName
}

Export-ModuleMember -Function $Public.BaseName -Alias *
Loading