history
Compact and rewrite a list’s change history (.changes.md) in a menu-driven editor, or print it read-only with --show.
A change log can get noisy: many small sessions before a commit, mistimed entries, or sets you would rather merge. history edits the change log only; it never edits the list’s own .md file. Nothing is written until you choose to save. Opening the editor runs the standard card-ID backfill first, since Rewrite with defaults embeds &N IDs in the lines it generates. --show skips it.
The admin site offers the same editor in the browser: see Change History.
ritual history [listName] [options][listName] names a list of any type; see List Names. Pass --deck, --collection, or --wanted to pin the type or disambiguate. With no list name, the command prompts you to pick one (filtered by the type flag if given).
Arguments
Section titled “Arguments”| Argument | Description | Required |
|---|---|---|
[listName] |
Name of the deck, collection, or wanted list (case- and accent-insensitive, no extension) | No |
Options
Section titled “Options”| Option | Description |
|---|---|
--deck |
Resolve the name as a deck |
--collection |
Resolve the name as a collection |
--wanted |
Resolve the name as a wanted list |
--show |
Print the change history and exit instead of opening the editor |
--limit <n> |
With --show: print only the newest <n> change sets (positive integer) |
--output <format> |
Output format for --show: text (default), json, or ndjson |
history has no --quiet: --show prints its payload and the editor needs a terminal (shared convention).
--deck, --collection, and --wanted are mutually exclusive. --limit and --output json/ndjson both require --show.
Read-only output with --show
Section titled “Read-only output with --show”--show prints the change history newest-first and exits. Nothing is written, not even the card-ID backfill.
ritual history my-deck --showritual history my-deck --show --limit 3ritual history my-deck --show --output jsonText output starts with a header line, Change history for Deck 'my-deck' — 4 change set(s)., where the count is the full history before any --limit truncation. Each set follows: its timestamp and line count, then its raw change lines indented two spaces verbatim (including the leading - and the &N card IDs), then any preserved hand-written lines attached to the set (see Lossless editing), indented the same way. A list with no history prints No change history recorded. and exits 0.
--limit <n> keeps only the newest n sets.
With --output json, the payload is the admin site’s GET /api/history/:type/:slug response minus its success and defaultEvents fields:
{ "header": "# Changelog for my-deck", "sets": [ { "timestamp": "2026-02-01T10:00:00.000Z", "lines": ["- Removed \"Lightning Bolt\" (LEA:161) &2"], "events": [ { "action": "remove", "cardName": "Lightning Bolt", "cardId": 2, "set": "lea", "collectorNumber": "161" } ] } ]}headeris everything before the first change set in the.changes.mdfile.setsholds the change sets newest first (truncated to--limit), each{ timestamp, lines, events }.linesare the raw-lines verbatim.eventsare the set’s typed change events from itsritual-changesblock, one per line, in order, and empty for a legacy entry with no block. Atrailingarray is present when hand-written text follows the set’s change lines (see Lossless editing). An empty history emits"sets": [].
--show is the only path available to a script. Running --show without a [listName], or running the editor at all, when prompts are unavailable is a usage error (exit 2) rather than a hang. The list picker only runs on a TTY, and the editor exits 2 with Input required: the interactive history editor is unavailable ….
The editor
Section titled “The editor”The main menu lists each change set (newest first) as a collapsed row: its timestamp and how many change lines it holds. Type to filter the list by timestamp (the global actions stay pinned); the list picker shown when no list name is given filters the same way. Selecting a set expands it, prints its lines, and opens a per-set action menu. The global actions sit below the sets.
Per-set actions
Section titled “Per-set actions”| Action | Effect |
|---|---|
| Delete | Removes the change set from the log. The cards themselves are not removed from the list. |
| Combine | Prompts for another set and merges it into the selected one, which keeps its timestamp. See Combining sets. |
| Edit timestamp | Replace the set’s timestamp with a valid ISO-8601 value (e.g. 2026-05-29T12:00:00.000Z). On save, sets are re-sorted chronologically. |
Global actions
Section titled “Global actions”These appear below the change sets, in this order:
| Action | Effect |
|---|---|
| Undo last change | Reverts the most recent edit. Edits are kept on a stack, so you can undo back to the loaded state. Offered only once you have made an edit. |
| Preview changes to be saved | Summarizes how the saved file will differ: change-set and change-line counts before/after, and the resulting list of sets. |
| Rewrite with defaults | Replaces all change sets with one new set (timestamped now) describing the list as it stands: every card, plus sections, commander, notes, label overrides, tags, categories, and printings. |
| Exit | With unsaved changes, prompts: Save and exit, Exit without saving, or Cancel. Nothing is written until you choose Save and exit. |
Behavior
Section titled “Behavior”List Resolution
Section titled “List Resolution”[listName] is matched case- and accent-insensitively across all list types (exact name first, then a unique substring). A name that exists in more than one type is rejected unless you pin it with a type flag. See List Names.
Combining sets
Section titled “Combining sets”When two sets are combined, their lines are interleaved by age, older set on top, so newer changes always end up at the bottom whichever set you combined into which. The result is then compacted the same way the card editor’s live change log is. An add and a later remove of the same card (matching printing, finish, condition, board, and ID) cancel out, as do set/unset-commander and add/remove-section pairs. This is decided on the sets’ typed events, never by re-reading the prose. A combine that cancels everything drops the set.
Surviving lines keep their exact original text, including &N card IDs, and their events. Two well-formed sets combine in lockstep (prose line i with event i). A legacy set with no events block can only be combined with another legacy set; the two merge as opaque prose and nothing cancels. A legacy set is never offered a set that carries a block, and a set whose prose and events are out of step is not offered at all.
Lossless editing
Section titled “Lossless editing”Apart from combine’s compaction, change lines are moved around verbatim, each with its typed event. The editor never re-parses or reformats them. Rewrite with defaults regenerates both lines and events from the current list contents and from the list’s .categories.json sidecar, the only other file it reads. A sidecar that cannot be read is reported and contributes no category events.
Hand-written text between change sets is preserved too. Non-change lines are attached to the set they follow (shown beneath its change lines, and carried in --show’s JSON as the set’s trailing array). They travel with that set through timestamp edits and combines and are re-emitted on save. Each line is kept as written, indentation included, but blank lines between them are dropped and the block always lands after the set’s change lines. Deleting a set deletes its attached text, and Rewrite with defaults discards every set’s attached text (the confirmation says how many lines). Text before the first set belongs to the header and always survives.
Only the change log is modified
Section titled “Only the change log is modified”Every action edits the .changes.md file beside the list. The list’s own .md file is never edited; only Rewrite with defaults reads it, along with the categories sidecar. The only write outside the changelog is the startup card-ID backfill.
Exit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
0 |
Success (saved, discarded, or nothing to save; with --show, printed — even an empty history) |
2 |
Usage error (see below) |
3 |
Not found (no matching list, or no lists at all) |
Exit 2 covers: conflicting type flags, an ambiguous list name, --limit or --output json/ndjson without --show, or a run needing a prompt when prompts are unavailable (the editor, or --show without a list name).
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.