velven
Menu

Publish with an agent

A coding agent or a chat assistant can put a space on Velven for its creator. There are three ways in. A coding agent publishes the build with the Velven CLI. An assistant in a chat publishes through Velven's MCP server. A space that's already live on another host is listed through the API. Every time, the creator approves the sign-in in their browser, so nobody copies a key by hand.

View as Markdown

Choose a way in

You are
A coding agent with a terminal, and the space is a folder or a build
Use
The Velven CLI: npx @velven/cli publish.
You are
An assistant in a chat, such as Claude or ChatGPT
Use
Velven's MCP server, with one page or a few files.
You are
Any agent, and the space is already live on one of the 7 supported hosts
Use
The listing API, in the steps below.

Ask the creator for the space's title and the devices it works on, or take them from what they've already told you. Don't guess. These are what people see on the listing.

Publish with the CLI

Run publish with two flags: --json, so it prints one JSON object, and --yes, so it never stops at a prompt. Every flag and exit code is in the CLI reference.

Terminal
# prints a code and a link: show both to the creatornpx @velven/cli loginnpx @velven/cli publish ./dist --title "Orbit Dodger" --devices desktop,mobile --yes --json# when the creator asks to go livenpx @velven/cli publish ./dist --prod --yes --wait --json
  • login prints a code and an approval link, then waits for the creator to approve. Show them both. The token is saved in ~/.config/velven/auth.json and used for this creator's later publishes.
  • The first publish writes velven.json into the folder, with "space" in it. Keep the file: it's how later publishes update the same space.
  • A plain publish answers status: "preview" and a previewUrl. Show the creator the preview.
  • --prod usually answers status: "live" with pageUrl right away. Or it answers refused, with a reason that names the file, and exits 6. Sometimes a version waits on Velven instead, usually under a minute. Then it answers status: "publishing" and a watchUrl, where the creator can follow it. With --wait, the CLI waits for it, up to 20 minutes. It then answers live with pageUrl. Or it answers refused, or unjudged when Velven could not tell what the page shows, with reason and shownOnTake (what Velven saw on the page), and exits 6.
  • For unjudged, add a start hint to velven.json, such as "start": { "click": "Play" }, and publish again. For refused, tell the creator the reason. They can press Ask for review at watchUrl. The exception is a program or a miner, which is never served: the creator removes the file and publishes again.

Without login, the same publish makes an unlisted page. It's published the same way, but it has no preview. The answer has pageUrl, claimToken, claimUrl, expiresAt and terms. Show the creator all of them. Tell them two things: the page is deleted after 7 days unless they claim it, and publishing means they agree to Velven's Terms. To claim it, run login and publish again from the same folder.

Publish from a chat with the MCP server

Velven's MCP server is at https://mcp.velven.ai/mcp (Streamable HTTP). Add it to an assistant as a custom connector. For Claude Code, install the plugin or run one command:

Terminal
claude mcp add --transport http velven https://mcp.velven.ai/mcp
Tool
publish
What it does
Publishes one HTML page or a few files, as a new space or as a new version of space. You get a private preview by default. With prod: true, the version goes live.
Sign-in
Optional
Tool
my_spaces
What it does
Lists the account's spaces, newest first, up to 100. Each has slug, title, status, hosted and pageUrl.
Sign-in
Needed
Tool
versions
What it does
Lists the versions of the hosted space in space, newest first. Each has its number and status, the reason if it was refused, and rollback: whether it can go live again.
Sign-in
Needed
Tool
rollback
What it does
Puts version of space live again, right away. It only works for a version that was live before.
Sign-in
Needed
Tool
search_docs
What it does
Searches these docs for query and answers the best sections, with links.
Sign-in
None

The publish tool's inputs

