mooR Development Status #2: Building Foundations for 1.0

For newcomers: mooR is a backend engine for building online multiuser/player games and communities where participants can build, program and modify the world in real-time. It's a modern reimplementation (written in Rust) of LambdaMOO, a pioneering 1990s platform for building interactive social spaces and MUDs (Multi-User Dungeons). The key feature: everything lives in a persistent, programmable object database where users can create, modify, and extend the world without needing server access or deployments. We're bringing this vision into the modern era with enhanced language features, extensibility and robustness, and support for web-based interfaces or other protocols. Read more about mooR's vision and capabilities.

It’s been just over a month since the first development status post, and the pace of development has been intense. We landed 187 commits in roughly 30 days averaging about 6 commits per day. Going full-time on mooR has meant being able to maintain sustained focus on complex architectural work that would have been impossible to tackle in scattered weekend sessions.

This kind of pace is only possible because I’m able to work on mooR full-time, but it comes with significant financial sacrifice. Working on mooR full-time is only going to be possible for me (for a bit) thanks to community support. If you find this work valuable, please consider sponsoring development to help keep this project moving forward. Or consider hiring me (25 years experienced systems software engineer, including 10 at Google) to work on your mooR-based (or similar!) project.

There’s also an active Discord community where we discuss development and share ideas.

This cycle was guided by a central question: What do we need for a compelling 1.0 release that provides a reasonable foundation to build upon? I’m hoping to get something I can call 1.0 out for mid-November, and that meant focusing on foundational work.

What Changed This Month

Making data formats future-proof[er]: Replaced the internal serialization format throughout mooR to support stable database upgrades and cross-language tooling. Not user-visible, but essential for 1.0 stability.

Version control tooling for MOO databases: Added the ability to import and export individual objects from within MOO code with conflict detection - think Git merge for MOO objects. This enables modern development workflows for maintaining and upgrading MOO systems.

A lot of polish: better LambdaMOO compatibility, improved telnet handling, improvements to the anonymous objects we mentioned in our last blog post, web client improvements, and countless bug fixes and edge case handling.

Let’s dive into the details.

Making Data Formats Future-Proof

Previously, mooR’s binary database format could be unstable between changes / versions. Migration via text dump always worked - you could dump to textdump or objdef format and re-import - but sometimes you’d hit incompatibilities with the binary format and have to blow away your database and re-import. This was nerve-wracking (deleting your database!), produced arcane error messages, and wasn’t an ideal workflow.

With FlatBuffers, the binary format is now more stable and evolvable. We can add version tagging and migration procedures to help migrate without needing the export/re-import dance.

Additionally, developers can now write tools, clients, and extensions in languages besides Rust - Python, JavaScript, C++, Go, whatever makes sense. As proof of concept, we’ve included a Python-based worker that demonstrates interacting with mooR’s components via the FlatBuffers RPC protocol. The technical reference for the RPC API documents the new FlatBuffers-based protocol.

The technical story

Early in mooR’s development, I chose bincode for encoding data - both for communication between mooR’s internal processes and for storing data in the database. bincode is fast and convenient, perfect for rapid prototyping when everything was changing constantly.

But it has a critical limitation: no schema evolution. Bincode just serializes Rust structs. If you add a field, remove a field, or if the data format changes between versions, the representation completely changes and old databases become incompatible. While you could always export to textdump and re-import, the workflow of “blow away your binary database and re-import” was far from ideal, especially with the arcane error messages or behaviours found when incompatibilities hit. For a 1.0 release that needs to be stable and upgradeable, this isn’t acceptable.

This cycle completely replaced bincode with FlatBuffers throughout the entire system. FlatBuffers provides:

  • Schema evolution: Databases can be upgraded across versions without breaking
  • Multi-language support: The format is accessible from any language with FlatBuffers support
  • Independent specification: The data formats are formally described in .fbs files, separate from the code
  • Performance potential: FlatBuffers enables zero-copy access, though we haven’t fully exploited this yet

The migration touched everything - RPC communication, database storage for variables and compiled code, connection state, event logs, task queues. It was comprehensive and necessary work for a production-ready system.

Change management for MOO Databases

MOO has always had a fundamental problem: everything lives in a “live” database that’s hard to version, share, or upgrade. Want to pull in improvements from another MOO? Want to upgrade your core system without destroying local customizations? Want to track changes over time? These have traditionally been somewhere between difficult and impossible.

