How-to guides
Building a Mod
A developer's guide to packaging an .oomu file.
A Beta 2 Mod is a content package. It carries knowledge files an assistant can read and a small set of keys it can persist. It does not carry code, and nothing in it executes.
If you are arriving from Beta 1, read What changed first. It will save you building something OOMU will politely decline to run.
The complete format is in the Mod package specification. This page is the recipe.
What you can actually build
| You want to | Can a Mod do it? |
|---|---|
| Ship reference material an assistant draws on: a style guide, a glossary, a domain primer, structured reference data | Yes. This is the use case. |
| Keep a small amount of state between sessions | Yes, via declared keys. |
| Change how the assistant writes, via a system prompt | No. Use agent instructions. |
| Run code, call an API, register a slash command, hook a turn | No. |
| Add a tool the assistant can invoke | No. Use a local MCP tool. |
Step 1: Lay out the folder
house-style/
├── manifest.json
└── knowledge/
├── style.md
└── terms.json
Content files must live under knowledge/ or content/, and must be .txt, .md, or .json. Those are the only two folder names and three extensions the ABI accepts.
Keep it small. The archive can hold 256 entries and 200 MB uncompressed, but a Mod that ships a handful of well-written reference documents is more useful than one that ships a library.
Step 2: Write the manifest
manifest.json must sit at the archive root.
{
"id": "com.example.mods.house-style",
"name": "House Style",
"version": "2.0.0",
"author": "Example Ltd",
"description": "Our editorial standards, terminology, and worked examples.",
"category": "writing",
"entrypoint": "knowledge/style.md",
"beta2Abi": {
"schemaVersion": 1,
"capabilities": [
{ "id": "mods.asset.read", "assets": ["knowledge/style.md", "knowledge/terms.json"] }
]
}
}
Rules worth committing to memory, because each one rejects the package if broken:
| Field | Rule |
|---|---|
id | Reverse-DNS. Lowercase only, plus digits, ., _, -. 3–200 characters, alphanumeric at both ends. |
name | 1–120 characters. |
version | 1–64 characters, no whitespace. |
author | 1–120 characters. Shown to the user. |
description | 1–500 characters. Shown to the user. |
entrypoint | Optional, but if present the file must exist in the archive. |
entrypointis validated and recorded, never executed. Point it at your main knowledge file, or leave it out.
Adding state
If your Mod needs to remember something, declare both halves with the same keys:
"capabilities": [
{ "id": "mods.asset.read", "assets": ["knowledge/style.md"] },
{ "id": "mods.state.read", "keys": ["last-reviewed", "revision"] },
{ "id": "mods.state.replace", "keys": ["last-reviewed", "revision"] }
]
Declaring state.replace without a matching state.read, or with a different key set, rejects the manifest. Keys follow the same character rules as id, capped at 64 characters.
Step 3: Package it
A plain ZIP, renamed:
cd house-style && zip -r ../house-style.oomu manifest.json knowledge
Then rename to .oomu if your tooling did not:
mv ../house-style.zip ../house-style.oomu
Two things to check before you ship:
manifest.jsonis at the root, not inside a wrapper folder.zip -r ../out.oomu house-style/produces a nested layout that OOMU rejects.- No two entries differ only in case.
Knowledge/style.mdandknowledge/style.mdin the same archive is an error.
Step 4: Install and check it
Open Mods → Install Mod and pick your file. Then:
- Confirm the badge reads Unsigned with "Local package without a signature. OOMU verifies its files before use.": expected for a package you built yourself.
- Expand {count} features and confirm every capability you declared is listed, and nothing you did not declare appears.
- Choose Verify. It re-hashes the installed files against the recorded digest.
- Enable it, then give an agent access under Chat → Agents → Mods.
If something you expected is marked Not supported in this Beta 2 build, you have declared a Beta 1 feature. See below.
Signing
Signing is optional, and it changes the badge, not the capabilities. A Mod's powers come entirely from its beta2Abi declaration; a signature does not widen them.
| Badge | How to earn it |
|---|---|
| Unsigned | Ship nothing extra. |
| Verified publisher | Sign the canonical payload digest with your Ed25519 key and include the public key in capability_bundle.publisher.publicKey. |
| OOMU reviewed | Requires a signature from OOMU's own review key. Not something you can self-issue. |
Both use Ed25519 over domain-separated messages, and the declared payloadSha256 must match the computed payload digest exactly. If you include trust material that does not verify, the package is rejected outright: a broken signature is treated as worse than no signature, not equivalent to it.
Exact envelope shapes are in the specification.
What changed from Beta 1
Beta 2 has no Mod code runtime. These declarations still parse, and are reported to the user as unsupported, but do nothing:
| Beta 1 | Status |
|---|---|
entrypoint: "engine.wasm" or .js | Not executed. |
default_system_prompt / prompt | Not applied. |
hooks, including shield_gate.on_prompt | Not registered. |
commands, slashCommands, triggers, regex | Not registered. |
endpoints, permissions.allowed_hosts | Recorded, not granted. No network access. |
capability_bundle as a capability declaration | Read only for signature material. |
Porting a Beta 1 Mod
If your Beta 1 Mod was primarily a default_system_prompt, its content belongs in an agent's instructions, not in a package.
If it shipped reference material alongside code, keep the material: move it under knowledge/, declare it with mods.asset.read, drop the rest, and you have a working Beta 2 Mod.
If it was genuinely a tool (it called an API or ran a process) a Mod is the wrong vehicle now. Build it as an MCP server and connect it under Connections → Tools on this Mac, where you choose the executable yourself and control per-tool whether it may make changes.
Related
- Mod package specification: every field, limit, and rejection message.
- Installing a Mod: the user's side.
- Connecting services: MCP, for capabilities that need to execute.