# CrossWatch is one sync layer between your media servers and your trackers

> CrossWatch is a self-hosted service that keeps the state of your media life in one place and moves it between the servers you watch on and the trackers you keep lists in. It syncs watchlists, ratings, history, playback progress and collections, it has its own local tracker that snapshots your data, and it does the whole thing from one container with one volume.

**cenodude/CrossWatch** — Synchronize your data across media servers, media agents and trackers. Keep your movies and shows in sync, no matter where you watch.

- Repository: https://github.com/cenodude/CrossWatch
- Website: https://wiki.crosswatch.app
- Stars: 969 · Forks: 25
- Language: Python
- License: AGPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/cenodude-crosswatch

## The state of your watching is spread across services that never talk

The description is that CrossWatch tracks what you watch through Watcher and syncs your watchlists, ratings, history, playback progress and collections across supported media servers and trackers. That is the whole problem in one sentence. A realistic setup has a media server, a couple of trackers, maybe a second server for a different kind of content, and the record of what has been watched lives in all of them, in slightly different shapes, and drifts apart. The project frames its answer as keeping your data with you without being tied to one tracker. So the architecture is a local service that talks to everything, and a local store that keeps snapshots so that the data is not only in the services it came from. The tool runs locally with a web interface and a command line, and the README is explicit that it is a single brain for all your media syncs, which is the phrase the container image carries as its description.

## Watcher is the piece that does not need a paid subscription

The headline benefit is stated twice, once in the introduction and once in the features list, and it is the one that will decide the adoption for many people. Watcher does not need Plex Pass or Emby Premiere. The features are otherwise the usual scrobbling ones, with the addition of a set of routes. You set up multiple Watcher routes for different servers and different users, and each route knows which server to report to and which tracker to report to. The scrobbling section spells out the sources. Watcher reports playback from Plex, Emby, Jellyfin, Kodi and Scrob to the supported trackers, and you can also use webhooks from Plex, Emby and Jellyfin directly, with anime ID mapping available for Watcher and for the webhook path where the provider supports it. So the design is that you report a play event once, from whichever server or add-on produced it, and the routing decides where it goes.

## Sync pairs, and what each pair is allowed to carry

The syncing model is pairwise, and the flexibility is the point. You can sync two media servers with each other, connect a server to a tracker, or sync tracker to tracker, and for each pair you choose what it carries, with watch history, playback progress, watchlists, ratings and collections all being options, subject to what the provider on each side actually supports. Pairs can be run by hand or on a schedule. The management surface is the web interface, where you handle accounts, Watcher routes, syncs, the current playback and a combined watchlist, and there are profiles so that your setup is kept separate from those of friends or family sharing the instance. The feature list also mentions multiple accounts, separate profiles and managed user support, and rewatches for the trackers that can report them, which is the kind of detail that only matters to somebody who has already run a scrobbler.

## Review before you apply, and a mapping system for the messy cases

When a sync goes wrong, and with anime and with series that have been split or combined across releases, it goes wrong in ways that need a human. Three features exist for that. Interactive Sync lets you review additions, updates and removals before they are applied, so a bad match is caught rather than propagated. The Analyzer helps you check for missing items, so a title that exists on one side and not the other is visible. And saved mappings let you fix the cases that keep recurring, wrong matches, anime episode numbering and split or combined episodes, and they are saved for future syncs. Together they turn the sync from a blind merge into something a person can supervise, which is the difference between a tool that works on a curated library and one that quietly corrupts one. The same section also notes that a local CW Tracker keeps snapshots of your server and tracker data, so there is a copy of the state inside your own machine rather than only in the services.

## A long integration list that is not uniform

The supported integrations are listed in one dense sentence, and it is worth picking out the shape of it. The media servers are Plex, Jellyfin, Emby, Kodi and Stremio. The trackers and databases are SIMKL, Floppy, FlickList, Trakt, WeTrakr, AniList, MyAnimeList, Kitsu, TMDb, MDBList, PublicMetaDB, Tracearr, Nuvio and the local CW Tracker. The supporting tools are Scrob, Tautulli, PunchPlay and BingeBase. The README says the important caveat in the next line, that not every integration supports every feature, and that some sync lists and history while others report playback activity. So the practical work of adopting this is not choosing a list but building a matrix of which pair can carry which field, and the documentation for each integration in the wiki is where that lives. The optional AI help sits on top of that, where you can ask CrossWatch for advice using your own AI model, and can give AI applications like Claude, Codex or Cursor read-only access to your library, and it is off until you set it up.

## One container, one volume, one port

The installation is Docker, and the compose file is short. The image is published to the GitHub Container Registry and to Docker Hub, and the service listens on 8787 with the configuration in a named volume:

