npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

embark-ai

v1.0.6

Published

Autonomous Minecraft agent powered by Featherless AI or Ollama

Readme

embark-ai — Autonomous Minecraft Agent

A Minecraft bot that thinks, survives, defends itself, and completes multi-step tasks. Built on Mineflayer + Featherless AI (cloud) or Ollama (local LLM). No TypeScript, no databases.


What Ember does

  • Talks naturally — LLM interprets intent: "build me a house" chains wood-gathering → plank-crafting → construction automatically
  • Has a real personality — stubborn, witty, refuses nonsense, holds grudges
  • Defends itself — attacks back when hit, escalates with insults, equips best weapon
  • Survives autonomously — manages hunger, energy, hazard avoidance, water escape, falling
  • Multi-step planning — single requests like build a house or mine 5 iron ore chain multiple tasks internally
  • Grounded perception — inventory, nearby blocks, mobs, drops read directly from Mineflayer APIs (zero hallucination)
  • Resilience architecture — position-guard, desync recovery, task watchdogs, supervised restart with backoff
  • Reports everything in chat — if a task fails, you see the reason in-game
<player> build me a house
<Ember>  Starting house. Will gather and craft if needed.
<Ember>  Got wood. Making planks. Have 32 planks. Building now.
<Ember>  House done!


<player> mine 5 iron_ore
<Ember>  On it.
<Ember>  Mined 5 iron_ore.

Architecture

Request pipeline

chat message
     │
     ├─► detectInsult()           anger++ / attack at threshold
     │
     ▼
classifyIntent()                  regex pre-filter (follow / build / attack / ...)
     │
     ▼
evaluateSurvival()                short-circuit if critically exhausted
     │
     ▼
buildGroundedState()              real inventory + blocks + mobs + drops + anger
     │                            only verified Mineflayer sensor data
     ▼
queryLLM()                        grounded prompt → strict JSON output
     │                            Featherless AI or Ollama (same code path)
     ▼
validateLLMOutput()               schema check → safeDefault() on failure
     │
     ▼
executeAction()                   LLM never controls movement directly
     │                            routes to runTask() → pathfinder / pvp / craft
     ▼
errors → bot.chat()               every failure surfaced in-game

Background loops (always running)

| Loop | Interval | What it does | |------|----------|-------------| | entityHurt listener | event | identifies attacker, fights back | | Threat loop | 2.5 s | auto-engages hostile mobs within 10 blocks | | Anger decay | 1 s | insults +1, hits +4, decays 0.05/s; attacks at level 5 | | State loop | 1 s | energy/hunger drain, autonomous goal selection | | Agent loop | 250 ms | look-at player, follow, water survival | | Environment perception | 3 s | scans 6-block radius for hazards, cliff edges, enclosures | | physicsTick guard | ~50 ms | restores NaN position from cache if a hit corrupts it |

Resilience system

Ember has a layered resilience architecture that keeps her running under game physics edge cases, server desync, and combat:

| Component | File | Role | |-----------|------|------| | positionGuard | positionGuard.js | Detects NaN position caused by knockback, restores from cache on every physics tick (~50 ms). Prevents the ~6 s freeze-on-hit. | | entityLiveness | entityLiveness.js | 5-state monitor: LIVE_VALID → TRANSIENT_INVALID → STALE_USING_CACHE → RECOVERING → FATAL. Declares desync in ~5–8 s. | | recoveryEngine | recoveryEngine.js | Single arbiter for all recovery. Maps symptoms (DESYNC, STUCK, CRITICAL_HP, …) to escalation classes. Sole owner of bot.quit(). | | fatalDesyncRecovery | fatalDesyncRecovery.js | Independent 2 s poller; reports DESYNC to recoveryEngine when entity is fatally stale. | | healthIntegrityWatchdog | healthIntegrityWatchdog.js | Detects HP drops not caught by the event stream. | | movementController | movementController.js | Sole writer to bot.pathfinder. Token-based ownership prevents multiple tasks from racing on movement. | | goalRegistry | goalRegistry.js | Sole mutator of state.goal. All goal changes go through setGoal(). | | damagePipeline | damagePipeline.js | Single damage-reaction authority. Classifies and routes player hits, mob attacks, environmental damage. Staging flag prevents health-handler / damage-window races. | | locomotionRecovery | locomotionRecovery.js | Raw-control-state escape sequences for physically stuck situations. Separate from desync recovery (which only reconnects). | | environmentPerception | environmentPerception.js | Scans surrounding blocks for lava, water, cliff edges, enclosed spaces, traversability. Returns { valid: false } on NaN position instead of silently reporting "all clear". | | botSupervisor | botSupervisor.js | Wraps the bot process with exit-reason classification, per-class exponential backoff, restart storm protection (≥5 restarts in 10 min → halt). |

LLM integration

