Files
dl-organizer/CLAUDE.md
T
windyboyandClaude Sonnet 4.5 259e7506d7 feat: add configurable category mappings for directory recognition
Allow users to configure multiple directory names per category (movie/series/anime) to support variations like "movies", "tv", "films". This enables proper categorization of files in directories that don't match the hardcoded singular forms, solving the issue where 635 files in "/mnt/Downloads/movies/" were incorrectly categorized as "other".

Configuration example:
  categories:
    movie: [movie, movies, films]
    series: [series, tv, shows]
    anime: [anime]

Changes include comprehensive validation, backward-compatible defaults, case-insensitive matching, and full test coverage (395 tests passing).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-09 22:40:48 +08:00

7.6 KiB

CLAUDE.md

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

Project Overview

Video Library Manager (VLM) is a Python CLI tool for managing personal video collections with a safety-first, human-in-the-loop approach. All file operations are reversible, require explicit confirmation, and generate reviewable execution plans before making changes.

Development Commands

Installation

# Install package in editable mode
uv pip install -e .

# Install with dev dependencies (pytest, hypothesis)
uv pip install -e ".[dev]"

Testing

# Run all tests
pytest

# Run specific test file
pytest tests/test_scanner.py

# Run with verbose output
pytest -v

Running the CLI

# Verify CLI works
vlm --help

# Initialize config
vlm config init

# Common workflow
vlm scan                    # Discover files
vlm parse                   # Extract identities
vlm analyze                 # Detect gaps/duplicates
vlm plan                    # Generate execution plan
vlm execute                 # Dry-run (default)
vlm execute --confirm       # Actually execute

Architecture

Core Workflow

VLM follows a read-first, multi-stage pipeline:

  1. Scan → discovers video files, extracts metadata via ffprobe (optional), saves to inventory.csv
  2. Parse → extracts titles/years/seasons/episodes from filenames, saves to identities.json
  3. Analyze → detects episode gaps and duplicates, saves to analysis.json
  4. Plan → generates reviewable execution plan (plan.json) with file operations
  5. Execute → performs file operations (dry-run by default, --confirm to execute)
  6. Rollback → reverses executed operations (best-effort)

Module Organization

  • cli.py - Click-based CLI interface, command definitions, all user-facing commands
  • scanner.py - File discovery using system find command, metadata extraction via ffprobe
  • parser.py - Filename parsing using regex patterns (movies: title + year, series: SxxExx)
  • analysis.py - Completeness checking (episode gaps) and duplicate detection
  • planner.py - Execution plan generation with conflict detection
  • executor.py - File operations (move/rename/quarantine) with rollback logging
  • quarantine.py - Quarantine management with manifest tracking
  • state.py - File state tracking across workflow stages
  • reports.py - Report generation (inventory, completeness, duplicates, summary)
  • config.py - YAML configuration loading and validation
  • models.py - Dataclass definitions for all data structures
  • logging_config.py - Logging setup with fallback to console if file logging fails

Key Data Structures

All defined in models.py:

  • VideoFile - represents discovered video file with metadata
  • MovieIdentity / SeriesIdentity - parsed identity with confidence score
  • ExecutionPlan - collection of file operations with summary
  • FileOperation - single operation (move/rename/quarantine/no-op) with conflict detection
  • RollbackLog - log of executed operations for reversal
  • QuarantineEntry - quarantined file with original location
  • FileState - workflow state (reviewed/ignored/planned/executed/quarantined)

File Categorization

Based on top-level directory within library root, matched against configured category mappings (case-insensitive).

Files in unmapped directories are categorized as "other" and skipped by planner/quarantine operations.

Parsing Patterns (Hardcoded)

Movies (high confidence):

  • {title} ({year})
  • {title}.{year}

Series (high confidence):

  • S{season:02d}E{episode:02d}
  • {season}x{episode}

Patterns are hardcoded in parser.py, not user-configurable.

Configuration

Default location: ~/.vlm/config.yaml

Key settings:

  • library_root - root directory to scan (required)
  • video_extensions - list of extensions to recognize
  • templates.movie_dir / templates.series_dir - directory structure templates
  • templates.movie_filename / templates.series_filename - filename templates
  • quarantine_dir - name of quarantine directory (default: .quarantine)
  • log_level - logging verbosity
  • categories - mapping of category names to directory name lists

Category Mappings

Categories are determined by matching the top-level directory name against configured mappings:

Default mappings:

categories:
  movie: [movie]
  series: [series]
  anime: [anime]

Custom mappings support multiple directory names per category:

categories:
  movie: [movie, movies, films]
  series: [series, tv, shows, television]
  anime: [anime]

This allows files in /library/movies/ or /library/films/ to be recognized as the "movie" category. Directory matching is case-insensitive.

Migration Note: If you have existing directories with non-standard names (like "movies" or "tv"), update your config.yaml and re-run vlm scan to fix categorization. No files will be moved.

File Discovery

Uses system find command for speed, falls back to Python recursion if unavailable. Hidden paths (starting with .) are skipped automatically.

Timestamp Handling

All timestamps stored in UTC using ISO 8601 format (YYYY-MM-DDTHH:MM:SS). The scanner normalizes naive timestamps to UTC using system timezone.

Logging

Logs to ~/.vlm/vlm.log by default. If log directory is unwritable, falls back to console-only logging and continues execution (does not fail).

Error Handling

  • Configuration errors: display helpful message, create default config, continue
  • Missing ffprobe: skip metadata extraction, log debug message, continue
  • File access errors: log error, skip file, continue scanning
  • Invalid YAML: display error, use default config

Testing Guidelines

  • Framework: pytest with hypothesis for property-based tests
  • Test file naming: test_*.py
  • Test function naming: test_*
  • Test class naming: Test*
  • Use CliRunner for CLI integration tests
  • Prefer narrow unit tests for module logic plus targeted CLI integration tests
  • Add tests with each behavior change, including error paths and edge cases

Important Implementation Notes

Safety Protocol

  • NEVER permanently delete files - use quarantine instead
  • All file operations create rollback logs when executed with --confirm
  • Execution plans detect destination conflicts and mark operations
  • Default mode is dry-run; --confirm required for actual execution
  • Quarantine is reversible via restore command

Anime Handling

Anime files are discovered and categorized but NOT parsed in v1 (deferred for future implementation).

State Management

State tracking is optional and allows marking files as reviewed/ignored/planned/executed/quarantined. State is persisted to ~/.vlm/state.json.

Quarantine Constraints

Only movie and series files can be quarantined in v1 (anime and other categories rejected).

Template Variables

Available for path/filename templates:

  • Movies: {title}, {year}, {ext}
  • Series: {title}, {season}, {episode}, {ext}

Format specifiers like {season:02d} are supported.

Code Style

  • Python 3.10+ idioms
  • 4-space indentation
  • PEP 8 naming: snake_case for functions/variables, PascalCase for classes, UPPER_SNAKE_CASE for constants
  • Type hints for public functions and non-trivial internal APIs
  • Modules focused on single responsibility
  • No formatter/linter enforced - maintain consistency with existing files

Commit Guidelines

  • Clear, imperative commit subjects (e.g., "fix logging fallback for unwritable log dir")
  • Keep commits focused - avoid mixing refactors and behavior changes
  • Include co-author tag: Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>