# Pulsarr: routing Plex watchlists into Sonarr and Radarr

> Pulsarr is a TypeScript service that watches Plex watchlists and hands matching requests to Sonarr and Radarr, with routing rules built on genre, user, language, year, certification, ratings and streaming service, plus approval queues with per-user quotas. It runs on SQLite by default, ships a Docker image and native installers, and the project labels itself an early release.

**jamcalli/Pulsarr** — Pulsarr: Real-time Plex watchlist monitoring and content acquisition tool. Seamlessly sync Plex watchlists with Sonarr and Radarr, featuring intelligent predicated content routing, multi-instance support, Discord, and Apprise notifications. Automate your media library management with a modern, user-friendly interface.

- Repository: https://github.com/jamcalli/Pulsarr
- Website: https://jamcalli.github.io/Pulsarr/
- Stars: 756 · Forks: 16
- Language: TypeScript
- License: AGPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/jamcalli-pulsarr

## What the project bridges and who it is for

Pulsarr is a real-time Plex watchlist monitoring, routing and notification centre. The README describes it as bridging Plex watchlists with Sonarr and Radarr for real-time media monitoring and automated content acquisition, and it makes the point that all of this happens from within the Plex app with no extra logins required.

That last clause is the design decision. The watchlist is the user's interface to the system, since a person watching on Plex presses add and expects the show to appear, and Pulsarr exists to make that press do something. A Plex Pass account gets instant watchlist updates, while non-Pass users are polled on a five-minute stagger, which reflects what the Plex API allows rather than a design choice.

The features list names multi-user watchlist sync, intelligent content routing, approval workflows with quotas, and notifications through Discord, Plex mobile push and Apprise. The topic tags describe the neighbourhood precisely, with plex, plex-integration, sonarr, radarr and the arrs family, alongside media-library, media-server, media-tracker, watchlist, home-server, docker, fastify, react and typescript.

The transparency section is unusual and worth reading. Pulsarr began as a TypeScript rewrite of Watchlistarr, it is developed with AI assistance, but every decision about architecture, features and direction is human-made, and everything is reviewed before it ships.

The licence field on the repository says AGPL-3.0, and the status badge in the README describes the project as an early release.

## Routing rules and the approval system

The content routing is the part that makes Pulsarr more than a sync script, and the rules are built on a set of conditions with AND and OR logic.

The conditions are genre, user, language, year, certification, season, IMDb, Rotten Tomatoes and TMDB ratings, and streaming service. That is a wide surface, and the ratings and certification in particular point at a use case: a user who only wants certain kinds of content, or content above a quality threshold, or content from particular services.

The rules can also require approval or bypass quotas, which is where the routing connects to the approval machinery.

The approval and quota system is described as administrative approval workflows with configurable user quotas, with daily, weekly and monthly limits. So the model is that a request arrives, is matched against rules, and then either goes straight through or waits for an administrator to approve it, with per-user limits on how much can be requested in a given period.

For a shared server this is the feature that matters, because without it a single enthusiastic user can fill the library with everything on their watchlist. With it, the system can be pointed at content people actually want, and the disk has a ceiling.

There is a Plex session monitoring feature that auto-searches for next seasons when users are near a season finale, which is a small automation that would otherwise be a recurring chore.

## Running it with Docker and the Node fallback image

The recommended installation is Docker, and it is a compose file with an environment file, which is the standard shape for this kind of self-hosted service.

The environment file needs at least a timezone, and the README shows the whole file as one variable.

```env
# Your timezone
TZ=America/Los_Angeles
```

The compose file publishes port 3003, mounts a data directory, and passes the user and group identifiers so that the files the service writes land with the right ownership on the host.

```yaml
services:
  pulsarr:
    image: lakker/pulsarr:latest
    container_name: pulsarr
    ports:
      - "3003:3003"
    volumes:
      - ./data:/app/data
    environment:
      - PUID=1000
      - PGID=1000
    restart: unless-stopped
    env_file:
      - .env
```

Then the service is pulled and started.

```bash
docker compose pull && docker compose up -d
```

And the web interface is at port 3003 on the host, where setup is completed.

The one detail with a real operational consequence is the fallback image. The README says that on a Synology NAS or a system with a Linux kernel older than 4.11 you should use the node image instead of the default. That image runs on Node.js rather than Bun, avoiding the kernel compatibility problem, and the two images are functionally identical.

