# client-setup | File | What | |---|---| | `setup-gaming-box.ps1` | The bootstrap. Run once on a fresh box | | `help.html` | The page he actually opens. Copied to his Desktop as `START HERE.html` | | `collect-diagnostics.ps1` | Dumps event logs, firewall, network, OBS logs to text | | `monitor-connection.ps1` | Logs gateway vs internet ping to a CSV | The two helpers get copied to `\Diagnostics\` with Desktop shortcuts, so he never opens a terminal. **His Desktop ends up with exactly three things**: `START HERE.html`, Collect Diagnostics, Monitor Connection. The long-form text guides go to `Documents\Rig Reference\` — still inside Claude's scope so it can read them, but out of his way. ## help.html Written for someone non-technical. Standalone — no build step, no CDN needed for it to function, so it works with the internet down, which is exactly when the troubleshooting half matters. Google Fonts degrade to real fallback stacks. Opens with the only thing he has to remember: run Collect Diagnostics, paste one sentence into Claude, text a human if still stuck. Below that, tappable cards per symptom, server addresses with copy buttons, a pre-stream checklist that remembers ticks in `localStorage`, and the sponsorship-scam warning. A published copy lives at for previewing without a Windows box. `help.html` in this directory is the source of truth — the published copy is generated by stripping the document wrapper, since the artifact host supplies its own. Bootstrap script for a **player's** Windows box — not a tofu module, and nothing in here touches AWS. It is the client-side companion to `gaming/servers` (the EC2 game servers) and `gaming/dns` (the `larryfargo.games` records). ## Run it On the target machine, in an **admin** PowerShell: ```powershell Set-ExecutionPolicy Bypass -Scope Process -Force .\setup-gaming-box.ps1 -DryRun # see everything it would do .\setup-gaming-box.ps1 # core: launchers, comms, Defender, tweaks ``` | Flag | Effect | |---|---| | `-Preset full` | Adds Firefox, HWiNFO, CPU-Z, VLC | | `-Streaming` | OBS, Chatterino, VoiceMeeter, ShareX, NVIDIA Broadcast (if NVIDIA), kills audio ducking, writes the go-live checklist | | `-VTuber` | Implies `-Streaming`; writes the VTuber guide | | `-TailscaleAuthKey ` | Tailscale always installs, but stays logged out unless you pass a key | | `-ObsWebSocket` | Firewall rule for OBS WebSocket on 4455, Private profile only | | `-ClaudeDirs a,b` | Override which folders Claude may read/write | | `-SkipClaudeFs` | Install Claude without filesystem access | | `-SkipTweaks` | Software only — no registry, power plan, debloat or Defender changes | | `-DryRun` | Changes nothing | Full streamer build: ```powershell .\setup-gaming-box.ps1 -Preset full -Streaming -VTuber ``` **Tailscale installs but does not log in.** It sits on the box unauthenticated until someone decides the box belongs on the tailnet. `-TailscaleAuthKey` is the deliberate opt-in. Idempotent — re-running skips what is already installed. ## Design notes **winget, not Chocolatey.** The other `.ps1` files in this repo bootstrap Chocolatey, because they run on our own boxes and predate winget being dependable. winget ships with Windows 11, so a guest machine needs nothing installed before the script runs. **Fail-soft installs.** A wrong package id reports at the end instead of aborting. The ids in `$Apps` were written from memory and have never been run; `-DryRun` and the failure list are how you find the bad ones. Verify one with `winget show --id `. **Debloat is curated, not a sweep.** An explicit removal list, plus a `$ProtectedApps` guard that refuses to remove anything on it even if the removal list matches. `Microsoft.DesktopAppInstaller` is on that guard list because it *is* winget — a wildcard sweep is how people delete the thing the script is running on. Xbox Game Bar and the Xbox app stay too: some games overlay through them and Game Pass needs them. Game DVR's background *recording* gets turned off instead, which is the part that costs frames. Also deliberate: no services disabled, and no third-party debloat mega-script. Those rot across Windows releases and leave nobody able to explain what broke. **OneDrive removal is guarded.** If OneDrive has already redirected Desktop or Documents, the script refuses and tells you to move them back by hand first — uninstalling in that state strands the files. **Defender, no third-party AV.** Consumer AV costs frames, fights anti-cheat, and monetises through bundleware. The script instead enables the three things Defender ships with switched off: PUA protection, network protection, and cloud-delivered protection. Two things it deliberately does *not* do, so nobody re-argues them: - *Controlled Folder Access* — blocks games writing saves to Documents. - *Steam library scan exclusions* — a popular framerate tip, but mods and workshop content are exactly what you want scanned, and the real-time scan cost on NVMe is noise. **The real threat is token theft, not viruses.** Streamers get "we'd love to sponsor you" DMs carrying infostealers; those lift browser session tokens, which walk straight past 2FA. Hence 1Password in the core tier and a blunt section in the checklist. **Guides over fake installs.** VRoid Studio, VTube Studio and Warudo are Steam titles; VSeeFace and VNyan are direct downloads. Rather than guess at package ids, `-VTuber` writes a guide naming the software and leaves the installing to a human. ## What it leaves behind His Desktop gets exactly three things: `START HERE.html`, and shortcuts for Collect Diagnostics and Monitor Connection. Long-form reference goes to `Documents\Rig Reference\` -- still inside Claude's scope so it can read it, but out of his way. ## Decisions already made Do not re-litigate these without a reason; the rationale is in the script. | | | |---|---| | Launchers | Steam and nothing else. No Epic/GOG/EA/Ubisoft, no Minecraft launcher — he does not play it | | Claude | Desktop app in core. Free tier is real, unlike 1Password's | | Claude file access | MCP filesystem server, scoped to OBS config + Desktop + Documents. **Never** `%APPDATA%` wholesale — that holds browser sessions and the 1Password data | | Password manager | 1Password, not Bitwarden. Paid with no free tier — he needs his own subscription or a seat on someone's Families plan, or this line is dead weight | | Browser | Chrome is the daily driver, Firefox moved to `-Preset full`. Setting the default is a manual click — Windows 11 blocks scripting it | | Tailscale | Installs always, logs in never (unless `-TailscaleAuthKey`) | | Telemetry | Required-only, and no further | | Fast Startup | Off. Hibernate itself left alone | | `-Preset` not `-Profile` | `$PROFILE` is a PowerShell automatic variable | ## Firewall Mostly verification, not configuration. A gaming box needs fewer inbound rules than people assume — games dial out, and the game servers live in AWS. Windows' default of block-inbound/allow-outbound is already right. The script checks all three profiles are on and defaulting to Block, fixes them if not, and enables dropped-packet logging to `pfirewall.log` so `collect-diagnostics.ps1` has evidence when something "won't connect". `-ObsWebSocket` is the one rule worth adding, and only if a Stream Deck or phone remote drives OBS. Scoped to the Private profile. The highest-value firewall advice is not scriptable, so it is in the streaming checklist: when a game pops the Windows firewall dialog, tick **Private**, never **Public**. ## Network monitoring The established tools come first, and the streaming checklist walks him through them in order: **OBS Stats dock** (separates network drops from encoder lag from render lag — nothing else matters until you know which), the **OBS Log Analyzer**, **Twitch Inspector**, **WinMTR/PingPlotter** for per-hop loss, and the **Waveform bufferbloat test**. Most of those are websites, so there is nothing to install. `monitor-connection.ps1` fills the one gap they leave: unattended logging over hours in a format Claude can read. It pings the default gateway **and** a public target at once, because pinging only 1.1.1.1 cannot tell a bad wifi link from a bad ISP. CSV to `Diagnostics\`, loss and p50/p95/max on Ctrl-C. It is step 6 of 6 in the checklist, not step 1. | What you see | What it means | |---|---| | gateway loss, internet clean | your wifi or cable — yours to fix | | gateway clean, internet loss | upstream, not your PC | | both clean, stream still bad | ingest server or encoder settings | Deliberately local-only. Shipping his metrics into the homelab VictoriaMetrics stack would mean joining him to the tailnet, which is a separate decision nobody has made — see the Tailscale row above. ## Claude's filesystem access `-SkipClaudeFs` turns this off entirely. Otherwise the script merges an MCP filesystem server into `%APPDATA%\Claude\claude_desktop_config.json`, scoped to five directories: the OBS config folder (scenes, profiles, logs — the thing that actually breaks), `Diagnostics\` (where the two helper scripts write), Downloads, Desktop, and Documents. The merge reads any existing config, backs it up to `.bak`, and adds or replaces only the `filesystem` key, so servers added later survive a re-run. **Why the scope is narrow.** The server writes as well as reads inside whatever it is given. `%APPDATA%` in full would include browser profiles, saved sessions and 1Password's local data — the same session tokens the streaming checklist exists to protect. And anything pasted into a chat is input: a config copied off a forum, or a "sponsor" document, is text acting with whatever access was granted. Narrow scope is the mitigation. Documents and Downloads are the loosest of the five — game saves live in one, and whatever he just downloaded lives in the other. Narrow the list with `-ClaudeDirs` if that is not a trade you want. ## Scripts must stay pure ASCII Windows PowerShell 5.1 decodes `.ps1` files as **cp1252** unless they carry a BOM. A UTF-8 em-dash (`e2 80 94`) then decodes to `a-circumflex, euro, U+201D` -- and that last character is a smart quote, which PowerShell treats as a **string delimiter**. Every em-dash inside a string silently terminated it early. This broke all four scripts at once: 39 parse errors in the big one. Nothing about the symptom points at encoding, so it cost a debugging round. Keep these files ASCII-only. Check before publishing: ```sh python3 -c "import glob,sys; sys.exit(any(b>127 for f in glob.glob('*.ps1') for b in open(f,'rb').read()))" ``` ## Verified, and how Checked on a real Windows 11 box (build 26200, PowerShell 5.1.26100, winget v1.29.290) on 2026-09-18: - All four scripts parse clean via `[Parser]::ParseFile` - Full `-DryRun` completes with exit code 0 and zero failures - All 26 winget ids probed with `winget show --id --exact` **`-DryRun` does not validate package ids** -- it only checks whether something is already installed. The ids need the `winget show` probe above, which is how these five were caught: | Wrong | Reality | |---|---| | `tailscale.tailscale` | `Tailscale.Tailscale` -- `--exact` is case-sensitive | | `Nvidia.App` | Not on winget at all | | `Nvidia.Broadcast` | Not on winget at all | | `AMD.AMDSoftwareAdrenalinEdition` | Not on winget at all | | `BlackmagicDesign.DaVinciResolve` | Not on winget at all | **Neither NVIDIA nor AMD publish driver software to winget. Only Intel does.** The script now detects the vendor and queues a manual download with a URL, printed at the end under "Download these by hand". It used to report a clean run while installing no driver software whatsoever. ## Known gaps - Only the `-DryRun` path has been executed. The real run has never been done on a clean machine -- registry writes, `Remove-AppxPackage` and the OneDrive uninstall are all still untested against a live system. - The Claude config path, its JSON schema, and whether `npx.cmd` or bare `npx` is the right command for a GUI-spawned MCP server on Windows are all unverified. If file access does not work, that config file is the first place to look. - `factorio.larryfargo.games` in `gaming/dns/main.tf:66` points at the *rimworld* Elastic IP and is confirmed leftover, so it is **not** in the cheat sheet. The Route53 record itself is still there — removing it is a separate tofu change nobody has approved yet.