A data-driven CLI tool that automatically ranks Pokémon into competitive tiers (S/A/B/C/D) based on base stats, usage data, and configurable meta modifiers.
I got tired of manually debating tier placements. Stats matter, usage matters, but so do intangibles like "is this thing way too slow to function in modern meta?"
This project exists to:
- Provide a reproducible, data-backed tier list
- Make tier thresholds configurable instead of arbitrary
- Allow experimentation with different scoring philosophies
- Serve as a foundation for more complex ranking systems
It's not meant to replace human judgment entirely, but it gives you a defensible starting point.
Each Pokémon gets a score based on three components:
A weighted sum of all six stats. Offensive stats and Speed are slightly favored because they tend to matter more in competitive play:
| Stat | Weight |
|---|---|
| HP | 1.0 |
| Attack | 1.15 |
| Defense | 0.9 |
| Sp. Attack | 1.15 |
| Sp. Defense | 0.9 |
| Speed | 1.25 |
These weights live in config/scoring.config.ts. Tweak them if you disagree.
Based on competitive usage data (usage % and win rate). Higher usage = we're more confident the Pokémon is actually good in practice.
- Usage is normalized relative to the most-used Pokémon
- Win rate provides a small bonus/penalty centered around 50%
- Pokémon with no usage data get a neutral score (not punished)
Adjustments for things pure stats don't capture:
- Glass Cannon Penalty (-8%): High offense + low bulk = inconsistent
- Very Slow Penalty (-12%): Speed < 50 is a real liability
- Legendary Soft Cap (-5%): Keeps the list interesting, not a ban
All modifiers are in rules/modifiers.rules.ts. Easy to add your own.
Tiers are assigned based on percentile rankings:
| Tier | Percentile Range |
|---|---|
| S | Top 10% |
| A | 70-90th |
| B | 45-70th |
| C | 20-45th |
| D | Bottom 20% |
Edit config/tiers.config.ts to rebalance.
# Install dependencies
npm install
# Generate the tier list
npm run generate
# Check the output
cat output/tierlist.jsonEdit config/scoring.config.ts:
statWeights: {
speed: 1.5, // Make speed even more important
defense: 1.0, // Value bulk more
// ...
}Edit config/tiers.config.ts:
thresholds: [
{ tier: 'S', minPercentile: 95 }, // More exclusive S tier
// ...
]Edit rules/modifiers.rules.ts and add to activeModifiers array.
- Add entry to
data/pokemon.json:
{
"id": 1000,
"name": "NewMon",
"types": ["Dragon", "Steel"],
"baseStats": {
"hp": 100,
"attack": 120,
"defense": 90,
"spAttack": 80,
"spDefense": 85,
"speed": 95
}
}- Optionally add usage data to
data/usage.json:
"NewMon": {
"usagePercent": 5.5,
"winRate": 51.0
}- Run
npm run generate
pokemon-tierlist/
├── data/ # JSON datasets
├── rules/ # Scoring rule implementations
├── engine/ # Core scoring & tier assignment logic
├── config/ # Weights and thresholds
├── utils/ # Helper functions
├── scripts/ # CLI entry point
└── output/ # Generated tier list
- Support for multiple formats (OU, UU, VGC)
- Type effectiveness integration
- Ability/movepool scoring
- Web UI for interactive tier list editing
- Export to image/markdown
- Historical tier tracking over time
- Node.js 18+
- npm or yarn
MIT - do whatever you want with it.