diff --git a/README.md b/README.md new file mode 100644 index 0000000..d988365 --- /dev/null +++ b/README.md @@ -0,0 +1,145 @@ +# Catser 🐾 + +A Windows desktop cat companion inspired by [Workcat](https://workcat.app/en/#how) and [Desktop Goose](https://github.com/arkangel-dev/desktop-goose-source). + +**Catser** wanders across your Windows desktop, interacts with you, and automatically monitors your active windows using [ActivityWatch](https://activitywatch.net/) (with a native Windows API fallback). When it spots drift content like **YouTube Shorts**, **Instagram Reels**, or **TikTok**, the cat perks up in alert, sprints and leaps to the target window's close button `[X]`, and **closes the window with a swift paw strike!** + +--- + +## Features + +- 🐱 **Authentic Workcat Animations**: + - **Walk Cycle**: 30 smooth SVG silhouette frames with antialiased vector rasterization and natural cadence. + - **Paw Strike**: 17 WebP animation frames at 24 FPS with contact triggered on **Frame 14** (`PAW_CONTACT_FRAME`). + - **Scruff Dragging**: Pick up the cat by its neck scruff (`scruff.webp`) and move it anywhere on your screen. + - **Gravity Physics**: When released in mid-air, the cat falls back down to the desktop floor with quadratic acceleration (`t²`). + - **Interactive Petting**: Click the cat without dragging to see happy eyes (`FACE_HAPPY`) and a rising floating heart particle (`♥`). + - **Autonomous Life Actions**: Sits, sleeps (with floating `z` snoring particle), stretches (37 frames), and flicks its tail (37 frames). + - **6 Coat Colors**: Ivory, Charcoal, Grey, Apricot, Sage, and Plum. + +- ⏱️ **ActivityWatch Backend**: + - Connects to `http://localhost:5600/api/0` and discovers active `aw-watcher-window_*` buckets. + - Monitors active application executables and window titles in real-time. + - **Zero-Config Fallback**: If ActivityWatch is offline or not installed, Catser automatically falls back to native Windows OS APIs (`GetForegroundWindow`, `GetWindowTextW`), ensuring it works right out of the box. + +- 🎯 **Pinpoint Targeting & Window Closing**: + - Catser calculates the exact screen coordinates of the target window's `[X]` close button. + - Applies Workcat's contact offset formula: + $$\text{offset}_x = \text{width} \times 1.0858$$ + $$\text{offset}_y = \text{height} \times 0.3874$$ + - Sprints diagonally across your screen to reach the close button, strikes it with its paw, and dispatches native `WM_CLOSE` to close the distracting app. + +- 🪟 **High-Performance Transparent Overlay**: + - Built with Win32 Layered Windows (`WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE`). + - Uses `UpdateLayeredWindow` with 32-bit ARGB premultiplied alpha for clean anti-aliased fur edges, soft contact shadows, and tear-free 60 FPS rendering. + - Pixel-perfect hit-testing allows mouse clicks on transparent regions to pass through to your apps, while clicking the cat itself allows dragging and petting. + +--- + +## Quickstart + +### Prerequisites +- Windows 10 or Windows 11 +- Python 3.10+ (Python 3.14 fully supported) +- [ActivityWatch](https://activitywatch.net/) *(optional, runs with native fallback if not active)* + +### Installation + +Clone the repository and install required dependencies: + +```bash +git clone https://github.com/yourusername/Catser.git +cd Catser +py -m pip install pillow +``` + +### Running Catser + +Run Catser with default settings (Ivory coat, closes Shorts/Reels/TikTok): + +```bash +py run_catser.py +``` + +Run in **Test Mode** (demonstrates an attack sprint and paw strike in 5 seconds): + +```bash +py run_catser.py --test +``` + +--- + +## CLI Options & Customization + +| Flag | Options | Default | Description | +|------|---------|---------|-------------| +| `--coat` | `ivory`, `charcoal`, `grey`, `apricot`, `sage`, `plum` | `ivory` | Choose the cat's fur coat color. | +| `--action` | `close`, `minimize`, `notify` | `close` | Action to take when the paw strikes the window. | +| `--aw-url` | URL string | `http://localhost:5600` | ActivityWatch server endpoint. | +| `--add-keyword` | keyword string | *None* | Add custom window title keyword to close. | +| `--width` | integer | `144` | Rendered width of the cat in pixels. | +| `--test` | *flag* | *False* | Launch in test demonstration mode. | +| `--verbose`, `-v` | *flag* | *False* | Enable debug logging output. | + +### Examples + +**Select a Charcoal cat that minimizes windows instead of closing them:** +```bash +py run_catser.py --coat charcoal --action minimize +``` + +**Add custom distraction targets (e.g. Steam, Reddit, Netflix):** +```bash +py run_catser.py --add-keyword "steam" --add-keyword "netflix" --add-keyword "reddit" +``` + +--- + +## User Interaction & Controls + +- **Drag the Cat**: Click and drag the cat anywhere on your desktop. It switches to the scruff sprite (`scruff.webp`). When released, it falls back down to your taskbar. +- **Pet the Cat**: Click the cat once without moving your mouse. It will purr, show smiling eyes (`^^`), emit a floating heart particle, and flick its tail. +- **Exit**: Press `Ctrl+C` in the terminal to close Catser cleanly. + +--- + +## Architecture & Codebase Overview + +``` +Catser/ +├── run_catser.py # CLI launcher and entry point +├── README.md # Project documentation +├── .gitignore # Git ignore rules +└── catser/ + ├── __init__.py # Package version and metadata + ├── config.py # Constants, kinematics, coats, and distraction rules + ├── assets_manager.py # Workcat sprite pipeline (vector rasterization & WebP frames) + ├── window_manager.py # Win32 window handles, geometry, and WM_CLOSE dispatcher + ├── activitywatch.py # ActivityWatch REST client with native Win32 fallback + ├── overlay.py # Win32 32-bit ARGB layered window overlay + ├── cat_controller.py # State machine, trajectory kinematics, and paw attack + ├── app.py # 60 FPS animation loop and coordinator + └── assets/ # Bundled sprite animations (walk, paw, tail, stretch, scruff) +``` + +--- + +## Technical Details + +### Kinematic & Physics Constants +Sourced directly from Workcat's engine (`apps/desktop/src/features/pet-mode/petModeData.ts` and `cat.js`): +- `WALK_SPEED = 20.8` (stride = `26.0`, cadence = `0.9`) +- `RUN_SPEED = 300.0` (stride = `72.0`) +- `PAW_FPS = 24` (17 total frames, contact at index `14`) +- `CONTACT_RATIO_X = (143.0 - 11.4) / 121.2 ≈ 1.0858` +- `CONTACT_RATIO_Y = (40.0 - 4.2) / 92.4 ≈ 0.3874` +- `ALERT_HOLD_MS = 620ms` + +### Win32 Window Closing +On contact frame 14, Catser issues both `WM_CLOSE` (`0x0010`) and `WM_SYSCOMMAND / SC_CLOSE` (`0x0112 / 0xF060`) to the target window's handle (`HWND`), ensuring smooth closing across standard Win32 apps and Chromium browsers. + +--- + +## License + +MIT License. Sprite assets courtesy of [Workcat](https://workcat.app).