Cardwave

CCV4, a new character card format

The full CCV4 site has the specification, the prompt-assembly algorithm, a reference example, and a live playground you can edit.

Open the CCV4 site ↗

CCV4 is a draft format for AI character cards, meant to replace the SillyTavern v1, v2 and v3 formats. A card is a normal PNG. The artwork previews everywhere, and the card data travels inside the file: TOML text in private chunks, media assets as raw bytes next to it.

Text blocks

Everything a card says is a text block: a small TOML table addressed by type and id. Type names are singular and telling: name, description, personality, wardrobe, scenario, greeting, prompt, lore.

[description.esmeralda]
text = "A dancer on the square of Notre Dame, admired by all of Paris ..."

The character table

A character is a flat combination of blocks. No inheritance, no defaults, no hidden magic. Its prompt list is the full prompt template, sent to the LLM in exactly that order. Lowercase strings reference blocks, one liners can stay inline, and UPPERCASE entries are placeholders the app fills.

[character.esmeralda]
name-card = "Esmeralda"                  # label in the app's card list
name-char = "name.esmeralda"             # what {{char}} resolves to
greetings = ["greeting.coin", "greeting.knife"]
prompt = [
  "name.esmeralda",
  "description.esmeralda",
  "personality.esmeralda",
  { text = "Paris, 1482, at night." },
  "CHAT-HISTORY",
]

The picked greeting is simply the first message of the chat. There is no greeting slot.

Blocks are shared

Cards reference blocks, they do not own them. Two cards can point at the same description: edit it once and both change. One file can hold a whole cast, parallel language versions of any block, and the same person on the best day of her year or on the worst.

[character.esmeralda-festival]
prompt = [ "description.esmeralda", "wardrobe.festival", "CHAT-HISTORY" ]

[character.esmeralda-sanctuary]
prompt = [ "description.esmeralda", "wardrobe.sanctuary", "CHAT-HISTORY" ]

Lorebooks

A lore block wakes up when one of its keywords appears in the chat. A lorebook bundles lore blocks, and the LOREBOOK placeholder marks where triggered entries land in the prompt. Characters can share a lorebook the same way they share any block.

[lore.shadow]
keywords = ["priest", "shadow", "cathedral"]
text = "A priest watches the square from the cathedral, every single day."

[lorebook.old-paris]
entries = ["lore.shadow"]

Card data and user data

Every chunk filename starts with card/ for authored work or user/ for personal data like chat sessions. Sharing a card means copying the PNG and dropping the user/ chunks. No parsing, no rebuild, your chats never leave your machine.

esmeralda.png
├─ IHDR, IDAT, IEND     standard PNG, the visible artwork
├─ toMl  card/character.toml    the cards, blocks and prompts
├─ toMl  card/lore.toml         lorebooks and lore blocks
├─ asEt  card/assets/voice.ogg  raw asset bytes, referenced as asset://
└─ toMl  user/session-01.toml   your chat, dropped when you share  ✂

Every CCV4 chunk is a private PNG chunk: toMl for a TOML file, asEt for one binary asset. Each carries a filename, and the card/ or user/ prefix decides what stays when you share. A viewer that does not know CCV4 ignores every one of them and still shows the picture.

Best way to get a feel for it: edit the eight examples live in the playground, or read the full specification and algorithm.