mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-09-21 20:40:47 +02:00
A deckbuilder for the commander format of Magic: The Gathering
.github/workflows | ||
code | ||
config | ||
.dockerignore | ||
.env.example | ||
.gitignore | ||
CHANGELOG.md | ||
docker-compose.yml | ||
DOCKER.md | ||
Dockerfile | ||
LICENSE | ||
mtg_deckbuilder.spec | ||
mypy.ini | ||
pyproject.toml | ||
README.md | ||
RELEASE_NOTES_TEMPLATE.md | ||
requirements.txt | ||
run-from-dockerhub.bat | ||
run-from-dockerhub.sh | ||
WINDOWS_DOCKER_GUIDE.md |
# 🃏 MTG Python Deckbuilder
A fast, menu-driven CLI to build MTG Commander/EDH decks. Supports interactive and headless runs, CSV/TXT exports, owned-card libraries, and Docker.
🔹 Features
- Commander search with smart theme tagging (primary/secondary/tertiary)
- Power bracket selection and ideal count prompts
- CSV and TXT exports with stable filenames
- Headless mode (non-interactive) and a headless submenu in the main menu
- Config precedence: CLI > env > JSON > defaults
✨ Highlights
- Smart tagging and suggestions for commander + themes
- Exports CSV and TXT decklists to
deck_files/
- Owned-cards mode: point to one or more
.txt
/.csv
files inowned_cards/
and choose "Use only owned cards?" - If you opt out, final CSV marks owned cards with an
Owned
column - Interactive menu with a headless submenu
- Works locally or in Docker (Windows PowerShell friendly)
🚀 Quick start
Docker Hub (PowerShell)
docker run -it --rm `
-v "${PWD}/deck_files:/app/deck_files" `
-v "${PWD}/logs:/app/logs" `
-v "${PWD}/csv_files:/app/csv_files" `
-v "${PWD}/owned_cards:/app/owned_cards" `
-v "${PWD}/config:/app/config" `
mwisnowski/mtg-python-deckbuilder:latest
From source
pip install -r requirements.txt
python code/main.py
From this repo with Docker Compose (PowerShell)
docker compose build
docker compose run --rm mtg-deckbuilder
🤖 Headless mode (no prompts)
- Auto-headless: set
DECK_MODE=headless
- Example (PowerShell):
docker compose run --rm -e DECK_MODE=headless mtg-deckbuilder
- Example (PowerShell):
- Use a JSON config: mount
./config
to/app/config
and setDECK_CONFIG=/app/config/deck.json
- Example (PowerShell):
docker compose run --rm ` -e DECK_MODE=headless ` -e DECK_CONFIG=/app/config/deck.json ` mtg-deckbuilder
- Example (PowerShell):
- Override via env vars (subset):
DECK_COMMANDER
,DECK_PRIMARY_CHOICE
,DECK_SECONDARY_CHOICE
,DECK_TERTIARY_CHOICE
,DECK_ADD_LANDS
,DECK_FETCH_COUNT
,DECK_BRACKET_LEVEL
- Precedence: CLI > env > JSON > defaults
Headless submenu notes:
- If one JSON exists in
config/
, it auto-runs it - If multiple exist, they’re listed as "Commander - Theme1, Theme2, Theme3";
deck.json
shows as "Default" - CSV/TXT are exported as usual; JSON run-config is exported only in interactive runs
Run locally (no Docker)
# Show resolved settings (no run)
python code/headless_runner.py --config config/deck.json --dry-run
# Run with a specific config file
python code/headless_runner.py --config config/deck.json
# Point to a folder; if exactly one config exists, it's auto-used
python code/headless_runner.py --config config
# Override via CLI
python code/headless_runner.py --commander "Pantlaza, Sun-Favored" --primary-choice 2 --secondary-choice 0 --add-lands true --fetch-count 3
CLI flags
- --config Path to JSON config file or a folder to discover configs (uses DECK_CONFIG by default)
- --commander Commander name to search and select
- --primary-choice Primary theme index
- --secondary-choice <n|none> Secondary theme index or omit with "none"
- --tertiary-choice <n|none> Tertiary theme index or omit with "none"
- --add-lands Include land building steps (true/false)
- --fetch-count Requested number of fetch lands
- --dual-count Requested number of dual lands (optional; not exported)
- --triple-count Requested number of triple lands (optional; not exported)
- --utility-count Requested number of utility lands (optional; not exported)
- --add-creatures Add creatures
- --add-non-creature-spells Add non-creature spells orchestrator
- --add-ramp Add ramp (when not using orchestrator)
- --add-removal Add removal (when not using orchestrator)
- --add-wipes Add board wipes (when not using orchestrator)
- --add-card-advantage Add card draw (when not using orchestrator)
- --add-protection Add protection (when not using orchestrator)
- --bracket-level <1-5> Power bracket selection (or use DECK_BRACKET_LEVEL)
- --dry-run Print resolved config and exit
Booleans accept: 1/0, true/false, yes/no, on/off.
JSON export in headless
- By default, headless runs do not export a JSON run-config to avoid duplicates.
- Opt-in with:
$env:HEADLESS_EXPORT_JSON = "1" python code/headless_runner.py --config config/deck.json
- Tip: when opting in, prefer using
--config
instead of aDECK_CONFIG
file path to avoid creating both a stem-based JSON and a second explicit-path JSON.
Example JSON (config/deck.json
):
{
"commander": "Pantlaza",
"bracket_level": 3,
"primary_choice": 2,
"secondary_choice": 2,
"tertiary_choice": 2,
"add_lands": true,
"fetch_count": 3,
"ideal_counts": { "ramp": 10, "lands": 36, "basic_lands": 16, "creatures": 28, "removal": 8, "wipes": 3, "card_advantage": 8, "protection": 3 }
}
Notes: headless honors ideal_counts
(leave prompts blank to accept). Only fetch_count
is tracked/exported for lands.
🕹️ Usage (interactive)
- Start the app (Docker or from source)
- Pick Build a New Deck
- Search/confirm commander
- Pick primary/secondary/tertiary themes (or stop at primary)
- Choose power bracket and review ideal counts
- Deck builds; CSV/TXT export to
deck_files/
⚙️ Environment variables (common)
- DECK_MODE=headless
- DECK_CONFIG=/app/config/deck.json
- DECK_COMMANDER, DECK_PRIMARY_CHOICE, DECK_SECONDARY_CHOICE, DECK_TERTIARY_CHOICE
- DECK_ADD_LANDS, DECK_FETCH_COUNT
- DECK_ADD_CREATURES, DECK_ADD_NON_CREATURE_SPELLS, DECK_ADD_RAMP, DECK_ADD_REMOVAL, DECK_ADD_WIPES, DECK_ADD_CARD_ADVANTAGE, DECK_ADD_PROTECTION
- DECK_BRACKET_LEVEL
Optional name-based tag overrides (mapped to indices for the chosen commander):
- DECK_PRIMARY_TAG, DECK_SECONDARY_TAG, DECK_TERTIARY_TAG
📁 Folders
deck_files/
— CSV/TXT exportscsv_files/
— card datalogs/
— logsconfig/
— JSON configs (optional)owned_cards/
— your owned cards lists (.txt
/.csv
); used for owned-only builds and Owned flagging
🧰 Troubleshooting
- Use
docker compose run --rm
(notup
) for interactive sessions - Ensure volumes are mounted so files persist (
deck_files
,logs
,csv_files
) - For headless with config, mount
./config:/app/config
and setDECK_CONFIG
- Card data refresh: if
csv_files/cards.csv
is missing or older than 7 days, the app refreshes data and re-tags automatically. A.tagging_complete.json
file incsv_files/
indicates tagging completion.
📦 Releases
- Release notes are maintained in
RELEASE_NOTES_TEMPLATE.md
. Automated workflows read from this file to populate Docker Hub and GitHub releases.
🧩 Owned cards library
- Place
.txt
or.csv
lists inowned_cards/
(one card name per line for.txt
; any.csv
with aname
column works). - After commander selection, you’ll be prompted: "Use only owned cards?"
- Yes: deck builds from owned cards only; if fewer than 100 cards, it stays incomplete and prints a note.
- No: the build uses the full pool, but the final CSV marks owned cards with an
Owned
column.
- If an owned-only build is incomplete, a recommendations file is exported:
deck_files/[stem]_recommendations.csv
and.txt
. The app prints: "Recommended but unowned cards in deck_files/[stem]_recommendations.csv".
📄 License & help
- License: MIT (see
LICENSE
) - Issues/Requests: GitHub Issues/Discussions
- Docker details: see
DOCKER.md