MTG Commander Deck Analyzer & Star Rating
This skill takes a Commander deck the user pastes in and rates it out of five stars against a target
bracket, with a transparent scorecard and concrete next steps. It is the evaluation counterpart to the
deckbuilding skills: it doesn't build (mtg-edh-build) or swap cards (mtg-edh-upgrade) — it measures and
judges, then points at what to fix.
Two principles keep the rating honest:
- The bracket is the benchmark, and it's determined STRICTLY. Five stars means "matches or beats the
comparable proven top lists for this bracket", not "a cEDH deck" and not "it works". Determine the deck's
actual bracket from concrete signals only (Game Changer count, early two-card combos, MLD, chained
extra turns, fast mana + tutor density — see
references/brackets.md), and report it against the target
the user named. A well-tuned, optimized deck with 0 Game Changers, no combos, no MLD is Bracket
2, not 3 — being good is not a B3 signal. If the deck and its claimed bracket disagree, say so plainly
(and a deck stuffed with Game Changers is not a five-star "Bracket 2" deck; it's mis-bracketed).
- The score is built from evidence, not vibes — and rounds DOWN when evidence is thin. Every dimension is
scored against the strict rubric in
references/rating.md, backed by hard numbers from
scripts/analyze_deck.py, by reading the actual Oracle text, and — for Staples and Synergy — against
comparison data (EDHREC inclusion rates/ranks and comparable real lists for this commander). A deck
that merely functions is ★★★ (3), not 4; 4–5 must be proven against the comparables. When you can't
pull that data, default to the lower score and say so.
Start here: paste your decklist and name a bracket
- The user provides their decklist inline (a Moxfield/Archidekt export, a
1 Card Name list, or a rough
list), or a Moxfield/Archidekt link — for a link, run scripts/import_deck.py <url> to pull it via
the site JSON API (it falls back to asking for a paste if the deck is private/unreachable; never invents
a list). To analyze, write the list to a temp file and run the analyzer (see below) — the parser
tolerates counts or no counts, 1x, (SET) 123 and *CMDR* markers, and section headers.
- Confirm the target bracket (1–5) — the power level to judge the deck against. If the user doesn't
give one, ask, and offer to also tell them which bracket the deck actually looks like. Default to
rating at the deck's apparent bracket if they're unsure. See
references/brackets.md.
- Identify the commander (a
*CMDR*/Commander-section card, or ask) and its color identity — needed
for the legality check and for reading synergy against the right card.
If the pasted list isn't ~100 cards, is malformed, or the commander is ambiguous, say what you found and
confirm with the user before rating.
How to run the analysis
The bundled scripts/analyze_deck.py does the measuring; you do the judging.
- Save the pasted list to a temp file (e.g.
.mtg/analysis/<slug>-input.txt, or any temp path).
- Run
python "${CLAUDE_SKILL_DIR}/scripts/analyze_deck.py" <file> --commander "<name>" --json (add
--identity <letters> if you already know it). It looks every card up in the local Scryfall database and
returns: total cards, land count, mana curve, average MV, EDHREC-rank staple signal (premier
≤500 / staple ≤1500 / played ≤4000 counts + median rank + unranked count), Game Changer count,
off-color-identity cards, total price (Cardmarket EUR), any cards not found, and the full
per-card data including Oracle text and type line.
- Read the per-card Oracle text to classify each card's role (land / ramp / card advantage / interaction
/ board wipe / synergy / wincon) and to score synergy —
analyze_deck.py gives the objective stats,
but classification and synergy are judgment calls that need the wording. Use scryfall_search.py for
anything extra: --named "Card" for a card's exact text, function:ramp id<=<colors> / function:removal … / is:gamechanger id<=<colors> to spot staples the deck is missing.
- Pull the comparable real decklists so the Staples and Synergy dimensions are scored against evidence,
not opinion:
python "${CLAUDE_SKILL_DIR}/scripts/edhrec_fetch.py" "<commander>" (top/staple +
high-synergy cards with inclusion rates), --average (the average ~100-card list), and --theme/--budget
for variants. Compare the deck's contents to these inclusion rates: which high-inclusion staples it runs vs.
misses, and whether its engine is as dense as the proven lists. If EDHREC is unreachable, say so and treat
proven-inclusion claims as lower-confidence — and rate down accordingly (references/rating.md).
If the database can't be built or reached, fall back to web_search/web_fetch of Scryfall pages (and say
prices/newest cards are unverified), or to known MTG knowledge — but prefer the local DB; it's what makes the
staple and curve signals reliable.
Score it: the five-dimension rubric
Apply the rubric in references/rating.md (read it). Score each dimension 1–5 (half-stars allowed), then
combine by weight and apply the gates:
- Structure & consistency (30%) — lands ~37–38, ramp ~10–11, ≥12 net-positive card advantage, ~10
interaction + 2–4 wipes, a curve with only 3–4 cards at MV 6+. The fundamentals that win games.
- Synergy density (25%) — via
references/synergy.md: what fraction of non-structural cards clear the
≥2–3 points of contact bar, the average contact count, and whether engines reinforce each other.
- Staples & card quality (20%) — scored against comparison data: the EDHREC-rank signal and the
inclusion rates of the comparable lists. Does it run the high-inclusion pieces its plan wants, at the rate
the proven lists do, and what high-inclusion cards is it missing? Scaled to bracket (B1–2 lenient, B3–5
demanding); round down when the data is thin.
- Win conditions & closing power (15%) — 3–4 real, repeatable, resilient ways to actually end the
game from a normal board (one unremarkable wincon is a 3, not a 4).
- Bracket calibration (10%, partial gate) — determine the actual bracket from the signals (Game
Changer count, early combos, MLD, chained extra turns, fast mana + tutor density) and compare to the
target. Actual < target is the common honest case (report it, don't inflate elsewhere); actual >
target/violation is mis-bracketed → report the real bracket and cap the score. See
references/brackets.md.
overall = 0.30·structure + 0.25·synergy + 0.20·staples + 0.15·wincons + 0.10·bracket, rounded to the
nearest half-star, then capped by the gates in references/rating.md — note the "it just functions"
ceiling of ★★★ (4+ must be earned against comparable lists), plus the caps for a dimension at 1, a missing
fundamental, or a mis-bracket.
The deliverable
Hand back a rating report in the conversation:
- Headline — e.g.
★★★½ (3.5/5) — a solid Bracket 2 deck, plus the actual bracket stated against the
target if they differ (e.g. "you asked for B3; as built it's B2").
- Scorecard — the five dimensions, each with its stars and the numbers/evidence behind it (show the
analyzer's stats and inclusion-rate comparisons: "Structure ★★★ — 37 lands, 11 ramp, 13 draw, 9
interaction + 3 wipes; on target but not tighter than the comparable lists, so 3").
- Strengths (2–3) and weaknesses (2–3) — concrete, each tied to a dimension and, where possible, to
comparison data.
- Move-up / move-down note — what would raise the deck one bracket and what would drop it
(
references/brackets.md).
- Highest-impact fixes (3–5) — cheapest-first changes that would raise the score most, and an offer to
hand off to
mtg-edh-upgrade to actually make the swaps (carry over the diagnosis).
Keep it honest and specific, and err toward the lower score when evidence is thin — "card advantage is
thin (9, want 12+); EDHREC lists average 14" beats "could be better".
Saving the report is optional — write a file only if the user asks. When they do, save it as
.mtg/analysis/<deck-slug>.md in the resolved workspace (slug = commander name, kebab-case) and share it with
present_files. Don't write decks or import lists here — that's the upgrade skill's job.
The .mtg workspace
This skill mostly reads; it writes only the temp input file and (on request) a report. Its I/O lives in the
same workspace the other MTG skills use, resolved in this order:
$MTG_HOME, if set — the user's portable data location (e.g. a private mtg-data git repo; see
SYNCING.md). Use it even if subfolders don't exist yet — create them.
- Otherwise the nearest
.mtg/ at or above the current working directory (conventionally git-ignored).
Run python "${CLAUDE_SKILL_DIR}/scripts/scryfall_search.py" --paths to print the resolved paths; analysis
files go in a sibling analysis/ folder. If $MTG_HOME is unset and there's no clear working directory and
the user wants a file saved, ask where the workspace should live first; a pure in-chat rating that writes only
a temp file doesn't need this. If a collection/ file exists, you can note which suggested fixes the user
already owns.
Scryfall reads come from the local card database (scripts/analyze_deck.py and scripts/scryfall_search.py
both read .mtg/database/cards.sqlite, built from Scryfall bulk data — see the mtg-db skill; built
automatically on first use, one-time ~78 MB compressed). If it reports the data is stale (>30 days), mention prices
and the staple signal may have shifted and ask whether to refresh first. function:/otag: (Tagger)
queries route to the live API automatically.
Quality bar before you hand it over
- Every dimension score is backed by the analyzer's numbers and by Oracle text you actually read — the
synergy score in particular names specific high-contact and zero-contact cards, not a guess.
- The headline rating is consistent with the rubric and the gates (
references/rating.md) — a deck
missing a fundamental or breaking its bracket isn't quietly handed four stars.
- Bracket is reported two ways when they differ: the rating as the target bracket, and the deck's
actual bracket placement.
- Color identity is checked —
analyze_deck.py flags off-identity cards; surface any (one off-identity
pip makes a card illegal in the deck) and any cards not found in the database (so the user can fix typos).
- The fixes are concrete, prioritized, and cheapest-first, with an offer to hand off to
mtg-edh-upgrade.
1---2name: mtg-edh-analyze3description: Analyze and star-rate an existing 100-card Magic the Gathering Commander (EDH) deck that the user pastes in, judged against a target power bracket. Use this skill whenever the user wants their Commander deck rated, scored, graded, reviewed, or assessed — "how good is my deck", "rate my EDH deck", "give my deck a score out of 5", "how does this deck stack up at Bracket 3", "analyze my commander deck", "is this deck any good", "what bracket is my deck", or any request to evaluate a Commander list rather than build or upgrade one. The user pastes their current decklist inline and names (or is asked for) a target bracket (1–5). The skill measures the deck's hard stats (land count, mana curve, ramp/draw/interaction density, EDHREC-rank staple signal, Game Changer count, color-identity legality, price) via the local Scryfall database, reads every card's Oracle text to score synergy density, then awards an overall ★ rating (with a per-dimension scorecard) for how well the deck performs *at its bracket* — covering pe4---56# MTG Commander Deck Analyzer & Star Rating78This skill takes a Commander deck the user pastes in and **rates it out of five stars against a target9bracket**, with a transparent scorecard and concrete next steps. It is the *evaluation* counterpart to the10deckbuilding skills: it doesn't build (`mtg-edh-build`) or swap cards (`mtg-edh-upgrade`) — it **measures and11judges**, then points at what to fix.1213Two principles keep the rating honest:14151. **The bracket is the benchmark, and it's determined STRICTLY.** Five stars means "matches or beats the16 comparable proven top lists *for this bracket*", not "a cEDH deck" and not "it works". Determine the deck's17 **actual** bracket from concrete signals only (Game Changer count, early two-card combos, MLD, chained18 extra turns, fast mana + tutor density — see `references/brackets.md`), and **report it against the target19 the user named.** A well-tuned, optimized deck with **0 Game Changers, no combos, no MLD** is **Bracket20 2**, not 3 — being good is not a B3 signal. If the deck and its claimed bracket disagree, say so plainly21 (and a deck stuffed with Game Changers is not a five-star "Bracket 2" deck; it's mis-bracketed).222. **The score is built from evidence, not vibes — and rounds DOWN when evidence is thin.** Every dimension is23 scored against the strict rubric in `references/rating.md`, backed by hard numbers from24 `scripts/analyze_deck.py`, by **reading the actual Oracle text**, and — for Staples and Synergy — against25 **comparison data** (EDHREC inclusion rates/ranks and comparable real lists for this commander). A deck26 that merely *functions* is **★★★ (3)**, not 4; 4–5 must be proven against the comparables. When you can't27 pull that data, default to the lower score and say so.2829## Start here: paste your decklist and name a bracket3031- The user provides their **decklist inline** (a Moxfield/Archidekt export, a `1 Card Name` list, or a rough32 list), or a **Moxfield/Archidekt link** — for a link, run `scripts/import_deck.py <url>` to pull it via33 the site JSON API (it falls back to asking for a paste if the deck is private/unreachable; never invents34 a list). To analyze, **write the list to a temp file and run the analyzer** (see below) — the parser35 tolerates counts or no counts, `1x`, `(SET) 123` and `*CMDR*` markers, and section headers.36- Confirm the **target bracket (1–5)** — the power level to judge the deck *against*. If the user doesn't37 give one, **ask**, and offer to also tell them which bracket the deck actually looks like. Default to38 rating at the deck's apparent bracket if they're unsure. See `references/brackets.md`.39- Identify the **commander** (a `*CMDR*`/Commander-section card, or ask) and its **color identity** — needed40 for the legality check and for reading synergy against the right card.4142If the pasted list isn't ~100 cards, is malformed, or the commander is ambiguous, say what you found and43confirm with the user before rating.4445## How to run the analysis4647The bundled **`scripts/analyze_deck.py`** does the measuring; **you** do the judging.48491. Save the pasted list to a temp file (e.g. `.mtg/analysis/<slug>-input.txt`, or any temp path).502. Run `python "${CLAUDE_SKILL_DIR}/scripts/analyze_deck.py" <file> --commander "<name>" --json` (add51 `--identity <letters>` if you already know it). It looks every card up in the local Scryfall database and52 returns: total cards, land count, **mana curve**, average MV, **EDHREC-rank staple signal** (premier53 ≤500 / staple ≤1500 / played ≤4000 counts + median rank + unranked count), **Game Changer count**,54 **off-color-identity** cards, total price (Cardmarket EUR), any **cards not found**, and the **full55 per-card data including Oracle text and type line**.563. **Read the per-card Oracle text** to classify each card's role (land / ramp / card advantage / interaction57 / board wipe / synergy / wincon) and to **score synergy** — `analyze_deck.py` gives the objective stats,58 but classification and synergy are judgment calls that need the wording. Use `scryfall_search.py` for59 anything extra: `--named "Card"` for a card's exact text, `function:ramp id<=<colors>` / `function:removal60 …` / `is:gamechanger id<=<colors>` to spot staples the deck is *missing*.614. **Pull the comparable real decklists** so the Staples and Synergy dimensions are scored against *evidence*,62 not opinion: `python "${CLAUDE_SKILL_DIR}/scripts/edhrec_fetch.py" "<commander>"` (top/staple +63 high-synergy cards with inclusion rates), `--average` (the average ~100-card list), and `--theme`/`--budget`64 for variants. Compare the deck's contents to these inclusion rates: which high-inclusion staples it runs vs.65 misses, and whether its engine is as dense as the proven lists. If EDHREC is unreachable, say so and treat66 proven-inclusion claims as lower-confidence — and rate **down** accordingly (`references/rating.md`).6768If the database can't be built or reached, fall back to `web_search`/`web_fetch` of Scryfall pages (and say69prices/newest cards are unverified), or to known MTG knowledge — but prefer the local DB; it's what makes the70staple and curve signals reliable.7172## Score it: the five-dimension rubric7374Apply the rubric in **`references/rating.md`** (read it). Score each dimension 1–5 (half-stars allowed), then75combine by weight and apply the gates:76771. **Structure & consistency** *(30%)* — lands ~37–38, ramp ~10–11, **≥12 net-positive card advantage**, ~1078 interaction + 2–4 wipes, a curve with only 3–4 cards at MV 6+. The fundamentals that win games.792. **Synergy density** *(25%)* — via `references/synergy.md`: what fraction of non-structural cards clear the80 **≥2–3 points of contact** bar, the average contact count, and whether engines reinforce each other.813. **Staples & card quality** *(20%)* — scored against **comparison data**: the EDHREC-rank signal **and** the82 inclusion rates of the comparable lists. Does it run the high-inclusion pieces its plan wants, at the rate83 the proven lists do, and what high-inclusion cards is it missing? Scaled to bracket (B1–2 lenient, B3–584 demanding); round down when the data is thin.854. **Win conditions & closing power** *(15%)* — 3–4 real, repeatable, resilient ways to actually end the86 game from a normal board (one unremarkable wincon is a 3, not a 4).875. **Bracket calibration** *(10%, partial gate)* — determine the **actual** bracket from the signals (Game88 Changer count, early combos, MLD, chained extra turns, fast mana + tutor density) and compare to the89 target. Actual < target is the common honest case (report it, don't inflate elsewhere); actual >90 target/violation is **mis-bracketed** → report the real bracket and cap the score. See `references/brackets.md`.9192`overall = 0.30·structure + 0.25·synergy + 0.20·staples + 0.15·wincons + 0.10·bracket`, rounded to the93nearest half-star, then capped by the gates in `references/rating.md` — note the **"it just functions"94ceiling of ★★★** (4+ must be earned against comparable lists), plus the caps for a dimension at 1, a missing95fundamental, or a mis-bracket.9697## The deliverable9899Hand back a **rating report** in the conversation:1001011. **Headline** — e.g. `★★★½ (3.5/5) — a solid Bracket 2 deck`, plus the **actual bracket** stated against the102 target if they differ (e.g. "you asked for B3; as built it's B2").1032. **Scorecard** — the five dimensions, each with its stars and the **numbers/evidence behind it** (show the104 analyzer's stats and inclusion-rate comparisons: "Structure ★★★ — 37 lands, 11 ramp, 13 draw, 9105 interaction + 3 wipes; on target but not tighter than the comparable lists, so 3").1063. **Strengths (2–3)** and **weaknesses (2–3)** — concrete, each tied to a dimension and, where possible, to107 comparison data.1084. **Move-up / move-down note** — what would raise the deck one bracket and what would drop it109 (`references/brackets.md`).1105. **Highest-impact fixes (3–5)** — cheapest-first changes that would raise the score most, and an **offer to111 hand off to `mtg-edh-upgrade`** to actually make the swaps (carry over the diagnosis).112113Keep it honest and specific, and **err toward the lower score when evidence is thin** — "card advantage is114thin (9, want 12+); EDHREC lists average 14" beats "could be better".115116**Saving the report is optional — write a file only if the user asks.** When they do, save it as117`.mtg/analysis/<deck-slug>.md` in the resolved workspace (slug = commander name, kebab-case) and share it with118`present_files`. Don't write decks or import lists here — that's the upgrade skill's job.119120## The `.mtg` workspace121122This skill mostly reads; it writes only the temp input file and (on request) a report. Its I/O lives in the123same **workspace** the other MTG skills use, resolved in this order:1241251. **`$MTG_HOME`**, if set — the user's portable data location (e.g. a private `mtg-data` git repo; see126 `SYNCING.md`). Use it even if subfolders don't exist yet — create them.1272. Otherwise the nearest **`.mtg/`** at or above the current working directory (conventionally git-ignored).128129Run `python "${CLAUDE_SKILL_DIR}/scripts/scryfall_search.py" --paths` to print the resolved paths; analysis130files go in a sibling `analysis/` folder. If `$MTG_HOME` is unset and there's no clear working directory and131the user wants a file saved, ask where the workspace should live first; a pure in-chat rating that writes only132a temp file doesn't need this. If a `collection/` file exists, you can note which suggested fixes the user133already owns.134135**Scryfall reads come from the local card database** (`scripts/analyze_deck.py` and `scripts/scryfall_search.py`136both read `.mtg/database/cards.sqlite`, built from Scryfall bulk data — see the **mtg-db** skill; built137automatically on first use, one-time ~78 MB compressed). If it reports the data is **stale (>30 days)**, mention prices138and the staple signal may have shifted and **ask** whether to refresh first. `function:`/`otag:` (Tagger)139queries route to the live API automatically.140141## Quality bar before you hand it over142143- **Every dimension score is backed by the analyzer's numbers and by Oracle text you actually read** — the144 synergy score in particular names specific high-contact and zero-contact cards, not a guess.145- **The headline rating is consistent with the rubric and the gates** (`references/rating.md`) — a deck146 missing a fundamental or breaking its bracket isn't quietly handed four stars.147- **Bracket is reported two ways** when they differ: the rating *as the target bracket*, and the deck's148 *actual* bracket placement.149- **Color identity is checked** — `analyze_deck.py` flags off-identity cards; surface any (one off-identity150 pip makes a card illegal in the deck) and any cards not found in the database (so the user can fix typos).151- **The fixes are concrete, prioritized, and cheapest-first**, with an offer to hand off to `mtg-edh-upgrade`.