Skip to content

import-csv

Import cards from a CSV file into a deck, collection, or wanted list — creating a new list or appending to an existing one. An interactive setup wizard maps your CSV’s columns to card fields, and prints the equivalent non-interactive command so the same import can be scripted.

CSV import is also available in the admin site (Import CSV page) and as the MCP import_csv tool, both backed by the same engine.

Terminal window
./ritual import-csv <file>

Run with no other flags to use the interactive wizard. The wizard asks for the list type, a name (and deck format for decks), whether the first row is a header, and which column holds each card field.

ArgumentDescriptionRequired
<file>Path to the CSV fileYes
OptionDescription
-t, --type <type>List type to import into: deck, collection, or wanted
-n, --name <name>Name of the list to create or append to
-f, --format <format>Deck format when creating a deck (e.g. commander, modern)
-c, --columns <mapping>Column mapping (see below). Skips the interactive setup wizard.
--no-headerTreat the first row as data instead of a header row
-o, --overwriteReplace an existing list file with the same name
-a, --appendAppend the cards to an existing list instead of creating a new one
--non-interactiveDisable interactive prompts; fail when input is required

Every import requires a name, and creating a deck also requires a format (appending to a deck does not — the format is already in the file). Interactively the wizard prompts for them; non-interactively pass --name (and --format).

By default the import creates a new list and refuses to touch an existing one. Pass --overwrite to replace an existing list, or --append to add the cards to it (--overwrite and --append are mutually exclusive). Interactively, when a list with the chosen name already exists, the wizard asks whether to append, overwrite, or cancel.

Appending:

  • Resolves the list name like every other command (case-insensitive, substring fallback).
  • Continues the list’s &N card IDs from its existing pool.
  • For decks, merges rows into existing lines when the name and printing match (incrementing quantity) and creates any missing sections.
  • Records every added card in the list’s changelog (visible in ritual history and the admin Change History page).

--columns takes a comma-separated list of field=column pairs with 1-based column numbers:

Terminal window
./ritual import-csv cards.csv --type collection --name "Red Binder" \
--columns "name=1,set=2,collector-number=3,finish=4,condition=5,quantity=6"
FieldNotes
nameCard name. Always required.
setSet code. Required for collections, optional for decks/wanted lists.
collector-numberCollector number (a string, e.g. 221★). Required for collections.
conditionCard condition. Not allowed for wanted lists (they carry none).
finishFoil/etched finish.
sectionSection/board. Blank cells fall back to Main.
quantityCopies per row. Blank cells mean one copy.

After the wizard completes, the command prints a ready-to-run ritual import-csv ... --columns ... line that pre-selects the same answers, so you can repeat the import without the wizard.

CSV exports differ between tools, so cell values are normalized during import (all matching is case-insensitive):

  • Condition — canonical codes (NM, LP, MP, HP, DMG), spelled-out names (Near Mint, Lightly Played/Light Played/Slightly Played, Moderately Played, Heavily Played/Heavy Played, Damaged, plus Mint, Played, Poor), short codes (SP → LP, PL → MP), and single letters (N, M, L, H, D).
  • FinishF/foil (and yes/true/1) for foil, E/etched/etched foil/foil etched for etched; empty cells, non-foil/nonfoil, normal, regular, no, false, and 0 all mean non-foil.
  • Section — blank means Main. For decks, common board names normalize to canonical headers: side/sideboard/sbSideboard, maybe/maybeboardMaybeboard, main/mainboard/maindeck/deckMain, commander/command/command zoneCommander. Anything else becomes a custom section verbatim.
  • Quantity — a positive integer, tolerating 4x/x4.
  • Set codes — stored lowercase internally and written uppercase in the markdown output, like everywhere else in Ritual.

Rows that fail validation (missing name, missing printing for a collection, unrecognized condition/finish/quantity) do not abort the import: every valid row is imported, and each failed row is reported with its line number, raw text, and reason. When any row fails, the command exits non-zero (1) even though the import was written — check stderr for the failed lines.

Interactive import (wizard maps the columns):

Terminal window
./ritual import-csv ./moxfield-export.csv

Scripted collection import:

Terminal window
./ritual import-csv binder.csv --type collection --name "Red Binder" \
--columns "name=1,set=2,collector-number=3,finish=4,condition=5,quantity=6"

Scripted deck import from a headerless CSV:

Terminal window
./ritual import-csv burn.csv --type deck --name "Burn" --format modern \
--columns "quantity=1,name=2,section=3" --no-header

Replace an existing list:

Terminal window
./ritual import-csv binder.csv --type collection --name "Red Binder" \
--columns "name=1,set=2,collector-number=3" --overwrite

Append new cards to an existing collection:

Terminal window
./ritual import-csv new-cards.csv --type collection --name "Red Binder" \
--columns "name=1,set=2,collector-number=3,quantity=4" --append