idk: Automating Storage in Minecraft with Bots, Shulkers, and a Web UI
I built idk because rummaging through chest halls on a multiplayer server was slow and boring. The plan: wire up a Mineflayer bot, a small web app, and a pile of shulker boxes so anyone could dump or request items without remembering what is in which chest.
Why a web UI?
In-game signs and books sounded cute until I realised no one wants to scroll through page after page of chest locations. A browser front-end felt obvious once I started sketching flows. The Svelte app lists everything in storage and lets players search for "mending books" or "stone," then sends an HTTP request to the bot service. From there the bot heads to the right chest, grabs the stack, and drops it into a delivery barrel near spawn. Deposits work the same in reverse.
Moving between aisles
Storage is just rows of chests stacked six high, laid out so the bot can hop between aisles without bumping into redstone. Mineflayer's default pathing was close but not reliable, so I added a BFS layer over a trimmed voxel map. I cache reachable blocks, reject jumps that would clip trapdoor hinges, and backtrack when a player blocks the aisle mid-run.
function findPath(start, target) {
const queue = [start];
const visited = new Set([start.key]);
while (queue.length) {
const current = queue.shift();
if (current.key === target.key) return reconstructPath(current);
for (const neighbor of neighbors(current)) {
if (!visited.has(neighbor.key) && !neighbor.isBlocked) {
neighbor.prev = current;
visited.add(neighbor.key);
queue.push(neighbor);
}
}
}
return null;
}
Keeping track of every stack
I keep state in a SQLite database behind the web API. Each row stores the item ID, item count, the chest coordinate, and whether that slot contains a shulker box. On deposit, the bot updates the record; on withdrawal, the web UI shows the new count via server-sent events. Watching the numbers tick down while the bot jogs back with your netherite scraps is the best part.
Shulker boxes, the fun part
Bulk moves needed smarter logic. The bot inspects a shulker before moving it, spreads the contents into temporary chests, and packs it back together when done. For mixed stacks or half-full boxes I run a small planner: keep items in place, merge, or crack open another shulker. It is a lot of branching for a block that looks like a decorative cube, but it stops the system from filling with half-used containers.
Inventory optimizer
Keeping rows of chests tidy meant grading every layout and shuffling stacks into better homes. A tiny A* search runs over the live database snapshot. I score each move by how many slots stay occupied and weight the search toward moves that tuck matching items together inside shulkers. In the heuristic I subtract a bit of cost for shulker slots and zero it out for boxes that end up completely full, so loose stacks cluster instead of scattering across the hall.
export async function optimize_inventory() {
const before = await db.get_inventory_items();
console.log("starting cost", inventory_cost(before));
const moves = a_star(before, 100);
const after = helper.apply_moves(types.ChestType.Inventory, before, moves);
console.log("recommended", moves, inventory_cost(after));
await db.add_job(types.JobType.Move, moves);
parentPort?.postMessage("done");
}
Stack choices
I wrote the bot service in TypeScript and the dashboard in Svelte: type safety on both sides, and a lightweight UI. Mineflayer handles the Minecraft protocol, Express exposes the API, and a small WebSocket layer streams status updates to whoever requested the items. Building it forced me to learn far more about synchronising game state, dealing with tick timing, and shipping real tooling for a sandbox game.
What I would still tweak
Speed is the obvious next knob to turn—either by caching more routes or by dedicating a second bot to run parallel jobs. Bulk exports for building projects and a smarter sorter for mixed shulkers are also on the list. Even without them, idk has turned storage duty into something I look forward to watching instead of doing by hand.