Get started
Get started
Pick whichever install path fits how you work. The client code is the same either way — one Socket.IO connection, one ActivityStreams 2.0 envelope per action.
Install
Repository →npm fastest way to try it
Requires Node.js 20+ and a Redis instance reachable at localhost:6379:
# install the current release channel
npm install -g sockethub@alpha
# start the gateway
sockethub
# or explore the bundled examples
sockethub --examples
Running version: 5.0.0-alpha.12
Docker for deployment
Bring up Sockethub + Redis with a single compose file:
# docker-compose.yml
services:
redis:
image: redis:7-alpine
sockethub:
image: sockethub/sockethub:alpha
ports: ["10550:10550"]
environment:
REDIS_URL: redis://redis:6379
depends_on: [redis]
docker compose up — Sockethub is live on
http://localhost:10550.
Source hack on it
Clone the monorepo and run with Bun:
git clone https://github.com/sockethub/sockethub.git
cd sockethub
bun install
bun run dev
This runs the full workspace with live reload. Changes in any package are picked up by the running gateway.
Talk to it from the browser
All platforms →The client is a thin wrapper over Socket.IO. Point it at your gateway, wait for the schema registry, then credentials → connect → join → send. Every call is the same JSON-LD ActivityStreams 2.0 shape.
This example sends a single message to
#sockethub on Libera.Chat. Swap
sc.contextFor('irc') for
sc.contextFor('xmpp') and the same code reaches
an XMPP contact (for 1:1 you can skip the join).
Every emit returns an ack. We wrap that as a promise so each step either resolves on success or throws — no silent failures, no guessing at state.
// Load @sockethub/client (ESM or bundled UMD)
import SockethubClient from '@sockethub/client';
const sc = new SockethubClient({
host: 'http://localhost:10550',
});
// wait for the schema registry to load
await sc.ready();
const ircContext = sc.contextFor('irc');
const actor = { id: 'alice@irc.libera.chat', type: 'person' };
const room = { id: '#sockethub@irc.libera.chat', type: 'room' };
// turn emit+ack into an awaitable step
const step = (event, activity) => new Promise((resolve, reject) => {
sc.socket.emit(event, activity, (ack) => {
if (ack?.error) reject(new Error(ack.error));
else resolve(ack);
});
});
try {
// 1. credentials (stored encrypted per session)
await step('credentials', {
'@context': ircContext,
type: 'credentials',
actor,
object: {
type: 'credentials',
nick: 'alice',
server: 'irc.libera.chat',
port: 6697,
secure: true,
token: process.env.IRC_TOKEN,
},
});
console.log('creds stored');
// 2. connect
await step('message', { '@context': ircContext, type: 'connect', actor });
console.log('connected');
// 3. join (required on IRC + XMPP MUC; skip for XMPP 1:1)
await step('message', { '@context': ircContext, type: 'join', actor, target: room });
console.log('joined', room.id);
// 4. send
const ack = await step('message', {
'@context': ircContext,
type: 'send',
actor,
target: room,
object: { type: 'message', content: 'hello from the browser' },
});
console.log('sent', ack);
} catch (err) {
console.error('sockethub:', err.message);
}
Looking for the deeper architecture? How it works Source on GitHub