""" Catser Launcher and CLI Interface. Usage: py run_catser.py # Run Catser with default settings py run_catser.py --test # Test mode: triggers an immediate attack run & paw swipe py run_catser.py --coat charcoal # Run with Charcoal coat py run_catser.py --action minimize # Minimize distraction windows instead of closing py run_catser.py --help # View all options """ import sys import argparse import logging from catser.config import Config, COATS from catser.app import CatserApp def setup_logging(verbose: bool = False) -> None: """Configures console logging format.""" level = logging.DEBUG if verbose else logging.INFO logging.basicConfig( level=level, format="[%(asctime)s] [%(levelname)s] %(name)s: %(message)s", datefmt="%H:%M:%S", ) def main() -> None: """CLI entry point for Catser.""" parser = argparse.ArgumentParser( prog="Catser", description="Desktop Cat Companion that closes Shorts, Reels, and distracting windows via ActivityWatch!", ) parser.add_argument( "--coat", choices=list(COATS.keys()), default="ivory", help="Select cat coat color (default: ivory)", ) parser.add_argument( "--action", choices=["close", "minimize", "notify"], default="close", help="Action to perform when cat hits the window (default: close)", ) parser.add_argument( "--aw-url", default="http://localhost:5600", help="ActivityWatch server URL (default: http://localhost:5600)", ) parser.add_argument( "--add-keyword", action="append", dest="extra_keywords", help="Add additional window title keywords to target as distractions", ) parser.add_argument( "--width", type=int, default=144, help="Width of the cat on screen in pixels (default: 144)", ) parser.add_argument( "--test", action="store_true", help="Run in test mode: launches Catser, performs a test sprint & paw swipe, and runs for 6 seconds", ) parser.add_argument( "--verbose", "-v", action="store_true", help="Enable detailed debug logging", ) args = parser.parse_args() setup_logging(args.verbose) config = Config( aw_url=args.aw_url, action_on_hit=args.action, coat_name=args.coat, cat_width=args.width, ) if args.extra_keywords: config.distraction_keywords.extend(args.extra_keywords) print("=" * 60) print(" Catser - Desktop Cat Companion for Windows") print(f" Coat: {config.coat_name.capitalize()} | Action: {config.action_on_hit.upper()}") print(f" ActivityWatch: {config.aw_url}") print(f" Targets: {', '.join(config.distraction_keywords)}") print("=" * 60) print(" Controls:") print(" - Drag cat: Click and drag with mouse (picks up by scruff)") print(" - Pet cat: Click once without dragging (happy reaction)") print(" - Exit: Press Ctrl+C in this terminal") print("=" * 60) app = CatserApp(config) app.initialize() if args.test: print("[TEST MODE] Triggering test attack to top-right screen in 1.5s...") # Schedule test attack after brief delay import threading def _demo(): import time time.sleep(1.5) app.trigger_test_attack() threading.Thread(target=_demo, daemon=True).start() app.run(max_seconds=6.0) else: app.run() if __name__ == "__main__": main()