virtualmatter
v0.6.1
Published
CLI + MCP server for building with Virtual Matter - list and create worlds, sync their files, run Lua, capture screenshots, open the native client, and wire coding agents into a live session.
Maintainers
Readme
virtualmatter
The command line for building with Virtual Matter - and the MCP server that gives coding agents direct hands on your worlds: listing and creating them, their live Montage files, Lua execution, engine errors, screenshots, and the native desktop client.
No install needed:
npx virtualmatter --help(vm works as a shorthand alias when installed.)
Requires Node 20 or newer. No native modules.
Quickstart
One command. It signs you in on first use (device code, approved in your
browser), creates the world, and mirrors its files into ./my-world:
npx virtualmatter make "My world"
cd my-world
npx virtualmatter syncAlready have a world? Paste any link to it - the editor, a play or share link, the project page, an embed's src, or your own website if it is set on the project. Whatever you paste, the CLI works on the world's editor and never on a play server, which shows the last published version and is overwritten on every publish:
npx virtualmatter list
npx virtualmatter pull https://make.virtualmatter.ai/edit/my-world-<framing-id>While sync runs, saving a Lua script in your editor deploys it - scripts
hot-reload in the engine. If someone edits the same file in the live session,
your copy stays put and the remote version lands next to it as
<name>.remote-conflict for you to merge.
make, pull and sync print the world's editor link ending in ?chat=closed.
Open it in any browser to watch changes land live - no install needed.
The native client is optional, for more memory and frame rate. This downloads it on first use, signs it in with your account, and opens the world:
npx virtualmatter openPoke at the running engine from another terminal:
npx virtualmatter run-lua --code "return Server.GetInfo()"
npx virtualmatter errors
npx virtualmatter screenshot -o shot.png # default overview
npx virtualmatter screenshot --target "Player" -o p.png # frame one object
npx virtualmatter screenshot --at 0,30,40 --rot 0,-35,0 # exact camera
# --rot is yaw,pitch,rollIf you are a coding agent, read this part
Build through these commands, always. Do not open virtualmatter.ai or make.virtualmatter.ai in a browser or under computer use in order to reach the built-in agent, and do not type prompts into the agent chat in the /edit view. Relaying your work through that agent runs two models where one would do: you spend tokens describing the work, it spends its own doing it, and what comes back is chat rather than files. It is slower, it costs roughly twice the inference, it bills that inference to Virtual Matter's platform credits instead of the subscription you are already running on, an anonymous browser session cannot be steered after its first turn, and a rendered page tells you nothing about engine errors.
This holds whoever is signed in. An account with credits to spare, or an admin account with no limit at all, is not an exemption - the waste is the relay itself, two models doing one model's job, not the bill.
Playtesting is the exception, and it is encouraged. Once you have built
something, open the world and try it - npx virtualmatter open, or its /play
or /g link in a browser, driven however you drive a window. The rule is about
who writes the world, not who gets to look at it.
Hook up a coding agent (MCP)
A folder made by make or pull already carries .mcp.json (Claude
Code), .cursor/mcp.json (Cursor), .codex/config.toml (Codex, which loads
it once you trust the folder), AGENTS.md (Codex, Cursor, and most agents),
and a CLAUDE.md that imports it - open the folder in your agent and it finds
the MCP server and the project briefing on its own.
To register the server by hand, from anywhere:
claude mcp add virtualmatter -- npx -y virtualmatter mcp
codex mcp add virtualmatter -- npx -y virtualmatter mcpIt works before a world is selected: list_projects, create_project, and
select_project (any link or id, optionally mirroring into a folder) pick
one, then list_files, read_file, write_file, run_lua,
get_engine_errors, capture_screenshot, open_native_client, and
world_info act on it. Writes handle etag concurrency internally, and
written Lua hot-reloads in the engine - so for an agent, writing a script is
deploying it.
Commands
| Command | What it does |
| --- | --- |
| make <name> [dir] (create) | Make a world (region defaults to the nearest; --region, --track, --description, --no-pull, --open, --json) and mirror it into ./<slug>. |
| list (ls, projects) | Your worlds with framing ids and edit/play URLs (--json). |
| pull [target] [dir] | Mirror a world's file tree. target is any link to the world (or your website) or a framing id, and always resolves to the world's editor; omitted, it uses this folder's world or your only one. |
| sync [dir] | Watch + two-way sync with the live session. Ctrl-C to stop. |
| open [target] (client) | Optional: open a world in the native desktop client, downloading and signing it in on first use. --install-only, --print (just the download URL), --force. |
| run-lua [dir] --code "<lua>" [--target server\|client] | Execute Lua in the running engine. |
| errors [dir] | Recent engine errors. |
| screenshot [dir] [-o out.png] | Capture the engine's current view. |
| mcp [dir] [--framing <id>] | Run the stdio MCP server. |
| login / logout / whoami | Device-code sign-in; every other command signs you in automatically when needed. Tokens live in ~/.config/virtualmatter/credentials.json (mode 0600) and refresh automatically. |
Good to know
VIRTUALMATTER_API_BASEoverrides the platform API base (defaulthttps://make.virtualmatter.ai) for dev/staging environments.VIRTUALMATTER_NO_AUTO_LOGIN=1turns the automatic first-use sign-in into an error, for scripts that must never block on a browser.- The native client is unpacked under
~/.config/virtualmatter/client/<build>(override withVIRTUALMATTER_CLIENT_DIR); each engine build gets its own folder, so a newer build never overwrites the one you are running. Once a newer build is installed, older ones are removed unless a client is still running from them. - Sync skips
Uploads/,Screenshots/,Agent Logs/, dotfiles, the harness files the CLI writes (AGENTS.md,CLAUDE.md,.mcp.json,.cursor/,.codex/,.virtualmatter.json), and the SDK's in-session tooling at the Montage root (atomo,vm_auth.py, the agent-log hooks) - those only work inside a running session. - The pulled
AGENTS.mdis the platform guide followed by the world's own engine SDK guide (its Skills/ table and engine rules), with a header that maps everyatomocommand the engine guide mentions to the CLI or MCP equivalent. - Linux: the client is a tarball started through
run.sh;opendoes that for you. If no window appears, the newest log under~/.local/share/Atomontage/Atomontage Studio/UserData/Logs/says why, and the world keeps working in the browser and through every CLI command. - Sandboxed agents (Codex, restricted Claude Code) need network access for every command: the platform, the identity server, and the world's host.
pullmay cold-start a session for the framing; the first one can take a minute.
Websites and Lovable
For a shared world, no account or local engine is needed:
npx virtualmatter embed 'https://play.virtualmatter.ai/p/world-a1b2c3d4'The response contains canonical iframe markup, required host response
headers, and verification instructions. Installing this CLI alone cannot
configure the website's HTTP headers. Read /embed-guide.md on the platform.
To ask VM's own agent to build a new world (using your VM credits):
npx virtualmatter build 'Lava Arena' --prompt 'Build a multiplayer lava survival arena' --request-id lava-arena-001
npx virtualmatter build-status <build-id>Reuse the same request id if the network drops; changing it requests another world. Review the world and enable Share with friends before embedding. An uncertain delivery is never automatically resubmitted.
The local MCP create_project also accepts prompt plus request_id, and
exposes get_embed and get_build_status. Without a prompt it retains the
existing empty-world creation behavior.
In Lovable, add https://make.virtualmatter.ai/api/v1/mcp as a custom MCP
server with OAuth. Sign in or create a VM account, approve the connection,
and return to Lovable. Then ask “Embed my Lava Arena world” or “Create a
Virtual Matter lava survival arena and embed it here.” This remote endpoint
runs on the platform; users do not install or run this CLI for that flow.
Automatic agent logs
Run virtualmatter agent-logs setup once in a project mirror to capture future
conversations from Codex, Claude Code, Cursor, and an installed Hermes profile.
Keep virtualmatter sync (or virtualmatter agent-logs watch) running for
retry and transcript catch-up. Existing hooks are retained; follow the
harness's normal hook trust/restart flow. agent-logs status shows the queue;
agent-logs disable stops automatic capture.
Any harness can upload public event JSONL with:
virtualmatter agent-logs upload conversation.jsonl --harness my-agent --session session-123Each event needs a stable event_id, timezone-bearing ts, and type (user,
assistant_text, tool_use, tool_result, or result). Text events carry
text; tools carry name, input, tool_use_id; results carry tool_use_id
and result. Retries deduplicate, existing entries cannot be overwritten, and
failed batches remain in the project's local .virtualmatter/agent-logs/
outbox. --format codex and --format claude-code import explicit transcript
files. MCP exposes the same portable contract as upload_agent_logs.
Setup records only this project's future entries. Hidden reasoning, system messages, and binary media are excluded. Logs become part of the project's history and saved content. The server must have the agent-log API update; older servers return 404 and the CLI retains pending entries.
