- Add Sippie Swartzel custom batter profile (0.820 OPS, SS/RF, no HR power) - Update Kalin Young profile (0.891 OPS, All-Star rarity) - Update Admiral Ball Traits profile with innings field - Fix S3 cache-busting to include Unix timestamp for same-day updates - Add pd_cards/core/upload.py and scouting.py modules - Add custom card submission scripts and documentation - Add uv.lock for dependency tracking
16 KiB
pd-cards CLI Reference
Complete command reference for the Paper Dynasty card creation CLI.
Installation
# Install in development mode
uv pip install -e .
# Verify installation
pd-cards version
Command Structure
pd-cards <subcommand> <command> [OPTIONS]
Subcommands:
custom- Custom character card managementlive-series- Live season card updatesretrosheet- Historical Retrosheet data processingscouting- Scouting report generationupload- Card image upload to S3
custom - Custom Character Cards
Manage fictional player cards using YAML profiles stored in pd_cards/custom/profiles/.
custom list
List all available character profiles.
pd-cards custom list
Output: Table showing name, type (batter/pitcher), target OPS, positions, and player ID.
custom preview
Preview a character's calculated ratings without submitting.
pd-cards custom preview <character>
Arguments:
character- Profile name (e.g.,kalin_young,tony_smehrik)
Output: Displays:
- Player info (name, hand, target OPS, IDs)
- Defensive positions with ratings
- Batting/pitching ratings vs L and R
- Calculated AVG/OBP/SLG/OPS for each platoon split
- Verification that ratings total 108
Example:
pd-cards custom preview kalin_young
custom submit
Submit a custom character to the database.
pd-cards custom submit <character> [OPTIONS]
Arguments:
character- Profile name
Options:
| Option | Short | Description |
|---|---|---|
--dry-run |
-n |
Preview changes without saving |
--skip-s3 |
Skip S3 upload after submit |
Requirements: Profile must have valid player_id and batting_card_id/pitching_card_id set.
Example:
pd-cards custom submit kalin_young --dry-run # Validate first
pd-cards custom submit kalin_young # Actually submit
custom new
Create a new character profile template.
pd-cards custom new --name <name> [OPTIONS]
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--name |
-n |
(required) | Character name |
--type |
-t |
batter |
Player type (batter or pitcher) |
--hand |
-h |
R |
Batting/throwing hand (L, R, or S for switch) |
--target-ops |
0.750 |
Target OPS (or OPS allowed for pitchers) |
Output: Creates YAML file at pd_cards/custom/profiles/<name>.yaml
Examples:
pd-cards custom new --name "Mike Power" --type batter --hand R --target-ops 0.850
pd-cards custom new --name "Sandy Lefty" --type pitcher --hand L --target-ops 0.620
live-series - Live Season Updates
Generate cards from current season FanGraphs/Baseball Reference data.
live-series update
Update live series cards from statistical data.
pd-cards live-series update --cardset <name> [OPTIONS]
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--cardset |
-c |
(required) | Target cardset name |
--season |
-s |
(from cardset) | Season year |
--games |
-g |
162 |
Number of games played (1-162) |
--description |
-d |
(year) | Player description |
--pull-fielding/--no-pull-fielding |
True |
Pull fielding stats from Baseball Reference | |
--post-batters/--skip-batters |
True |
Post batting cards and ratings | |
--post-pitchers/--skip-pitchers |
True |
Post pitching cards and ratings | |
--post-fielders/--skip-fielders |
True |
Post card positions | |
--post-players/--skip-players |
True |
Post player updates | |
--live/--not-live |
True |
Look up current MLB clubs from statsapi | |
--ignore-limits |
False |
Ignore minimum PA/TBF requirements | |
--dry-run |
-n |
False |
Preview without saving to database |
Data Input: Reads from data-input/{cardset} Cardset/
Examples:
pd-cards live-series update --cardset "2025 Season" --games 81 --dry-run
pd-cards live-series update --cardset "2025 Season" --games 162
pd-cards live-series update --cardset "2025 Season" --games 40 --ignore-limits
live-series status
Show status of live series cardsets.
pd-cards live-series status [OPTIONS]
Options:
| Option | Short | Description |
|---|---|---|
--cardset |
-c |
Filter by cardset name |
Output: Table showing cardset ID, name, season, and player count.
Examples:
pd-cards live-series status
pd-cards live-series status --cardset "2025"
retrosheet - Historical Data Processing
Generate cards from Retrosheet play-by-play historical data.
retrosheet process
Process Retrosheet data and create player cards.
pd-cards retrosheet process <year> --cardset-id <id> [OPTIONS]
Arguments:
year- Season year to process (e.g., 2005)
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--cardset-id |
-c |
(required) | Target cardset ID |
--description |
-d |
Live |
Player description (Live or <Month> PotM) |
--start |
{year}0301 |
Start date YYYYMMDD | |
--end |
{year}1002 |
End date YYYYMMDD | |
--events |
-e |
retrosheets_events_{year}.csv |
Retrosheet events CSV filename |
--input |
-i |
data-input/{year} Live Cardset/ |
Data input directory |
--season-pct |
1.0 |
Season percentage (0.0-1.0) | |
--min-pa-vl |
20 (Live) / 1 (PotM) |
Minimum PA vs LHP | |
--min-pa-vr |
40 (Live) / 1 (PotM) |
Minimum PA vs RHP | |
--post/--no-post |
True |
Post data to database | |
--dry-run |
-n |
False |
Preview without saving |
Examples:
pd-cards retrosheet process 2005 --cardset-id 27 --description Live --dry-run
pd-cards retrosheet process 2005 --cardset-id 27 --description Live
pd-cards retrosheet process 2005 --cardset-id 28 --description "April PotM" --start 20050401 --end 20050430
retrosheet arms
Generate outfield arm ratings from Retrosheet play-by-play data.
pd-cards retrosheet arms <year> --events <file> [OPTIONS]
Arguments:
year- Season year
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--events |
-e |
(required) | Retrosheet events CSV file |
--output |
-o |
data-output/retrosheet_arm_ratings_{year}.csv |
Output CSV file |
--season-pct |
1.0 |
Season percentage for min sample |
Output: CSV with player_id, position, arm_rating, balls_fielded, assist_rate, z_score
Example:
pd-cards retrosheet arms 2005 --events data-input/retrosheet/retrosheets_events_2005.csv
retrosheet validate
Validate positions for a cardset.
pd-cards retrosheet validate <cardset_id> [OPTIONS]
Arguments:
cardset_id- Cardset ID to validate
Options:
| Option | Default | Description |
|---|---|---|
--api |
https://pd.manticorum.com/api |
API URL |
Checks:
- Anomalous DH counts (should be <5 for full-season cards)
- Missing outfield positions (LF, CF, RF)
Example:
pd-cards retrosheet validate 27
pd-cards retrosheet validate 27 --api https://pddev.manticorum.com/api
retrosheet defense
Fetch defensive statistics from Baseball Reference.
pd-cards retrosheet defense <year> [OPTIONS]
Arguments:
year- Season year to fetch
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--output |
-o |
data-input/{year} Live Cardset/ |
Output directory |
Output: Creates defense_{position}.csv files for: c, 1b, 2b, 3b, ss, lf, cf, rf, of, p
Note: Includes 8-second delay between requests for rate limiting.
Example:
pd-cards retrosheet defense 2005 --output "data-input/2005 Live Cardset/"
scouting - Scouting Reports
Generate scouting reports and ratings comparisons.
scouting batters
Generate batting scouting reports.
pd-cards scouting batters [OPTIONS]
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--cardset-id |
-c |
(all) | Cardset ID(s) to include (repeatable) |
--output |
-o |
scouting |
Output directory |
Output: Creates batting-basic.csv and batting-ratings.csv
Examples:
pd-cards scouting batters --cardset-id 27
pd-cards scouting batters --cardset-id 27 --cardset-id 29
pd-cards scouting batters --output reports/
scouting pitchers
Generate pitching scouting reports.
pd-cards scouting pitchers [OPTIONS]
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--cardset-id |
-c |
(all) | Cardset ID(s) to include (repeatable) |
--output |
-o |
scouting |
Output directory |
Output: Creates pitching-basic.csv and pitching-ratings.csv
Examples:
pd-cards scouting pitchers --cardset-id 27
pd-cards scouting pitchers --cardset-id 27 --cardset-id 29
scouting all
Generate all scouting reports (batters and pitchers).
pd-cards scouting all [OPTIONS]
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--cardset-id |
-c |
(all) | Cardset ID(s) to include (repeatable) |
--output |
-o |
scouting |
Output directory |
Output: Creates all four scouting CSV files.
Example:
pd-cards scouting all --cardset-id 27
upload - S3 Card Upload
Upload card images to AWS S3.
upload s3
Upload card images to AWS S3 bucket.
pd-cards upload s3 --cardset <name> [OPTIONS]
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--cardset |
-c |
(required) | Cardset name to upload |
--start-id |
Player ID to start from (for resuming) | ||
--limit |
-l |
Limit number of cards to process | |
--html |
False |
Upload HTML preview cards instead of PNG | |
--skip-batters |
False |
Skip batting cards | |
--skip-pitchers |
False |
Skip pitching cards | |
--upload/--no-upload |
True |
Upload to S3 | |
--update-urls/--no-update-urls |
True |
Update player URLs in database | |
--dry-run |
-n |
False |
Preview without uploading |
Prerequisites: AWS CLI configured with credentials (~/.aws/credentials)
S3 URL Structure: cards/cardset-{id:03d}/player-{player_id}/{batting|pitching}card.png?d={date}
Examples:
pd-cards upload s3 --cardset "2005 Live" --dry-run
pd-cards upload s3 --cardset "2005 Live" --limit 10
pd-cards upload s3 --cardset "2005 Live" --start-id 5000
pd-cards upload s3 --cardset "2005 Live" --skip-pitchers
upload refresh
Refresh (re-generate and re-upload) card images.
pd-cards upload refresh --cardset <name> [OPTIONS]
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--cardset |
-c |
(required) | Cardset name |
--limit |
-l |
Limit number of cards | |
--dry-run |
-n |
False |
Preview without refreshing |
Example:
pd-cards upload refresh --cardset "2005 Live" --limit 10
upload check
Check and validate card images without uploading.
pd-cards upload check --cardset <name> [OPTIONS]
Options:
| Option | Short | Default | Description |
|---|---|---|---|
--cardset |
-c |
(required) | Cardset name |
--limit |
-l |
Limit number of cards to check | |
--output |
-o |
data-output |
Output directory |
Example:
pd-cards upload check --cardset "2005 Live" --limit 10
YAML Profile Schema
See also: docs/CUSTOM_CARD_TIERS.md for tier progression system.
Batter Profile
name: Player Name
player_type: batter
hand: R # L, R, or S (switch)
# Tier tracking (see CUSTOM_CARD_TIERS.md for values)
tier: M-STR # Current tier code
target_ops: 0.850 # Must match tier target
tier_history:
- tier: L-STR
date: 2025-01-15
reason: Initial card creation
- tier: M-STR
date: 2025-03-20
reason: Season 5 championship reward
cardset_id: 29
player_id: null # Set after creation
batting_card_id: null
positions:
RF:
range: 3 # 1-5 (lower = better)
error: 7 # 1-20 (higher = better)
arm: 0 # -6 to +5 (negative = strong)
LF:
range: 4
error: 6
arm: 2
baserunning:
steal_jump: 0.166667 # Fraction for steal success
steal_high: 15 # High end of steal range
steal_low: 8 # Low end of steal range
steal_auto: 0 # Auto-steal threshold
running: 12 # Base running rating
hit_and_run: A # A/B/C/D
bunting: B # A/B/C/D
ratings:
vs_L: # All values must sum to 108
homerun: 2.0
bp_homerun: 1.0 # Ballpark home run
triple: 0.5
double_three: 0.0 # Double to 3-zone
double_two: 4.0 # Double to 2-zone
double_pull: 2.0 # Pulled double
single_two: 5.0
single_one: 5.0
single_center: 5.0
bp_single: 3.0 # Ballpark single
walk: 10.0
hbp: 1.0
strikeout: 20.0
lineout: 12.0
popout: 2.0
flyout_a: 2.0
flyout_bq: 2.0
flyout_lf_b: 4.0
flyout_rf_b: 4.0
groundout_a: 5.0
groundout_b: 10.0
groundout_c: 8.5
pull_rate: 0.30
center_rate: 0.40
slap_rate: 0.30
vs_R:
# Same structure as vs_L
Pitcher Profile
name: Pitcher Name
player_type: pitcher
hand: L
target_ops: 0.620 # OPS allowed
cardset_id: 29
player_id: null
pitching_card_id: null
positions:
P: null
pitching:
starter_rating: 5 # 1-5 (higher = better starter)
relief_rating: 5 # 1-5 (higher = better reliever)
closer_rating: null # null or 1-5 for closers
ratings:
vs_L: # All values must sum to 108 (includes 29 for x-checks)
homerun: 1.0
bp_homerun: 1.0
triple: 0.5
double_three: 0.0
double_two: 3.0
double_cf: 2.0 # Pitchers use double_cf, not double_pull
single_two: 4.0
single_one: 3.0
single_center: 4.0
bp_single: 5.0
walk: 8.0
hbp: 1.0
strikeout: 20.0
flyout_lf_b: 4.0
flyout_cf_b: 5.0 # Pitchers have flyout_cf_b
flyout_rf_b: 4.0
groundout_a: 6.0
groundout_b: 7.5
# X-checks (fielder plays) - must sum to 29
xcheck_p: 1.0
xcheck_c: 3.0
xcheck_1b: 2.0
xcheck_2b: 6.0
xcheck_3b: 3.0
xcheck_ss: 7.0
xcheck_lf: 2.0
xcheck_cf: 3.0
xcheck_rf: 2.0
vs_R:
# Same structure as vs_L
Common Workflows
Creating a New Custom Character
# 1. Create template
pd-cards custom new --name "John Slugger" --type batter --hand R --target-ops 0.850
# 2. Edit the YAML file
# pd_cards/custom/profiles/john_slugger.yaml
# 3. Preview ratings
pd-cards custom preview john_slugger
# 4. Create player in database (get IDs)
# Use Paper Dynasty admin interface
# 5. Update YAML with player_id and batting_card_id
# 6. Submit
pd-cards custom submit john_slugger --dry-run
pd-cards custom submit john_slugger
Processing a Historical Season
# 1. Fetch defensive stats
pd-cards retrosheet defense 2005 --output "data-input/2005 Live Cardset/"
# 2. Generate arm ratings
pd-cards retrosheet arms 2005 --events data-input/retrosheet/retrosheets_events_2005.csv
# 3. Process cards
pd-cards retrosheet process 2005 --cardset-id 27 --description Live --dry-run
pd-cards retrosheet process 2005 --cardset-id 27 --description Live
# 4. Validate positions
pd-cards retrosheet validate 27
# 5. Upload to S3
pd-cards upload s3 --cardset "2005 Live" --dry-run
pd-cards upload s3 --cardset "2005 Live"
# 6. Generate scouting reports
pd-cards scouting all --cardset-id 27
Updating Live Season Cards
# Mid-season update (81 games)
pd-cards live-series update --cardset "2025 Season" --games 81 --dry-run
pd-cards live-series update --cardset "2025 Season" --games 81
# Full season update
pd-cards live-series update --cardset "2025 Season" --games 162
# Upload updated cards
pd-cards upload s3 --cardset "2025 Season"