Minecraft agents that do whatever you ask. Each agent is a real player (Mineflayer) in a vanilla world; TypeSafe's JEV model picks every action it takes, and a planner model (Claude Opus 5.5 or GPT-6 Astra, on the subscription you already have) understands what you say and speaks for it.
Use it two ways:
herobrine up --world play, herobrine spawn --persona "my bodyguard", herobrine tell Cedar "bring me 5 logs".Both drive the same core; the CLI also works against the MCP instance while Claude Code has it open.
Agents have no fixed roles. Each one has three free-text fields, and the user can change any of them at any time:
| Field | Examples |
|---|---|
| persona: who to be and how to behave | "my bodyguard", "a chill builder who plays alongside me", "a grumpy dwarf miner who never leaves the caves" |
| long_term_goal: an objective it works toward over time | "get us full iron gear", "build a base by the river" |
| task: what to do right now | "collect 10 logs", "make a stone pickaxe", "come here", "bring me 5 cobblestone" |
With no task, the agent picks its own next short-term task based on its persona and long-term goal. Tasks end as done or stuck.
Each agent gets a short single-word Minecraft-style name (e.g. Flake, Basalt, Cedar) when it spawns. Names are never reused in the same world.
Two models with clearly separated jobs:
src/planner.mjs): a full language model that turns what people say into a typed task, reviews progress, picks the next task from the persona and long-term goal, and writes every chat reply. It runs through the host you already use, so no extra key is needed:
claude-code-acp driving your installed claude) with Opus 5.5codex mcp-server (codex / codex-reply threads) with GPT-6 AstraANTHROPIC_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY)
One persistent session per agent, so it remembers the conversation.src/jev.mjs): TypeSafe's choice model. Once a second it picks one concrete action from a menu built from what the agent can see. It never sees free text.player chat / dashboard / MCP text ──▶ planner ──▶ TaskSpec {kind, items, recipient, location, entity, until} + reply
│
world memory ◀── observe ──▶ action menu ──▶ JEV picks one ──▶ Mineflayer executes (bounded)
│
predicates verify completion (inventory / delivered / arrived / killed / built)
planner reviews "judged"/"ongoing" tasks, budgets and repeated failures
src/tasks.mjs): completion is verified by the game state, not declared by a model. items (inventory), delivered (hand-over events), arrived (distance), killed, built, ongoing (follow/guard), judged (planner reviews it). Item matches are exact ids, globs (*_log) or categories (food, tool, building…) resolved from the game's own registry.src/actions.mjs): for "make a stone pickaxe" the missing chain (logs → planks → table → sticks → wooden pickaxe → cobblestone) is worked out from Minecraft's recipe data and shown to JEV as the next step.src/memory.mjs): last-seen player positions, known tables/furnaces/chests/beds/ores, visited areas, home. Every action can target something out of view ("walk to where satuke was last seen", "go back to the furnace").Cedar <anything>, all <anything>, or a whisper. The planner decides whether it is a task, a goal, a persona change, a stop/resume, or just a question, and answers in character and honestly.Requirements: Node 20+, a TypeSafe (JEV) key, and a planner: Claude Code (logged in) or Codex (logged in) on the same machine, or an API key. To run worlds locally you also need Java: 21+ for Minecraft 1.20.5 and later, 17 for 1.17–1.20.4.
git clone git@github.com:xatuke/herobrine.git && cd herobrine
npm install
npm link # puts `herobrine` on your PATH (optional)
herobrine config set key <TYPESAFE_KEY> # or: config set key-file /path/to/keyfile
herobrine up --world play --difficulty peaceful # daemon + world (asks you to accept the Minecraft EULA)
herobrine spawn --world play --persona "a friendly survival companion" --goal "get us iron gear" --owner YourName
herobrine tell Cedar "bring me 5 logs" # planner interprets it, agent replies
herobrine chat Cedar # interactive conversation
herobrine status # everything at a glance
herobrine logs Cedar -f # follow task / chat / planner events
herobrine actions Cedar # the menu JEV is choosing from right now
herobrine cmd play "time set day" # server console
herobrine down # stop agents, worlds and the daemon
herobrine is a thin client of the local HTTP API (http://127.0.0.1:3600, also the dashboard). herobrine up starts a daemon that runs the same core as the MCP server; if Claude Code already has the MCP open, the CLI talks to that instead.
claude mcp add herobrine -e TYPESAFE_API_KEY=your_key -- node /absolute/path/to/herobrine/src/server.mjs
~/.codex/config.toml)[mcp_servers.herobrine]
command = "node"
args = ["/absolute/path/to/herobrine/src/server.mjs"]
env = { TYPESAFE_API_KEY = "your_key" }
tool_timeout_sec = 300 # first start_server downloads the jar and generates a world
TYPESAFE_KEY_FILE=/path/to/keyfile or herobrine config set key ... work instead of putting the key in the config. The key stays in the server process and is never logged.
codex mcp-server instead).Just talk to Claude or Codex:
Start a peaceful survival world and spawn two agents. One should be my bodyguard; the other should get us iron tools.
Tell Cedar to bring me 10 logs.
Make Flake act like a lazy farmer who complains a lot.
Watching: herobrine status, herobrine logs <agent> -f, or open the dashboard at http://127.0.0.1:3600 (or ask for open_dashboard). It shows each agent's live 3D view, persona, goals, current task and action, next prerequisite, inventory and recent results, plus a box to send it instructions. You can also join the world with Minecraft Java at the same version: Multiplayer → Direct Connect → localhost:25565. Managed servers run in offline mode.
| Tool | Purpose |
|---|---|
start_server / stop_server / list_servers / server_logs / server_command | Run local vanilla servers (needs accept_eula: true after the user agrees to the Minecraft EULA) |
spawn_agent | Join a managed server, or any offline-mode server or LAN world by host/port, with persona/goal/task |
instruct_agent | text in the user's words (planner interprets, replies in chat) and/or structured persona, long_term_goal, task (TaskSpec), owner for one agent or all |
planner_status | Active planner backend/model, call stats, and the TaskSpec schema |
agent_status, agent_events, read_chat | See what agents are doing and what players said |
pause_agent / resume_agent / stop_agent | Control |
agent_say | Say something in game chat through an agent |
list_actions / run_action | See the current action menu, or run one step directly without JEV |
open_dashboard | Get the dashboard URL |
| Env | Default | |
|---|---|---|
TYPESAFE_API_KEY / TYPESAFE_KEY_FILE | — | Your JEV key (required) |
TYPESAFE_MODEL | jev-latest | |
PLANNER | auto | claude, codex, api or none. Auto: Claude when launched by Claude Code, else Codex if logged in, else Claude if installed, else API key |
PLANNER_MODEL | claude-opus-5-5 / gpt-6-astra | Planner model for the chosen backend |
CLAUDE_CODE_EXECUTABLE | claude on PATH | Claude binary the ACP adapter drives |
MCP_MINECRAFT_HOME | ~/.minecraft-jev-mcp | Server jars, worlds, name registry, agent logs |
DASHBOARD_PORT | 3600 | |
VIEWER_BASE_PORT | 3601 | One 3D-viewer port per agent |
VIEWER=0 | on | Turns off the 3D views |
MINECRAFT_JAVA | auto | Java binary for managed servers |
~/.minecraft-jev-mcp/config.json (written by herobrine config set …) can hold typesafeApiKey / typesafeKeyFile, planner and plannerModel; environment variables override it. Agent logs (every JEV decision and result) are written to ~/.minecraft-jev-mcp/logs/<name>.jsonl. Performance and cost numbers: BENCHMARKS.md.
2 commits
JavaScript
100.0%
Minecraft agents that do whatever you ask. Each agent is a real player (Mineflayer) in a vanilla world; TypeSafe's JEV model picks every action it takes, and a planner model (Claude Opus 5.5 or GPT-6 Astra, on the subscription you already have) understands what you say and speaks for it.
Use it two ways:
herobrine up --world play, herobrine spawn --persona "my bodyguard", herobrine tell Cedar "bring me 5 logs".Both drive the same core; the CLI also works against the MCP instance while Claude Code has it open.
Agents have no fixed roles. Each one has three free-text fields, and the user can change any of them at any time:
| Field | Examples |
|---|---|
| persona: who to be and how to behave | "my bodyguard", "a chill builder who plays alongside me", "a grumpy dwarf miner who never leaves the caves" |
| long_term_goal: an objective it works toward over time | "get us full iron gear", "build a base by the river" |
| task: what to do right now | "collect 10 logs", "make a stone pickaxe", "come here", "bring me 5 cobblestone" |
With no task, the agent picks its own next short-term task based on its persona and long-term goal. Tasks end as done or stuck.
Each agent gets a short single-word Minecraft-style name (e.g. Flake, Basalt, Cedar) when it spawns. Names are never reused in the same world.
Two models with clearly separated jobs:
src/planner.mjs): a full language model that turns what people say into a typed task, reviews progress, picks the next task from the persona and long-term goal, and writes every chat reply. It runs through the host you already use, so no extra key is needed:
claude-code-acp driving your installed claude) with Opus 5.5codex mcp-server (codex / codex-reply threads) with GPT-6 AstraANTHROPIC_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY)
One persistent session per agent, so it remembers the conversation.src/jev.mjs): TypeSafe's choice model. Once a second it picks one concrete action from a menu built from what the agent can see. It never sees free text.player chat / dashboard / MCP text ──▶ planner ──▶ TaskSpec {kind, items, recipient, location, entity, until} + reply
│
world memory ◀── observe ──▶ action menu ──▶ JEV picks one ──▶ Mineflayer executes (bounded)
│
predicates verify completion (inventory / delivered / arrived / killed / built)
planner reviews "judged"/"ongoing" tasks, budgets and repeated failures
src/tasks.mjs): completion is verified by the game state, not declared by a model. items (inventory), delivered (hand-over events), arrived (distance), killed, built, ongoing (follow/guard), judged (planner reviews it). Item matches are exact ids, globs (*_log) or categories (food, tool, building…) resolved from the game's own registry.src/actions.mjs): for "make a stone pickaxe" the missing chain (logs → planks → table → sticks → wooden pickaxe → cobblestone) is worked out from Minecraft's recipe data and shown to JEV as the next step.src/memory.mjs): last-seen player positions, known tables/furnaces/chests/beds/ores, visited areas, home. Every action can target something out of view ("walk to where satuke was last seen", "go back to the furnace").Cedar <anything>, all <anything>, or a whisper. The planner decides whether it is a task, a goal, a persona change, a stop/resume, or just a question, and answers in character and honestly.Requirements: Node 20+, a TypeSafe (JEV) key, and a planner: Claude Code (logged in) or Codex (logged in) on the same machine, or an API key. To run worlds locally you also need Java: 21+ for Minecraft 1.20.5 and later, 17 for 1.17–1.20.4.
git clone git@github.com:xatuke/herobrine.git && cd herobrine
npm install
npm link # puts `herobrine` on your PATH (optional)
herobrine config set key <TYPESAFE_KEY> # or: config set key-file /path/to/keyfile
herobrine up --world play --difficulty peaceful # daemon + world (asks you to accept the Minecraft EULA)
herobrine spawn --world play --persona "a friendly survival companion" --goal "get us iron gear" --owner YourName
herobrine tell Cedar "bring me 5 logs" # planner interprets it, agent replies
herobrine chat Cedar # interactive conversation
herobrine status # everything at a glance
herobrine logs Cedar -f # follow task / chat / planner events
herobrine actions Cedar # the menu JEV is choosing from right now
herobrine cmd play "time set day" # server console
herobrine down # stop agents, worlds and the daemon
herobrine is a thin client of the local HTTP API (http://127.0.0.1:3600, also the dashboard). herobrine up starts a daemon that runs the same core as the MCP server; if Claude Code already has the MCP open, the CLI talks to that instead.
claude mcp add herobrine -e TYPESAFE_API_KEY=your_key -- node /absolute/path/to/herobrine/src/server.mjs
~/.codex/config.toml)[mcp_servers.herobrine]
command = "node"
args = ["/absolute/path/to/herobrine/src/server.mjs"]
env = { TYPESAFE_API_KEY = "your_key" }
tool_timeout_sec = 300 # first start_server downloads the jar and generates a world
TYPESAFE_KEY_FILE=/path/to/keyfile or herobrine config set key ... work instead of putting the key in the config. The key stays in the server process and is never logged.
codex mcp-server instead).Just talk to Claude or Codex:
Start a peaceful survival world and spawn two agents. One should be my bodyguard; the other should get us iron tools.
Tell Cedar to bring me 10 logs.
Make Flake act like a lazy farmer who complains a lot.
Watching: herobrine status, herobrine logs <agent> -f, or open the dashboard at http://127.0.0.1:3600 (or ask for open_dashboard). It shows each agent's live 3D view, persona, goals, current task and action, next prerequisite, inventory and recent results, plus a box to send it instructions. You can also join the world with Minecraft Java at the same version: Multiplayer → Direct Connect → localhost:25565. Managed servers run in offline mode.
| Tool | Purpose |
|---|---|
start_server / stop_server / list_servers / server_logs / server_command | Run local vanilla servers (needs accept_eula: true after the user agrees to the Minecraft EULA) |
spawn_agent | Join a managed server, or any offline-mode server or LAN world by host/port, with persona/goal/task |
instruct_agent | text in the user's words (planner interprets, replies in chat) and/or structured persona, long_term_goal, task (TaskSpec), owner for one agent or all |
planner_status | Active planner backend/model, call stats, and the TaskSpec schema |
agent_status, agent_events, read_chat | See what agents are doing and what players said |
pause_agent / resume_agent / stop_agent | Control |
agent_say | Say something in game chat through an agent |
list_actions / run_action | See the current action menu, or run one step directly without JEV |
open_dashboard | Get the dashboard URL |
| Env | Default | |
|---|---|---|
TYPESAFE_API_KEY / TYPESAFE_KEY_FILE | — | Your JEV key (required) |
TYPESAFE_MODEL | jev-latest | |
PLANNER | auto | claude, codex, api or none. Auto: Claude when launched by Claude Code, else Codex if logged in, else Claude if installed, else API key |
PLANNER_MODEL | claude-opus-5-5 / gpt-6-astra | Planner model for the chosen backend |
CLAUDE_CODE_EXECUTABLE | claude on PATH | Claude binary the ACP adapter drives |
MCP_MINECRAFT_HOME | ~/.minecraft-jev-mcp | Server jars, worlds, name registry, agent logs |
DASHBOARD_PORT | 3600 | |
VIEWER_BASE_PORT | 3601 | One 3D-viewer port per agent |
VIEWER=0 | on | Turns off the 3D views |
MINECRAFT_JAVA | auto | Java binary for managed servers |
~/.minecraft-jev-mcp/config.json (written by herobrine config set …) can hold typesafeApiKey / typesafeKeyFile, planner and plannerModel; environment variables override it. Agent logs (every JEV decision and result) are written to ~/.minecraft-jev-mcp/logs/<name>.jsonl. Performance and cost numbers: BENCHMARKS.md.
2 commits
JavaScript
100.0%