* studio: add uninstall.ps1 and document it in README for Windows
The previous Windows uninstall guidance was Remove-Item -Recurse -Force on
$HOME\.unsloth\studio, which only deletes the install dir and leaves
behind:
* %LOCALAPPDATA%\Unsloth Studio (data dir)
* Desktop\Unsloth Studio.lnk (Desktop shortcut)
* %APPDATA%\Microsoft\Windows\Start Menu\Programs\Unsloth Studio.lnk
* Custom UNSLOTH_STUDIO_HOME / STUDIO_HOME roots
* Running unsloth_studio venv processes
* User PATH entry under .unsloth\studio
* HKCU\Software\Unsloth\PathBackup
This script mirrors uninstall.sh for Windows. It stops listening backends
by reading the port from share\studio.port (with a Win32_Process sweep
anchored on \unsloth_studio\ as a fallback), removes the install dir,
data dir, both shortcuts, the Studio PATH entry, and the PathBackup
registry key. Custom roots discovered from env vars or share\studio.conf
are accepted only if they contain a Studio sentinel (share\studio.conf,
unsloth_studio\.unsloth-studio-owned, or bin\unsloth.exe) and are not
on a hard deny list (drive root, %USERPROFILE%, parent of %USERPROFILE%,
or top-level system paths).
README now points Windows users at the script.
* Scope port-file kill and PATH cleanup to known Studio roots for PR #5513
Three findings from the reviewer round:
1. _StopByPortFile killed whatever owned the recorded port without proving
the PID belonged to this Studio install. A stale studio.port pointing
at a port a different local service later bound would force-kill that
service. New _PidUnderKnownRoot checks the listening PID's exe path
against the same $KnownRoots that _StopStudioProcesses already uses.
2. The netstat.exe fallback matched ":$port " anywhere in the line, so a
stale port file with 443 (or any common port) could match an
ESTABLISHED row whose remote endpoint was that port, killing an
unrelated process (browser, IDE). Now requires the row contain
LISTENING, and applies the same _PidUnderKnownRoot ownership check.
3. PATH cleanup removed any entry whose expanded path contained
\unsloth_studio\, which would also clobber an unrelated user virtualenv
that shared the name. Now only removes entries that resolve inside a
known Studio root (default %USERPROFILE%\.unsloth\studio plus any
custom roots discovered from UNSLOTH_STUDIO_HOME / STUDIO_HOME /
share\studio.conf).
* Expand tilde and honor UNSLOTH_STUDIO_HOME precedence for PR #5513
Two findings from the latest review round:
1. install.ps1 (lines 152-154) expands ~ and ~\path to $env:USERPROFILE
before resolving the install root, but uninstall.ps1 was passing the
raw env value to [System.IO.Path]::GetFullPath. That resolved ~\foo
relative to the current directory rather than the user profile, so a
user who installed with UNSLOTH_STUDIO_HOME='~\custom' could not
uninstall through the same variable. New _ExpandTilde helper matches
install.ps1's behavior.
2. Mirror install.ps1's env-var precedence: UNSLOTH_STUDIO_HOME wins,
STUDIO_HOME is ignored when both are set. Otherwise uninstalling
install A could also touch install B if the user has a stale
STUDIO_HOME pointing at B.
---------
Co-authored-by: Daniel Han <info@unsloth.ai>