What I build
CRCMZ (crcmz.me) — a private platform for a 7-person gaming squad called Professional Goopers. What started as a Stream Deck button that sent PSN messages has grown into a full-stack product: PSN clip pipeline, WhatsApp AI assistant, watch party, voice huddle, monthly video montages, giveaway system, and soundboard. The stack is self-hosted on Linux via Coolify. AI is both my coding partner and a live feature inside the product.
The WhatsApp bot (Hasaan)
The squad's primary AI interface. Messages prefixed with ai on PSN or @bot on WhatsApp to Hasaan trigger the bot. Hasaan is "the 8th member of Professional Goopers."
- Tool-calling AI over live squad data: PSN presence, clip catalog, giveaway state, music stats, web search
- Chat summarizer: "catch me up" → fetches everything since your last message, runs Gemma 4 26B to summarize, sends a Kokoro TTS voice note + text reply
- Build trigger: "build me a plant website" → SSH to ai-controller →
openclaw engineer→ deploys toplant.buildanator.com→ sends the URL back to the group - Ask Claw: "hey claw, explain how the audio works" → routes directly to Clawbot with a persistent session per group (2h inactivity reset)
- Typing indicators: re-sends
composing=trueevery 8 seconds during long ops so the group sees the bot is working - @mention resolution: translates
@2123456789phone numbers to@Namebefore passing to the model - Emoji reactions: reacts with 🌐 when the answer used web search
- Creator diagnostic mode: say "i am your creator" → next message returns raw internal state (model name, bridge URL, etc.) instead of AI
LLM: Qwen3.6-35B-A3B-Uncensored-Heretic-MLX-8bit running via oMLX (MacBook Pro M2 Max 96gb RAM). Summaries use Gemma 4 26B. TTS is Kokoro on the same Mac, transcoded to real OGG Opus via ffmpeg before delivery so iOS WhatsApp accepts the audio.
The clip pipeline
Every PSN clip shared in the squad PSN group from console flows through a lifecycle: discovered → downloading → processing → delivering → delivered.
- PSN poller detects a new clip in the group (every 30s)
- Downloads from PSN CDN, archives to S3, processes with ffmpeg
- Forwards to WhatsApp group via the Baileys bridge
- Optionally forwards to Discord (capped at 25MB)
A separate montage engine (psn-montage) compiles the month's eligible clips into a video on day 1 at 6am. A /api/scan-group endpoint pages through PSN history to backfill clips the real-time poller may have missed — registers them in the DB but never forwards to WhatsApp.
Soundboard
One-tap buttons to fire pre-set messages into the PSN squad group.
- Shared soundboard: built-in buttons plus up to 24 custom entries shared across everyone. Custom text gets passed through
roast_bot.flavor_message()— raw input is punched up by the LLM automatically before saving. - Personal soundboard: every signed-in user has their own private board. Buttons are private; messages post to the squad group. Drag-to-reorder persists server-side.
- Send-as-user: when the caller has a linked PSN account via the Portal, messages send from their own PSN identity rather than the group account.
Watch Party & Huddle
- Watch Party: Self-hosted WatchParty fork. Zitadel OIDC session → signed ES256 watch ticket → Socket.IO handshake. yt-dlp extraction for playback.
- Huddle: Self-hosted LiveKit on a separate VPS (
qcloud-public). Rooms auto-create on join. During a session: same LLM as the WhatsApp bot is available for questions, and Whisper (MLX on Mac) handles live transcription.
Other features
- Giveaway system: full lifecycle —
draft → open → locked → drawn → revealed → closed - Squad facts: short facts about squad members added by anyone; top 40 are injected into the assistant's system prompt as shared context
- Hype Meter (
/api/hype): counts today's PSN group messages and returns a 5-tier label — ☠️ DEAD SILENT through 💥 HYPE OVERLOAD - WhatsApp analytics: all messages stored in SQLite; stats, activity heatmap, word frequency, emoji usage, awards, member rankings
- PSN self-link portal: squad members open the portal, paste their PSN NPSSO token once; the app links their PSN identity to their Zitadel account
- Auth: Zitadel OIDC for all web sessions, with passkey (WebAuthn) support
How I develop
- Describe what's broken or needed in plain language — Claude Code reads the codebase, makes the change, commits, pushes
- Redeploy via Coolify dashboard; test live in the WhatsApp group or at
app.crcmz.me - For urgent fixes: hotpatch the running container directly (
docker cp), then sync back to git before the next deploy - When the squad wants a custom site built, they say so in WhatsApp and Clawbot ships it to
*.buildanator.com— no manual step
Apps
- Coolify (current): Container management on opti3 (Linux). All production services deploy here.
- Claude Code (current): Primary dev agent. Plain-language requests → code changes → commit + push.
- openclaw / Clawbot (current): AI engineer on
ai-controller. Triggered by the WhatsApp bot over SSH via Tailscale. Builds and deploys to*.buildanator.com. - Zitadel (current): OIDC identity for all web sessions. Cross-platform user metadata (PSN ID, WhatsApp JID, Mattermost username) stored via Zitadel metadata API.
- Outline (current): Architecture and feature docs, updated alongside the codebase.
- LiveKit (current): Self-hosted on
qcloud-publicVPS. Voice huddle infrastructure. - Mattermost (current): Squad comms. Bot DM alerts route here for async notifications.
- Baileys bridge (current): Node.js WhatsApp bridge. All message ingestion and send paths go through it.
What runs where
- opti3 (Coolify host): FastAPI app, clip pipeline, montage scheduler, PSN poller, WatchParty fork
- qcloud-public VPS: LiveKit server for voice huddle rooms
- ai-controller (Tailscale): openclaw / Clawbot for site builds;
lab-llm-relayproxies the Mac LLM to LAN - Mac (local inference): oMLX for all AI replies (Qwen3 35B), Gemma 4 26B for summaries, Kokoro TTS for voice notes, MLX Whisper for huddle transcription