LM Studio Tray Manager
Python Docstrings Documentation
This documentation provides detailed information about the functions and classes in the LM Studio Tray Manager project.
Note: the accompanying setup.sh script now
verifies GTK3/GObject typelibs and may prompt the user to install
gir1.2-gtk-3.0 and related packages before proceeding.
Last updated: 2026-03-02
Functions
load_version_from_dir
function
load_version_from_dir(base_dir)
Load app version from the VERSION file.
Args:
base_dir (str): Directory path containing the VERSION file.
Returns:
str: Version string read from the VERSION file, or DEFAULT_APP_VERSION
if the file is missing or empty.
_get_default_script_dir
function
_get_default_script_dir()
Get the default script directory.
Returns the directory containing the currently executing script,
or the current working directory if the script path cannot be determined.
Returns:
str: Absolute path to the script directory.
parse_args
function
parse_args()
Parse command-line arguments from sys.argv.
This function reads all arguments and flags provided on the command line
via sys.argv and returns them as a structured namespace object.
Command-line Arguments:
model (str): Model name to monitor; positional, optional.
script_dir (str): Script directory for logs; positional, optional.
--debug, -d (bool): Flag to enable debug logging.
--auto-start-daemon, -a (bool): Start daemon on launch.
--gui, -g (bool): Start LM Studio GUI on launch.
--version, -v (bool): Print version and exit.
--help (bool): Print help message and exit.
Returns:
argparse.Namespace: Parsed arguments as an object with attributes
matching argument names (e.g., namespace.model, namespace.debug).
Raises:
SystemExit: If --help or --version flags are used, or if the
argument parser encounters invalid arguments (handled by
argparse.ArgumentParser).
sync_app_state_for_tests
function
sync_app_state_for_tests(gtk_mod, glib_mod, app_mod, gdk_pixbuf_mod, script_dir_val, app_version_val, auto_start_val, gui_mode_val, api_host_val, api_port_val)
Synchronize test mocks with _AppState and module-level variables.
This public helper function allows tests to update both _AppState
(private class) and module-level variables in a coordinated way,
avoiding direct access to _AppState.
Args:
gtk_mod (ModuleType, optional): GTK module to set.
glib_mod (ModuleType, optional): GLib module to set.
app_mod (ModuleType, optional): AppIndicator3 module to set.
gdk_pixbuf_mod (ModuleType, optional): GdkPixbuf module to set.
script_dir_val (str, optional): script_dir value to set.
app_version_val (str, optional): APP_VERSION value to set.
auto_start_val (bool, optional): AUTO_START_DAEMON value to set.
gui_mode_val (bool, optional): GUI_MODE value to set.
api_host_val (str, optional): API host value to set.
api_port_val (int, optional): API port value to set.
Returns:
None.
get_app_version
function
get_app_version()
Load app version from VERSION file in script directory.
Reads the app version from the VERSION file located in the script
directory. Falls back to DEFAULT_APP_VERSION if the file is missing
or unreadable.
Returns:
str: Version string read from the VERSION file, or
DEFAULT_APP_VERSION if loading fails.
main
function
main()
Initialize module globals from CLI args and run the tray application.
Parses command-line arguments (from sys.argv) via parse_args(), loads
GTK dependencies, configures logging, and starts the GTK main loop.
Exits immediately when the --version flag is provided, without loading
GTK.
Raises:
SystemExit: When --version flag is provided (via sys.exit(0)).
get_asset_path
function
get_asset_path()
Locate asset file handling both PyInstaller and normal execution.
Searches in this order:
1. sys._MEIPASS/assets/... (PyInstaller bundle)
2. script_dir/assets/... (Release package or source dir)
3. Current working directory/assets/...
Args:
*path_components: Path components relative to assets/ directory.
Example: get_asset_path("img", "lm-studio-tray-manager.svg")
Returns:
str | None: Full path to the asset file if found, None otherwise.
_get_config_path
function
_get_config_path()
Return the user config file path in the home config directory.
_normalize_api_port
function
_normalize_api_port(value)
Normalize and validate the API port value.
load_config
function
load_config()
Load config values for the LM Studio API endpoint.
Updates _AppState.API_HOST and _AppState.API_PORT when valid values are
present in the config file.
save_config
function
save_config(api_host, api_port)
Persist config values for the LM Studio API endpoint.
_validate_url_scheme
function
_validate_url_scheme(url)
Validate that URL uses only permitted schemes (http/https).
Args:
url: URL string to validate.
Raises:
ValueError: If URL scheme is not http or https.
get_api_base_url
function
get_api_base_url()
Return the base URL for the LM Studio API endpoint.
Constructs the URL using the configured API_HOST and API_PORT
from _AppState.
Returns:
str: Base API URL in format
http://host:port
Raises:
ValueError: If the API host or port configuration is invalid.
get_api_models_url
function
get_api_models_url()
Return the full URL for the LM Studio API models endpoint.
get_authors
function
get_authors()
Load authors from AUTHORS file in script directory.
Reads the AUTHORS file located in _AppState.script_dir and parses
author names from markdown list format. If the file cannot be read
or contains no valid authors, a fallback list containing
APP_MAINTAINER is returned instead.
Returns:
list: List of author name strings extracted from the AUTHORS file.
If the file cannot be read or contains no valid authors,
returns a list containing APP_MAINTAINER as a fallback.
parse_version
function
parse_version(version)
Parse a version string into a comparable tuple of integers.
is_newer_version
function
is_newer_version(current, latest)
Return True when latest is newer than current.
_is_allowed_update_url
function
_is_allowed_update_url(url)
Validate update URL to prevent unsafe schemes or hosts.
Args:
url: URL string to validate.
Returns:
bool: True when the URL uses HTTPS and GitHub API host.
get_latest_release_version
function
get_latest_release_version()
Fetch the latest GitHub release tag name.
get_lms_cmd
function
get_lms_cmd()
Return the LM Studio CLI path if executable or resolve it from PATH.
get_llmster_cmd
function
get_llmster_cmd()
Return llmster executable path from PATH or LM Studio install dir.
get_pkill_cmd
function
get_pkill_cmd()
Return the absolute pkill path from PATH if available.
get_notify_send_cmd
function
get_notify_send_cmd()
Return the absolute notify-send path from PATH if available.
get_ps_cmd
function
get_ps_cmd()
Return the absolute ps path from PATH if available.
get_pgrep_cmd
function
get_pgrep_cmd()
Return the absolute pgrep path from PATH if available.
get_dpkg_cmd
function
get_dpkg_cmd()
Return the absolute dpkg path from PATH if available.
check_api_models
function
check_api_models()
Check if any models are loaded via LM Studio API.
Queries the configured API endpoint to check if models are loaded.
This is a fallback when 'lms ps' fails (e.g., desktop app running
without daemon).
Returns:
bool: True if at least one model is loaded, False otherwise.
_run_safe_command
function
_run_safe_command(command)
Run a pre-validated command list via subprocess.
The caller MUST ensure that ``command`` only contains trusted,
absolute-path executables resolved through helper functions.
Args:
command: List of strings forming the command.
Returns:
CompletedProcess: The completed process result.
Raises:
ValueError: If command format is invalid or executable is not
an absolute path.
is_llmster_running
function
is_llmster_running()
Return True when a llmster process is currently running.
get_desktop_app_pids
function
get_desktop_app_pids()
Return PIDs of LM Studio desktop app root processes.
kill_existing_instances
function
kill_existing_instances()
Terminate other running instances of this script.
apply_cli_args
function
apply_cli_args(cls, args)
Apply parsed command-line arguments to app state.
Args:
args (argparse.Namespace): Parsed command-line arguments.
Expected fields: model, script_dir, debug, gui,
auto_start_daemon.
Returns:
None.
set_gtk_modules
function
set_gtk_modules(cls, gtk_module, glib_module, app_indicator_module, gdk_pixbuf_module)
Store imported GTK-related module references on the class.
Args:
gtk_module (ModuleType): The Gtk module to store as cls.Gtk.
glib_module (ModuleType): The GLib module to store as cls.GLib.
app_indicator_module (ModuleType): The AppIndicator3 module
to store as cls.AppIndicator3.
gdk_pixbuf_module (ModuleType): The GdkPixbuf module to store
as cls.GdkPixbuf.
Returns:
None.
__init__
function
__init__(self)
Initialize tray indicator, menu, and periodic status checks.
_maybe_auto_start_daemon
function
_maybe_auto_start_daemon(self)
Start llmster daemon on launch when enabled.
_maybe_start_gui
function
_maybe_start_gui(self)
Start LM Studio GUI on launch when enabled.
begin_action_cooldown
function
begin_action_cooldown(self, action_name, seconds)
Prevent rapid double-triggering of tray actions.
_schedule_menu_refresh
function
_schedule_menu_refresh(self, delay_seconds)
Schedule a delayed menu refresh when GLib is available.
Args:
delay_seconds (int): Number of seconds to delay before
refreshing the menu. Defaults to 2 seconds.
build_menu
function
build_menu(self)
Build or rebuild the context menu with current status and
options.
get_daemon_status
function
get_daemon_status(self)
Check if llmster headless daemon is running.
Returns:
str: "running" if daemon process is active,
"stopped" if llmster is installed but daemon not running,
"not_found" if llmster is not installed.
get_desktop_app_status
function
get_desktop_app_status(self)
Check if LM Studio desktop app is running.
The desktop app is started via lmstudio_autostart.sh --gui or directly,
and runs WITHOUT the --run-as-service flag.
This is different from the headless daemon (--run-as-service).
Returns:
str: "running" if desktop app process is active,
"stopped" if installed but not running,
"not_found" if not installed.
get_status_indicator
function
get_status_indicator(self, status)
Convert status string to emoji indicator.
Args:
status: "running", "stopped", or "not_found"
Returns:
str: Emoji indicator (🟢 running, 🟡 stopped, 🔴 not_found)
_run_validated_command
function
_run_validated_command(command)
Run a pre-validated command list via subprocess.
The caller MUST ensure that ``command`` only contains trusted,
absolute-path executables resolved through ``get_lms_cmd``,
``get_llmster_cmd`` or equivalent helpers.
Args:
command: List of strings forming the command.
Returns:
CompletedProcess: The completed process result.
Raises:
ValueError: If command format is invalid or executable is not
absolute path.
_run_daemon_attempts
function
_run_daemon_attempts(self, attempts, stop_when)
Run daemon command attempts until a condition is met.
Args:
attempts: Ordered list of command argument lists.
stop_when: Callable that receives the subprocess result and
returns True when no further attempts are needed.
Returns:
CompletedProcess | None: Last command result, or None if no
command was executed.
_build_daemon_attempts
function
_build_daemon_attempts(self, action)
Build ordered daemon CLI attempts for one action.
Args:
action: Either "start" or "stop".
Returns:
list[list[str]]: Commands to try in order.
_force_stop_llmster
function
_force_stop_llmster(self)
Force-stop llmster and wait briefly for process exit.
_stop_llmster_best_effort
function
_stop_llmster_best_effort(self)
Stop llmster with graceful attempts and force-stop fallback.
Returns:
tuple[bool, CompletedProcess | None]: Tuple containing:
- True when llmster is no longer running.
- Last command result used during stop attempts.
_stop_desktop_app_processes
function
_stop_desktop_app_processes(self)
Stop LM Studio desktop processes using TERM, then KILL.
Returns:
bool: True when the desktop app is no longer running.
start_daemon
function
start_daemon(self, _widget)
Start the headless daemon.
Stops the desktop app first if needed, then tries daemon start
variants and notifies on success/failure.
Args:
_widget: Widget that triggered the action (unused).
stop_daemon
function
stop_daemon(self, _widget)
Stop the headless daemon.
Tries graceful stop variants first and falls back to force-stop.
Args:
_widget: Widget that triggered the action (unused).
start_desktop_app
function
start_desktop_app(self, _widget)
Start the LM Studio desktop app.
Stops the daemon first if needed, locates the app (.deb or AppImage),
and launches it with user notification.
Args:
_widget: Widget that triggered the action (unused).
stop_desktop_app
function
stop_desktop_app(self, _widget)
Stop the LM Studio desktop app process.
Useful when the window closes to tray but the process remains active.
Args:
_widget: Widget that triggered the action (unused).
quit_app
function
quit_app(self, _widget)
Handle the tray quit action by logging and exiting the Gtk main
loop.
show_status_dialog
function
show_status_dialog(self, _widget)
Show a GTK message dialog containing the LM Studio CLI status output.
Runs `lms ps` to retrieve status information. If daemon is not
running, falls back to querying the LM Studio API directly.
Formats a friendly message on success or error, and displays it in
an informational dialog. Errors are caught and shown to the user
instead of raising.
show_about_dialog
function
show_about_dialog(self, _widget)
Show application information in a GTK dialog.
show_config_dialog
function
show_config_dialog(self, _widget)
Show configuration dialog for LM Studio API endpoint.
get_version_label
function
get_version_label(self)
Return version text with update status for the About dialog.
Returns:
str: Version text in the format '<APP_VERSION> (<status>)'.
_check_updates_tick
function
_check_updates_tick(self)
Run the update check for scheduled timers.
_initial_update_check
function
_initial_update_check(self)
Run a single update check shortly after startup.
_format_update_check_message
function
_format_update_check_message(self, status, latest, error)
Build the update check notification message.
manual_check_updates
function
manual_check_updates(self, _widget)
Run update check on demand and notify about the result.
check_updates
function
check_updates(self)
Check GitHub for a newer release and notify the user.
Returns:
bool: True if a notification was sent.
check_model
function
check_model(self)
Check LM Studio runtime/model status and update tray icon.
Updates the tray icon using this schema:
- FAIL: neither daemon nor desktop app is installed
- WARN: neither daemon nor desktop app is running
- INFO: daemon or desktop app is running, but no model loaded
- OK: a model is loaded
Sends desktop notifications when status changes from a
previous non-None state, and logs status changes and errors.
Returns:
bool: True to indicate the check completed (used for
scheduled callbacks).
_get_writable_logs_dir
function
_get_writable_logs_dir(base_script_dir)
Get a writable directory for logs.
If base_script_dir is writable, returns base_script_dir/.logs.
Otherwise (e.g., in AppImage), returns a writable location
in the user's home directory.
Args:
base_script_dir (str): The script directory to check.
Returns:
str: Absolute path to a writable logs directory.
_ensure_gsettings_schema
function
_ensure_gsettings_schema()
Set GSETTINGS_SCHEMA_DIR if not already set and schemas exist.
This prevents GSettings crashes when running PyInstaller binaries
on systems where GTK tries to load missing schema keys.
Returns:
None.
_copy_to_clipboard
function
_copy_to_clipboard(url)
Open *url* in the default web browser.
Historically this helper copied the link to the clipboard; the
behaviour was updated to perform an indirect open instead. It remains
easily monkey-patchable for unit tests.
_activate_link
function
_activate_link(url)
Open a link from GTK dialogs and report success.
Args:
url (str): URL from the activate-link signal.
Returns:
bool: True when the URL open was attempted successfully.
get_release_url
function
get_release_url(tag)
Return a GitHub URL for a release.
Args:
tag (str, optional): A release tag name (e.g. "v1.2.3"). If
provided the URL will point directly to that tag. If omitted
the generic ``/releases/latest`` URL is returned, which
GitHub redirects to the newest release.
Returns:
str: Absolute URL to the desired release page.
_has_loaded_model
function
_has_loaded_model(output)
Return True if ``lms ps`` output indicates a loaded model.
Some releases of the CLI print *all* available models even when none
are actually loaded. Other releases explicitly say "No models are
currently loaded.". We treat such outputs as *not* containing a
loaded model; a debug log entry is emitted so the behavior is
traceable.
_api_loaded_model_names
function
_api_loaded_model_names(models)
Return model names that are explicitly marked as loaded.
LM Studio API responses may include *available* models that are not
currently loaded. To avoid false positives, we only treat a model as
loaded when there is explicit evidence in the model object.
Args:
models: Parsed ``data`` list from the API response.
Returns:
list[str]: Names/ids for models explicitly marked as loaded.
Classes
_AppState
class
_AppState()
Mutable application state shared across the module.
Methods:
apply_cli_args()
Apply parsed command-line arguments to app state.
Args:
args (argparse.Namespace): Parsed command-line arguments.
Expected fields: model, script_dir, debug, gui,
auto_start_daemon.
Returns:
None.
set_gtk_modules()
Store imported GTK-related module references on the class.
Args:
gtk_module (ModuleType): The Gtk module to store as cls.Gtk.
glib_module (ModuleType): The GLib module to store as cls.GLib.
app_indicator_module (ModuleType): The AppIndicator3 module
to store as cls.AppIndicator3.
gdk_pixbuf_module (ModuleType): The GdkPixbuf module to store
as cls.GdkPixbuf.
Returns:
None.
__init__()
Initialize tray indicator, menu, and periodic status checks.
_maybe_auto_start_daemon()
Start llmster daemon on launch when enabled.
_maybe_start_gui()
Start LM Studio GUI on launch when enabled.
begin_action_cooldown()
Prevent rapid double-triggering of tray actions.
_can_use_lms_ps()
Return True when running ``lms ps`` is currently safe/useful.
_schedule_menu_refresh()
Schedule a delayed menu refresh when GLib is available.
Args:
delay_seconds (int): Number of seconds to delay before
refreshing the menu. Defaults to 2 seconds.
build_menu()
Build or rebuild the context menu with current status and
options.
get_daemon_status()
Check if llmster headless daemon is running.
Returns:
str: "running" if daemon process is active,
"stopped" if llmster is installed but daemon not running,
"not_found" if llmster is not installed.
get_desktop_app_status()
Check if LM Studio desktop app is running.
The desktop app is started via lmstudio_autostart.sh --gui or directly,
and runs WITHOUT the --run-as-service flag.
This is different from the headless daemon (--run-as-service).
Returns:
str: "running" if desktop app process is active,
"stopped" if installed but not running,
"not_found" if not installed.
get_status_indicator()
Convert status string to emoji indicator.
Args:
status: "running", "stopped", or "not_found"
Returns:
str: Emoji indicator (🟢 running, 🟡 stopped, 🔴 not_found)
_run_validated_command()
Run a pre-validated command list via subprocess.
The caller MUST ensure that ``command`` only contains trusted,
absolute-path executables resolved through ``get_lms_cmd``,
``get_llmster_cmd`` or equivalent helpers.
Args:
command: List of strings forming the command.
Returns:
CompletedProcess: The completed process result.
Raises:
ValueError: If command format is invalid or executable is not
absolute path.
_run_daemon_attempts()
Run daemon command attempts until a condition is met.
Args:
attempts: Ordered list of command argument lists.
stop_when: Callable that receives the subprocess result and
returns True when no further attempts are needed.
Returns:
CompletedProcess | None: Last command result, or None if no
command was executed.
_build_daemon_attempts()
Build ordered daemon CLI attempts for one action.
Args:
action: Either "start" or "stop".
Returns:
list[list[str]]: Commands to try in order.
_force_stop_llmster()
Force-stop llmster and wait briefly for process exit.
_stop_llmster_best_effort()
Stop llmster with graceful attempts and force-stop fallback.
Returns:
tuple[bool, CompletedProcess | None]: Tuple containing:
- True when llmster is no longer running.
- Last command result used during stop attempts.
_stop_daemon_with_notification()
Stop daemon and show notification on success/failure.
Single source of truth for daemon-stop logic with user notifications.
Used by both stop_daemon() menu action and start_desktop_app() to
ensure consistent daemon-stopping behavior.
Returns:
tuple[bool, CompletedProcess | None]: (stopped, result)
from _stop_llmster_best_effort().
_stop_desktop_app_processes()
Stop LM Studio desktop processes using TERM, then KILL.
Returns:
bool: True when the desktop app is no longer running.
start_daemon()
Start the headless daemon.
Stops the desktop app first if needed, then tries daemon start
variants and notifies on success/failure.
Args:
_widget: Widget that triggered the action (unused).
stop_daemon()
Stop the headless daemon.
Tries graceful stop variants first and falls back to force-stop.
Args:
_widget: Widget that triggered the action (unused).
start_desktop_app()
Start the LM Studio desktop app.
Stops the daemon first if needed, locates the app (.deb or AppImage),
and launches it with user notification.
Args:
_widget: Widget that triggered the action (unused).
_start_desktop_app_body()
Background thread body for start_desktop_app.
Stops the daemon first using _stop_daemon_with_notification(),
locates the app (.deb or AppImage), and launches it.
All GTK menu updates are posted back to the main loop via
GLib.idle_add() so this method is safe to call from any thread.
stop_desktop_app()
Stop the LM Studio desktop app process.
Useful when the window closes to tray but the process remains active.
Args:
_widget: Widget that triggered the action (unused).
quit_app()
Handle the tray quit action by logging and exiting the Gtk main
loop.
show_status_dialog()
Show a GTK message dialog containing the LM Studio CLI status output.
Runs `lms ps` to retrieve status information. If daemon is not
running, falls back to querying the LM Studio API directly.
Formats a friendly message on success or error, and displays it in
an informational dialog. Errors are caught and shown to the user
instead of raising.
show_about_dialog()
Show application information in a GTK dialog.
show_config_dialog()
Show configuration dialog for LM Studio API endpoint.
get_version_label()
Return version text with update status for the About dialog.
Returns:
str: Version text in the format '<APP_VERSION> (<status>)'.
_check_updates_tick()
Run the update check for scheduled timers.
_initial_update_check()
Run a single update check shortly after startup.
_format_update_check_message()
Build the update check notification message.
manual_check_updates()
Run update check on demand and notify about the result.
check_updates()
Check GitHub for a newer release and notify the user.
Returns:
bool: True if a notification was sent.
check_model()
Check LM Studio runtime/model status and update tray icon.
Updates the tray icon using this schema:
- FAIL: neither daemon nor desktop app is installed
- WARN: neither daemon nor desktop app is running
- INFO: daemon or desktop app is running, but no model loaded
- OK: a model is loaded
Sends desktop notifications when status changes from a
previous non-None state, and logs status changes and errors.
Returns:
bool: True to indicate the check completed (used for
scheduled callbacks).
TrayIcon
class
TrayIcon()
Manage the GTK tray icon for LM Studio runtime monitoring.
The tray displays runtime status, provides daemon/app controls, and sends
desktop notifications on status transitions.
Methods:
apply_cli_args()
Apply parsed command-line arguments to app state.
Args:
args (argparse.Namespace): Parsed command-line arguments.
Expected fields: model, script_dir, debug, gui,
auto_start_daemon.
Returns:
None.
set_gtk_modules()
Store imported GTK-related module references on the class.
Args:
gtk_module (ModuleType): The Gtk module to store as cls.Gtk.
glib_module (ModuleType): The GLib module to store as cls.GLib.
app_indicator_module (ModuleType): The AppIndicator3 module
to store as cls.AppIndicator3.
gdk_pixbuf_module (ModuleType): The GdkPixbuf module to store
as cls.GdkPixbuf.
Returns:
None.
__init__()
Initialize tray indicator, menu, and periodic status checks.
_maybe_auto_start_daemon()
Start llmster daemon on launch when enabled.
_maybe_start_gui()
Start LM Studio GUI on launch when enabled.
begin_action_cooldown()
Prevent rapid double-triggering of tray actions.
_can_use_lms_ps()
Return True when running ``lms ps`` is currently safe/useful.
_schedule_menu_refresh()
Schedule a delayed menu refresh when GLib is available.
Args:
delay_seconds (int): Number of seconds to delay before
refreshing the menu. Defaults to 2 seconds.
build_menu()
Build or rebuild the context menu with current status and
options.
get_daemon_status()
Check if llmster headless daemon is running.
Returns:
str: "running" if daemon process is active,
"stopped" if llmster is installed but daemon not running,
"not_found" if llmster is not installed.
get_desktop_app_status()
Check if LM Studio desktop app is running.
The desktop app is started via lmstudio_autostart.sh --gui or directly,
and runs WITHOUT the --run-as-service flag.
This is different from the headless daemon (--run-as-service).
Returns:
str: "running" if desktop app process is active,
"stopped" if installed but not running,
"not_found" if not installed.
get_status_indicator()
Convert status string to emoji indicator.
Args:
status: "running", "stopped", or "not_found"
Returns:
str: Emoji indicator (🟢 running, 🟡 stopped, 🔴 not_found)
_run_validated_command()
Run a pre-validated command list via subprocess.
The caller MUST ensure that ``command`` only contains trusted,
absolute-path executables resolved through ``get_lms_cmd``,
``get_llmster_cmd`` or equivalent helpers.
Args:
command: List of strings forming the command.
Returns:
CompletedProcess: The completed process result.
Raises:
ValueError: If command format is invalid or executable is not
absolute path.
_run_daemon_attempts()
Run daemon command attempts until a condition is met.
Args:
attempts: Ordered list of command argument lists.
stop_when: Callable that receives the subprocess result and
returns True when no further attempts are needed.
Returns:
CompletedProcess | None: Last command result, or None if no
command was executed.
_build_daemon_attempts()
Build ordered daemon CLI attempts for one action.
Args:
action: Either "start" or "stop".
Returns:
list[list[str]]: Commands to try in order.
_force_stop_llmster()
Force-stop llmster and wait briefly for process exit.
_stop_llmster_best_effort()
Stop llmster with graceful attempts and force-stop fallback.
Returns:
tuple[bool, CompletedProcess | None]: Tuple containing:
- True when llmster is no longer running.
- Last command result used during stop attempts.
_stop_daemon_with_notification()
Stop daemon and show notification on success/failure.
Single source of truth for daemon-stop logic with user notifications.
Used by both stop_daemon() menu action and start_desktop_app() to
ensure consistent daemon-stopping behavior.
Returns:
tuple[bool, CompletedProcess | None]: (stopped, result)
from _stop_llmster_best_effort().
_stop_desktop_app_processes()
Stop LM Studio desktop processes using TERM, then KILL.
Returns:
bool: True when the desktop app is no longer running.
start_daemon()
Start the headless daemon.
Stops the desktop app first if needed, then tries daemon start
variants and notifies on success/failure.
Args:
_widget: Widget that triggered the action (unused).
stop_daemon()
Stop the headless daemon.
Tries graceful stop variants first and falls back to force-stop.
Args:
_widget: Widget that triggered the action (unused).
start_desktop_app()
Start the LM Studio desktop app.
Stops the daemon first if needed, locates the app (.deb or AppImage),
and launches it with user notification.
Args:
_widget: Widget that triggered the action (unused).
_start_desktop_app_body()
Background thread body for start_desktop_app.
Stops the daemon first using _stop_daemon_with_notification(),
locates the app (.deb or AppImage), and launches it.
All GTK menu updates are posted back to the main loop via
GLib.idle_add() so this method is safe to call from any thread.
stop_desktop_app()
Stop the LM Studio desktop app process.
Useful when the window closes to tray but the process remains active.
Args:
_widget: Widget that triggered the action (unused).
quit_app()
Handle the tray quit action by logging and exiting the Gtk main
loop.
show_status_dialog()
Show a GTK message dialog containing the LM Studio CLI status output.
Runs `lms ps` to retrieve status information. If daemon is not
running, falls back to querying the LM Studio API directly.
Formats a friendly message on success or error, and displays it in
an informational dialog. Errors are caught and shown to the user
instead of raising.
show_about_dialog()
Show application information in a GTK dialog.
show_config_dialog()
Show configuration dialog for LM Studio API endpoint.
get_version_label()
Return version text with update status for the About dialog.
Returns:
str: Version text in the format '<APP_VERSION> (<status>)'.
_check_updates_tick()
Run the update check for scheduled timers.
_initial_update_check()
Run a single update check shortly after startup.
_format_update_check_message()
Build the update check notification message.
manual_check_updates()
Run update check on demand and notify about the result.
check_updates()
Check GitHub for a newer release and notify the user.
Returns:
bool: True if a notification was sent.
check_model()
Check LM Studio runtime/model status and update tray icon.
Updates the tray icon using this schema:
- FAIL: neither daemon nor desktop app is installed
- WARN: neither daemon nor desktop app is running
- INFO: daemon or desktop app is running, but no model loaded
- OK: a model is loaded
Sends desktop notifications when status changes from a
previous non-None state, and logs status changes and errors.
Returns:
bool: True to indicate the check completed (used for
scheduled callbacks).