loading…
Search for a command to run...
loading…
Diablo II Resurrected modding toolkit — character builder, mod build/deploy pipeline, save inspector, CASC reader, and MCP server for Claude/Codex/AI integratio
Diablo II Resurrected modding toolkit — character builder, mod build/deploy pipeline, save inspector, CASC reader, and MCP server for Claude/Codex/AI integration. Linux/Steam Deck.
Tests Python 3.10+ License: MIT Platform: Linux
D2R modding toolkit for Linux and Steam Deck (Proton). YAML-driven character builder, data modding pipeline, and an MCP server that exposes the tools to agentic clients (Claude Code, Codex, Cursor, etc.).
.d2s save filesgit clone <repo-url>
cd d2r-tools
pip3 install -e .
d2r-mod extract # extracts + generates data from your D2R install
d2r-chargen build MyChar
(or pip install -e . if pip points to Python 3 on your system)
Three commands from clone to working. The extract step generates Python data modules from your D2R installation (required for legal reasons - no game data is distributed).
# If D2R is not auto-detected:
d2r-mod extract --game-dir /path/to/Diablo\ II\ Resurrected
# Or set the environment variable:
export D2R_GAME_DIR="/path/to/Diablo II Resurrected"
An example character YAML is included in chars/ExamplePaladin.yaml.
Create your own characters in the chars/ directory.
D2R install path is auto-detected on Linux/Steam Deck and Windows. Use --game-dir to override.
Characters are defined in YAML files placed in a chars/ directory. Here's a complete example:
schema_version: 1
name: MyPaladin
class: paladin
level: 85
stats:
strength: 156
dexterity: 100
vitality: 250
energy: 15
skills:
Holy Shield: 20
Smite: 20
Fanaticism: 20
Charge: 1
Salvation: 1
Cleansing: 1
equipment:
# Unique items - resolved automatically from game data
- slot: helm
unique: Guillaume's Face
# Runeword items - specify runeword name and base item code
- slot: body
runeword: Fortitude
base: utp # Archon Plate
# Rare/crafted items with explicit properties
- slot: hands
rare: true
base: uvg # Vampirebone Gloves
ilvl: 90
properties:
fire_res: 30
cold_res: 30
light_res: 30
life: 20
- slot: weapon
unique: Grief
base: 7cr # Phase Blade
- slot: shield
unique: Herald of Zakarum
- slot: belt
unique: Verdungo's Hearty Cord
- slot: feet
unique: Gore Rider
- slot: neck
rare: true
ilvl: 90
properties:
class_skills: [2, paladin]
fcr: 10
fire_res: 30
light_res: 25
- slot: ring_right
unique: Bul Katho's Wedding Band
- slot: ring_left
unique: Ravenfrost
inventory:
charms:
# Unique charms
- unique: Annihilus
properties:
all_skills: 1
strength: 20
dexterity: 20
fire_res: 20
cold_res: 20
light_res: 20
poison_res: 20
add_exp: 10
# Repeatable magic charms
- magic_grand_charm:
count: 8
properties:
skill_tab: [1, 15] # Combat skills (paladin)
life: 40
- magic_small_charm:
count: 5
properties:
life: 20
light_res: 11
merc:
equipment:
- slot: weapon
unique: The Reaper's Toll
ethereal: true
helm, body, weapon, shield, hands, belt, feet, neck, ring_right, ring_left, weapon_switch, shield_switch
| Field | Description |
|---|---|
unique: "Name" |
Unique item - stats auto-resolved from game data |
set_item: "Name" |
Set item |
runeword: "Name" |
Runeword - requires base code |
rare: true |
Rare item - requires base and properties |
magic_grand_charm |
Magic grand charm with count and properties |
magic_small_charm |
Magic small charm with count and properties |
amazon, sorceress, necromancer, paladin, barbarian, druid, assassin, warlock
d2r-chargen build <name> [--phase N] [--force] # Build character (phases 1-4)
d2r-chargen validate <name> [--yaml-only] # Validate YAML definition
d2r-chargen list # List defined characters
d2r-chargen scan <name> # Run scanner diagnostics
d2r-chargen import <name> [--force] # Import .d2s -> YAML
d2r-chargen diff <file1> <file2> # Compare .d2s files
d2r-mod extract [--game-dir PATH] # Extract game data + generate Python modules
d2r-mod build [--no-regen] # Build mod from vanilla + overlays
d2r-mod deploy [--force] [--no-casc] # Deploy mod to game directory
d2r-mod undeploy # Remove mod from game
d2r-mod diff [--summary] # Compare vanilla vs modded tables
d2r-mod inject [--from-dir PATH] # Inject files into CASC archive
d2r-mod audit [--skills] [--items] # Audit game data
d2r-mod clean # Remove build/ and reset data
d2r-mod update # Re-extract after game update
Overlays modify D2R data tables declaratively using YAML. Place overlay files in an overlays/ directory and run d2r-mod build.
Create an overlays/ directory in your project root to add custom overlays.
If no overlays directory exists, d2r-mod build will proceed with vanilla data only.
target: data/global/excel/UniqueItems.txt
changes:
- row: {index: "The Gnasher"}
set:
prop4: "dmg%"
min4: "50"
max4: "50"
comment: "Buff The Gnasher with +50% Enhanced Damage"
Each overlay targets a specific game table (TSV file) and specifies row matches and column changes. See examples/sample_overlay.yaml for a complete example.
D2R reads item names, mercenary names, and most UI strings from JSON files in data/local/lng/strings/ (not from the older .tbl files). To add a new string or override a vanilla one, drop a YAML spec into patches/json_strings/ and rebuild.
# patches/json_strings/my_renames.yaml
description: "Rename a few potions"
target: item-names.json
entries:
- key: "vps" # vanilla string key (super healing potion)
value: "Wild Rice Cake" # what D2R should display instead
- key: "MyCustomItem" # new key — auto-allocated string ID
value: "Heart of the Mountain"
If the key already exists in the target JSON, its enUS value is overridden. If it doesn't, a new entry is appended with the next free string ID (read from data/local/lng/next_string_id.txt). Targets currently used: item-names.json, mercenaries.json, ui.json.
After d2r-mod build, the patched JSONs land in build/data/local/lng/strings/; d2r-mod deploy injects them into CASC. D2R caches strings at startup, so fully exit and relaunch to see changes.
If no patches/json_strings/ directory exists, the build skips this step.
d2r_chargen/ YAML character builder
build_lib.py Binary item encoder (Huffman, stat encoding, checksums)
character.py Build orchestrator (YAML -> items -> .d2s)
resolve.py Name-to-ID resolution (uniques, runewords, stats, skills)
save.py Save file operations (stats, skills, waypoints, items)
scanner.py Diagnostic validator
data/ Game data (generated via extract, not distributed)
d2r_mod/ Data modding pipeline
casc.py Pure Python CASC reader (TBL, TXT, JSON)
casc_write.py CASC archive builder + ekey-hijack injection
overlay.py YAML overlay loader and applier
build.py Build orchestrator (vanilla + overlays -> build/)
build_steps/ Specialized build steps:
register_custom_uniques.py Auto-register custom unique names in TBL
build_string_registry.py Diff built TBLs vs vanilla into a registry
patch_json_strings.py Apply patches/json_strings/*.yaml to JSON
deploy.py Deploy/undeploy mod files
regen.py Generate chargen data from extracted tables
tools/ Standalone diagnostics
audit_string_registry.py Categorize string_registry entries vs JSON
| Platform | Status |
|---|---|
| Linux / Steam Deck (Proton) | Supported, tested |
| Windows | Untested — path detection included, contributions welcome |
| macOS | Unsupported |
mcp SDK (installed automatically with the package)MIT
d2r-tools ships an MCP server that exposes
game-data lookups, save inspection, the chargen pipeline, and the mod pipeline
as typed tools to any MCP-compatible agent. See d2r_mcp/README.md for the
full tool catalog (23 tools across lookup / save / chargen / mod).
pip install -e . # `mcp` SDK is included as a base dependency
python3 -m d2r_mcp # stdio transport
Claude Code (user-scoped):
claude mcp add d2r-tools --transport stdio --scope user -- python3 -m d2r_mcp
Codex / Cursor / any other MCP client — add to the client's MCP config:
{
"mcpServers": {
"d2r-tools": {
"command": "python3",
"args": ["-m", "d2r_mcp"],
"env": {}
}
}
}
Mutation tools (d2r_chargen_build, d2r_mod_deploy) enforce the project's
safety rules structurally: they back up the live save, build to a staging
file, run the scanner on the staging, and only promote to the live save if
the scanner passes.
The plugin/ directory is a Claude Code plugin that adds slash commands and
skills on top of the MCP server. Point Claude Code at the repo or symlink
plugin/ into your Claude Code plugins directory.
| Command | Description |
|---|---|
/d2r-build <name> |
Safe build cycle (backup → build → scan → verify) |
/d2r-validate <name> |
Validate character YAML without building |
/d2r-scan <name> |
Run diagnostic scanner |
/d2r-lookup <query> |
Look up items, stats, skills from game data |
Добавь это в claude_desktop_config.json и перезапусти Claude Desktop.
{
"mcpServers": {
"crabsmadethis-d2r-horadric-tools": {
"command": "npx",
"args": []
}
}
}