Install any skill in seconds. Free to start, no credit card required.
Get Started Free →You are an expert in Centrifugo, the scalable real-time messaging server. You help developers add WebSocket-based real-time features (chat, notifications, live updates, presence) to any application with a language-agnostic server that handles millions of concurrent connections — publishing from your backend via HTTP/gRPC API while clients subscribe via WebSocket, SSE, or HTTP streaming.
.claude/skills/terminalskills-centrifugo/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 42% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-19 | ✓→✓ | = Same ✓ | 51% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 72% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 61% | 0% |
You are an expert in Centrifugo, the scalable real-time messaging server. You help developers add WebSocket-based real-time features (chat, notifications, live updates, presence) to any application with a language-agnostic server that handles millions of concurrent connections — publishing from your backend via HTTP/gRPC API while clients subscribe via WebSocket, SSE, or HTTP streaming.
bash# Docker docker run -d --name centrifugo -p 8000:8000 \ centrifugo/centrifugo:latest centrifugo \ --token_hmac_secret_key="your-secret" \ --api_key="your-api-key" \ --admin --admin_password="admin" \ --allowed_origins="*" # Config file (config.json) { "token_hmac_secret_key": "your-256-bit-secret", "api_key": "your-api-key", "allowed_origins": ["https://myapp.com"], "namespaces": [ { "name": "chat", "presence": true, "join_leave": true, "history_size": 100, "history_ttl": "300s", "force_recovery": true }, { "name": "notifications", "presence": false, "history_size": 50, "history_ttl": "86400s" } ] }
typescriptimport { Centrifuge } from "centrifuge"; const client = new Centrifuge("ws://localhost:8000/connection/websocket", { token: userJwtToken, // JWT signed with your secret }); // Subscribe to channel const sub = client.newSubscription("chat:room-42"); sub.on("publication", (ctx) => { console.log("New message:", ctx.data); // { user: "Alice", text: "Hello!" } }); sub.on("join", (ctx) => { console.log(`${ctx.info.user} joined`); }); sub.on("leave", (ctx) => { console.log(`${ctx.info.user} left`); }); // Presence — who's online const presence = await sub.presence(); console.log("Online users:", Object.values(presence.clients).map(c => c.user)); // History — missed messages (recovery) const history = await sub.history({ limit: 50 }); history.publications.forEach(p => console.log(p.data)); sub.subscribe(); client.connect();
typescript// Publish from your server via HTTP API async function publishMessage(channel: string, data: any) { await fetch("http://localhost:8000/api/publish", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "apikey your-api-key", }, body: JSON.stringify({ channel, data }), }); } // Send chat message await publishMessage("chat:room-42", { user: "Alice", text: "Hello everyone!", timestamp: Date.now(), }); // Send notification await publishMessage("notifications:#user-123", { type: "order_shipped", title: "Your order has shipped!", orderId: "ORD-456", }); // JWT token generation (Node.js) import jwt from "jsonwebtoken"; function generateToken(userId: string, channels: string[]) { return jwt.sign( { sub: userId, channels }, process.env.CENTRIFUGO_SECRET!, { expiresIn: "24h" }, ); }
bash# Server docker pull centrifugo/centrifugo # Or binary: https://github.com/centrifugal/centrifugo/releases # Client SDK npm install centrifuge # JavaScript/TypeScript
chat: for chat, notifications: for alertsforce_recovery for chat; clients automatically catch up on reconnect#user-123 pattern for per-user notifications; only that user can subscribe| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-19 | pass→pass | 9,699 | 7,976 | -18% | 1 | 1 | 0% | 1,719 | 2,595 | +51% | 0 | 0 | — |
case-01 | fail→pass | 8,873 | 5,979 | -33% | 1 | 1 | 0% | 1,968 | 2,791 | +42% | 0 | 0 | — |
case-02 | pass→pass | 7,119 | 4,860 | -32% | 1 | 1 | 0% | 1,309 | 2,257 | +72% | 0 | 0 | — |
case-03 | pass→pass | 6,184 | 3,838 | -38% | 1 | 1 | 0% | 1,198 | 1,934 | +61% | 0 | 0 | — |
case-04 | pass→pass | 4,513 | 3,100 | -31% | 1 | 1 | 0% | 903 | 1,575 | +74% | 0 | 0 | — |
case-05 | pass→pass | 2,821 | 2,733 | -3% | 1 | 1 | 0% | 462 | 1,687 | +265% | 0 | 0 | — |
case-06 | pass→pass | 9,065 | 8,656 | -5% | 1 | 1 | 0% | 1,863 | 2,984 | +60% | 0 | 0 | — |
case-07 | pass→pass | 11,975 | 8,127 | -32% | 1 | 1 | 0% | 2,118 | 2,824 | +33% | 0 | 0 | — |
case-08 | fail→pass | 5,307 | 3,898 | -27% | 1 | 1 | 0% | 995 | 1,849 | +86% | 0 | 0 | — |
case-09 | pass→pass | 6,585 | 2,551 | -61% | 1 | 1 | 0% | 1,332 | 1,704 | +28% | 0 | 0 | — |
case-10 | pass→pass | 3,021 | 2,477 | -18% | 1 | 1 | 0% | 524 | 1,550 | +196% | 0 | 0 | — |
case-11 | pass→pass | 5,707 | 6,102 | +7% | 1 | 1 | 0% | 999 | 2,327 | +133% | 0 | 0 | — |
case-12 | pass→pass | 8,824 | 4,047 | -54% | 1 | 1 | 0% | 1,512 | 1,931 | +28% | 0 | 0 | — |
case-13 | pass→pass | 7,230 | 5,927 | -18% | 1 | 1 | 0% | 1,245 | 2,277 | +83% | 0 | 0 | — |
case-14 | pass→pass | 4,030 | 2,479 | -38% | 1 | 1 | 0% | 809 | 1,626 | +101% | 0 | 0 | — |
case-15 | pass→pass | 2,353 | 2,523 | +7% | 1 | 1 | 0% | 312 | 1,613 | +417% | 0 | 0 | — |
case-16 | pass→pass | 3,269 | 2,383 | -27% | 1 | 1 | 0% | 600 | 1,510 | +152% | 0 | 0 | — |
case-17 | pass→pass | 13,910 | 13,633 | -2% | 1 | 1 | 0% | 2,204 | 3,778 | +71% | 0 | 0 | — |
case-18 | pass→pass | 3,603 | 2,554 | -29% | 1 | 1 | 0% | 605 | 1,589 | +163% | 0 | 0 | — |
case-20 | pass→pass | 8,715 | 6,308 | -28% | 1 | 1 | 0% | 1,784 | 2,462 | +38% | 0 | 0 | — |
case-21 | pass→pass | 10,296 | 10,883 | +6% | 1 | 1 | 0% | 1,753 | 3,026 | +73% | 0 | 0 | — |
case-22 | pass→pass | 7,119 | 7,454 | +5% | 1 | 1 | 0% | 1,543 | 2,482 | +61% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.