Files
ersatztv/CLAUDE.md
Timothy aa6d8eae4c
Some checks failed
Build / Calculate version information (push) Successful in 17s
Build / build_and_upload (push) Failing after 0s
Build / build_images (push) Failing after 0s
Close stale issues / stale (push) Successful in 13s
Add Task Completion Protocol to CLAUDE.md
Replace informal implementer workflow with structured 7-step protocol
including mandatory root cause analysis for bug fixes. References /done
skill for automated enforcement.

Part of adversarial-reviewer #260.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 22:29:45 +01:00

4.8 KiB

ErsatzTV Fork

Custom IPTV channel server for Jellyfin. Forked from ErsatzTV/ErsatzTV after upstream archival (Feb 2026, v26.3.0). Our fork lives on Gitea.

Architecture

  • Language: C# / .NET 10, Blazor Server UI (MudBlazor)
  • Pattern: CQRS via MediatR — queries/commands in ErsatzTV.Application/
  • Database: EF Core (SQLite default, MySQL optional) — context in ErsatzTV.Infrastructure/Data/TvContext.cs
  • Media: FFmpeg via CliWrap, SkiaSharp for logo generation
  • Functional C#: Language Ext (Option, Either monads throughout)

Project Layout

Project Role
ErsatzTV/ ASP.NET Core host, Blazor pages, API controllers, DI setup
ErsatzTV.Application/ MediatR handlers (business logic)
ErsatzTV.Core/ Domain entities, interfaces, no infrastructure deps
ErsatzTV.Infrastructure/ EF Core repos, data access
ErsatzTV.Infrastructure.Sqlite/ SQLite-specific implementations
ErsatzTV.FFmpeg/ FFmpeg process wrapper
ErsatzTV.Scanner/ Media library scanning

Key Files

  • M3U generation: ErsatzTV.Core/Iptv/ChannelPlaylist.csToM3U()
  • XMLTV generation: ErsatzTV.Application/Channels/Queries/GetChannelGuideHandler.cs
  • IPTV controller: ErsatzTV/Controllers/IptvController.cs/iptv/* routes
  • Logo generation: ErsatzTV.Core/Images/ChannelLogoGenerator.cs
  • Channel entities: ErsatzTV.Core/Domain/Channel.cs
  • DB context: ErsatzTV.Infrastructure/Data/TvContext.cs

Deployment

  • Docker host: jazz (192.168.1.99), container ersatztv, port 8409
  • Config volume: ~/downloadswarm/ersatztv/ on jazz → /config in container
  • SQLite DB: /config/ersatztv.sqlite3 (WAL mode, root-owned)
  • Image: ghcr.io/ersatztv/ersatztv:latest (to be replaced with our fork's image)

Development

# Build
dotnet build ErsatzTV.sln

# Run locally (needs FFmpeg in PATH)
dotnet run --project ErsatzTV

# Docker build
docker build -f docker/Dockerfile -t ersatztv:dev .

Conventions

  • Follow existing MediatR CQRS pattern for new features
  • Domain logic in ErsatzTV.Core, infrastructure in ErsatzTV.Infrastructure
  • Keep Blazor pages thin — delegate to MediatR handlers
  • Test with xUnit (existing test projects)
  • Backlog tracked via Gitea Issues

Task Completion Protocol

Every task that closes a Gitea issue MUST complete ALL of these before it is considered done. Use /done <issue> to run through this automatically.

  1. Root cause (bug fixes / incidents only): Document WHY the problem existed, not just what was changed. If root cause is unknown, say so explicitly and open a follow-up investigation issue. Fixing symptoms without understanding causes creates recurring problems.
  2. Comment on issues as you work — what you found, what approach you're taking, any deviations from the suggested fix.
  3. Push changes: git push all commits before closing. Use fixes #N in commit messages to auto-close where appropriate.
  4. Close comment: Add a structured closing comment on the issue covering: what was done, root cause (if applicable), files changed, anything deferred, follow-up issues created, and which docs were updated.
  5. Close the issue via API or fixes #N commit. Leave open with a comment only if partially addressed.
  6. Update docs: If the change affects operational behavior, update the relevant Obsidian docs (~/homelab-docs/), MEMORY.md, or CLAUDE.md inline — not as a follow-up.
  7. Reply to reviewer (if from adversarial review): Summary of done/deferred/questions. This triggers the next review cycle.

Project Boundaries

ersatztv OWNS: ErsatzTV fork code (C#/.NET), channel/collection/schedule management, M3U/XMLTV generation, the ErsatzTV skill in server-management.

ersatztv does NOT own:

  • Docker compose configs → server-management (~/downloadswarm/stacks/ersatztv/)
  • NFS mounts, Ansible, DNS, networking → server-management
  • Content sourcing (yt-dlp downloads, Sonarr/Radarr libraries) → media-management (planned)
  • Jellyfin skill → server-management (symlinked)

For infrastructure changes (Docker, NFS, ports, Authelia): open an issue in timothy/server-management.

For content/media sourcing questions (what goes into channels, yt-dlp pipelines): open an issue in timothy/media-management once it exists; for now, timothy/server-management.

For plan/audit reviews: open ~/adversarial-reviewer before significant architecture changes.

Full cross-project rules: ~/homelab-docs/Operations/Project Boundaries.md (https://docs.tblindustries.be). ErsatzTV docs: ~/homelab-docs/Docker/ErsatzTV.md + project-local docs/ (fork strategy, channels, M3U/XMLTV).