Configuration (config.json)
Config file location, load rules, and key reference for config.json.
Use this as a reference for config.json.
Values come from defaults and normalization in cw_platform/config_base.py.
config.json contains tokens and secrets.
Redact it before sharing logs or screenshots.
Avoid editing config.json by hand.
Most settings are configurable in the UI.
At a glance
Config file
<CONFIG_BASE>/config.json
Created if missing.
Docker default
/config/config.json
Used when /app exists.
Manual edits
Avoid
UI covers most settings.
Secrets
Tokens and password hashes
Redact before sharing.
Config file location
CrossWatch chooses the config base directory in this order.
1
CONFIG_BASE env var is set
CONFIG_BASE value
2
Running in Docker image (/app exists)
/config
3
Running from source
Project root (one level above cw_platform/)
The file path is always:
<CONFIG_BASE>/config.json
Load and save behavior
Defaults + deep merge
Your config overlays DEFAULT_CFG. Missing keys are filled in.
Unknown keys preserved
Extra keys are kept. Useful for experiments.
Version stamping
version is rewritten on load/save.
Pair feature normalization
pairs[].features.* are coerced to a uniform shape.
Atomic saves
Writes use a temp file then replace config.json.
Redaction helper
Sensitive fields can be masked for UI/log output.
Defaults + deep merge
On startup, CrossWatch:
Loads
config.json.Deep-merges it over
DEFAULT_CFG.
Merge rules:
Dict + dict merges recursively.
Any other type overrides the default.
Version stamping
On load/save:
version= app version (leadingvremoved)
1
api.versionAPI.CURRENT_VERSION
2
APP_VERSION env var
3
Fallback v0.7.0
Pair feature normalization
Each feature becomes:
true
Enabled, adds on, removes off
Missing keys
Defaults: enable:true, add:true, remove:false
Invalid values
Feature disabled
Ratings has extra fields.
See Ratings feature.
Redaction
redact_config(cfg) replaces sensitive values with ••••••••.
app_auth.password.hash
Password hash
app_auth.password.salt
Password salt
app_auth.session.token_hash
Session token hash
Key reference
Top-level
version
string
Managed by the app.
pairs
array
Pair definitions created in the UI.
plex, trakt, …
object
Provider connection and tuning.
sync
object
Global orchestrator defaults.
runtime
object
Logging and guardrails.
scrobble
object
Real-time progress forwarding.
scheduling
object
Periodic runs.
ui
object
UI toggles.
app_auth
object
Optional UI login.
Providers
plex
server URL, token, tuning
Sync + scrobble source
jellyfin / emby
server URL, token, tuning
Sync + scrobble source
trakt / simkl / mdblist
OAuth/API keys
Tracker targets/sources
anilist
OAuth/API keys
Anime tracker
tmdb
API key
Matching support
tautulli
URL + API key
History import
crosswatch
local paths + snapshot rules
Local backup provider
Plex
Connection
plex.server_url
string
Example: http://192.168.1.10:32400
plex.verify_ssl
bool
Keep false for self-signed.
plex.account_token
string
Set via UI PIN login.
plex.client_id
string
Client identifier.
plex.machine_id
string
Targets a specific server.
plex.username
string
Plex Home profile name.
plex.account_id
string
Server-local account ID.
plex.home_pin
string
Optional Plex Home PIN.
plex.timeout
number
Seconds.
plex.max_retries
int
Retry budget.
plex.fallback_GUID
bool
Discover fallback for missing GUID mapping.
Scrobble filters
plex.scrobble.libraries
array
Empty means all libraries.
History
plex.history.libraries
array
Whitelist of library GUIDs. Empty = all.
plex.history.include_marked_watched
bool
Include Plex “marked watched” state (add-only behavior).
plex.history_workers
int
Parallel workers for history indexing. 12–16 is ideal on a local NAS.
Ratings
plex.ratings.libraries
array
Whitelist of library GUIDs. Empty = all.
plex.rating_workers
int
Parallel workers for ratings indexing. 12–16 is ideal on a local NAS.
Watchlist (Discover-driven)
plex.watchlist_allow_pms_fallback
bool
Allow PMS watchlist fallback when needed. Keep false for strict Discover-only behavior.
plex.watchlist_page_size
int
Discover page size (100–200). Higher is faster, but can trigger 504s.
plex.watchlist_query_limit
int
Max Discover search results per query (10–25).
plex.watchlist_write_delay_ms
int
Optional pacing between Discover writes. Set 50–150 if you hit 429/5xx.
plex.watchlist_title_query
bool
Use title/slug tokens for Discover candidate fetching.
plex.watchlist_use_metadata_match
bool
Try PMS /library/metadata/matches first, then fallback to Discover.
plex.watchlist_guid_priority
array
GUID resolution order (first match wins).
Trakt
OAuth
trakt.client_id
string
From your Trakt app.
trakt.client_secret
string
From your Trakt app.
trakt.access_token
string
OAuth2 access token.
trakt.refresh_token
string
OAuth2 refresh token.
trakt.scope
string
Usually public or private.
trakt.token_type
string
Usually Bearer.
trakt.expires_at
int
Epoch seconds.
trakt._pending_device
object
Temporary device code state (PIN flow).
HTTP
trakt.timeout
int
HTTP timeout (seconds).
trakt.max_retries
int
Retry budget (429/5xx backoff).
Watchlist
trakt.watchlist_use_etag
bool
Use ETag + local shadow to skip unchanged lists.
trakt.watchlist_shadow_ttl_hours
int
Refresh ETag baseline periodically even if 304s keep coming.
trakt.watchlist_batch_size
int
Chunk size for add/remove to reduce rate spikes.
trakt.watchlist_log_rate_limits
bool
Log X-RateLimit-* and Retry-After when present.
trakt.watchlist_freeze_details
bool
Persist last status & ids for debugging.
Ratings
trakt.ratings_per_page
int
Items per page when indexing (10–100).
trakt.ratings_max_pages
int
Safety cap per type.
trakt.ratings_chunk_size
int
Batch size for POST/REMOVE.
History
trakt.history_per_page
int
Max allowed by Trakt (100).
trakt.history_max_pages
int
Safety cap for large histories.
trakt.history_unresolved
bool
Enable unresolved “freeze” files.
trakt.history_number_fallback
bool
Episode number fallback if episode IDs are missing.
trakt.history_collection
bool
Mirror history adds into your Trakt Collection.
SIMKL
simkl.access_token
string
OAuth2 access token.
simkl.refresh_token
string
OAuth2 refresh token.
simkl.token_expires_at
int
Epoch seconds.
simkl.client_id
string
From your SIMKL app.
simkl.client_secret
string
From your SIMKL app.
simkl.date_from
string
YYYY-MM-DD (optional backfill start).
AniList
anilist.client_id
string
From your AniList app.
anilist.client_secret
string
From your AniList app.
anilist.access_token
string
OAuth access token.
anilist.user
object
Cached viewer object (id/name).
MDBList
Connection
mdblist.api_key
string
Your MDBList API key.
mdblist.timeout
int
HTTP timeout (seconds).
mdblist.max_retries
int
Retry budget.
Watchlist
mdblist.watchlist_shadow_ttl_hours
int
Shadow TTL (hours). 0 disables.
mdblist.watchlist_shadow_validate
bool
Validate shadow on every run.
mdblist.watchlist_page_size
int
GET page size for /watchlist/items.
mdblist.watchlist_batch_size
int
Batch size for add/remove writes.
mdblist.watchlist_freeze_details
bool
Store extra details for “not_found” freezes.
Ratings
mdblist.ratings_per_page
int
Items per page when indexing.
mdblist.ratings_max_pages
int
Max pages to fetch (safety cap).
mdblist.ratings_chunk_size
int
Batch size for POST/REMOVE.
mdblist.ratings_write_delay_ms
int
Optional pacing between writes.
mdblist.ratings_max_backoff_ms
int
Max backoff time for retries.
mdblist.ratings_since
string
First-run baseline; watermark overrides after.
History
mdblist.history_per_page
int
Items per page for watched delta.
mdblist.history_max_pages
int
Max pages to fetch (safety cap).
mdblist.history_chunk_size
int
Batch size for watched/unwatched writes.
mdblist.history_write_delay_ms
int
Optional pacing between writes.
mdblist.history_max_backoff_ms
int
Max backoff time for retries.
mdblist.history_since
string
First-run baseline; watermark overrides after.
Tautulli
Connection
tautulli.server_url
string
Example: http://host:8181
tautulli.api_key
string
Tautulli API key.
tautulli.verify_ssl
bool
Verify TLS certificates.
tautulli.timeout
number
HTTP timeout (seconds).
tautulli.max_retries
int
Retry budget.
History import
tautulli.history.user_id
string
Optional user filter.
tautulli.history.per_page
int
Tautulli history page size.
tautulli.history.max_pages
int
Safety cap.
Jellyfin / Emby
Same structure.
Connection
*.server
string
Base URL.
*.access_token
string
Auth token.
*.user_id
string
Active user.
*.device_id
string
Client device id.
*.username
string
Optional login username.
*.user
string
Optional display name (hydrated after auth).
*.verify_ssl
bool
TLS verification.
*.timeout
number
Seconds.
*.max_retries
int
Retry budget.
Scrobble filters
*.scrobble.libraries
array
Whitelist of library GUIDs. Empty = all.
Watchlist (emulated)
*.watchlist.mode
string
favorites | playlist | collections
*.watchlist.playlist_name
string
Used when mode is playlist.
*.watchlist.watchlist_query_limit
int
Batch size.
*.watchlist.watchlist_write_delay_ms
int
Delay between writes.
*.watchlist.watchlist_guid_priority
array
ID match order.
History
*.history.history_query_limit
int
Batch size.
*.history.history_write_delay_ms
int
Delay between writes.
*.history.history_guid_priority
array
ID match order.
*.history.libraries
array
Whitelist of library GUIDs. Empty = all.
Ratings
*.ratings.ratings_query_limit
int
Ratings query limit (default 2000).
*.ratings.libraries
array
Whitelist of library GUIDs. Empty = all.
CrossWatch (local provider)
crosswatch.root_dir
string
Local provider folder.
crosswatch.enabled
bool
Enables provider.
crosswatch.auto_snapshot
bool
Snapshot before writes.
crosswatch.retention_days
int
0 keeps forever.
crosswatch.max_snapshots
int
0 unlimited.
crosswatch.restore_watchlist
string
latest, empty, or a specific snapshot stem.
crosswatch.restore_history
string
latest, empty, or a specific snapshot stem.
crosswatch.restore_ratings
string
latest, empty, or a specific snapshot stem.
Sync (sync)
sync)Global defaults. Pair-level settings override these by design.
sync.enable_add
bool
Allow additions by default.
sync.enable_remove
bool
Safer default: disabled unless you opt in.
sync.verify_after_write
bool
When supported, re-check destination after writes.
sync.dry_run
bool
Plan and log only. No writes.
sync.drop_guard
bool
Guard against empty/suspect snapshots.
sync.allow_mass_delete
bool
If false, block large delete plans.
sync.tombstone_ttl_days
int
How long “observed deletes” stay valid.
sync.include_observed_deletes
bool
If false, skip processing observed deletes for the run.
Two-way defaults (optional)
sync.bidirectional.enabled
bool
Default off. Pairs still decide final mode.
sync.bidirectional.mode
string
Placeholder default (usually two-way).
sync.bidirectional.source_of_truth
string
Optional tie-breaker if you enforce strict authority.
Blackbox (including flapper protection)
sync.blackbox.enabled
bool
Turn off to fully disable blackbox logic.
sync.blackbox.promote_after
int
Promote after N consecutive unresolved/fail events.
sync.blackbox.unresolved_days
int
Minimum unresolved age before it counts (0 = immediate).
sync.blackbox.pair_scoped
bool
Track per pair to avoid blocking the same title elsewhere.
sync.blackbox.cooldown_days
int
Auto-prune after cooldown.
sync.blackbox.block_adds
bool
Block planned ADDs while blackboxed.
sync.blackbox.block_removes
bool
Block planned REMOVEs while blackboxed.
Runtime (runtime)
runtime)runtime.debug
bool
Extra verbose logging (debug level).
runtime.debug_http
bool
Extra verbose HTTP logging.
runtime.debug_mods
bool
Extra verbose MOD logs for Synchronization Providers.
runtime.state_dir
string
Optional override for state dir. Avoid for containers.
runtime.telemetry.enabled
bool
Usage stats.
runtime.snapshot_ttl_sec
int
Reuse snapshots within this window.
runtime.apply_chunk_size
int
Batch size for apply.
runtime.apply_chunk_pause_ms
int
Pause between chunks.
runtime.apply_chunk_size_by_provider
object
Per-provider overrides (example: SIMKL).
runtime.suspect_min_prev
int
Minimum previous size to enable suspect guard.
runtime.suspect_shrink_ratio
number
Shrink ratio to trigger suspect guard.
Metadata (metadata)
metadata)metadata.locale
string
Example: en-US.
metadata.ttl_hours
int
Coarse resolver cache TTL.
Scrobble (scrobble)
scrobble)scrobble.enabled
bool
Master toggle.
scrobble.mode
string
watch or webhook.
scrobble.delete_plex
bool
Legacy name but still valid. Auto-remove movies from watchlists.
scrobble.delete_plex_types
array
Legacy name but still valid. Types: movie, show, episode.
Watcher mode (scrobble.watch)
scrobble.watch)scrobble.watch.autostart
bool
Start watcher on boot if enabled + mode=watch.
scrobble.watch.provider
string
plex | emby | jellyfin.
scrobble.watch.sink
string
trakt | simkl | mdblist.
scrobble.watch.plex_simkl_ratings
bool
Forward Plex ratings to SIMKL.
scrobble.watch.plex_trakt_ratings
bool
Forward Plex ratings to Trakt.
scrobble.watch.plex_mdblist_ratings
bool
Forward Plex ratings to MDBList.
scrobble.watch.pause_debounce_seconds
int
Ignore micro-pauses just after start.
scrobble.watch.suppress_start_at
int
Kill near-end start flaps (credits).
scrobble.watch.filters.username_whitelist
array
["name", "id:123", "uuid:abcd…"]
scrobble.watch.filters.server_uuid
string
Restrict to a specific server (Plex).
Webhook mode (scrobble.webhook)
scrobble.webhook)scrobble.webhook.pause_debounce_seconds
int
Ignore micro-pauses.
scrobble.webhook.suppress_start_at
int
Suppress near-end start flaps.
scrobble.webhook.suppress_autoplay_seconds
int
Plex autoplay suppression window.
scrobble.webhook.probe_session_progress
bool
Probe Plex sessions to match item by ratingKey/sessionKey.
scrobble.webhook.plex_trakt_ratings
bool
Forward Plex ratings to Trakt in webhook mode.
scrobble.webhook.filters_plex.username_whitelist
array
Accepted Account.title values. Empty = allow all.
scrobble.webhook.filters_plex.server_uuid
string
Restrict to a specific Plex server.
Progress rules (scrobble.trakt)
scrobble.trakt)Used by Trakt, SIMKL, and MDBList sinks.
scrobble.trakt.progress_step
int
Send progress in % steps.
scrobble.trakt.stop_pause_threshold
int
STOP below this becomes PAUSE.
scrobble.trakt.force_stop_at
int
STOP at/above this is forced.
scrobble.trakt.regress_tolerance_percent
int
Clamp small backwards jumps.
Scheduling (scheduling)
scheduling)scheduling.enabled
bool
Master toggle for periodic runs.
scheduling.mode
string
hourly or daily.
scheduling.every_n_hours
int
When mode=hourly, run every N hours (1–12).
scheduling.daily_time
string
When mode=daily, run at HH:MM (24h).
UI (ui)
ui)ui.show_watchlist_preview
bool
Show Watchlist Preview on Main tab.
ui.show_playingcard
bool
Show Now Playing card on Main tab.
ui.show_AI
bool
Show ASK AI (GitBook) in UI.
ui.protocol
string
http or https.
TLS (ui.tls)
ui.tls)ui.tls.self_signed
bool
Auto-generate a self-signed certificate when missing.
ui.tls.hostname
string
Used for certificate CN/SAN.
ui.tls.valid_days
int
Certificate validity (days).
ui.tls.cert_file
string
Optional override path to a PEM cert.
ui.tls.key_file
string
Optional override path to a PEM key.
UI auth (app_auth)
app_auth)app_auth.enabled
bool
Enables login.
app_auth.username
string
Required when enabled.
Pairs (pairs[])
pairs[])Each entry is one sync connection.
id
string
Generated by UI/API.
enabled
bool
Master switch.
source
string
Provider name.
target
string
Provider name.
mode
string
one-way or two-way.
features
object
Per-feature rules.
Feature format
enable
bool
Run feature at all.
add
bool
Allow adds to target.
remove
bool
Allow removes on target.
Example:
Special: pairs[].features.ratings
pairs[].features.ratingstypes
array
movies, shows, seasons, episodes. all expands.
mode
string
only_new or from_date.
from_date
string
Used only when mode = "from_date".
Last updated