diff --git a/studio/backend/core/inference/llama_cpp.py b/studio/backend/core/inference/llama_cpp.py
index 7bcf02dc35..8ba195bdd6 100644
--- a/studio/backend/core/inference/llama_cpp.py
+++ b/studio/backend/core/inference/llama_cpp.py
@@ -3651,8 +3651,9 @@ class LlamaCppBackend:
logger.warning(
"Requested MTP speculative decoding but "
"llama-server lacks --spec-type mtp/draft-mtp; "
- "run `unsloth studio update`. Loading without "
- "speculative decoding."
+ "update by running curl -fsSL https://unsloth.ai/install.sh | sh "
+ "(macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex "
+ "(Windows). Loading without speculative decoding."
)
return False
draft_n_max = _resolved_draft_n_max()
diff --git a/studio/backend/main.py b/studio/backend/main.py
index 10fbbfddf0..0e1af5a305 100644
--- a/studio/backend/main.py
+++ b/studio/backend/main.py
@@ -344,7 +344,9 @@ async def lifespan(app: FastAPI):
if _caps.get("found") and not _caps.get("supports_mtp"):
_msg = (
"llama.cpp prebuilt lacks MTP support "
- "(--spec-type mtp/draft-mtp). Run `unsloth studio update`. "
+ "(--spec-type mtp/draft-mtp). Update by running "
+ "curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or "
+ "irm https://unsloth.ai/install.ps1 | iex (Windows). "
"MTP GGUFs will load without speculative decoding."
)
_log.warning(_msg)
diff --git a/studio/backend/tests/test_llama_cpp_freshness.py b/studio/backend/tests/test_llama_cpp_freshness.py
index b32aeefcdb..d41f8ce308 100644
--- a/studio/backend/tests/test_llama_cpp_freshness.py
+++ b/studio/backend/tests/test_llama_cpp_freshness.py
@@ -317,7 +317,8 @@ def test_format_stale_warning_contains_actionable_command():
assert "b9190" in msg
assert "b9300" in msg
assert "5 days" in msg
- assert "unsloth studio update" in msg
+ assert "install.sh" in msg
+ assert "install.ps1" in msg
def test_format_stale_warning_singular_day():
diff --git a/studio/backend/utils/llama_cpp_freshness.py b/studio/backend/utils/llama_cpp_freshness.py
index 2c781f4a7b..e16b2228a6 100644
--- a/studio/backend/utils/llama_cpp_freshness.py
+++ b/studio/backend/utils/llama_cpp_freshness.py
@@ -233,8 +233,9 @@ def format_stale_warning(info: dict) -> str:
age_str = f"{age} day{'s' if age != 1 else ''}" if age is not None else "some time"
return (
f"llama.cpp prebuilt is {age_str} behind: installed "
- f"{installed}, latest {latest}. Run `unsloth studio update` "
- f"to refresh."
+ f"{installed}, latest {latest}. Update to refresh by running "
+ f"curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or "
+ f"irm https://unsloth.ai/install.ps1 | iex (Windows)."
)
diff --git a/studio/frontend/src/components/tauri/update-banner.tsx b/studio/frontend/src/components/tauri/update-banner.tsx
index 62038f92a9..332ca7bdcb 100644
--- a/studio/frontend/src/components/tauri/update-banner.tsx
+++ b/studio/frontend/src/components/tauri/update-banner.tsx
@@ -102,7 +102,7 @@ export function UpdateBanner({
: isManualLinuxPackage
? "Open the GitHub release page to install the Linux package"
: isExternalServer
- ? "Run `unsloth studio update` from your terminal"
+ ? "To update, run curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows) from your terminal"
: "A new app update is available"}
diff --git a/studio/frontend/src/components/web/update-banner.tsx b/studio/frontend/src/components/web/update-banner.tsx
index 685a8aa3dc..0e3b0c541a 100644
--- a/studio/frontend/src/components/web/update-banner.tsx
+++ b/studio/frontend/src/components/web/update-banner.tsx
@@ -8,7 +8,11 @@ import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { AnimatePresence, motion } from "motion/react";
import { type ReactElement, useEffect, useRef, useState } from "react";
-const STUDIO_UPDATE_CMD = "unsloth studio update";
+const STUDIO_UPDATE_UNIX_CMD = "curl -fsSL https://unsloth.ai/install.sh | sh";
+const STUDIO_UPDATE_WINDOWS_CMD = "irm https://unsloth.ai/install.ps1 | iex";
+// Match "windows" (every Windows UA carries "Windows NT") rather than "win",
+// which also matches "Darwin" and would mis-detect macOS as Windows.
+const WINDOWS_UA_RE = /windows/i;
const RELEASE_NOTES_URL = "https://unsloth.ai/docs/new/changelog";
const EASE_OUT_QUART: [number, number, number, number] = [0.165, 0.84, 0.44, 1];
@@ -36,7 +40,15 @@ export function WebUpdateBanner({
}
async function handleCopyCommand() {
- if (!(await copyToClipboard(STUDIO_UPDATE_CMD))) {
+ // Copy only the command for the user's OS: pasting both (Unix + PowerShell)
+ // into a single terminal runs the wrong one and errors out.
+ const isWindows =
+ typeof navigator !== "undefined" &&
+ WINDOWS_UA_RE.test(navigator.userAgent || "");
+ const command = isWindows
+ ? STUDIO_UPDATE_WINDOWS_CMD
+ : STUDIO_UPDATE_UNIX_CMD;
+ if (!(await copyToClipboard(command))) {
return;
}
setCopiedVersion(status?.latestVersion ?? null);
@@ -90,8 +102,23 @@ export function WebUpdateBanner({
Installed package: {status.currentVersion}. To update Studio,
- run this in your terminal, then restart Studio.
+ run the command for your OS in a terminal, then restart
+ Studio.
+
+
+ macOS / Linux
+
+
+ {STUDIO_UPDATE_UNIX_CMD}
+
+
+ Windows (PowerShell)
+
+
+ {STUDIO_UPDATE_WINDOWS_CMD}
+
+
diff --git a/studio/frontend/src/features/settings/components/update-studio-instructions.tsx b/studio/frontend/src/features/settings/components/update-studio-instructions.tsx
index 90f66483b7..7bbdd524c3 100644
--- a/studio/frontend/src/features/settings/components/update-studio-instructions.tsx
+++ b/studio/frontend/src/features/settings/components/update-studio-instructions.tsx
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
-import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { useT } from "@/i18n";
+import { copyToClipboard } from "@/lib/copy-to-clipboard";
import { cn } from "@/lib/utils";
import { Copy01Icon, Tick02Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
@@ -10,13 +10,9 @@ import { AnimatePresence, motion, useReducedMotion } from "motion/react";
import type { ReactElement } from "react";
import { useEffect, useRef, useState } from "react";
-const STUDIO_UPDATE_CMD = "unsloth studio update";
-const STUDIO_UPDATE_FALLBACK_UNIX_CMD =
- "curl -fsSL https://unsloth.ai/install.sh | sh";
-const STUDIO_UPDATE_FALLBACK_WINDOWS_CMD =
- "irm https://unsloth.ai/install.ps1 | iex";
+const STUDIO_UPDATE_UNIX_CMD = "curl -fsSL https://unsloth.ai/install.sh | sh";
+const STUDIO_UPDATE_WINDOWS_CMD = "irm https://unsloth.ai/install.ps1 | iex";
const STUDIO_LOCAL_PULL_CMD = "git pull --ff-only";
-const STUDIO_LOCAL_UPDATE_CMD = "unsloth studio update --local";
const STUDIO_LOCAL_FALLBACK_UNIX_CMD = "./install.sh --local";
const STUDIO_LOCAL_FALLBACK_WINDOWS_CMD = ".\\install.ps1 --local";
@@ -145,6 +141,9 @@ export function UpdateStudioInstructions({
const shell = shellOverride ?? defaultShell;
const prefersReducedMotion = useReducedMotion();
const windows = shell === "windows";
+ const updateCmd = windows
+ ? STUDIO_UPDATE_WINDOWS_CMD
+ : STUDIO_UPDATE_UNIX_CMD;
const localInstallSource = isLocalInstallSource(installSource);
const checkoutInstallSource =
installSource === "editable" || installSource === "local_repo";
@@ -224,16 +223,9 @@ export function UpdateStudioInstructions({
command={STUDIO_LOCAL_PULL_CMD}
copyLabel={t("settings.about.update.gitPullCommand")}
/>
-
-
- {t("settings.about.update.localInstallerFallback")}
-
@@ -291,17 +283,20 @@ export function UpdateStudioInstructions({
{t("settings.about.update.curlOrPypi")}
-
-
- {t("settings.about.update.localCheckout")}
-
-
+
+
+
+
+
{t("settings.about.update.restartAfterUpdate")}
@@ -320,28 +315,17 @@ export function UpdateStudioInstructions({
{getStudioUpdateInstructionLine(shell, t)}
-
-
- {t("settings.about.update.fallbackInstruction")}
-
diff --git a/studio/frontend/src/hooks/use-tauri-backend.ts b/studio/frontend/src/hooks/use-tauri-backend.ts
index c7628c0fd0..8feffd7da1 100644
--- a/studio/frontend/src/hooks/use-tauri-backend.ts
+++ b/studio/frontend/src/hooks/use-tauri-backend.ts
@@ -71,8 +71,8 @@ function externalConflictMessage(preflight: DesktopPreflightResult) {
}
return preflight.port
- ? `A Studio server for this install is already running from a terminal on port ${preflight.port}. Stop that server, or run \`unsloth studio update\` from that terminal before using the desktop app.`
- : "A Studio server for this install is already running from a terminal. Stop that server, or run `unsloth studio update` from that terminal before using the desktop app.";
+ ? `A Studio server for this install is already running from a terminal on port ${preflight.port}. Stop that server, or update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows) from that terminal before using the desktop app.`
+ : "A Studio server for this install is already running from a terminal. Stop that server, or update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows) from that terminal before using the desktop app.";
}
async function waitForManagedServerReady(
@@ -248,8 +248,8 @@ export function useTauriBackend() {
} else {
setBackendError(
preflight.disposition === "owned_stale"
- ? "Desktop-owned Studio backend is too old for this desktop app. Run `unsloth studio update`, then restart Studio."
- : "Managed Studio install is too old. Run `unsloth studio update`.",
+ ? "Desktop-owned Studio backend is too old for this desktop app. Update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows), then restart Studio."
+ : "Managed Studio install is too old. Update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows).",
);
}
return;
diff --git a/studio/frontend/src/i18n/locales/en.ts b/studio/frontend/src/i18n/locales/en.ts
index 83a04b60c1..97412e967d 100644
--- a/studio/frontend/src/i18n/locales/en.ts
+++ b/studio/frontend/src/i18n/locales/en.ts
@@ -307,8 +307,6 @@ export const en = {
"Pull latest changes from your Unsloth repo checkout, then update Studio locally:",
gitPullCommand: "git pull command",
localUpdateCommand: "local update command",
- localInstallerFallback:
- "If the Studio update command is unavailable, run the local installer from that checkout:",
localInstallerCommand: "local installer command",
sourceInstallDetected:
"This looks like a source or VCS package install. Reinstall from the original local path or Git URL you used.",
@@ -320,11 +318,6 @@ export const en = {
"Studio could not detect how it was installed. Check how you installed Studio first, then choose the matching update path.",
curlOrPypi: "For curl or PyPI installs, run:",
updateCommand: "update command",
- localCheckout:
- "For local checkout installs, update from that checkout instead and use the local update command:",
- fallbackInstruction:
- "If that fails or unsloth studio update is unavailable, run:",
- fallbackCommand: "fallback command",
},
},
},
diff --git a/studio/frontend/src/i18n/locales/zh-CN.ts b/studio/frontend/src/i18n/locales/zh-CN.ts
index f7075eb887..bc0e24028b 100644
--- a/studio/frontend/src/i18n/locales/zh-CN.ts
+++ b/studio/frontend/src/i18n/locales/zh-CN.ts
@@ -288,8 +288,6 @@ export const zhCN = {
"从你的 Unsloth 仓库 checkout 拉取最新变更,然后本地更新 Studio:",
gitPullCommand: "git pull 命令",
localUpdateCommand: "本地更新命令",
- localInstallerFallback:
- "如果 Studio 更新命令不可用,请从该 checkout 运行本地安装器:",
localInstallerCommand: "本地安装器命令",
sourceInstallDetected:
"这看起来是源码或 VCS 包安装。请从最初使用的本地路径或 Git URL 重新安装。",
@@ -300,11 +298,6 @@ export const zhCN = {
"Studio 无法检测安装方式。请先确认你如何安装 Studio,然后选择匹配的更新方式。",
curlOrPypi: "对于 curl 或 PyPI 安装,请运行:",
updateCommand: "更新命令",
- localCheckout:
- "对于本地 checkout 安装,请改为从该 checkout 更新并使用本地更新命令:",
- fallbackInstruction:
- "如果失败,或 unsloth studio update 不可用,请运行:",
- fallbackCommand: "备用命令",
},
},
},
diff --git a/studio/src-tauri/src/commands.rs b/studio/src-tauri/src/commands.rs
index 06f2dca941..0c796694d8 100644
--- a/studio/src-tauri/src/commands.rs
+++ b/studio/src-tauri/src/commands.rs
@@ -30,7 +30,7 @@ fn external_conflict_message(conflict: &crate::preflight::ExternalBackendConflic
);
}
format!(
- "A Studio server for this install is already running from a terminal on port {}. Stop that server, or run `unsloth studio update` from that terminal before using desktop repair/update.",
+ "A Studio server for this install is already running from a terminal on port {}. Stop that server, or update by running curl -fsSL https://unsloth.ai/install.sh | sh (macOS/Linux) or irm https://unsloth.ai/install.ps1 | iex (Windows) from that terminal before using desktop repair/update.",
conflict.port
)
}