Chub.ai, RisuAI, and SillyTavern sync: why character cards drift across platforms.
The same Tavern card, dropped into Chub.ai, RisuAI, and SillyTavern, will not behave identically. Greetings reshuffle, lorebook triggers go quiet, custom prompts vanish. Here’s why — field by field — and what to do about it.
The same card, three lives
Take a card you wrote yesterday. Export it from SillyTavern as a V2 PNG. Upload it to Chub.ai. Re-download the file Chub serves you, then load it into RisuAI. In all three places the card looks the same on the surface — same portrait, same name, same description — but the live behaviour drifts in ways that take days to diagnose.
The opening message might be your third alternate_greeting instead of the canonical first_mes. A lorebook entry that fires reliably in SillyTavern silently fails to trigger in RisuAI. A custom extensions.depth_prompt you set in Tavern is simply not there on the third host. None of these are bugs in the usual sense; they are implementation drift between three projects that share a format and not much else.
Three platforms, three philosophies
To predict where a field will and won’t survive, it helps to remember what each host actually is.
- SillyTavern is a self-hosted client. It treats the card spec as its native language: V1, V2, and large parts of V3 are read directly by the chat loop, and most extensions add their own keys into extensions rather than fight the schema. If you want to know what “canonical” behaviour looks like for a Tavern card, SillyTavern is broadly the reference.
- Chub.ai is a community host. Its job is storage and presentation, not inference: it parses the card to power its gallery, versioning, and search UI, then serves the PNG back to whatever client the user is running. Chub adds its own extension namespaces (the chub-prefixed keys you’ll see under extensions) and is generally conservative about modifying card payloads on upload, but its gallery view is opinionated about which fields it surfaces.
- RisuAI is a cross-platform client — web, desktop, mobile — that has historically treated the Tavern format as a base layer and built its own module system on top. Lorebooks, triggers, and module bindings have Risu-specific affordances that round-trip through extensions rather than the canonical V2 keys. The card still loads in other hosts; the Risu-specific behaviour does not.
None of these designs is wrong. They reflect three different bets about where the work belongs: in the client, in the host, or in a portable runtime. The drift creators see is the shadow those bets cast on a shared file format.
Where the fields actually drift
The drift is not random. It clusters around a handful of fields that the spec defines loosely or that each platform decided to extend. Treat the table below as a working field-guide, not a contract — behaviour has changed release to release and will keep changing.
| Field | SillyTavern | Chub.ai | RisuAI |
|---|---|---|---|
| character_book | Native; full V2 semantics | Preserved; surfaced via chub_lorebook extension | Read, then often re-projected into Risu lore module |
| alternate_greetings | Order preserved; user-selectable | Order preserved; gallery may reorder for display | Order broadly preserved; UI picker varies by build |
| extensions.* | Mostly kept; consumed by matching extension | Round-trips, including chub_ keys | Risu keys are honoured; others may be dropped on re-export |
| mes_example | Parsed by ‘START’ markers, fed as few-shot | Stored verbatim; not interpreted by host | Interpreted; whitespace and markers can be normalised |
| system_prompt | Honoured; may be merged with global preset | Stored verbatim | Honoured; may be re-wrapped by Risu module |
| assets (V3) | Growing support; resolution rules still settling | Stored; only some asset kinds are surfaced | Partial; expression assets handled separately |
| creator_notes_multilingual (V3) | Read where present | Sometimes shown alongside creator_notes | Not consistently surfaced |
Two patterns repeat. First, extensions is the honest namespace: anything any host wants to add lives there, and round-trips depend entirely on whether the next host knows the key. Second, interpreted fields drift more than stored fields: a host that simply archives the JSON (Chub) will preserve more than a host that parses and re-renders it (SillyTavern, RisuAI).
PNG tEXt: the silent stage
Even before any field-level interpretation, the PNG container itself is a source of drift. Tavern cards live inside a tEXt chunk (or, for larger payloads, zTXt), keyed under chara and Base64-encoded. The three hosts differ in how aggressively they touch that chunk:
- SillyTavern reads the chunk on import and writes a fresh one on export — lossless for fields it knows, but extension data it doesn’t recognise has been reported to occasionally be re-ordered or normalised in transit.
- Chub.ai broadly preserves the original chunk on upload but may re-encode the PNG itself when generating thumbnails or optimised variants; the canonical card download path is the safest fetch.
- RisuAI’s import path normalises the payload through its own model before re-emitting, which is why a card that round-trips through Risu often comes out structurally identical and byte-different.
If your card is losing fields on upload but you can’t see where, the answer is usually at this layer. We unpack the encoding in detail in PNG tEXt chunk metadata & Tavern cards.
How to keep your library in sync
You will not get every host to agree. You can get them close enough that your library survives the trip. Three working habits help most:
- Author against the minimum common subset. Treat V2’s canonical keys — name, description, personality, scenario, first_mes, alternate_greetings, mes_example, system_prompt, character_book — as load-bearing, and treat everything under extensions as best-effort. If a behaviour matters, it should be expressible in the canonical set.
- Round-trip test every release. Export from your source of truth, import into each target host, re-export, then diff the JSON. The diff is the drift. Most card maintainers do this manually once and never again; the cards that survive are the ones whose owners automated it.
- Keep an auto-diff report. Drift compounds. A field that lasted three round-trips yesterday may not survive a host update next week. Tracking the diff as data — not as a vibe — is the only way to catch silent regressions before your readers do.
One source, three dialects
tavernai.cards is being built as the codex for exactly this problem: one canonical card, three live dialects, and a diff you can read.
- Bidirectional sync — push the same card to Chub.ai, RisuAI, and SillyTavern, and pull host-side edits back into your source of truth.
- Auto-diff reports — after every round-trip, see which fields were preserved, normalised, or dropped, per host.
- Format-aware conversion — V1, V2, V3, plus the host dialects under extensions, converted with a visible mapping rather than a black-box rewrite.
- Lint before publish — catches host-incompatible fields, stale asset references, and silent encoding bugs before your card ships.
We’re opening the workbench in waves. If you maintain a card library that has to live on Chub, Risu, and Tavern at once, put your name on the scroll — cross-platform sync is the first feature out the door.