That is a real deployment consideration rather than a footnote, because the default runtime is Bun and the people running the arr stack on NAS hardware are exactly the people who will hit it.

## Native installs, databases and the API

There are standalone builds with installers for Linux, macOS and Windows, with no Docker and no runtime install required. The Linux route is a piped shell installer, the Windows route is a downloaded setup executable from the latest release, and the macOS route is a disk image for the relevant architecture.

The database is SQLite by default, and the configuration documentation covers switching to PostgreSQL. The .env.example in the repository shows the shape of that configuration, and it is worth reading because it documents the precedence rule explicitly. Environment variables override the web UI settings on restart, and removing a variable lets the web UI value persist instead. That is a specific and slightly surprising behaviour, since most applications treat the file and the UI as the same source of truth.

The file also shows the security settings. There is a listen port and a base path for a subfolder reverse proxy, a cookieSecured flag that the README says to set only when serving over HTTPS, and an authenticationMethod with the options required, requiredExceptLocal and disabled. So local access can be exempt from authentication, which is convenient on a home network and is a decision to make deliberately.

The REST API is documented two ways, with public documentation on the site and interactive Scalar documentation built into every instance at the api docs path on port 3003.

There is also a hosted option. ElfHosted offers managed Pulsarr hosting with pre-configured media server bundles, and 33 percent of every subscription supports the project, which is a way to run it without touching the stack yourself.

## The build system and the repository layout

The package.json shows a Bun-first project with a fine-grained script layout, and the structure is the clearest sign of how the code is organised.

The server is TypeScript compiled with tsc and tsc-alias, and the client is built with Vite. The build script cleans the server output, builds the server, cleans the client and then runs the Vite build, and the development scripts run the server directly through Bun with watch mode. There are separate dev scripts for the mocks, including one that starts a Radarr mock and one that starts a Sonarr mock, which is a sensible way to develop against the Arr APIs without a live instance.

The test setup is vitest with a run mode, a UI mode and a coverage mode, and there are six separate typecheck scripts, one each for the server, the client, the tests, the scripts, the migrations and the packages. A separate typecheck for migrations and for a local package called better-sqlite3-bun tells you the project treats the database layer and the migration code as its own boundaries.

The repository root matches. There is a src/ directory, a packages/ directory holding the local packages, a migrations/ directory, a docs/ directory, scripts/, test/ and data/, a .bun-version file, a .nvmrc, a bun.lock, a biome.json for formatting and linting, a commitlint config, a husky directory for hooks, and a components.json, which is the shadcn configuration.

The Docker side has separate files for the two runtimes, dockerfile and dockerfile.node, with matching entrypoint scripts and a healthcheck script, plus a docker-compose.migration.yml for moving an existing installation across.

## Where Pulsarr is the wrong choice

The first limitation is that it needs the whole arr stack. Pulsarr sits between Plex and Sonarr and Radarr, so it is a fourth service to run, to update and to point at the other three. For a single-user library where you add things to Sonarr and Radarr by hand, the orchestration is overhead with no payoff.

The second is the maturity, and the README is upfront about it with an early release status badge. The version is 0.19.7 and the release history shows a stream of patch releases through October 2026, which is a lot of movement for a young project. Moving the Arr stack around is not free, and a young project doing it automatically is a combination to think about.

The third is the deletion features. Advanced lifecycle management covers watchlist-based or tag-based deletion with playlist protection, and a system that removes media files based on a watchlist is a system that can remove something you wanted. The playlist protection and the quota system are the guards against that, and the approval workflow is the other one.

The fourth is the AGPL licence. That is a deliberate choice for a self-hosted service that a user might want to offer to others, and it matters if the plan is to run it as a service for a group.

The fifth is that the Plex side has real limits. Instant watchlist updates need a Plex Pass, and non-Pass accounts are polled on a five-minute stagger, so the real-time selling point only applies to some accounts. The README says as much, which is the right thing to do, but it is a constraint on the design rather than a detail.

## Pulsarr compared with Watchlistarr and with Tdarr

The comparison with Watchlistarr is the one the project itself draws, since Pulsarr began as a TypeScript rewrite of it. The difference in approach is the runtime and the scope. Watchlistarr is a Node project, and Pulsarr is Bun-first with a Node fallback image, and the feature list is much wider: routing rules with a dozen conditions, quotas, multi-instance support, Plex label synchronisation, session monitoring and a Discord bot with interactive approval, none of which is a small addition to a watchlist sync.

