# Quickstart
Get Rutster running and hear your own voice echoed back in under 5 minutes.
> **Status:** Slices 1โ3 are merged to `main`. Slice 4 (barge-in / VAD-driven playout
> kill) is the active build target, in flight on the `slice-4-dev-a-reflex` +
> `slice-4-dev-b-tap` branches. This quickstart exercises the slice-1 WebRTC media
> loopback, which remains the simplest end-to-end demo on `main`. See
> [`docs/superpowers/specs/2026-07-01-slice-4-barge-in-design.md`](superpowers/specs/2026-07-01-slice-4-barge-in-design.md)
> for the active build target's design.
---
## Prerequisites
### 1. Rust toolchain
Install via [rustup](https://rustup.rs/):
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
The repo pins a specific stable channel in `rust-toolchain.toml` โ `rustup`
will pick it up automatically on first `cargo` invocation. No manual
toolchain selection needed.
### 2. libopus (FFI dependency)
The `opus` crate links system libopus via FFI (per PORT_PLAN ยง7's
"๐ฆ Core (FFI)" disposition โ Opus is the codec surface Rust doesn't need
to re-implement). Install the dev headers:
| Platform | Command |
|---|---|
| Debian/Ubuntu | `sudo apt-get install -y libopus-dev` |
| Fedora | `sudo dnf install -y opus-devel` |
| Arch | `sudo pacman -S opus` |
| macOS (Homebrew) | `brew install opus` |
Verify: `pkg-config --cflags opus` should print a path with no error.
That's the only system dependency in slice 1. Everything else is pure
Rust from crates.io.
---
## Run the server
```bash
cargo run
# listening on http://0.0.0.0:8080
```
First build takes ~2 minutes (str0m + axum + tokio compile fresh).
Subsequent builds are incremental.
---
## Hear the echo
1. Open a browser to
` element. Look for the failure there. | | Port 8080 already in use | Set `RUTSTER_HTTP_BIND`, e.g. `RUTSTER_HTTP_BIND=0.0.0.0:8090 cargo run -p rutster` | The browser test page at `GET /` is a single self-contained HTML file with inline JS โ no build step. View source to see exactly what the client side is doing. --- ## What's happening When you click "Start call": 1. Browser captures microphone audio via `getUserMedia`. 2. Browser creates an `RTCPeerConnection` and generates an SDP offer (audio-only, Opus codec). 3. Browser POSTs the offer to `POST /v1/sessions/:id/offer`. 4. The Rutster core (built on [`str0m`](https://docs.rs/str0m), a sans-IO WebRTC implementation) accepts the offer, generates an SDP answer with its DTLS fingerprint + ICE credentials. 5. Browser sets the answer as remote description; ICE + DTLS handshake completes. 6. RTP starts flowing: browser โ core terminates DTLS-SRTP โ decodes Opus to 16-bit PCM @ 24 kHz mono โ echoes PCM back โ re-encodes to Opus โ DTLS-SRTP โ browser plays it. The "codec-to-PCM boundary" is the canonical point where, in a future slice, the audio tap for an external AI brain splices in. Slice 1 just echoes; step 2 of the spearhead swaps the echo for a real tap. For the why, see [`ARCHITECTURE.md`](ARCHITECTURE.md). For the dev loop, see [`DEVELOPMENT.md`](DEVELOPMENT.md).