{"id":49320244,"url":"https://github.com/eusougustavocesar/reverb","last_synced_at":"2026-04-26T17:04:18.308Z","repository":{"id":352929129,"uuid":"1217240246","full_name":"eusougustavocesar/reverb","owner":"eusougustavocesar","description":"Persistent Claude Code across messaging channels. Mac stays closed. Claude keeps working.","archived":false,"fork":false,"pushed_at":"2026-04-26T00:40:02.000Z","size":858,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-26T01:18:20.577Z","etag":null,"topics":["ai-tools","anthropic","baileys","claude","claude-code","cli","daemon","launchagent","typescript","whatsapp"],"latest_commit_sha":null,"homepage":"https://reverb.eusougustavocesar.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eusougustavocesar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-21T17:27:49.000Z","updated_at":"2026-04-26T00:40:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/eusougustavocesar/reverb","commit_stats":null,"previous_names":["eusougustavocesar/claude-bridge","eusougustavocesar/reverb"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/eusougustavocesar/reverb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eusougustavocesar%2Freverb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eusougustavocesar%2Freverb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eusougustavocesar%2Freverb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eusougustavocesar%2Freverb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eusougustavocesar","download_url":"https://codeload.github.com/eusougustavocesar/reverb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eusougustavocesar%2Freverb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32305043,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-tools","anthropic","baileys","claude","claude-code","cli","daemon","launchagent","typescript","whatsapp"],"created_at":"2026-04-26T17:04:15.705Z","updated_at":"2026-04-26T17:04:18.295Z","avatar_url":"https://github.com/eusougustavocesar.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"brand/logo-lockup.svg\" alt=\"reverb\" width=\"200\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003eConnect your AI CLI to any messaging channel.\u003c/b\u003e\u003cbr\u003e\n  Your device stays closed. Your AI keeps working.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/demo.gif\" alt=\"Demo — sending a prompt from WhatsApp, Claude replies. The host machine is asleep the whole time.\" width=\"320\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#quickstart\"\u003eQuickstart\u003c/a\u003e ·\n  \u003ca href=\"#why\"\u003eWhy\u003c/a\u003e ·\n  \u003ca href=\"#how-it-works\"\u003eHow it works\u003c/a\u003e ·\n  \u003ca href=\"#comparison\"\u003eComparison\u003c/a\u003e ·\n  \u003ca href=\"#roadmap\"\u003eRoadmap\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n`reverb` is a lightweight daemon that connects your AI CLI (Claude Code, Gemini CLI, or any AI assistant) to messaging channels (WhatsApp today, Telegram/Signal/Discord soon) with **real persistence** — it keeps running in the background, survives reboots, reconnects on network drops, and spawns `claude --print` on demand. You use your own Claude Code subscription. No API tokens. No Docker. No cloud.\n\nSend yourself a WhatsApp message from the bus. Claude replies. Your machine was asleep the whole time.\n\n## Why\n\nEveryone building \"Claude via WhatsApp\" hits the same wall: **persistence**.\n\n- **Official Claude Code channel plugins** (like the WhatsApp plugin approved in the Anthropic marketplace) load inside your Claude Code session. The moment you close Claude Code, the bridge dies. Useless when you're away from your desk.\n- **Docker-based alternatives** do persist — at the cost of a 2–4 GB Linux VM running 24/7. Overkill.\n- **Twilio / WhatsApp Business API solutions** require paid APIs and a business account.\n\n`reverb` runs as a native daemon (~50 MB RAM). Auto-restarts on crash. Auto-reconnects on WhatsApp drops. Auto-starts on boot. Uses your existing Claude Code subscription via `claude --print`.\n\n## Features\n\n- 🔗 **WhatsApp** channel via multidevice linked-device protocol (no Business API, no phone number hosting)\n- 🧱 **Native persistence** — LaunchAgent on macOS · systemd user service on Linux · Task Scheduler on Windows\n- 🛡️ **Sandboxed execution** — Claude Code runs with a scoped working directory, not your entire `$HOME`\n- 🚦 **Rate limiting** per chat (configurable; default 10 msgs / 60s)\n- 📜 **Audit log** with hashed JIDs — every processed message recorded in `logs/audit.jsonl`\n- 🛑 **Kill switch** — send `/stop` from your own WhatsApp to shut the bridge down\n- 📎 **Response chunking** — long Claude responses split into multiple WhatsApp messages\n- 🔒 **Local-only** — no cloud, no third-party servers, no telemetry\n\n## Quickstart\n\n### Prerequisites\n\n- **macOS, Linux, or Windows** — Node.js 18+\n- **Claude Code CLI** installed and authenticated (`claude login`)\n- An active WhatsApp account on your phone with a free Linked Device slot (max 4)\n\n### Install\n\n**macOS / Linux**\n```bash\ngit clone https://github.com/eusougustavocesar/reverb.git\ncd reverb \u0026\u0026 npm install \u0026\u0026 npm run setup\n```\n\n**Windows**\n```powershell\ngit clone https://github.com/eusougustavocesar/reverb.git\ncd reverb; npm install; npm run setup\n```\n\n`npm run setup` builds the project, registers the background service for your OS (LaunchAgent / systemd / Task Scheduler), and starts it.\n\n### Pair your phone\n\n```bash\nnpm run pair\n```\n\nA QR code renders in your terminal. On your phone:\n\n\u003e **iOS:** WhatsApp › Settings › Linked Devices › Link a Device  \n\u003e **Android:** WhatsApp › ⋮ Menu › Linked Devices › Link a Device\n\nOnce you see `Connected to WhatsApp`, send yourself a test message. When Claude replies, hit `Ctrl+C` — the background service takes it from here.\n\nThat's it. The service now runs continuously, survives reboots, and your AI is a WhatsApp message away.\n\n### Verify it's alive\n\n**macOS**\n```bash\nlaunchctl list | grep reverb\ntail -f /tmp/reverb.log\n```\n\n**Linux**\n```bash\nsystemctl --user status reverb\njournalctl --user -u reverb -f\n```\n\n**Windows**\n```powershell\nGet-ScheduledTask -TaskName \"reverb\" | Get-ScheduledTaskInfo\nGet-Content \"$env:APPDATA\\reverb\\reverb.log\" -Tail 50\n```\n\n## How it works\n\n```\n        ┌────────────────────┐\n        │  WhatsApp (phone)  │\n        └─────────┬──────────┘\n                  │  multidevice linked device (WebSocket)\n                  ▼\n        ┌────────────────────┐\n        │    Baileys (Node)  │◄── runs as daemon, never sleeps\n        │       reverb       │\n        └─────────┬──────────┘\n                  │  spawn subprocess on each message\n                  ▼\n        ┌────────────────────┐\n        │  claude --print    │\n        │  (your CC session) │\n        └─────────┬──────────┘\n                  │  stdout\n                  ▼\n        ┌────────────────────┐\n        │   Reply to chat    │\n        └────────────────────┘\n```\n\n**Why it works when the official plugin doesn't:** the daemon is a **separate process** from Claude Code itself. Claude Code starts, runs, exits — repeatedly — on demand. The bridge keeps the WhatsApp socket alive independently. You never need Claude Code open.\n\n## Configuration\n\nEverything lives in `.env`:\n\n```env\n# Path to Claude binary (run `which claude` to find yours)\nCLAUDE_BIN=claude\n\n# Sandboxed working directory (Claude can only read/write inside this)\nCLAUDE_CWD=./workspace\n\n# Empty MCP config — bypasses MCP server startup hang under headless daemon\nCLAUDE_MCP_CONFIG=./empty-mcp.json\n\n# Rate limit\nRATE_LIMIT_MAX=10\nRATE_LIMIT_WINDOW_SECONDS=60\n\n# Allowed chats. Empty = only self-chat. Include both phone JID and LID.\n# Example: \"5511999999999@s.whatsapp.net,123456789012345@lid\"\nALLOWED_JIDS=\n\n# Session mode: \"continue\" (rolling session) | \"none\" (stateless)\nSESSION_MODE=continue\n```\n\nSee [`docs/configuration.md`](docs/configuration.md) for details and [`docs/troubleshooting.md`](docs/troubleshooting.md) for common issues.\n\n## In-chat commands\n\n- `/help` — list commands\n- `/stop` — shut down the bridge (the background service auto-restarts; disable the service/task to stop permanently)\n\n## Notifications (inbound webhooks)\n\nAny service can push a notification to your WhatsApp by posting to reverb's local HTTP API:\n\n```bash\ncurl -X POST http://localhost:3737/api/notify \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"title\":\"Deploy failed\",\"body\":\"api-server stopped after 3 retries\",\"level\":\"error\",\"service\":\"api-server\"}'\n```\n\nYou'll receive:\n\n```\n🔴 *Deploy failed*\n_api-server_\n\napi-server stopped after 3 retries\n\n— reverb · 14:32\n```\n\n**Payload fields:**\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `title` | string | ✅ | Notification headline |\n| `body` | string | — | Detail text |\n| `level` | `error` \\| `warning` \\| `info` \\| `success` | — | Sets the emoji (🔴🟡🔵🟢) |\n| `service` | string | — | Service or source name |\n| `to` | string | — | Target JID (overrides `NOTIFY_JID`) |\n\n**Auth:** Set `NOTIFY_TOKEN` in `.env` to require `Authorization: Bearer \u003ctoken\u003e`.\n\n**Target JID:** Set `NOTIFY_JID` in `.env` to route notifications to a specific chat. Defaults to your self-chat.\n\nSince the API is bound to `127.0.0.1`, it's only reachable from the same machine — no need to expose it to the internet.\n\n## Audio transcription\n\nEnable voice message support by installing [openai-whisper](https://github.com/openai/whisper) and setting two env vars:\n\n```bash\npip install openai-whisper   # also requires ffmpeg in PATH\n```\n\n```env\nAUDIO_ENABLED=true\nWHISPER_BIN=whisper          # or full path from `which whisper`\nWHISPER_MODEL=base           # tiny | base | small | medium | large\nWHISPER_LANGUAGE=pt          # ISO 639-1 code — speeds up transcription\n```\n\nWhen someone sends a voice message, reverb:\n1. Downloads the audio buffer from WhatsApp\n2. Runs it through Whisper locally\n3. Echoes the transcript (`🎤 _...transcript..._`)\n4. Forwards the text to Claude and replies with the response\n\nNo cloud, no API key — Whisper runs entirely on your machine.\n\n## Image support\n\nEnable image processing by setting:\n\n```env\nIMAGE_ENABLED=true\nMEDIA_TMP_TTL_SECONDS=60   # seconds to keep tmp file after Claude reads it\n```\n\nWhen someone sends an image, reverb:\n1. Downloads the image buffer from WhatsApp\n2. Saves it to `CLAUDE_CWD/tmp/\u003cfilename\u003e.jpg`\n3. Sends Claude a prompt referencing that file path\n4. Claude reads the image (using its file-access in the sandbox) and replies\n5. The temp file is deleted after `MEDIA_TMP_TTL_SECONDS`\n\nAny caption on the image is included as context in the prompt.\n\n## Comparison\n\n| | reverb | [Rich627/whatsapp-claude-plugin][rich627] | [osisdie/claude-code-channels][osisdie] | Twilio + API |\n|---|:---:|:---:|:---:|:---:|\n| Persistence (device can be closed) | ✅ | ❌ | ✅ | ✅ |\n| Uses your Claude Code subscription (no API cost) | ✅ | ✅ | ✅ | ❌ |\n| Runtime footprint | ~50 MB | 0 (inside Claude Code) | 2–4 GB (Docker) | N/A (cloud) |\n| Installation | 1 script | `claude plugin install` | `docker compose up` | complex |\n| macOS | ✅ | ✅ | ✅ | ✅ |\n| Linux / VPS | ✅ | ❌ | ✅ | ✅ |\n| Windows | ✅ | ❌ | ❌ | ✅ |\n| Multi-channel | WA (+ Telegram/Signal planned) | WA only | WA + Telegram + Discord + Slack + LINE | any |\n| Official Anthropic marketplace | not yet | ✅ | ❌ | ❌ |\n| Open source | ✅ MIT | ✅ | ✅ | varies |\n\n[rich627]: https://github.com/Rich627/whatsapp-claude-plugin\n[osisdie]: https://github.com/osisdie/claude-code-channels\n\n## Security\n\n`reverb` gives a WhatsApp message access to Claude Code running on your machine. That's powerful — and risky — so the defaults are conservative:\n\n- **Sandboxed `CLAUDE_CWD`** — defaults to `./workspace` inside the repo. Claude can only read/write inside it. Do NOT set it to `$HOME`.\n- **Rate limiting** per chat (10 msgs / 60s).\n- **ALLOWED_JIDS allowlist** — by default only your own self-chat works.\n- **Audit log** with hashed JIDs in `logs/audit.jsonl`.\n- **Kill switch** via `/stop`.\n\nSee [`docs/security.md`](docs/security.md) for threat model and hardening tips.\n\n\u003e ⚠️ `reverb` uses WhatsApp's multidevice (linked device) protocol via [Baileys](https://github.com/WhiskeySockets/Baileys). This is the same mechanism WhatsApp Web uses, but using it programmatically **may violate WhatsApp's Terms of Service**. Historical ban rate on low-volume personal use is very low, but non-zero. Use a dedicated number for heavy automation.\n\n## Roadmap\n\n- [x] v0.1 — WhatsApp channel, LaunchAgent (macOS), sandboxing, rate limiting\n- [x] v0.1 — systemd user service (Linux/VPS), Task Scheduler (Windows)\n- [x] v0.1 — Inbound webhook notifications (`POST /api/notify`)\n- [x] v0.4 — Audio transcription via Whisper (local, no API key)\n- [x] v0.4 — Image support via Claude's file-reading sandbox\n- [ ] v0.2 — Telegram channel (plug-in adapter)\n- [ ] v0.3 — Session per chat (multi-conversation context isolation)\n- [ ] v0.5 — Slash commands framework (`/reset`, `/session new`, `/status`)\n- [ ] v1.0 — Homebrew formula, signed release binaries\n\n## Contributing\n\nIssues and PRs welcome. Start by opening an issue to discuss larger changes. See [`CONTRIBUTING.md`](CONTRIBUTING.md).\n\n## License\n\nMIT — see [`LICENSE`](LICENSE).\n\n## Acknowledgements\n\n- [Baileys](https://github.com/WhiskeySockets/Baileys) — the whatsmeow-style TS client that does the real work\n- [Anthropic Claude Code](https://claude.com/claude-code) — the CLI this bridges to\n- Prior art: [Rich627/whatsapp-claude-plugin](https://github.com/Rich627/whatsapp-claude-plugin), [osisdie/claude-code-channels](https://github.com/osisdie/claude-code-channels), [RichardAtCT/claude-code-telegram](https://github.com/RichardAtCT/claude-code-telegram) — inspiration and reference points\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feusougustavocesar%2Freverb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feusougustavocesar%2Freverb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feusougustavocesar%2Freverb/lists"}