π TypeDocs Β Β·Β API Reference
monad.ai 2.2.0
Active execution agents inside semantic namespaces.
A monad is a daemon that runs a .me kernel, exposes it over HTTP, resolves namespace paths, and registers itself on a mesh surface so other monads and users can find it.
npm install -g monad.ai
monads # start the daemon on port 8161
monads proxy # start browser gateway on port 8160 (routes name.monad)
What a monad does
.me kernel β semantic tree, memory log, identity proof
HTTP surface β GET /path/name, POST / (write), /__bootstrap (health)
cleaker β anchors the kernel to a namespace (suign.cleaker.me)
mesh β announces self, accepts remote monad registrations
Every HTTP request carries a Host header. The monad resolves it into a namespace and routes the read or write into the correct kernel branch:
GET /profile/name
Host: suign.cleaker.me
β me://suign.cleaker.me:read/profile/name
URL model
monad.ai separates meaning (namespace + path) from execution (which daemon answers):
me://<namespace>/<path> canonical semantic address
http://127.0.0.1:<port>/path transport address for browser / curl / fetch
The HTTP surface is what you call. The me:// address is what the namespace, mesh, logs, and routing layer use internally.
curl http://127.0.0.1:8161/profile/name -H "Host: suign.cleaker.me"
# β reads profile.name from the suign.cleaker.me kernel
curl -X POST http://127.0.0.1:8161/ \
-H "Host: suign.cleaker.me" \
-H "Content-Type: application/json" \
-d '{"expression":"profile.name","value":"Sui"}'
# β writes into the namespace memory log
monad[name] β scope-chain routing
Targets can name a specific monad using bracket syntax:
me://suign.cleaker.me:read/monad[frank]/projects/x
The bridge extracts monadId = "frank" and resolves via fallback chain:
1. frank @ suign.cleaker.me (compound β exact match)
2. frank @ cleaker.me (rootspace β fallback)
3. 404
Same name resolves differently depending on namespace context. Mirrors JS prototype chain / CSS cascade / DNS resolution.
The bridge strips the monad[name] prefix before proxying β frankβs endpoint receives the request at /projects/x, not at /monad[frank]/projects/x.
Mesh β announce and discovery
Outgoing: monad announces itself
Set MONAD_SURFACE_URL to any surface and the monad announces itself on startup and every 30 seconds:
MONAD_SURFACE_URL=https://cleaker.me monads # announce to public mesh
MONAD_SURFACE_URL=http://sui-macbook.local:8161 monads # announce to LAN mesh
# (unset) = local-only, invisible to any remote surface
The announce interval is configurable:
MONAD_ANNOUNCE_INTERVAL_MS=60000 monads # announce every 60s instead of 30s
Incoming: POST /.mesh/announce
Any monad can register on any surface:
POST /.mesh/announce
{
"monad_id": "monad:abc123",
"name": "frank",
"namespace": "suign.cleaker.me",
"endpoint": "http://raspberry.local:8161",
"claimed_namespaces": ["suign.cleaker.me"],
"tags": ["raspberry", "sensor"],
"scope_path": "/projects/music"
}
Response:
{ "ok": true, "registered": true, "namespace": "suign.cleaker.me", "monad_id": "monad:abc123" }
Surfaces throttle repeated announces: minimum 10 seconds between accepted registrations from the same monad_id. Entries go stale after 5 minutes without a heartbeat.
Query: GET /.mesh/monads
Returns all registered monads on this surface. Used by the surface[] mesh resolver.
Environment variables
| Variable | Default | Description |
|---|---|---|
PORT |
8161 |
HTTP port |
SEED |
β | Kernel seed (required for identity) |
MONAD_SURFACE_URL |
β | Surface to announce self to |
MONAD_ANNOUNCE_INTERVAL_MS |
30000 |
Heartbeat interval (min 10s) |
MONAD_SELF_IDENTITY |
β | Explicit namespace override |
CLEAKER_NAMESPACE_ROOT |
β | Namespace root override |
HOSTNAME / COMPUTERNAME |
β | Auto-discovered for local surface |
Identity & claims
Before a namespace can receive writes, it must be claimed. A claim anchors a cryptographic identity β derived from (who, secret) via this.me β to the namespace:
POST /
Host: suign.cleaker.me
{ "operation": "claim", "secret": "...", "proof": { ... } }
Opening a claimed namespace returns the memory log for that identity. The caller replays it locally into their own .me kernel:
POST /
Host: suign.cleaker.me
{ "operation": "open", "secret": "...", "identityHash": "..." }
β returns memories[] replayable by .me
The daemon verifies the proof but never holds the seed. The seed never leaves the client.
The kernel is the storage
Every write becomes a memory event in an append-only, hash-chained log:
memoryHash β prevMemoryHash β path β operator β value β timestamp β namespace
The /blocks endpoint projects that log. No separate database. No migrations. On restart, the daemon hydrates from the DiskStore β nothing is lost.
Surface hierarchy
Priority order for surface resolution:
1. local processes first
2. LAN / .local devices (os.hostname() β suis-macbook-air.local)
3. trusted mirrors
4. public surface (cleaker.me)
Every monad auto-discovers its own local surface via os.hostname(). This is the same mechanism cleaker uses for fallback β no configuration needed, devices find each other naturally on the LAN.
Deployment topologies
Local only (no mesh, invisible externally)
# MONAD_SURFACE_URL unset
SEED="my-seed" monads
# Reachable only from same machine at http://localhost:8161
Personal LAN mesh
MONAD_SURFACE_URL=http://sui-macbook.local:8161 SEED="my-seed" monads
# All LAN devices announce to the Mac; Mac serves as private mesh registry
Community namespace (public mesh)
MONAD_SURFACE_URL=https://cleaker.me SEED="my-seed" monads
# Monad appears in public directory
# Namespace owner controls traffic rules, billing, access policies
Running locally
cd npm
npm install
npm run build
SEED="your-seed" node dist/src/index.js
# read
curl http://localhost:8161/profile/name
# write
curl -X POST http://localhost:8161/ \
-H "Host: suign.cleaker.me" \
-H "Content-Type: application/json" \
-d '{"expression":"profile.name","value":"Sui"}'
# health
curl http://localhost:8161/__bootstrap
Install
# Global daemon
npm install -g monad.ai
# Project dependency
npm install monad.ai
KDF deterministic identity
When SEED is set, monad derives its Ed25519 keypair deterministically via HKDF:
HKDF-SHA256(compound_seed, salt='', info='monad.ai/ed25519/v1', length=32) β Ed25519 seed
Same (who, secret) β same monad identity everywhere, every time. No key files to sync across machines.
SEED="your-seed" monads # deterministic identity
monads # random keypair (backwards compatible)
Browser gateway
monads proxy # start on port 8160 (default)
monads proxy --port 9000 # custom port
Configure browser to use PAC file: http://127.0.0.1:8160/proxy.pac
Then open frank.monad, local.monad, or localhost:8161 in the browser β all route to the correct running monad.
The stack
this.me β sovereign kernel. derives identity from (who, secret) seed. works offline.
cleaker β resolver. projects .me into a namespace surface. handles fallback chain.
monad.ai β daemon. runs the kernel over HTTP. registers on the mesh.
netget β gateway. routes physical requests to monad endpoints.
The namespace is not storage. The namespace is chemistry. It is the surface where identities react and compounds form.