# VidFlow — Codex Agent Instructions ## Role Codex implements. Claude reads context, writes task prompts, and reviews diffs. When Claude delegates a task here, implement it fully and trust your own reading of the file — Claude will catch anything that needs correction in the diff review. ## How Claude Delegates Claude writes a task description and runs: ```bash cd /home/aaron/Programming/vidflow && /home/aaron/.npm-global/bin/codex exec < /tmp/vf-task.md # or inline: cd /home/aaron/Programming/vidflow && /home/aaron/.npm-global/bin/codex exec "edit vidflow.html: ..." ``` After you finish, Claude reviews with `git -C /home/aaron/Programming/vidflow diff` and either accepts or makes targeted corrections. ## Project Rules (enforce these without being told) - **Single file**: everything lives in `vidflow.html` — no new files, no build step, no frameworks - **Script section order** must be preserved (see below) - **Never hardcode API keys** — stored in `localStorage` only - **All app state in `const A`** — never create separate state variables - **Keyboard shortcuts**: call player API directly, never `.click()` on DOM elements - **`DEBUG = false`** — never commit as true ## Script Section Order When adding functions, insert them in the correct section: 1. State (`const A`, `const FD`, `DEBUG`, `dbg`) 2. Utility (`qs`, `qsa`, `esc`, `cleanArtist`, `extractPID`) 3. YouTube IFrame API (`onYouTubeIframeAPIReady`, `onPReady`, `onPState`, `onPErr`) 4. Channel flip (`flip()`) 5. Channel loading (`loadCh()`) 6. Now playing (`updateNP`, `setTicker`, `tickerLoop`, `showTitleCard`) 7. Progress bar (`startPB`) 8. Data API (`apiFetch`, `validateKey`, `searchPL`, `getPLInfo`) 9. Channel management (`addCh`, `removeCh`, `updateCS`) 10. UI rendering (`renderTab`, `renderChTab`, `renderSearchTab`, `renderAddTab`) 11. NCO onboarding (`initNCO`, `renderNCOTab`, `ncoAdd`) 12. Visibility helpers + toast 13. Persistence (`save`, `loadState`) 14. Setup (`initSetup`) 15. App launch (`launchApp`) 16. Controls wiring (`wireControls`) 17. Pop-out transfer (`popOut`, storage listeners) 18. Idle system (poll + event listeners) 19. PWA manifest injection 20. Init: `loadState(); wireControls(); initSetup();` ## Known Gotchas (check these when editing related code) - `stopVideo()` before `loadPlaylist()` on channel switch — prevents shared-video stuck state - Shuffle: must call `setShuffle(true)` AND `playVideoAt(startIdx)` — `loadPlaylist` index alone isn't enough - Sidebar click-close: guard with `document.contains(e.target)` before checking `sb.contains()` - Keyboard handlers: skip if `e.target.tagName` is INPUT or TEXTAREA - `window.opener` distinguishes popup from main window for pop-out transfer logic ## Local Dev ```bash python3 -m http.server 8080 # Open http://localhost:8080/vidflow.html # Must be HTTP — YouTube API rejects file:// ```