> For the complete documentation index, see [llms.txt](https://wiki.crosswatch.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wiki.crosswatch.app/crosswatch/command-line-interface-cli.md).

# Command-Line Interface (CLI)

Manage CrossWatch from a terminal with the cw command.

If you're more of a CLI kind of person, I've got you covered..

`cw` brings CrossWatch to your terminal.

It manages status, configuration, provider logins, syncs, Watcher, schedules, logs, and every major tool. The CLI runs in the CrossWatch container. It calls the running API.

### Quick start

Run commands from the CrossWatch container.

```shell
docker exec -it crosswatch cw status
docker exec -it crosswatch cw auth setup --local --username admin
docker exec -it crosswatch cw sync run --follow
```

Use `cw --help` to list command groups. Use `cw <group> --help` for options and examples.

### Run the CLI

Run `cw` inside the CrossWatch container:

```shell
docker exec -it crosswatch cw status
docker exec -it crosswatch cw sync run --follow
docker exec -it crosswatch cw shell
```

Inside the container, `cw` is on `PATH`:

```shell
cw status
cw auth token create --local
```

Outside Docker, run from the installation root:

```shell
python cli/cw.py status
python -m cli status
```

### CLI-only container mode

Set `CW_CLI_ONLY=1` to keep the API, CLI, webhooks, and auth callbacks available.

This disables the CrossWatch web UI.

### First setup

On a fresh install, set the admin password before using API commands:

```shell
cw --local auth setup --username admin
```

This also creates and saves a CLI API token. Add `--no-token` to only set the password.

### Tokens

Without application authentication, remote access only exposes health, status, and setup endpoints.

For CLI-only installs, run `cw --local auth setup` from the host or container. With authentication enabled, create a local token:

```shell
cw --local auth token create --name cli
```

The token is shown once. The CLI saves it to `/config/.cw_cli/cli.json` in Docker.

Outside Docker, it uses `~/.crosswatch/cli.json`.

Provide a token per command or through `CW_TOKEN`:

```shell
cw --token cwt_... status
CW_TOKEN=cwt_... cw status
```

```shell
cw auth token whoami
cw auth token list
cw auth token revoke <id>
```

Tokens are hashed at rest. They inherit their user's permissions. Token actions enter the audit log. Use `--expires-days` to set an expiry.

### Global options

Global options work before or after a subcommand.

* `-U`, `--url` — Base URL. Uses `CW_URL`, then the local installation.
* `-T`, `--token` — API token. Uses `CW_TOKEN`, then the saved token.
* `-o`, `--output` — Output format: `auto`, `table`, `json`, `yaml`, or `plain`.
* `-L`, `--local` — Use this installation. Never call the API.
* `-k`, `--insecure` — Skip TLS checks for self-signed certificates.
* `--http-timeout` — Request timeout in seconds. Default: `30`.
* `-q`, `--quiet` — Suppress non-essential output.
* `--no-color` — Disable colour output.

Use `-o json` or `-o plain` in scripts. JSON is written to stdout. Errors are written to stderr.

```shell
cw pair list -o json | jq '.[] | select(.enabled) | .id'
cw auth token list -o plain | cut -f1
```

### Status

Use these commands to check the service and connected providers:

```shell
cw status                    # Full status summary.
cw status --fresh            # Probe providers instead of cached status.
cw status --no-providers     # Skip the provider table.
cw version                   # CW and provider module versions.
cw health                    # Check whether the service responds.
```

### Pairs

Create and manage synchronization pairs:

```shell
cw pair create plex trakt --feature watchlist --feature ratings
cw pair create simkl trakt --mode two-way
cw pair list [--enabled]
cw pair show <id>
cw pair enable <id>
cw pair disable <id>
cw pair feature <id> <feature> on|off
cw pair reorder <id> <id> ...
cw pair delete <id> [--yes]
```

Use any unique pair-ID prefix. You can also use the route name.

```shell
cw pair show pair_07c3
cw pair show "PLEX -> TRAKT"
```

### Run a sync

Run and monitor synchronization:

```shell
cw sync run                      # Run every enabled pair.
cw sync run 1                    # Run pair #1 from `cw sync list`.
cw sync run pair_07c3            # Run one pair by ID or unique prefix.
cw sync run --pair pair_07c3     # Run one pair.
cw sync run --follow             # Stream logs until completion.
cw sync once                     # Run locally and wait for completion.
cw sync once --pair pair_07c3    # Run one selected pair locally.
cw sync once --pair a --pair b   # Run several selected pairs locally.
cw sync once --feature watchlist # Run one feature locally.
cw sync status                   # Current or latest run.
cw sync follow                   # Attach to an active run.
cw sync cancel                   # Stop after the current step.
cw sync unresolved               # Items unmatched by the latest run.
cw sync providers [--counts]
```

`cw sync run` starts work through the running service. `cw sync once` runs locally, waits, and returns the sync result code.

Use `cw sync once` with `docker run --rm`, cron, or Kubernetes CronJobs. Unresolved items do not fail the command by default. Add `--fail-on-unresolved` for strict runs.

`cw sync run --follow` returns the underlying sync exit code.

### Configuration

Read or change configuration values:

```shell
cw config show [path]              # Full config or a subtree. Secrets are masked.
cw config get sync.anime.enabled
cw config set sync.anime.enabled true
cw config set some.list "[1,2,3]" --json
cw config unset some.key
cw config edit                     # Opens $EDITOR.
cw config meta                     # UI schema.
cw config migrate                  # Update an older config.
cw config path                     # Config, state, and database locations.
```

`set` uses a merge patch. It changes only the named key. Values parse as booleans, numbers, or `null` when applicable.

Use `--json` to replace an object or list. `unset` removes a key. Values under `app_auth` cannot be changed.

### Provider logins

Review available login flows before connecting:

```shell
cw auth providers
cw auth show jellyfin
cw auth list [--fresh]
```

`cw auth login <provider>` selects the required flow:

```shell
cw auth login trakt                # Prints a code and waits for approval.
cw auth login plex --no-wait       # Prints a code without waiting.
cw auth login jellyfin             # Prompts for server, username, and password.
cw auth logout simkl
```

Plex, Trakt, SIMKL, MDBList, PunchPlay, BingeBase, and Nuvio use device codes.

They print a URL and code. The CLI polls until connected or timed out.

Jellyfin, Emby, Kodi, Stremio, Floppy, Scrob, Tautulli, PublicMetaDB, and TMDb require fields.

Trakt, SIMKL, and AniList require a client ID and secret first.

For scripted logins, supply fields and disable prompts:

```shell
cw auth login jellyfin \
  --field jellyfin.server=http://192.168.2.100:8096 \
  --field jellyfin.username=admin \
  --field jellyfin.password="$JF_PASSWORD" \
  --non-interactive
```

Use `cw auth show <provider>` for supported field names. The provider prefix is optional. `--non-interactive` exits with code `2` when input is missing.

AniList then requires a browser approval. The CLI prints the URL and waits for its callback.

Use `--instance <id>` with commands that support multiple provider instances.

### Analysis and events

Investigate mismatches and review recorded activity:

```shell
cw analyzer problems
cw analyzer attention
cw analyzer ratings
cw analyzer activity
cw analyzer detail <provider> <feature> <key>
cw analyzer suggest <provider> <feature> <key>
cw analyzer fix <provider> <feature> <key>
cw analyzer drop <provider> <feature> <key>
cw analyzer tracker
```

Most analyzer commands accept `--pairs id1,id2`.

```shell
cw events status
cw events recent [--domain scrobble] [--view events]
cw events search "dragon ball" --provider TRAKT
cw events groups
cw events show <group_id>
cw events run <run_id>
cw events item <item_key>
cw events stats --range 7d
cw events calendar [--range 3m|6m|1y|60] [--metric changes|runs|failures]
cw events day [2026-09-05|today|yesterday]
cw events ack <group_id> [--undo]
cw events clear
```

### Captures and backups

Captures provide point-in-time rollback:

```shell
cw capture list
cw capture create [--provider PLEX] [--feature watchlist]
cw capture diff <older> <newer>
cw capture read <path>
cw capture restore <path> [--dry-run]
cw capture delete <path>
cw capture clear
```

`capture create` waits and prints progress. Add `--no-wait` to return immediately.

```shell
cw backup list
cw backup create --note "before the big sync"
cw backup validate <path>
cw backup restore <path>
cw backup delete <path>
cw backup schedule [--enable] [--every-hours 24]
cw backup retention 10
```

### Media and playlists

#### Watchlists and playback

Manage watchlists, playback records, and editor data:

```shell
cw watchlist list [--type movie] [--search dune]
cw watchlist remove <key> [<key> ...]

cw progress list [--provider PLEX] [--min 10]
cw progress providers
cw progress settings
cw progress watched <key>
cw progress set <key> 45
cw progress remove <key>
```

#### Editor

```shell
cw editor list --kind watchlist [--provider PLEX]
cw editor sources
cw editor providers
cw editor send <key> --provider TRAKT
cw editor export
```

#### Playlists

Configure playlist resources, endpoints, mappings, and rules:

```shell
cw playlist overview
cw playlist providers
cw playlist resources PLEX
cw playlist activity
cw playlist setup --source-provider TRAKT --source-playlist LIST_ID --target-provider PLEX --create-target "Weekend"

cw playlist resource list PLEX
cw playlist resource create PLEX --name Weekend
cw playlist resource rename PLEX LIST_ID --name NewName
cw playlist resource delete PLEX LIST_ID

cw playlist endpoint list
cw playlist endpoint add PLEX LIST_ID --name PlexFavs
cw playlist endpoint edit EP-01 --playlist LIST_ID
cw playlist endpoint sync EP-01
cw playlist endpoint delete EP-01

cw playlist mapping list
cw playlist mapping add --source EP-01 --target EP-02 --name Movies
cw playlist mapping edit MAP-01 --membership mirror --order preserve
cw playlist mapping enable MAP-01
cw playlist mapping disable MAP-01
cw playlist mapping run MAP-01
cw playlist mapping preview MAP-01
cw playlist mapping result MAP-01
cw playlist mapping delete MAP-01

cw playlist ruleset list
cw playlist ruleset show trakt_free_account
cw playlist ruleset clone trakt_free_account --name MyRules
cw playlist ruleset add ruleset.json
cw playlist ruleset validate ruleset.json
cw playlist ruleset delete RULESET_ID
```

{% hint style="warning" %}
Always run `cw playlist mapping run <id> --dry-run` before a live mapping run.
{% endhint %}

### Import, metadata, and anime

#### Import and export

Use these commands for data exchange and item matching:

```shell
cw export options
cw export preview --provider PLEX --feature watchlist
cw export file out.csv --provider PLEX --feature watchlist

cw import options
cw import preview letterboxd.csv
cw import commit <import_id> --features watchlist
```

#### Metadata and manual entries

```shell
cw metadata search "blade runner" --year 1982
cw metadata resolve imdb=tt0083658
cw metadata providers

cw manual providers
cw manual watched --field imdb=tt0083658 --field type=movie --provider TRAKT
```

#### Anime mapping

```shell
cw anime status
cw anime update [--rebuild]
cw anime overrides
cw anime add-override \
  --field match_provider=tvdb --field match_id=81472 \
  --field target_namespace=anidb --field target_id=4563
cw anime delete-override <rule_id>
cw anime search "dragon ball z"
cw anime export
```

### Instances, profiles, and scrobbling

#### Instances and profiles

Manage provider instances, user profiles, and scrobbling routes:

```shell
cw instance list [PLEX] [--configured]
cw instance add plex --field server=http://...
cw instance set plex PLEX-P01 --field label="Living room"
cw instance delete plex PLEX-P01

cw user-profile list|show|create|set|delete
```

#### Scrobbling

```shell
cw scrobbler overview
cw scrobbler event-routes
cw scrobbler route add|set|delete
cw scrobbler webhook urls
cw scrobbler webhook regenerate
cw scrobbler webhook cleanup-legacy
```

### Reporting and maintenance

#### Reporting

Review local activity, then run maintenance when needed:

```shell
cw insights
cw stats [--raw]
cw activity recent
cw activity history [--type movie] [--search dune]
cw activity clear
```

#### Maintenance

Maintenance commands can delete local data or restart CrossWatch.

```shell
cw maintenance tools               # Show modal-style maintenance actions.
cw maintenance database
cw maintenance events              # Archive health, --optimize, --purge, --rebuild.
cw maintenance cache <what>        # all, metadata, provider-sync, activity-log, scrobbles, state.
cw maintenance provider-cache
cw maintenance provider-cleanup    # Clear provider watchlist, ratings, history, progress, or collection.
cw maintenance state-file --prune|--compact
cw maintenance tracker [--clear]
cw maintenance reset-stats
cw maintenance reset-watching
cw maintenance support [--scopes]
cw maintenance factory-reset       # Requires --confirm RESET.
cw maintenance restart
```

### Watcher, scheduler, and logs

#### Watcher

Control background services and inspect their output:

```shell
cw watcher status
cw watcher start
cw watcher stop
cw watcher restart                 # Reload config and restart routes.
cw watcher now
cw watcher logs [-n 200]
```

#### Scheduler

```shell
cw scheduler status
cw scheduler next
cw scheduler enable
cw scheduler disable
cw scheduler list                  # List advanced jobs.
cw scheduler set hourly
cw scheduler set every 6h
cw scheduler set daily 03:30
cw scheduler set interval 45m
cw scheduler add PAIR_ID --at 00:00 --at 12:00
cw scheduler setup --kind pair --pair 1,3 --at 03:30
cw scheduler edit JOB_ID --at 03:30
cw scheduler pause JOB_ID
cw scheduler resume JOB_ID
cw scheduler delete JOB_ID
cw scheduler setup                 # Run guided setup.
cw scheduler run-now
cw scheduler replan
cw scheduler stop
cw scheduler show
```

#### Logs

```shell
cw logs tail                       # Last 200 SYNC lines.
cw logs tail -t WATCH -n 500
cw logs tail -f
cw logs tail -f --grep "ERROR|WARN"
cw logs channels
```

### Interactive shell

Run `cw shell` to open an interactive prompt.

```
cw> sync
cw(sync)> ?
cw(sync)> status
cw(sync)> run --follow
cw(sync)> !status
cw(sync)> exit
cw> config
cw(config)> get sync.anime.enabled
cw(config)> exit
cw> exit
```

`?` lists commands in the current group. Use `help <command>` for detailed help. Use `exit`, `end`, or `..` to move back.

History is saved to `~/.crosswatch/history`. Tab completion works where `readline` is available.

### Exit codes

```
0   Success.
1   Command failed.
2   Invalid usage.
3   Cannot reach CrossWatch.
4   Not allowed.
5   Not found.
6   Busy. A sync is already running.
```

### When the service is down

Supported read-only and repair commands fall back to the local installation. The CLI writes a notice to stderr and reports `local (fallback)` as the endpoint.

```
! Cannot reach CrossWatch at http://127.0.0.1:8787 - answering from the local install instead
```

The fallback supports `status`, `health`, `version`, all `config` commands, `pair list/show/enable/disable/delete`, `sync list`, `scheduler status/next/show`, and all `auth token` commands.

Commands requiring the running engine fail with exit code `3`. This includes syncs, Watcher actions, and live logs. `--local` forces this mode and rejects unsupported commands immediately.

### CLI layout

```
cli/
  cw.py            Entry point.
  _app.py          Typer app, argument hoisting, and error handling.
  _context.py      Per-invocation state with API-first local fallback.
  _transport.py    HTTP client and SSE log streaming.
  _local.py        In-process transport for offline commands.
  _settings.py     URL and token resolution, plus cli.json.
  _render.py       Table, key-value, JSON, YAML, and plain output.
  _util.py         Dotted paths, parsing, formatting, and pair lookup.
  _errors.py       Error types and exit codes.
  commands/        One module per command group.
```

To add a group, create `commands/<name>.py` with `register(app)`. List it in `_app._register_all`. Commands use `Ctx`, which provides automatic local fallback.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://wiki.crosswatch.app/crosswatch/command-line-interface-cli.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
