A Claude Code skill for Gmail OAuth,
search, draft, send, and fetch. Drop the repo into
~/.claude/skills/gmail/, build the bundled Rust CLI once, run a
one-time OAuth flow against your own Google client, and Claude can:
- Send email (
gmail-skill send --to ... --subject ... --body ...). - Draft email for later review.
- Search the inbox with full Gmail query syntax.
- Fetch the full body of any message by id.
- Send a draft by id.
It is also installable as a stand-alone CLI for use outside Claude Code.
git clone https://github.com/RobinGase/gmail-skill ~/.claude/skills/gmail
cd ~/.claude/skills/gmail/cli
cargo build --releasecargo install --git https://github.com/RobinGase/gmail-skill gmail-skill --bin gmail-skillYou provide your own Google OAuth credentials. The skill never ships them.
-
Enable the Gmail API for the project.
-
Create credentials → OAuth client ID → application type Desktop app.
-
Add
http://127.0.0.1:9876/callbackas an authorized redirect URI. -
Export the client id + secret:
export GMAIL_OAUTH_CLIENT_ID="xxxx.apps.googleusercontent.com" export GMAIL_OAUTH_CLIENT_SECRET="GOCSPX-..."
| Variable | Required | Purpose |
|---|---|---|
GMAIL_OAUTH_CLIENT_ID (or GOOGLE_OAUTH_CLIENT_ID) |
yes | OAuth client ID. |
GMAIL_OAUTH_CLIENT_SECRET (or GOOGLE_OAUTH_CLIENT_SECRET) |
yes | OAuth client secret. |
GMAIL_OAUTH_REDIRECT_URI |
no | Defaults to http://127.0.0.1:9876/callback. |
GMAIL_OAUTH_STORE_PATH |
no | Where tokens are saved. Default: platform data dir (%APPDATA%\gmail-skill\ on Windows, ~/.local/share/gmail-skill/ on Linux). |
GMAIL_API_BASE_URL |
no | Override for testing. Default https://gmail.googleapis.com/gmail/v1. |
SKILL_WORKSPACE_ROOT |
no | Root for resolving relative attachment paths. Default: cwd. |
gmail-skill connect # default: spawns loopback listener on 127.0.0.1:9876
gmail-skill status # verifyFor headless servers:
gmail-skill connect --manual # prints URL, exits
# (open URL in a browser, copy the `code` query param from the redirect)
gmail-skill complete --code <auth-code>gmail-skill status
gmail-skill search --query "from:foo@bar.com newer_than:7d" --limit 5
gmail-skill fetch --id 18b7e9d2c4a56789
gmail-skill send \
--to alice@example.com \
--subject "Quick update" \
--body "Hi,\n\nQuick note...\n\nThanks." \
--attachment data/leads.csv
gmail-skill draft --to alice@example.com --subject "..." --body "..."
gmail-skill send-draft --id <draft-id>
gmail-skill disconnect # clear stored tokensJSON-stdin mode for orchestrators:
echo '{"command":"run","operation":"send","args":{"to":["a@b.c"],"subject":"hi","body":"hi"}}' \
| gmail-skill --json-stdin- OAuth: Installed-app PKCE flow against
accounts.google.com/o/oauth2/v2/authandoauth2.googleapis.com/token. State + code-verifier are stored in agmail_pending.jsonfile alongside the token store;--manualmode persists pending state socompletecan finish the exchange. - Token refresh: On every API call the access token is checked for expiry (60 s skew). If expired and a refresh token is present, it's refreshed automatically and re-saved.
- RFC 822 builder: Plain-text bodies stay single-part. With
attachments, the message becomes
multipart/mixedwith one binary part per attachment, base64-encoded with the standard 76-char line-wrap. - Body decoding (fetch): Walks the MIME tree, prefers
text/plain, falls back to a stripped-tagtext/html, then to Gmail's snippet.
- Not a multi-account manager. The token store is single-account.
- Not a label/filter/rule editor. Send/draft/search/fetch only.
- Not a webhook receiver. It's a one-shot CLI; orchestrators poll
via
search.
The token store path search includes
data/oauth/gmail_tokens.json and ../data/oauth/gmail_tokens.json
(KaizenMAX's location) as low-priority fallbacks. Run gmail-skill
from inside a KaizenMAX workspace and your existing tokens are
discovered automatically. Or set GMAIL_OAUTH_STORE_PATH explicitly.
cd cli
cargo build --release
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --allRust 2024 edition (MSRV 1.88).
Dual-licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option. Contributions are accepted under the same dual licence unless noted otherwise.