Goal: Gmail watch -> Pub/Sub push -> gog gmail watch serve -> CoderClaw webhook.
gcloud installed and logged in (install guide).gog (gogcli) installed and authorized for the Gmail account (gogcli.sh).tailscale logged in (tailscale.com). Supported setup uses Tailscale Funnel for the public HTTPS endpoint.
Other tunnel services can work, but are DIY/unsupported and require manual wiring.
Right now, Tailscale is what we support.Example hook config (enable Gmail preset mapping):
{
hooks: {
enabled: true,
token: "CODERCLAW_HOOK_TOKEN",
path: "/hooks",
presets: ["gmail"],
},
}
To deliver the Gmail summary to a chat surface, override the preset with a mapping
that sets deliver + optional channel/to:
{
hooks: {
enabled: true,
token: "CODERCLAW_HOOK_TOKEN",
presets: ["gmail"],
mappings: [
{
match: { path: "gmail" },
action: "agent",
wakeMode: "now",
name: "Gmail",
sessionKey: "hook:gmail:",
messageTemplate: "New email from \nSubject: \n\n",
model: "openai/gpt-5.2-mini",
deliver: true,
channel: "last",
// to: "+15551234567"
},
],
},
}
If you want a fixed channel, set channel + to. Otherwise channel: "last"
uses the last delivery route (falls back to WhatsApp).
To force a cheaper model for Gmail runs, set model in the mapping
(provider/model or alias). If you enforce agents.defaults.models, include it there.
To set a default model and thinking level specifically for Gmail hooks, add
hooks.gmail.model / hooks.gmail.thinking in your config:
{
hooks: {
gmail: {
model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
thinking: "off",
},
},
}
Notes:
model/thinking in the mapping still overrides these defaults.hooks.gmail.model → agents.defaults.model.fallbacks → primary (auth/rate-limit/timeouts).agents.defaults.models is set, the Gmail model must be in the allowlist.hooks.gmail.allowUnsafeExternalContent: true.To customize payload handling further, add hooks.mappings or a JS/TS transform module
under ~/.coderclaw/hooks/transforms (see Webhooks).
Use the CoderClaw helper to wire everything together (installs deps on macOS via brew):
coderclaw webhooks gmail setup \
--account [email protected]
Defaults:
hooks.gmail config for coderclaw webhooks gmail run.hooks.presets: ["gmail"]).Path note: when tailscale.mode is enabled, CoderClaw automatically sets
hooks.gmail.serve.path to / and keeps the public path at
hooks.gmail.tailscale.path (default /gmail-pubsub) because Tailscale
strips the set-path prefix before proxying.
If you need the backend to receive the prefixed path, set
hooks.gmail.tailscale.target (or --tailscale-target) to a full URL like
http://127.0.0.1:8788/gmail-pubsub and match hooks.gmail.serve.path.
Want a custom endpoint? Use --push-endpoint <url> or --tailscale off.
Platform note: on macOS the wizard installs gcloud, gogcli, and tailscale
via Homebrew; on Linux install them manually first.
Gateway auto-start (recommended):
hooks.enabled=true and hooks.gmail.account is set, the Gateway starts
gog gmail watch serve on boot and auto-renews the watch.CODERCLAW_SKIP_GMAIL_WATCHER=1 to opt out (useful if you run the daemon yourself).listen tcp 127.0.0.1:8788: bind: address already in use.Manual daemon (starts gog gmail watch serve + auto-renew):
coderclaw webhooks gmail run
gog.gcloud auth login
gcloud config set project <project-id>
Note: Gmail watch requires the Pub/Sub topic to live in the same project as the OAuth client.
gcloud services enable gmail.googleapis.com pubsub.googleapis.com
gcloud pubsub topics create gog-gmail-watch
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
--member=serviceAccount:[email protected] \
--role=roles/pubsub.publisher
gog gmail watch start \
--account [email protected] \
--label INBOX \
--topic projects/<project-id>/topics/gog-gmail-watch
Save the history_id from the output (for debugging).
Local example (shared token auth):
gog gmail watch serve \
--account [email protected] \
--bind 127.0.0.1 \
--port 8788 \
--path /gmail-pubsub \
--token <shared> \
--hook-url http://127.0.0.1:18789/hooks/gmail \
--hook-token CODERCLAW_HOOK_TOKEN \
--include-body \
--max-bytes 20000
Notes:
--token protects the push endpoint (x-gog-token or ?token=).--hook-url points to CoderClaw /hooks/gmail (mapped; isolated run + summary to main).--include-body and --max-bytes control the body snippet sent to CoderClaw.Recommended: coderclaw webhooks gmail run wraps the same flow and auto-renews the watch.
If you need a non-Tailscale tunnel, wire it manually and use the public URL in the push subscription (unsupported, no guardrails):
cloudflared tunnel --url http://127.0.0.1:8788 --no-autoupdate
Use the generated URL as the push endpoint:
gcloud pubsub subscriptions create gog-gmail-watch-push \
--topic gog-gmail-watch \
--push-endpoint "https://<public-url>/gmail-pubsub?token=<shared>"
Production: use a stable HTTPS endpoint and configure Pub/Sub OIDC JWT, then run:
gog gmail watch serve --verify-oidc --oidc-email <svc@...>
Send a message to the watched inbox:
gog gmail send \
--account [email protected] \
--to [email protected] \
--subject "watch test" \
--body "ping"
Check watch state and history:
gog gmail watch status --account [email protected]
gog gmail history --account [email protected] --since <historyId>
Invalid topicName: project mismatch (topic not in the OAuth client project).User not authorized: missing roles/pubsub.publisher on the topic.historyId; fetch via gog gmail history.gog gmail watch stop --account [email protected]
gcloud pubsub subscriptions delete gog-gmail-watch-push
gcloud pubsub topics delete gog-gmail-watch