a88ae62db1
The v1 `docker-compose` binary on the deploy host fails with KeyError: 'ContainerConfig' when it recreates a container, so every instruction pointed at a command that cannot finish a deploy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
65 lines
4.4 KiB
Markdown
65 lines
4.4 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## What this is
|
|
|
|
muzick is a self-hosted music player + recommendation engine (deployed at `muzick.kvmx.ru:5174`). Three deployable units — `backend/` (Fastify API), `frontend/` (Vite React SPA), `workers/` (BullMQ job processor) — plus Postgres, Redis, and Typesense. All wired together by `docker-compose.yml`.
|
|
|
|
## Commands
|
|
|
|
Each unit is its own npm package; `cd` into it first.
|
|
|
|
```bash
|
|
# backend/ and workers/
|
|
npm run dev # tsx watch
|
|
npm run typecheck # tsc --noEmit (also runs as prebuild)
|
|
npm run build # tsc
|
|
|
|
# backend/ only
|
|
npm test # vitest run
|
|
npm run test:watch
|
|
npx vitest run src/services/generators.test.ts # single file
|
|
npx vitest run -t "comfortGenerator" # single test by name
|
|
|
|
# frontend/
|
|
npm run dev # vite
|
|
npm run build # vite build
|
|
npm run typecheck
|
|
|
|
# whole stack
|
|
# Use `docker compose` (v2). The old `docker-compose` v1 binary on this machine
|
|
# crashes with KeyError: 'ContainerConfig' when recreating a container.
|
|
docker compose up -d --build
|
|
```
|
|
|
|
There is no lint step. `typecheck` is the gate; the `prebuild` hook fails the build on type errors.
|
|
|
|
## Architecture
|
|
|
|
**Split by process, sharing one Postgres database.** The backend serves the API and the frontend consumes it; the worker runs offline enrichment/analysis. They communicate only through Postgres (source of truth) and Redis (BullMQ queue). There is no shared code package — `workers/` and `backend/` each carry their own copy of things like `queue.ts` and pg clients.
|
|
|
|
- **backend/src/app.ts** — the real entry point (`server.ts` just calls `buildApp`). Registers all routes, connects pg/redis/typesense, and runs several `setInterval` background jobs directly in-process: claim-fusion materialized-view refresh (10s), belief decay (hourly), forgotten-profile derivation (nightly). Auth is a single `onRequest` hook keyed on `MUZICK_API_KEY` / `MUZICK_ADMIN_KEY` (both optional — no keys means open); `/api/admin/*` requires the admin key specifically, `/api/health` is always exempt.
|
|
- **backend/src/services/** — business logic. `db.service.ts` owns schema application (`ensureSchema`/`runMigrations` run on every boot — the docker init-mount only fires on a fresh volume, so migrations live here). `session-director.service.ts` and `generators.service.ts` implement the recommendation/vibe logic.
|
|
- **workers/src/index.ts** — one BullMQ `Worker` with a `switch` on job name (scan_library, metadata refresh, audio analysis, artist similarity, image enrichment…). Also registers cron repeatables (integrity sweep, dislike cleanup, stale-session reaper). External metadata clients live in `workers/src/integrations/`.
|
|
- **frontend/src/** — TanStack Router + TanStack Query. `services/api.ts` is the axios base; per-domain service files wrap endpoints. Zustand stores in `store/` hold playback/vibe/toast state. `components/ethos/` is the shared Ethos design-system UI.
|
|
|
|
### Domain concepts (from README + spec comments)
|
|
|
|
- **Rolling Vibe** — continuous stream interleaving owned library tracks with "probation" external discoveries. Managed by the session-director.
|
|
- **Belief / claim fusion** — enrichment produces `claims` from multiple sources fused into a materialized view; beliefs decay over time. The in-process timers in `app.ts` keep this fresh.
|
|
- **Dislike lifecycle** — multi-stage state machine; the worker's cleanup sweep advances it.
|
|
|
|
## Deployment gotchas (see AGENTS.md)
|
|
|
|
- **Typesense is pinned to 0.25.1** — do not bump casually, the API breaks across majors.
|
|
- **Worker uses `network_mode: host` + a SOCKS5 proxy** (`SOCKS_PROXY_URL`) for all external metadata calls (Last.fm, Discogs, MusicBrainz, etc.).
|
|
- **DB schema** is `backend/src/db/schema.sql`, dropped into `docker-entrypoint-initdb.d` — only applied on a fresh volume. Schema changes for existing volumes must go through `db.service.ts` migrations.
|
|
- Music dir is a **read-only** bind from `/mnt/hdd1/media/Music` → `/music`.
|
|
- Redis host inside compose is `infra-redis` (external `infra-net` network); the host-mode worker reaches it at `127.0.0.1:6379`.
|
|
- An older `muzick.service` systemd unit runs the pre-docker backend on port 5213 and may conflict — docker compose is the active deployment.
|
|
|
|
## Working docs
|
|
|
|
`PLANS.md`, `AUDIT.md`, `progress.md`, and dated `SESSION-*.md` files track in-flight work and are not part of the running system.
|