htmlstring
A whole page as one HTML string. It's published as index.html. Send this or files.
filesobject
Files by relative path. Send text as a string and a binary file as { "base64": "…" }. Up to 500 files and 3 MB in all. Include the entry page.
entrystringDefault index.html
The page that opens first.
titlestring, up to 80 characters
Required for a new space.
devicesa list of desktop, mobile, vr
Required for a new space.
descriptionstring, up to 160 characters
One line, shown under the name.
enginestring
One of the allowed engines.
spacestring
The slug of the creator's space, to publish a new version of it. Needs sign-in.
claimstring
The claim token of an unlisted page. Publishes the page's next version. If you're signed in, it also claims the page.
prodbooleanDefault false
Publish the version live on its Velven page instead of making a preview. Needs sign-in.
spabooleanDefault false
Serve the entry page for any path that has no file. Use it for client-side routing.
sdkbooleanDefault true
Add the Velven SDK's script tag to the entry page.
thumbnailstring
The picture on the space's tile: the path of one of the files. Use a JPEG, PNG or WebP, up to 2 MB and 4096 pixels on each side.
clipstring
The video the tile plays on hover, without sound: the path of one of the files. Use an MP4 or WebM, up to 3 MB and 5 to 10 seconds long. When you send one, Velven doesn't record a clip. Without a thumbnail, the clip's first frame becomes the picture. Both must show the space itself.

Some files are always left out and never published: a velven.json, dotfiles, dot-folders and node_modules, in any folder. The answer lists the first 10 in leftOut and counts them all in leftOutCount. Send velven.json's settings as the tool's inputs instead. The tool has no input for a start hint, leaderboards or achievements. For those, publish the folder with the CLI.

What publish answers

Every answer has space (the slug), version, status and pageUrl. A preview also has previewUrl, a private link that lasts 24 hours, and watchUrl, the version on the space's Files tab. With prod: true, the answer is usually status: "live", or refused with a reason. Sometimes a version waits on Velven instead and answers status: "publishing" and a watchUrl. It goes live or is refused, usually within a minute. Call versions to follow it.

When a tool needs an account, the app asks the creator to sign in to Velven and approve the connection in their browser. Without signing in, publish makes an unlisted page, published the same way. It answers pageUrl, claimToken, claimUrl, expiresAt and terms. Show the creator every one. Tell them to keep the token: it's the only way to update the page or keep it past 7 days. To publish the page's next version, publish again with claim set to the token. If the creator is signed in, the same call claims the page.

Note: Without signing in, prod: true answers sign_in_required, and a publish that names space makes the app ask the creator to sign in. An unlisted page has no previews: every publish to it goes live on the page.

Note: For a folder over 3 MB or 500 files, or when you have a terminal, use the CLI.

List a live URL with the API

If a space is already live on one of the 7 supported hosts, you can list it where it is, without uploading its files. It stays on its host. Velven plays it in a frame on its Velven page, records its clip and counts its plays. For a person on the add page, the same flow is Link a live URL.

The 5 steps below sign in as the creator, put the proof on the site, submit the listing and reply to the creator. The sign-in is the same device-code flow velven login runs, and it gives the same kind of token.

After the steps, the sections below use that token on the creator's spaces. They cover writing a space's page, asking for a new clip, adding leaderboards, claiming a space Velven listed and moving a space to a new address. Every other call is in the REST API.

Ask for a sign-in link

Make one call, with no token. agent_name is optional, up to 60 characters. The creator sees it on the approval screen.

Terminal
curl -s -X POST https://velven.ai/api/agent/login \  -H "content-type: application/json" \  -d '{"agent_name":"Claude Code"}'

The response, with status 201:

JSON
{  "device_code": "a3Vw…",  "user_code": "K7PX-4MDQ",  "verification_url": "https://velven.ai/agent/approve?code=K7PX-4MDQ",  "expires_in": 900,  "interval": 5}

Keep device_code to yourself. Show the creator verification_url and user_code. The code lasts 15 minutes.

Status
400
Body
{ "error": "invalid_request", "message" }
Meaning
The body wasn't JSON, or agent_name is over 60 characters.
Status
429
Body
{ "error": "rate_limited", "message" }
Meaning
This address asked for more than 20 sign-in links in 15 minutes. Wait. Don't retry in a loop.
Status
500
Body
{ "error": "server_error" }
Meaning
Something went wrong on Velven's side. Try again in a moment.

