Gmail Plugin Setup Guide
This guide walks you through setting up the Gmail plugin for nakimi.
Overview
What you’ll get:
- Read access to your Gmail (unread emails, search, labels)
- Compose access (create drafts, send emails)
- No delete/modify access (readonly + compose scope only)
What you need:
- A Google account
- A Google Cloud project (free tier is fine)
- 15-20 minutes
Architecture
The Gmail plugin is a standard nakimi plugin that:
- Loads credentials from the vault’s encrypted secrets
- Uses Google’s official API libraries
- Auto-refreshes OAuth tokens before expiry
- Provides CLI commands through the plugin system
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ User CLI │────▶│ GmailPlugin │────▶│ GmailClient │
│nakimi │ │ │ │ │
│gmail.unread │ │ • validate │ │ • OAuth │
│gmail.send │ │ • commands │ │ • API calls │
└─────────────┘ └──────┬──────┘ └─────────────┘
│
┌──────┴──────┐
│ Vault Core │
│ (encrypted) │
└─────────────┘
Step 1: Create a Google Cloud Project
- Go to Google Cloud Console
- Sign in with your Google account
- Click the project selector at the top
- Click New Project
- Enter a name (e.g., “nakimi-gmail”)
- Click Create
- Wait for it to create, then select your new project
Step 2: Enable Gmail API
- Go to APIs & Services → Library (in the left sidebar)
- Search for “Gmail API”
- Click on Gmail API
- Click Enable
- Wait for it to activate (may take a minute)
Step 3: Configure OAuth Consent Screen
- Go to APIs & Services → OAuth consent screen
- Select External (or Internal if you have a Workspace org)
- Click Create
- Fill in:
- App name: “Kimi Vault Gmail” (or whatever you want)
- User support email: Your email
- Developer contact information: Your email
- Click Save and Continue
- On the Scopes page:
- Click Add or Remove Scopes
- Search for “Gmail API”
- Select:
.../auth/gmail.readonly.../auth/gmail.compose
- Click Update
- Click Save and Continue
- On the Test users page:
- Click Add Users
- Add your own email address
- Click Add
- Click Save and Continue
- Review and click Back to Dashboard
Step 4: Create OAuth Credentials
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Select Desktop app as Application type
- Enter a name: “Kimi Vault Desktop”
- Click Create
- You’ll see your Client ID and Client Secret
- Click Download JSON and save it as
client_secret.json
Step 5: Get Refresh Token
The refresh token is what the plugin uses to access Gmail on your behalf.
Option A: Using Google’s OAuth Playground (Easiest)
- Go to OAuth Playground
- Click the Settings (gear) icon
- Check “Use your own OAuth credentials”
- Enter:
- OAuth Client ID: (from your client_secret.json)
- OAuth Client Secret: (from your client_secret.json)
- Close settings
- In “Select & authorize APIs”:
- Find and select both scopes:
https://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.compose
- Click Authorize APIs
- Find and select both scopes:
- Sign in with your Google account
- Grant permission
- Click Exchange authorization code for tokens
- Copy the Refresh token (long string starting with
1//)
Option B: Python Script
If you prefer:
from google_auth_oauthlib.flow import InstalledAppFlow
SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/gmail.compose'
]
flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES)
credentials = flow.run_local_server(port=0)
print(f"Refresh token: {credentials.refresh_token}")
Step 6: Add Credentials to Vault
- Copy the template:
cp config/secrets.template.json ~/.nakimi/secrets.json - Edit
~/.nakimi/secrets.json:{ "gmail": { "client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com", "client_secret": "YOUR_CLIENT_SECRET", "refresh_token": "YOUR_REFRESH_TOKEN", "user": "your-email@example.com" } } - Encrypt with your vault key:
age -r $(cat ~/.nakimi/key.txt.pub) \ -o ~/.nakimi/secrets.json.age \ ~/.nakimi/secrets.json - Securely delete plaintext:
shred -u ~/.nakimi/secrets.json # Or on macOS: rm -P ~/.nakimi/secrets.json - Also delete the downloaded client_secret.json:
shred -u client_secret.json
Step 7: Test!
# Check plugin loaded
nakimi plugins list
# Should show: gmail - Gmail integration - read, search, and send emails
# Test commands
nakimi gmail.profile
nakimi gmail.unread
nakimi gmail.labels
# Search
nakimi gmail.search "from:boss@company.com"
# Send a test email (to yourself)
nakimi gmail.send "your-email@example.com" "Test" "This is a test email from nakimi!"
Using in a Session
# Start a secure session
nakimi session
# Inside the session, same commands work:
$ nakimi gmail.unread 5
$ nakimi gmail.search "subject:invoice"
The vault automatically:
- Decrypts secrets when you start the session
- Makes them available to the Gmail plugin
- Securely shreds them when you exit
Gmail Commands Reference
| Command | Description | Example |
|---|---|---|
gmail.profile | Show your Gmail profile | nakimi gmail.profile |
gmail.unread [limit] | List unread emails (default: 10) | nakimi gmail.unread 5 |
gmail.labels | List all labels | nakimi gmail.labels |
gmail.search <query> | Search emails | nakimi gmail.search "from:google" |
gmail.send <to> <subject> <body> | Send an email | nakimi gmail.send "test@example.com" "Hi" "Hello" |
gmail.draft <to> <subject> <body> | Create a draft | nakimi gmail.draft "test@example.com" "Draft" "Content" |
Troubleshooting
“Access blocked: app not verified”
Google shows a warning because it’s a personal app (not verified by Google).
- Click Advanced
- Click Go to [your app name] (unsafe)
- Continue with authorization
This is normal for personal OAuth apps.
“Invalid client” errors
- Check that
client_idends with.apps.googleusercontent.com - Make sure there are no extra spaces in the JSON
- Verify the client ID matches what’s in Google Cloud Console
“Refresh token expired”
Refresh tokens for “Testing” apps expire after 7 days.
Solution: Repeat Step 5 to get a new refresh token, then update your vault.
Plugin not showing in list
# Check if secrets file exists
ls ~/.nakimi/secrets.json.age
# Decrypt and verify content
age -d -i ~/.nakimi/key.txt ~/.nakimi/secrets.json.age | python -m json.tool
# Should have "gmail" section with all required fields
“Missing Gmail configuration”
The plugin needs these fields in secrets.json:
client_idclient_secretrefresh_token
Check that all are present:
age -d -i ~/.nakimi/key.txt ~/.nakimi/secrets.json.age | \
python -c "import sys, json; d=json.load(sys.stdin); print('gmail' in d and all(k in d['gmail'] for k in ['client_id', 'client_secret', 'refresh_token']))"
Security Notes
- Scope: We use
gmail.readonly+gmail.compose- can read and compose emails but cannot delete or modify existing ones - Token storage: Tokens are encrypted at rest with age, decrypted only during sessions
- Session lifetime: Secrets exist only in a temp file during the session (
/dev/shmif available,/tmpotherwise) - Cleanup: Automatically shredded when the session ends
Next Steps
- Learn how to create custom plugins
- Set up additional plugins (Calendar, GitHub coming soon)
- Review the Architecture to understand security model