Datasets
Create a dataset page, update its record, choose who can read it and add a cover image.
dataset
Section titled “dataset”mr-data dataset {categories,create,set,draft,show,state,note,activity,watch,publish,archive} [DATASET_ID] [options] [--json]mr-data dataset is one name over eleven verbs. They all act on the page a person is looking at.
Create the page before the research starts, so whoever is watching sees it fill in rather than appear finished. Every other verb edits a page that already exists.
The decision record here belongs to the dataset. A run’s own record closes when the run does. Research a person will read next week goes on the dataset, and what happened inside one run goes on that run.
| Verb | Needs DATASET_ID |
What it does |
|---|---|---|
categories |
no | Print the fixed primary-category vocabulary and its assignment policy. Reaches no network. |
create |
no | Mint the page from a working title. This is what produces a dataset identifier. |
show |
yes | Read the page back as Studio holds it. |
set |
yes | Write the title, topics, licence or description, conditional on the version read. |
draft |
yes | Write a bounded live description snapshot without changing the saved description. |
state |
yes | Read the bounded current state, plus paged source inventory, recording membership and event history. |
note |
yes | Write one cell of the dataset’s decision record, or --list what is written. |
activity |
yes | Say in one line what is happening right now. The page shows it, then forgets it. |
watch |
yes | Follow the page’s own event stream. |
publish |
yes | Say who can read the dataset, or --show who can now. |
archive |
yes | Retire the page and free its title. Nothing built is deleted. |
Options
Section titled “Options”| Flag | Argument | Required | Meaning | Default |
|---|---|---|---|---|
--json |
none | no | One JSON object instead of human lines. | off |
--name |
NAME |
create |
With create, the working title the page opens under. With set, the title it settles on. set requires any one of --name, --category, --topics, --license and --description-file. At most 160 characters. |
none |
--expected-version |
N |
draft |
With draft or set, preserve this dataset version and refuse intervening edits. draft requires it, from create, show or the previous draft. |
set reads the current version itself |
--handoff |
none | no | With create, also prepare the single-use address the host opens immediately. |
off |
--description-file |
FILE |
draft |
The description as UTF-8 markdown read from a file. - reads standard input. At most 4000 characters, the same bound the recipe document’s dataset.description carries. |
none |
--category |
one id | no | With set, the primary category, from the vocabulary this page lists. |
none |
--topics |
a,b,c |
no | With set, descriptive tags as one comma-separated list, separate from the primary category. This client trims and lowercases them. Studio holds the bounds: at most eight, no duplicates, each 1 to 40 characters of lowercase letters, digits, spaces and hyphens. --topics '' takes them off the page. |
none |
--license |
ID |
no | With set, the SPDX identifier of the rights basis the sources grant, such as CC-BY-4.0 or ODbL-1.0. --license '' takes it off. Leave it off where the sources’ terms are not an open licence. |
none |
--confirm-name |
TITLE |
archive |
With archive, the dataset’s current title, typed out. |
none |
--mode |
public|link|private |
no | With publish, who can read this dataset. |
public |
--show |
none | no | With publish, report who can read the dataset now and change nothing. |
off |
--heading |
TEXT |
note |
With note, the cell’s one outcome-led line. The page shows it. |
none |
--cell-id |
ID |
no | With note, a stable identifier. Writing it again revises the cell in place. |
derived from the heading |
--markdown-file |
FILE |
no | With note, the cell body as UTF-8 markdown. |
standard input |
--blocks-file |
FILE |
no | With note, the cell’s typed blocks as a JSON array of source, decision or clarification objects. A clarification carrying a question and no answer is the pending question the page shows and the chat asks. |
none |
--phase |
word | no | With note, one of acquire, parse, transform, check, persist. With activity, one of researching, comparing, drafting, building, verifying, waiting_on_you, done. The two vocabularies are disjoint. The flag accepts the union because argparse holds one list per flag, and each verb then closes its own set, so activity --phase acquire is refused. |
none |
--message |
TEXT |
activity |
With activity, the one line the page shows beside the phase word. At most 80 characters. |
none |
--fact |
KEY=VALUE |
no | With activity, one counter beside the sentence, repeatable. Keys: sources_found, sources_probed, candidates, table_columns, checks_declared, rows. Every value is a non-negative whole number. |
none |
--ttl |
SECONDS |
no | With activity, how long this stays current before the page calls it stale. 30 to 1800. |
120 |
--revise |
CELL_ID |
no | With note, the identifier of a different cell this one supersedes, which records the answer to a pending question. Revising a cell under its own identifier needs no flag. |
none |
--list |
none | no | With note, list the cells this dataset holds instead of writing one. |
off |
--from-seq |
N |
no | With watch, replay from after this log position. Ignored once a cursor is known. |
none |
--last-event-id |
CURSOR |
no | With watch, resume from this cursor, as a previous watch reported it. |
none |
--paged-sources |
none | no | With state, request one paged source-state snapshot. |
off |
--source-inventory-recipe-manifest |
MANIFEST |
no | With state, the exact inventory manifest from a prior paged response. Give it with the position. |
none |
--source-inventory-position |
POSITION |
no | With state, bounded source-inventory page position. Give it with the manifest. |
none |
--membership-position |
POSITION |
no | With state, recording-membership page position. |
none |
--membership |
FENCE |
no | With state, recording-membership fence from the preceding page. |
none |
--history-before-cursor |
CURSOR |
no | With state, exclusive durable-event cursor from the preceding page. |
none |
--history-limit |
N |
no | With state, durable-event page size, 1 to 200. |
server default |
A flag belonging to another writing verb returns THIN_REQUEST_INVALID and names the verb it belongs to. --confirm-name typed at note and --message typed at set are two examples. The client never ignores an unsupported flag.
JSON shapes
Section titled “JSON shapes”{ "schema_version": "mostlyright-thin-client-v4-dataset-created.v1", "status": "dataset_created", "lane": "hosted", "dataset_id": "d31017e0", "name": "Kalshi hourly BTC", "version": 1, "dashboard_url": "https://mostlyright.md/datasets/d31017e0", "navigation": { "url": "https://mostlyright.md/datasets/d31017e0", "target": "/datasets/d31017e0", "open_before_research": true, "follow_agent": true, "status": "dashboard_ready" }, "note": "The page exists now and is empty. …"}Values are illustrative. With --handoff, navigation.url becomes a single-use redeem address and navigation.status becomes handoff_ready, or handoff_unavailable when minting failed. The dataset was created either way. Never recreate it to retry its handoff.
{ "schema_version": "mostlyright-thin-client-v4-dataset-read.v1", "status": "dataset_reported", "lane": "hosted", "dashboard_url": "https://mostlyright.md/datasets/d31017e0", "dataset_id": "d31017e0", "name": "Kalshi hourly BTC", "description": "…", "topics": ["bitcoin", "prediction markets"], "license": "CC-BY-4.0", "category_id": "crypto", "dataset_status": "active", "version": 7, "cover": { "cover_image_url": "https://…" }, "tables": [], "latest_run": {}, "activity": null}This payload carries the record’s own status as dataset_status, because the envelope’s status is the command’s word. activity is null for a dataset nothing is working on.
{ "schema_version": "mostlyright-thin-client-v4-dataset-updated.v1", "status": "dataset_updated", "lane": "hosted", "dataset_id": "d31017e0", "version": 8, "fields": ["description", "license", "name", "topics"], "retried_after_conflict": false, "idempotent_replay": false, "dashboard_url": "https://mostlyright.md/datasets/d31017e0"}retried_after_conflict says the first conditional write lost a race and ran again at the new version. idempotent_replay says Studio changed nothing because the record already held those values. version alone cannot separate a write from a repeat. draft answers the same schema with status: "description_drafting" and only dataset_id and version.
{ "schema_version": "mostlyright-thin-client-v4-dataset-access.v1", "status": "dataset_access_changed", "lane": "hosted", "dataset_id": "d31017e0", "requested_mode": "public", "external_mode": "public", "public_url": "https://mostlyright.md/data/kalshi-hourly-btc", "link_url": "https://mostlyright.md/d/…", "dataset_slug": "kalshi-hourly-btc", "dashboard_url": "https://mostlyright.md/datasets/d31017e0"}status is dataset_access_changed when the sharing moved, dataset_access_unchanged when it was already that way, and dataset_access_reported under --show. A mode with no address and no public name carries no public_url, no link_url and no dataset_slug.
{ "schema_version": "mostlyright-thin-client-v4-dataset-narrative.v1", "status": "dataset_note_written", "lane": "hosted", "dataset_id": "d31017e0", "workspace_id": "39ffafde-86ed-5d7b-b337-1c205ea79390", "cell": { "cell_id": "chose-kalshi-over-polymarket", "heading": "Chose Kalshi over Polymarket for hourly strikes", "checkpoint_seq": null, "revision_of": null, "sequence": 4, "cursor": "4-…", "appended_at": "2026-09-12T09:00:00Z", "payload_digest": "9f3c…", "superseded": null, "markdown_bytes": 812, "block_count": 2, "phase": null }, "sealed": false, "not_evidence": "…", "dashboard_url": "https://mostlyright.md/datasets/d31017e0"}--list answers status: "dataset_notes_listed" with cell_count, rendered_count, source_truncated and cells numbered note 1, note 2. A cell is not sealed. No receipt quotes it, and it is not evidence about a run. Every narrative payload asserts "sealed": false and refuses a Studio answer that does not.
{ "schema_version": "mostlyright-thin-client-v4-dataset-activity.v1", "status": "dataset_activity_reported", "lane": "hosted", "dataset_id": "d31017e0", "phase": "building", "message": "Fetching 20 city stations", "transition": "changed", "expires_at": "2026-09-12T09:02:00Z", "sequence": 12, "dashboard_url": "https://mostlyright.md/datasets/d31017e0", "facts": { "sources_probed": 18 }}A report that named no counters carries no facts. transition says whether the page moved or the expiry alone was renewed.
{ "schema_version": "mostlyright-thin-client-v4-dataset-watch.v1", "status": "dataset_stream_ended", "lane": "hosted", "dataset_id": "d31017e0", "dashboard_url": "https://mostlyright.md/datasets/d31017e0", "ended_because": "stream_closed", "event_count": 41, "last_event": {}, "stream": { "last_event_id": "41-…", "last_sequence": 41, "events_seen": 41, "reconnects": 0 }}ended_because is stream_unavailable when the stream could not be followed at all. stream is then {}.
{ "schema_version": "mostlyright-thin-client-v4-dataset-current-state.v1", "status": "dataset_state_reported", "lane": "hosted", "dataset_id": "d31017e0", "current_state": {}, "source_inventory": null, "recording_membership": {}, "event_history": {}}{ "schema_version": "mostlyright-thin-client-v4-dataset-archived.v1", "status": "dataset_archived", "lane": "hosted", "dataset_id": "d31017e0", "name": "Kalshi hourly BTC", "version": 9, "dashboard_url": "https://mostlyright.md/datasets/d31017e0", "note": "The dataset is retired and the title 'Kalshi hourly BTC' is free for another one. Nothing built was deleted: every run, artifact, version and decision cell stays where it is."}{ "schema_version": "mostlyright-dataset-categories.v1", "version": 1, "assignment_policy": "Exactly one primary category, chosen from the dataset purpose, tables and measured entities. …", "categories": [{ "id": "crypto", "label": "Crypto", "definition": "Cryptocurrencies, blockchain networks, DeFi and digital-asset markets." }]}Errors
Section titled “Errors”| Code | When |
|---|---|
THIN_REQUEST_INVALID |
A verb that needs DATASET_ID got none. draft without --expected-version or without --description-file. A state paging flag without its pair. A flag belonging to another writing verb. archive without --confirm-name. |
THIN_CONFIRMATION_MISMATCH |
archive, where --confirm-name does not match the title Studio holds. Archiving releases the title, so the title confirms it. |
THIN_DATASET_VERSION_CONFLICT |
The dataset moved twice under a set, or once under an archive. Somebody else is editing it. Read it with mr-data dataset show and write again. archive never retries on its own, because a racing set may have rewritten the title that confirmed it. |
THIN_CLOUD_PUBLIC_SHARING_DISABLED |
publish, where this organization does not allow datasets to be shared publicly. |
THIN_CLOUD_PUBLISHER_PROFILE_REQUIRED |
publish, where this organization has no publisher name yet. Set it under the team’s settings. |
THIN_CLOUD_STEP_UP_REQUIRED |
publish, where publishing needs a verification only a signed-in browser can finish. Open the dashboard page and share it from there, or hand yourself the page with mr-data open. |
THIN_NARRATIVE_CELL_TOO_LARGE |
note, where the heading runs over 200 characters or the markdown body over 65536 bytes. |
THIN_NARRATIVE_CELL_CONTROL_CHARACTER |
note, where the body carries a control character other than tab and newline. The command refuses a carriage return rather than stripping it. |
THIN_NARRATIVE_REVISION_INVALID |
note --revise naming the cell’s own identifier. Reusing the identifier is the revision. |
THIN_RESPONSE_INVALID |
Studio answered without a dataset_id, without a version a conditional write needs, without saying how the dataset is shared, or described a narrative cell as sealed. |
THIN_ACTIVITY_BUDGET_SPENT |
The automatic activity report ran out of its 1.5-second budget. It never fails the command it rides beside. |
publish also carries Cloud’s own sentence after this client’s, with its author named.
Example
Section titled “Example”DATASET_ID=$(mr-data dataset create --name "US city temperature history" --json | jq -r .dataset_id)mr-data open "/datasets/$DATASET_ID" --open
mr-data dataset set "$DATASET_ID" \ --name "US city temperature history, 20 metros" \ --category climate-environment \ --topics "weather,temperature,cities" \ --license CC-BY-4.0 \ --description-file description.md
mr-data dataset publish "$DATASET_ID" --mode public --jsonThe category vocabulary
Section titled “The category vocabulary”Exactly one primary category, chosen from the dataset purpose, tables and measured entities. Prefer the principal subject over its source, cadence, format or secondary variables. Preserve the assignment on refresh. other requires a recorded reason.
--category |
Label | Definition |
|---|---|---|
climate-environment |
Climate & Environment | Weather, climate, pollution, ecosystems and environmental measurements. |
crypto |
Crypto | Cryptocurrencies, blockchain networks, DeFi and digital-asset markets. |
finance |
Finance | Banking, securities, investment, insurance and financial-market activity. |
economics-business |
Economics & Business | Economic indicators, businesses, commerce, industry and consumer activity. |
government-politics |
Government & Politics | Elections, public policy, government institutions and administration. |
people-society |
People & Society | Population, demographics, communities, social conditions and human behavior. |
health-medicine |
Health & Medicine | Clinical medicine, healthcare, diseases and public health. |
science-research |
Science & Research | Physical and natural sciences, experiments, astronomy and general research metadata. |
technology |
Technology | Software, computing, AI, internet and telecommunications. |
energy |
Energy | Electricity, fuels, energy production, consumption and supply infrastructure. |
agriculture-food |
Agriculture & Food | Farming, livestock, fisheries, food production and food systems. |
transport-mobility |
Transport & Mobility | Movement of people and goods by road, rail, air and sea. |
places-infrastructure |
Places & Infrastructure | Geography, maps, property, buildings, housing and non-energy infrastructure. |
education |
Education | Schools, universities, learning, students and educational outcomes. |
sports |
Sports | Sports competitions, athletes, teams and athletic performance. |
arts-media-entertainment |
Arts, Media & Entertainment | Culture, arts, news media, music, film, gaming, esports and audience activity. |
law-public-safety |
Law & Public Safety | Legal systems, courts, crime, policing and emergency response. |
other |
Other | A meaningful subject not covered by any category after reviewing its definitions. |
mr-data dataset categories --json prints this table from the copy in the wheel, which reads offline.
mr-data cover DATASET_ID SUBJECT [--json]mr-data cover generates one branded cover image and attaches it to a dataset. Describe what the image should depict. Studio chooses the single-colour style, the palette, the model and the dimensions. Each invocation picks a new curated colour and composition, so run it again for a different cover. There is no style flag.
| Flag | Argument | Required | Meaning | Default |
|---|---|---|---|---|
DATASET_ID |
id | yes | The dataset the cover goes on. | none |
SUBJECT |
text | yes | What the image should depict, in plain language. Style and dimensions are fixed. | none |
--json |
none | no | One JSON object instead of human lines. | off |
{ "schema_version": "mostlyright-thin-client-v4-dataset-cover.v1", "status": "dataset_cover_generated", "lane": "hosted", "dataset_id": "d31017e0", "cover_image_url": "https://…", "width": 1200, "height": 630, "media_type": "image/webp", "color": { "name": "cobalt", "hex": "#2447C4" }, "model": "…", "style_policy": "mostlyright-single-ink-editorial-v1", "estimated_cost_usd": "0.101", "sha256": "9f3c…", "generated_at": "2026-09-12T09:00:00Z"}width, height, media_type, style_policy and estimated_cost_usd are fixed. The command
checks the response against those values before printing its receipt. Any mismatch produces
THIN_RESPONSE_INVALID. color.hex is # followed by six uppercase hexadecimal digits. A
lowercase value indicates drift.
Errors: THIN_REQUEST_INVALID for a SUBJECT over 600 characters. THIN_RESPONSE_INVALID for a drifted answer, a non-HTTPS image URL, a bad sha256, or a timestamp that is not YYYY-MM-DDTHH:MM:SS(.fff)Z. THIN_NOT_FOUND for a dataset that is not yours or does not exist.
mr-data cover "$DATASET_ID" "a thermometer over a city skyline at dusk" --jsonSee also
Section titled “See also”- CLI reference: conventions, exit codes, environment variables
- Tables: the tables this dataset holds
- Runs: the run-scoped decision record
notehas a twin of