From nanotars-gmail
Configures Gmail access for NanoTars agents via gog CLI, enabling search, read, and send email capabilities. Reuses Google Calendar OAuth if configured.
npx claudepluginhub terrifiedbug/nanotars-skills --plugin nanotars-gmailThis skill uses the workspace's default tool permissions.
Configures Gmail access for agent containers using the `gog` CLI, the same tool used for Google Calendar. If the user already has Calendar set up via `/add-skill-calendar`, Gmail just needs the scope added.
Adds read-only IMAP email access to NanoTars agent containers for Gmail, Yahoo, Outlook, and custom servers. Guides app password setup and .env configuration.
Adds Gmail integration to ClaudeClaw as tool (read/send/search/draft emails) or full channel (inbox polling, auto-triggers/replies). Guides GCP OAuth setup and applies code changes via git merge.
Adds Google Calendar (gog CLI with OAuth) and CalDAV (iCloud, Nextcloud, Fastmail via cal CLI) access to NanoTars by guiding authentication and configuring environment variables.
Share bugs, ideas, or general feedback.
Configures Gmail access for agent containers using the gog CLI, the same tool used for Google Calendar. If the user already has Calendar set up via /add-skill-calendar, Gmail just needs the scope added.
Mode: Tool Mode only -- agents can read/send emails when triggered from a channel (e.g., "check my email", "send an email to..."). This is NOT a channel (emails don't trigger the agent).
Before installing, verify NanoTars is set up:
[ -d node_modules ] && echo "DEPS: ok" || echo "DEPS: missing"
docker image inspect nanoclaw-agent:latest &>/dev/null && echo "IMAGE: ok" || echo "IMAGE: not built"
if grep -q "ANTHROPIC_API_KEY\|CLAUDE_CODE_OAUTH_TOKEN" .env 2>/dev/null || [ -f "$HOME/.claude/.credentials.json" ]; then echo "AUTH: ok"; else echo "AUTH: missing"; fi
If any check fails, tell the user to run /nanotars-setup first and stop.
which gog && echo "GOG_INSTALLED" || echo "GOG_MISSING"
grep "^GOG_KEYRING_PASSWORD=" .env 2>/dev/null && echo "GOG_CONFIGURED" || echo "GOG_NOT_CONFIGURED"
[ -d plugins/gmail ] && echo "PLUGIN_EXISTS" || echo "PLUGIN_MISSING"
[ -d data/gogcli ] && echo "GOG_CREDS_EXIST" || echo "GOG_CREDS_MISSING"
If gog is already installed and configured (Calendar is set up via /add-skill-calendar):
If gog is not installed:
Only needed if /add-skill-calendar hasn't been run yet.
Install gog:
which gog && echo "Already installed" || curl -sL "https://github.com/steipete/gogcli/releases/download/v0.9.0/gogcli_0.9.0_linux_amd64.tar.gz" | tar -xz -C /usr/local/bin gog
USER ACTION REQUIRED
Tell the user:
I need you to set up Google Cloud OAuth credentials:
- Go to https://console.cloud.google.com
- Create a new project (or select an existing one)
- Go to APIs & Services > Library, search for Gmail API, and Enable it
- Go to APIs & Services > Credentials
- Click + CREATE CREDENTIALS > OAuth client ID
- If prompted for consent screen, choose "External", fill in app name, save
- Application type: Desktop app, name it anything
- Click Create, then DOWNLOAD JSON
- Tell me where you saved the file
Import the credentials:
gog auth credentials /path/to/client_secret.json
Set keyring password:
grep "^GOG_KEYRING_PASSWORD=" .env 2>/dev/null && echo "ALREADY_SET" || echo 'GOG_KEYRING_PASSWORD=CHOOSE_A_PASSWORD' >> .env
Optionally set GOG_ACCOUNT if the user has multiple Google accounts (gog defaults to the first):
echo 'GOG_ACCOUNT=user@gmail.com' >> .env
If gog was already set up for Calendar (via /add-cal):
Tell the user:
You already have a GCP project from Calendar setup. I just need you to enable the Gmail API in that same project:
- Go to https://console.cloud.google.com
- Select your existing project (the one used for Calendar)
- Go to APIs & Services > Library
- Search for Gmail API and click Enable
- Let me know when done
Wait for confirmation, then re-auth with both scopes. gog stores one token per account — re-authing with expanded scopes replaces the old token. Google will prompt the user to grant the additional Gmail permission:
GOG_KEYRING_PASSWORD=$(grep GOG_KEYRING_PASSWORD .env | cut -d'=' -f2) gog auth login --services gmail,calendar
On a headless server (no browser):
GOG_KEYRING_PASSWORD=$(grep GOG_KEYRING_PASSWORD .env | cut -d'=' -f2) gog auth login --services gmail,calendar --manual
This prints an OAuth URL. Tell the user to open it in any browser, authorize the expanded permissions, then paste back the redirect URL.
If this is a fresh gog setup (Step 2 was completed):
GOG_KEYRING_PASSWORD=$(grep GOG_KEYRING_PASSWORD .env | cut -d'=' -f2) gog auth login --services gmail
Verify Gmail access:
GOG_KEYRING_PASSWORD=$(grep GOG_KEYRING_PASSWORD .env | cut -d'=' -f2) gog gmail labels list
mkdir -p data/gogcli
cp -r ~/.config/gogcli/* data/gogcli/
chown -R 1000:1000 data/gogcli
Ask the user which groups should have access to Gmail:
mainIf the user wants to restrict access, update plugins/gmail/plugin.json after copying (Step 6) to set "groups" to the list of group folder names:
"groups": ["main"]
If all groups (or the user doesn't care), leave as "groups": ["*"].
Restricting access means only those groups' agents will have Gmail tools. Other groups won't see the email commands or credentials.
Also ask about channel types. If the user wants this plugin available on all channel types (WhatsApp, Discord, etc.), leave "channels": ["*"]. To restrict, set "channels" to specific types (e.g., ["whatsapp"]). Most users will want the default.
cp -r ${CLAUDE_PLUGIN_ROOT}/files/ plugins/gmail/
The runtime silently rejects container mounts not covered by ~/.config/nanotars/mount-allowlist.json. Gmail mounts data/gogcli (shared with the calendar plugin if installed). Check whether it's already covered:
node -e '
const fs = require("fs"), path = require("path");
const home = process.env.HOME;
const allowlistPath = path.join(home, ".config/nanotars/mount-allowlist.json");
const expand = (p) => p.startsWith("~/") ? path.join(home, p.slice(2)) : path.resolve(p);
const target = path.resolve("data/gogcli");
if (!fs.existsSync(allowlistPath)) { console.log("MISSING_ALLOWLIST"); process.exit(0); }
const list = JSON.parse(fs.readFileSync(allowlistPath, "utf8"));
const covered = (list.allowedRoots || []).some(r => {
const a = expand(r.path);
return target === a || target.startsWith(a + "/");
});
console.log(covered ? "COVERED" : "NEEDS_ALLOWLIST_ENTRY");
'
If COVERED, skip ahead. Otherwise tell the user:
Gmail needs
~/nanotars/data/gogcliadded to the mount allowlist (~/.config/nanotars/mount-allowlist.json). I'll add a tightly-scoped entry — only this directory will be mountable, no broader access. OK?
After confirmation:
node -e '
const fs = require("fs"), path = require("path");
const allowlistPath = path.join(process.env.HOME, ".config/nanotars/mount-allowlist.json");
fs.mkdirSync(path.dirname(allowlistPath), { recursive: true });
const list = fs.existsSync(allowlistPath)
? JSON.parse(fs.readFileSync(allowlistPath, "utf8"))
: { allowedRoots: [], blockedPatterns: [], nonMainReadOnly: true };
list.allowedRoots = list.allowedRoots || [];
list.allowedRoots.push({
path: "~/nanotars/data/gogcli",
allowReadWrite: true,
description: "gmail/calendar plugin gogcli OAuth state"
});
fs.writeFileSync(allowlistPath, JSON.stringify(list, null, 2) + "\n");
JSON.parse(fs.readFileSync(allowlistPath, "utf8"));
console.log("ALLOWLIST_UPDATED");
'
./container/build.sh && npm run build
nanotars restart 2>/dev/null || echo "Restart the NanoTars service manually"
After restart, remove any stale agent containers so the next message spawns a fresh one with the new mount applied:
docker ps --format '{{.Names}}' | grep '^nanoclaw-' | xargs -r docker rm -f
Send a message in your channel like:
.env and the plugin's containerEnvVars includes it--services gmail,calendarIf this plugin is already installed and you want different credentials for a specific group (e.g., a work account for one group, personal for another):
Check which groups exist:
ls -d groups/*/
Ask the user which group should get separate credentials.
Collect the new GOG credentials for that group.
Write to the group's .env file (creates if needed):
echo 'GOG_KEYRING_PASSWORD=new-password' >> groups/{folder}/.env
echo 'GOG_ACCOUNT=other@gmail.com' >> groups/{folder}/.env
These values override the global .env for that group's containers only.
Restart NanoTars:
nanotars restart
rm -rf plugins/gmail/--services calendar only