The comparison with Tdarr is about where the automation lives. Tdarr is a management layer over the arr stack that applies the quality profile rules and handles the list management across instances, and it works at the level of the arr applications themselves. Pulsarr works at the level of the user's intent, the watchlist, and routes the resulting request into whichever arr instance the rules select. They are complementary rather than competing, and a setup that has both is not unusual.

The third comparison is with doing it by hand, which for a small library is honestly fine. You watch something, you add it to Plex, you add it to Sonarr. The work that Pulsarr automates is the repetition of that across many items and several people, and the part it adds that you cannot get by hand is the rules.

The fourth is with a general automation platform. A workflow tool could watch the watchlist and call the arr APIs, and the difference is that Pulsarr already knows the arr API shapes, the Plex webhook behaviour and the label conventions, so the configuration is a set of rules rather than a graph of triggers.

## Licence, project state and what to set up before you let it act

The licence field on the repository says AGPL-3.0, and the README carries a licence badge for GPL. AGPL is a strong copyleft licence with a network clause, which is a reasonable choice for a self-hosted service you might run for a group, and it means a modified version offered over a network has to publish its source.

The project is not archived and the last push was on 2026-10-20, so it is actively worked on, and the release history shows v0.19.7 from 2026-10-13, v0.19.6 from 2026-10-12 and v0.19.5 from 2026-10-11.

Four things to set up before you let it act on its own.

The authentication method, because the environment configuration offers a disabled option alongside required and requiredExceptLocal, and that default is worth choosing deliberately on anything reachable from outside your network.

The quotas and approval rules, with at least one rule requiring approval, so that the first content that lands is one you looked at.

The database and the backup of it. The data directory is mounted as a volume in the compose file, and that directory holds the database, so it is the thing to back up.

And the deletion and lifecycle settings, which is the feature most likely to surprise you. Watchlist-based deletion and tag-based deletion both act on real media, and the playlist protection exists because of that.

## Conclusion

Pulsarr suits a self-hosted media library where several people share a Plex server and want watchlist additions to become library requests without hand adding each one, and it suits anyone who wants routing rules rather than one Arr instance taking everything. It is the wrong tool for a single-user library where Sonarr and Radarr already cover the watchlist, and it is a young project, so an operator should read the upgrade notes before letting it move content automatically. Before you enable auto-approval, set quotas and require approval for at least one rule, since the deletion and lifecycle features act on real media files.

## FAQ

### What does Pulsarr do?

It bridges Plex watchlists with Sonarr and Radarr, monitoring watchlists in real time and routing matching requests into the right Arr instance as content acquisitions. Plex Pass accounts get instant updates, while non-Pass accounts are polled on a five-minute stagger.

### What conditions can a Pulsarr routing rule use?

Rules combine with AND and OR logic over genre, user, language, year, certification, season, IMDb, Rotten Tomatoes and TMDB ratings, and streaming service. A rule can also require administrative approval or bypass the quota system.

### How do I install Pulsarr with Docker?

Create a .env file with your timezone, create a docker-compose.yml using the lakker/pulsarr image with port 3003 published and a data volume mounted, then run `docker compose pull && docker compose up -d` and open http://your-server:3003 to complete setup. On a Synology NAS or a kernel older than 4.11, use the node image instead of the Bun default.

### Does Pulsarr need Docker, and which database does it use?

No, standalone builds with installers exist for Linux, macOS and Windows. SQLite is used by default, and the configuration documentation covers switching to PostgreSQL.

### What notifications does Pulsarr support?

A Discord bot with interactive approval commands, Plex mobile push, webhooks, and more than eighty services through Apprise. The Discord integration and its commands are documented separately on the project site.

### What licence does Pulsarr use?

AGPL-3.0, with the terms in the LICENSE file at the root of the repository. The project also states that it began as a TypeScript rewrite of Watchlistarr and is developed with AI assistance but with human decisions on architecture, features and direction.

## Sources

- [jamcalli/Pulsarr on GitHub](https://github.com/jamcalli/Pulsarr)
- [License: AGPL-3.0](https://github.com/jamcalli/Pulsarr/blob/master/LICENSE)
- [Project website](https://jamcalli.github.io/Pulsarr/)
- [README](https://github.com/jamcalli/Pulsarr/blob/master/README.md)
- [Releases](https://github.com/jamcalli/Pulsarr/releases)

---

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