* Fix Windows installer Python detection and winget error handling
The PowerShell installer crashes on some Windows machines due to two
issues:
1. Windows Store App Execution Aliases: Get-Command finds the stub at
WindowsApps\python.exe, then python --version writes to stderr.
With $ErrorActionPreference = "Stop" on PowerShell 5.1, stderr
from native commands becomes a terminating error, killing the
script before it tries to install Python.
2. winget "already installed" exit code: winget returns -1978335189
(APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE) when the package is
already at the latest version. The script treated any non-zero exit
as failure. The fallback Get-Command check could also find the
Store stub or fail if Python was partially uninstalled.
Changes:
- Add Find-CompatiblePython helper that tries the py launcher first,
then python3/python via Get-Command -All, explicitly skipping any
WindowsApps stubs. All invocations wrapped in try-catch so stderr
never triggers ErrorActionPreference.
- Replace exit-code-based winget error handling with outcome-based:
re-detect Python after install, retry with --force if not found,
show actionable manual install instructions on final failure.
- Deduplicate PATH entries in Refresh-SessionPath to prevent unbounded
growth from repeated machine+user path prepending.
* Address reviewer feedback: wrap winget calls, remove blanket WindowsApps filter
Three fixes based on code review:
1. Wrap all winget install calls in $ErrorActionPreference = "Continue"
blocks so that winget stderr (progress bars, warnings) does not
become a terminating error on PowerShell 5.1. This matches the
pattern already used in studio/setup.ps1 line 983.
2. Remove the blanket *\WindowsApps\* path filter that rejected all
WindowsApps executables including valid Microsoft Store Python
installs. Instead, rely on the existing try-catch + version regex
probing to determine if a candidate is functional. Non-functional
entries (App Execution Alias stubs) fail the try-catch and are
skipped naturally.
3. Use $pyLauncher.Source (resolved path) instead of bare py name,
add -CommandType Application to avoid matching aliases/functions,
and derive winget package ID from $PythonVersion variable instead
of hardcoding Python.Python.3.13.
* Add back WindowsApps filter for python3/python fallback path
The App Execution Alias stubs in WindowsApps can open the Microsoft
Store as a side effect when invoked, even though the try-catch handles
the error. Since the py launcher (tried first) already detects
legitimate Store Python -- Store packages include py since Python
3.11 -- filtering WindowsApps in the python3/python fallback is safe
and avoids the Store popup.
---------
Co-authored-by: Daniel Han <danielhanchen@users.noreply.github.com>
* fix(install.ps1): detect AMD/no-NVIDIA GPU early and guard unsloth.exe existence
When a user has an AMD GPU (no nvidia-smi), uv's --torch-backend=auto
resolves to CPU torch, which constrains the solver to unsloth==2024.8.
That ancient release has no unsloth.exe CLI entry point, so the subsequent
& \ studio setup call throws a confusing PowerShell
'module could not be loaded' CommandNotFoundException instead of a
clear error.
Two fixes:
- Detect nvidia-smi early; if no NVIDIA GPU is found, print a clear
error explaining AMD/Intel GPUs are unsupported and exit before
wasting time installing the wrong package version.
- Guard Test-Path \ before invoking it, so any future case
where the CLI entry point is missing produces a readable error
instead of a cryptic PowerShell exception.
Fixes: unsloth_studio\Scripts\unsloth.exe CommandNotFoundException
on AMD GPU systems (Windows).
* fix(install.ps1): correct GPU support message - AMD is Linux-only via ROCm
* Slim down to just the unsloth.exe existence guard
Remove the early NVIDIA GPU detection gate -- Studio supports Windows
and Mac without a GPU (finetuning is simply disabled). The GPU gate
was blocking legitimate non-NVIDIA users from installing.
Keep only the Test-Path guard on unsloth.exe before invoking it. This
turns the confusing PowerShell CommandNotFoundException into a clear
error message pointing at the likely cause (older unsloth version
resolved by the package solver that does not include the Studio CLI).
* Fix quickstart link in unsloth.exe guard message
---------
Co-authored-by: LeoBorcherding <LeoBorcherding@users.noreply.github.com>
Co-authored-by: Daniel Han <danielhanchen@gmail.com>
* One liner setup for unsloth studio
* Fix install scripts: system deps, activation bugs, curl/wget support
- install.sh: detect platform (macOS/Linux/WSL) and check for missing
system dependencies (cmake, git, build-essential, libcurl4-openssl-dev).
Prompt user once for permission to install all missing packages via
brew (macOS) or sudo apt-get (Linux/WSL). Add wget fallback via
download() helper since curl is not always present on minimal Linux
installs. Fix nested curl|sh stdin stealing by downloading uv installer
to a tempfile first. Replace venv activation (no-op in a pipe subshell)
with explicit --python flag for uv pip install and direct venv binary
invocation. Add idempotency guard for venv creation. Redirect stdin
on unsloth studio setup to prevent pipe consumption. On macOS, check
for Xcode Command Line Tools and trigger install if missing.
- install.ps1: wrap script body in Install-UnslothStudio function so
that errors use return instead of exit (exit kills the terminal when
run via irm|iex). Remove activate.ps1 invocation entirely -- use
explicit --python path for uv pip install and & $UnslothExe for
studio setup. This avoids both the child-scope activation bug (& vs
dot-source) and the execution policy error on default Windows systems.
Add winget availability check with clear error message. Fix PATH
refresh to append registry paths instead of replacing the session PATH.
Add uv installer fallback via astral.sh PowerShell script if winget
install does not put uv on PATH. Broaden Python version check to
accept 3.11-3.13. Add idempotency guard for venv creation.
- README.md: add wget one-liner alternative for systems without curl.
* Fix Tailwind CSS v4 .gitignore bug on Windows (#4444)
- Add .gitignore hiding workaround to setup.ps1 (matching existing
setup.sh logic) so venv .gitignore files containing "*" don't prevent
Tailwind's oxide scanner from finding .tsx source files
- Add CSS size validation to setup.sh, setup.ps1, and build.sh to catch
truncated Tailwind builds early
- Remove stray force-rebuild overrides that made the "skip build if
current" cache check dead code in both setup scripts
- Add rm -rf dist to build.sh to force clean rebuilds for wheel packaging
* Change default port 8000 to 8888, fix installer bugs, improve UX
- Change default Studio port from 8000 to 8888 across all entry points
(run.py, studio.py, ui.py, colab.py, vite.config.ts, setup scripts)
- Update launch banner: "Launching with studio venv..." to
"Launching Unsloth Studio... Please wait..."
- Add "Open your web browser" banner and rename labels
(Local -> Local Access, External -> Worldwide Web Address)
- Fix venv idempotency: check for bin/python instead of just directory
existence, clean up partial venvs on retry
- Fix build.sh CSS validation: handle empty CSS case that silently
bypassed the check with "integer expression expected"
- Fix install.sh sudo handling: try apt-get without sudo first (works
when root), then escalate with per-package tracking and user prompt
- Fix install.ps1: check exit code from studio setup, fail on error
- Add pciutils to WSL GGUF build dependencies
- Apply same smart apt-get escalation pattern to studio/setup.sh
* Use detected Python version for venv, abort on non-apt Linux
- install.ps1: detect existing Python 3.11/3.12/3.13 and use that
version for venv creation instead of always forcing 3.13
- install.sh: exit with error on non-apt Linux distros when required
packages cannot be auto-installed, instead of silently continuing
* Make sudo permission prompt more prominent with warning banner
* Add Accept [Y/n] sudo prompt to studio/setup.sh for consistency
* Fix native command exit code handling and sudo decline flow
install.ps1: Add $LASTEXITCODE checks after winget (Python), uv venv,
and uv pip install calls. $ErrorActionPreference only catches PowerShell
cmdlet errors, not native executable failures. The Python check also
handles winget returning non-zero for "already installed".
setup.sh: Skip llama-server build when user declines sudo or sudo is
unavailable. Previously the script continued to section 8 which would
fail with confusing errors (e.g. "gcc: command not found") since
build-essential was never installed.
* Move rm -rf llama.cpp inside build branch to preserve existing install
When _SKIP_GGUF_BUILD is set (user declined sudo or sudo unavailable),
the previous rm -rf would destroy an already-working llama-server before
the skip check ran. Move it inside the else branch so existing builds
are preserved when the rebuild is skipped.
---------
Co-authored-by: Daniel Han <danielhanchen@users.noreply.github.com>
Co-authored-by: Daniel Han <danielhanchen@gmail.com>