Commit graph

1 commit

Author SHA1 Message Date
Daniel Han
47167885b0
studio: add uninstall.ps1 for Windows (#5513)
* 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>
2026-05-18 02:32:24 -07:00