12 KiB
CLAUDE.md
Documentation Status
- Synchronized with post-refactor baseline on 2026-04-07 (see
CHANGELOG.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
Important: This project uses uv for Python package management. All commands should be run with uv run to ensure they execute in the correct project environment with proper dependencies.
Installation
# Install package in editable mode
uv pip install -e .
# Install with dev dependencies (pytest, hypothesis)
uv pip install -e ".[dev]"
# Optional Textual UI for `vlm review-plan --tui`
uv pip install -e ".[tui]"
The default CLI path does not require Textual; it is imported only when uv run vlm review-plan --tui is used.
Testing
# Run all tests (use uv run to execute in the project environment)
uv run pytest
# Run specific test file
uv run pytest tests/test_scanner.py
# Run with verbose output
uv run pytest -v
# Run with quiet output (summary only)
uv run pytest -q
# Count total test cases
uv run pytest --collect-only -q
Running the CLI
# Verify CLI works (use uv run for proper environment)
uv run vlm --help
# Initialize config
uv run vlm config init
# Common workflow
uv run vlm scan # Discover files
uv run vlm parse # Extract identities (v1 schema)
uv run vlm parse --inventory artifacts/inventory.csv # Embed metadata for quality-aware duplicate handling
uv run vlm enrich # (Optional) Enrich titles/reputation via TMDB
uv run vlm enrich --refresh-all # Force full refresh (ignore cache)
uv run vlm analyze # Detect gaps/duplicates
uv run vlm plan # Generate execution plan
uv run vlm plan --analysis artifacts/analysis.json # Generate plan with duplicate resolution
uv run vlm review-plan # Export CSV + terminal review preview
uv run vlm review-plan --tui # Optional full-screen review UI
uv run vlm apply-review # Sync edited CSV decisions back into the plan
uv run vlm execute # Dry-run (default)
uv run vlm execute --confirm # Actually execute
uv run vlm rollback # Undo executed operations
# Reporting
uv run vlm report summary # Overview statistics
uv run vlm report inventory # File inventory
uv run vlm report completeness # Series with missing episodes
uv run vlm report duplicates # Duplicate files with quality comparison
# Quarantine management
uv run vlm quarantine list # List quarantined files
uv run vlm quarantine add <file> --reason "duplicate"
uv run vlm quarantine restore <file>
# State management
uv run vlm state show <file>
uv run vlm state set <file> --status reviewed
Architecture
Core Workflow
VLM follows a read-first, multi-stage pipeline:
- Scan → discovers video files, extracts metadata via ffprobe (optional), saves to
artifacts/inventory.csv - Parse → extracts titles/years/seasons/episodes from filenames, saves to
artifacts/identities.json- Use
--inventory artifacts/inventory.csvto embed video metadata (v2 schema) for accurate duplicate resolution by quality - Without
--inventory, produces v1 schema (lightweight, no embedded metadata)
- Use
- Enrich (optional) → adds bilingual titles and reputation (TMDB); updates
artifacts/identities.jsonin place; uses SQLite cache for incremental runs - Analyze → detects episode gaps and duplicates, saves to
artifacts/analysis.json - Plan → generates reviewable execution plan (
artifacts/plan.json) with file operations - Review / Apply Review → previews high-risk operations in terminal or optional TUI, then syncs edited CSV decisions back into the plan when needed
- Execute → performs file operations (dry-run by default,
--confirmto execute) - Rollback → reverses executed operations (best-effort)
Module Organization
cli.py- Click-based CLI interface, global options, command registrationcontext.py- CLIContext (config, paths) and pass_context for commandscommands/- Command implementations (scan, parse, enrich, analyze, plan, execute/rollback)scanner.py- File discovery using systemfindcommand, metadata extraction via ffprobeparser.py- Filename parsing using regex patterns (movies: title + year, series: SxxExx)enrichment.py- Enrichment pipeline;cache.py- SQLite cache;providers/- TMDB etc.io.py- Unified JSON/CSV I/O helpers, including validated typed plan loading/savingutils.py- UTC time, format_size, shared helpersanalysis.py- Completeness checking (episode gaps) and duplicate detectionduplicate_resolve.py- Duplicate group resolution with explicit failures for unresolved strategies/dataplanner.py- Execution plan generation with conflict detection and manual-review duplicate fallbackexecutor.py- File operations (move/rename/quarantine) with rollback logging and library-root safety checksquarantine.py- Quarantine management with manifest trackingstate.py- File state tracking across workflow stagesreports.py- Report generation (inventory, completeness, duplicates, summary)config.py- YAML configuration loading and validationmodels.py- Dataclass definitions for all data structureslogging_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 metadataMovieIdentity/SeriesIdentity- parsed identity with confidence scoreExecutionPlan- collection of file operations with summaryFileOperation- single operation (move/rename/quarantine/no-op) with conflict detectionRollbackLog- log of executed operations for reversalQuarantineEntry- quarantined file with original locationFileState- 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 recognizetemplates.movie_dir/templates.series_dir- directory structure templatestemplates.movie_filename/templates.series_filename- filename templatesquarantine_dir- name of quarantine directory (default:.quarantine)log_level- logging verbositycategories- mapping of category names to directory name listsenrichment(orenrich) - TMDB/api_keys, cache_db, translation, reputation; see README for full schemaplan.duplicate_keep- when usingvlm plan --analysis:by_quality(resolution > source > codec > size),by_reputation(default),first_seen, ormanual
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.
Schema Versioning
identities.json Schema Versions:
-
v1 (default without
--inventory): Lightweight schema without embedded metadata- Records contain: path, filename, category, title, year/season/episodes, confidence, needs_review
- VideoFile objects reconstructed with defaults: size_bytes=0, resolution=None, codec=None
- Suitable for basic organization workflows
-
v2 (with
--inventory): Enhanced schema with embedded video metadata- All v1 fields plus
video_metadataobject containing:- size_bytes, modified_timestamp, resolution, codec, duration_seconds, bitrate_kbps
- Enables accurate duplicate resolution by quality (compare resolution, codec, file size)
- Required for
by_qualityduplicate resolution strategy - Backward compatible: v1 files load without errors
- All v1 fields plus
Implementation Details:
_video_file_from_record()in io.py extracts embedded metadata if present- Parse command with
--inventoryflag loads inventory.csv and embeds metadata in output - Schema version stored in
vlm_schema_versionfield at root level of identities.json
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
CliRunnerfor 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_casefor functions/variables,PascalCasefor classes,UPPER_SNAKE_CASEfor 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>