🧩 HyperToken

A game engine where the entire state is a conflict-free replicated data type (CRDT).

Deterministic replay. Serverless multiplayer. Forkable worlds. Built on Automerge for distributed consensus, with optional Rust→WASM acceleration for hot paths. Games, collaborative tools, marketplaces — any multi-user app where state must converge.

Showcase:

Play Watershed β€” a real time territory game.
Play Cuttle β€” a card combat game.
Play Blackjack - a card counting game.

Table of Contents

What This Gets You

CapabilityHow
Serverless multiplayerCRDTs sync state across peers without a central server
Perfect replayEvery action recorded with actor and timestamp
Forkable worldsSnapshot state, explore alternatives, compare outcomes
Offline-firstPeers diverge safely, converge mathematically
PersistenceSave and resume games with IndexedDB or filesystem adapters
Browser-readyOne command bundles any game for the browser

How It Compares

Traditional EngineBlockchain GameRaw CRDT (Automerge/Yjs)HyperToken
MultiplayerServer authoritativeOn-chain consensusManual networkingP2P CRDT sync, built-in
CostMonthly hostingGas fees per actionRelay onlyMinimal β€” just a relay
ConflictsLast-write-winsConsensus delayMathematical mergeMathematical merge
OfflineDisconnectedCannot actDiverge and mergeDiverge and merge safely
HistoryServer logsOn-chain eventsChange logPerfect replay + provenance
ForkableManual snapshotsImpossibleManual clone/mergeFork, diverge, merge back
AbstractionsGame objectsSmart contractsNone β€” raw documentsTokens, agents, stacks, spaces

Try It

git clone https://git.carpocratian.org/sibyl/hypertoken
cd hypertoken
npm install && npm run build

# Play Watershed in the browser
npm run relay              # Terminal 1: start relay
npm run watershed:web     # Terminal 2: build + serve
# Open http://localhost:8080 in two tabs
# Play Blackjack
npm run blackjack

# Play Cuttle
npm run cuttle

How It Works

Tokens Compose With Provenance

const enchantedSword = engine.dispatch("token:merge", {
  tokens: [sword, fireEnchantment],
  resultProperties: { label: "Flaming Sword" }
});
// enchantedSword._mergedFrom = [sword.id, fireEnchantment.id]

const pieces = engine.dispatch("token:split", {
  token: goldPile,
  count: 3
});
// pieces[0]._splitFrom = goldPile.id

State Syncs Automatically

const host = new Engine();
host.connect("ws://relay.local:8080");

const client = new Engine();
client.connect("ws://relay.local:8080");

// Both make changes β†’ CRDTs merge β†’ identical final state
// No conflict resolution code. It just works.

Persistence

const engine = new Engine();

// Use storage adapter (IndexedDB in browser,
// FilesystemAdapter in Node.js)
engine.useStorage(new IndexedDBAdapter());

// Save state
await engine.persist("my-game-session");

// Resume later β€” even after closing the browser
await engine.resume("my-game-session");

Forkable Worlds

// Fork the engine β€” divergent branch with new actor ID
const fork = engine.fork();

// Explore timeline A
fork.dispatch('token:merge', { tokens: [sword, fireEnchantment] });
const outcomeA = fork.getState();

// Merge changes back β€” CRDT conflict resolution
engine.mergeFrom(fork);
const outcomeB = engine.getState();

What's Inside