CLI

The og command ships in the SDK (cli/). It wraps the compiler, the dev server and the headless runtime. In a clone of the SDK, npm install && npm link puts og on your PATH. og doctor checks your toolchain.

Command What it does
og new <name> Scaffold a firmware project.
og build [dir | file.c …] Compile C to build/<id>.wasm. Flags: --debug, -o <out.wasm>.
og dev [dir] Build, watch and serve with live reload. Flags: --port 5173, --profile kick, --open.
og verify <file.wasm …> The registry checks, printed as JSON per profile. Flags: --profile p, --seconds 10. Exits 1 if any check fails.
og render <file.wasm> Render audio headlessly. Flags: --out out.wav, --script events.json, --seconds 8, --profile p, --png screen.png, --float.
og serve [dir] Static server that sends the COOP/COEP headers. Flags: --port 8080, --open <path>.
og doctor Check the toolchain.

The dev loop

sh
og new my-box
cd my-box
og dev

Open the URL it prints (port 5173 by default), tap the device to power it on, and edit main.c. Each save rebuilds and swaps the firmware in place. og_log output and anything written to stdout or stderr through WASI appears in the browser console panel.

The dev server sends the cross-origin isolation headers the runtime needs (see below), so you get the low-latency SharedArrayBuffer path.

Hosting a firmware yourself

The browser runtime uses a SharedArrayBuffer, which needs a cross-origin isolated page. Any server that hosts <og-device> must send:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

and serve .wasm as application/wasm. Without isolation the runtime still works, falling back to postMessage audio blocks with more latency, and logs a warning.

Embedding a device

html
<script type="module" src="/runtime/opengroove-runtime.js"></script>
<og-device src="/fw/my-box.wasm" profile="kick"></og-device>
Attribute Meaning
src Firmware URL. Changing it hot-swaps the firmware and keeps the AudioContext.
profile generic, kick or fire. Sets the skin and the counts passed in og_device.
muted Boolean.
compact Boolean. Renders only the screen and pads, for cards and thumbnails.

Methods: start() (from a user gesture; the built-in "tap to power on" overlay calls it), stop(), load(src | ArrayBuffer), and the read-only state (idle, loading, running, error).

Events, all bubbling CustomEvents: og-ready (detail.exports), og-error (detail.message) and og-log (detail.line).

Keyboard: pads on 1234 / qwer / asdf / zxcv, space is PLAY, arrows are LEFT/RIGHT/UP/DOWN, shift is SHIFT. WebMIDI input is forwarded to og_midi_in once the user grants it.