export
Export any set of cards from your decks, collections, and wanted lists as CSV, JSON, plain text, or Markdown. Run it bare in a terminal for an interactive wizard, or drive everything with flags for scripting. The global --no-input flag guarantees the wizard never opens. The same engine backs the MCP export_cards tool.
# Interactive wizardritual export
# Everything, as JSON on stdoutritual export --format json > all-cards.json
# One deck to a CSV file with custom columnsritual export deck:burn --out burn.csv --columns name,quantity,listName
# One flat decklist of everything you ownritual export --collection --format text
# Cherry-pick cards across lists, filteredritual export --card "sol ring" --card "lightning bolt" --finish foil
# A CSV ready for Archidekt's collection importerritual export --collection --preset archidekt --out archidekt.csvArguments
Section titled “Arguments”| Argument | Description | Required |
|---|---|---|
[lists...] |
Lists to export. See List Names; a deck: / collection: / wanted: prefix selects the type |
No |
With no lists and no --card picks, a headless run exports every list, so ritual export --format json dumps everything. A completely bare ritual export opens the interactive wizard instead. Where prompting is unavailable, it fails with a usage error asking for --all or another flag.
Options
Section titled “Options”Sources
Section titled “Sources”| Option | Description |
|---|---|
--deck |
Only decks (also disambiguates list names) |
--collection |
Only collections (also disambiguates list names) |
--wanted |
Only wanted lists (also disambiguates list names) |
--all |
Export every list in scope (the default when no lists or --card are given) |
--card <terms> |
Add every entry (across all lists in scope) whose name matches all terms. Repeatable; deduplicated against selected lists |
Filters
Section titled “Filters”Filters apply to the assembled set, list entries and card picks alike.
| Option | Description |
|---|---|
--name <terms> |
Only cards whose name contains every whitespace-separated term |
--set <code> |
Only cards from this set code (case-insensitive) |
--finish <finish> |
Only nonfoil, foil, or etched. nonfoil also matches cards with no explicit finish |
--condition <list> |
Only cards with one of these conditions, comma-separated: NM, LP, MP, HP, DMG, none |
--labels <list> |
Only cards whose effective labels include one of these, comma-separated: sale, trade, keep, proxy, none |
--tags <list> |
Only cards carrying one of these tags, comma-separated |
Notes:
--condition: an explicit grade matches only cards with it marked on their line;nonematches cards with no condition marked (e.g.--condition NM,none). Wanted entries never carry a condition, so they never match.--labels: a card’s effective labels are the list’s front-matter default adjusted by its own[labels]override (see Card labels).nonematches unlabeled cards. A filter may combine exclusive labels freely; it selects, it does not declare. A deck line carriesproxyalone, so--labels proxyselects a deck’s proxies. Wanted entries carry no labels, so they never match, not evennone.--tags: exact and case-sensitive (Signed,Card Draw). Spaces are part of a tag, so quote the value. Matches on every list type, wanted lists included; a card with no tags never matches. There is nononevalue;noneis an ordinary tag.
Output
Section titled “Output”| Option | Description |
|---|---|
--format <format> |
csv (default), json, text, or md |
--columns <list> |
Comma-separated properties in output order (csv/json only) |
--dialect <name> |
Output vocabulary: ritual (default), archidekt, arena, or moxfield. See Dialects |
--no-header |
Omit the CSV header row |
--quote-all |
Quote every CSV cell instead of only cells that need it |
--out <file> |
Write to this file instead of stdout |
--preset <name> |
Export with a saved or built-in preset (explicit flags override its values) |
--save-preset <name> |
Save the resolved format/columns/CSV options as a named preset |
--quiet |
Suppress progress and status messages (never the payload or the warnings) |
The rendered export goes to stdout (or --out) raw, with no envelope. export has no scripting --output flag because its stdout payload is the export.
The same engine backs the admin API’s POST /api/export. That route returns the export inline by default, or, with write: true, writes it to a server-named file under a gitignored exports/ directory in the base dir and returns the relative path. Files written that way are byte-identical to --out output.
Formats
Section titled “Formats”csv and json
Section titled “csv and json”Column-shaped output driven by --columns, --no-header, and --quote-all. See Properties.
text — a plain-text decklist
Section titled “text — a plain-text decklist”Identical printings (same name, printing, finish, condition, and language) are aggregated with summed quantities. A multi-list export merges into one list, so list boundaries disappear. Lines keep first-seen file order, and the printing is omitted for cards without one. The line form follows the dialect.
In the default ritual dialect (and in archidekt, which has no plain-text form of its own): {quantity} {Name} ({SET}:{Collector Number}) lines, with no headers or sections.
2 Lightning Bolt (LEA:161)1 Fireblast (VIS:78)1 Price of ProgressIn the arena and moxfield dialects: bare board markers over {quantity} {Name} ({SET}) {Collector Number} lines, the form those sites import. Sections map to boards (Commander, Companion, Sideboard, everything else Deck), except maybeboard and token sections, which are left out entirely. Aggregation is per board. moxfield puts its *F* / *E* finish marker between the set and the collector number, following Moxfield’s bulk-edit grammar ({quantity} {Name} ({SET}) *F* {Collector Number}).
moxfield also writes each card’s categories as Moxfield tags at the end of the line, primary first: 1 Sol Ring (C21) 263 #Ramp #Artifacts. Moxfield’s grammar documents only single-word tags, so a category with a space in it (Board Wipes), one starting with ! (Moxfield’s global-tag marker), or one holding a character Ritual’s own tag grammar refuses (#, &, brackets and the like, which would not import back) is left out, and the export warns naming each one. Importing the file back with ritual import reads those # tokens as Ritual’s per-copy tags, not categories: pasted text cannot tell the two apart. To bring a Moxfield deck’s tags in as categories, import it by URL; see Categories from a URL import.
Commander1 Atraxa, Praetors' Voice (CMR) 523
Deck2 Lightning Bolt (LEA) 1611 Fireblast (VIS) *F* 78
Sideboard1 Price of ProgressMaybeboard and token sections are not part of a decklist, and neither Arena nor Moxfield has a board for them, so an arena or moxfield export leaves those cards out. If your selection reached any, a warning on stderr reports the count and the sections dropped; --quiet never silences it. The ritual and archidekt text forms are flat lists, so they carry every selected entry, maybeboard included.
md — grouped canonical markdown
Section titled “md — grouped canonical markdown”The canonical list markdown, grouped by source: a # List Name H1 per list (first-seen order), ## Section H2 blocks within it, and each card’s canonical line for its list type. Every line is a - bullet, deck lines carry their quantity, and finish/condition/note tokens appear as stored. Card &N IDs are never included.
# burn
## Main
- 2 Lightning Bolt (LEA:161)- 1 Fireblast (VIS:78) [foil]
# binder
## Main
- Sol Ring (C21:263) [foil]Conflicts
Section titled “Conflicts”--columns, --no-header, and --quote-all only shape csv/json output. Giving any of them explicitly with --format text or --format md is a usage error (exit 2). --dialect also shapes text, so it conflicts only with --format md. A preset whose stored columns accompany a text/md format is fine; the columns are simply unused.
Properties
Section titled “Properties”The exportable properties are the fields stored in your list files, the list identity, three derived columns, and two columns read from the local Scryfall cache (scryfallId, edhrecRank):
name, quantity, set, collectorNumber, edition, scryfallId, edhrecRank, finish, isFoil, condition, language, labels, tags, categories, primaryCategory, note, section, listName, listType
The default column set matches the site’s CSV export: name,set,collectorNumber,finish,condition,language,quantity.
Notes on values:
- Set codes are lowercase in JSON (a data format) and uppercase in CSV (like every other user-facing surface).
editioncombines set and collector number into one value:LEA:161in CSV,lea:161in JSON (collector numbers are kept verbatim). Empty for cards without a printing.scryfallIdis the printing’s Scryfall UUID, resolved from your local Scryfall cache (list files do not store it). A card with no printing, or a printing your cache lacks, exports an empty cell plus a warning naming the card. Refresh the cache (ritual cache preload-all) if you need the ids.edhrecRankis the card’s EDHREC rank (1 = the most-played Commander card), also read from the local Scryfall cache. The rank belongs to the card rather than the printing, so it is looked up by name and an entry without a pinned printing gets one too. A card EDHREC has not ranked exports an empty cell silently; a card the cache does not hold at all exports an empty cell plus a warning.scryfallIdandedhrecRankare the only columns that read the cache; an export with neither never touches it. Export never contacts Scryfall itself: a card missing from the cache stays missing until you refresh it.isFoilistruewhen the finish isfoiloretched,falseotherwise (a boolean in JSON,true/falsetext in CSV).languageis the line’s Scryfall language code (ja,zhs, …), blank for English, like the markdown token. In thearchidektdialect it is written as Archidekt’s CSV codes (EN CT DE FR IT JP KR PT RU CS SP, always filled in,ENfor English). A language Archidekt has no code for exports asEN.labelsis the card’s effective labels, comma-joined (sale, trade). A deck line resolves against the deck’s front-matterlabels:default exactly as a collection’s does ([no-proxy]in aproxydeck exports as no labels). Empty for unlabeled cards and always empty for wanted entries. The export flattens the list file, so the override/default split is not represented and ano-negation never appears. Themdformat writes effective labels inline as[labels]tokens for collection entries only (positive, so a line re-imported into a list that has a default adds to that default); deck lines are written without labels, since their effective set can hold collection-only vocabulary a deck line could not re-parse, so a deck’s[proxy]is not exported. Same spelling in every dialect.tagsis the card’s tags, comma-joined in canonical order (Card Draw, Ramp), without the#the card line writes. Tags have no list-level default, so the column is exactly the line’s tags and empty for an untagged card. Themdformat writes them back as the line’s#tagstoken on every list type. Same spelling in every dialect.categoriesis the card’s categories in that list, comma-joined in stored order (Ramp, Artifacts), the first being primary. Categories belong to a card name in one list, so every line of that name (whatever its printing or section) reports the same value, and the column is empty for an uncategorized card. They are read from the list’s<name>.categories.jsonsidecar, not the list file. Same spelling in every dialect (Archidekt’s board is not composed into the cell). Themdformat and theritual,archidektandarenatext forms drop categories, since a category is never on a card line; themoxfieldtext form writes them as#tagtokens (see Dialects). A sidecar that cannot be read is reported as a warning and its list exports with empty category cells.primaryCategoryis the first category, the one the site groups by; empty for an uncategorized card.- JSON records omit properties the entry does not have (no
nulls). Key order follows the column order. - CSV renders missing values as empty cells. An explicit
[nonfoil]finish is written asnonfoil; unlike the site’s fixed CSV export, nothing is blanked. - Card
&NIDs are never exported.
Dialects
Section titled “Dialects”A dialect decides how an export is spelled, so it can be fed straight into another tool’s importer. csv/json take their values from it, text takes its line and board form, and md takes nothing (--dialect with --format md is a usage error).
| Dialect | csv / json values |
text lines |
|---|---|---|
ritual (default) |
finish as nonfoil / foil / etched (blank when the line marks none); condition as NM…DMG (blank when unmarked) |
One flat list of 1 Sol Ring (C21:263) lines |
archidekt |
finish as Normal / Foil / Etched under a Variant header; condition as NM / LP / MP / HP / D |
Same as ritual — Archidekt’s lane is the CSV preset |
arena |
Same as ritual |
Board markers over 1 Sol Ring (C21) 263 lines, no finish marker |
moxfield |
Same as ritual |
The arena form with *F* / *E* between the set and the number, and categories as #tag tokens |
Column keys, the JSON schema, and every property not named above are identical in every dialect.
In the archidekt dialect a line that marks no finish or condition is written as its effective value (Normal, NM), since Archidekt’s CSV has no “unmarked” spelling. An etched-only printing without an explicit [etched] tag is therefore written as Normal; mark the finish on the line if you export such cards by hand. (ritual collection-sync resolves finishes against the Scryfall cache before building its own CSV, so its uploads are never affected.)
Interactive Wizard
Section titled “Interactive Wizard”A bare ritual export opens the wizard when prompting is possible: stdout and stdin are both terminals and --no-input / RITUAL_NO_INPUT is not in force. Any argument or flag that describes a concrete export (list names, --all, --card, a filter, an output-shape flag, --out, --preset, or --save-preset) skips the wizard and runs headlessly. A bare ritual export where prompting is unavailable is a usage error with a hint to pass such a flag (for example --all).
From the main menu you can:
- Add lists: an autocomplete over every deck, collection, and wanted list.
- Add individual cards: an autocomplete over every card entry across all your lists. Search by name, set, or list.
- Filters: the same name/set/finish/condition/labels/tags filters as the flags (tags typed comma-separated).
- Load preset: apply a saved or built-in output shape (the built-in
archidektpreset is always listed). It sits above the three items it overwrites, so you never set format and columns by hand only to lose them to a preset. This is also the only way to pick a dialect in the wizard. The header line names the dialect when it actually shapes the chosen format’s output (moxfield lineson atextexport,archidekt valueson acsvone) and stays silent when it changes nothing (archidektontext,arenaoncsv). - Format, Columns, CSV options: pick
csv/json/text/md. Forcsv/jsonyou then pick columns in output order (each pick appends;Donefinishes,Reset to defaultrestores the standard columns) and toggle the header row and quoting mode. Fortext/mdthe Columns and CSV options menus disappear; atextexport’s line form comes from its dialect, andmdis always Ritual’s canonical markdown. - Save current settings as a preset: store the current output shape under a name.
- Review: print the assembled cards before exporting.
- Export: prompts for the output path (defaults to
export.csv/export.json/export.txt/export.mdto match the format).
ritual export --preset <name> runs the export directly with that preset’s output shape (every list, unless other flags narrow it) and does not open the wizard. To start the wizard from a preset, open the wizard and pick Load preset.
Presets
Section titled “Presets”Presets capture the output shape: format, columns and their order, the CSV toggles, and the dialect. They do not capture sources or filters. They live under exportPresets in ritual.config.json and are managed with --save-preset, the wizard, or by editing the file directly (config set does not manage them):
{ "exportPresets": { "trade-sheet": { "format": "csv", "columns": ["name", "set", "collectorNumber", "condition", "quantity"], "header": true, "quoteAll": false } }}The stored format may be csv, json, text, or md. columns are always stored but only read by csv/json output. dialect is stored only when it is not the default ritual.
Precedence: built-in defaults → --preset values → explicit flags. So ritual export --preset trade-sheet --no-header uses the preset’s columns without the header row.
Built-in presets
Section titled “Built-in presets”| Preset | Output |
|---|---|
archidekt |
Scryfall ID,Quantity,Variant,Condition,Language CSV with a header row, in the archidekt dialect. The file Archidekt’s collection importer takes |
This is exactly what ritual collection-sync push uploads for a large batch of additions. Built-ins need no config and are always available to --preset. Saving a preset of the same name shadows it for ritual export (the sync builds its own upload either way).
ritual export --collection --preset archidekt --out archidekt.csv# 1b59533a-3e38-495d-873e-2f89fbd08494,2,Normal,NM,ENBecause the CSV is keyed by Scryfall ID, rows never need name matching. A printing missing from your local cache exports an empty id cell and a warning, and Archidekt cannot import that row.
Exit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
0 |
Export written |
1 |
Runtime error (for example, the output file could not be written) |
2 |
Usage error (see below) |
3 |
Not found (unknown list or preset) |
Exit 2 covers: conflicting type flags, a type prefix contradicting a type flag, an unknown column or dialect, an invalid filter, column/CSV flags with --format text/--format md, --dialect with --format md, an ambiguous list name, or a bare export where the wizard cannot open.
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.