Both backends use the same llm.js code path. Ollama mode overrides FEATHERLESS_URL to point at Ollama's OpenAI-compatible endpoint.

Featherless AI  →  api.featherless.ai/v1/chat/completions  (cloud, 3000+ models)
Ollama          →  localhost:11434/v1/chat/completions      (local, private)

LLM output schema:

{
  "decision": "accept | reject | delay",
  "reason":   "...",
  "action":   "follow | stop | explore | gather_wood | craft_planks | go_to | remember_here |
               attack_mobs | attack_player | collect_items | craft | place_block | mine_block |
               eat_food | flee | escape | build_house_smart | none",
  "say":      "...",
  "target":   "..."
}

Invalid or missing output falls back to safeDefault(intent). The LLM picks an action label — it never touches movement or pathfinder directly.


Stack

| Layer | Technology | |-------|-----------| | Bot framework | Mineflayer | | Pathfinding | mineflayer-pathfinder | | Combat | mineflayer-pvp | | Cloud LLM | Featherless AI — OpenAI-compatible API, 3,000+ models | | Local LLM | Ollama — runs models locally, no GPU required for small models | | TUI | blessed | | Minecraft server | Vanilla Java Edition 1.21.4 | | Runtime | Node.js 18+ | | Language | CommonJS JavaScript — no TypeScript, no databases |


System Requirements

| Requirement | Minimum | |-------------|---------| | Node.js | 18+ | | Java | 21+ (for the Minecraft server) | | RAM | 4 GB (bot + server); 8 GB recommended | | OS | macOS, Linux (Windows via WSL) | | Disk | ~1 GB for server + world data |

For Ollama (local LLM):

| RAM available | Recommended model | Download size | |---------------|------------------|---------------| | < 4 GB | llama3.2:1b | 1.3 GB | | 4–8 GB | llama3.2 | 2.0 GB | | 16 GB | qwen2.5-coder:14b | 9 GB | | 32 GB+ | qwen2.5:32b | 20 GB |

For Featherless AI (cloud):

  • API key from featherless.ai (format: rc_xxx)
  • No GPU, no local model download required

Setup

1. Install dependencies

npm install                        # TUI (blessed)
cd mc-server/bot && npm install    # Bot (mineflayer, pathfinder, pvp)
cd ../..

2. Java 21+

# macOS
brew install openjdk@21

# Linux (Debian/Ubuntu)
sudo apt install openjdk-21-jdk

3. Minecraft server jar

Download the Minecraft Java Edition 1.21.4 server jar from minecraft.net/download/server and place it at:

mc-server/server.jar

4. Run

npm start
# or: node tui.js

On first launch the onboarding wizard opens automatically:

  1. Choose Ollama (local) or Featherless API (cloud)
  2. Ollama path — detects installation; if missing, shows the install command; reads your RAM and recommends a model; walks through ollama pull <model>
  3. Featherless path — prompts for API key, then shows a model picker
  4. Server check — verifies server.jar is present

Config is saved to .ember-config.json (gitignored). Press [8] in the TUI at any time to change backend, model, or API key.


TUI

┌─ embark-ai ─ ● Server localhost:25565 ─ Bots: ● Ember (llama3.2, 142s) ────┐
├─ Bot Status ────────────────────┬─ Actions ──────────────────────────────────┤
│ Ember                           │ AI: Ollama (llama3.2)                      │
│                                 │                                            │
│ HP:    ████████████░░ 18.0/20  │ [1] Start server                          │
│ Food:  ████████████████ 20/20  │ [2] Stop server                           │
│ Goal:  following               │ [3] Spawn bot                             │
│ Pos:   (12, 64, -8)            │ [4] Stop bot                              │
│ Anger: none                    │ [5] Restart bot                           │
│                                 │ [6] World settings                        │
│ Inventory:                      │ [7] List models                           │
│   oak_log x3, stick x4         │ [8] Reconfigure                           │
│                                 │ [s] Switch active bot                     │
├─ Live Log ──────────────────────┤                                            │
│ 14:23:01 [info] spawn_ok       │ ↑↓   scroll log                           │
│ 14:23:05 [info] task_start     │ Tab  switch focus                         │
│   action=follow                │ r    refresh                              │
│ ...                            │ q    quit                                 │
└─────────────────────────────────┴────────────────────────────────────────────┘

| Key | Action | |-----|--------| | 1 | Start Minecraft server | | 2 | Stop Minecraft server | | 3 | Spawn bot (choose name + model) | | 4 | Stop a bot | | 5 | Restart a bot (clean chain) | | 6 | World settings — gamemode, difficulty, pvp, seed, view distance, … | | 7 | List models (installed Ollama models or Featherless catalog) | | 8 | Re-run onboarding (change AI backend, model, or API key) | | s | Switch which bot the status panel shows | | ↑↓ / PgUp/Dn | Scroll the live log | | Tab | Cycle panel focus | | r | Manual refresh | | q / Ctrl+C | Quit — stops all managed processes cleanly |

