Quickstart
Get a relay running, mint a session, and exchange messages — about three minutes.
1. Run the server
For the impatient — local dev without an IdP:
go run github.com/emdzej/swsrs/cmd/swsrs@latest serve --no-auth --addr :8080You'll see the loud warning:
WARN AUTH DISABLED — admin API is open. Do not use in production.
INFO listening addr=:8080 tls=falseFor production, point at your IdP:
swsrs serve \
--oidc-issuer https://your-idp.example.com/realms/foo \
--oidc-audience swsrs \
--oidc-client-id swsrs # for clients' device flowOr Docker:
docker run --rm -p 8080:8080 \
-e SWSRS_OIDC_ISSUER=https://your-idp.example.com/realms/foo \
-e SWSRS_OIDC_AUDIENCE=swsrs \
-e SWSRS_OIDC_CLIENT_ID=swsrs \
ghcr.io/emdzej/swsrs:latest2. Log in (production only)
swsrs auth --relay https://relay.example.comThis drives the OAuth 2.0 device flow against the IdP configured on the server side — no IdP coordinates required from you. The CLI prints a URL and a one-time code, you sign in on any device, the token is cached at ~/.config/swsrs/credentials.json (or the OS-equivalent).
Skip this step entirely with --no-auth.
3. Create a session
swsrs create --admin-url https://relay.example.comOutput (JSON):
{
"id": "OVMnxnEzZA9QvFc…",
"initiator_token": "Gi-jvZfpHgahXc618jUP8A",
"responder_token": "tKuylZcPfwjvy43…",
"created_at": "2026-06-03T12:00:00Z",
"expires_at": "2026-06-03T13:00:00Z"
}Two opaque tokens, one per slot. Give one to each side that needs to attach.
4. Connect both sides
Pick any combo of the adapter subcommands; both peers need to use the same session id with their own slot's token.
Echo over stdin/stdout (raw)
Terminal A — host:
swsrs raw --url wss://relay.example.com \
--session OVMnxnEzZA9QvFc… --token $INITIATOR_TOKEN --role initiatorTerminal B — the other side:
swsrs raw --url wss://relay.example.com \
--session OVMnxnEzZA9QvFc… --token $RESPONDER_TOKEN --role responderAnything you type on one side appears on the other.
TCP tunnel
Have the peer machine expose local TCP (e.g. its SSH port):
swsrs tcp-dial \
--url wss://relay.example.com \
--session ... --token $RESPONDER_TOKEN --role responder \
--target 127.0.0.1:22On the connecting side, bind a local TCP listener:
swsrs tcp-listen \
--url wss://relay.example.com \
--session ... --token $INITIATOR_TOKEN --role initiator \
--listen 127.0.0.1:2222 &
ssh -p 2222 user@127.0.0.1Next
- Architecture — why the design looks like this
- Authentication — scopes, --no-auth, audience, device flow
- Go SDK / TypeScript SDK — embed in your app
- Chat example — runnable two-party text chat