Wait for the creator to approve

Tell the creator: "Open this link and press Approve. The code on the page should read K7PX-4MDQ." If they aren't signed in to Velven, the same screen signs them in with GitHub, Google or an email link, and asks them for a handle.

Meanwhile, poll for the token every interval seconds. Give up after expires_in seconds:

Terminal
curl -s -X POST https://velven.ai/api/agent/token \  -H "content-type: application/json" \  -d '{"device_code":"<device_code>"}'
Status
200
Body
{ "access_token", "token_type": "bearer", "handle", "profile_url" }
What to do
Approved. Store the token. You get it once, and it lasts 90 days.
Status
428
Body
{ "error": "authorization_pending", "interval": 5 }
What to do
Not decided yet. Wait interval seconds and poll again.
Status
403
Body
{ "error": "access_denied" }
What to do
The creator pressed Deny. Stop and tell them.
Status
400
Body
{ "error": "expired_token" }
What to do
15 minutes passed, or the code is unknown. Start over from step 1.
Status
400
Body
{ "error": "invalid_grant" }
What to do
This device code was already exchanged. Use the token you have, or start over.
Status
400
Body
{ "error": "invalid_request" }
What to do
The body wasn't { "device_code": "…" }. Fix the request.
Status
5xx
Body
{ "error": "server_error" }, or no answer
What to do
Something went wrong on Velven's side. Keep polling until expires_in runs out.

Store the token at ~/.config/velven/token with mode 600, and reuse it for this creator's later spaces. A token belongs to one creator. It works on the endpoints on this page and in the REST API, in the CLI as VELVEN_TOKEN, and on the MCP server as a bearer token. A token saved by velven login in ~/.config/velven/auth.json works here too.

If a call answers 401, the token expired, the creator revoked it in their settings, or the account is banned. Delete the file and sign in again.

To check who a token belongs to:

Terminal
curl -s https://velven.ai/api/agent/me -H "authorization: Bearer $VELVEN_TOKEN"
JSON
{ "handle": "mara", "profile_url": "https://velven.ai/mara" }

Put the proof on the site

Only a verified creator can list a space, so the proof goes on the site before you submit. Add this tag to the page's <head>, using the handle from the token response. Then deploy again:

HTML
<meta name="velven" content="@handle">

Wait until the deploy is live before you submit. If you submit too early, the answer is 409, with the change still needed. Velven lists spaces on Vercel, Netlify, GitHub Pages, Cloudflare, Replit, Firebase and ChatGPT sites. Linking a live URL has the details for each host, including the framing header a page must allow.

Note: Publish a ChatGPT site with "Who has access" set to "Anyone on the Internet". A site only its owner can open answers 401, and Velven can't verify it.

Submit the space

Fill in the details from the project instead of asking the creator. Take the engine from package.json and the imports, the AI tools from yourself, the devices from the pointer and touch handling, and the description from the README. Velven fetches the URL and checks the proof. Anything you leave out, it fills in from the page: the title, the meta description, the engine from its scripts and the AI tool from its markup. What you send always wins.

Terminal
curl -s -X POST https://velven.ai/api/spaces \  -H "authorization: Bearer $VELVEN_TOKEN" \  -H "content-type: application/json" \  -d @- <<'JSON'{  "url": "https://orbit-dodger.netlify.app",  "title": "Orbit Dodger",  "description": "Dodge debris in a decaying orbit. Arrow keys or swipe.",  "engine": "three.js",  "models": ["claude-opus-5"],  "ai_tools": ["claude-code"],  "devices": ["desktop", "mobile"],  "source_url": "https://github.com/mara/orbit-dodger"}JSON
Field
url
Required
Yes
Notes
The space's public http(s) URL. Velven stores it after following redirects.
Field
devices
Required
Yes
Notes
An array with at least one allowed value.
Field
title
Required
No
Notes
Up to 80 characters. Defaults to the page's og:title or <title>.
Field
description
Required
No
Notes
One line, up to 160 characters. Defaults to the page's og:description or meta description.
Field
engine
Required
No
Notes
An allowed value. If you leave it out, Velven reads it from the page's scripts. Send null for none.
Field
models
Required
No
Notes
An array of the models that wrote it.
Field
ai_tools
Required
No
Notes
An array of the tools the model ran in. If you leave it out, Velven reads it from the page's markup. Send [] for none.
Field
source_url
Required
No
Notes
The repository's URL.
Field
about, how_to_play, controls, features, faq, orientation, players
Required
No
Notes
The text of the space's page. See Your space's page.

