Quickstart: ship your first Pack
What you’ll build
Section titled “What you’ll build”A working Pack with one Event, fired through the bridge so you can watch it apply end-to-end. You’ll go from a fresh clone to a paired bridge running the reference Adapter, then fire the Event from the CLI and read back its result.
Prerequisites
Section titled “Prerequisites”- Rust toolchain (stable):
rustup install stable. - Python 3 on your
PATH(the reference Adapter is a stdlib-only Python script). - A Twitch broadcaster account. Pairing the bridge connects it to your channel.
- The mobrule app installed and able to run. It bundles the Dashboard and the bridge daemon. See Install mobrule.
Step 1: Get the hello-world Pack
Section titled “Step 1: Get the hello-world Pack”The pack-hello-world/ directory in the platform repo is the reference Pack
used by smoke tests, the smallest working example. Clone the platform repo and
change into it.
git clone <REPO_URL> mobrulecd mobrule/packs/pack-hello-worldReplace <REPO_URL> with the platform repository URL from your mobrule
distribution.
Step 2: Install the mobrule CLI
Section titled “Step 2: Install the mobrule CLI”The CLI validates Packs and fires test Events. Install it from the clone.
cargo install --path ../../climobrule --version should now print a version. The reference Adapter shells out
to mobrule pack print-hash, so the CLI must stay on your PATH.
Step 3: Inspect the Manifest
Section titled “Step 3: Inspect the Manifest”Open pack.toml. It declares the Pack identity, an [adapter] block the bridge
uses to launch the Adapter, one queue, and one Event:
manifest = 1id = "tv.mobrule.hello-world"name = "Hello World"version = "0.1.0"mpp = "2"authors = ["mobrule"]
[adapter]command = "python3"args = ["-u", "adapter.py"]restart = "on_crash"
[queues.default]ready_after = "applied"
[events.play_sound]summary = "Log a play-sound notification (hermetic; no audio output)."queue = "default"[events.play_sound.params_schema]type = "object"additionalProperties = falserequired = ["sound_id"][events.play_sound.params_schema.properties.sound_id]type = "string"maxLength = 64"x-mobrule-viewer-override" = trueEvery Pack declares at least one [queues.<name>], and every Event names the
queue it dispatches through. The [adapter] block tells the bridge what process
to spawn; the bridge runs it and injects the Adapter’s auth token. For every
other key, see the Manifest reference.
Step 4: Validate the Pack
Section titled “Step 4: Validate the Pack”From the Pack directory:
mobrule pack validate .On success the CLI prints the Pack id with its Event count, then the canonical Manifest hash:
ok tv.mobrule.hello-world (1 events)manifest_hash = sha256:<64-hex>A non-zero exit means the TOML failed to parse or a JSON Schema in your Manifest
was invalid; the validator points at the offending line and column. Exit code 2
means it parsed but emitted warnings (for example, an unbounded string with no
maxLength).
Step 5: Start and pair the bridge
Section titled “Step 5: Start and pair the bridge”The bridge boots unpaired. While unpaired it refuses every Adapter connection, so pairing comes first.
- Launch the mobrule app. The Dashboard opens and starts the bundled bridge daemon.
- On the landing screen, click Connect channel and complete the Twitch flow. This pairs the bridge to your broadcaster account.
- Select the hello-world Pack as the active Pack.
With a paired bridge and an active Pack, the bridge launches the Pack’s Adapter
itself using the [adapter] block from pack.toml. It injects the Adapter’s
auth token through the MOBRULE_ADAPTER_TOKEN environment variable, so the
Adapter never needs a token handed to it by hand. The reference Adapter
(pack-hello-world/adapter.py) reads that variable, connects to the bridge on
127.0.0.1:7777, and completes the handshake.
Step 6: Understand the Adapter lifecycle
Section titled “Step 6: Understand the Adapter lifecycle”You do not have to write an Adapter to finish this Quickstart; the reference Adapter is what the bridge just launched. Knowing its loop explains what you’ll see when you fire an Event.
After the hello handshake succeeds, the Adapter sends one pull per declared
queue to grant the bridge a dispatch credit. For each Invocation it acknowledges
receipt, applies the effect, marks it done, then re-pulls to grant the next
credit:
# Handshake: hello -> hello_acksend({"mpp": 2, "type": "hello", "pack_id": PACK_ID, "manifest_hash": MANIFEST_HASH, "bridge_token": TOKEN})ack = recv()assert ack["ok"]
# Grant one dispatch credit on the queue.send({"mpp": 2, "type": "pull", "queue": "default"})
while True: msg = recv() if msg["type"] == "invocation": inv = msg["id"] send({"mpp": 2, "type": "ack", "id": inv}) send({"mpp": 2, "type": "applied", "id": inv, "result": None}) send({"mpp": 2, "type": "done", "id": inv}) send({"mpp": 2, "type": "pull", "queue": msg["queue"]})TOKEN comes from MOBRULE_ADAPTER_TOKEN, MANIFEST_HASH from
mobrule pack print-hash. The pull frame is load-bearing: the bridge
dispatches at most one Invocation per outstanding pull on a queue, and never
dispatches without one. Skip the re-pull and the Adapter goes silent after the
first Invocation.
For the full walkthrough, including failed, log, and heartbeat frames, see
the Adapter tutorial: Python. The wire spec lives
at MPP protocol.
Step 7: Fire your first Event
Section titled “Step 7: Fire your first Event”With the bridge paired and the Adapter running, fire the play_sound Event
through the bridge from the CLI:
mobrule dev invoke play_sound --params '{"sound_id":"coin"}'invocation 1 queued on `default`The bridge dispatches the Invocation to the Adapter, which logs
PLAY: coin to its stderr and walks the ack/applied/done lifecycle. Read the
result back:
mobrule dev invocations#1 play_sound [done] queue=defaultA [done] state is your first Event applied end-to-end: CLI to bridge to
Adapter and back.
Step 8: Wire it to Twitch
Section titled “Step 8: Wire it to Twitch”Channel-point redeem creation and Cue to Event mapping live in the Dashboard. To
let viewers trigger this Event with channel points, create a reward and map its
Cue to play_sound. See Operator install and the
UI overview.
What’s next
Section titled “What’s next”- Manifest reference: every key in
pack.toml. - Defining Events: JSON Schema, viewer overrides.
- MPP protocol: full wire spec for the bridge to Adapter channel.
- Adapter tutorial: Python: the long-form Adapter walkthrough.
- Glossary: vocabulary you’ll see across the docs.