Skip to content
This repository was archived by the owner on Sep 21, 2026. It is now read-only.

Latest commit

 

History

43 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

● guigenmc

JSON → Minecraft GUI datapack generator.

  • CLI — generate from a config file in the terminal
  • Web UI — visual editor in your browser

Works on Linux, macOS, GitHub Codespaces, and GitHub Actions.
No extra packages — Python 3.9+ only.


Quick start

pip install -e .

# Visual editor (browser)
guigenmc ui

# Or from a JSON file
guigenmc generate my_menu.json
guigenmc generate my_menu.json -z    # zip

In Minecraft:

  1. Put the datapack folder in world/datapacks/
  2. /reload
  3. /function <namespace>:menu/<menu_id>/open
  4. Right-click the minecart → SHIFT-click buttons

Commands

Command What it does
guigenmc ui Open the visual web editor
guigenmc generate config.json Build datapack folder
guigenmc generate config.json -z Build a .zip
guigenmc generate config.json -o name Custom output name
guigenmc generate config.json -f Overwrite existing
guigenmc validate config.json Check errors / warnings
guigenmc tree config.json Preview file list (no write)
guigenmc -h Help

Aliases: guigenmc gen, guigenmc g, guigenmc check.

UI options

guigenmc ui                  # http://127.0.0.1:8765 (default, localhost only)
guigenmc ui -p 9000          # custom port
guigenmc ui --host 0.0.0.0   # Codespaces / remote access — see security note
guigenmc ui --no-open        # don't open browser

Default bind address is 127.0.0.1 (localhost only).

In Codespaces: use --host 0.0.0.0 and open the forwarded port in the browser. When binding to all interfaces, guigenmc prints a clear warning: the API has no authentication. Only use --host 0.0.0.0 in trusted or isolated environments (port-forwarded Codespaces, local containers, etc.).


Colors

Colored terminal output is on by default.

  • Off: NO_COLOR=1 guigenmc generate …
  • Force on: FORCE_COLOR=1 guigenmc generate …

GitHub Actions example

name: Build datapack
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install -e .
      - run: guigenmc generate my_menu.json -z -o datapack.zip
      - uses: actions/upload-artifact@v4
        with:
          name: datapack
          path: datapack.zip

Config basics

Minimal config.json:

{
  "namespace": "mymod",
  "menu_id": "shop",
  "pages": [
    {
      "index": 0,
      "name": "Main",
      "widgets": [
        {
          "kind": "button",
          "slot": 13,
          "item": "minecraft:diamond",
          "name": { "text": "Get Diamond", "color": "aqua" },
          "commands": ["give @s minecraft:diamond 1"]
        },
        { "kind": "close", "slot": 26 }
      ]
    }
  ]
}

Widget kinds

kind Description
button Runs commands / functions on click
label Display-only item
separator Filler pane
toggle On/off switch with score
counter +/− a scoreboard value
progress Multi-slot progress bar
nav Go to another page
confirm Go to a confirm page
close Close the menu
random Weighted random rewards
link Clickable external URL (tellraw open_url)
cycle Cycle through options (score-based selector)

Also supports: cost, cooldown, conditions (item_count_*, score, has_tag, gamemode, has_advancement), sounds, multi-page menus, hopper/chest minecart containers.

New widget examples

Link

{
  "kind": "link",
  "slot": 11,
  "item": "minecraft:writable_book",
  "name": { "text": "Discord", "color": "aqua" },
  "url": "https://discord.gg/example",
  "link_text": { "text": "Join our Discord", "color": "aqua" }
}

Cycle

{
  "kind": "cycle",
  "slot": 13,
  "cycle": {
    "score": "difficulty",
    "options": [
      { "item": "minecraft:wooden_sword", "name": { "text": "Easy", "color": "green" } },
      { "item": "minecraft:iron_sword", "name": { "text": "Normal", "color": "yellow" } },
      { "item": "minecraft:diamond_sword", "name": { "text": "Hard", "color": "red" } }
    ]
  }
}

has_advancement condition

{
  "kind": "button",
  "slot": 15,
  "item": "minecraft:nether_star",
  "name": { "text": "Claim Reward" },
  "commands": ["give @s minecraft:diamond 5"],
  "condition": {
    "type": "has_advancement",
    "advancement": "minecraft:story/mine_diamond",
    "fail_message": { "text": "You need the Mine Diamond advancement!", "color": "red" }
  }
}


Security model

guigenmc is a datapack generator, not a sandbox for Minecraft commands.

What guigenmc does What it does not do
Reads a JSON config and writes .mcfunction / datapack files Run OS shell commands (subprocess, os.system, etc.) from config
Embeds commands / functions / on_open / on_close / tick_while_on from your config into the generated datapack Sandbox or filter Minecraft commands inside the config
Validates identifiers and output paths; limits request and output size Protect a multiplayer server from malicious datapack content

Implications:

  • There is no OS shell injection surface from config: guigenmc never runs the host shell based on config values.
  • Config Minecraft command strings (commands, functions, on_open, on_close, tick_while_on, …) are copied into the generated datapack as-is. Anyone who loads that datapack can execute those Minecraft commands in-game. That is intentional generator behavior, not a host OS vulnerability.
  • Path traversal via namespace / menu_id / action_id is rejected (identifiers must match [a-z0-9._-]+). Generated files and ZIP entries are checked so they cannot escape the output directory. Writes also refuse symlink escape (including O_NOFOLLOW on POSIX where available).
  • Resource limits: HTTP request bodies ≤ ~2 MiB; JSON depth ≤ 64 and node count ≤ 100 000; generated datapack ≤ 5 000 files and ≤ ~50 MiB total content.
  • The web UI API (/api/generate, /api/validate, /api/zip) has no authentication. Default listen address is localhost. Binding to 0.0.0.0 exposes an unauthenticated API — use only in trusted/isolated environments.
  • The UI ships a bundled copy of JSZip (static/jszip.min.js, v3.10.1) so it works offline; there is no CDN dependency at runtime.

Identifiers: namespace, menu_id, and action_id must be non-empty lowercase Minecraft resource-location segments (a-z, 0-9, _, -, .). Values containing /, \, .., NULL bytes, absolute paths, or Windows drive letters are rejected with a clear error (e.g. Invalid action_id: contains path separator).


Requirements

  • Python 3.9+
  • Nothing else (stdlib only)


Install from PyPI

pip install guigenmc
guigenmc ui

Publish (maintainers)

  1. Create a GitHub release (tag v1.0.0, etc.) — or run the Publish to PyPI workflow manually.
  2. On PyPI, add a Trusted Publisher for this repo:
    • Owner: your GitHub user/org
    • Repository: guigenmc
    • Workflow: publish.yml
    • Environment: pypi
  3. No API token needed (OIDC).

Local build check:

pip install build twine
python -m build
twine check dist/*
# optional TestPyPI:
# twine upload --repository testpypi dist/*

License

MIT

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages