GroundEffect
Hyper-fast, local Gmail and Google Calendar indexing for Claude Code, available as a Skill or MCP Server.
GroundEffect
Hyper-fast, local Gmail and Google Calendar indexing for Claude Code.
GroundEffect is a local headless IMAP/CalDav client, Claude Code skill, and MCP server built in Rust with LanceDB.
Features
- Hybrid Search: BM25 full-text + vector semantic search with Reciprocal Rank Fusion
- Local Embeddings: Runs nomic-embed-text-v1.5 locally via Candle with Metal acceleration
- Multi-Account: Connect unlimited Gmail/GCal accounts with independent sync
- MCP Integration: Exposes email and calendar tools directly to Claude Code
- Real-time Sync: IMAP IDLE for instant email notifications, CalDAV polling for calendar
- HTML Text Extraction: Automatically converts HTML emails to clean plain text using
html2text - Pluggable Token Storage: File-based (default) or PostgreSQL with AES-256-GCM encryption
Quick Start
1. Install
brew tap jamiequint/groundeffect
brew install groundeffect
This automatically:
- Installs the daemon (starts at login)
- Installs the Claude Code skill
- Adds permissions to run groundeffect commands
2. Configure OAuth
Create a Google Cloud project with OAuth credentials:
- Go to Google Cloud Console
- Create a project and enable Gmail API and Google Calendar API
- Go to APIs & Services > Credentials
- Create OAuth client ID (Desktop app type)
- Add your credentials:
echo 'export GROUNDEFFECT_GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"' >> ~/.zshrc
echo 'export GROUNDEFFECT_GOOGLE_CLIENT_SECRET="your-client-secret"' >> ~/.zshrc
source ~/.zshrc
3. Add an Account
groundeffect account add
This opens a browser for Google OAuth. After authentication, the daemon syncs automatically.
That's it! Ask Claude Code to search your emails and calendar.
CLI Reference
All commands output JSON by default. Add --human for readable output.
Account Commands
| Command | Description |
|---|---|
account list | List all connected accounts |
account show <account> | Show account details and sync status |
account add | Add new Google account via OAuth |
account reauth <account> | Re-authenticate an existing account via OAuth |
account delete <account> | Remove account and all synced data |
account configure <account> | Update account settings (alias, attachments) |
Parameters for add:
| Parameter | Description | Default |
|---|---|---|
--years | Years of email history to sync (1-20 or "all") | 1 |
--attachments | Enable automatic attachment download | off |
--alias | Friendly name for the account | - |
Email Commands
| Command | Description |
|---|---|
email search <query> | Hybrid BM25 + semantic search |
email list | List recent emails |
email show <id> | Show full email content |
email thread <thread_id> | Show all emails in a thread |
email send | Compose and send email |
email attachment <id> | Get attachment content |
email folders | List IMAP folders |
Parameters for search:
| Parameter | Description | Default |
|---|---|---|
--account | Filter to specific account | all |
--limit | Max results (max: 100) | 10 |
--from | Filter by sender | - |
--to | Filter by recipient | - |
--date-from | Filter after date (YYYY-MM-DD) | - |
--date-to | Filter before date (YYYY-MM-DD) | - |
--has-attachment | Filter emails with attachments | - |
Parameters for send:
| Parameter | Description |
|---|---|
--from | Account to send from (required) |
--to | Recipient(s) (required) |
--subject | Email subject (required) |
--body | Email body (required) |
--cc | CC recipients |
--bcc | BCC recipients |
--reply-to | Email ID to reply to (for threading) |
--html | Force HTML format (auto-detected from markdown/URLs) |
--save-as-draft | Save as draft instead of sending |
--confirm | Send immediately (without: preview only) |
Draft Commands
| Command | Description |
|---|---|
email draft create | Create a new email draft |
email draft list | List all drafts for an account |
email draft show <id> | Show full draft content |
email draft update <id> | Update an existing draft |
email draft send <id> | Send a draft |
email draft delete <id> | Delete a draft |
Parameters for draft create:
| Parameter | Description |
|---|---|
--from | Account to create draft in (required) |
--to | Recipient(s) |
--subject | Email subject |
--body | Email body |
--cc | CC recipients |
--bcc | BCC recipients |
--html | Force HTML format |
--reply-to | Email ID to reply to (for threading) |
Calendar Commands
| Command | Description |
|---|---|
calendar events | List events in a date range (no query required) |
calendar search <query> | Search events with semantic search |
calendar show <id> | Show event details |
calendar create | Create new event |
Parameters for events:
| Parameter | Description | Default |
|---|---|---|
--from | Start date (YYYY-MM-DD) | today |
--to | End date (YYYY-MM-DD) | 7 days from start |
--account | Filter to specific account(s) | all |
--limit | Max results (max: 200) | 50 |
--human | Human-readable output grouped by date | - |
Use calendar events to answer questions like "what's on my calendar tomorrow" or "show me my meetings next week" without requiring a search query.
Parameters for create:
| Parameter | Description | Default |
|---|---|---|
--account | Account to create event in (required) | - |
--summary | Event title (required) | - |
--start | Start time (ISO 8601) (required) | - |
--end | End time (ISO 8601) (required) | - |
--description | Event description | - |
--location | Event location | - |
--attendees | Attendee emails (repeatable) | - |
--calendar | Calendar ID | primary |
Sync Commands
| Command | Description |
|---|---|
sync status | Show sync status for all accounts |
sync reset --account <a> --confirm | Clear all synced data |
sync extend --account <a> --target-date <d> | Sync older emails back to date |
sync resume-from --account <a> --target-date <d> | Force sync to resume from date |
sync download-attachments --account <a> | Download pending attachments |
Daemon Commands
| Command | Description |
|---|---|
daemon install | Install launchd agent (auto-start at login) |
daemon uninstall | Remove launchd agent |
daemon status | Check if daemon is running |
daemon restart | Restart the daemon |
Config Commands
| Command | Description |
|---|---|
config settings | View/modify daemon settings |
config add-permissions | Add to Claude Code allowlist |
config remove-permissions | Remove from Claude Code allowlist |
Parameters for settings:
| Parameter | Description | Default |
|---|---|---|
--logging | Enable/disable file logging | off |
--email-interval | Email poll interval in seconds (60-3600) | 300 |
--calendar-interval | Calendar poll interval in seconds (60-3600) | 300 |
--max-fetches | Max concurrent fetches (1-50) | 10 |
--timezone | User timezone for date parsing (e.g., America/Los_Angeles) | UTC |
--embedding-provider | Embedding backend: local, openrouter, remote | local |
--embedding-batch-size | Embedding + IMAP fetch batch size (1-1024) | 128 |
--openrouter-model | OpenRouter embedding model ID | openai/text-embedding-3-small |
--openrouter-api-key-env | Env var name with OpenRouter API key | OPENROUTER_API_KEY |
Embeddings backend examples:
# Use local embeddings (default)
groundeffect config settings --embedding-provider local
# Use OpenRouter embeddings
export OPENROUTER_API_KEY="your-key"
groundeffect config settings --embedding-provider openrouter
# Set embedding + IMAP fetch batch size (128 recommended for Gmail/OpenRouter stability)
groundeffect config settings --embedding-batch-size 128
# Optional: set a different OpenRouter model
groundeffect config settings --openrouter-model "openai/text-embedding-3-large"
MCP Integration (Alternative)
If you prefer MCP over the CLI skill, add to ~/.claude.json:
{
"mcpServers": {
"groundeffect": {
"type": "stdio",
"command": "groundeffect-mcp",
"env": {
"GROUNDEFFECT_GOOGLE_CLIENT_ID": "${GROUNDEFFECT_GOOGLE_CLIENT_ID}",
"GROUNDEFFECT_GOOGLE_CLIENT_SECRET": "${GROUNDEFFECT_GOOGLE_CLIENT_SECRET}"
}
}
}
}
The skill is faster (direct CLI calls vs MCP JSON-RPC overhead) but MCP works with other MCP-compatible clients.
Build from Source
git clone https://github.com/jamiequint/groundeffect.git
cd groundeffect
cargo build --release
Binaries:
target/release/groundeffect- CLItarget/release/groundeffect-daemon- Background sync daemontarget/release/groundeffect-mcp- MCP server
Install manually:
# Install binaries
sudo cp target/release/groundeffect* /usr/local/bin/
# Install skill
cp -r skill ~/.claude/skills/groundeffect
# Install daemon
groundeffect daemon install
# Add permissions
groundeffect config add-permissions
Data Storage
~/.config/groundeffect/
├── config.toml # Main configuration
├── daemon.toml # Daemon configuration
└── tokens/ # OAuth tokens (file provider)
~/.local/share/groundeffect/
├── lancedb/ # LanceDB database
├── attachments/ # Downloaded attachments
├── models/ # Embedding model files
├── logs/ # Log files
└── cache/
└── sync_state/ # Sync state
~/.claude/skills/groundeffect/ # Claude Code skill
Token Storage
By default, OAuth tokens are stored in ~/.config/groundeffect/tokens/ as encrypted JSON files.
For server deployments or ephemeral containers, you can store tokens in PostgreSQL instead. This requires the postgres feature.
PostgreSQL Token Storage
-
Build with the postgres feature:
cargo build --release --features postgres -
Create the tokens table:
CREATE TABLE IF NOT EXISTS groundeffect_tokens ( email VARCHAR(255) PRIMARY KEY, encrypted_tokens BYTEA NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -
Configure in
~/.config/groundeffect/config.toml:[tokens] provider = "postgres" database_url_env = "DATABASE_URL" encryption_key_env = "GE_TOKEN_ENCRYPTION_KEY" # table_name = "groundeffect_tokens" # optional -
Set environment variables:
export DATABASE_URL="postgres://user:pass@localhost/mydb" export GE_TOKEN_ENCRYPTION_KEY="your-secret-key-here"
Tokens are encrypted at rest using AES-256-GCM with a key derived from your encryption key via HKDF-SHA256.
Troubleshooting
"OAuth token expired"
Re-authenticate:
groundeffect account reauth <email-or-alias>
Daemon not running
Check status and restart:
groundeffect daemon status
groundeffect daemon restart
Or check launchd:
launchctl list | grep groundeffect
View logs
tail -f ~/.local/share/groundeffect/logs/daemon.log
Enable logging if disabled:
groundeffect config settings --logging true
groundeffect daemon restart
High memory usage
Embedding model uses ~500MB-1GB during active embedding. Normal when idle.
Architecture
┌──────────────┐ ┌──────────────────┐
│ Claude Code │─────►│ groundeffect-mcp │────────┐
│ (MCP Host) │stdio │ │ │
└──────────────┘ └──────────────────┘ │
▼
┌──────────────┐ ┌──────────────────┐ ┌─────────┐
│ Claude Code │─────►│ groundeffect │───►│ LanceDB │
│ (Skill/Bash) │ │ (CLI) │ └─────────┘
└──────────────┘ └──────────────────┘ ▲
│
┌──────────────────┐ │
│ groundeffect- │─────────┘
│ daemon │◄──── IMAP/CalDAV
└──────────────────┘
License
MIT
İlgili Sunucular
4th Brain MCP Server
Interact with markdown notes in a personal knowledge vault, such as Obsidian.
Iron Manus MCP
A modular MCP server for task orchestration, API integration, and knowledge synthesis using a finite state machine.
Rember
Create spaced repetition flashcards in Rember to remember anything you learn in your chats
No-code Slack MCP Client (Powered by Runbear)
Unlock MCP for your whole team in Slack with a single install.
LimeSurvey
Manage surveys and responses in your LimeSurvey instance.
macOS Notification MCP
Trigger macOS notifications, sounds, and text-to-speech from an AI assistant.
Google Calendar
An MCP server for Google Calendar, enabling LLMs to read, create, and manage calendar events.
Microsoft Office (PowerPoint & Excel)
Automate Microsoft PowerPoint and Excel on Windows using AI-powered COM automation.
DeepLucid3D UCPF Server
An MCP server for advanced cognitive analysis, creative problem-solving, and structured thinking using the UCPF framework.
Counsel
Multi LLM Council for deep counsel on your topic or idea