Multiple bots with different names and models can run simultaneously.


In-Game Commands

Speak naturally — the LLM interprets intent. Direct commands work too:

| Say | What happens | |-----|-------------| | follow me | Pathfinds to you, follows continuously | | stop | Stops all movement and tasks | | explore | Walks around autonomously | | build me a house | Chains gather wood → craft planks → place 70 blocks | | get some wood | Finds and chops the nearest log | | make planks | Converts logs in inventory to planks | | craft a wooden_pickaxe | Looks up recipe, crafts it (auto-makes sticks if needed) | | mine 5 iron_ore | Mines that block type N times, auto-equips best tool | | place a crafting_table | Places named block from inventory | | eat something | Eats food from inventory | | kill that zombie | Equips best weapon, engages nearest hostile mob | | pick up those items | Walks to and collects nearby dropped items | | go to spawn | Navigates to a saved location by name | | remember this place as base | Saves current coordinates | | where are you | Reports real coordinates | | what do you have | Reports real inventory | | flee | Runs away from the nearest hostile mob | | escape / you're stuck | Pillars up or digs to surface | | (hit Ember) | Anger +4; retaliates at threshold | | (insult Ember) | Anger +1; warns at 3, attacks at 5 |


File Structure

embark-ai/
├── tui.js                       TUI control panel — server + bot management + onboarding
├── botSupervisor.js             Supervised bot lifecycle: backoff, storm protection
├── package.json
└── mc-server/
    ├── server.jar               (gitignored — download separately)
    ├── server.properties
    └── bot/
        ├── bot.js               Main loop, action execution, agent/state/threat loops
        ├── engine.js            Intent classifier, LLM validation, anger/insult detection
        ├── state.js             buildGroundedState() — Mineflayer sensor data only
        ├── llm.js               Featherless AI / Ollama integration (same code path)
        ├── memory.js            Persistent memory — locations, events, knowledge
        ├── logger.js            Structured JSONL logger → events.jsonl
        ├── env.js               Environment variable loader
        ├── safeMineflayer.js    Safe wrappers: safeDig, safeCraft, safeAttack, …
        ├── movementController.js  Token-owned pathfinder writes
        ├── goalRegistry.js      Sole mutator of state.goal
        ├── entityLiveness.js    5-state entity validity monitor
        ├── positionGuard.js     physicsTick NaN position repair
        ├── recoveryEngine.js    Single recovery arbiter; sole bot.quit() owner
        ├── fatalDesyncRecovery.js  Desync reporter (independent 2 s poll)
        ├── healthIntegrityWatchdog.js  HP integrity watchdog
        ├── damagePipeline.js    Unified damage classification and reaction
        ├── tasks.js             All 16 task implementations
        ├── environmentPerception.js  Spatial scan — hazards, traversability
        ├── locomotionRecovery.js     Physical escape sequences
        └── package.json

Design Principles

Anti-hallucinationbuildGroundedState() returns only what bot.inventory.items(), bot.findBlock(), and bot.entities actually report. The LLM is explicitly told not to invent facts.

LLM picks labels, code executes — The LLM output is an action label. executeAction() is the only path to pathfinder, pvp, or crafting. Invalid LLM output falls back to safeDefault(intent).

Single authority per concern — One module owns each resource: movementController for pathfinder, goalRegistry for state.goal, recoveryEngine for bot.quit(), damagePipeline for damage reactions.

Token discipline — Long-running async tasks mint a Symbol ownership token before starting. Every deferred callback checks isOwner(myToken) before acting, so a preempted task's callbacks silently no-op instead of racing with the new task.

Survival is hardcoded — Energy drain, hunger, water survival, threat reaction, and damage recovery live entirely outside the LLM path. The LLM can be wrong; the code enforces physical reality.

Structured logging — All events written as JSONL to events.jsonl with correlation IDs. The TUI tails this file live at 500 ms intervals.

Errors surface to the player — Every task body is wrapped in try/catch and calls bot.chat("Error: ...").


Environment Variables

Config is normally handled through TUI onboarding (saved to .ember-config.json). These env vars override it:

| Variable | Default | Description | |----------|---------|-------------| | BOT_NAME | Ember | In-game bot name | | SERVER_HOST | localhost | Minecraft server host | | SERVER_PORT | 25565 | Minecraft server port | | MC_VERSION | 1.21.4 | Minecraft protocol version | | FEATHERLESS_API_KEY | — | Featherless key (rc_xxx) or ollama for local mode | | FEATHERLESS_MODEL | — | Model ID | | FEATHERLESS_URL | Featherless endpoint | Set to http://localhost:11434/v1/chat/completions for Ollama |


License

ISC