This cycle added the building blocks for proper version control workflows. MOO code can now:

  • Export individual objects to a structured format
  • Import objects with conflict detection
  • Merge changes intelligently, choosing how to handle conflicts
  • Work object-by-object instead of needing whole-database imports/exports

This enables workflows like bitMuse’s VCS worker - Git-style version control for MOO objects, letting you track changes, manage branches, and merge improvements just like you would with regular code.

The technical story

mooR has had “objdef” - a human-readable object definition format - for a while — this is an alternative to LambdaMOO’s “textdump” database format (which was not meant to be human editable or readable). With objdef, you can export entire databases as directories of text files, and import from it as well — which is useful for Git repositories,using a text editor, etc. But there were two missing pieces:

Granular object management: Before this cycle, you could only import/export entire databases at once - an all-or-nothing operation. There was no way to bring individual objects into a running MOO. To enable version control workflows, you need to be able to work object-by-object, importing changes incrementally without replacing the entire database.

Conflict resolution: When you’re merging changes from different sources, conflicts are inevitable. The system needed to detect when an imported object definition conflicts with what’s already in the database, and provide tools for resolving those conflicts intelligently.

This cycle added the load_object and dump_object builtins, along with a comprehensive conflict detection and resolution API. You can now:

  • Load/save individual objects from MOO code
  • Detect conflicts at a granular level (property values, verb code, permissions)
  • Choose conflict strategies: clobber everything, skip conflicts, or detect and report
  • Selectively override or remove specific properties and verbs

The work was driven by real-world needs - bitMuse’s VCS worker project exposed exactly what was missing and helped shape the API.

Lots of Polish

Telnet Compatibility

The telnet-host (the component in mooR that handles inbound “telnet” TCP connections, often from a MUD client, etc) got a significant overhaul to more closely match how LambdaMOO and ToastStunt handle connections, which some clients and cores depend on. This included implementing the set_connection_option and connection_options builtins, giving MOO code control over connection capabilities like linebreak handling and character encoding. The journey was circuitous (tried a third-party library, reverted to hand-rolled when it had issues), but the result is proper compatibility with classic MOO clients.

Anonymous Objects: Getting More Production Ready

Anonymous objects (introduced in the previous post) had some improvements. The garbage collection system was optimized for concurrent operation, performance improved significantly, and they’re now fully documented in the book, with a feature flag for enabling/disabling them. I would still classify them as “experimental” but they’re ready for more aggressive testing.

Language Features & Compatibility

A collection of language improvements landed, many contributed by Norman Nunley:

  • New operators: logical shift right (>>>) and full bitwise operations. These are compatible with both ToastStunt and the upcoming LambdaMOO 1.9 release.
  • Support for “fully parenthesized” program listings, as in LambdaMOO (thanks Norm!)
  • Parser improvements for edge cases and LambdaMOO compatibility
  • New hooks compatible with Lambda: $handle_task_timeout, $handle_uncaught_error, among others.
  • Numerous fixes for some found bugs in UTF-8 handling, iteration over object numbers, object matching, scattering assignment, and some parsing edge cases

Web Client & Developer Tools

The web client gained a property editor for editing object properties in the browser, retro terminal themes (RetroGreen and RetroAmber), better error presentation, and improved login handling.

Developer tooling added (optional) tracing support for database transactions and scheduler operations in the daemon itself, exporting traces in a format readable by Perfetto, making it easier to diagnose issues.

LambdaCore Extraction

mooR now includes our own extraction of LambdaCore (in objdef format), forked and adapted to take advantage of mooR’s features. The fork includes support for UUID objects (covered in the previous blog post) and better password encryption (switching away from the old, insecure crypt() function). This gives users a working, familiar MOO core to start with out of the box, rather than requiring them to find and adapt an existing database. It’s been invaluable for testing compatibility and provides a baseline for people wanting to get started quickly.

Note: this is not intended as a replacement for more ambitious core efforts like HackerCore or Cowbell - those are about showcasing mooR’s modern capabilities. The LambdaCore extraction is more about providing a familiar, working baseline and a realistic conservative test case for compatibility.

Community Contributions

This development cycle has been heavily influenced by active community collaboration:

bitMuse continues pushing mooR’s capabilities through HackerCore (a modern MOO core built from scratch for mooR) and his VCS worker that brings Git-style version control to MOO. The VCS worker’s requirements directly drove the objdef conflict resolution work. His work on his own core turned over many rocks that had bugs under them. Which were promptly squashed.

