# Scripts reference

## Launch parameters

```bash
python3 <skillPath>/scripts/open_chrome.py <page> [W H X Y] [--session=<session_id>] [--launcher=<auto|spawn|apple|manual>]
# page      : register | verify
# W H       : window width / height (defaults to 500×500)
# X Y       : window position (defaults to centered)
# --session : unique session_id (UUID) injected by the AI; used to match the result of this run
# --launcher: launcher strategy (default: auto). Rarely needed — only for debugging.
#             auto   = auto-detect (macOS restricted TCC context → apple, otherwise spawn)
#             spawn  = direct Popen of Chrome with isolated user-data-dir + --app pure window
#             apple  = macOS-only AppleScript that opens a window in the user's running Chrome
#             manual = HTTP server only, prints URL for the user to open manually
```

## Launcher strategies

| Strategy | Best for | How |
|---|---|---|
| `spawn` | Plain terminal / non-Electron clients on any OS | Popen Chrome binary with isolated `--user-data-dir`; pre-writes camera/mic whitelist via `init-chrome-prefs.py` so the very first request does not even prompt. |
| `apple` | macOS Electron clients (WorkBuddy / CodeBuddy / VS Code etc.) where parent's TCC context blocks camera | Runs `osascript` so Chrome opens a new window from its already-running main process — TCC attributes to Chrome itself. |
| `manual` | Last-resort fallback (no auto-launcher worked) | Just starts the HTTP server and prints the URL. User opens it in their own browser. |
| `auto` | Default | macOS: detects restricted TCC via env vars (`ELECTRON_RUN_AS_NODE`, `__CFBundleIdentifier`), `$HOME` containment in `Containers/`, and parent process chain → picks `apple`; otherwise `spawn`. Other OSes: always `spawn`. |

## Process lifecycle

```
open_chrome.py starts
  ├── Resolve launcher (auto-detect or explicit --launcher=)
  ├── (spawn only) Kill leftover Chrome with same user_dir + previous open_chrome.py (excluding self)
  ├── (spawn only) Patch Chrome Preferences with camera/mic whitelist
  ├── Start a local HTTP server on port 51823 (random fallback if occupied)
  ├── Read credentials (token / userid) from creds.py (refuse to start if missing)
  ├── Accept the AI-provided session_id (or generate a fallback one)
  ├── Open the verification window via the chosen launcher
  └── Block until the page POSTs /result (5-min timeout) → print RESULT JSON and exit
```

> If Chrome (in `spawn` mode) is closed without producing a result, the Python process exits within ~1s on the next poll cycle.
> In `apple` mode, the script polls AppleScript every 2s (after a 6s startup grace period) to check whether the session tab is still alive; closing the window/tab causes the script to exit within ~4s with `status: user_closed`.
> In `manual` mode the script has no reliable way to detect window close and relies on the 5-minute timeout.
