DjangoMOO
“LambdaMOO on Django”
DjangoMOO is a MOO server built on Python and Django. A MOO is a persistent online text world where objects — rooms, things, players — have properties and verbs (methods) that define how they behave. Those verbs are written in Python and run in a sandboxed execution environment, so the world itself is programmable by its inhabitants.
The design follows the LambdaMOO model where it makes sense: a parsed command line, verb dispatch through the caller’s inventory and location, object inheritance, and a permission system. The implementation is independent — no MOO bytecode, no C — just Python and Django.
Documentation | GitLab | GitHub mirror | PyPI
What’s included
A LambdaMOO-inspired parser with full dobj/iobj preposition support
Objects, Properties, Verbs, and a ManyToMany inheritance hierarchy backed by PostgreSQL
A RestrictedPython verb sandbox with and integrated permissions system and extensive testing
A default bootstrap world: rooms, exits, containers, players, a lighting system, in-world mail, and an object placement system
Browser playable with no client required, or via plain SSH client
Full support for MUDlet and other MUD clients using sshelnet helper
Django admin for browsing and editing the world’s objects, properties, and verb source
Docker for self-hosting with
docker compose up
Quick Start
git clone https://gitlab.com/bubblehouse/django-moo
cd django-moo
docker compose up
Bootstrap the database and create your first wizard:
docker compose run webapp manage.py migrate
docker compose run webapp manage.py collectstatic
docker compose run webapp manage.py moo_init
docker compose run webapp manage.py createsuperuser --username wizard
docker compose run webapp manage.py moo_enableuser --wizard wizard Wizard
Connect at https://localhost/ and log in with the account you just created.
Interfaces
MUD Clients
A Mudlet package in extras/mudlet/ provides one-click
setup for MUD-client users. Mudlet has no native SSH support, so the package
bundles a managed sshelnet launcher
that bridges Mudlet’s plain-TCP connection to the server’s SSH port. It also
ships a setup wizard (dmsetup) and a generic-mapper bridge that subscribes
to GMCP Room.Info events and feeds them into Mudlet’s bundled mapper.

The server speaks GMCP, MSSP, MSP, EOR, and CHARSET, so other clients (TinTin++, MUSHclient, Blightmud) work too, though without the bundled mapper integration, or automatic sshelnet setup. MXP is not implemented.
Web (WebSocket SSH)
The server is accessible through a browser-based SSH client at /. No SSH client needed.


SSH
Direct SSH access is also available.
ssh -p 8022 yourname@localhost

Hit Ctrl-D to disconnect.
Changing your password and managing SSH keys
Credentials are managed from inside the world with in-game verbs rather than the Django admin:
@password— interactively changes your password. Prompts for the old password, then the new one twice for confirmation. Wizards may leave the old password blank to perform an administrative reset.@keys— lists your currently registered SSH public keys.@add-key <public-key>— registers a new SSH public key. The key name is taken from the comment field automatically.@remove-key <index>— removes a key by its index from@keys.
Once a key is registered, reconnecting with ssh -p 8022 yourname@localhost
skips the password prompt.
Django Admin
A full Django admin interface is available at /admin for managing objects, properties,
verbs, and users.

Attributions
LambdaCore
This package is derived from the LambdaMOO and LambdaCore documentation, including the LambdaCore Programmer’s Manual and the LambdaMOO Programmer’s Manual. The code was written without reading the original LambdaCore source; it is an independent reimplementation based on documented behavior and conventions.
Various verbs have been modified from their LambdaCore equivalents to better fit a Pythonic
codebase: output uses print() rather than return values, property access follows Django ORM
patterns, and permission idioms have been updated to account for differences in how this
server dispatches verbs compared to LambdaMOO.
DjangoMOO could not have happened without the work of the following authors:
LambdaCore Database User’s Manual (LambdaMOO 1.3, April 1991) Mike Prudence (blip), Simon Hunt (Ezeke), Floyd Moore (Phantom), Kelly Larson (Zaphod), Al Harrington (geezer)
LambdaCore Programmer’s Manual (LambdaMOO 1.8.0p6, Copyright 1991) Mike Prudence (blip), Simon Hunt (Ezeke), Floyd Moore (Phantom), Kelly Larson (Zaphod), Al Harrington (geezer)
LambdaMOO Programmer’s Manual (LambdaMOO 1.8.0p6, March 1997) Pavel Curtis (Haakon / Lambda)
Introduction
Tutorials
- Getting Started as a Player
- Building Your First Room
- Prerequisites
- Step 1: Orient yourself
- Step 2: Create a room
- Step 3: Describe the room
- Step 4: Wire the return exit
- Step 5: Create an object
- Step 6: Describe and alias the object
- Step 7: Make the object visible
- Step 8: Put something inside the box
- Step 9: Check your work
- What just happened
- Where to go next
- Your First MOO Verb
- Writing Tests for Your Verbs
- Prerequisites
- The verb we’re testing
- Step 1: Create the test file
- Step 2: Add the fixtures and markers
- Step 3: Capture
print()output - Step 4: Capture
tell()andwrite()output - Step 5: Test database side effects
- Step 6: Call verbs directly (skip the parser)
- Step 7: Test a lock guard
- Step 8: Using the
setup_itemfixture - Step 9: Run the tests
- What just happened
- Where to go next
- Building a Persistent World from Scratch
- Prerequisites
- What you’re building
- A note on packaging
- Step 1: Create the package skeleton
- Step 2: Write the orchestrator
- Step 3: Define your root classes
- Step 4: Create the starting rooms
- Step 5: Wire the exits
- Step 6: Add a verb
- Step 7: Finalize and load verbs
- Step 8: Register the dataset
- Step 9: Run the bootstrap
- Step 10: Iterate
- Step 11: Test it
- Where to look for more
- Out-of-tree packaging (future direction)
How-to Guides
- Creating MOO Verbs
- The shebang line
- Words the parser treats as prepositions
- RestrictedPython execution
- Names injected into the verb’s scope
- The
contextobject - Parser methods
- Sending output to players
- Reading and writing properties
- Error handling
- Permission checks
- Validating arguments
- A real verb, end to end
- Where to go next
- Advanced Verb Patterns
- How Permissions Work in Verbs
- Bootstrap Recipes
- Sync verbs after editing source files
- Add a verb to an existing dataset
- Update an existing verb in place
- Test a custom bootstrap
- Make a property inherit ownership
- Allow non-wizards to create instances of a class
- Update an object’s properties idempotently
- Replace a verb’s
--ontarget - Debug a failing bootstrap
- Run Multiple Universes on One Server
- NPCs and Daemons
- Development
- Connection Control Verbs
- Accessibility and MUD Client Compatibility
- SSH Key Management
Reference
Explanation
API Reference