diff --git a/README.md b/README.md index 7046a2af7c..5dbe099344 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,9 @@ irm https://unsloth.ai/install.ps1 | iex #### Launch ```bash -unsloth studio -H 0.0.0.0 -p 8888 +unsloth studio ``` +> For cloud VMs or LAN access, add `-H 0.0.0.0` to bind on all interfaces. #### Update To update, use the same install commands as above. Or run (does not work on Windows): @@ -151,7 +152,7 @@ The below advanced instructions are for Unsloth Studio. For Unsloth Core advance git clone https://github.com/unslothai/unsloth cd unsloth ./install.sh --local -unsloth studio -H 0.0.0.0 -p 8888 +unsloth studio ``` Then to update : ```bash @@ -164,7 +165,7 @@ git clone https://github.com/unslothai/unsloth.git cd unsloth Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass .\install.ps1 --local -unsloth studio -H 0.0.0.0 -p 8888 +unsloth studio ``` Then to update : ```bash @@ -177,11 +178,11 @@ git clone https://github.com/unslothai/unsloth cd unsloth git checkout nightly ./install.sh --local -unsloth studio -H 0.0.0.0 -p 8888 +unsloth studio ``` Then to launch every time: ```bash -unsloth studio -H 0.0.0.0 -p 8888 +unsloth studio ``` #### Nightly: Windows: @@ -192,11 +193,11 @@ cd unsloth git checkout nightly Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass .\install.ps1 --local -unsloth studio -H 0.0.0.0 -p 8888 +unsloth studio ``` Then to launch every time: ```bash -unsloth studio -H 0.0.0.0 -p 8888 +unsloth studio ``` #### Uninstall diff --git a/install.ps1 b/install.ps1 index 5ddb42ea7e..de3946f8df 100644 --- a/install.ps1 +++ b/install.ps1 @@ -958,15 +958,25 @@ shell.Run cmd, 0, False step "path" "added unsloth to PATH" } - # Launch studio automatically in interactive terminals; - # in non-interactive environments (CI, Docker) just print instructions. + # In interactive terminals, ask the user before starting Studio. + # In non-interactive environments (CI, Docker) just print instructions. $IsInteractive = [Environment]::UserInteractive -and (-not [Console]::IsInputRedirected) if ($IsInteractive) { - & $UnslothExe studio -H 0.0.0.0 -p 8888 + Write-Host "" + $reply = Read-Host " Start Unsloth Studio now? [Y/n]" + if ([string]::IsNullOrWhiteSpace($reply) -or $reply -match '^[Yy]') { + & $UnslothExe studio -p 8888 + } else { + step "launch" "to start later, run:" + substep "unsloth studio" + substep "(add -H 0.0.0.0 to allow network / cloud access)" + Write-Host "" + } } else { step "launch" "manual commands:" substep "& `"$VenvDir\Scripts\Activate.ps1`"" - substep "unsloth studio -H 0.0.0.0 -p 8888" + substep "unsloth studio" + substep "(add -H 0.0.0.0 to allow network / cloud access)" Write-Host "" } } diff --git a/install.sh b/install.sh index 053f334d2b..28b05d4a95 100755 --- a/install.sh +++ b/install.sh @@ -447,11 +447,11 @@ if [ -t 1 ]; then ) & # Clear traps so exec does not trigger _release_lock (the subshell owns it) trap - EXIT INT TERM - exec "$UNSLOTH_EXE" studio -H 0.0.0.0 -p "$_launch_port" + exec "$UNSLOTH_EXE" studio -p "$_launch_port" else # ── Background mode (no TTY) ── # Used by macOS .app and headless invocations. - _launch_cmd=$(printf '%q ' "$UNSLOTH_EXE" studio -H 0.0.0.0 -p "$_launch_port") + _launch_cmd=$(printf '%q ' "$UNSLOTH_EXE" studio -p "$_launch_port") _launch_cmd=${_launch_cmd% } _spawn_terminal "$_launch_cmd" @@ -1211,28 +1211,42 @@ printf " ${C_TITLE}%s${C_RST}\n" "Unsloth Studio installed!" printf " ${C_DIM}%s${C_RST}\n" "$RULE" echo "" -# Launch studio automatically in interactive terminals; -# in non-interactive environments (Docker, CI, cloud-init) just print instructions. +# In interactive terminals, ask the user before starting Studio. +# In non-interactive environments (Docker, CI, cloud-init) just print instructions. if [ -t 1 ]; then - step "launch" "starting Unsloth Studio..." - "$VENV_DIR/bin/unsloth" studio -H 0.0.0.0 -p 8888 - _LAUNCH_EXIT=$? - if [ "$_LAUNCH_EXIT" -ne 0 ] && [ "$_MIGRATED" = true ]; then - echo "" - echo "⚠️ Unsloth Studio failed to start after migration." - echo " Your migrated environment may be incompatible." - echo " To fix, remove the environment and reinstall:" - echo "" - echo " rm -rf $VENV_DIR" - echo " curl -fsSL https://unsloth.ai/install.sh | sh" - echo "" - fi - exit "$_LAUNCH_EXIT" + echo "" + printf " Start Unsloth Studio now? [Y/n] " + read -r _reply "argparse.ArgumentParser": + """Build and return the ArgumentParser for standalone run.py execution. - # Ensure stderr can handle Unicode on Windows (tracebacks with non-ASCII paths) - if sys.platform == "win32" and hasattr(sys.stderr, "reconfigure"): - try: - sys.stderr.reconfigure(encoding = "utf-8", errors = "replace") - except Exception: - pass + Extracted from ``__main__`` so it can be imported and tested without + executing the full startup sequence. + """ + import argparse parser = argparse.ArgumentParser(description = "Run Unsloth UI Backend server") - parser.add_argument("--host", default = "0.0.0.0", help = "Host to bind to") + parser.add_argument( + "--host", + default = "127.0.0.1", + help = "Host to bind to (default: 127.0.0.1; use 0.0.0.0 for network/cloud access)", + ) parser.add_argument("--port", type = int, default = 8888, help = "Port to bind to") parser.add_argument( "--frontend", @@ -380,8 +379,22 @@ def _trigger_shutdown(): help = "Path to frontend build", ) parser.add_argument("--silent", action = "store_true", help = "Suppress output") + return parser + + +# For direct execution (also invoked by CLI via os.execvp / subprocess) +if __name__ == "__main__": + import signal + import traceback + + # Ensure stderr can handle Unicode on Windows (tracebacks with non-ASCII paths) + if sys.platform == "win32" and hasattr(sys.stderr, "reconfigure"): + try: + sys.stderr.reconfigure(encoding = "utf-8", errors = "replace") + except Exception: + pass - args = parser.parse_args() + args = _make_argument_parser().parse_args() kwargs = dict(host = args.host, port = args.port, silent = args.silent) if args.frontend is not None: diff --git a/unsloth_cli/commands/studio.py b/unsloth_cli/commands/studio.py index 2fecb9d6b1..6ebc6e7325 100644 --- a/unsloth_cli/commands/studio.py +++ b/unsloth_cli/commands/studio.py @@ -76,7 +76,7 @@ def _find_setup_script() -> Optional[Path]: def studio_default( ctx: typer.Context, port: int = typer.Option(8888, "--port", "-p"), - host: str = typer.Option("0.0.0.0", "--host", "-H"), + host: str = typer.Option("127.0.0.1", "--host", "-H"), frontend: Optional[Path] = typer.Option(None, "--frontend", "-f"), silent: bool = typer.Option(False, "--silent", "-q"), ):