Skip to the content.

VibeSense game plugin contract (protocol v1)

New to this? Start with the step-by-step tutorial: Building a VibeSense game.

A VibeSense game is anything that can start when the Claude agent begins executing and pause when it stops or needs the user. Two kinds exist under one contract:

Manifest

Every plugin has a vibesense-game.json at its root:

{
  "id": "my-game",
  "name": "My Game",
  "version": "1.0.0",
  "protocolVersion": 1,
  "kind": "web",
  "entry": "index.html",
  "entitlement": "free"
}
Field Notes
id [a-z0-9-], unique; also the npm package suffix.
protocolVersion Always 1 for now.
kind "web" or "external".
entry web only: the HTML file to open, served at /games/<id>/<entry>.
commands external only: { "start", "pause", "resume", "stop" } — shell commands run in the plugin dir on state transitions. All optional; omitted transitions are skipped.
entitlement "free" or "paid". Paid is a reserved stub: activation is blocked until licensing ships, so the field can be used today without a payment system.

Runtime contract — web games

Your page is served by the vibesense host and receives everything over one SSE stream:

const events = new EventSource('/events')
events.onmessage = (e) => {
  const msg = JSON.parse(e.data)
  // { type: 'state', state: 'playing' | 'paused' }
  //   playing → the agent is executing; run your game loop.
  //   paused  → Claude needs the user; freeze and show why.
  // { type: 'input', kind: 'button', button: 'r2'|'l2', pressed: boolean }
  // { type: 'input', kind: 'axis', axis: 'left_x'|'left_y', value: -1..1 }
}

Rules:

Runtime contract — external games

The host runs your manifest’s shell commands (in your plugin directory):

An adapter for a Steam game can be as small as:

{
  "id": "my-steam-adapter",
  "name": "My Steam Game",
  "version": "1.0.0",
  "protocolVersion": 1,
  "kind": "external",
  "commands": {
    "start": "open steam://run/12345",
    "pause": "osascript pause.scpt",
    "resume": "osascript resume.scpt"
  },
  "entitlement": "free"
}

Note: external games own their controller input themselves (Steam already reads your gamepad); vibesense only tells them when to run.

Publishing to the marketplace

The marketplace is npm:

  1. Name your package vibesense-game-<id> and put vibesense-game.json at the package root.
  2. npm publish.
  3. Users install it with vibesense install <id> and activate it with vibesense use <id>.

Discovery: npm search vibesense-game- or vibesense games for what’s installed locally. Test unpublished games with vibesense install ./my-game.tgz (any npm-installable spec works).

Trust model: installing a game is installing an npm package — it can run code (external games run shell commands by design). Install games you trust, same as any dependency.