Update Install Scripts (#5968)

* Update Install Scripts

Add SPDX AGPL-3.0 headers to the installer scripts and let the piped web
installs take their common options from the environment.

- install.sh / install.ps1: read UNSLOTH_NO_TORCH (and UNSLOTH_PYTHON for
  install.sh) so a piped install needs no positional flags. Flags and the
  pipe forms still work; an explicit flag wins.
- Fix the UNSLOTH_STUDIO_HOME example so the variable sits after the pipe
  and reaches sh instead of curl.
- Add SPDX headers to install.sh, install.ps1, the uninstall scripts, and
  the MLX install scripts.
- Drop the internal test package names from the studio install comments.

* Mirror UNSLOTH_PYTHON env var to install.ps1

install.ps1 now reads UNSLOTH_PYTHON to pin the Python version, matching
install.sh, and lists all three env vars (UNSLOTH_NO_TORCH, UNSLOTH_PYTHON,
UNSLOTH_STUDIO_HOME) in the header examples. The requested version is
preferred during detection and used as the winget install target; behavior
is unchanged when the variable is unset.
This commit is contained in:
Daniel Han 2026-06-03 05:39:42 -07:00 committed by GitHub
parent 92e7563fa2
commit c6e86d5e77
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 58 additions and 26 deletions

View file

@ -1,14 +1,20 @@
# Unsloth Studio Installer for Windows PowerShell
# Usage: irm https://raw.githubusercontent.com/unslothai/unsloth/main/install.ps1 | iex
# Local: Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; .\install.ps1 --local
# NoTorch: .\install.ps1 --no-torch (skip PyTorch, GGUF-only mode)
# Test: .\install.ps1 --package roland-sloth
#
# Env vars (priority: UNSLOTH_STUDIO_HOME > STUDIO_HOME > USERPROFILE-redirect > default):
# UNSLOTH_STUDIO_HOME / STUDIO_HOME = path -> install under that path
# (DataDir nests inside; user PATH not modified persistently).
# Default ($USERPROFILE\.unsloth\studio) is preserved when no env var is set.
# Usage: irm https://unsloth.ai/install.ps1 | iex
# Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; .\install.ps1 --local
#
# irm | iex cannot forward arguments, so web installs take options as env vars set
# before the pipe (flags still work via .\install.ps1):
# $env:UNSLOTH_NO_TORCH=1; irm https://unsloth.ai/install.ps1 | iex # skip PyTorch (GGUF-only)
# $env:UNSLOTH_PYTHON='3.12'; irm https://unsloth.ai/install.ps1 | iex # pin Python version
# $env:UNSLOTH_STUDIO_HOME='C:\path'; irm https://unsloth.ai/install.ps1 | iex
# .\install.ps1 --no-torch # equivalent flag
# Or pass flags to a scriptblock: & ([scriptblock]::Create((irm https://unsloth.ai/install.ps1))) --no-torch
#
# Install dir priority: UNSLOTH_STUDIO_HOME > STUDIO_HOME (alias) > $USERPROFILE\.unsloth\studio
#
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
function Install-UnslothStudio {
$ErrorActionPreference = "Stop"
$script:UnslothVerbose = ($env:UNSLOTH_VERBOSE -eq "1")
@ -112,6 +118,10 @@ function Install-UnslothStudio {
}
}
}
# Env-var equivalent for web installs; an explicit flag still wins.
if ($env:UNSLOTH_NO_TORCH -in @('1', 'true', 'yes', 'on')) { $SkipTorch = $true }
# Propagate to child processes so they also respect verbose mode.
# Process-scoped -- does not persist.
if ($script:UnslothVerbose) {
@ -132,7 +142,8 @@ function Install-UnslothStudio {
return (Exit-InstallFailure "--package name contains invalid characters")
}
$PythonVersion = "3.13"
# UNSLOTH_PYTHON pins the version (mirrors install.sh --python); default 3.13.
$PythonVersion = if ($env:UNSLOTH_PYTHON) { $env:UNSLOTH_PYTHON } else { "3.13" }
# Resolve install destinations. Priority: UNSLOTH_STUDIO_HOME, then
# STUDIO_HOME alias, then USERPROFILE-redirect, then default.
@ -935,7 +946,9 @@ shell.Run cmd, 0, False
# py.exe resolves to the standard CPython install, not conda.
$pyLauncher = Get-Command py -CommandType Application -ErrorAction SilentlyContinue
if ($pyLauncher -and $pyLauncher.Source -notmatch $script:CondaSkipPattern) {
foreach ($minor in @("3.13", "3.12", "3.11")) {
# Prefer the requested $PythonVersion, then newest-first fallback.
$minors = @($PythonVersion) + (@("3.13", "3.12", "3.11") | Where-Object { $_ -ne $PythonVersion })
foreach ($minor in $minors) {
try {
$out = & $pyLauncher.Source "-$minor" --version 2>&1 | Out-String
if ($out -match "Python (3\.1[1-3])\.\d+") {

View file

@ -1,17 +1,22 @@
#!/bin/sh
# Unsloth Studio Installer
# Usage (curl): curl -fsSL https://unsloth.ai/install.sh | sh
# Usage (wget): wget -qO- https://unsloth.ai/install.sh | sh
# Usage (local): ./install.sh --local (install from local repo instead of PyPI)
# Usage (no-torch): ./install.sh --no-torch (skip PyTorch, GGUF-only mode)
# Usage (test): ./install.sh --package roland-sloth (install a different package name)
# Usage (py): ./install.sh --python 3.12 (override auto-detected Python version)
#
# Env vars (priority: UNSLOTH_STUDIO_HOME > STUDIO_HOME > HOME-redirect > default):
# UNSLOTH_STUDIO_HOME=/abs/path -> install under that path
# STUDIO_HOME=/abs/path -> alias, same effect (UNSLOTH_STUDIO_HOME wins)
# (DATA_DIR + unsloth CLI shim nest inside; no shell rc-file append.)
# Default ($HOME/.unsloth/studio) is preserved when no env var is set.
# Unsloth Studio Installer
#
# Usage: curl -fsSL https://unsloth.ai/install.sh | sh
# wget -qO- https://unsloth.ai/install.sh | sh
# ./install.sh --local (install from a cloned repo instead of PyPI)
#
# Piped installs take options as env vars after the pipe (a bare `| sh --no-torch`
# makes sh reject --no-torch as its own option). Flags still work via ./install.sh:
# curl -fsSL https://unsloth.ai/install.sh | UNSLOTH_NO_TORCH=1 sh # skip PyTorch (GGUF-only)
# curl -fsSL https://unsloth.ai/install.sh | UNSLOTH_PYTHON=3.12 sh # pin Python version
# curl -fsSL https://unsloth.ai/install.sh | UNSLOTH_STUDIO_HOME=/abs/path sh
# Equivalent flags: ./install.sh --no-torch --python 3.12 (or pipe them: sh -s -- --no-torch)
#
# Install dir priority: UNSLOTH_STUDIO_HOME > STUDIO_HOME (alias) > $HOME/.unsloth/studio
#
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
set -e
# ── Output style (aligned with studio/setup.sh) ──
@ -70,6 +75,10 @@ for arg in "$@"; do
esac
done
# Env-var equivalents for piped installs; an explicit flag still wins.
case "${UNSLOTH_NO_TORCH:-}" in 1|true|TRUE|yes|YES|on|ON) _NO_TORCH_FLAG=true ;; esac
[ -z "$_USER_PYTHON" ] && [ -n "${UNSLOTH_PYTHON:-}" ] && _USER_PYTHON="$UNSLOTH_PYTHON"
if [ "$_VERBOSE" = true ]; then
export UNSLOTH_VERBOSE=1
fi

View file

@ -1,4 +1,6 @@
#!/bin/bash
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
set -euo pipefail
# ============================================================

View file

@ -1,4 +1,6 @@
#!/bin/bash
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
set -euo pipefail
# ============================================================

View file

@ -1,3 +1,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
#
# Unsloth Studio uninstaller for Windows PowerShell.
# Stops running servers and removes install dir, launcher data, CLI shim,
# desktop and Start Menu shortcuts, the user PATH entry, and the PathBackup

View file

@ -1,4 +1,7 @@
#!/usr/bin/env sh
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
#
# Unsloth Studio uninstaller (macOS / Linux / WSL).
# Stops running servers and removes install dir, launcher data,
# CLI shim, desktop shortcut, .app bundle, and Launch Services entry.

View file

@ -1406,7 +1406,7 @@ def install_python_stack() -> int:
# When called from "unsloth studio update", it is NOT set so base packages
# (unsloth + unsloth-zoo) are always reinstalled to pick up new versions.
skip_base = os.environ.get("SKIP_STUDIO_BASE", "0") == "1"
# When --package is used, install a different package name (e.g. roland-sloth for testing)
# When --package is used, install a different package name (for testing)
package_name = os.environ.get("STUDIO_PACKAGE_NAME", "unsloth")
# When --local is used, overlay a local repo checkout after updating deps
local_repo = os.environ.get("STUDIO_LOCAL_REPO", "")
@ -1565,7 +1565,7 @@ def install_python_stack() -> int:
constrain = False,
)
elif package_name != "unsloth":
# Custom package name (e.g. roland-sloth for testing) — install directly
# Custom package name (for testing), install directly
_progress("base packages")
pip_install(
f"Installing {package_name}",

View file

@ -2016,7 +2016,7 @@ if ($env:SKIP_STUDIO_BASE -ne "1" -and $env:STUDIO_LOCAL_INSTALL -ne "1") {
# # the fresh .venv. Install it so run_install() can find its modules
# # and bundled requirements files.
# Write-Host " Installing package into venv..." -ForegroundColor Cyan
# pip install unsloth-roland-test 2>&1 | Out-Null
# pip install unsloth 2>&1 | Out-Null
# }
if (-not $SkipPythonDeps) {