79b5d049ce
Adds LAST30DAYS_YT_SSH_HOST env var (or `~/.config/last30days/.env` key). When set, yt-dlp YouTube search invocations are wrapped as `ssh <host> "yt-dlp ..."` so they run on a residential-IP machine. Motivation: when last30days runs on a datacenter VPS (Hetzner, DigitalOcean, AWS, etc.), `ytsearch:` queries return 0 results because YouTube's bot-wall fingerprints datacenter IP ranges before any cookie check runs. Cookies alone don't fix this — the IP reputation is checked first. Verified across yt-dlp stable 2026.03.17 and nightly builds. The existing fallbacks (browser cookies, residential proxy services, excluding YouTube) all have downsides: cookies expire, proxies cost money, exclusion loses signal. Many users with a Mac mini, Pi, or home server can host yt-dlp on their own residential IP — this just needs an SSH alias and a one-line env var to wire it up. Behaviour: - Default (env var unset): identical to before, no shape change. - Env var set: search command list is wrapped with `ssh -o BatchMode=yes <host> "<shell-quoted yt-dlp invocation>"`. is_ytdlp_installed() returns True without a local PATH check (the binary lives on the remote host). - Transcript path: when SSH-routing is on, skips the yt-dlp transcript path (which writes a VTT file we couldn't easily read back over SSH) and uses the existing _fetch_transcript_direct HTTP fallback. The timedtext API isn't bot-walled, so this works fine on datacenter IPs. Setup pitfall documented in the function docstring: on macOS hosts with Homebrew, `eval "$(/opt/homebrew/bin/brew shellenv zsh)"` must live in ~/.zshenv (not just ~/.zprofile) — non-login SSH shells don't source .zprofile, so without this `ssh macmini "yt-dlp ..."` returns "command not found" while interactive SSH works fine. Tests: 10 new cases covering env var read, whitespace stripping, empty-value handling, command wrapping passthrough/active modes, shlex quoting, is_ytdlp_installed short-circuit, and end-to-end search_youtube wrapping. Full test suite: 0 new failures (the 14 pre-existing failures in test_store, test_watchlist, test_setup_openclaw, test_safari_cookies, test_version_consistency are unchanged on main). Verified live: 0 results → 4 real hits for "claude code" search from a Hetzner VPS routed through a Mac mini exit node on Tailscale.