name: windows-pc description: >- Drive James's Windows PC (supedupsilly) from this Mac: shell work over SSH (specs, winget installs, git, Unreal Windows packaging, files, services) and desktop work through the C:\desk agent (screenshots, mouse, keyboard, window focus) once it is installed. Use for any task that has to run or be seen on the PC. Not for the PC's own Claude Code session's work; coordinate with it on the Linear issue instead of both driving the same desktop.
windows-pc
The PC is supedupsilly: Windows 11 Pro, i9-14900KF (24C/32T), 32 GB, RTX 4080
SUPER, 2560×1440, ~675 GB free on C:. User volpe, logged in on the console
session. Reach it as ssh volpe@supedupsilly (Tailscale 100.108.214.60; LAN
192.168.4.123). Key auth from this Mac's ~/.ssh/id_ed25519 is installed in
C:\Users\volpe\.ssh\authorized_keys. Tracker home: VUH-1194.
Shell work: pc.sh
~/.claude/skills/windows-pc/pc.sh 'Get-PSDrive C | Select-Object Free,Used'
~/.claude/skills/windows-pc/pc.sh -f setup.ps1
PC_TIMEOUT=1800 ~/.claude/skills/windows-pc/pc.sh 'winget install --id Git.Git --silent --accept-package-agreements --accept-source-agreements'
pc.sh ships the PowerShell text as -EncodedCommand, so write ordinary
PowerShell: $vars, pipes, quotes and backslashes all survive. Plain
ssh volpe@supedupsilly '<cmd>' lands in cmd.exe, not PowerShell; anything
beyond whoami/ver/dir wants the wrapper. Output has \r stripped and the
CLIXML progress noise filtered.
Probe the toolchain before assuming its state; installs change it:
& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -property displayName,installationVersion
Get-ChildItem 'C:\Program Files\Epic Games' # engines appear as UE_5.x
Get-Command git,python -ErrorAction SilentlyContinue | Select-Object Source
query session # console must show volpe Active for desktop work
Desktop work: desk.sh
SSH sessions have no screen. The bridge is a scheduled task, desk-agent,
registered with an Interactive logon for volpe so it runs inside the console
session; it polls C:\desk\jobs\*.ps1, runs each with C:\desk\lib.ps1
loaded, and writes C:\desk\done\<job>.out. desk.sh drops a job and waits.
~/.claude/skills/windows-pc/desk.sh install # deploy lib.ps1 + agent.ps1, register and start the task
~/.claude/skills/windows-pc/desk.sh 'Windows' # every window: process, x,y, w×h, title
~/.claude/skills/windows-pc/desk.sh shot out.png # full-screen PNG pulled to this Mac; Read it
~/.claude/skills/windows-pc/desk.sh 'Focus "Epic Games"; Click 1200 700; Type "5.8"; Key "{ENTER}"'
lib.ps1 must define: Screenshot [path], MouseMove x y, Click x y [right] [times],
Scroll n, Type text and Key keys (SendKeys syntax: {ENTER}, ^c, %{F4}),
Windows, Focus titlePart, Launch path [args]. Implementation notes for
whoever writes it: call SetProcessDPIAware first or screenshots and clicks
land at 2/3 scale; System.Drawing CopyFromScreen for shots, user32
SetCursorPos/mouse_event for the mouse, SendKeys.SendWait for typing.
The task needs ExecutionTimeLimit zero and MultipleInstances IgnoreNew,
RunLevel Limited (no UAC), trigger AtLogOn so it survives reboots.
Always shot before and after a click sequence and Read both; coordinates are
screen pixels at 2560×1440, and a wrong click on a live desktop is not undone
by the next one. If the console shows Disc or a lock screen, the agent has no
input to inject: ask James to unlock rather than retrying.
Long jobs
The SSH session dies with this Mac's command and takes its children with it. For anything over a few minutes (VS install, engine build, cook, package):
Start-Process -FilePath powershell -ArgumentList '-NoProfile','-File','C:\jobs\build.ps1' -RedirectStandardOutput 'C:\jobs\build.log' -RedirectStandardError 'C:\jobs\build.err' -WindowStyle Hidden
then poll Get-Content C:\jobs\build.log -Tail 20 on later calls. Write the
job's exit code into its log yourself; a detached process has no other channel
back. Keep PC_TIMEOUT on the poll, not on the job.
That Start-Process line has been observed starting nothing: the job script was
written, both redirect files appeared at 0 bytes and never grew, and the work
never happened — silently, because a detached process that dies has no channel
to report on. Check the job's own side effect (its output directory, not just
its log) before believing it is running. The reliable fallback is to keep the
session open from this Mac rather than detaching:
nohup env PC_TIMEOUT=3600 pc.sh -f job.ps1 > local.log 2>&1 &
It lives as long as the Mac-side background task and streams progress into
local.log. A 4 GB LFS clone finished that way in 4.5 minutes after the
detached form silently did nothing.
Gotchas that cost real attempts
- Stop it sleeping before anything else, every session. A sleeping PC is not
reachable and cannot be woken remotely as configured (see WOL below), so a lost
afternoon starts here. First command on contact:
powercfg -change -standby-timeout-ac 0andpowercfg -change -hibernate-timeout-ac 0, then read the active scheme back rather than trusting the exit code —powercfg /query SCHEME_CURRENT SUB_SLEEP, whereCurrent AC Power Setting Index: 0x00000000is never. Both read 0 as of 2026-09-10. It is per-scheme, so it reverts if the active plan changes. - Wake-on-LAN will not actually wake it as configured.
WakeOnMagicPacketis Enabled on both adapters, butHiberbootEnabled=1— Windows fast startup — turns a full shutdown into a hibernate that WOL does not fire from. The live adapter is also Wi-Fi (Intel AX211,C8-58-B3-2F-B9-D0); the Realtek 2.5GbE Ethernet readsDisconnected, so a magic packet aimed at88-AE-DD-71-FE-07reaches nothing. Until fast startup is off, waking it still means asking James. - Try the LAN address before Tailscale; they fail independently. On 2026-09-10
192.168.4.123answered while100.108.214.60did not.PC_HOSToverrides the default:PC_HOST=volpe@192.168.4.123 pc.sh '...'. - A new address means a new host key, and
BatchModeturns that intoHost key verification failed. Do not reach forStrictHostKeyChecking=no. Compare what the address offers against the key already trusted for the name and only then add it:ssh-keyscan -T 6 -t ed25519,rsa <addr>againstssh-keygen -F supedupsilly. Identical base64 on every shared key type is the same machine, and appending the scan toknown_hostsis then safe. - Key rejected with
Permission denied (publickey,...)although the key is installed. Windows sshd readsadministrators_authorized_keysonly whilesshd_config'sMatch Group administratorsblock is active; on this PC it is commented out, so the per-user file is the one that counts. Check the block before deciding where a key goes. Anyecho ... >>orOut-Filein Windows PowerShell writes UTF-16, which sshd cannot parse; write keys with[IO.File]::WriteAllText($f, $k + "n", [Text.Encoding]::ASCII)`. - Finding the PC when the name does not resolve:
arp -ais empty inside this Mac's sandbox, so sweepnc -z -G 1 192.168.4.N 22across the /24 and read banners withnc; Windows answersSSH-2.0-OpenSSH_for_Windows_*. - The auto-mode classifier refuses desktop actions unless an allow rule
covers them:
desk.sh shot,chmod +xon these scripts and SSH loops that try several usernames all got blocked on 2026-09-09 even with James's spoken authorization. The rule that clears it, in the project's.claude/settings.local.jsonpermissions.allow:"Bash(zsh ~/.claude/skills/windows-pc/desk.sh:*)"and"Bash(zsh ~/.claude/skills/windows-pc/pc.sh:*)". Invoke the scripts aszsh <path>so the rule matches;desk.sh installdeploysdesktop/lib.ps1anddesktop/agent.ps1from this skill and (re)registers the task. - The build machine is not the play machine. Package on the PC, ship the ZIP; James and friends run it on their own PCs, like the Mac ZIPs.
- Unreal has no Windows-from-Mac path (Epic's cross-compile is Windows→Linux only, and Remote Windows Deployment needs a Windows host), which is the whole reason this PC exists.
Evidence
Retain the Windows package receipt the same way as the Mac one: tested
revision, four phase exits, startup log, one inspected first frame, ZIP size
and sha256, on the issue with launch steps. Load grapple-native-proof for the
repo's evidence rules before claiming a Windows result.
