diff --git a/cli/commands/studio.py b/cli/commands/studio.py index 4287c756a8..2489676844 100644 --- a/cli/commands/studio.py +++ b/cli/commands/studio.py @@ -1,19 +1,34 @@ +import time +from pathlib import Path +from typing import Optional + import typer def studio( port: int = typer.Option(8000, "--port", "-p", help="Port to run the UI server on."), host: str = typer.Option("0.0.0.0", "--host", "-H", help="Host address to bind to."), - share: bool = typer.Option(True, "--share", "-s", help="Create a public Gradio share link."), + frontend: Optional[Path] = typer.Option(None, "--frontend", "-f", help="Path to frontend build directory."), + silent: bool = typer.Option(False, "--silent", "-q", help="Suppress startup messages."), ): - """Launch the Unsloth web UI for training, inference, and export.""" - from app import demo, script_dir + """Launch the Unsloth web UI backend server.""" + from studio.backend.run import run_server - typer.echo(f"Starting Unsloth UI on http://{host}:{port}") + if not silent: + from studio.backend.run import _resolve_external_ip + display_host = _resolve_external_ip() if host == "0.0.0.0" else host + typer.echo(f"Starting Unsloth Studio on http://{display_host}:{port}") - demo.launch( - share=share, - server_port=port, - server_name=host, - favicon_path=f"{script_dir}/assets/favicon-32x32.png", + run_server( + host=host, + port=port, + frontend_path=frontend, + silent=silent, ) + + # Keep running until interrupted + try: + while True: + time.sleep(1) + except KeyboardInterrupt: + typer.echo("\nShutting down...") diff --git a/setup.sh b/setup.sh index c493d357ee..5f7d96eff3 100755 --- a/setup.sh +++ b/setup.sh @@ -212,38 +212,38 @@ USER_SHELL="$(basename "${SHELL:-/bin/bash}")" case "$USER_SHELL" in zsh) SHELL_RC="$HOME/.zshrc" - ALIAS_BLOCK="alias unsloth-ui='${REPO_DIR}/.venv/bin/python ${REPO_DIR}/cli.py ui -f ${REPO_DIR}/studio/frontend/dist'" + ALIAS_BLOCK="alias unsloth-studio='${REPO_DIR}/.venv/bin/python ${REPO_DIR}/cli.py studio -f ${REPO_DIR}/studio/frontend/dist'" ;; fish) SHELL_RC="$HOME/.config/fish/config.fish" # fish uses 'abbr' or 'function'; a simple alias works via 'alias' in config.fish - ALIAS_BLOCK="alias unsloth-ui '${REPO_DIR}/.venv/bin/python ${REPO_DIR}/cli.py ui -f ${REPO_DIR}/studio/frontend/dist'" + ALIAS_BLOCK="alias unsloth-studio '${REPO_DIR}/.venv/bin/python ${REPO_DIR}/cli.py studio -f ${REPO_DIR}/studio/frontend/dist'" ;; ksh) SHELL_RC="$HOME/.kshrc" - ALIAS_BLOCK="alias unsloth-ui='${REPO_DIR}/.venv/bin/python ${REPO_DIR}/cli.py ui -f ${REPO_DIR}/studio/frontend/dist'" + ALIAS_BLOCK="alias unsloth-studio='${REPO_DIR}/.venv/bin/python ${REPO_DIR}/cli.py studio -f ${REPO_DIR}/studio/frontend/dist'" ;; *) # Default to bash for bash and any other POSIX-compatible shell SHELL_RC="$HOME/.bashrc" - ALIAS_BLOCK="alias unsloth-ui='${REPO_DIR}/.venv/bin/python ${REPO_DIR}/cli.py ui -f ${REPO_DIR}/studio/frontend/dist'" + ALIAS_BLOCK="alias unsloth-studio='${REPO_DIR}/.venv/bin/python ${REPO_DIR}/cli.py studio -f ${REPO_DIR}/studio/frontend/dist'" ;; esac echo " Detected shell: $USER_SHELL → $SHELL_RC" ALIAS_ADDED=false -if ! grep -qF "unsloth-ui" "$SHELL_RC" 2>/dev/null; then +if ! grep -qF "unsloth-studio" "$SHELL_RC" 2>/dev/null; then mkdir -p "$(dirname "$SHELL_RC")" # needed for fish's nested config path cat >> "$SHELL_RC" <