```yaml
services:
  crosswatch:
    image: ghcr.io/cenodude/crosswatch:latest
    container_name: crosswatch
    ports:
      - "8787:8787"
    environment:
      TZ: Europe/Amsterdam
    volumes:
      - crosswatch_config:/config
    restart: unless-stopped
```

The single command form is the equivalent one liner:

```bash
docker run -d \
  --name crosswatch \
  -p 8787:8787 \
  -v crosswatch_config:/config \
  -e TZ=Europe/Amsterdam \
  --restart unless-stopped \
  ghcr.io/cenodude/crosswatch:latest
```

The README makes one point about that volume that matters operationally, that both examples store persistent data in a Docker volume mounted at `/config`, and that you should keep it when replacing or updating the container. Your first sync is then four steps in the browser at `http://localhost:8787`, connect the accounts you want, create a sync pair by choosing the services and what to sync, run the pair and check the results, using Interactive Sync if you want to review first, and add a schedule if you want it to run by itself.

## The stack, the image and the release rhythm

The requirements file describes the implementation. It is a FastAPI service with pydantic for the models and uvicorn underneath, requests and the websocket libraries for talking to the services, `plexapi` for the Plex side specifically, `typer` and `rich` for the command line, and `cryptography`, `defusedxml` and `qrcode`, which together suggest that credentials are handled with real crypto and that XML from third parties is parsed defensively. The Dockerfile is careful for a hobby project of this kind, built on a Python 3.13 slim base, running as a non-root `appuser` with a fixed uid and gid, with byte code writing and pip caching turned off and the entrypoint and the sync runner copied in separately. The repository is laid out the same way, with `api/`, `cli/`, `providers/`, `services/` and a `cw_platform/` directory, plus pytest configuration and a requirements file for development. The licence is AGPL-3.0, and the release cadence is very fast, with v0.13.4, v0.13.5 and v0.13.6 landing on 2026-10-11, 2026-10-14 and 2026-10-18, and the last push to the repository on 2026-10-19.

## Conclusion

CrossWatch suits a household or a small group with more than one media server and more than one tracking account, since the whole point is that the state of what you have watched is spread across services that were never designed to talk, and this puts a single service in the middle. It is a poor fit if you have one server and one tracker, because there is nothing to reconcile, and the AI features are optional, off until you set them up, and they involve giving a model read access to your library. Before you deploy it, check three things: which pairs of services you actually want synchronised, since not every integration supports every feature, that you keep the `/config` volume when you replace the container, since that is where the state lives, and the licence, which is AGPL-3.0, with releases landing roughly every three days and the last one on 2026-10-18.

## FAQ

### What does CrossWatch actually synchronise?

Watchlists, ratings, watch history, playback progress and collections, with rewatches for the trackers that support them. You choose per sync pair what it carries, between servers, between trackers or from a server to a tracker, and pairs can be run manually or on a schedule.

### Does CrossWatch need Plex Pass or Emby Premiere?

No. The README says twice that Watcher does not need Plex Pass or Emby Premiere, and the scrobbling section spells out that Watcher reports playback from Plex, Emby, Jellyfin, Kodi and Scrob to the supported trackers, with webhooks also available from Plex, Emby and Jellyfin.

### How do I run CrossWatch?

With Docker, using the published image ghcr.io/cenodude/crosswatch:latest, port 8787 exposed, and a named volume mounted at /config. The README stresses that the volume holds the persistent data and should be kept when the container is replaced or updated. Then you connect your accounts and create a sync pair in the web interface at http://localhost:8787.

### What is Interactive Sync in CrossWatch?

A mode where additions, updates and removals are reviewed before they are applied, so a bad match does not propagate. It sits alongside the Analyzer, which helps find missing items, and the saved mappings that fix recurring problems such as wrong matches, anime episode numbering and split or combined episodes.

### Does CrossWatch send my library to an AI service?

Only if you set it up. The AI help is optional and off until you configure it, and it works with your own AI model, and the documentation also mentions giving AI applications such as Claude, Codex or Cursor read-only access to your library. The project is AGPL-3.0 licensed, with v0.13.6 published on 2026-10-18.

## Sources

- [cenodude/CrossWatch on GitHub](https://github.com/cenodude/CrossWatch)
- [License: AGPL-3.0](https://github.com/cenodude/CrossWatch/blob/main/LICENSE)
- [Project website](https://wiki.crosswatch.app)
- [README](https://github.com/cenodude/CrossWatch/blob/main/README.md)
- [Releases](https://github.com/cenodude/CrossWatch/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cenodude-crosswatch