The response, with status 201. The page exists right away on the creator's handle. While status is processing, only the creator can see it. It goes public as published a few minutes later, once Velven has recorded its clip and thumbnail.

JSON
{  "slug": "orbit-dodger",  "url": "https://velven.ai/mara/orbit-dodger",  "status": "processing",  "title": "Orbit Dodger"}

If the page carries a boards block, the answer also has boards, the keys Velven synced from it. Or it has boards_error, which says why Velven didn't take the block.

Status
401
Body
{ "error": "unauthorized" }
Meaning
The token is missing, revoked or unknown. Sign in again.
Status
403
Body
{ "error": "blocked", "message" }
Meaning
This URL can't be listed. Velven removed it before, it's on Velven's blocklist, or it's listed as malware or phishing. message says which.
Status
409
Body
{ "error": "unverified", "message", "instruction", "snippet" }
Meaning
The proof isn't on the live site yet. Make the change instruction describes, deploy, wait for the host's cache, and call again. Don't retry more than a few times without changing something.
Status
409
Body
{ "error": "duplicate", "message", "url" }
Meaning
It's already on Velven, and url is its page. If message says to claim it, claim it.
Status
422
Body
{ "error": "invalid", "issues": [{ "path", "message" }] }
Meaning
Fix the fields listed and retry. An issue on url can also mean Velven doesn't list that host.
Status
422
Body
{ "error": "unreachable", "message", "instruction" }
Meaning
The URL didn't answer (a timeout, a DNS failure, a refused connection), or it's closed to visitors (a Vercel deployment behind Vercel Authentication, or a site shared only with its owner). Check that the deployment is public and call again. instruction says how to open it, and comes only with a closed page.
Status
422
Body
{ "error": "unframeable", "message", "instruction", "snippet" }
Meaning
The site's headers don't let Velven frame it. Make the change instruction describes (see the steps for each host), deploy, and call again.
Status
500
Body
{ "error": "server_error", "message" }
Meaning
Something went wrong on Velven's side. Retry once after a moment. If it keeps failing, tell the creator.

Reply to the creator

Reply with the url, and offer the badge for the README:

HTML
<a href="https://velven.ai/mara/orbit-dodger"><img src="https://velven.ai/badge/orbit-dodger" alt="On Velven"></a>

To see the creator's spaces, newest first, leaving out any Velven removed:

Terminal
curl -s "https://velven.ai/api/spaces?mine=1" -H "authorization: Bearer $VELVEN_TOKEN"
JSON
[{ "slug": "orbit-dodger", "title": "Orbit Dodger", "url": "https://orbit-dodger.netlify.app", "plays": 412, "upvotes": 18, "velven_url": "https://velven.ai/mara/orbit-dodger" }]

Your space's page

Under the frame, the space's page says what the space is, how to play it and which keys do what. Velven writes this text from its own recording. But you know the project better, so write it from the code and send it with the listing, or change it later. Every field you send belongs to the creator. Velven's recording never writes over it, not even a field you cleared.

Take the controls from the input handlers (the key bindings, the pointer and touch events). Take the goal and the rules from the game logic, and the features from what the project actually does. Write plainly, in the second person, for someone about to play. If the space isn't a game, leave out how_to_play and controls when they don't apply.

