coderClaw

Gmail Pub/Sub -> CoderClaw

Goal: Gmail watch -> Pub/Sub push -> gog gmail watch serve -> CoderClaw webhook.

Prereqs

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:

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:

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):

Manual daemon (starts gog gmail watch serve + auto-renew):

coderclaw webhooks gmail run

One-time setup

  1. Select the GCP project that owns the OAuth client used by 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.

  1. Enable APIs:
gcloud services enable gmail.googleapis.com pubsub.googleapis.com
  1. Create a topic:
gcloud pubsub topics create gog-gmail-watch
  1. Allow Gmail push to publish:
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
  --member=serviceAccount:[email protected] \
  --role=roles/pubsub.publisher

Start the watch

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).

Run the push handler

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:

Recommended: coderclaw webhooks gmail run wraps the same flow and auto-renews the watch.

Expose the handler (advanced, unsupported)

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@...>

Test

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>

Troubleshooting

Cleanup

gog gmail watch stop --account [email protected]
gcloud pubsub subscriptions delete gog-gmail-watch-push
gcloud pubsub topics delete gog-gmail-watch