> 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/advanced-and-api/crosswatch-cli.md).

# CrossWatch CLI

`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. Actions appear in the web UI and use the same sync guard.

When the service is unavailable, supported read-only commands use the local installation.

### Run the CLI

In Docker, 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         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
    --no-color
```

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

```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 and sync

```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"
```

```shell
cw sync run                      # Run every enabled pair.
cw sync run --pair pair_07c3     # Run one pair.
cw sync run --follow             # Stream logs until completion.
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 --follow` returns the sync exit code. This suits cron jobs and health checks.

### Configuration

```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=pascal \
  --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

```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 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

```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>
```

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

```shell
cw playlist overview
cw playlist providers
cw playlist resources PLEX
cw playlist activity
cw playlist endpoint list|add|sync|delete
cw playlist mapping list|add|run|preview|result|delete
cw playlist ruleset list|show|delete
```

Always run `cw playlist mapping run <id> --dry-run` first.

### Import, metadata, and anime

```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
```

```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
```

```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

```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
```

```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

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

```shell
cw maintenance tools               # Show modal-style maintenance actions.
cw maintenance database
cw maintenance events              # Archive health, --optimize, --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, or progress.
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

```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]
```

```shell
cw scheduler status
cw scheduler next
cw scheduler enable
cw scheduler disable
cw scheduler run-now
cw scheduler replan
cw scheduler stop
cw scheduler show
```

```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.
```

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

### 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`, `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/advanced-and-api/crosswatch-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.
