Just the known world
The shared renderer uses public perception. Hidden rooms stay hidden. A beautiful map never invents knowledge.
Forty years of dungeon intelligence, a lovingly drawn world, and an interface that belongs to you.
Drop in the viewer. Supply a public observation. Build a spectator screen, a replay, or a home for your autonomous adventurer.
<neohack-world src="https://neohack.dev/dashboard?run=RUN_ID" autoplay speed="4" controls> </neohack-world>
Shadow DOM · Pixel renderer · Read only by default
One module registers the component and exports the same Neonethack and Game API used by the app. Styles live inside its shadow root; the selected runtime artwork is included in the module.
This showcase never starts a game. The entrance is decorative. Replays display captured observations without spending turns or loading an engine.
// <script type="module" src="https://neohack.dev/component/neohack.js"></script> import Nethack from '/component/neohack.js'; const world = document.querySelector('neohack-world'); world.addEventListener('frame', ({ detail }) => { console.log(detail.observation.turn); }); // Existing public API + your owned transport. const api = world.connect(transport, { writable: true }); const game = await api.create({ name: 'Ada', seed: 42 }); world.snapshot = game.state; await game.move('north');
world.addEventListener('message', ({ data }) => {
console.log(data.id, data.result ?? data.error);
});
world.postMessage({
jsonrpc: '2.0', id: 'discover',
method: 'tools/list'
});
world.postMessage({
jsonrpc: '2.0', id: 'observe',
method: 'tools/call',
params: {
name: 'neonethack_session_observe',
arguments: { sessionId: game.id }
}
});Discover generated tool schemas with tools/list. Call named operations with tools/call. Each reply keeps your correlation ID and the engine’s original response.
No transport means no engine tools. Read-only connections expose only read-only tools. Execution is an explicit host choice. Messages target this element, with no global window listener.
Call world.registerWebMcp() to register the connected tools with a supported browser’s model context. Call the returned dispose() when done.
The shared renderer uses public perception. Hidden rooms stay hidden. A beautiful map never invents knowledge.
src="https://neohack.dev/dashboard?run=RUN_ID" autoplay speed="4" controls loads a public ledger recording. Optional sound enables sound after a user gesture; loop repeats playback. Boolean attributes can use ="false" to disable them. Speed is 0.5–5×, default 4× (16 frames/second). You can also use loadReplay(frames), seek(index), play(250), and pause(). Also available as replay.* messages.
Use the same game API in the Ascender workshop. Edit a strategy, choose a character, and watch a real test run.