#!/usr/bin/env python3 """ Simple script to launch an application or focus it if already running in niri Usage: niri-launch-or-focus [--class CLASS] [--title TITLE] [args...] Examples: niri-launch-or-focus firefox niri-launch-or-focus code --class Code --title "My Project" niri-launch-or-focus kitty --class kitty """ import argparse import json import subprocess import sys def find_window(class_name=None, title=None, app_name=None): """Find window by app_id (class), title, or app name.""" try: result = subprocess.run( ["niri", "msg", "--json", "windows"], capture_output=True, text=True, check=False, ) windows_json = result.stdout.strip() if not windows_json or windows_json == "[]": return None windows = json.loads(windows_json) for window in windows: app_id = window.get("app_id", "").lower() if class_name: if app_id == class_name.lower(): return window.get("id") elif title: if window.get("title") == title: return window.get("id") elif app_name: if app_id == app_name.lower(): return window.get("id") return None except (json.JSONDecodeError, subprocess.SubprocessError, KeyError): return None def focus_window(window_id): """Focus a window by ID.""" subprocess.run( ["niri", "msg", "action", "focus-window", "--id", str(window_id)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) def launch_command(command, args): """Launch a command in the background.""" subprocess.Popen( [command] + args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True, ) def main(): parser = argparse.ArgumentParser( description="Launch an application or focus it if already running in niri" ) parser.add_argument("command", help="Command to run") parser.add_argument("--class", dest="class_name", help="Window class (app_id)") parser.add_argument("--title", help="Window title") parser.add_argument("args", nargs=argparse.REMAINDER, help="Additional arguments for command") args = parser.parse_args() # Extract app name from command (basename) app_name = args.command.split("/")[-1] # Try to find existing window window_id = find_window( class_name=args.class_name, title=args.title, app_name=app_name if not args.class_name and not args.title else None, ) # Build command arguments cmd_args = [] if args.class_name: cmd_args.append(f"--class={args.class_name}") if args.title: cmd_args.append(f"--title={args.title}") cmd_args.extend(args.args) # Focus if found, otherwise launch if window_id: focus_window(window_id) else: launch_command(args.command, cmd_args) if __name__ == "__main__": main()