Skip to content

Commit f857cbc

Browse files
suchintanSuchintan Singh
andauthored
Add skyvern run dev command and superset workspace setup (#4593)
Co-authored-by: Suchintan Singh <suchintan@skyvern.com>
1 parent e96358c commit f857cbc

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

skyvern/cli/run_commands.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,103 @@ def run_ui() -> None:
163163
return
164164

165165

166+
@run_app.command(name="ui-dev")
167+
def run_ui_dev() -> None:
168+
"""Run the Skyvern UI server in development mode (npm run start-local)."""
169+
console.print(Panel("[bold blue]Starting Skyvern UI Server (dev mode)...[/bold blue]", border_style="blue"))
170+
try:
171+
with console.status("[bold green]Checking for existing process on port 8080...") as status:
172+
pids = get_pids_on_port(8080)
173+
if pids:
174+
status.stop()
175+
response = Confirm.ask("Process already running on port 8080. [yellow]Kill it?[/yellow]")
176+
if response:
177+
kill_pids(pids)
178+
console.print("✅ [green]Process killed.[/green]")
179+
else:
180+
console.print("[yellow]UI server not started. Process already running on port 8080.[/yellow]")
181+
return
182+
status.stop()
183+
except Exception as e: # pragma: no cover - CLI safeguards
184+
console.print(f"[red]Error checking for process: {e}[/red]")
185+
186+
frontend_env_path = resolve_frontend_env_path()
187+
if frontend_env_path is None:
188+
console.print("[bold red]ERROR: Skyvern Frontend directory not found.[/bold red]")
189+
return
190+
191+
frontend_dir = frontend_env_path.parent
192+
193+
os.chdir(frontend_dir)
194+
195+
try:
196+
console.print("📦 [bold blue]Running npm ci...[/bold blue]")
197+
subprocess.run("npm ci", shell=True, check=True)
198+
console.print("✅ [green]npm ci complete.[/green]")
199+
console.print("🚀 [bold blue]Starting npm UI server (start-local)...[/bold blue]")
200+
subprocess.run("npm run start-local", shell=True, check=True)
201+
except subprocess.CalledProcessError as e:
202+
console.print(f"[bold red]Error running UI server: {e}[/bold red]")
203+
return
204+
205+
166206
@run_app.command(name="all")
167207
def run_all() -> None:
168208
"""Run the Skyvern API server and UI server in parallel."""
169209
asyncio.run(start_services())
170210

171211

212+
@run_app.command(name="dev")
213+
def run_dev() -> None:
214+
"""Run the Skyvern API server and UI server in the background (detached).
215+
216+
This command starts both services and immediately returns control to your terminal.
217+
Use 'skyvern stop all' to stop the services.
218+
"""
219+
load_dotenv(resolve_backend_env_path())
220+
from skyvern.config import settings as skyvern_settings # noqa: PLC0415
221+
222+
console.print(Panel("[bold green]Starting Skyvern in development mode...[/bold green]", border_style="green"))
223+
224+
# Start server in background (detached) - call uvicorn directly
225+
server_process = subprocess.Popen(
226+
[
227+
"uvicorn",
228+
"skyvern.forge.api_app:create_api_app",
229+
"--host",
230+
"0.0.0.0",
231+
"--port",
232+
str(skyvern_settings.PORT),
233+
"--factory",
234+
],
235+
stdout=subprocess.DEVNULL,
236+
stderr=subprocess.DEVNULL,
237+
start_new_session=True,
238+
)
239+
console.print(f"✅ [green]Server started in background (PID: {server_process.pid})[/green]")
240+
241+
# Start UI (dev mode) in background (detached) - call npm directly
242+
frontend_env_path = resolve_frontend_env_path()
243+
if frontend_env_path is None:
244+
console.print("[bold red]ERROR: Skyvern Frontend directory not found.[/bold red]")
245+
return
246+
frontend_dir = frontend_env_path.parent
247+
248+
ui_process = subprocess.Popen(
249+
["npm", "run", "start-local"],
250+
cwd=frontend_dir,
251+
stdout=subprocess.DEVNULL,
252+
stderr=subprocess.DEVNULL,
253+
start_new_session=True,
254+
)
255+
console.print(f"✅ [green]UI (dev mode) started in background (PID: {ui_process.pid})[/green]")
256+
257+
console.print("\n🎉 [bold green]Skyvern is starting![/bold green]")
258+
console.print(f"🌐 [bold]API server:[/bold] [cyan]http://localhost:{skyvern_settings.PORT}[/cyan]")
259+
console.print("🖥️ [bold]UI:[/bold] [cyan]http://localhost:8080[/cyan]")
260+
console.print("\n[dim]Use 'skyvern stop all' to stop the services.[/dim]")
261+
262+
172263
@run_app.command(name="mcp")
173264
def run_mcp() -> None:
174265
"""Run the MCP server."""

0 commit comments

Comments
 (0)