| name | add-gmail |
| description | Add Gmail integration to NanoClaw. Can be configured as a tool (agent reads/sends emails when triggered from WhatsApp) or as a full channel (emails can trigger the agent, schedule tasks, and receive replies). Guides through GCP OAuth setup and implements the integration. |
Add Gmail Integration
This skill adds Gmail support to NanoClaw — either as a tool (read, send, search, draft) or as a full channel that polls the inbox.
Phase 1: Pre-flight
Check if already applied
Read .nanoclaw/state.yaml. If gmail is in applied_skills, skip to Phase 3 (Setup). The code changes are already in place.
Ask the user
Ask whether incoming emails should be able to trigger the agent.
- Yes — Full channel mode: the agent listens on Gmail and responds to incoming emails automatically
- No — Tool-only: the agent gets full Gmail tools (read, send, search, draft) but won't monitor the inbox. No channel code is added.
Phase 2: Apply Code Changes
Initialize skills system (if needed)
If .nanoclaw/ directory doesn't exist yet:
npx tsx scripts/apply-skill.ts --init
Path A: Tool-only (user chose "No")
Do NOT run the full apply script. Only two source files need changes. This avoids adding dead code (gmail.ts, gmail.test.ts, index.ts channel logic, routing tests, googleapis dependency).
1. Expose Gmail credentials to the local worker
The old container mount instructions are obsolete. For the current local worker, prefer a group-scoped workerEnv entry in ~/.config/nanoclaw/group-secrets.json or an explicit writable root only when the MCP server needs filesystem credentials. Do not expose the full project .env.
2. Add Gmail MCP server to the Codex runtime
For local stdio MCP, add the gmail server to the mcp_servers config built in container/agent-runner/src/runtime/codex-runtime.ts. For HTTP/SSE MCP, prefer per-group containerConfig.mcpServers.
3. Record in state
Add gmail to .nanoclaw/state.yaml under applied_skills with mode: tool-only.
4. Validate
npm run build
Build must be clean before proceeding. Skip to Phase 3.
Path B: Channel mode (user chose "Yes")
Run the full skills engine to apply all code changes:
npx tsx scripts/apply-skill.ts .claude/skills/add-gmail
This deterministically:
- Adds
src/channels/gmail.ts (GmailChannel class with self-registration via registerChannel)
- Adds
src/channels/gmail.test.ts (unit tests)
- Appends
import './gmail.js' to the channel barrel file src/channels/index.ts
- Ports Gmail credential access to the current local-worker runtime
- Adds the Gmail MCP server to the Codex runtime config
- Installs the
googleapis npm dependency
- Records the application in
.nanoclaw/state.yaml
If the apply reports merge conflicts, read the intent files:
modify/src/channels/index.ts.intent.md — what changed for the barrel file
modify/src/container-runner.ts.intent.md — what changed for container-runner.ts
modify/container/agent-runner/src/index.ts.intent.md — what changed for agent-runner
Add email handling instructions
Append the following to groups/main/AGENTS.md:
## Email Notifications
When you receive an email notification (messages starting with `[Email from ...`), inform the user about it but do NOT reply to the email unless specifically asked. You have Gmail tools available — use them only when the user explicitly asks you to reply, forward, or take action on an email.
Validate
npm test
npm run build
All tests must pass (including the new gmail tests) and build must be clean before proceeding.
Phase 3: Setup
Check existing Gmail credentials
ls -la ~/.gmail-mcp/ 2>/dev/null || echo "No Gmail config found"
If credentials.json already exists, skip to "Build and restart" below.
GCP Project Setup
Tell the user:
I need you to set up Google Cloud OAuth credentials:
- Open https://console.cloud.google.com — create a new project or select existing
- Go to APIs & Services > Library, search "Gmail API", click Enable
- Go to APIs & Services > Credentials, click + CREATE CREDENTIALS > OAuth client ID
- If prompted for consent screen: choose "External", fill in app name and email, save
- Application type: Desktop app, name: anything (e.g., "NanoClaw Gmail")
- Click DOWNLOAD JSON and save as
gcp-oauth.keys.json
Where did you save the file? (Give me the full path, or paste the file contents here)
If user provides a path, copy it:
mkdir -p ~/.gmail-mcp
cp "/path/user/provided/gcp-oauth.keys.json" ~/.gmail-mcp/gcp-oauth.keys.json
If user pastes JSON content, write it to ~/.gmail-mcp/gcp-oauth.keys.json.
OAuth Authorization
Tell the user:
I'm going to run Gmail authorization. A browser window will open — sign in and grant access. If you see an "app isn't verified" warning, click "Advanced" then "Go to [app name] (unsafe)" — this is normal for personal OAuth apps.
Run the authorization:
npx -y @gongrzhe/server-gmail-autoauth-mcp auth
If that fails (some versions don't have an auth subcommand), try timeout 60 npx -y @gongrzhe/server-gmail-autoauth-mcp || true. Verify with ls ~/.gmail-mcp/credentials.json.
Build and restart
Compile and restart:
npm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
Phase 4: Verify
Test tool access (both modes)
Tell the user:
Gmail is connected! Send this in your main channel:
@Andy check my recent emails or @Andy list my Gmail labels
Test channel mode (Channel mode only)
Tell the user to send themselves a test email. The agent should pick it up within a minute. Monitor: tail -f logs/nanoclaw.log | grep -iE "(gmail|email)".
Once verified, offer filter customization. By default, only unread Primary inbox emails trigger the agent (is:unread category:primary). The user can keep this default or narrow further by sender, label, or keywords.
Check logs if needed
tail -f logs/nanoclaw.log
Troubleshooting
Gmail connection not responding
Test directly:
npx -y @gongrzhe/server-gmail-autoauth-mcp
OAuth token expired
Re-authorize:
rm ~/.gmail-mcp/credentials.json
npx -y @gongrzhe/server-gmail-autoauth-mcp
Worker can't access Gmail
- Verify the Gmail MCP server can find
~/.gmail-mcp/credentials.json
- Check the newest worker log:
ls -lt groups/*/logs/worker-*.log | head
Emails not being detected (Channel mode only)
- By default, the channel polls unread Primary inbox emails (
is:unread category:primary)
- Check logs for Gmail polling errors
Removal
Tool-only mode
- Remove
~/.gmail-mcp mount from src/container-runner.ts
- Remove
gmail MCP server and mcp__gmail__* from container/agent-runner/src/index.ts
- Remove
gmail from .nanoclaw/state.yaml
- Rebuild:
npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw (macOS) or systemctl --user restart nanoclaw (Linux)
Channel mode
- Delete
src/channels/gmail.ts and src/channels/gmail.test.ts
- Remove
import './gmail.js' from src/channels/index.ts
- Remove
~/.gmail-mcp mount from src/container-runner.ts
- Remove
gmail MCP server and mcp__gmail__* from container/agent-runner/src/index.ts
- Uninstall:
npm uninstall googleapis
- Remove
gmail from .nanoclaw/state.yaml
- Rebuild:
npm run build && launchctl kickstart -k gui/$(id -u)/com.nanoclaw (macOS) or systemctl --user restart nanoclaw (Linux)