- Python 71.5%
- TypeScript 22.7%
- Shell 1.9%
- PowerShell 1.6%
- Rust 1.5%
- Other 0.7%
* studio/frontend: wire logout, singleflight refresh, shared 422 helper, current-password input Four frontend follow-ups to #5375 that the train-api fix in #5409 did not cover. Log out: features/auth/api.ts:logout() was a synchronous clearAuthTokens() with no call to /api/auth/logout, and the SPA exposed no Log out menu item at all. Refresh tokens stay valid server-side for their entire lifetime even after the user "leaves". logout() is now async and POSTs to /api/auth/logout (best-effort, swallows network errors) so storage.revoke_user_refresh_tokens fires server-side. The account dropdown in components/app-sidebar.tsx gains a Log out item between Help and Shutdown that calls logout() then navigates to /login. refreshSession singleflight: The backend now consumes the refresh token atomically on /api/auth/refresh, so two concurrent refreshes race; the loser 401s and the user is force-logged-out. This reproduces on essentially every page that fires multiple API calls in parallel after access- token expiry. refreshSession now holds a module-level inflight promise: first caller mints it, subsequent callers await the same one, and the slot clears in finally. Shared formatDetail helper: Roland's #5409 fix lived inside train-api.ts. Other api modules (chat-api.ts, export-api.ts, history-api.ts, datasets-api.ts, recipe-studio/api/index.ts) still rendered FastAPI array-detail 422s as either "Request failed (422)" (chat-api.ts's typeof-string gate) or "[object Object]" (the others). format-fastapi-error.ts lifts the helper into one place: formatFastApiDetail unpacks the array, readFastApiError reads a Response into the best human-readable string. All five sibling api modules now use it. recipe-studio also swaps ?? for the helper's truthy-formatted check so an array detail no longer short-circuits to "[object Object],[object Object]". Current password input: features/auth/components/auth-form.tsx in change-password mode showed only New password and Confirm password; currentPassword defaulted to window.__UNSLOTH_BOOTSTRAP__?.password. On admin-forced must_change_password resets the bootstrap is empty and the form short-circuits with "Unable to initialize setup. Reload the page". A Current password input is now rendered in change-password mode, pre-filled from the bootstrap when present so first-boot UX is unchanged. Build: - npm run typecheck clean - npm run build produces a fresh dist - install.sh rebuilds dist on next install.sh --local * studio/frontend: logout refresh-retry, generation guard, two missed 422 sites, password toggle Reviewer follow-ups to the auth-UX PR. Logout server-side revoke missed the expired-access case. /api/auth/ logout requires a valid access JWT and only then calls storage.revoke_user_refresh_tokens(). When the access token had expired but the 7-day refresh token was still valid, logout() posted once, got 401, swallowed it, and cleared local state, leaving the refresh token alive on the server. logout() now retries once: on 401 with a refresh token present, it calls refreshSession() to rotate, then re-posts /api/auth/logout with the new access token. Both branches still clearAuthTokens in finally. In-flight refresh could repopulate localStorage after logout. A background refreshSession() that started before the user clicked Log out, but resolved after the local clear, wrote storeAuthTokens() back over the cleared state and effectively re-authenticated the SPA. Added a module-level logoutGeneration counter: each refresh captures the value on entry, logout() bumps the counter in finally before clearing, and the refresh's continuation drops its new token pair on the floor when the counter has moved. Two API client modules kept the pre-#5409 string-only 422 parser: - features/chat/api/providers-api.ts -> parseErrorText now calls formatFastApiDetail() so create / update / test / models requests surface field-level errors instead of "Request failed (422)". - features/chat/api/openai-containers.ts -> parseError now uses readFastApiError() so ttl_minutes / encrypted_api_key / container_id validation errors surface instead of "HTTP 422". recipe-studio/api/index.ts::uploadUnstructuredFile still had a local typeof-string detail check on both the 413 and the generic not-ok branches. Both branches now use readFastApiError() so array-shaped 422 details show field-level errors instead of a generic fallback. Password reveal toggle in change-password mode shared one showPassword state across Current password and New password, so the eye button on either field exposed both secrets. Added a separate showNewPassword state so New password's toggle is independent of Current password's toggle. Confirm password remains type="password" unconditionally. Test: - npm run typecheck clean - npm run build produces a fresh dist * studio/frontend: drop dynamic auth/api + auth/session imports in sidebar Log out's onSelect dynamically imported logout from "@/features/auth/api" and clearAuthTokens from "@/features/auth/session". Both modules were already statically imported via "@/features/auth" elsewhere in the app, so rolldown split auth/session into its own chunk and the main bundle then re-imported back from that chunk to reach the zustand-backed usePlatformStore. The resulting circular dependency left session.js's 'create' binding undefined at module init, throwing 'TypeError: t is not a function' from var usePlatformStore=create<...> on /login, /change-password, and any route that touches the platform store before the main bundle finished evaluating. Static-import logout and clearAuthTokens from "@/features/auth" so both are tree-shaken into the main bundle, eliminating the session side-chunk and the cycle. Exported clearAuthTokens from auth/index.ts since it was previously only reachable through the session.ts path module. Test: - npm run typecheck clean - npm run build no longer emits a session-*.js chunk - Local Playwright pre/post: /login, /change-password, /chat render with 0 page errors on the rebuilt dist (pre: 'TypeError: t is not a function' on every route) * studio/frontend: decouple must_change_password from storeAuthTokens CodeQL's js/clear-text-storage-of-sensitive-information rule traced must_change_password through loginWithPassword() into localStorage.setItem(AUTH_MUST_CHANGE_PASSWORD_KEY, ...) at session.ts:46 and flagged the line as new high-severity. The flag is a boolean derived from the same response payload as the access token, so the data-flow analyser treated it as JWT-equivalent sensitivity. Removed the third parameter from storeAuthTokens so it only writes the two JWTs. Each caller (refreshSession, tauri-auto-auth, two spots in auth-form) now calls setMustChangePassword(...) explicitly with the boolean. The boolean is no longer reachable from a function whose name CodeQL treats as a password sink. Test: - npm run typecheck clean - npm run build produces no session-*.js side-chunk - Local Playwright over /login, /change-password, /chat: 0 page errors (parity with the previous fix) * studio/frontend: suppress CodeQL clear-text-storage on must_change_password flag CodeQL's js/clear-text-storage-of-sensitive-information rule traces the must_change_password boolean back through loginWithPassword's TokenResponse and flags any localStorage.setItem of that boolean as sensitive-clear-text storage. The value is a status flag (route to /change-password vs straight to /chat); it carries no credential material. Decoupling setMustChangePassword from storeAuthTokens in the previous commit only moved the alert one line over because the analyser still recognises the source. Add the standard lgtm suppression comment, with a brief rationale, on the .setItem call. Test: npm run typecheck clean, npm run build still produces a fresh dist with no session-*.js side-chunk. * studio/frontend: encode must_change_password as key presence to silence CodeQL setMustChangePassword wrote String(required) which is a derivative of the boolean and which CodeQL's clear-text-storage analyser traces back through loginWithPassword's TokenResponse, flagging the .setItem call as sensitive-information storage. Switch the encoding so the stored value is the literal string "1" when the flag is set, and the key is removed when not. The reader switches from `=== "true"` to a presence check (`!== null`). This breaks the boolean's data flow into .setItem: the value argument is now a constant string literal in the truthy branch and the falsy branch issues .removeItem (no stored value to taint). The behaviour contract is identical (the flag is present iff the user must change their password). Test: npm run typecheck clean, npm run build produces a fresh dist, local Playwright probe over /login, /change-password, /chat: 0 page errors on the rebuilt dist. * studio/frontend: trim verbose comments in auth api + session Compress singleflight + logoutGeneration paragraphs in api.ts from ~9 lines each to ~3. Same logic. Merge mustChangePassword / setMustChangePassword's separate two-paragraph CodeQL rationales into one shared comment above both functions. Typecheck + build still clean. |
||
|---|---|---|
| .github | ||
| images | ||
| scripts | ||
| studio | ||
| tests | ||
| unsloth | ||
| unsloth_cli | ||
| .gitattributes | ||
| .gitignore | ||
| .pre-commit-ci.yaml | ||
| .pre-commit-config.yaml | ||
| build.sh | ||
| cli.py | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| COPYING | ||
| install.ps1 | ||
| install.sh | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| unsloth-cli.py | ||
Unsloth Studio lets you run and train models locally.
Features • Quickstart • Notebooks • Documentation
⚡ Get started
macOS, Linux, WSL:
curl -fsSL https://unsloth.ai/install.sh | sh
Windows:
irm https://unsloth.ai/install.ps1 | iex
Community:
⭐ Features
Unsloth Studio (Beta) lets you run and train text, audio, embedding, vision models on Windows, Linux and macOS.
Inference
- Search + download + run models including GGUF, LoRA adapters, safetensors
- Export models: Save or export models to GGUF, 16-bit safetensors and other formats.
- Tool calling: Support for self-healing tool calling and web search
- Code execution: lets LLMs test code in Claude artifacts and sandbox environments
- API inference endpoint: Deploy and run local LLMs in Claude Code, Codex tools with Unsloth
- Auto set inference settings and customize chat templates.
- We work directly with teams behind gpt-oss, Qwen3, Llama 4, Mistral, Gemma 1-3, and Phi-4, where we’ve fixed bugs that improve model accuracy.
- Upload images, audio, PDFs, code, DOCX and more file types to chat with.
Training
- Train and RL 500+ models up to 2x faster with up to 70% less VRAM, with no accuracy loss.
- Custom Triton and mathematical kernels. See some collabs we did with PyTorch and Hugging Face.
- Data Recipes: Auto-create datasets from PDF, CSV, DOCX etc. Edit data in a visual-node workflow.
- Reinforcement Learning (RL): The most efficient RL library, using 80% less VRAM for GRPO, FP8 etc.
- Supports full fine-tuning, RL, pretraining, 4-bit, 16-bit and, FP8 training.
- Observability: Monitor training live, track loss and GPU usage and customize graphs.
- Multi-GPU training is supported, with major improvements coming soon.
📥 Install
Unsloth can be used in two ways: through Unsloth Studio, the web UI, or through Unsloth Core, the code-based version. Each has different requirements.
Unsloth Studio (web UI)
Unsloth Studio (Beta) works on Windows, Linux, WSL and macOS.
- CPU: Supported for Chat and Data Recipes currently
- NVIDIA: Training works on RTX 30/40/50, Blackwell, DGX Spark, Station and more
- macOS: Currently supports chat and Data Recipes. MLX training is coming very soon
- AMD: Chat + Data works. Train with Unsloth Core. Studio support is out soon.
- Coming soon: Training support for Apple MLX, AMD, and Intel.
- Multi-GPU: Available now, with a major upgrade on the way
macOS, Linux, WSL:
curl -fsSL https://unsloth.ai/install.sh | sh
Windows:
irm https://unsloth.ai/install.ps1 | iex
Launch
unsloth studio -p 8888
For cloud VMs or LAN access, add
-H 0.0.0.0to bind on all interfaces.
Update
To update, use the same install commands as above. Or run (does not work on Windows):
unsloth studio update
Docker
Use our Docker image unsloth/unsloth container. Run:
docker run -d -e JUPYTER_PASSWORD="mypassword" \
-p 8888:8888 -p 8000:8000 -p 2222:22 \
-v $(pwd)/work:/workspace/work \
--gpus all \
unsloth/unsloth
Developer, Nightly, Uninstall
To see developer, nightly and uninstallation etc. instructions, see advanced installation.
Unsloth Core (code-based)
Linux, WSL:
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv unsloth_env --python 3.13
source unsloth_env/bin/activate
uv pip install unsloth --torch-backend=auto
Windows:
winget install -e --id Python.Python.3.13
winget install --id=astral-sh.uv -e
uv venv unsloth_env --python 3.13
.\unsloth_env\Scripts\activate
uv pip install unsloth --torch-backend=auto
For Windows, pip install unsloth works only if you have PyTorch installed. Read our Windows Guide.
You can use the same Docker image as Unsloth Studio.
AMD, Intel:
For RTX 50x, B200, 6000 GPUs: uv pip install unsloth --torch-backend=auto. Read our guides for: Blackwell and DGX Spark.
To install Unsloth on AMD and Intel GPUs, follow our AMD Guide and Intel Guide.
📒 Free Notebooks
Train for free with our notebooks. You can use our new free Unsloth Studio notebook to run and train models for free in a web UI. Read our guide. Add dataset, run, then deploy your trained model.
| Model | Free Notebooks | Performance | Memory use |
|---|---|---|---|
| Gemma 4 (E2B) | ▶️ Start for free | 1.5x faster | 50% less |
| Qwen3.5 (4B) | ▶️ Start for free | 1.5x faster | 60% less |
| gpt-oss (20B) | ▶️ Start for free | 2x faster | 70% less |
| Qwen3.5 GSPO | ▶️ Start for free | 2x faster | 70% less |
| gpt-oss (20B): GRPO | ▶️ Start for free | 2x faster | 80% less |
| Qwen3: Advanced GRPO | ▶️ Start for free | 2x faster | 70% less |
| embeddinggemma (300M) | ▶️ Start for free | 2x faster | 20% less |
| Mistral Ministral 3 (3B) | ▶️ Start for free | 1.5x faster | 60% less |
| Llama 3.1 (8B) Alpaca | ▶️ Start for free | 2x faster | 70% less |
| Llama 3.2 Conversational | ▶️ Start for free | 2x faster | 70% less |
| Orpheus-TTS (3B) | ▶️ Start for free | 1.5x faster | 50% less |
- See all our notebooks for: Kaggle, GRPO, TTS, embedding & Vision
- See all our models and all our notebooks
- See detailed documentation for Unsloth here
🦥 Unsloth News
- API inference endpoint: Deploy and run local LLMs in Claude Code, Codex tools. Guide
- Qwen3.6: Qwen3.6-35B-A3B can now be trained and run in Unsloth Studio. Blog
- Gemma 4: Run and train Google’s new models directly in Unsloth. Blog
- Introducing Unsloth Studio: our new web UI for running and training LLMs. Blog
- Qwen3.5 - 0.8B, 2B, 4B, 9B, 27B, 35-A3B, 112B-A10B are now supported. Guide + notebooks
- Train MoE LLMs 12x faster with 35% less VRAM - DeepSeek, GLM, Qwen and gpt-oss. Blog
- Embedding models: Unsloth now supports ~1.8-3.3x faster embedding fine-tuning. Blog • Notebooks
- New 7x longer context RL vs. all other setups, via our new batching algorithms. Blog
- New RoPE & MLP Triton Kernels & Padding Free + Packing: 3x faster training & 30% less VRAM. Blog
- 500K Context: Training a 20B model with >500K context is now possible on an 80GB GPU. Blog
- FP8 & Vision RL: You can now do FP8 & VLM GRPO on consumer GPUs. FP8 Blog • Vision RL
📥 Advanced Installation
The below advanced instructions are for Unsloth Studio. For Unsloth Core advanced installation, view our docs.
Developer installs: macOS, Linux, WSL:
git clone https://github.com/unslothai/unsloth
cd unsloth
./install.sh --local
unsloth studio -p 8888
Then to update :
unsloth studio update
Developer installs: Windows PowerShell:
git clone https://github.com/unslothai/unsloth.git
cd unsloth
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\install.ps1 --local
unsloth studio -p 8888
Then to update :
unsloth studio update
Nightly: MacOS, Linux, WSL:
git clone https://github.com/unslothai/unsloth
cd unsloth
git checkout nightly
./install.sh --local
unsloth studio -p 8888
Then to launch every time:
unsloth studio -p 8888
Nightly: Windows:
Run in Windows Powershell:
git clone https://github.com/unslothai/unsloth.git
cd unsloth
git checkout nightly
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\install.ps1 --local
unsloth studio -p 8888
Then to launch every time:
unsloth studio -p 8888
Uninstall
You can uninstall Unsloth Studio by deleting its install folder usually located under $HOME/.unsloth/studio on Mac/Linux/WSL and %USERPROFILE%\.unsloth\studio on Windows. Using the rm -rf commands will delete everything, including your history, cache:
- MacOS, WSL, Linux:
rm -rf ~/.unsloth/studio - Windows (PowerShell):
Remove-Item -Recurse -Force "$HOME\.unsloth\studio"
For more info, see our docs.
Deleting model files
You can delete old model files either from the bin icon in model search or by removing the relevant cached model folder from the default Hugging Face cache directory. By default, HF uses:
- MacOS, Linux, WSL:
~/.cache/huggingface/hub/ - Windows:
%USERPROFILE%\.cache\huggingface\hub\
💚 Community and Links
| Type | Links |
|---|---|
| Join Discord server | |
| Join Reddit community | |
| 📚 Documentation & Wiki | Read Our Docs |
| Follow us on X | |
| 🔮 Our Models | Unsloth Catalog |
| ✍️ Blog | Read our Blogs |
Citation
You can cite the Unsloth repo as follows:
@software{unsloth,
author = {Daniel Han, Michael Han and Unsloth team},
title = {Unsloth},
url = {https://github.com/unslothai/unsloth},
year = {2023}
}
If you trained a model with 🦥Unsloth, you can use this cool sticker!
License
Unsloth uses a dual-licensing model of Apache 2.0 and AGPL-3.0. The core Unsloth package remains licensed under Apache 2.0, while certain optional components, such as the Unsloth Studio UI are licensed under the open-source license AGPL-3.0.
This structure helps support ongoing Unsloth development while keeping the project open source and enabling the broader ecosystem to continue growing.
Thank You to
- The llama.cpp library that lets users run and save models with Unsloth
- The Hugging Face team and their libraries: transformers and TRL
- The Pytorch and Torch AO team for their contributions
- NVIDIA for their NeMo DataDesigner library and their contributions
- And of course for every single person who has contributed or has used Unsloth!