categories
Inspect and edit a list’s card categories: a card’s role in that one list, such as Ramp, Removal, or Board Wipes. It is what Archidekt calls a category and Moxfield a tag. Categories are not Ritual’s tags or labels; see Labels, tags, and categories for how the three differ.
A category belongs to a card name, not to a card line. One assignment covers every line of that name in the list, whatever its printing, section, or quantity. It is never written on the line, and it never follows a move. A card’s categories are ordered, and the first one is its primary category, which is what the site groups by. Categories are stored in a <list>.categories.json file beside the list; see Categories in the list format.
ritual categories list [listName]ritual categories rename [listName] <from> <to>ritual categories order [listName] <value>ritual categories remove [listName] <name>listName names a list of any type unless a type flag narrows it; see List Names. Omit it to pick a list interactively.
Subcommands
Section titled “Subcommands”Print the list’s category vocabulary in display order, each with how many cards carry it, followed by one line per categorized card.
| Argument | Description |
|---|---|
[listName] |
The list to read (prompted when omitted) |
Read-only: it takes no --dry-run, never writes, and never prunes. It does report stale entries (see Stale names).
rename
Section titled “rename”Rename a category throughout the list: in the vocabulary and on every card carrying it, with each card’s own order preserved.
| Argument | Description |
|---|---|
[listName] |
The list to edit |
<from> |
The category to rename |
<to> |
The new name for the category |
A <from> the list does not use (neither in order nor on any card, compared case-insensitively) is a not_found (exit 3).
Set the display order of the list’s vocabulary.
| Argument | Description |
|---|---|
[listName] |
The list to edit |
<value> |
The categories in their new order, comma-separated |
Names the list does not use yet are accepted: order declares a vocabulary. An empty value is a usage error (exit 2); use remove to drop a name.
remove
Section titled “remove”Remove a category from the list’s vocabulary and from every card that uses it. A card left with no categories loses its entry in the categories file.
| Argument | Description |
|---|---|
[listName] |
The list to edit |
<name> |
The category to remove |
Options
Section titled “Options”| Option | Description | Default |
|---|---|---|
--deck |
Resolve the name as a deck | |
--collection |
Resolve the name as a collection | |
--wanted |
Resolve the name as a wanted list | |
-n, --dry-run |
Report what would change without writing anything (not on list) |
false |
--output <format> |
Output format: text, json, or ndjson |
text |
--quiet |
Suppress non-essential output | false |
Examples
Section titled “Examples”ritual categories list --deck "Winota Stax"ritual categories list --deck "Winota Stax" --output jsonritual categories rename --deck "Winota Stax" Draw "Card Draw"ritual categories order --deck "Winota Stax" "Ramp, Card Draw, Removal"ritual categories remove --collection main Ramp --dry-runBehavior
Section titled “Behavior”What this command writes
Section titled “What this command writes”Every mutating subcommand writes the list’s <list>.categories.json and <list>.categories.json.sha256 when the edit changes them, then appends one entry to the list’s .changes.md changelog. Those paths come back in writtenFiles. The list .md file is never rewritten. This command writes no card lines and reads no &N, so it does not trigger the card-ID backfill.
An edit that changes nothing (rename Draw Draw, or an order equal to the one on disk) reports wouldWrite: false, writes no file and no changelog entry, and returns an empty writtenFiles. A real run and its --dry-run preview always agree about whether the command touches disk.
A categories file left with no vocabulary and no cards is deleted rather than written as {}, and its .sha256 goes with it.
The .sha256 is refreshed only when it matched the categories file before the write. A hand-edited file therefore keeps its stale hash (its .sha256 is not in writtenFiles), so detect-changes still records the hand edit.
Changelog entries
Section titled “Changelog entries”The changelog records:
Renamed category "Draw" to "Card Draw"Set category order to Ramp, Draw, Removal(orClear category order)Set categories of "Sol Ring" to Ramp, Artifacts/Cleared categories of "Sol Ring"
remove has no event of its own. It is recorded as a set-category-order without the name plus one set-categories per affected card.
Stale names
Section titled “Stale names”An entry naming a card the list no longer holds is kept. categories list reports it on stderr:
Categories are recorded for cards this list no longer holds: Sol Ring. They are kept until the list is saved or cleaned up.--quiet does not hide it, because the next save will drop that data. The check needs a complete read of the list. When the file holds a body line the card-line parser cannot read, categories list reports that instead and names no entry stale, since a card it could not see is not a card that is gone.
Nothing in this command prunes. Pruning happens on the list’s own save (an editor session, an admin save), on a cross-list move that rewrites the list from a clean parse, and in ritual cleanup.
Dry runs
Section titled “Dry runs”-n / --dry-run resolves the list, validates the arguments, computes the edit, reports it, and stops. Nothing is written: no categories file, no .sha256, no changelog. wouldWrite says whether a real run would touch the categories file. It is false for a no-op edit, in which case a real run writes nothing at all, changelog included. Text output is prefixed [dry-run]; JSON output carries "dryRun": true alongside the usual fields.
JSON payloads
Section titled “JSON payloads”categories list:
{ "type": "deck", "list": "Winota Stax", "order": ["Ramp", "Draw", "Removal"], "cards": [{ "name": "Sol Ring", "categories": ["Ramp", "Artifacts"] }], "warnings": []}categories rename / order / remove:
{ "type": "deck", "list": "Winota Stax", "action": "rename", "order": ["Ramp", "Card Draw", "Removal"], "cardsChanged": ["Rhystic Study"], "wouldWrite": true, "writtenFiles": [ "/decks/Winota Stax.categories.json", "/decks/Winota Stax.categories.json.sha256", "/decks/Winota Stax.changes.md" ]}cardsChanged lists the cards whose recorded categories differ after the edit, so a rename reports every card that carried the old name.
On the site
Section titled “On the site”The built site reads the same categories file. On any single list view, Group: Category puts each card under its primary category, Group: Categories shows it under every category it holds (non-primary appearances dimmed and badged), Sort: Category orders by primary, and a Categories filter row narrows the list. All of this is shareable in the view URL. On a deck the two groupings nest inside every board, so headings read Main › Ramp and Sideboard › Draw. See Grouping, sorting and filtering by category.
Both the admin and the public in-browser editors edit categories directly: an Edit Categories… row in a card’s ⋯ menu, and a Categories (Manage categories) dialog for renaming, reordering, and removing. See Card Categories in the editors.
Related
Section titled “Related”set-card --categories/--no-categories— set one card’s categories.ritual edit— the🗂 Edit Categoriesaction and the list menu’sRename Category…/Reorder Categories…rows.defaultCategories— the global vocabulary that seeds a list’s resolved order.ritual export— thecategoriesandprimaryCategorycolumns.ritual import— thecategoriesCSV field, and how a board value in that cell routes to the section.
Exit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
0 |
Success |
1 |
Runtime error (the <list>.categories.json file could not be read — the command refuses rather than overwriting it) |
2 |
Usage error (a malformed category name, an empty order value, an ambiguous list name, prompts unavailable for the interactive list picker) |
3 |
Not found (missing list file, or a category the list does not use given to rename/remove) |
Ritual is unofficial Fan Content permitted under the Fan Content Policy. Not approved or endorsed by Wizards of the Coast. Portions of the materials used are property of Wizards of the Coast. ©Wizards of the Coast LLC.
Card data, images and symbols come from Scryfall, which is not affiliated with this project. Ritual is free software under the AGPL-3.0. License and attribution.