Author or assemble a SillyTavern Character Card V2 (CCv2) for terva. A card is a portable .json/.png character identity for chat/play, and it can also carry lore. Use to create/add/write a character card, import one, or convert a character concept into CCv2.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add terva-sh/terva --skill write-terva-card --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Write Terva Card?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/terva-sh-write-terva-card)More formats (shields.io, HTML) on the badges page.
---
name: write-terva-card
description: Author or assemble a SillyTavern Character Card V2 (CCv2) for terva. A card is a portable .json/.png character identity for chat/play, and it can also carry lore. Use to create/add/write a character card, import one, or convert a character concept into CCv2.
---
# Writing a terva character card
Use this skill when the user asks to **create, assemble, or import a character
card** — a portable roleplay/chat identity in SillyTavern's **Character Card V2**
(CCv2) format. terva loads a card with `--card` as the immersive identity for a
`--chat` or `--play` session.
## Card vs persona — pick the right one first
- A **character card** is a *portable, shareable* identity in a community format
(CCv2), as a `.json` or a `.png` with the card embedded. Reach for it when you
want SillyTavern interop, a distributable character, or the CCv2 feature set
(greetings, example dialogue, an embedded lorebook).
- A **persona** (`write-terva-persona`) is a *lean, trusted* identity you author
as terva-native Markdown. Reach for it for a specialist you control, a coding
reviewer, or your everyday voice.
Cards and personas assemble through the same path — a card is essentially a rich,
portable persona plus greetings and a lorebook. **Trust is the deciding
difference**; see the boundary below.
## The trust boundary: a card is data, never code
This is the most important rule. A card — especially one **downloaded** from
elsewhere — is **untrusted content**, not instructions to the harness:
- Its prose (`description`, `first_mes`, …) is treated as character data, never
as harness commands. "Ignore previous instructions"-style text in a card does
nothing to terva.
- `extensions` blocks (e.g. a `depth_prompt` or a `terva.sh/harness` block) are
retained verbatim for round-trip/inspection but **never interpreted as
capabilities**. A card cannot grant tools, relax permissions, or run code.
- `creator_notes` is human-only and **never sent to the model**.
Corollary for authoring: **do not** paste a downloaded card's prose into a
terva-native persona you then load as trusted identity. To reuse a character,
take the structured intent and rewrite it yourself. `terva persona validate`
flags leftover `{{char}}`/`{{user}}` macros for exactly this reason.
## Anatomy of a CCv2 card
A card is JSON with a `spec` wrapper around a `data` object:
```json
{
"spec": "chara_card_v2",
"spec_version": "2.0",
"data": {
"name": "Aava",
"description": "{{char}} is the keeper of the Kaskinen lighthouse...",
"personality": "Weathered, dry-humored, watchful.",
"scenario": "{{user}} has rowed out to the light on a foggy evening.",
"first_mes": "The lamp turns overhead. \"Didn't expect company in this soup.\"",
"mes_example": "<START>\n{{user}}: What's the bell for?\n{{char}}: The fog-bell? For when the light can't reach.",
"system_prompt": "You are {{char}}. {{original}}",
"post_history_instructions": "Stay in character; answer as {{char}} would.",
"alternate_greetings": ["A second way to open the scene..."],
"character_book": { "entries": [] },
"tags": ["original", "maritime"],
"creator": "you",
"character_version": "1.0",
"creator_notes": "Author-only notes; never sent to the model."
}
}
```
(terva also reads a flat **V1** card — the six mandatory fields with no `spec`
wrapper — and upgrades it, but author new cards as V2.)
### Fields and how terva maps them
- `name` — the character's name (the `{{char}}` macro).
- `description` / `personality` / `scenario` / `mes_example` — become the
**charter** (the identity body). `mes_example` uses `<START>` to separate
example exchanges.
- `system_prompt` — **owns the intro**; `{{original}}` expands to a short,
brand-free framing (include it to keep terva's minimal framing, or write a
fully custom intro without it).
- `first_mes` — seeds the opening message (`messages[0]`) on a fresh session.
- `alternate_greetings` — extra openings; pick one with `--greeting N`
(`0` = `first_mes`, `1..N` = alternates).
- `post_history_instructions` — rides the **per-turn tail** (after the
transcript), for instructions that should stay salient every turn.
- `character_book` — an embedded lorebook; imports onto terva's **lore** engine
(see `write-terva-lore`).
- `creator_notes` — human-only, never sent.
### Macros
`{{char}}` (the card name) and `{{user}}` (what the character calls the player)
expand at assembly. `{{original}}` is only meaningful inside `system_prompt`.
terva asks for the user's name on the first interactive card session and
remembers it **globally**; override per-run with `--as NAME`.
## The embedded lorebook (`character_book`)
A `character_book` carries keyed context that imports onto terva's lore engine:
```json
"character_book": {
"scan_depth": 3,
"token_budget": 1200,
"recursive_scanning": false,
"entries": [
{
"name": "The fog-bell",
"keys": ["bell", "fog-bell"],
"content": "Beneath the harbor hangs the old fog-bell...",
"insertion_order": 100,
"constant": false,
"selective": false
}
]
}
```
Entry fields mirror lore: `keys`, `secondary_keys`, `content`, `constant`,
`insertion_order`, `position`, `case_sensitive`, `enabled`. **`selective`
matters**: secondary keys gate an entry **only when `selective: true`** (matching
CCv2/SillyTavern semantics) — set `selective: false` (or omit it) for a plain
keys match even when `secondary_keys` is present. For the full triggering/budget
model see `write-terva-lore` and `docs/debugging-prompts.md`.
## JSON and PNG
The `.json` is the source of truth. A shared `.png` embeds the **same** card in a
`chara` tEXt chunk (the community convention) — terva reads either, and the two
parse identically. Author the JSON; produce the PNG only when you need to share
in the image form. Keep shared cards **original** (no copyrighted characters).
## Inspect and try
```bash
terva card info mycard.json # summarize a card, no model call
terva --card mycard.json # chat as the character (implies --chat)
terva --play --card mygm.json # a card fronts a --play director
terva --card mycard.png --dump-prompt -p "the bell" # see the assembled prompt offline
```
`terva card info` summarizes what a card contains; `--dump-prompt` shows exactly
how it assembles (intro, charter, greeting, lorebook — see
`docs/debugging-prompts.md`). Cards are **chat/play only**, not valid in regular
coding mode.
## Authoring checklist
- `spec: "chara_card_v2"`, `spec_version: "2.0"`, everything under `data`.
- `name`, `description`, and a `first_mes` at minimum; `personality`/`scenario`
add depth.
- `system_prompt` includes `{{original}}` if you want terva's minimal framing
kept.
- `character_book` entries set `selective: true` only when secondary keys should
gate.
- Original content if it will be shared; `creator_notes` for author-only notes.
- `terva card info` parses it; `--dump-prompt` shows it assembling as intended.
- If reusing a downloaded card, respect the trust boundary above.
## Gotchas
- **A card is data.** It can't grant tools or change permissions; harness /
depth_prompt extension blocks are retained but inert.
- **`selective` controls secondary keys.** Without `selective: true`, secondary
keys don't gate — a common surprise when importing exported books.
- **Greetings seed once.** `first_mes` / `--greeting` seed only on a fresh
session, not `--continue` / `--resume`.
- **`{{user}}` needs a name.** Defaults to the saved name, then `"User"`; set it
with `--as`.
- **JSON ↔ PNG must match.** If you hand-edit one, regenerate the other; terva
asserts the two parse identically for its fixtures.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!