Skip to content

Trackers & sync

Local history needs no account — SQLite is the source of truth and sync is a projection of it. Syncing to AniList, MyAnimeList, Simkl or Trakt is opt-in, and each service needs an app you register — there is no public client to borrow, and shipping credentials in an open-source binary would make them public.

[trackers]
enabled = ["anilist", "mal", "simkl", "trakt"]
token_storage = "keychain" # or "file" — see below
[trackers.anilist]
client_id = ""
client_secret = "" # required: AniList has no PKCE and no public client
[trackers.mal]
client_id = "" # that is all: MAL is a public client, PKCE covers it
[trackers.simkl]
client_id = ""
[trackers.trakt]
client_id = ""
client_secret = "" # Trakt wants one on the token exchange
AniList MyAnimeList Simkl Trakt
Register at anilist.co myanimelist.net — App Type other simkl.com trakt.tv
Sign-in flow browser redirect browser redirect device code device code
Redirect URL http://127.0.0.1:45617/callback http://127.0.0.1:45617/callback none needed none needed
Needs a secret yes no no yes
Token life ~1 year 30 days, refreshed automatically long-lived refreshed automatically

Then anistream --login, or anistream --login --tracker mal. Simkl and Trakt use the OAuth device flow, so --login --tracker simkl prints a code and a URL to enter it at. Check any of them with anistream --sync.

Updates go through a durable outbox: watch offline for a week and everything is pushed, in order, when a connection returns. The merge logic is pure and heavily tested, and when local and remote genuinely disagree the conflict gets its own screen instead of a silent overwrite.

An episode is pushed when it crosses commit_threshold, 85% of runtime by default. It is set high so that opening an episode to check the subtitles does not mark it seen.

Use keychain for an installed build. Use file, which is 0600, if you are running from cargo: macOS keys keychain access on the binary, and every rebuild produces a new one, so “Always Allow” never sticks and every run prompts you. anistream --token-to-file moves an existing token across, and ANISTREAM_TOKEN_STORAGE=file overrides for a single run.