Appearance
Testing in Studio
Run your local code in Studio with the real kernel, the dev menu and DataStores, without uploading anything. typetorch serve runs the whole Studio loop in one process, and the TypeTorch Studio plugin attaches to it by itself: no Connect button, and a save reaches a running playtest without Stop + Play.
- Needs kernel 0.3.1+ in
node_modules/@typetorch/kernelfor the local payload, and kernel 0.5.4+ for live reload in a playtest. CLI 0.11+ fortypetorch serve(0.12+ for the--remotetunnel and pairing link, 0.12.2+ for thelivescript default and Rojo's restarts below, 0.15+ for the hot asset Diff). The template's@typetorch/clirange (^0.9.1) stays on 0.9.x:bun add -d @typetorch/cli@latestgets the current release. Studio plugin 0.7.1 is the latest release. - Deploy messages never reach Studio playtests, so Studio doesn't follow your deploys. The kernel mounts your compiled code straight from
ServerStorage.TypeTorchDev.Payload, which Rojo syncs.
Set up (once)
studio.project.jsonfrom the template, next todefault.project.json. It syncs the kernel fromnode_modules/@typetorch/kernel, your compiled payload (out/,include/and the packages) intoServerStorage.TypeTorchDev.Payload, and the kernel place's baseplate and spawn.- The TypeTorch Studio plugin. Download
TypeTorchSync.rbxmfrom the latest release into Studio's plugins folder (Windows:%LOCALAPPDATA%\Roblox\Plugins), then restart Studio or reload plugins. From a checkout of typetorch/studio-plugin:bun run typetorch studio install-plugin --from ../studio-pluginbuilds it into the same folder with Rojo. The plugin is not on npm. There is also a Creator Store copy, but it is updated by hand and can lag behind the GitHub release. It carries Rojo's own sync (7.7.0-rc.1, the versionrokit.tomlpins), so you don't need the stock Rojo plugin; if you keep it, connect only one of the two at a time. - Game Settings > Security > Enable Studio Access to API Services, so DataStores work in a playtest.
- The first time the plugin probes
typetorch serve, Studio asks to allow its HTTP requests to localhost: allow it.
Run it
In the game folder:
sh
bun run typetorch serveIt starts, and restarts when they exit (after 0.5 s, doubling up to 10 s while a child keeps crashing):
- watch: the game's
watchscript (elserbxtsc -w). Compile errors are kept forserve statusand the plugin's panel.--no-watchleaves compiling to your editor. - rojo:
rojo serve studio.project.json(elsedefault.project.json;--project <file>) on Rojo's port 34872 or the next free one (--port). If another process holds the port when Rojo (re)starts, Rojo moves to the next free one and the plugin follows. Rojo can't follow a$pathfolder (out/server, ...) that is deleted and recreated, as a deploy's clean build does, so serve restarts Rojo when that happens;serve statusshows it. - live: the game's
livescript frompackage.json, when it has one. On by default;--no-liveturns it off. - extra scripts:
--with <a,b>runs thosepackage.jsonscripts withbun run. - the control API on
127.0.0.1, the first free port of 34880-34887 (loopback only, no browser can call it)..typetorch/serve.json(git-ignored) records the port, and the children's process ids, while it runs.
A serve that was killed (kill -9, a closed SSH session) leaves its children running, and that Rojo keeps its port. The next serve (or serve status) stops them on Linux; on Windows and macOS it names them so you can stop them.
Open a place of your experience in Studio. The plugin finds the serve whose typetorch.json universeId matches the place and syncs; another experience's place or an unpublished file syncs only after Connect anyway in its panel. Press Play.
Check: the plugin's panel (the TypeTorch toolbar button) says "Synced", Server > Status in the dev menu shows "Studio: local payload", and /tt status says "local payload". The artifact id is local-<HHMMSS> on branch dev (or the Branch attribute of ServerStorage.TypeTorchDev), dev channel.
Ctrl+C, or bun run typetorch serve stop from another terminal, stops everything. Other subcommands: serve status (children, attached Studios, sync state, compile errors), serve restart <watch|rojo|claude|script> and serve logs [--studio] [--since <seq>] [--limit <n>] [--follow] (--studio: Studio's Output, as the plugin forwards it).
The two-terminal loop still works: bun run watch and bun run studio (rojo serve studio.project.json) with the stock Rojo plugin, but nothing reloads a running playtest then.
How it behaves
- A save reaches the running playtest. In a playtest the plugin also runs in the server and syncs into the running game; it sets
LiveReloadonServerStorage.TypeTorchDev, and the kernel (0.5.4+) reloads a fresh copy of the local payload about 0.4 s after the last change, server and client code, as Reload does. Turn it off in the panel's Playtest card ("Live playtest: on"). With an older kernel, code changes need Stop + Play. - Reload tests swaps. The dev menu's Reload (or
/tt reload) remounts a fresh copy of the same code, so you can testpersist,onSwapOut, update toasts and everything else a deploy does, while you play. - Deploys and the 60 s poll don't move a local session. A pin or a branch switch in the dev menu still loads an uploaded build; Reload comes back to the local copy.
- To boot the branch head instead, delete
ServerStorage.TypeTorchDev.Payload(with the sync disconnected). - In Studio everyone is a dev with the owner role, so kick and ban can't be tried there.
- A dropped connection or a restarted
servereconnects with a full resync. Until then the panel says Disconnected (red) with how long ago, and keeps retrying. "Auto-connect: on" in the panel turns it off per place. - In a playtest the toolbar and the panel stay (on the client in Play, the server in Run), with only the status, playtest and compile cards: pairing and hot assets act on the edit session.
Hot assets from the panel
The plugin's Hot assets card does hot assets without publishing the place first: select models or UI, Add marks them (TypeTorchAsset, a key from the name or the name box; with one hot asset selected, a new name turns Add into Rename), Remove unmarks them. Each marked instance shows as new, changed, up to date, or what a sync would refuse.
- Check runs
typetorch assets statuson the plugin's export of the open place (locally, no key needed). - Upload runs
typetorch assets syncon it. - Publish to dev runs
assets sync --deploy dev(serve --dev-branch <b>picks another dev branch, and the button is named after it; a prod-channel branch is refused). The deploy follows yourapprovalpolicy like any other: with"approval": "all"it becomes a proposal fortypetorch approve. - Diff (CLI 0.15.0+), on each new, changed or removed row after a check: the instances added, removed or changed inside that asset, with old and new property values (at most 30 instances and 8 properties each). The old side is the copy of the lockfile's version that
assets statusandsynckeep in the state dir (.typetorch/hot-assets/<hash>.rbxm); for a lockfile synced on another machine the diff only summarizes the new export, until a sync here. With an older CLI the button stays hidden.
A button shows only when it has work. While the panel is open in edit mode and a serve is attached, the check also runs by itself every 30 seconds (never while a job runs, never with nothing marked), and once after every (re)connect. It sends a job to serve only when the place or the lockfile changed since the last check.
They run inside serve with its keys from the game repo's .env (progress in serve logs). Because the export comes from the open place, the lockfile records place version 0 for changed entries; the next sync from a published place records a real version again.
Agents and Studio
typetorch serve --detach starts serve in the background (log: .typetorch/serve.log) and returns once it answers; every subcommand takes --json. An agent can then drive the Studio the plugin attached:
sh
bun run typetorch studio status # attached Studios (edit, playtest server and client), sync state
bun run typetorch studio reconnect # resync from scratch, wait for the result (--anyway: another experience)
bun run typetorch studio play # start a playtest (--run: Run mode, no player)
bun run typetorch studio logs --follow # Studio's Output, edit and playtest
bun run typetorch studio stop # end the playtest--target <id|edit|server|client> picks the Studio (default: the edit DataModel; stop: the playtest server), and --timeout <s> how long to wait for its answer (default 20).
The plugin keeps listening for these while its sync is down, so an agent can always get Studio back. When no Studio is attached at all, run this in Studio's command bar (or the Roblox Studio MCP's execute_luau) and the plugin reconnects:
lua
game:GetService("ServerStorage"):SetAttribute("TypeTorchReconnect", os.time())typetorch mcp serves the same over stdio as MCP tools (serve_status, serve_start, serve_stop, serve_logs, studio_logs, studio_reconnect, studio_play, studio_stop). Claude Code, from the game repo: claude mcp add typetorch -- bunx typetorch mcp.
A Studio on another machine
bun run typetorch serve --remote lets someone else's Studio sync from your machine:
- serve opens a gateway on
127.0.0.1:34890(--remote-port) and a free Cloudflare quick tunnel to it (no account;cloudflaredis installed when it's missing). - Once the tunnel answers, serve prints a one-time pairing link (valid 15 minutes): the tunnel URL with the code after a
#.serve statusshows it again;typetorch serve pairmakes a new one. - The other person pastes the link into the plugin's Server card and presses Pair. Their Studio stays paired for 30 days (
serve deviceslists devices,serve unpair --name <device>or--allrevokes them). Use this computer's serve goes back.
- A quick tunnel's address changes when cloudflared restarts; serve then prints a new link. For a fixed address, run your own named tunnel to
http://localhost:34890and pass--url https://<your tunnel>;--no-tunnelopens none and leavestypetorch serve pair --url <it>to you (the URL is remembered). - A remote Studio syncs code read-only, reports its state and Output, and runs the Hot assets buttons (uploads with your keys, deploys only to the dev branch). It can't stop or restart serve, read serve's log or drive other Studios, and
typetorch studio ...and the MCP tools never pick a remote Studio unless--targetnames it. - Every request but pairing needs that device's token (kept hashed in
.typetorch/serve-remote.json). Five wrong codes lock pairing until you make a new code.
Claude in Studio
bun run typetorch serve --claude also runs remote-claude on this machine (no tunnel), and the plugin's Claude button opens a chat with Claude Code, like the in-game DEV > Claude tab. Code mode only: Claude edits a copy of your branch, and you Apply the change into this checkout (Rojo syncs it to Studio), Deploy it to the dev branch, or Discard it. With CLI 0.12.2+ this needs @typetorch/dev-server 0.4.0, which is not on npm yet (see From Studio).
Don't publish that session
Live servers ignore ServerStorage.TypeTorchDev, but it bloats the place, and typetorch doctor warns when the published place still holds it. Publish the place only through the kernel deploy (or your own clean Studio session).
Without a local payload
A Studio playtest with no ServerStorage.TypeTorchDev.Payload boots an uploaded build: the head of ServerStorage.TypeTorchDev's Branch attribute, or of defaultBranch. It reads the stored heads from DataStores, so it also needs Studio API access. (Kernel 0.3.8 dropped the BootAssetId and Registry attributes, stand-ins for the old ConfigService registry.)