Karasu 1.0.0 is the first tagged release: a desktop and Android tracker built
exclusively for AniList, in the spirit of Taiga. It watches what you play or
read — the system's media sessions on Windows and Linux, player and browser
windows on Windows, and a Jellyfin server anywhere — parses the release name,
matches it against your list and scrobbles the progress, asking first when it
is not sure. Around that sit the list itself with offline editing and a sync
queue, a local library scanner that knows which episode you have on disk,
statistics and a year-in-review poster, AniList's forum and activity feed,
and on Android four home-screen widgets and background notifications that
run with the app closed.
This release also opens the Stable update channel: new installs follow it
by default, and the per-commit build lives on as Nightly for anyone who
wants to stay on the edge. Everything below is what changed on the way here,
grouped by what it means for you rather than by commit; the full record is
the commit log.
Fixed
- Account-free mode no longer wipes an entry when you edit one field of it.
Every quick control —+1, the status dropdown, the score select, the bulk
bar, the detail editor — sends only the field you changed, and the local list
was filling in the rest with defaults: a+1reset the status to Planning and
zeroed the score, repeat count, volume count, notes and tags. Absent now means
"leave it alone" for every field, as it always has for AniList. - The sign-in merge no longer deletes local rows it never pushed. A local
entry that agreed with AniList on status, progress and score was cleared
without being sent — so notes, tags, rewatch count, volume count, privacy and
both dates that existed only locally were lost, and the merge reported
success. It now pushes whatever the AniList row is missing before clearing,
and never overwrites a value AniList already has. - A library scan can no longer wipe the index because the drive was offline.
An unreachable folder produced zero files, and zero files were written down as
the truth across all three library tables — reported as a successful scan, and
surviving a restart. The folder is checked before anything is replaced, and
finding nothing where something was indexed before keeps the index and says so. - Queued offline edits can no longer land on a different account. Signing out
left them in the database with no record of who made them, so the next account
to sign in drained them onto its own list. Each queued edit is now stamped with
the account that made it and is only ever replayed for that account — so
signing back in still syncs what you were waiting on, and nobody else's client
ever sees it. - The JSON backup carries every list field again. It dropped advanced
scores, custom-list membership and hidden-from-status-lists — the three that
AniList writes wholesale with no undo, and so the three a backup is most
needed for. - Undo is no longer offered for a save it cannot reverse. It covered six
fields and silently skipped the rest; it now reverses dates, privacy and
hidden-from-status-lists too, and declines outright when a save touched custom
lists or advanced scores. - The score rescale reads the list as it is now, not as it was when you
opened Settings — it could claim there was no list at all, and otherwise
planned real score writes from a stale snapshot. - A daily backup that was truncated (a full disk, a process killed mid-write) is
checked and rewritten instead of occupying a retained slot unusably. - Clicking the tag box no longer deletes a tag. A
<label>around the tag
editor made the first chip's remove button its target, so clicking the caption,
the box's padding, or another chip's text removed the first tag silently. - The list view's keyboard shortcuts no longer fire against the wrong entry.
After one arrow press, Enter/Space/e/c/s acted on the highlighted row whatever
else had focus — Space on a focused button wrote a+1to your real list for a
title you weren't looking at, and cancelled the button you actually pressed. - Ctrl+K no longer opens the command palette behind an open editor and discards
what you were typing; the season picker no longer lets/and Ctrl+1/2/3 fire
underneath it. - The Stable update channel no longer claims you are up to date. No stable
release has ever been published, so its manifest 404s — and a manual check
answered that with a green tick. It now says the channel has no release yet. - An update check that fails no longer burns the once-a-day throttle, and the
request has a timeout like every other one in the app. - Switching update channel clears the download held for the old one, instead of
offering to install a build the new channel does not have. - On Linux, an update is only offered to a running AppImage. A self-built binary
was offered one whose install would have overwritten the user's own build. - Settings that failed to save no longer look saved. The content filter and
every detection toggle were fire-and-forget: the switch moved, the write was
dropped, and the choice quietly did not survive a restart. They put the
control back and say what went wrong. - The bell no longer answers a failed read with "You're all caught up."
- The media-session diagnostic distinguishes "no player is reporting anything"
from "the system service could not be reached" — on Linux the second means
detection is down, and it used to send you to debug your player. - Turning airing notifications off no longer arms them: re-enabling months later
used to replay every episode that had aired in between. - A title hidden by the content filter can no longer surface in an on-hold
reminder. - "No such user" is no longer what a dropped connection looks like. Profiles,
threads and character/staff pages rendered every failure as "this does not
exist" — a definite claim about someone else's account, made because the
network was down. A real not-found still reads as one; everything else says
what failed and offers a retry. - Relative timestamps ("3m", "5h", "2d") are translated. They were hardcoded
English sitting directly beside a translated "now"; German now reads 3 Min. /
3 h / 3 T. - The franchise graph's status legend uses the right vocabulary — it said
"Watching" over a manga graph whose own cards said "Reading". - Jellyfin's sign-in errors are translated. "Wrong username or password" was
composed in Rust and printed verbatim, so a German UI showed it in English. - Five things that were reading or writing the wrong cache entry. The
sidebar's Anime and Manga counts were blank for the whole of account-free mode
and the franchise rail could not see a local entry (both keyed onundefined
where every other screen keys on0); the favourite heart on a character,
staff or studio page patched a media entry keyed by a character id and never
moved; liking a thread updated nothing on screen; and the thread author's
avatar was always missing, because the query asked for a size the page does
not read. - Fetching media in bulk no longer fires every batch at once into a shared
~30/min budget. - Portable mode's "replace the database that's already there" works. It called
a copy that refuses an existing file, so it could only ever print a raw SQLite
error — the only route to a portable copy was deleting the old file by hand. - Two list screens opening at once no longer each send the whole offline queue,
and a queued edit AniList refuses outright now says so instead of vanishing. - The trailer card and the streaming-episode tiles no longer render as broken
images. Their thumbnails live on hosts the content-security policy does not
allow, and widening it to cover them would hand those hosts your IP and what
you are looking at — so the cards are drawn instead, and still open the same
link. - The command palette's keyboard cursor follows the list. Twelve navigation
items do not fit its box, so the last one was unreachable: arrowing down moved
an invisible highlight and Enter opened something never on screen. It also
announces the highlighted row to a screen reader now. - On Linux, mpv's IPC socket defaults to your own runtime directory rather than
a/tmppath shared with every other account on the machine. - The detail page's play button appears as soon as a library scan finds the next
episode, instead of waiting for something else to redraw the page. - An episode that has just aired no longer shows an empty pair of brackets where
its countdown was. - The franchise graph says when it stopped expanding, instead of only when it ran
out of room for nodes. - The match picker shows "TV Short" rather than
TV_SHORT. - The context menu takes focus when it opens and announces itself as a menu, so
it can be used from the keyboard at all. - Grid-card buttons become visible when tabbed to, instead of being focusable
while fully transparent. - The review composer's body label no longer points at a field that isn't there
in preview mode. - An offline edit is no longer deleted when AniList answers with something
recoverable — an expired token, a rate limit, a server fault. Only a payload
AniList rejects on its own terms is dropped, and when one is, it says so. - Repeated offline edits to the same entry collapse instead of replaying as one
request each into a ~30/min budget. - The sign-in merge refuses to run unless it has read both live AniList lists
first. A failed read used to look like an empty account, at which point the
local list was pushed over real progress. - A merged entry whose write only reached the offline queue keeps its local row
until the write lands. - Enabling portable mode with a database already beside the executable asks
which copy to keep instead of silently adopting the older one. Disabling says
which database it is going back to. - A panic in a background loop can no longer poison a lock and take detection or
the alert passes out for the rest of the session. - A failed request stops reading as an empty result: Wrapped, the recommendation
sections and activity replies say the request failed rather than showing an
empty year, a missing section, or "no replies yet". - A bulk edit that stops partway reports how much it wrote, and the list
refetches instead of rolling back entries AniList has already changed. - A scrobble can only ever move progress forward; "Update now" from a blocked
session can no longer write episode 1 over episode 27. - A season Karasu cannot place is refused with the sequels offered, rather than
guessed at against season one. - One slow Jellyfin response no longer flips the now-playing card to another
source. - A paused mpv no longer outranks the thing actually playing.
- Scores got their colour back in the list, and a bio's centred lines render as
lines. - Signing out of one account and into another no longer carries the first
account's data across. Queued offline edits, bell rows and the alert dedupe
keys belong to the account that made them; the queue could drain one
account's unsent edits onto another's list. - A scrobble can no longer overwrite an edit you just made. Every write
path keeps the cached list in step, which is what the scrobbler reads to
decide whether progress moved backwards. - A queued edit is no longer reported as a saved one. An edit that can only
be sent later says so, instead of showing a green receipt and a progress bar
that had not moved on AniList. - A deleted entry stays deleted. It used to remain a scrobble candidate,
and playing that title recreated the row. - A paused player stops the clock. Detection reads the audio session, so an
episode left paused mid-watch is no longer eventually written as watched.
Windows only — the other detection sources already reported their own play
state. - A database that will not open falls back to the newest daily backup
rather than blocking the app whose only recovery path runs through it. - A declined update stops re-downloading itself. It fetched the whole
installer again every 24 hours and announced the same release each time. A
clock pushed backwards no longer disables update checks either. - The local library only renders the rows on screen, so a large collection
opens without the pause. - The background notification check reports it when Android refuses to register the job, instead of showing a schedule that does not exist.
- A title's page now shows what your list already knows when you are offline, with a working +1, instead of a raw network error.
- Switching AniList accounts no longer carries the previous account's notification cursor along.
- AniList activity permalinks open in Karasu on Android.
- The Android background notification check now actually registers with the system; before, Android had been refusing it silently since the feature existed.
- An anilist.co link that launches Karasu on Android now opens the page it names instead of the dashboard.
- The local library's scrollbar no longer creeps while scrolling into rows it has not drawn yet.
- On Android, "Save report", the poster export and the calendar export write a file instead of leaving an empty one behind.
- Switching update channel no longer leaves the other channel's "ready to install" notice in the bell.
- Sharing a link to Karasu on Android works from apps that share styled text.
Added
- Arrow keys move a cursor across the Seasonal and Search grids, and Enter opens
the highlighted title — the same movement the list view has had. - A clear button in the search and filter boxes — Search, the list filter, the
forum search, the unplaced-titles filter and the filter dropdowns. - The sidebar collapses to icons, and remembers it. The button sits below the
navigation; collapsed, every icon keeps its name as a tooltip, the group
headings become dividers, and an unsent-changes dot stays on your avatar. - Karasu's own bell rows open the title they are about, the way the AniList rows
beside them already did. Rows from before this update carry no title to open
and behave as they always have. - Detection corrections: tell Karasu which entry a detected title really is, and
which episode number that season starts at. - Position-aware scrobbling — Jellyfin's playback position and a direct mpv IPC
probe, so progress is written where you actually are in the episode. - Reviews on the detail page, with a composer that knows AniList's rules.
- AniList's own notifications in the bell, merged with Karasu's into one
stream (the grouping is presentation only —lib/notifGroups). - Export: MAL XML per medium and Karasu's own JSON; MAL import into the local
list; a daily local database backup. - A global hotkey, a real tray menu, and a working button on the scrobble
confirm toast. - Statistics: Ratings, Years and themed tabs, all charts drawn here.
- The whole app reads, edits and charts in the account's own score format.
- Search filters, sorting and paging, which makes it the browse page.
- Custom list membership per entry; entry dates, privacy and repeat count.
- A one-pass score rescale that prints the request count before it runs.
- The airing week exports to any calendar app.
- Profiles gained a Lists tab with an affinity score.
Changed
- An aired episode no longer arrives twice. When your AniList account raises its
own airing notification, Karasu still shows the desktop notification — the one
thing the website cannot do while Karasu sits in the tray — and leaves the bell
row to the AniList tab, where it opens the entry. Turn AniList's off and Karasu
writes that row itself, as before. Both settings say so, on both screens. - The Social tab is now called Activities.
- New installs follow the Stable update channel; the per-commit build is the Nightly channel, and every install that was on it stays there.
Windows -- the .exe installer. It is unsigned, so SmartScreen may
warn on first run. Verify the download against SHA256SUMS.txt if you want to
confirm it wasn't tampered with in transit.
Linux -- the .AppImage, x86_64. chmod +x it and run it; it works on
Ubuntu 22.04+, Debian 12+ and Arch. It needs webkit2gtk-4.1 present on the
system (libwebkit2gtk-4.1-0 on Ubuntu/Debian, webkit2gtk-4.1 on Arch) --
that one is not bundled. For a tray icon you also need a StatusNotifier host; on
GNOME that means the AppIndicator extension. Without one Karasu still runs and
closing the window quits instead of hiding.
Android -- the .apk, sideloaded. Take the _arm64 one; _universal
is the fallback for anything that refuses it (old 32-bit phones, emulators).
Both are signed with the project key, so installing over a previous release
keeps your data. The built-in updater covers desktop only -- on Android a new
version is installed the same way, over the top.
Karasu's built-in updater (About page, or automatic daily checks) verifies
updates against its own signing key regardless -- see latest.json for the
update manifest.
VirusTotal scan: src-tauri\target\release\bundle\nsis\Karasu_1.0.0.563_x64-setup.exe=https://www.virustotal.com/gui/file-analysis/NDM2NDEyZmIzYmNlMTBlYTQ4M2U4Njg2YzdiMzJjNmE6MTc4ODYzODQ1MQ==/detection