Concepts

Collaboration

Presence, locks, cursors, and how multi-user editing stays sane.

Moonshine is built for teams. The collaboration surface — presence, locks, live cursors, request-access flows — is part of the product, not a layer bolted on. Understanding the lock model is the difference between smooth handoffs and stepping on each other.

Presence

Every connected operator shows up in the Presence indicator with their name and a color. The color is assigned at connect time and stays with that operator for the session. You’ll see their color in:

  • The cursor that follows them around in the 3D viewport
  • The lock indicators on resources they hold
  • Any UI surfaces where multiple operators are visible (the node graph node borders, for example)

Presence is real-time. When someone joins or drops, you see it within a frame.

The lock model — selection is lock

The model is selection-as-lock: when you select an editable resource (a projector for warping, a mask layer for painting, a playlist for editing), Moonshine acquires the lock on that resource for you. No separate “lock” button.

You can read any resource regardless of locks. Locks only affect editing.

Locks are TTL-based with auto-renewal. If you’re actively editing, the lock stays with you. If you walk away from your laptop for the configured TTL (default 60 seconds), the lock releases automatically and someone else can take it. This is so an operator who closes their laptop in the middle of a session doesn’t permanently strand a resource.

Lock keys

Locks are keyed on userId, not session. This means:

  • One operator, one identity, one lock per resource — you can’t have two browser tabs both holding the same lock as the same user
  • When you reconnect after a network drop, you get your locks back (the user identity is the same)
  • A different user can’t sneakily release someone else’s lock — release messages must include the lock ID that proves authorship

Request access

When a resource is locked by another operator and you need to edit it, the Request Access modal lets you ping them. They get a notification with the option to release the lock and hand the resource over.

This replaces the “who has the file open?” question in your headset. The modal carries a short message field — write what you want to do with the resource, and the lock holder decides whether to release.

The lock holder can either:

  • Release the lock immediately — the requester gets it
  • Decline — the requester sees the response and tries again later
  • Ignore — the request times out after a few seconds with no response

No automatic forcing. You have to ask, and the current holder has to agree.

Read-only UI when locked

If you select a resource that’s locked by someone else, the editing surface is read-only. You can see the current state, observe their edits in real time as they make them (via WebRTC preview and live cursor), but you can’t move a vertex, paint a stroke, or change a parameter.

This is the right default — accidental simultaneous edits are a worse failure mode than “you couldn’t edit for a moment.”

Live cursors

Every operator’s cursor in the 3D viewport is shown to every other operator in real time, in their assigned color, with their name floating beside it. Cursors update at frame rate; you can literally follow what someone is doing.

This is the most natural collaboration tool — you don’t have to “share my screen” to show your collaborator what you’re looking at. They just see your cursor land on the thing.

Tab visibility and cursor broadcast

When your tab loses focus (you alt-tabbed away), your cursor stops broadcasting. This is intentional — there’s no point spamming the network with cursor updates from a tab no one is looking at. Your presence still shows; just the cursor pauses.