Robert Pate II has made extensive code contributions: UUID object bug fixes in our LambdaCore fork, string parsing enhancements, the web client property editor, security fixes, frontend tooling, and documentation. Crucially, his testing of mooR against the forked LambdaCore uncovered numerous issues and edge cases that would have otherwise gone unnoticed. Great job on keeping the issue tracker full!

Norman Nunley delivered major language improvements: improving how the language handled operator precedence during both parse and unparse, implementing all the bitwise operations, adding missing fully_paren and indent options to the verb_code() builtin, and continued work on mooR’s parser and compiler infrastructure. He also maintains tree-sitter-moor, a tree-sitter grammar for mooR’s dialect of MOO. Norm wrote the original version of mooR’s unparser/decompiler over two years ago, and his contributions have continued to be super-useful.

Overall: The cycle of “build something real → find the rough edges → fix the platform → build more” has been invaluable.

What’s Next: The Road to 1.0

The 1.0 milestone is currently targeted for November 2025. Here’s what remains:

Critical for 1.0

Emergency Mode (#499): An emergency access mechanism for when administrators need to fix critical issues (like broken logins) without e.g. having an objdef dump available. Essential for production deployments.

Core Update & Version Control Workflows (#478): While the load_object/dump_object builtins exist, there’s still work needed on higher-level workflows and finer-grained change management. How do MOO administrators safely pull in improvements from upstream cores without destroying local customizations? How do we merge “changelists” (sets of specific changes to objects) from version control systems like bitMuse’s VCS worker? Currently load_object brings in whole objects with optional conflict overrides, but the granularity isn’t great for sophisticated merge workflows. This needs additional tooling, APIs, and documented patterns.

Event Log Privacy (#476): The web client’s event log enables Discord/Slack-style persistent history, but currently stores everything in plaintext. For 1.0, this either needs end-to-end encryption (substantial work) or needs to be removed/disabled by default.

The Showcase Question: What Does 1.0 Mean?

Here’s the harder question: Right now you can run an existing LambdaMOO database with mooR (with fairly minor modifications), but it doesn’t really showcase what makes mooR compelling. mooR has significant capabilities over LambdaMOO or ToastStunt such as lambda expressions, anonymous objects, modern web client, easier extendibility,but without something demonstrating these advantages, will there be enough pull to drive adoption or get initial excitement? (Will my neurotic obsession for the last 3 years be a waste?)

Two efforts are underway:

  • HackerCore (bitMuse): A modern MOO core built from scratch for mooR
  • Cowbell (my own project): Another modern core taking advantage of mooR’s features

The tension is: finding time to work on compelling examples (cores, actual running MUDs / communities) while still improving the foundation is tricky. All the foundation work this cycle enables better core development, but doesn’t itself demonstrate the vision.

Another aspect: the motley group of people working on mooR coordinate on Discord, even though what we’re building is in some respects a competitor to that kind of application. Actually convening on a MOO would both demonstrate what we’re working on and provide real-world testing. But this runs into the same time constraints. Setting up and maintaining a MOO for coordination takes time away from building the platform. It also potentially limits the audience, since Discord has lower friction for new contributors (mobile apps, established user base, integration with other tools).

Basically .. a killer app (game or community) for mooR would be nice.

Does this block 1.0? It’s a question of the target audience. If we’re building for experienced MOO/MU* developers who understand the platform and can work with existing tools, mooR is nearly there. If we’re targeting newcomers who need a polished, ready-to-run example before they can envision what’s possible, then we probably need that killer app first.

My current thinking: 1.0 means a stable, well-documented foundation with semantic versioning and clear upgrade paths. Compelling showcase applications can come after. But I’m open to input on this - what does 1.0 mean to you? Join the discussion on Discord and share your thoughts. Either way, mid-November remains the target.

Conclusion

This has been a cycle focused on foundations rather than features. Making data formats future-proof and enabling version control workflows aren’t flashy, but they’re essential for a production-ready system. The telnet work, language features, and LambdaMOO compatibility improvements ensure everything actually works reliably with real MOO code and clients.

The foundation is solidifying. The focus now shifts from “building features” to “ensuring stability” - fixing edge cases, improving error messages, documenting patterns, and making sure everything works reliably.

If you’re interested in MOO development, virtual world systems, or just following along, now is a great time to get involved. Join the Discord community or check out the code on Codeberg.

As always, if you find this work valuable, please consider sponsoring development to help keep this project moving forward.


mooR is open source and available at codeberg.org/timbran/moor. Documentation is at timbran.codeberg.page/moor-book-html.

← Back to Blog