# Claude Instructions for WLED Screen Controller ## Code Search **If `ast-index` is available, use it as the PRIMARY code search tool.** It is significantly faster than grep and returns structured, accurate results. Fall back to grep/Glob only when ast-index is not installed, returns empty results, or when searching regex patterns/string literals/comments. **IMPORTANT for subagents:** When spawning Agent subagents (Plan, Explore, general-purpose, etc.), always instruct them to use `ast-index` via Bash for code search instead of grep/Glob. Example: include "Use `ast-index search`, `ast-index class`, `ast-index usages` etc. via Bash for code search" in the agent prompt. ```bash # Check if available: ast-index version # Rebuild index (first time or after major changes): ast-index rebuild # Common commands: ast-index search "Query" # Universal search across files, symbols, modules ast-index class "ClassName" # Find class/struct/interface definitions ast-index usages "SymbolName" # Find all places a symbol is used ast-index implementations "BaseClass" # Find all subclasses/implementations ast-index symbol "FunctionName" # Find any symbol (class, function, property) ast-index outline "path/to/File.cpp" # Show all symbols in a file ast-index hierarchy "ClassName" # Show inheritance tree ast-index callers "FunctionName" # Find all call sites ast-index changed --base master # Show symbols changed in current branch ast-index update # Incremental update after file changes ``` ## CRITICAL: Git Commit and Push Policy **🚨 NEVER CREATE COMMITS WITHOUT EXPLICIT USER APPROVAL 🚨** **🚨 NEVER PUSH TO REMOTE WITHOUT EXPLICIT USER APPROVAL 🚨** ### Strict Rules 1. **DO NOT** create commits automatically after making changes 2. **DO NOT** commit without being explicitly instructed by the user 3. **DO NOT** push to remote repository without explicit instruction 4. **ALWAYS WAIT** for the user to review changes and ask you to commit 5. **ALWAYS ASK** if you're unsure whether to commit ### Workflow 1. Make code changes as requested 2. **STOP** - Inform user that changes are complete 3. **WAIT** - User reviews the changes 4. **ONLY IF** user explicitly says "commit" or "create a commit": - Stage the files with `git add` - Create the commit with a descriptive message - **STOP** - Do NOT push 5. **ONLY IF** user explicitly says "push" or "commit and push": - Push to remote repository ### What Counts as Explicit Approval ✅ **YES - These mean you can commit:** - "commit" - "create a commit" - "commit these changes" - "git commit" ✅ **YES - These mean you can push:** - "push" - "commit and push" - "push to remote" - "git push" ❌ **NO - These do NOT mean you should commit:** - "that looks good" - "thanks" - "perfect" - User silence after you make changes - Completing a feature/fix ### Example Bad Behavior (DON'T DO THIS) ``` ❌ User: "Fix the MSS engine test issue" ❌ Claude: [fixes the issue] ❌ Claude: [automatically commits without asking] <-- WRONG! ``` ### Example Good Behavior (DO THIS) ``` ✅ User: "Fix the MSS engine test issue" ✅ Claude: [fixes the issue] ✅ Claude: "I've fixed the MSS engine test issue by adding auto-initialization..." ✅ [WAITS FOR USER] ✅ User: "Looks good, commit it" ✅ Claude: [now creates the commit] ``` ## IMPORTANT: Auto-Restart Server on Code Changes **Whenever server-side Python code is modified** (any file under `/server/src/` **excluding** `/server/src/wled_controller/static/`), **automatically restart the server** so the changes take effect immediately. Do NOT wait for the user to ask for a restart. **No restart needed for frontend-only changes** — but you **MUST rebuild the bundle**. The browser loads the esbuild bundle (`static/dist/app.bundle.js`, `static/dist/app.bundle.css`), NOT the source files. After ANY change to frontend files (JS, CSS under `/server/src/wled_controller/static/`), run: ```bash cd server && npm run build ``` Without this step, changes will NOT take effect. No server restart is needed — just rebuild and refresh the browser. ### Restart procedure Use the PowerShell restart script — it reliably stops only the server process and starts a new detached instance: ```bash powershell -ExecutionPolicy Bypass -File "c:\Users\Alexei\Documents\wled-screen-controller\server\restart.ps1" ``` **Do NOT use** `Stop-Process -Name python` (kills unrelated Python processes like VS Code extensions) or bash background `&` jobs (get killed when the shell session ends). ## IMPORTANT: Server Startup Commands There are two server modes with separate configs, ports, and data directories: | Mode | Command | Config | Port | API Key | Data | |------|---------|--------|------|---------|------| | **Real** | `python -m wled_controller.main` | `config/default_config.yaml` | 8080 | `development-key-change-in-production` | `data/` | | **Demo** | `python -m wled_controller.demo` | `config/demo_config.yaml` | 8081 | `demo` | `data/demo/` | Both can run simultaneously on different ports. ### Restarting after code changes - **Real server**: Use the PowerShell restart script (it only targets the real server process): ```bash powershell -ExecutionPolicy Bypass -File "c:\Users\Alexei\Documents\wled-screen-controller\server\restart.ps1" ``` - **Demo server**: Find and kill the process on port 8081, then restart: ```bash # Find PID powershell -Command "netstat -ano | Select-String ':8081.*LISTEN'" # Kill it powershell -Command "Stop-Process -Id -Force" # Restart cd server && python -m wled_controller.demo ``` **Do NOT use** `Stop-Process -Name python` — it kills unrelated Python processes (VS Code extensions, etc.). ## Project Structure This is a monorepo containing: - `/server` - Python FastAPI backend (see `server/CLAUDE.md` for detailed instructions) - `/client` - Future frontend client (if applicable) ## Working with Server For detailed server-specific instructions (restart policy, testing, etc.), see: - `server/CLAUDE.md` ## Frontend (HTML, CSS, JS, i18n) For all frontend conventions (CSS variables, UI patterns, modals, localization, tutorials), see [`contexts/frontend.md`](contexts/frontend.md). ## Task Tracking via TODO.md Use `TODO.md` in the project root as the primary task tracker. **Do NOT use the TodoWrite tool** — all progress tracking goes through `TODO.md`. - **When starting a multi-step task**: add sub-steps as `- [ ]` items under the relevant section - **When completing a step**: mark it `- [x]` immediately — don't batch updates - **When a task is fully done**: mark it `- [x]` and leave it for the user to clean up - **When the user requests a new feature/fix**: add it to the appropriate section with a priority tag ## Documentation Lookup **Use context7 MCP tools for library/framework documentation lookups.** When you need to check API signatures, usage patterns, or current behavior of external libraries (e.g., FastAPI, OpenCV, Pydantic, yt-dlp), use `mcp__plugin_context7_context7__resolve-library-id` to find the library, then `mcp__plugin_context7_context7__query-docs` to fetch up-to-date docs. This avoids relying on potentially outdated training data. ## IMPORTANT: Demo Mode Awareness **When adding new entity types, engines, device providers, or stores — keep demo mode in sync:** 1. **New entity stores**: Add the store's file path to `StorageConfig` in `config.py` — the `model_post_init()` auto-rewrites `data/` → `data/demo/` paths when demo is active. 2. **New capture engines**: If a new engine is added, verify demo mode filtering still works (demo engines use `is_demo_mode()` gate in `is_available()`). 3. **New audio engines**: Same as capture engines — `is_available()` must respect `is_demo_mode()`. 4. **New device providers**: If discovery is added, gate it with `is_demo_mode()` like `DemoDeviceProvider.discover()`. 5. **New seed data**: When adding new entity types that should appear in demo mode, update `server/src/wled_controller/core/demo_seed.py` to include sample entities. 6. **Frontend indicators**: Demo mode state is exposed via `GET /api/v1/version` → `demo_mode: bool`. Frontend stores it as `demoMode` in app state and sets `document.body.dataset.demo = 'true'`. 7. **Backup/Restore**: If new stores are added to `STORE_MAP` in `system.py`, they automatically work in demo mode since the data directory is already isolated. **Key files:** - Config flag: `server/src/wled_controller/config.py` → `Config.demo`, `is_demo_mode()` - Demo engines: `core/capture_engines/demo_engine.py`, `core/audio/demo_engine.py` - Demo devices: `core/devices/demo_provider.py` - Seed data: `core/demo_seed.py` ## General Guidelines - Always test changes before marking as complete - Follow existing code style and patterns - Update documentation when changing behavior - Write clear, descriptive commit messages when explicitly instructed - Never make commits or pushes without explicit user approval