Files
NaviWatcher/CLAUDE.md

5.5 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Development Commands

Building

# Build the application
go build -o naviwatcher

# Build with race detector
go build -race -o naviwatcher

# Cross-platform build examples
GOOS=linux GOARCH=amd64 go build -o naviwatcher-linux
GOOS=darwin GOARCH=amd64 go build -o naviwatcher-mac
GOOS=windows GOARCH=amd64 go build -o naviwatcher.exe

Running

# Run the application
./naviwatcher

# Run with specific config file
./naviwatcher -config=/path/to/config.yaml

# Run in development mode (if implemented)
go run main.go

Testing

# Run all tests
go test ./...

# Run tests with coverage
go test ./... -cover

# Run a specific test package
go test ./internal/scanner

# Run tests verbose
go test ./... -v

Dependency Management

# Add a new dependency
go get github.com/example/package@v1.2.3

# Update dependencies
go get -u ./...

# Tidy up dependencies
go mod tidy

# Vendor dependencies (if needed)
go mod vendor

Linting and Formatting

# Format code
go fmt ./...

# Vet for potential issues
go vet ./...

# Static analysis (if golangci-lint is installed)
golangci-lint run

Docker

# Build Docker image
docker build -t naviwatcher .

# Run with docker compose
docker compose up

# Run in background
docker compose up -d

# View logs
docker compose logs -f

Code Architecture

Based on the specification (docs/Specification.md), the application follows a modular architecture:

Core Modules

  1. Navidrome Client (internal/navidrome/ or similar)

    • Handles Subsonic API communication
    • Fetches artist and album data from Navidrome instance
    • Implements authentication and error handling
  2. MusicBrainz Provider (internal/musicbrainz/ or similar)

    • Interfaces with MusicBrainz API
    • Implements rate limiting (1 request/second)
    • Manages caching of artist discographies (24-hour TTL)
    • Works with Release Group (RG) entities to minimize duplicates
  3. Scanner Engine (internal/scanner/ or similar)

    • Normalizes string comparisons for fuzzy matching
    • Implements the comparison algorithm (0.85 similarity threshold)
    • Handles removal of special characters, years, and bracketed keywords
    • Compares local albums vs. external discographies

    Shared normalization lives in internal/normalize (NormalizeString, NormalizeArtistName) — this is the single source of truth for string normalization, reused by both internal/musicbrainz and internal/scanner. Do NOT add local copies of normalization logic elsewhere.

  4. Database Layer (internal/database/ or similar)

    • SQLite 3 integration via github.com/mattn/go-sqlite3
    • Subsonic API client via github.com/delucks/go-subsonic
    • Manages schema migrations
    • Handles tables:
      • artist_settings: Artist monitoring configuration
      • local_albums: Navidrome albums synced via Subsonic API (id, artist_id, title)
      • external_releases: Cached MusicBrainz data
      • notifications_sent: Sent notification tracking
  5. Notifier (internal/notifier/ or similar)

    • Telegram bot integration
    • Scheduled task execution (cron-based)
    • Batch notification sending
    • Message formatting with Web UI links
  6. Web UI (internal/web/ or similar)

    • Go standard library net/http + html/template
    • Embedded templates using //go:embed
    • Basic authentication protection
    • Dashboard for viewing missing albums
    • Artist detail views with ignore functionality
    • Archive view for previously ignored releases

Key Technical Requirements

  • Concurrency: Separate goroutines for external API calls to keep web UI responsive
  • Rate Limiting: Strict adherence to MusicBrainz 1 request/second limit
  • Graceful Shutdown: Proper SIGTERM handling to close database connections
  • Configuration: YAML-based config (config.yaml) with environment-specific overrides
  • Static Assets: HTML templates embedded via //go:embed for single-binary deployment
  • Data Modeling: Focus on Release Group entities rather than specific releases

Common Development Patterns

  • Use context.Context for cancellation and timeouts
  • Implement proper error handling with logging
  • Follow Go idioms and conventions
  • Write table-driven tests for complex logic
  • Use dependency injection for testability
  • Apply the specified fuzzy matching algorithm consistently
  • Centralize shared logic: Place reusable filtering, validation, or utility functions in dedicated files (e.g., internal/musicbrainz/filter.go) and import them across packages to ensure consistent behavior across cache-hit, cache-miss, and real-time paths

Configuration Reference

See docs/Specification.md Section 7 for full config.yaml structure including:

  • Server settings (host, port, basic auth)
  • Navidrome connection details
  • MusicBrainz API configuration
  • Telegram notification settings
  • Scanner parameters (fuzzy threshold, filters)

Database Schema

See docs/Specification.md Section 5 for complete SQLite schema including:

  • artist_settings table columns and defaults
  • external_releases table structure
  • notifications_sent table for tracking

Getting Started

  1. Copy config.yaml.example to config.yaml and fill in your values
  2. Ensure Navidrome instance is running and accessible
  3. Set up Telegram bot and obtain token/chat ID
  4. Initialize database: ./naviwatcher (will create tables on first run)
  5. Start the service: ./naviwatcher
  6. Access Web UI at http://localhost:8080 (or configured host/port)