Move uninstall scripts into scripts/ and fix references (#5644)

* Move uninstall scripts into scripts/ and fix all references

Relocates `uninstall.sh` and `uninstall.ps1` from the repo root into
the existing `scripts/` directory, alongside the other helper scripts.

Reference fixes:
* `README.md`: Studio uninstall instructions now point at the raw
  GitHub URLs under `scripts/`. The previous `unsloth.ai/uninstall.*`
  short URLs currently 404 (unlike `unsloth.ai/install.sh`, which
  301s to the raw github URL), so the raw URL is the working entry
  point until that redirect is configured.
* `scripts/uninstall.sh` header `Usage:` example updated to the new
  raw GitHub path.
* `scripts/uninstall.ps1` header `Usage:` example updated to the new
  raw GitHub path.
* `.github/workflows/studio-update-smoke.yml`: `paths:` trigger and
  round-trip exec/exists checks now use `scripts/uninstall.sh`.
* `.github/workflows/studio-mac-update-smoke.yml`: same.
* `.github/workflows/studio-windows-update-smoke.yml`: `paths:`
  trigger and round-trip exec/exists checks now use
  `scripts/uninstall.ps1`.

The in-script help hints (e.g. `sh uninstall.sh`, `.\uninstall.ps1`)
are left unchanged because they are user-facing examples shown after
the user already has the file locally, and the basename form works
regardless of which directory the user downloaded the script into.

Follow-up note for unsloth.ai: once this lands, please add the
`unsloth.ai/uninstall.sh` and `unsloth.ai/uninstall.ps1` short-URL
redirects to `raw.githubusercontent.com/unslothai/unsloth/main/scripts/...`
(matching the existing `unsloth.ai/install.sh` redirect pattern).

* Update remaining uninstall script help hints for new scripts/ path

Three user-facing strings inside the uninstall scripts still showed
the old basename form, which became misleading after the move:

* `scripts/uninstall.ps1` header `# Local:` example: now references
  `.\scripts\uninstall.ps1` (the actual path from the cloned repo
  root).
* `scripts/uninstall.sh` env-var re-run hint: now shows the canonical
  curl-pipe form documented in README, since callers who came via
  `curl -fsSL ... | sh` never had a local `uninstall.sh` to invoke.
* `scripts/uninstall.ps1` env-var re-run hint: same, switched to the
  `irm ... | iex` form documented in README.

Pure string changes, no behavior change.

---------

Co-authored-by: Lee Jackson <130007945+Imagineer99@users.noreply.github.com>
This commit is contained in:
Daniel Han 2026-05-20 04:42:03 -07:00 committed by GitHub
commit a74a1080e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 39 additions and 38 deletions

View file

@ -21,7 +21,7 @@ on:
pull_request:
paths:
- 'install.sh'
- 'uninstall.sh'
- 'scripts/uninstall.sh'
- 'studio/setup.sh'
- 'studio/install_python_stack.py'
- 'studio/install_llama_prebuilt.py'
@ -139,20 +139,20 @@ jobs:
echo "post-update Studio /api/health OK"
- name: Uninstall and verify clean
# Round-trip through uninstall.sh on real macOS. As a side effect
# this exercises the macOS-only .app bundle + Launch Services
# Round-trip through scripts/uninstall.sh on real macOS. As a side
# effect this exercises the macOS-only .app bundle + Launch Services
# removal path (~/Applications/Unsloth Studio.app, lsregister -u)
# which is not testable from a Linux runner. Skips gracefully if
# uninstall.sh has not landed yet (lets this workflow merge
# scripts/uninstall.sh has not landed yet (lets this workflow merge
# before #5497).
run: |
set -o pipefail
if [ ! -f uninstall.sh ]; then
echo "uninstall.sh not present in this tree; skipping round-trip"
if [ ! -f scripts/uninstall.sh ]; then
echo "scripts/uninstall.sh not present in this tree; skipping round-trip"
: > logs/uninstall.log
exit 0
fi
sh uninstall.sh 2>&1 | tee logs/uninstall.log
sh scripts/uninstall.sh 2>&1 | tee logs/uninstall.log
leak=0
for p in \
"$HOME/.unsloth/studio" \
@ -166,8 +166,8 @@ jobs:
fi
done
[ "$leak" -eq 0 ] || exit 1
sh uninstall.sh 2>&1 | tail -5
sh uninstall.sh 2>&1 | tail -5
sh scripts/uninstall.sh 2>&1 | tail -5
sh scripts/uninstall.sh 2>&1 | tail -5
echo "PASS: mac install -> update -> uninstall round-trip clean"
- name: Upload update logs

View file

@ -15,7 +15,7 @@ on:
pull_request:
paths:
- 'install.sh'
- 'uninstall.sh'
- 'scripts/uninstall.sh'
- 'studio/setup.sh'
- 'studio/install_python_stack.py'
- 'studio/install_llama_prebuilt.py'
@ -141,22 +141,22 @@ jobs:
echo "post-update Studio /api/health OK"
- name: Uninstall and verify clean
# Round-trip the installer through uninstall.sh: confirms the
# Round-trip the installer through scripts/uninstall.sh: confirms the
# uninstaller actually finds and removes everything install.sh +
# update wrote. Safety-guard scenarios (refuse-$HOME etc.) belong
# in a separate fast smoke job; this is the happy-path cleanup
# assertion that catches regressions where install.sh starts
# writing to a new location and uninstall.sh hasn't caught up.
# Skips gracefully if uninstall.sh has not landed yet (lets this
# workflow merge before #5497).
# writing to a new location and scripts/uninstall.sh hasn't caught up.
# Skips gracefully if scripts/uninstall.sh has not landed yet (lets
# this workflow merge before #5497).
run: |
set -o pipefail
if [ ! -f uninstall.sh ]; then
echo "uninstall.sh not present in this tree; skipping round-trip"
if [ ! -f scripts/uninstall.sh ]; then
echo "scripts/uninstall.sh not present in this tree; skipping round-trip"
: > logs/uninstall.log
exit 0
fi
sh uninstall.sh 2>&1 | tee logs/uninstall.log
sh scripts/uninstall.sh 2>&1 | tee logs/uninstall.log
leak=0
for p in \
"$HOME/.unsloth/studio" \
@ -171,8 +171,8 @@ jobs:
done
[ "$leak" -eq 0 ] || exit 1
# Idempotent: re-runs exit 0 on an empty $HOME.
sh uninstall.sh 2>&1 | tail -5
sh uninstall.sh 2>&1 | tail -5
sh scripts/uninstall.sh 2>&1 | tail -5
sh scripts/uninstall.sh 2>&1 | tail -5
echo "PASS: install -> update -> uninstall round-trip clean"
- name: Upload update logs

View file

@ -23,7 +23,7 @@ on:
pull_request:
paths:
- 'install.ps1'
- 'uninstall.ps1'
- 'scripts/uninstall.ps1'
- 'studio/setup.ps1'
- 'studio/setup.bat'
- 'studio/install_python_stack.py'
@ -268,21 +268,22 @@ jobs:
echo "post-update Studio /api/health OK"
- name: Uninstall and verify clean
# Round-trip through uninstall.ps1 against the default install
# tree at %USERPROFILE%\.unsloth\studio. Catches regressions
# where install.ps1 starts writing under a new key (registry,
# Start Menu, %APPDATA%) and uninstall.ps1 has not been updated
# to match. Skips gracefully if uninstall.ps1 has not landed yet
# (lets this workflow merge before #5513).
# Round-trip through scripts/uninstall.ps1 against the default
# install tree at %USERPROFILE%\.unsloth\studio. Catches
# regressions where install.ps1 starts writing under a new key
# (registry, Start Menu, %APPDATA%) and scripts/uninstall.ps1 has
# not been updated to match. Skips gracefully if
# scripts/uninstall.ps1 has not landed yet (lets this workflow
# merge before #5513).
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path logs | Out-Null
if (-not (Test-Path "$PWD\uninstall.ps1")) {
Write-Host "uninstall.ps1 not present in this tree; skipping round-trip"
if (-not (Test-Path "$PWD\scripts\uninstall.ps1")) {
Write-Host "scripts/uninstall.ps1 not present in this tree; skipping round-trip"
"" | Set-Content logs/uninstall.log
exit 0
}
pwsh -NoProfile -File "$PWD\uninstall.ps1" *>&1 | Tee-Object -FilePath logs/uninstall.log
pwsh -NoProfile -File "$PWD\scripts\uninstall.ps1" *>&1 | Tee-Object -FilePath logs/uninstall.log
$leak = 0
foreach ($p in @(
"$env:USERPROFILE\.unsloth\studio",
@ -296,8 +297,8 @@ jobs:
}
if ($leak -gt 0) { exit 1 }
# Idempotency.
pwsh -NoProfile -File "$PWD\uninstall.ps1" *>&1 | Select-Object -Last 5
pwsh -NoProfile -File "$PWD\uninstall.ps1" *>&1 | Select-Object -Last 5
pwsh -NoProfile -File "$PWD\scripts\uninstall.ps1" *>&1 | Select-Object -Last 5
pwsh -NoProfile -File "$PWD\scripts\uninstall.ps1" *>&1 | Select-Object -Last 5
Write-Host "PASS: windows install -> update -> uninstall round-trip clean"
- name: Upload update logs

View file

@ -220,8 +220,8 @@ unsloth studio -p 8888
#### Uninstall
The recommended way to fully remove Unsloth Studio is the matching uninstall script for your OS. It stops any running servers, removes the install dir, the launcher data dir, the desktop shortcut, and any platform-specific entries (macOS `.app` bundle + Launch Services on Mac; Start Menu, `HKCU\Software\Unsloth` registry key and user `PATH` entries on Windows):
* **MacOS, WSL, Linux:** `curl -fsSL https://unsloth.ai/uninstall.sh | sh`
* **Windows (PowerShell):** `irm https://unsloth.ai/uninstall.ps1 | iex`
* **MacOS, WSL, Linux:** `curl -fsSL https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.sh | sh`
* **Windows (PowerShell):** `irm https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.ps1 | iex`
If you only want to drop the install dir and keep the launcher/shortcut for a later reinstall, you can instead run `rm -rf ~/.unsloth/studio` (Mac/Linux/WSL) or `Remove-Item -Recurse -Force "$HOME\.unsloth\studio"` (Windows). The model cache at `~/.cache/huggingface` is not touched by any of these.

View file

@ -4,8 +4,8 @@
# registry key. Honors custom roots set via UNSLOTH_STUDIO_HOME / STUDIO_HOME
# at install time (read back from share\studio.conf).
#
# Usage: irm https://raw.githubusercontent.com/unslothai/unsloth/main/uninstall.ps1 | iex
# Local: Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; .\uninstall.ps1
# Usage: irm https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.ps1 | iex
# Local: Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; .\scripts\uninstall.ps1
function Uninstall-UnslothStudio {
$ErrorActionPreference = "Continue"
@ -345,7 +345,7 @@ function Uninstall-UnslothStudio {
Write-Host "If you installed Unsloth Studio with UNSLOTH_STUDIO_HOME or STUDIO_HOME"
Write-Host "pointing at a custom directory, re-run this script with the same variable"
Write-Host "set to also remove that install tree, e.g.:"
Write-Host " `$env:UNSLOTH_STUDIO_HOME = 'C:\your\path'; .\uninstall.ps1"
Write-Host " `$env:UNSLOTH_STUDIO_HOME = 'C:\your\path'; irm https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.ps1 | iex"
}
}

View file

@ -5,7 +5,7 @@
# Honors custom roots set via UNSLOTH_STUDIO_HOME / STUDIO_HOME at
# install time (read back from studio.conf).
#
# Usage: curl -fsSL https://unsloth.ai/uninstall.sh | sh
# Usage: curl -fsSL https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.sh | sh
set -e
@ -279,5 +279,5 @@ if [ -z "${UNSLOTH_STUDIO_HOME:-}" ] && [ -z "${STUDIO_HOME:-}" ]; then
echo "If you installed Unsloth Studio with UNSLOTH_STUDIO_HOME or STUDIO_HOME"
echo "pointing at a custom directory, re-run this script with the same variable"
echo "set to also remove that install tree, e.g.:"
echo " UNSLOTH_STUDIO_HOME=/your/path sh uninstall.sh"
echo " UNSLOTH_STUDIO_HOME=/your/path sh -c \"\$(curl -fsSL https://raw.githubusercontent.com/unslothai/unsloth/main/scripts/uninstall.sh)\""
fi