Field
about
Limit
Up to 1500 characters
Notes
What the space is, in a paragraph or two.
Field
how_to_play
Limit
Up to 1000 characters
Notes
The goal and how to reach it.
Field
controls
Limit
Up to 4 groups, 12 rows in all
Notes
Groups of { "label", "rows": [{ "input", "action" }] }. label is optional, up to 40 characters. input is up to 40, such as W, Space or Mouse drag. action is up to 80.
Field
features
Limit
Up to 6 items, 100 characters each
Notes
Short lines on what sets the space apart.
Field
faq
Limit
Up to 8 pairs
Notes
{ "q", "a" }: a question up to 150 characters and an answer up to 500. Only the creator writes this. Velven never does.
Field
orientation
Limit
One value
Notes
landscape, portrait, any: how the space is meant to be held on a phone.
Field
players
Limit
One value
Notes
single single player, multi multiplayer.

In the body of POST /api/spaces, beside the other fields:

JSON
{  "about": "Orbit Dodger drops you into a decaying orbit full of debris. Every lap is faster than the last.",  "how_to_play": "Stay alive as long as you can. Collect fuel cells to climb back to a higher orbit.",  "controls": [    { "label": "Keyboard", "rows": [{ "input": "Left / Right", "action": "Thrust" }, { "input": "Space", "action": "Boost" }] },    { "label": "Touch", "rows": [{ "input": "Swipe", "action": "Thrust" }] }  ],  "features": ["Procedural debris field", "A new orbit every run"],  "orientation": "landscape",  "players": "single"}

Sometimes the listing is made but its page text can't be saved. Then the 201 response carries "page_not_written": true. The space is still listed, without the text. Send the same fields again with PATCH /api/spaces/{slug}.

To read the page as it stands, call GET /api/spaces/{slug}. page_authors says who wrote each field: model for Velven, creator for you. To change the page, send any of these fields to PATCH /api/spaces/{slug}. You can also send any of the listing's own fields (title, description, engine, models, ai_tools, devices, source_url). Only the fields you send change, and null clears one. Both calls answer with the space's fields.

Terminal
curl -s https://velven.ai/api/spaces/orbit-dodger -H "authorization: Bearer $VELVEN_TOKEN"curl -s -X PATCH https://velven.ai/api/spaces/orbit-dodger \  -H "authorization: Bearer $VELVEN_TOKEN" \  -H "content-type: application/json" \  -d '{ "features": ["Procedural debris field", "Daily seed"], "faq": null }'
Status
200
Body
The space's fields, page_authors and velven_url
Meaning
Read, or changed.
Status
401
Body
{ "error": "unauthorized" }
Meaning
The token is missing, revoked or unknown. Sign in again.
Status
404
Body
{ "error": "not_found" }
Meaning
No space with that slug on this account.
Status
422
Body
{ "error": "invalid", "issues": [{ "path", "message" }] }
Meaning
Fix the fields listed. A field that can't be changed is refused by name. To change url, move the space with POST /api/spaces/{slug}/move.
Status
500
Body
{ "error": "server_error", "message" }
Meaning
Saving failed. The message says whether the page text was saved (page_written) while the other fields weren't. Send again whatever didn't land.

Keep the clip current

After listing, Velven plays the space in its own browser and records a 5-second clip. The clip's first frame becomes the thumbnail. When the site is rebuilt, Velven's background check notices the change and records again, at most once a day. A space published on Velven gets its clip after its first version goes live, unless its velven.json supplies one. A clip the creator uploaded is never replaced.

After a deploy that changes how the space looks, ask for a retake right away. note is optional: up to 100 characters on what the clip should show, such as a mode, a moment or something to avoid. The creator gets 2 retakes per space. The background check's own retakes don't count.

Terminal
curl -s -X POST https://velven.ai/api/spaces/recapture \  -H "authorization: Bearer $VELVEN_TOKEN" \  -H "content-type: application/json" \  -d '{ "slug": "orbit-dodger", "note": "start after the title screen, night mode" }'
Status
202
Body
{ "slug", "status" }
Meaning
Queued, or already queued or running. status says which. The clip lands within a few minutes.
Status
401
Body
{ "error": "unauthorized" }
Meaning
The token is missing, revoked or unknown. Sign in again.
Status
404
Body
{ "error": "not_found" }
Meaning
No published or processing space with that slug on this account.
Status
409
Body
{ "error": "no_retakes_left" }
Meaning
Both retakes are used. The background check still records again when the page changes.
Status
422
Body
{ "error": "invalid", "issues" }
Meaning
The body wasn't { slug, note? }, or note is over 100 characters.
Status
503
Body
{ "error": "capture_off" }
Meaning
Recording is paused on Velven's side. There's nothing to fix. Try later.

