Mist Domain — Complete Reference
Last updated: 2026-04-15
A Mist is a content-addressed, cryptographically signable, forkable, embeddable artifact share. It is the sixth interface of the Muse universe — what a gist becomes when you reimagine it through the full Muse philosophy.
Contents
- Concepts
- URL Schema
- Artifact Types
- CLI Reference
- REST API
- MCP Tools & Resources
- Agent Publishing Workflow
- Forking & Sub-domain Delegation
- Embedding
- Content Addressing
- Security Model
- Limits
Concepts
| Property | Value |
|---|---|
| Identity | Content-addressed — SHA-256 over content bytes, base-58 encoded, truncated to 12 chars |
| Storage | Every mist is a Muse repo with domain="mist" |
| Versioning | Full muse log, muse diff, muse checkout on the backing repo |
| Authorship | Optional Ed25519 (--sign) or GPG signature proving human/agent identity |
| Visibility | public (default) or secret |
| Forkability | Any public mist is forkable; fork depth capped at 5 |
| Embeddability | Standalone iframe card served at /{owner}/mists/{id}/embed |
URL Schema
# Web UI
https://musehub.ai/{owner}/mists/{mist_id} # detail page
https://musehub.ai/{owner}/mists/{mist_id}/embed # iframe-safe embed card
https://musehub.ai/{owner}/mists/{mist_id}/raw # raw artifact download
https://musehub.ai/{owner}/mists # owner's public mist list
https://musehub.ai/mists/explore # global discovery feed
# REST API
POST /api/mists # create
GET /api/mists/{mist_id} # read
PATCH /api/mists/{mist_id} # update (owner only)
DELETE /api/mists/{mist_id} # delete (owner only)
POST /api/mists/{mist_id}/fork # fork
GET /api/mists/{mist_id}/forks # list direct forks
GET /api/mists/explore # global public feed
GET /api/{owner}/mists # owner's public list
GET /api/{owner}/mists/{mist_id}/embed # embed codes
# MCP Resource
musehub://mists/{owner}/{mist_id} # single mist resource
musehub://mists/{owner} # owner's mist list resource
Artifact Types
The server auto-detects the artifact type from the filename and content bytes.
Callers may omit artifact_type in POST /api/mists — the server fills it in.
| Type | Detection heuristic | Language detection |
|---|---|---|
code |
Common code extensions (.py, .js, .ts, .rs, .go, …) |
Yes — extracted from extension |
midi |
.mid / .midi extension or MIDI magic bytes (4D 54 68 64) |
No |
schema |
.json + JSON content with $schema or type/properties keys |
No |
abi |
.abi, .abi.json, or JSON array of ABI objects |
No |
dataset |
.csv, .tsv, .ndjson, .jsonl |
No |
config |
.yaml, .yml, .toml, .env, .ini, .conf |
No |
text |
.md, .txt, .rst, .adoc or unrecognised text |
No |
unknown |
Binary content with no recognised signature | No |
Symbol anchors (symbol_anchors) are extracted automatically for Python, JavaScript,
and TypeScript code artifacts. They appear in the sidebar on the detail page and in
the MCP resource response.
CLI Reference
The muse mist subcommand is the primary interface for humans and agents.
Create
muse mist create <file> [options]
Options:
--title TEXT Human-readable title
--description TEXT Longer description (shown on the detail page)
--visibility public (default) | secret
--tags TAG,... Comma-separated tags (max 10, 64 chars each)
--agent-id TEXT Agent identifier for provenance (e.g. "cccode-v3")
--model-id TEXT Model ID for agent provenance (e.g. "claude-sonnet-4-6")
--sign Sign with the local Ed25519 identity key (~/.muse/identity.toml)
--push Push to the configured hub after creation
--json Machine-readable output
Example:
muse mist create validate_handle.py \
--title "Handle validation primitive" \
--tags "security,auth" \
--sign --push --json
# → {"mist_id": "aB3xKq9dPwNm", "url": "https://musehub.ai/gabriel/mists/aB3xKq9dPwNm", ...}
List
muse mist list [--owner HANDLE] [--artifact-type TYPE] [--limit N] [--json]
Read
muse mist read <mist_id> [--json]
Fork
muse mist fork <mist_id> [--push] [--json]
Update
muse mist update <mist_id> [--title TEXT] [--description TEXT]
[--visibility public|secret] [--content FILE]
[--tags TAG,...] [--json]
Delete
muse mist delete <mist_id> [--json]
REST API
All write endpoints require Authorization: MSign ... (see MSign reference).
POST /api/mists
Create a new mist. The mist_id is computed by the server — callers do not supply it.
Request body:
{
"filename": "validate_handle.py",
"content": "def _validate_handle(h): ...",
"visibility": "public",
"title": "Handle validation primitive",
"description": "Security gate used by auth middleware.",
"tags": ["security", "auth"],
"agentId": "cccode-v3",
"modelId": "claude-sonnet-4-6",
"gpgSignature": ""
}
Response (201):
{
"mistId": "aB3xKq9dPwNm",
"url": "https://musehub.ai/gabriel/mists/aB3xKq9dPwNm",
"owner": "gabriel",
"filename": "validate_handle.py",
"artifactType": "code",
"language": "python",
"content": "def _validate_handle(h): ...",
"sizeBytes": 42,
"version": 1,
"visibility": "public",
"title": "Handle validation primitive",
"description": "Security gate used by auth middleware.",
"tags": ["security", "auth"],
"agentId": "cccode-v3",
"modelId": "claude-sonnet-4-6",
"signed": false,
"forkCount": 0,
"viewCount": 0,
"embedCount": 0,
"forkDepth": 0,
"forkParentId": null,
"symbolAnchors": ["validate_handle.py::_validate_handle"],
"createdAt": "2026-04-15T12:00:00+00:00",
"updatedAt": "2026-04-15T12:00:00+00:00"
}
409 Conflict — Same content already exists under your handle (idempotent: the existing mist_id is stable).
PATCH /api/mists/{mist_id}
Partial update. Only provided fields change; omit a field to leave it unchanged.
{
"title": "New title",
"visibility": "secret",
"content": "def _validate_handle(h): pass # v2",
"tags": ["security", "auth", "v2"]
}
Updating content increments version and records a new commit on the backing repo.
404 if mist_id not found or caller is not the owner.
DELETE /api/mists/{mist_id}
Hard delete. 204 on success. 404 if not found or not the owner.
POST /api/mists/{mist_id}/fork
Create a fork. The fork gets a new mist_id (computed from the content + caller
identity + timestamp) and fork_depth = parent.fork_depth + 1.
422 if the parent is already at depth 5.
GET /api/mists/explore
Global public discovery feed. Supports artifact_type and cursor pagination.
GET /api/mists/explore?artifact_type=code&limit=20&cursor=<ISO-8601>
Response shape:
{
"mists": [...],
"total": 1234,
"nextCursor": "2026-04-14T09:30:00+00:00"
}
MCP Tools & Resources
Tools
| Tool | Auth | Description |
|---|---|---|
muse_mist_create |
write | Create a new mist |
muse_mist_update |
write | Patch title/description/visibility/tags/content |
muse_mist_fork |
write | Fork a public mist |
muse_mist_delete |
write | Hard-delete a mist (owner only) |
muse_mist_read |
read | Fetch full mist including content |
muse_mist_list |
read | List mists (owner or global explore) |
muse_mist_embed |
read | Get iframe, script, and badge embed codes |
Resources
musehub://mists/{owner}/{mist_id} — full mist response (content included)
musehub://mists/{owner} — owner's public mist list (no content)
Secret mists are returned for the authenticated owner; unauthenticated or
non-owner reads of secret mists return a forbidden error.
Agent Publishing Workflow
An agent session produces an artifact it wants to share permanently:
# Via MCP tool (no shell required):
result = muse_mist_create(
filename="validate_handle.py",
content=content,
title="Handle validation security primitive",
agent_id="cccode-v3",
model_id="claude-sonnet-4-6",
visibility="public",
tags=["security", "auth"],
)
# → {"mistId": "aB3xKq9dPwNm", "url": "https://musehub.ai/gabriel/mists/aB3xKq9dPwNm", ...}
Or via CLI (signed with MUSE_AGENT_KEY env var injected by Agentception):
muse mist create /tmp/validate_handle.py \
--title "Handle validation security primitive" \
--agent-id cccode-v3 \
--model-id claude-sonnet-4-6 \
--sign --push --json
The resulting URL is a permanent, verifiable artifact:
- The human can view it at
https://musehub.ai/{owner}/mists/{id} - It can be forked, improved, and a proposal submitted back to the original
- It can be embedded in blog posts via
<iframe>or<script> - The
agent_idandmodel_idfields are displayed on the detail page, proving provenance - In the ERC8004 on-chain identity world: agent contract address → MSign key → Mist signature → content hash
Forking & Sub-domain Delegation
Every mist is a Muse repo (domain="mist"). Forking creates a new repo whose
first commit copies the parent's content. The fork graph is visible on the
detail page sidebar (Forked From + Forks panels).
Depth limit: Fork chains are capped at depth 5. This prevents infinite
fork-bomb chains that could exhaust storage. The server returns 422 when a
depth-5 mist is forked.
Sub-domain delegation (future): Because each mist backs a full Muse repo,
any future domain plugin (genomics, spatial, MIDI v2) can be applied to the
backing repo. A mist that was created as artifact_type=code can have its
repo re-initialised under a code domain plugin and gain symbol-level diffs,
blast radius, and AST versioning for free.
Embedding
iframe
<iframe
src="https://musehub.ai/{owner}/mists/{mist_id}/embed"
width="600"
height="400"
frameborder="0"
title="my_file.py">
</iframe>
The embed card shows the artifact type chip, filename, content (Prism.js syntax-highlighted), size/version metadata, and a "View on MuseHub" link.
Script tag
<script
src="https://musehub.ai/embed.js"
data-mist="{owner}/{mist_id}">
</script>
The embed endpoint increments embed_count on each render. Cross-origin
framing is allowed (frame-ancestors *).
Content Addressing
The mist_id is computed deterministically from the artifact bytes:
import hashlib, base58
def compute_mist_id(content: bytes) -> str:
digest = hashlib.sha256(content).digest()
return base58.b58encode(digest).decode()[:12]
Properties:
- Deterministic: The same file always produces the same
mist_id. - Collision-resistant: SHA-256 with 12-char base-58 → ~7×10¹⁶ distinct IDs.
- Offline verifiable: Any caller can recompute the ID and confirm integrity without contacting the server.
- Idempotent creates:
POST /api/mistswith the same content returns409(the existing mist is not overwritten).
Security Model
| Threat | Mitigation |
|---|---|
| Path traversal via filename | _validate_mist_filename() in muse/plugins/mist/plugin.py rejects .., /, \, null bytes, control chars, ANSI escapes |
| Content injection (XSS) | Content stored verbatim; Jinja2 auto-escapes {{ mist.content \| e }} at render time |
| Oversized content | ContentSizeLimitMiddleware returns 413 for bodies > 10 MiB |
| Unauthorised mutation | PATCH/DELETE check mist.owner == caller.handle; return 404 on mismatch |
| Secret mist leakage | Secret mists excluded from /explore and owner list; direct GET returns 403 |
| Fork bomb | Depth cap enforced at service layer (_FORK_DEPTH_LIMIT = 5) and REST route (422) |
| Rate limiting | MIST_CREATE_LIMIT = 20/min, MIST_FORK_LIMIT = 30/min per MSign handle |
| Tag injection | validate_tags() enforces count ≤ 10, length ≤ 64, no null bytes |
Limits
| Parameter | Limit |
|---|---|
| Content size | 10 MiB (enforced by middleware) |
| Filename length | 255 characters |
| Title length | 500 characters |
| Description length | 10,000 characters |
| Tag count | 10 |
| Tag length | 64 characters |
| Fork depth | 5 |
| Create rate | 20 / minute per handle |
| Fork rate | 30 / minute per handle |
| Explore page size | 1–100 (default 20) |