Files
ledgrab/server/CLAUDE.md
alexei.dolgolyov 12b40e6071 docs: actualize README and API reference, embed screenshots
README: add free & open-source (MIT) framing; add a Platforms table (Windows/Linux/macOS/Docker supported, Android-TV build marked experimental, scrcpy phone-capture retained); expand the LED device list to ~20 protocols; correct storage to SQLite, the auth model, and resource names (Output Targets, Automations); add a prebuilt-download section; remove the Architecture and Acknowledgments sections; embed dashboard, channels, live-preview, and device-picker screenshots.

docs/API.md: full rewrite from the live route modules — all 253 endpoints across 34 modules, grouped by resource with REST + WebSocket tables, accurate auth model and WS handshake, worked examples, and sensitive-endpoint markers. Replaces the stale v0.1.0 stub.

server/CLAUDE.md: storage is now SQLite (BaseSqliteStore / ledgrab.db / LEDGRAB_DATA_DIR / data_migrations.py); fix the auth description (loopback anonymous, LAN rejected with 401 — not all endpoints open); router registration happens in api/__init__.py.
2026-05-29 14:35:45 +03:00

4.1 KiB

Claude Instructions for LedGrab Server

Project Structure

  • src/ledgrab/main.py — FastAPI application entry point
  • src/ledgrab/api/routes/ — REST API endpoints (one file per entity)
  • src/ledgrab/api/schemas/ — Pydantic request/response models (one file per entity)
  • src/ledgrab/core/ — Core business logic (capture, devices, audio, processing, automations)
  • src/ledgrab/storage/ — Data models (dataclasses) and SQLite-backed persistence stores (BaseSqliteStore)
  • src/ledgrab/utils/ — Utility functions (logging, monitor detection, SSRF validation, sound playback)
  • src/ledgrab/static/ — Frontend files (TypeScript, CSS, locales)
  • src/ledgrab/templates/ — Jinja2 HTML templates
  • config/ — Configuration files (YAML)
  • data/ — Runtime data: SQLite database (ledgrab.db) + assets. Relocate the root with LEDGRAB_DATA_DIR.

Entity & Storage Pattern

Each entity follows: dataclass model (storage/) + SQLite store (storage/*_store.py, subclassing BaseSqliteStore) + Pydantic schemas (api/schemas/) + routes (api/routes/).

Stores keep an in-memory write-through cache over a per-entity SQLite table (the legacy BaseJsonStore still exists for reference but new stores use BaseSqliteStore). Schema/data shape changes go through storage/data_migrations.py — migrations are idempotent and tracked in a dedicated data_migrations audit table, so they run safely on every startup. When renaming or restructuring stored fields, add a migration there (see the Data Migration Policy in the root CLAUDE.md).

Authentication

API key authentication via Bearer token in the Authorization header (Authorization: Bearer <key>). WebSocket connections authenticate with a first-message handshake ({"type":"auth","token":"<key>"}). See src/ledgrab/api/auth.py for the canonical logic.

  • Config: config/default_config.yaml under auth.api_keys; env var LEDGRAB_AUTH__API_KEYS
  • When api_keys is empty (default): loopback requests (127.0.0.1 / ::1 / localhost) are allowed anonymously, but LAN / remote requests are rejected with 401. Auth is not fully open.
  • When api_keys is set: a valid Bearer token is required from every client (loopback included).
  • require_authenticated() rejects even loopback-anonymous callers on sensitive endpoints (e.g. backup download, secret reveal).

Common Tasks

Adding a new API endpoint

  1. Create route file in api/routes/ (define an APIRouter(prefix="/api/v1/..."))
  2. Define request/response schemas in api/schemas/
  3. Register the router in api/__init__.py (it aggregates every route module into the single router that main.py mounts)
  4. Restart the server
  5. Test via /docs (Swagger UI)

Adding a new field to existing API

  1. Update Pydantic schema in api/schemas/
  2. Update corresponding dataclass in storage/
  3. Update backend logic to populate the field
  4. Restart the server
  5. Update frontend to display the new field
  6. Rebuild bundle: cd server && npm run build

Adding translations

  1. Add keys to static/locales/en.json, static/locales/ru.json, and static/locales/zh.json
  2. Add data-i18n attributes to HTML elements in templates/
  3. Use t('key') in TypeScript modules (static/js/)
  4. No server restart needed (frontend only), but rebuild bundle if JS changed

Modifying display/monitor detection

  1. Update functions in utils/monitor_names.py or core/screen_capture.py
  2. Restart the server
  3. Test with GET /api/v1/config/displays

Testing

cd server && pytest                    # Run all tests
cd server && pytest --cov              # With coverage report
cd server && pytest tests/test_api.py  # Single test file

Tests are in server/tests/. Config in pyproject.toml under [tool.pytest].

Frontend Conventions

For all frontend conventions (CSS variables, UI patterns, modals, localization, icons, bundling), see contexts/frontend.md.

Server Operations

For restart procedures, server modes, and demo mode checklist, see contexts/server-operations.md.