From dc48578c7e2443f7a37f64be2559d5a886906a8f Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 29 Apr 2026 01:24:54 +0000 Subject: [PATCH] feat: launch Chrome in app mode for chromeless window python -m src.gui now opens Chrome with --app flag, hiding the address bar, tabs, and bookmarks bar. Falls back to default browser if Chrome is not found. Headless flag passed via CLI so streamlit run directly still auto-opens normally. Co-Authored-By: Claude Opus 4.6 --- src/gui/__main__.py | 66 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/gui/__main__.py b/src/gui/__main__.py index c230e93..0f4b346 100644 --- a/src/gui/__main__.py +++ b/src/gui/__main__.py @@ -1,8 +1,70 @@ -"""Allow running as ``python -m src.gui``.""" +"""Allow running as ``python -m src.gui``. +Launches Streamlit with headless=true and opens Chrome in --app mode +so the window has no address bar, tabs, or bookmarks — looks like a +native desktop app. +""" + +import os +import shutil import subprocess import sys +import threading +import time from pathlib import Path +_URL = "http://localhost:8501" + + +def _find_chrome() -> str | None: + """Return the path to a Chrome/Chromium executable, or None.""" + # Check PATH first + for name in ("chrome", "google-chrome", "google-chrome-stable", "chromium", "chromium-browser"): + found = shutil.which(name) + if found: + return found + + # Windows common install locations + if sys.platform == "win32": + candidates = [ + Path(os.environ.get("PROGRAMFILES", r"C:\Program Files")) + / "Google" / "Chrome" / "Application" / "chrome.exe", + Path(os.environ.get("PROGRAMFILES(X86)", r"C:\Program Files (x86)")) + / "Google" / "Chrome" / "Application" / "chrome.exe", + Path(os.environ.get("LOCALAPPDATA", "")) + / "Google" / "Chrome" / "Application" / "chrome.exe", + ] + for c in candidates: + if c.exists(): + return str(c) + + # macOS + if sys.platform == "darwin": + mac_chrome = Path("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome") + if mac_chrome.exists(): + return str(mac_chrome) + + return None + + +def _open_app_window() -> None: + """Wait for the server, then open Chrome in app mode (no address bar).""" + time.sleep(2) + chrome = _find_chrome() + if chrome: + subprocess.Popen([chrome, f"--app={_URL}"]) + else: + # Fallback: open in default browser (will have address bar) + import webbrowser + webbrowser.open(_URL) + + app_path = Path(__file__).parent / "app.py" -subprocess.run([sys.executable, "-m", "streamlit", "run", str(app_path)]) + +# Open the browser in a background thread so it doesn't block Streamlit +threading.Thread(target=_open_app_window, daemon=True).start() + +subprocess.run([ + sys.executable, "-m", "streamlit", "run", str(app_path), + "--server.headless", "true", +])