marmot

Marmot docs

20 pages, from the idea to the error codes

Concepts

Lookout and watcher

A guardian who never looks is just a delay. These make sure you look.

Why you need one

The waiting room protects you only if somebody is watching it. A veto needs a human decision ("is that me?") or a rule ("is that an address I know?"). Marmot ships both a web lookout and a terminal watcher.

The web lookout

Open the Lookout, paste the vault address. It reads the chain directly from your browser (the public RPC allows it), shows every announcement in a sentence, and refreshes every 6 seconds. When a new one appears it plays a whistle, flashes the tab title and, if you pressed "Alert me", sends a desktop notification. Each live announcement has a "Whistle" button.

For a passkey guardian, the button asks your device for the passkey, checks the signature in the page, then offers to send it with your wallet, or to copy the calldata or a CLI command. For a wallet guardian it builds the veto transaction for that wallet.

The terminal watcher

node cli/marmot.mjs watch <vault> [--interval 5] [--notify-url URL]
                                  [--auto-veto --allow 0xA,0xB]

On start it examines everything already waiting (announcements made while it was off), then follows new events. For each announcement it prints a line with a risk label, and posts JSON to --notify-url if you gave one. The JSON carries both a text field (Slack-style webhooks) and a content field (Discord webhooks), so either accepts it as is.

QUEUED   #4 [MONEY] Send 1.0 ETH to 0x0F54...1074  (ready 2026-10-10T15:18:19.000Z)
PENDING  #5 [UNLIMITED APPROVAL] Let 0x91aa...30c2 spend UNLIMITED USDC
QUEUED   #6 [CONTROL CHANGE] Hand the vault to a new owner 0x4faE...432E

Auto-veto

With --auto-veto and a guardian wallet key in MARMOT_PRIVATE_KEY, the watcher refuses every announcement that is not a plain send (ETH or token) to an address on your --allow list. That means every approval, call, setting and owner change is refused automatically, and so is any send to an unknown address.

It checks that the announcement is still live before sending the veto, so replaying history never fires a stale transaction. A passkey guardian cannot auto-veto: a passkey needs a person. Use the notification to wake yourself up.

A hot guardian key

An auto-veto key lives on a machine that is online. It can only refuse, never move money, so the worst a thief can do with it is annoy you. Even so, treat it like a password.

Risk labels

LabelMeans
MONEYSends ETH or tokens out, or an ordinary call
UNLIMITED APPROVALAn approve with an effectively unlimited amount. Once run, the spender can drain that token without the vault.
CONTROL CHANGEChanges who controls the vault (new owner or new guardian), or shortens the wait below an hour
SETTINGChanges the wait to an hour or more

Keeping it running

On a spare machine or a small server, run the watcher under any process manager (pm2, systemd, a Windows scheduled task). Keep the --notify-url webhook private. Check that you really get the alert: announce a tiny test withdrawal and see how long the notification takes.