# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project overview A two-component photo booth system running on Raspberry Pi: 1. **`camera/`** — Python/Flask camera server using `picamera2` (Raspberry Pi HQ Camera M12). Streams live MJPEG video and exposes a `/capture` endpoint that saves JPEG snapshots to `camera/photos/`. 2. **`ImmichUploader/`** — Laravel 13 PHP application that watches `camera/photos/` via `inotify`, and uploads new photos to a self-hosted [Immich](https://immich.app) instance via its HTTP API, then adds each asset to a specific album. ## Running the camera server ```bash cd camera python main.py ``` The server listens on port 5000 on all interfaces. Endpoints: - `GET /` — live MJPEG stream viewer - `GET /video_feed` — raw MJPEG stream - `GET /capture` — saves current frame to `camera/photos/` and returns JSON ## Running the ImmichUploader ```bash cd ImmichUploader composer run setup # first-time: installs deps, generates key, runs migrations composer run dev # starts all services: web server + queue worker + log viewer + vite ``` Or run the folder watcher and queue worker individually: ```bash php artisan immich:watch-folder # watches FOLDER_PATH via inotify, dispatches jobs php artisan queue:listen --tries=1 --timeout=0 # processes SendToImmichJob ``` Run tests: ```bash composer run test ``` ## Environment variables **`ImmichUploader/.env`** (not the root `.env`): - `IMMICH_URL` — base URL of the Immich instance (e.g. `https://photos.example.com`) - `IMMICH_KEY` — Immich API key - `FOLDER_PATH` — absolute path to the photos directory (matches `camera/photos/`) The root `.env` is gitignored and only excluded `camera/photos` from tracking. ## Architecture notes **Camera → Uploader flow:** 1. `camera/main.py` writes a JPEG to `camera/photos/.jpg` on `/capture` 2. `WatchFolder` artisan command (`inotify_add_watch` on `IN_CLOSE_WRITE | IN_MOVED_TO`) detects the new file 3. Dispatches `SendToImmichJob` to the database queue 4. The queue worker runs `SendToImmichJob::handle()` which POSTs the image to `/api/assets` then adds it to the hardcoded album via `PUT /api/albums/{albumId}/assets` **Hardcoded values in `SendToImmichJob.php`:** - `$albumId` — Immich album ID where photos are added - `$id` (deviceAssetId) — fixed UUID used as the Immich device asset identifier **`camera/` directory structure:** The `camera/` directory is itself a Python venv (has `pyvenv.cfg`), but the actual venv used by the app is `camera/myenv/` (contains Flask). `picamera2` is available from the system Python installation. **ImmichUploader** uses SQLite (default, `database/database.sqlite`) for the queue, cache, and sessions — no separate database process needed.