Release Notes overlay redesign (scoped via .release-notes-shell)
- Backend exposes release.assets (name/size/download_url) through
UpdateReleaseInfo so the frontend can render real download links.
- New masthead: eyebrow + display-font title + tag/published/pre-release
chip strip + close/external action buttons; opts out of layout.css's
global `header { height: 60px }` and `header::before` accent bar that
were leaking into the overlay's <header>.
- Markdown body: <code> filenames are wrapped in clickable <a> via fuzzy
asset match (exact basename, then same-extension token-overlap), with
per-asset description tooltip and a small download glyph.
- Per-asset description derived from filename pattern (Windows installer
/portable/msi, Linux tarball/AppImage/deb/rpm, macOS dmg/pkg, Android
apk/aab, iOS ipa, generic archives) with i18n keys in en/ru/zh.
- Hide checksum / signature side-files (.sha256/.sha512/.sig/.asc/...).
Settings modal & dashboard polish
- ds-section refresh, rail-channel routing, notif matrix updates.
- Dashboard customize panel + per-account layout updates.
- New docs/settings-modal-redesign.html design reference.
Streams / targets / color-strip
- Stream cards rewrite (cards.css, streams.css, streams.ts).
- Composite stream + metrics history adjustments.
- WLED target processor + color-strip pipeline refinements.
- Color-strip WS source streamer touch-ups.
Misc
- Perf charts overhaul; tabular game-integration / HA / MQTT / weather
source cards; donation/sync-clocks/scene-presets minor polish.
- New i18n keys across en/ru/zh.
Test infrastructure
- conftest pre-creates the test DB so main.py's legacy-data migration
doesn't shovel the user's production DB into the test temp dir.
- test_preferences_notifications wipes its own setting at the start of
the defaults test (was relying on isolation it never enforced).
Pre-commit gates: ruff clean, tsc clean, npm run build clean,
pytest 899/899 passing.
8.4 KiB
Claude Instructions for LedGrab
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.
ast-index search "Query" # Universal search
ast-index class "ClassName" # Find class/struct/interface definitions
ast-index usages "SymbolName" # Find all usage sites
ast-index symbol "FunctionName" # Find any symbol
ast-index callers "FunctionName" # Find all call sites
ast-index outline "path/to/File.py" # Show all symbols in a file
ast-index changed --base master # Show symbols changed in current branch
Git Commit and Push Policy
NEVER commit or push without explicit user approval. Wait for the user to review changes and explicitly say "commit" or "push". Completing a task, "looks good", or "thanks" do NOT count as approval. See the system-level instructions for the full commit workflow.
Auto-Restart and Rebuild Policy
- Python code changes (
server/src/excludingstatic/): Auto-restart the server. See contexts/server-operations.md for the restart procedure. - Frontend changes (
static/js/,static/css/): Runcd server && npm run buildto rebuild the bundle. No server restart needed.
Project Structure
/server— Python FastAPI backend (see server/CLAUDE.md)/android— Android TV app (Kotlin shell + embedded Python via Chaquopy)/contexts— Context files for Claude (frontend conventions, graph editor, Chrome tools, server ops, demo mode)
Android Dependency Sync (CRITICAL)
The Android app (android/app/build.gradle.kts) installs the server package with --no-deps and lists Android-compatible dependencies explicitly in the Chaquopy pip {} block. This is because server/pyproject.toml includes desktop-only packages (mss, psutil, sounddevice, etc.) that have no Android wheels.
When adding a new dependency to server/pyproject.toml:
- If the package is pure Python or has Chaquopy wheels (check Chaquopy PyPI), also add it to
android/app/build.gradle.ktsin thepip { install(...) }block - If the package is desktop-only (native C/Rust extension without Android support), do NOT add it to
build.gradle.kts— and guard its import withtry/except ImportErrorin Python code - If unsure, check Chaquopy's package index first
Incident context: Chaquopy's pip runs on the build machine (Windows), not on Android. Platform markers like sys_platform != 'linux' evaluate against the BUILD host, not the target device. pip install --exclude does not exist. The only reliable way to exclude packages is to not list them.
Context Files
| File | When to read |
|---|---|
| contexts/frontend.md | HTML, CSS, JS/TS, i18n, modals, icons, bundling |
| contexts/graph-editor.md | Visual graph editor changes |
| contexts/server-operations.md | Server restart, startup modes, demo mode |
| contexts/chrome-tools.md | Chrome MCP tool usage for testing |
| contexts/ci-cd.md | CI/CD pipelines, release workflow, build scripts |
| Gitea Python CI/CD Guide | Reusable CI/CD patterns: Gitea Actions, cross-build, NSIS, Docker |
| server/CLAUDE.md | Backend architecture, API patterns, common tasks |
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.
Documentation Lookup
Use context7 MCP tools for library/framework documentation lookups (FastAPI, OpenCV, Pydantic, yt-dlp, etc.) instead of relying on potentially outdated training data.
Data Migration Policy (CRITICAL)
NEVER rename a storage file path, store key, entity ID prefix, or JSON field name without writing a migration. User data lives in JSON files under data/. If the code starts reading from a new filename while the old file still has user data, THAT DATA IS SILENTLY LOST.
When renaming any storage-related identifier:
- Add migration logic in
BaseJsonStore.__init__(or the specific store) that detects the old file/key and migrates data to the new name automatically on startup - Log a clear warning when migration happens so the user knows
- Keep the old file as a backup after migration (rename to
.migratedor similar) - Test the migration with both old-format and new-format data files
- Document the migration in the commit message
This applies to: file paths in StorageConfig, JSON root keys (e.g. picture_targets → output_targets), entity ID prefixes (e.g. pt_ → ot_), and any field renames in dataclass models.
Incident context: A past rename of picture_targets.json → output_targets.json was done without migration. The app created a new empty output_targets.json while the user's 7 targets sat unread in the old file. Data was silently lost.
UI Component Rules (CRITICAL)
NEVER use plain HTML <select> elements. The project uses custom selector components:
- IconSelect (icon grid) — for predefined items (effect types, palettes, easing modes, animation types)
- EntitySelect (entity picker) — for entity references (sources, templates, devices)
Plain HTML selects break the visual consistency of the UI.
Pre-Commit Checks (MANDATORY)
Before every commit, run the relevant checks and fix any issues:
- Python changes:
cd server && ruff check src/ tests/ --fix - TypeScript changes:
cd server && npx tsc --noEmit && npm run build - Both: Run both checks
- Always run tests:
cd server && py -3.13 -m pytest tests/ --no-cov -q— all tests MUST pass before committing. Do NOT commit code that fails tests.
Do NOT commit code that fails linting or tests. Fix the issues first.
General Guidelines
- Always test changes before marking as complete
- Follow existing code style and patterns
- Update documentation when changing behavior
- Never make commits or pushes without explicit user approval
MCP Tools: code-review-graph
IMPORTANT: This project has a knowledge graph. ALWAYS use the code-review-graph MCP tools BEFORE using Grep/Glob/Read to explore the codebase. The graph is faster, cheaper (fewer tokens), and gives you structural context (callers, dependents, test coverage) that file scanning cannot.
When to use graph tools FIRST
- Exploring code:
semantic_search_nodesorquery_graphinstead of Grep - Understanding impact:
get_impact_radiusinstead of manually tracing imports - Code review:
detect_changes+get_review_contextinstead of reading entire files - Finding relationships:
query_graphwith callers_of/callees_of/imports_of/tests_for - Architecture questions:
get_architecture_overview+list_communities
Fall back to Grep/Glob/Read only when the graph doesn't cover what you need.
Key Tools
| Tool | Use when |
|---|---|
detect_changes |
Reviewing code changes — gives risk-scored analysis |
get_review_context |
Need source snippets for review — token-efficient |
get_impact_radius |
Understanding blast radius of a change |
get_affected_flows |
Finding which execution paths are impacted |
query_graph |
Tracing callers, callees, imports, tests, dependencies |
semantic_search_nodes |
Finding functions/classes by name or keyword |
get_architecture_overview |
Understanding high-level codebase structure |
refactor_tool |
Planning renames, finding dead code |
Workflow
- The graph auto-updates on file changes (via hooks).
- Use
detect_changesfor code review. - Use
get_affected_flowsto understand impact. - Use
query_graphpattern="tests_for" to check coverage.