Repository navigation
v3.0.0
Upgrading from 2.x
- 3.0.0 is the release after 2.1.0. A 2.2 was prepared and never published; everything it carried
is in this release. Removing the chatbot factory is why this is a major version. - Node 22.14 or newer. 2.x asked for 22.12, but on Node 22.12 and 22.13 the database library
(better-sqlite3) crashes the process the first time it opens the database, with no message; 2.1.0
crashes the same way. 3.0 checks the version at start-up and says which Node to install. - The 2.x line is unmaintained. No 2.x release will be patched, and running one is not
recommended. 2.1.0 and the bot image it deploys (mojulo-bot0.5.1) have known security issues: an
open relay on deployed bots (/api/send-webhook), SSRF inupload_document_from_url, path
traversal in the Office-document parser, Fly credentials in the machine environment, dashboard DNS
rebinding and cross-site writes, a revoked delegate's dashboard session that outlives the
revocation, a delegate's dashboard session that holds the operator's authority, and an
update_sketchpatch that reaches the prototype chain
(SECURITY.md). Bots
already deployed from 2.x run on their own, on that image, until you take them down. - Unpinned installs move to 3.0 on their next start once 3.0.0 is npm
latest. A host that runs
npx -y mojulo(every config 2.xmojulo initwrote, the README's manual lines, and the Claude
plugin up to 2.0.1) installs 3.0.0 on its next start, whether or not the plugin was updated. The
3.0 plugin runsnpx -y mojulo@3.0.0; update it, and remove anymojulo initorclaude mcp add
registration beside it (two registrations run two servers). Exact pins and a global
npm i -g mojulostay on their version until you change them. The first start downloads about
79 MB (the package and its dependencies); if the host gives up, start Claude Code with
MCP_TIMEOUT=60000, or runnpx -y mojulo@3.0.0 --helponce in a terminal. Restart every host
afterwards so no 2.x server keeps running against the same~/.mojulo. - Saved provider keys become unreadable to 2.x. With
API_KEY_ENCRYPTION_KEYunset (the
default), the first time a 3.0 process reads saved keys (mojulo-config,listincluded;
mojulo init's key prompt; the dashboard's key settings;mint_solidvia:'prompt'without an
inlineapiKey), it re-encrypts every key a 2.x install saved, the Fly token included, under a
per-install key at$MOJULO_HOME/secret.key. 2.x cannot decrypt them after that; the change is
one way. Back upsecret.keytogether with the database: without it 3.0 cannot read the keys
either. - What left, and what it left behind. The chatbot factory is no longer part of mojulo as of 3.0
and is moving to its own project. Earlier 2.x versions that include it are unmaintained and have
known security issues. Its tools, packs and dashboard pages are not in 3.0; calling one of its
tools,mojulo install chatbotor anartifact_materializationcommit does nothing and answers
with that notice. Its tables (deployments,modular_sessions,mcp_jobs) and their rows, and the
packs/chatbotmarker, stay in~/.mojulo, inert: 3.0 does not use them, and you may delete them.
~/.mojulo/data/artifacts/holds each old bot's.envwith its provider key in plain text:
delete it. - Downloaded helpers and draft figure specs move out of the npx cache. 2.1.0 kept Chrome for
Testing, ffmpeg, gallery stills, turntable strips and draft figure specs inside its package folder;
3.0 keeps them under$MOJULO_HOME. An unpinned upgrade replaces that folder, so they are not
carried over; pending figure specs are lost unless another version's npx folder still holds them
(3.0 copies those across once). The browser (now build 154) is no longer fetched in the
background: with no browser installed, gallery thumbnails stay blank until one is available (an
installed one,MOJULO_CHROMIUM, or, outside the Claude plugin build, an explicit render's
download).
@puppeteer/browsers 3 has no proxy support, so a host behind an HTTP proxy setsMOJULO_CHROMIUM. - Other changes a 2.x setup can notice.
mojulo initchanges nothing without--yeswhen stdin is not a terminal: it prints its plan and
exits 2. With the Claude plugin installed it leaves Claude Code to the plugin.- The dashboard is its own package,
mojulo-ui(npx -y mojulo-ui);npx -y -p mojulo mojulo-ui
downloads the matching version on first use (MOJULO_UI_NO_FETCH=1refuses). It answers 403 to
aHostother than loopback,MOJULO_UI_HOSTor a name inMOJULO_UI_ALLOWED_HOSTS, and to a
cross-site write, so a LAN, proxy or tunnel setup needsMOJULO_UI_ALLOWED_HOSTS. mint_solidvia:'prompt'requiresprovider: nothing chooses the provider for you any more.
The key isapiKey, the saved key named byapiKeyId, or else your saved key for the provider
you name.- Exported World pages are self-contained by default again (
world.html, no third-party fetch);
cdn: truewritesworld.cdn.html, andworld.offline.htmlis no longer written. - Stored
floorplanandcondo-complexrows that relied on the old room defaults re-render
roomier, and the furnish pass doors sealed rooms, parks interior doors open against the wall and
moves wall pieces out of a door's way
(Room livability,
Furniture audit). chatbotoropsinMOJULO_PACKSis ignored, soMOJULO_PACKS=chatbotalone now leaves the
creative tools on.MOJULO_MCP_TELEMETRY=offstops only the local tool-call log, no longer the tool timeout, and
MOJULO_MCP_TOOL_TIMEOUT_MScan raise a tool's budget but not lower it. Render tools get 600 s.mojulo install creativeinstalls nothing (the creative pack always ships), and
mojulo install recallnow works from npm and npx. With the runtime already installed and the
search model missing, it fetches the model instead of reporting nothing to do.- A delegate (roles pack) signed in to the dashboard reads and no longer writes (below).
- A city minted from now on wears the round street kit (below); stored cities are unchanged, and
elements: { roundKit: false }keeps the block kit. - A material object whose
metalis a name ({ metal: 'steel', finish: 'brushed' }) is a metal
surface (below); besidebaseorpresetit is refused. The shelf's numericmetal: 1is
unchanged.
What 3.0 is
- A 3D compiler for agents. Your agent builds objects, walkable worlds and games by conversation
as small deterministic recipes on your machine, compiled back to the same geometry (byte for byte on
the same platform) and exported to STL / 3MF, glTF, OpenUSD, IFC4, self-contained HTML, Godot,
Blender, Unity and Unreal. The bot factory, which never fit that, is gone.
Determinism
- What "the same geometry" means. A recipe compiles to the same geometry every time: byte for byte
on the same platform (OS, CPU and Node version), and to within floating-point rounding on any other.
V8'sMathis not one function everywhere: its arm64 builds roundsin,cos,exp,atan2and the
rest differently from x64, and since Node 24Math.powand**call the platform's C library. An
embedded texture PNG can also differ in its compressed bytes between Node builds (Homebrew's Node links
a different zlib), never in its pixels. - 3.0's generators go further. The vegetation engine, terrain worlds, the anime head and hero, stores
and construction, metro and canal cities, the metro refacade and the Tian Tan Buddha take their
transcendental functions from a deterministic math module (fdlibm in plain double arithmetic), so their
pinned outputs are the same bytes on Linux and macOS, x64 and arm64, Node 22 and 24, and CI checks them
on every runner. The older helpers they reach switch to it only inside a 3.0 build, so nothing minted
with 2.x changes. A few older helpers still use the engine'sMath(specular shading, sRGB conversion,
some textures, roads, the metro World's walkers and cars).
Lean install
-
3.0.0 against the published 2.1.0, one method. A cold start with an empty npm cache and a
freshHOMEandMOJULO_HOME(npm exec --package=<tarball> -- mojulo) through a local registry
stand-in, timed from spawn to theinitializeanswer, on one macOS arm64 machine (M1 Max). Sizes
are decimal MB; the installed and downloaded rows include the package itself, and "downloaded" is
the unique tarballs plus the package metadata, estimated gzipped.2.1.0 3.0.0 npm tarball 31.2 MB 6.7 MB Unpacked package 121.7 MB 21.3 MB Installed, package and dependencies 539 MB, 426 packages 227 MB, 153 packages Downloaded on a cold start, package included about 182 MB about 79 MB Cold start to initialize, median (p90)12.7 s (15.7 s), 14 runs 4.5 s (4.6 s), 6 runs -
Machine caveat. The two timings come from separate sessions on a busy machine: 2.1.0 on
2026-09-27 (load average 3 to 12), 3.0.0 on 2026-09-30 (7 to 11). In the 3.0.0 session, runs of a
pre-release 3.0 candidate interleaved with the release's took a median 6.1 s: the release installs
one copy of sharp instead of two, 26 packages fewer. Trust the sizes more than the seconds, and
expect the real registry to be slower than the stand-in. npm also keeps the downloaded tarballs in
its cache, about 140 MB for 3.0.0. 2.1.0's package carried the dashboard build; 3.0.0's dashboard
ismojulo-ui(12.7 MB packed, 57.0 MB unpacked), fetched only when it is opened. -
The package never carries a local content pack. A tarball or
mojulo-uibuild made from a
checkout holding the operator-local mobile-suit content pack carried it; the package file list
leaves it out, a test fails any tarball carrying a gitignored file, and the dashboard build refuses
such a checkout. A clean install no longer prints warnings about that absent pack. -
What left the install: the dashboard build,
@swc/core,three, the dashboard-only libraries,
dotenv, and the chatbot factory'sofficeparserandpdf2json. puppeteer-core, archiver and
react load on first use, so the stdio server boots without them. Details:
docs/tech-requirements.md,
Lean cold start.
Security and consent
-
Saved provider keys are encrypted under a random per-install key (
$MOJULO_HOME/secret.key, mode
0600) instead of a constant in the source. The dashboard refuses DNS-rebinding and cross-site
requests.mint_solidvia:'prompt'never chooses the LLM provider for the caller:provideris
required, and the key isapiKey, the saved keyapiKeyIdnames, or the caller's saved key for
that provider. -
Chrome for Testing downloads only for an explicit render and says so (never under the Claude
plugin, below); headless Chromium keeps its sandbox (on Linux it falls back only on Chrome's
sandbox errors or as root); the ffmpeg download is SHA-256 pinned; everything mojulo writes lazily
lands under~/.mojulo. -
mojulo initneeds--yeswhen nobody is at a keyboard. "No telemetry" is now "no external
telemetry", with the local tool-call log described. Core has no Docker, Fly, GHCR, webhook or
uploaded-document code path.
(Security hardening,
Runtime footprint and consent) -
Revoking a delegate's key now ends their dashboard session on their next request. Before, the
dashboard checked only a session's signature and 7-day cookie expiry. A delegate (roles pack) whose
key was revoked withrevoke_role_key, had expired, or had its token epoch bumped could keep using
the dashboard until the cookie ran out, even though their MCP bearer had already stopped working.
Such a session now gets the same 401 on/api/*and redirect to/loginas no session, and with
the roles pack off a delegate session is refused outright. The dashboard middleware now runs on the
Node runtime so it can make this check. The operator's own session, installs with login off, and
installs without the roles pack make no database read. -
A delegate's dashboard session is read-only. No dashboard route checks a role, a grant or a
flag, so on 2.x a signed-in delegate held the operator's authority there, whatever the role
granted: deleting the operator's saved keys, writing an app's.envand starting the app, deleting
sketches. A live delegate session now reads pages and the API, and gets 403 (DELEGATE_READ_ONLY)
on every write and on the settings API. The roles pack's grants still bind the delegate's MCP key;
the operator's session is unchanged. -
sharp 0.35.5. The image library moves past high-severity advisories in its bundled libvips and
libheif (GHSA-f88m-g3jw-g9cj, GHSA-rgj7-g3m4-5g8c), andmojulo-uino longer carries the older copy
Next.js keeps fornext/image, which the dashboard never imports. An image submitted for a render
that does not decode is refused at submit. -
A patch cannot reach the prototype chain. An
update_sketchpatch path through__proto__or
constructor/prototypeset or deleted a property on every object in the server process until it
restarted. Such a path, or the same key in a set-by-id merge, now refuses by name.
Claude plugin and directory readiness
-
Every tool carries a
titleand behaviorannotations,initializenegotiates2025-06-18,
2025-03-26or2024-11-05, and the Claude plugin pinsnpx -y mojulo@3.0.0
(annotations,
disclosure). -
The Claude plugin build. When the Claude plugin starts mojulo, it leaves out the handoff tools
for AI image, voice and mesh generators. That covers the image-render and mesh handoffs, the voice
registers, sprite sheets, style presets, the skin op, the painted sketch kinds, the painted cover
title,forge_motion's scene and cel sources, the character-from-dream figure specs and a
figure'sdream_audit, and the image-driven catalysts. The vocab cards and catalysts it keeps are
served without their lines about those loops. It also leaves out the keyed
mint_solid via:'prompt'door (usevia:'packet') and every automatic download:- renders use a Chrome, Chromium, Edge or Brave you already have, or
MOJULO_CHROMIUM; - MP4 encodes use an ffmpeg you already have, or
MOJULO_FFMPEG; - the search model arrives only through
install recall.
Exported World and game pages are always self-contained there:
cdn: trueis ignored, and the
result says so. The host adapter cards are served without their image-generator and CDN lines, and
the MCP Apps preview is not offered. A call to a tool the plugin build leaves out answers in-band.
Installs from npm or a checkout are unchanged. - renders use a Chrome, Chromium, Edge or Brave you already have, or
-
The plugin listing. It is rewritten for 3.0 with three example prompts that work in the plugin
build, a table of what it installs, fetches, runs and writes, a privacy policy link, an "Upgrading
from 2.x" note, and an icon.
Hosts
- ChatGPT. Its own adapter card (
get_adapter({ id: 'chatgpt' })) and handoff profile, for
connected MCP and for a shell-enabled Work box. A separate ChatGPT skills package
(plugins/mojulo-chatgpt)
prefers connected MCP and otherwise sets up a pinned, workspace-local CLI in the box. Handoff notes
keep a file on the MCP server apart from a file in the session, and promise no attachment or inline
preview the session has not shown. Codex is no longer recognized by the bare OpenAI vendor name. - Meta Muse. A host profile and adapter card for the shell-only agent on its own persistent Linux
VM, wherenpx mojulo callis the whole surface andMOJULO_HOST=musenames its doors: pages leave
through its Artifacts, files through its Library. A bundle export's<ref>.courier.htmllists the
export's files underoutcomes/<ref>/, each with a Save where the viewer allows it, so one HTML page
can deliver any of them. A host profile
may name its own page words (pageVerb,pageTool,pageOpensIn), what its page door does with
inline scripts (inlinePage), and adrop-folderfile door. MOJULO_HOSTpicks the adapter card on the CLI, forget_adapter, catalyst composition and
recommendations, when no client identity says which host is calling. An explicit adapter id or a
recognized client still wins.- Recipe recovery.
create_sketchaccepts an exported world recipe and passes it through the same
validation and ledger stamp asupdate_sketch, so a recipe carried out of a temporary box comes back
as it left, a hero with its hand edits. A duplicate ref refuses, and referenced assets must already
exist. - MCP Apps preview, opt-in. With
MOJULO_MCP_APPS=1,preview_worldshows an inline mesh
snapshot of a stored ref in a host that supports MCP Apps; the exported HTML stays the full world.
Nothing is hosted publicly.
Dashboard package
- The dashboard is its own npm package,
mojulo-ui, published at the same version asmojulo
and depending on exactly that version.npx -y mojulo-uistarts it; core'smojulo-uicommand
runs the matching package or downloads it after saying so. It has no bot pages. Both packages
carry LICENSE and NOTICE, and the dashboard lists every package it redistributes in
THIRD_PARTY_NOTICES.md
(Dashboard package).
Creative work
- Characters and heroes: the hero as a core form with a create-hero loop and tunes kept as the
record, fitted landmark heads with a face tune and a hair library, the ring plan and creature loop,
planar humanoids, and worn things that follow the dials
(Create hero,
Hero detail,
Hero tune,
Fitted heads,
Face tune,
Hair library,
Ring plan,
Planar detail,
Planar humanoid,
Read and attach).
The hero also wears the Anime Form Studio's head (head: 'anime') on anime proportions, with
fitted hair forms, looks as composable words, a graphic face and neck, a character light with
designed shadow shapes, draw layers and clips at the door; its skinned GLB and Godot pack carry the
face. Worn armour (plate, samurai lamellar and hard-suits, with themes carried down a suit) and held
gear with swings ride the hero door
(layered manual,
designing a hero). - Arms, metal and gems: swords, daggers, greatswords, staves, bows and shields composed from a few
dials and laws, pattern-welded blades included (mint_solidkindequipment); metal as a surface
any part, facade, roof or trim can wear (a metal, a finish and an oxide film), reflected on the World
page and kept in glTF and USD; gems with their optics and exact light prints, and crystals as light
operators in worlds, performed in Godot
(equipment manual,
workbench manual). - Cities and worlds: metro and canal profiles for the fractal city, redrawn landmarks and sacred
buildings, stores and malls from concept cards, and large cities streamed by tile
(City scale,
Canal city,
Local city refacade,
Retail concept cards,
World streaming).
New cities wear a round street kit: lamps, poles, bins, bollards, piers, playground frames and
rooftop equipment drawn round, a few of them in metal. - Interiors: houses minted in a style, livable default room sizes, and a furniture audit that
gives every room a way in
(House styles,
Room livability,
Furniture audit). - Buildings and furniture: timber from a synthetic log, steel sections, reinforced concrete and
masonry, joined by Western and Japanese joinery through the exact kernel and checked, never refused;
houses framed, lined and wired by their building tradition, carrying a building model with a
takeoff; tile roofs and drainage; houses exported as IFC4 (export_modelformat: 'ifc'); house
design checks that measure the walkways, with a repair; furniture built from sheet goods and
fittings (carcasses, tables, chairs, sofas with upholstery and cloth from a weave draft), checked for
sag, racking and tipping, with wordless assembly manuals; and the built pieces placed in rooms and
condos (floor plan manual,
workbench manual). - Terrain and nature: a painted landscape made real-scale ground you walk, fly and orbit, up to a
small planet, or a world composed from features (a river, a range, a lake, a volcano, a coast) sized
on real-world bands, with fractal cities sited on its hills; plants grown rather than drawn (trees by
their architecture, palms, bamboo, figs and conifers), standing as forests where the ground is
painted wood, and grass; rocks built from their minerals, and landforms and erosion on painted
landscapes (terrain manual,
vegetation). - Look and drawing: shading normals from the hull, outlines and rims carried into Godot, Unity
and Unreal, key-and-fill art direction, and thelayeredkind drawn from its compiled mesh, with
rigs and clips
(Shader look,
Art direction,
Planar drawing).
A line drawn on alayeredsolid becomes a recipe op (a silhouette solves the shape dials, a
contour becomes a ridge strip, a brush a dial), with the share of the line it could not hold. - Audio: stereo and per-hit variation, tuned strings, orchestral scoring and era synths, and
anthem and roots song styles, all synthesized from formulas and opt-in
(Audio fidelity,
Orchestra and era synthesis,
Anthem styles,
Roots styles).
2.1.0 and earlier releases, and the detailed log behind this release, are in
CHANGELOG-2.x.md.