MAKED on MoonBit: rabbita SPA frontend + a Flask-style micro-framework on moonback

| Layer | What it is |
|---|---|
| Subject | One state machine per domain — 34 positions × 8 slots × 272 rules, of which 228 have no way out |
| Group | Group states computed across the domains — Scattered → Converging → Common Tongue → Settled (20 states) |
| Society | The collective as a communicative whole — 13 positions × 8 phases × 28 transitions, from riantr/pyroduct |
| You use | You get | Shape |
|---|---|---|
| riantr/MAKED/backend (native) and riantr/MAKED/frontend (js) | the loop, the API and the storage; the single-page app | two MoonBit packages |
| cmd/server | the API and the browser app in one process | HTTP |
| cmd/mcp | the agent's server | Model Context Protocol 2026-07-28, over stdio or HTTP |
| GET /api/agent | the discovery document: the seven tools, their argument schemas, the HTTP endpoints, the four files | JSON |
| GET /api/model | the machine as data: the domains, the positions, the slots, and the rule for every pair | JSON |
| GET /api/sessions/:id/export | one exploration, taken away | Markdown or JSON |
moon add riantr/MAKED///|
import {
"riantr/MAKED/backend@0.1.8" @maked,
}docker compose up --builddocker run --rm -p 8080:8080 -v maked-data:/data ghcr.io/riantr/maked:latestA package on ghcr.io is private until someone says otherwise, and only the owner can say it: Settings → Package settings → Change visibility → Public, once, for riantr/maked.
| Platform | Asset |
|---|---|
| Linux x86-64 | maked-<version>-linux-x86_64.tar.gz |
| macOS (Apple Silicon) | maked-<version>-macos-arm64.tar.gz |
| Windows x64 | maked-<version>-windows-x64.zip |
# The web server: the API and the browser app, one process.
moon run --release --target native cmd/server
# The agent's server, over stdio. Spawn this; speak MCP to it.
moon run --release --target native cmd/mcp
# The agent's server, over HTTP, on the port you name.
MAKED_MCP_PORT=8735 moon run --release --target native cmd/mcp.\build.ps1
moon run --release --target native cmd/serverdocker compose up --buildcurl -s http://127.0.0.1:8080/api/agentmoon build --release --target native cmd/mcp{
"mcpServers": {
"maked": {
"command": "/path/to/MAKED_moonbit/_build/native/release/build/cmd/mcp/mcp.exe"
}
}
}The agent's server is not in the published release artifacts yet — those carry the web server and the browser bundle. It is built from this repository, and it will join the release when it is worth shipping.
MAKED_MODEL=models/product-iteration.json \
MAKED_RESEARCH=research/product-iteration.yaml \
moon run --release --target native cmd/server| Method | Path | What it does |
|---|---|---|
| GET | /api/status | is the server up, how many pages, which domains |
| GET | /api/pages | the ten pages the server holds, in the language asked for |
| GET | /api/pages/:slug | one page by slug |
| PUT | /api/pages/:slug | correct what one page says |
| GET | /api/domains | the five domains in ring order |
| GET | /api/bootstrap | pages, workspace entries and session state in one call |
| GET | /api/entries | the workspace entries |
| POST | /api/entries | put your own record in the workspace |
| PUT | /api/entries/:id | correct one |
| DELETE | /api/entries/:id | remove one |
| GET | /api/sessions | the named explorations |
| POST | /api/sessions | start one |
| GET | /api/sessions/:id | one exploration, with its timeline |
| POST | /api/sessions/:id/activate | bring one to the front |
| POST | /api/sessions/:id/replay | re-run a run |
| POST | /api/sessions/:id/branch | fork an exploration |
| POST | /api/sessions/:id/rename | rename one |
| DELETE | /api/sessions/:id | delete one |
| GET | /api/sessions/:id/export | one exploration as markdown or json |
| GET | /api/loop/status | where the loop stands |
| GET | /api/loop/slots | the eight-slot vocabulary |
| GET | /api/loop/continuations | what the machine says could happen next |
| GET | /api/loop/mode | the current mode |
| POST | /api/loop/mode/:mode | change it |
| POST | /api/loop/step/:slot | take a move with a named slot |
| POST | /api/loop/step | take a move and let the table choose |
| POST | /api/loop/reset | back to Model with an empty history |
| POST | /api/loop/reset/:domain | back to a chosen domain |
| GET | /api/model | the machine as data |
| GET | /api/agent | the discovery document: the seven tools, the instructions, and the HTTP endpoints |
| GET | /api/research/documents | the documents the corpus holds |
| POST | /api/research/drive | drive a document through the loop |
| GET | /api/research/config | the mapping table, and whether it can be written back |
| PUT | /api/research/config | put a table of your own |
| GET | /api/research/corpus | the corpus, and whether it can be written back |
| PUT | /api/research/corpus | put a corpus of your own |
| GET | /api/research/causal | the causal estimate, and what it rests on |
| GET | /api/society | the collective: where it stands, what it can do |
| POST | /api/society/step | take a move for the collective |
| ?lang= | What comes back |
|---|---|
| (absent) | English |
| zh | Chinese |
GET /api/loop/status?lang=zh
GET /api/loop/slots?lang=zh
GET /api/loop/continuations?lang=zh
POST /api/loop/step?lang=zh
GET /api/sessions/1?lang=zh
GET /api/pages?lang=zh
GET /api/pages/model?lang=zh
GET /api/bootstrap?lang=zhGET /api/sessions/1/export?format=md&lang=zh
GET /api/sessions/1/export?format=json&lang=zh| Tool | Arguments | What it answers |
|---|---|---|
| maked_status | lang | where the loop stands, what the last move did, what the run adds up to, whether it is still finding ground |
| maked_options | depth, lang | the slots that can move, the slots that cannot and why, the successors the table declined to choose between |
| maked_step | slot, target, lang | take a move, and say what happened |
| maked_model | — | the machine as data: domains, positions, slots, and the rule for every pair |
| maked_society | trigger, lang | where the collective stands; with a trigger, take that move |
| maked_sessions | lang | the named explorations, and which one is in front of us |
| maked_export | session_id, format, lang | one exploration as Markdown (to read) or JSON (to process) |
curl -s http://127.0.0.1:8080/api/agent| File | Format | Named by | What it decides |
|---|---|---|---|
| The machine | maked.model.v1 (JSON or YAML) | MAKED_MODEL | the domains, positions, slots and rules the loop runs on |
| The mapping table | maked.research.v1 (JSON or YAML) | MAKED_RESEARCH | what a document means — which words make a rule fire, and which slot it drives |
| The society vocabulary | maked.society.v1 (YAML) | MAKED_SOCIETY | the English words for the collective's positions and moves |
| The corpus | maked.corpus.v1 (YAML) | MAKED_CORPUS | where the documents come from: arxiv, an RSS feed, or your own folder |
| Variable | Default | Meaning |
|---|---|---|
| MAKED_PORT | 8080 | listen port |
| MAKED_HOST | 127.0.0.1 | listen address — 0.0.0.0 to be reachable from other machines |
| MAKED_DB | maked.db | SQLite file path |
| MAKED_DIST | frontend/dist | frontend build output directory |
| MAKED_MODEL | (unset) | a machine to run instead of the built-in one |
| MAKED_RESEARCH | (unset) | a mapping table that says what a document means |
| MAKED_CORPUS | (unset) | a corpus file: where the documents come from |
| MAKED_SOCIETY | (unset) | a vocabulary file: the English words for the collective |
| MAKED_MCP_PORT | (unset) | a port: the agent's server speaks HTTP instead of stdio |
{
"format": "maked.model.v1",
"name": "One small machine",
"domains": [
{ "id": "idea", "letter": "I", "title": "Idea", "role": "the idea", "anchor": "raw" }
],
"positions": [
{ "id": "raw", "label": "Raw idea", "gloss": "Nobody has built it yet.", "domain": "idea" },
{ "id": "asked", "label": "A question asked", "gloss": "Somebody was asked.", "domain": "idea" }
],
"slots": [
{ "id": "ask", "designation": "Ask", "gloss": "Talk to somebody who would use it." }
],
"rules": [
{
"from": "raw",
"slot": "ask",
"outcome": { "kind": "moved", "edge": "A customer said no", "to": "asked" }
}
]
}format: maked.research.v1
mapping:
- label: A question worth asking
keywords:
- question
- why
- unclear
slot: ask
notes: The document opens a question rather than answering one.
fallback:
label: Anything else
slot: askformat: maked.corpus.v1
source:
kind: local
path: ./notes
max_results: 20curl -X POST http://127.0.0.1:8080/api/entries \
-H 'Content-Type: application/json' \
-d '{"domain": "M", "title": "The failure I want to keep", "body": "The loop reached a position it could not leave."}'curl -X PUT http://127.0.0.1:8080/api/entries/1 \
-H 'Content-Type: application/json' \
-d '{"domain": "M", "title": "The failure I want to keep, corrected", "body": "The loop reached a position it could not leave."}'curl -X PUT http://127.0.0.1:8080/api/pages/model \
-H 'Content-Type: application/json' \
-d '{"title": "The model I read it as", "body": "What the model is, in my own words."}'curl -X PUT 'http://127.0.0.1:8080/api/pages/model?lang=zh' \
-H 'Content-Type: application/json' \
-d '{"title": "我读出来的模型", "body": "用我自己的话说。"}'$ MAKED_MCP_PORT=8735 moon run --release --target native cmd/mcp &
$ curl -s http://127.0.0.1:8735/mcp \
-H 'MCP-Protocol-Version: 2026-07-28' \
-H 'Mcp-Method: tools/list' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}'MAKED_moonbit/
├── backend/ # the loop, the API and the storage (native)
│ ├── model.mbt # the machine: domains, positions, slots, rules
│ ├── loop.mbt # the subject loop and the group states
│ ├── society.mbt # the collective
│ ├── step.mbt # one step, shared by the API and the agent
│ ├── agent.mbt # the agent's payloads, in sentences, and the discovery document
│ ├── bootstrap.mbt # the start-up: plan → read → install
│ ├── version.mbt # the version the agent reports
│ ├── api.mbt # every HTTP route
│ ├── app.mbt # the Flask-style app: the route table and the middleware chain
│ ├── maked_app.mbt # the app, assembled
│ ├── request.mbt # the request wrapper
│ ├── response.mbt # the response helpers
│ ├── pages.mbt # the content model, and the ten public pages
│ ├── entries.mbt # the workspace: the things the reader brings
│ ├── research_config.mbt # the mapping table
│ ├── research.mbt # what a document means
│ ├── corpus.mbt # the corpus
│ ├── corpus_sources.mbt # where the documents come from: arxiv, a feed, a folder
│ ├── datafile.mbt # a file that may be JSON or YAML
│ ├── causal.mbt # the causal estimate
│ ├── narration.mbt # the sentences
│ ├── i18n.mbt # the language switch
│ ├── export_words.mbt # the exported document's words, in both languages
│ ├── metrics.mbt # the measures, in both languages
│ ├── session.mbt # explorations, timelines, exports
│ ├── database.mbt # SQLite
│ ├── *_test.mbt # 447 tests
│ └── *_wbtest.mbt # 16 tests
├── frontend/ # the single-page app (js)
│ ├── app.mbt # the TEA loop and the messages
│ ├── i18n.mbt # the words the client owns
│ ├── loop_state.mbt # the loop's state, and why a step may do nothing
│ ├── society.mbt # the society panel
│ ├── session.mbt # the explorations panel
│ ├── entries.mbt # the workspace panel
│ ├── causal.mbt # the causal panel
│ ├── page.mbt # the page, and how it is decoded
│ ├── logo.mbt # the ring
│ ├── views.mbt # the views
│ └── frontend_test.mbt # 173 tests
├── cmd/
│ ├── server/main.mbt # the web server
│ ├── mcp/main.mbt # the agent's server
│ └── web/main.mbt # the browser bundle
├── models/ # example machines
│ ├── product-iteration.json
│ └── product-iteration.yaml
├── research/ # example tables, corpora and vocabularies
│ ├── product-iteration.yaml
│ ├── society.yaml
│ ├── corpus-arxiv.yaml
│ ├── corpus-local.yaml
│ └── notes/ # the corpus the local example names
│ └── failed-launch.md
├── tools/
│ ├── integration-test.ps1 # 447 checks against a running server
│ ├── mutate-backend.ps1 # 148 mutations of the backend
│ ├── mutate-frontend.ps1 # 65 mutations of the frontend
│ ├── mutate-loop.ps1 # 16 mutations of the loop
│ ├── check-mutation-anchors.ps1 # 229 anchors, and whether any is dead
│ ├── check-readme.ps1 # the claims this document states, against the tree
│ ├── check-readme.sh # the same gate, in bash
│ ├── check-docs.ps1 # the other documents' claims, against the tree
│ └── check-docs.sh # the same gate, in bash
├── .githooks/ # the pre-commit hook, and the note beside it
│ ├── pre-commit # the hook itself
│ └── README.md # what it runs, and how to install it
├── AGENT.md # how to drive MAKED from another agent
├── AGENTS.md # how to work on MAKED
├── maked.png # the logo
├── moon.mod moon.pkg
├── build.ps1 # build the bundle, check, test, build the server
├── ci.sh # 18 gates
└── Dockerfile docker-compose.ymlcurl -X POST http://127.0.0.1:8080/api/loop/reset/knowledge| What | How many | How it is checked |
|---|---|---|
| Backend tests | 463 | moon test --target native backend |
| Frontend tests | 173 | moon test --target js frontend |
| Integration checks | 447 | tools/integration-test.ps1 — against a server that is really running |
| Backend mutations | 148 | tools/mutate-backend.ps1 |
| Frontend mutations | 65 | tools/mutate-frontend.ps1 |
| Loop mutations | 16 | tools/mutate-loop.ps1 |
| Mutation anchors | 229 | tools/check-mutation-anchors.ps1 — and whether any is dead |
| CI gates | 18 | ci.sh |
moon check --target native # type-check the backend
moon fmt --check # the formatter is a gate
moon test --target native backend # the backend
moon test --target js frontend # the frontend
bash ci.sh # everything, including the slow gatesMAKED_MODEL=models/product-iteration.json \
MAKED_RESEARCH=research/product-iteration.yaml \
moon run --release --target native cmd/serverInstall
Download zipMAKED on MoonBit: rabbita SPA frontend + a Flask-style micro-framework on moonback