# MTG EDH Deck Manager Command-line toolkit for managing Magic: The Gathering Commander (EDH) decks using the Scryfall API. ## Installation ```bash git clone cd Decks # Install git hook for auto-updating docs cp scripts/pre-commit .git/hooks/pre-commit chmod +x .git/hooks/pre-commit ``` No dependencies required - pure Python 3 standard library. ## Usage ### Hydrate a Collection Fetch card data from Scryfall for a decklist: ```bash python hydrate.py hydrate data/collection/decklist.txt -o output/hydrated/ -c cache/card_cache.json ``` ### Create a New Deck ```bash python hydrate.py new my_deck ``` ### Analyze Decks Find upgrade options from your collection: ```bash python scripts/analyze_decks.py --collection output/hydrated/deck.json --deck-dir data/decks/ ``` ### Find Synergies Search for cards by keywords, colors, and type: ```bash # Find landfall cards in Simic colors python scripts/find_synergies.py --collection output/hydrated/deck.json --colors U G --keywords landfall # Find Bird creatures in Bant colors python scripts/find_synergies.py --collection output/hydrated/deck.json --colors U G W --creature-type Bird # Find instants with CMC 2 or less python scripts/find_synergies.py --collection output/hydrated/deck.json --type instant --cmc-max 2 ``` ### Generate Reports ```bash python scripts/deck_report.py --collection output/hydrated/deck.json --decks-dir data/decks/ --output output/report.md ``` ## Decks | Deck | Colors | Commander | Archetype | |------|--------|-----------|-----------| | my_choco_deck | BUW | G'raha Tia, Scion Reborn | Auto-generated | | Choco | UGW | Choco, Seeker of Paradise | Bird Tribal Landfall | | Hazel | BG | Hazel of the Rootbloom | Golgari Aristocrats | | Palamecia | UR | The Emperor of Palamecia // The Lord Master of Hell | Izzet Self-Mill Storm | | Yshtola | UBW | Y'shtola, Night's Blessed | Esper Stax Drain | ## Workflow ### Quick Reference 1. **Import** - Place text decklists in `data/collection/` 2. **Hydrate** - Run `hydrate.py` to fetch Scryfall data → `output/hydrated/` 3. **Explore** - Find synergies and commanders in your collection 4. **Define** - Create deck JSON files in `data/decks/` 5. **Analyze** - Run `analyze_decks.py` to find upgrade options 6. **Report** - Use `deck_report.py` for markdown summaries --- ## Runbook: Build a Deck From Your Collection ### Step 1: Import Your Collection Create a text file in `data/collection/` with your cards (one per line): ``` 1 Sol Ring (CMA) 1 3 Birds of Paradise (M12) 165 1 Eternal Witness (EMA) 183 ``` Format: ` () ` The set code and collector number are optional but help with accuracy. ### Step 2: Hydrate Your Collection Fetch card data from Scryfall: ```bash python hydrate.py hydrate data/collection/my_cards.txt -o output/hydrated/ -c cache/card_cache.json ``` This creates: - `output/hydrated/deck.json` - All cards with full data - `output/hydrated/creatures.json` - Creatures only - `output/hydrated/instants.json`, `sorceries.json`, etc. ### Step 3: Explore Your Collection **View color distribution:** ```bash python -c " import json from collections import Counter cards = json.load(open('output/hydrated/deck.json')) colors = Counter(c for card in cards for c in card.get('color_identity', [])) for c, n in colors.most_common(): print(f'{c}: {n}') " ``` **Find creature types you own:** ```bash python scripts/find_synergies.py --collection output/hydrated/deck.json --creature-type Elf python scripts/find_synergies.py --collection output/hydrated/deck.json --creature-type Elemental ``` **Find cards by keyword/mechanic:** ```bash # Find all landfall cards python scripts/find_synergies.py --collection output/hydrated/deck.json --keywords landfall # Find lifegain synergies python scripts/find_synergies.py --collection output/hydrated/deck.json --keywords "gain life" # Find -1/-1 counter cards python scripts/find_synergies.py --collection output/hydrated/deck.json --keywords "-1/-1 counter" ``` **Find cards by color identity:** ```bash # Simic (UG) cards python scripts/find_synergies.py --collection output/hydrated/deck.json --colors U G # Esper (WUB) instants python scripts/find_synergies.py --collection output/hydrated/deck.json --colors W U B --type instant ``` ### Step 4: Choose a Commander Based on your collection strengths, pick a commander that matches: - Your most abundant colors - Creature types you have many of - Mechanics with good support in your collection ### Step 5: Create the Deck File Create `data/decks/.json`: ```json { "name": "My Deck Name", "commander": "Commander Name", "colors": ["U", "G"], "archetype": "Simic Value", "cards": { "Sol Ring": 1, "Birds of Paradise": 1, "Eternal Witness": 1 } } ``` ### Step 6: Analyze for Upgrades Find cards in your collection that fit your deck: ```bash python scripts/analyze_decks.py --collection output/hydrated/deck.json --deck-dir data/decks/ ``` This compares your deck against your collection and suggests: - Cards matching your commander's color identity - Cards with synergistic mechanics - Cards not yet in the deck ### Step 7: Generate a Report ```bash python scripts/deck_report.py --collection output/hydrated/deck.json --decks-dir data/decks/ --output output/report.md ``` --- ## Example: Building a Deck From Scratch ```bash # 1. Add your collection echo "1 Ashling, Rekindled // Ashling, Rimebound (ECL) 124" >> data/collection/my_cards.txt # 2. Hydrate python hydrate.py hydrate data/collection/my_cards.txt -o output/hydrated/ -c cache/card_cache.json # 3. Find red instants/sorceries (spellslinger support) python scripts/find_synergies.py --collection output/hydrated/deck.json --colors R --type instant python scripts/find_synergies.py --collection output/hydrated/deck.json --colors R --type sorcery # 4. Create deck file cat > data/decks/ashling.json << 'EOF' { "name": "Ashling Spellslinger", "commander": "Ashling, Rekindled // Ashling, Rimebound", "colors": ["R"], "archetype": "Mono-Red Spellslinger", "cards": {} } EOF # 5. Analyze and find synergies python scripts/analyze_decks.py --collection output/hydrated/deck.json --deck-dir data/decks/ ``` --- ## Runbook: Update Your Collection ### Scenario 1: Add New Cards (Single File) If you opened new packs and want to add cards: ```bash # 1. Create a new file with the new cards cat > data/collection/new_cards_2026-02-20.txt << 'EOF' 1 Bre of Clan Stoutarm (ECL) 8 3 Mulldrifter (ECC) 67 1 Sol Ring (ECC) 57 EOF # 2. Hydrate the new file (merges into existing cache) python hydrate.py hydrate data/collection/new_cards_2026-02-20.txt -o output/hydrated/ -c cache/card_cache.json ``` ### Scenario 2: Add Cards to Existing File ```bash # Append to existing collection file echo "1 The Reaper, King No More (ECC) 4" >> "data/collection/Box1 2026-01-30.txt" # Re-hydrate that file python hydrate.py hydrate "data/collection/Box1 2026-01-30.txt" -o output/hydrated/ -c cache/card_cache.json ``` ### Scenario 3: Merge Multiple Collection Files If you have multiple files to combine: ```bash # Hydrate each file separately (cache persists) python hydrate.py hydrate data/collection/Box1.txt -o output/hydrated/ -c cache/card_cache.json python hydrate.py hydrate data/collection/Box2.txt -o output/hydrated/ -c cache/card_cache.json # Note: Each run overwrites deck.json. To merge, combine files first: cat data/collection/Box1.txt data/collection/Box2.txt > data/collection/combined.txt python hydrate.py hydrate data/collection/combined.txt -o output/hydrated/ -c cache/card_cache.json ``` ### Scenario 4: Re-hydrate Entire Collection If cache is corrupted or you want fresh data: ```bash # Option A: Keep cache, just re-run python hydrate.py hydrate data/collection/combined.txt -o output/hydrated/ -c cache/card_cache.json # Option B: Clear cache and fetch fresh (slow, ~100ms per unique card) rm cache/card_cache.json python hydrate.py hydrate data/collection/combined.txt -o output/hydrated/ -c cache/card_cache.json ``` ### Scenario 5: Update After Set Release When a new set releases and you want to add those cards: ```bash # 1. Add new set cards to collection file echo "# Lorwyn Eclipsed - 2026-01-23" >> data/collection/my_collection.txt cat data/collection/new_ecl_cards.txt >> data/collection/my_collection.txt # 2. Hydrate (cache speeds up existing cards, fetches new ones) python hydrate.py hydrate data/collection/my_collection.txt -o output/hydrated/ -c cache/card_cache.json # 3. Verify new cards are present python -c " import json cards = json.load(open('output/hydrated/deck.json')) print(f'Total unique cards: {len(cards)}') " ``` ### Collection File Format ``` # Comments start with # # Format: () 1 Sol Ring (CMA) 1 3 Birds of Paradise 1 Eternal Witness (EMA) 183 # Set code and collector number are optional but recommended # They help Scryfall find the exact printing ``` ### Troubleshooting **Card not found:** ``` Error fetching 'Some Card Name': HTTP 404 ``` → Check spelling, or try without set code. Use the exact name from Scryfall. **Duplicate cards:** If the same card appears multiple times in your file, they're stored separately. Dedupe first: ```bash # Combine duplicates python -c " from collections import Counter cards = Counter() with open('data/collection/my_cards.txt') as f: for line in f: line = line.strip() if line and not line.startswith('#'): parts = line.split(None, 1) if parts: count = int(parts[0]) if parts[0].isdigit() else 1 name = parts[1] if len(parts) > 1 else parts[0] cards[name.split('(')[0].strip()] += count for name, count in sorted(cards.items()): print(f'{count} {name}') " > data/collection/deduped.txt ``` **Slow hydration:** - First run fetches all cards (~100ms each) - Subsequent runs use cache (instant) - 866 unique cards ≈ 87 seconds first run ## Collection Stats - **Total cards:** 1288 - **Unique cards:** 892 - **By type:** - Artifacts: 86 - Creatures: 419 - Enchantments: 67 - Instants: 134 - Lands: 76 - Planeswalkers: 2 - Sorceries: 107 --- *This file is auto-generated. Edit `docs/templates/README.template.md` instead.*