Dead Ringer
Docs

Install on Mac

Dead Ringer is a local stand-in for Meta's WhatsApp Cloud API. It runs entirely on your machine: your app sends messages to it instead of to Meta, and you play the customer from its window. No Meta account is involved, and nothing leaves the machine except a media link your app sends, which Dead Ringer downloads as Meta would (you can turn that off per project).

Works on Apple Silicon and Intel Macs, macOS 11 or later.

Install

  1. Sign in and download Dead-Ringer-<version>-macos.dmg. Signing in emails you a six-digit code; there is no password.
  2. Open the disk image and drag Dead Ringer onto the Applications shortcut beside it.
  3. Eject the image, then open Dead Ringer from Applications.

That is the whole install. The app is signed with an Apple Developer ID certificate and notarized by Apple, so it opens like any other app — no "unidentified developer" warning, and nothing to allow in Privacy & Security.

If you are holding an older build from before September 2026, macOS blocks it on first launch with "Apple could not verify". Click Done, open System Settings → Privacy & Security, scroll to the Security section and click Open Anyway. Better: get a current build, which does not ask.

What you get

The window is the mock's UI: create a project per integration you work on, and each project gives you the credentials and base URL to put in your app's config. The API listens on http://127.0.0.1:3010. See the quickstart for pointing an integration at it, and agent and MCP setup if an agent is doing that for you.

Menu items worth knowing:

  • Mock → Open in Browser (⌘B): the same UI in your default browser, if you prefer tabs.
  • Mock → Copy API Base URL (⇧⌘C): what your app's Graph API base URL should be.
  • Mock → Copy MCP URL: what to add to an AI agent so it can drive the mock. Connect an agent at the top of the window walks through it for Claude Code, Cursor, VS Code and Codex.
  • Mock → Show Data Folder: where the database and uploaded media live.

Closing the window does not quit. The mock keeps running and keeps delivering webhooks to your app, like a menu bar tool. Quit with ⌘Q. Click the dock icon to get the window back.

Where your data is

~/Library/Application Support/deadringer/
    deadringer.db        every project, customer, message and template
    media/               uploaded files
    app.log              the current run's log, if something goes wrong
    app.json             only exists if you chose a different port

This is outside the app bundle, so updating the app never touches your data: replace the app in Applications, open it, and everything is where you left it. The new version upgrades the database in place if it needs to. To start from scratch, quit the app and delete that folder.

The terminal build of the mock uses the same folder, so projects are shared between the two.

Upgrading from the earlier build

Dead Ringer was renamed in September 2026. Quit the old app (⌘Q) and delete it from Applications, then install this one as above. On its first launch Dead Ringer moves your data over from ~/Library/Application Support/whatsapp-mock/, so every project is still there.

Quit the old app before opening the new one. While it runs it holds port 3010, and Dead Ringer does not recognise it as a copy of itself.

If it will not start

"Port 3010 is already in use." Every project's API base URL points at that port, so the app will not silently pick another one. The dialog gives you two choices:

  • Use another port. The app finds the next free port (3011 if it can), runs there, and remembers it for every future launch. Each project's base URL then shows that port, and that is what you put in your app's config. Mock → Forget Custom Port goes back to 3010 on the next launch.

  • Quit, stop the other program, and open the app again. To see what is holding the port:

    lsof -nP -iTCP:3010 -sTCP:LISTEN
    

If what is using it is another copy of the mock (for example one started from a terminal), the app attaches to that one instead of asking, and you will see its projects.

Anything else: look in app.log in the data folder above.