Skip to content

Repository files navigation

D4 Filter Generator

Generate and decode Diablo IV loot-filter import/export codes from a human- and AI-authorable spec — no in-game clicking, and full round-trip (decode an existing code back into an editable spec).

The filter code is base64-wrapped protobuf. This project reads and writes it directly, so you can:

  • Build a filter from a readable spec (rules → conditions) instead of the in-game editor.
  • Decode any existing code — including ones shared elsewhere — into a spec you can inspect and edit.
  • Use capabilities the client hides, such as translucent labels via the color's alpha channel.

Three surfaces over one engine: a web app, a scriptable CLI, and an interactive terminal builder.

Install

Web app — nothing to install; use the hosted builder + decoder at https://zmsl.github.io/djunker/.

CLI — grab the tarball from the latest release and install it globally (it's self-contained — the engine and catalogs are bundled in):

npm install -g ./djunker-cli-<version>.tgz
djunker decode <code>                      # now on your PATH

Or run it once without installing: npx ./djunker-cli-<version>.tgz decode <code>. To work from source instead, see Development.

Quickstart (from source)

pnpm install
pnpm build

CLI — author a filter as a pipeline of small commands (a spec flows stdin → stdout), then encode. Rules are referenced by index or name; conditions by type (one of each per rule):

pnpm -s djunker draft create "Endgame" \
  | pnpm -s djunker draft rule create --action recolor --color '#80ff00ff' --name "Great 2H" \
  | pnpm -s djunker draft rule condition create rarity "Great 2H" --rarities Legendary,Unique \
  | pnpm -s djunker draft build            # → a base64 filter code

Decode any code back into a spec with pnpm -s djunker decode <code>. The command tree is self-describing for agents: pnpm -s djunker manifest (machine-readable command tree) and pnpm -s djunker schema (JSON Schema for the spec). (-s keeps pnpm's banner out of the pipe; an installed package exposes the djunker binary directly.)

Web app — a themed builder + decoder:

pnpm web                                   # Vite dev server

Interactive TUI — the same builder in your terminal:

pnpm -s djunker interactive

Authoring with Claude — the loot-filter-creator skill

A Claude Code skill that turns a build, a goal, or an existing filter code into a precedence-ordered rule set and emits it through this engine. It knows the engine and the reasoning (first-match-wins ordering, the condition vocabulary, the in-game constraints), and gets the itemization — which affixes, uniques, and thresholds matter — from you or from a build guide you share. It's meta-agnostic on purpose, so it doesn't go stale with the season.

What it does:

  • From a build — paste a build guide or a Mobalytics / Maxroll / Wowhead / D4Builds URL and it extracts the uniques, per-slot affix priorities, and greater-affix targets, then structures them into keeps → highlights → suppression → floor.
  • From a goal — "hide the junk", "only show my build's gear", "highlight GA cooldown rolls" — it interviews for what it needs and builds to it.
  • From a code — hand it an existing base64 filter code and it decodes, explains, and edits in place.

It always emits a validated JSON FilterSpec and an importable code (via the same @djunker/app engine and djunker CLI documented above), then explains the filter back to you rule by rule.

The skill lives in skills/loot-filter-creator/ — a SKILL.md plus references/ (the condition/action vocabulary, the authoring API, build-extraction notes, and reusable rule archetypes). To use it with Claude Code, make it discoverable as an Agent Skill: copy it into this repo's .claude/skills/ (project scope) or your ~/.claude/skills/ (personal scope) —

cp -r skills/loot-filter-creator .claude/skills/

— then invoke it with /loot-filter-creator, or just describe what you want ("make a strict endgame filter for my Rogue") and Claude will trigger it. The skills/ copy is the source of truth; re-copy after editing so the two don't drift.

Development

A pnpm monorepo: packages/data (catalogs) → packages/core (encode/decode engine + the one Zod spec schema) → packages/app (stateless operations + the FilterEditor ViewModel) → packages/cli (the djunker binary + Ink TUI); apps/web (Vite + React) consumes @djunker/app. All three surfaces bind the same engine.

  • pnpm build — build the packages · pnpm typecheck — type-check every project
  • pnpm test — engine + CLI tests · pnpm web:test — web app · pnpm test:all — both

Releases & deployment

Two GitHub Actions workflows in .github/workflows/:

  • Release (release.yml) — cut a CLI release by pushing a semver tag:

    git tag v0.1.0 && git push origin v0.1.0

    The workflow typechecks and tests, stamps the tag's version into @djunker/cli, builds, and runs scripts/pack-cli.mjs to produce a self-contained tarball — the CLI's tsup build inlines the @djunker/* workspace packages, so the tarball carries the engine and catalogs and only pulls its real npm deps (commander, ink, react, zod) on install. It's attached to a GitHub Release with auto-generated notes. Build one locally to inspect it with pnpm pack:cli.

  • Deploy Pages (deploy-pages.yml) — builds apps/web and publishes it to GitHub Pages on every push to main. The site is served under /djunker/ (set via Vite base). One-time setup: in the repo, go to Settings → Pages → Source → GitHub Actions to enable it.

Reference

  • docs/embedding.md — build your own UI on the engine: the stateful FilterEditor ViewModel and the stateless operations around it, covering the full decode/new → edit → encode lifecycle (with a framework-free walkthrough and a React binding).
  • docs/wire-format.md — the complete byte format (envelope, message layouts, condition types 0–9, enums, bitmasks, constraints), reverse-engineered from live in-game exports plus the public protobuf spec. Reference only — the engine doesn't load it; it's what the encoder/decoder is written and audited against, and proven by the round-trip fixtures in packages/core/test/fixtures/.
  • packages/data/src/ — the reference data the engine loads: the ID ↔ name catalogs (affixes.json, uniques.json incl. variant: "seal" forms, item-types.json) plus enums.json (rarities, item-property tiers, visibility, condition types — the name↔wire mappings). Catalog entries have an id (fixed32 hex), decimal, and name; affixes also carry category/stat/classes where known.

Names resolve through these catalogs, with a raw 0x… escape hatch for anything not catalogued.

Status

Reverse-engineering of the format and catalogs is complete and byte-verified against real game codes (packages/core/test/fixtures/). The engine, CLI, TUI, and web app are in active development.

License

MIT — see LICENSE.

About

Diablo IV loot-filter generator — encode/decode filter codes from a human/AI-authorable spec (engine, CLI+TUI, web).

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages