Configuring UrsaMU

This page documents the v2.6.0 configuration surface — config/config.json and
the environment variables consumed at startup.

Files

  • config/config.json — runtime configuration, validated at boot
  • .env — secrets (notably JWT_SECRET), loaded by src/main.ts via dotenv/load

ursamu create scaffolds both with sensible defaults and a fresh JWT_SECRET.

Top-Level Shape

{
  "server": { /* transport + KV prefixes */ },
  "game":   { /* world metadata */ },
  "theme":  { /* web client styling */ },
  "plugins": { /* per-plugin scoped config */ }
}

server

Transport ports and Deno-KV collection prefixes.

{
  "server": {
    "telnet": 4201,
    "ws":     4202,
    "http":   4203,
    "db":       "data/ursamu.db",
    "counters": "counters",
    "chans":    "chans",
    "mail":     "mail",
    "wiki":     "wiki",
    "bboard":   "bboard"
  }
}
Key Type Default Purpose
telnet number 4201 Telnet sidecar port
ws number 4202 Legacy standalone WebSocket port (the hub also accepts WS upgrades on http)
http number 4203 Hub HTTP + REST + WebSocket port
db string data/ursamu.db Fallback Deno KV database path (only used if fallback DenoKvAdapter is enabled)
counters string counters KV prefix for ID counters
chans string chans KV prefix for channels
mail string mail KV prefix for player mail
wiki string wiki KV prefix for wiki pages
bboard string bboard KV prefix for bulletin boards

game

{
  "game": {
    "name":            "My UrsaMU Game",
    "description":     "A collaborative-fiction MUSH.",
    "version":         "1.0.0",
    "playerStart":     "1",
    "timeMultiplier":  1,
    "text": {
      "connect": "text/default_connect.txt",
      "welcome": "text/welcome.txt",
      "404":     "text/404.txt"
    }
  }
}
Key Type Purpose
name string Game name (shown in who, REST /api/v1/config)
description string Free-form description
version string Reported via @version
playerStart string DBref of the starting room for new characters
timeMultiplier number In-game-clock multiplier (u.sys.gameTime())
text.connect path Pre-auth banner
text.welcome path Post-create welcome
text.404 path Static-route fallback
layout.header mushcode Template for header() / u.util.header
layout.divider mushcode Template for divider() / u.util.divider
layout.footer mushcode Template for footer() / u.util.footer

game.layout — header / divider / footer mushcode

Override the engine layout helpers with TinyMUX-style templates. When set,
these apply to native header() / divider() / footer(), sandbox
u.util.*, and softcode [header()] / [divider()] / [footer()].

{
  "game": {
    "layout": {
      "header":  "[center(%ch%cy%0%cn,%1,%cg=%cn)]",
      "divider": "[center(%ch%cy%0%cn,%1,%cg-%cn)]",
      "footer":  "[repeat(%cg=%cn,%1)]"
    }
  }
}
Placeholder Meaning
%0 Title / label
%1 Width (default 78)
%2 Filler character(s)

Supported bracket functions inside templates (sync subset):
center, ljust, rjust, repeat, space, cat, lit, strlen.
Color codes (%ch, %cy, …) and %r / %t / %b pass through.

Plugin registerHeader / registerDivider / registerFooter still work
when no config template is set for that slot. A config template for a slot
takes priority over registered plugin layout functions.

theme

Theme tokens read by the bundled web client and /api/v1/config:

{
  "theme": {
    "primary":    "#7f5af0",
    "secondary":  "#2cb67d",
    "accent":     "#ff8906",
    "background": "#16161a",
    "surface":    "#242629",
    "text":       "#fffffe",
    "muted":      "#94a1b2",
    "glass":      0.6,
    "backgroundImage": "https://example.com/bg.jpg"
  }
}

plugins

Per-plugin scoped config. Plugins read their slice via
PluginConfigManager or getConfig("plugins.<name>.<key>", default).

{
  "plugins": {
    "discord": { "enabled": true, "token": "...", "channelId": "..." },
    "my-game": { "startingGold": 100 }
  }
}

Plugin manifests (ursamu.plugin.json) declare their dependencies — see
Plugin development for the manifest format and atomic-install
behavior introduced in v2.6.0.

Environment Variables

Name Required Purpose
JWT_SECRET Yes HMAC secret for JWT signing. Loaded from .env by src/main.ts. If unset, JWT issuance fails — start scripts generate one automatically.
URSAMU_TYPEGRAPH_DB No Database directory/file path for the primary TypeGraph/PGlite database. Defaults to ${Deno.cwd()}/data/typegraph.db (or memory:// during test runs).

.env is generated by ursamu create and excluded from git by the scaffold’s
.gitignore. Rotate by replacing the secret and restarting the hub; existing
sessions will be invalidated.

Runtime Configuration API

import { getConfig, setConfig } from "../../services/Config/mod.ts";

const port = getConfig<number>("server.http", 4203);
await setConfig("game.name", "New Name");

u.sys.setConfig(key, value) is the sandbox equivalent — restricted to
admin/wizard at the command layer.

Text Files

The paths in game.text.* resolve relative to the game project root. Files
support the full MUSH color-code set (%ch, %cn, %cr, %cg, %cb, %cy,
%cw, %cc, %cm, plus %xRRGGBB truecolor and %r/%t/%b).

%ch%cy==================================%cn
%ch%cw           Welcome                 %cn
%ch%cy==================================%cn

Type 'connect <name> <password>' to log in.
Type 'create <name> <password>' to make a new character.