Leaderboards and sign-in

If the space keeps a score, give it a hosted leaderboard and sign-in with the Velven SDK. The SDK guide covers all of it, and https://velven.ai/docs/sdk.md is the same guide as one file for you to read. In short, load the script or install @velven/sdk. Declare the boards in a <script type="application/velven+json"> block beside the proof tag, or in velven.json for a space published on Velven. Then post scores with Velven.scores.submit. The space draws its own boards from top and around. A board declared with display page or both also shows on its Velven page. Achievements are declared the same way.

HTML
<meta name="velven" content="@handle"><script type="application/velven+json">{"boards":[{"key":"main","trust":"client","metric":"points","sort":"desc"}]}</script><script src="https://velven.ai/sdk/v1.js"></script>

Choose a tier for each board. trust: "server" is the default. It takes posts only from the space's own server, with the space's secret and the player's token. If the page posts to it, the answer is server_only. trust: "client" takes the page's posts within a range, a cooldown and caps. A space with no backend uses client, as in the snippet above. Server scores helps you choose.

A server board needs the secret. You issue it with the creator's token, and it's shown once. Put it in the host's server environment, never in the page:

Terminal
curl -s -X POST https://velven.ai/api/spaces/<slug>/secret -H "authorization: Bearer $VELVEN_TOKEN"

You can also declare or change boards without a deploy, in the same shape as the block. Only the boards you send are written. The page's next sync overwrites any key it also declares:

Terminal
curl -s -X PUT https://velven.ai/api/spaces/<slug>/boards \  -H "authorization: Bearer $VELVEN_TOKEN" \  -H "content-type: application/json" \  -d '{"boards":[{"key":"main","trust":"client","metric":"points","sort":"desc","min":0,"max":100000,"cooldown":5}]}'

To read the boards, see the REST API. To delete a submission or ban a player, see Moderation.

Claim a space Velven listed

Velven lists some spaces itself, credited to their creators, at /s/slug, each with a “Made this? Claim it” line on its page. A duplicate answer on submit can point at one. Once the proof is on the site, claim it for the creator. Its plays stay, and it moves to their handle.

An unlisted page published without an account is claimed with its token instead. Run velven login and publish again from the folder that holds its velven.json, or have the creator open the claim link.

Terminal
curl -s -X POST https://velven.ai/api/spaces/verify \  -H "authorization: Bearer $VELVEN_TOKEN" \  -H "content-type: application/json" \  -d '{ "slug": "orbit-dodger" }'
Status
200
Body
{ "verified": true, "slug", "url" }
Meaning
Done. url is now the creator's page, /handle/slug.
Status
403
Body
{ "error": "blocked" }
Meaning
This account can't claim spaces. Tell the creator and stop.
Status
404
Body
{ "error": "not_found" }
Meaning
No published space has that slug, or Velven hosts it. An unlisted page is claimed with its token.
Status
409
Body
{ "error": "unverified", "instruction", "snippet" }
Meaning
The proof isn't on the live site yet. Deploy, wait, and call again.
Status
409
Body
{ "error": "owned" }
Meaning
Someone else already verified it. Tell the creator. They can let Velven know with Feedback on the space's page.
Status
422
Body
{ "error": "invalid", "issues" }
Meaning
The body wasn't { slug }.

Move to another host

When the space moves to a new URL, move its listing with it. Its slug, plays, likes, boards, scores, saves and page text all stay. Velven checks the new page the same way it checks a listing. So first put the proof tag on the new page and allow framing there. Deploy, then call:

Terminal
curl -s -X POST https://velven.ai/api/spaces/orbit-dodger/move \  -H "authorization: Bearer $VELVEN_TOKEN" \  -H "content-type: application/json" \  -d '{ "url": "https://orbit-dodger.vercel.app" }'

It answers with the space's fields, as GET /api/spaces/{slug} does, plus previous_url. Every refusal and its code is in the REST API.

A space published on Velven moves back to a live URL with the same call, and Velven stops hosting it. To move a linked space onto Velven's hosting instead, publish its files with the CLI. See Move a linked space onto Velven.

  • Velven reads the boards block on the new page. If the old page declared a board and the new one doesn't, that board is withdrawn and its scores are kept.
  • If a server posts scores, set the board secret in the new host's server environment. Copy the existing one if you have it. Or issue a new one with POST /api/spaces/{slug}/secret. That replaces the old secret at once, so the old host stops posting.
  • From the move on, identity tokens name the new origin as their audience (aud). A server that checks aud must expect the new origin. Tokens issued before the move carry the old one for up to an hour.
  • The old origin keeps its localStorage, so a game that saves there starts empty on the new one. Velven.data saves belong to the space and move with it.

Allowed values

engine

  • three.js Three.js
  • r3f React Three Fiber
  • babylon.js Babylon.js
  • playcanvas PlayCanvas
  • a-frame A-Frame
  • godot Godot web
  • unity Unity web
  • phaser Phaser
  • p5.js p5.js
  • canvas Canvas / vanilla JS
  • webgl WebGL / shaders
  • webgpu WebGPU / shaders
  • wasm WebAssembly
  • dom HTML / DOM
  • marble Marble
  • spline Spline
  • other Other

models

  • claude-fable-5.1 Claude Fable 5.1
  • claude-opus-5.5 Claude Opus 5.5
  • claude-opus-5 Claude Opus 5
  • claude-sonnet-5.5 Claude Sonnet 5.5
  • claude-sonnet-5 Claude Sonnet 5
  • gpt-6.1-sol GPT-6.1 Sol
  • gpt-6-astra GPT-6 Astra
  • gpt-6-sol GPT-6 Sol
  • gpt-6-luna GPT-6 Luna
  • gpt-5.6-sol GPT-5.6 Sol
  • gemini-3.8-flash Gemini 3.8 Flash
  • muse-spark-1.3 Muse Spark 1.3
  • grok-4.7 Grok 4.7
  • grok-4.6 Grok 4.6
  • kimi-k3 Kimi K3
  • glm-5.3 GLM-5.3
  • jev Jev
  • other Other

ai_tools

  • claude-code Claude Code
  • claude Claude
  • cursor Cursor
  • codex Codex
  • copilot GitHub Copilot
  • gemini Gemini
  • windsurf Windsurf
  • lovable Lovable
  • bolt Bolt
  • v0 v0
  • replit Replit
  • marble Marble (world model)
  • muse-code Muse Code
  • grok-build Grok Build
  • kimi-code Kimi Code CLI
  • opencode Opencode
  • devin Devin
  • other Other

devices

  • desktop Desktop
  • mobile Mobile
  • vr VR headset

In the browser

If you drive a browser instead, Velven's pages offer their actions as WebMCP tools on document.modelContext. Call those instead of reading the page: search_spaces on every page; start_game on /create; send_game_message and publish_game on a game in the builder; inspect_space_url and publish_space on /add; check_claim and claim_with_token on a claim page; enter_space, upvote_space, save_space and report_space on a space page; email_sign_in_link and choose_handle on sign-in.

On the add page, inspect_space_url works signed out. publish_space needs the creator signed in. If the proof is already on the site, it lists the space right away. If not, it keeps the details and shows the proof steps. Then it checks the site again every 20 seconds while the tab is in front, for about 15 minutes. Upload files on the add page has no tool, so publish files with the CLI or the MCP server. Chrome ships WebMCP in an origin trial. Other browsers see the same pages without the tools.

Note: If your agent uses skills, it can install Velven's onboard skill, which carries this whole flow. See Agent skills.