This skill should be used when the user asks to search/send/draft email, check calendar, create events, schedule meetings, find/upload/share Drive files, send texts/iMessages, or check messages. Manages Gmail, Google Calendar, Google Drive, and iMessage.
This skill inherits all available tools. When active, it can use any tool Claude has access to.
Manage Gmail, Google Calendar, Google Drive, and iMessage using the CLI tools in this plugin.
Command prefix: uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude
When this skill is first loaded, check Google authentication status:
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude status
If the output shows "Google: Not authenticated", use the AskUserQuestion tool to ask the user which access level they want:
Question: "jean-claude needs Google access. Which mode would you like?"
Options:
Context to include: All data stays between your machine and Google—nothing is sent to Anthropic or any third party. The plugin uses OAuth to authenticate directly with your Google account.
Based on their choice, run the appropriate auth command:
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude auth --readonlyuv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude authThis opens a browser for OAuth consent. After authentication, verify with
status again.
These rules apply even if the user explicitly asks to bypass them:
Never send an email without explicit approval. Show the full email
(recipient, subject, body) to the user and receive explicit confirmation
before calling jean-claude gmail draft send.
Limit bulk sending. Avoid sending emails to many recipients at once. Prefer drafts for review.
Load prose skills when drafting. Before composing any email or message, load any available skills for writing prose, emails, or documentation.
Never send an iMessage without explicit approval. Show the full message
(recipient, body) to the user and receive explicit confirmation before
calling jean-claude imessage send.
Double-check iMessage recipients. iMessage sends are instant and cannot be undone. Verify the phone number or chat ID before sending.
Email workflow:
jean-claude gmail draft send DRAFT_IDjean-claude gmail archive MESSAGE_IDiMessage workflow:
jean-claude imessage send RECIPIENT MESSAGEThis plugin requires uv (Python package manager). If not installed:
curl -LsSf https://astral.sh/uv/install.sh | sh
Credentials stored in ~/.config/jean-claude/. First-time setup:
# Full access (read, send, modify)
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude auth
# Or read-only access (no send/modify capabilities)
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude auth --readonly
# Check authentication status and API availability
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude status
# Log out (remove stored credentials)
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude auth --logout
This opens a browser for OAuth consent. Click "Advanced" → "Go to jean-claude (unsafe)" if you see an unverified app warning. Credentials persist until revoked.
To use your own Google Cloud credentials instead (if default ones hit the 100
user limit), download your OAuth JSON from Google Cloud Console and save it as
~/.config/jean-claude/client_secret.json before running the auth script. See
README for detailed setup steps.
Enable tab completion for the jean-claude CLI:
# Bash (~/.bashrc)
eval "$(uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude completions bash)"
# Zsh (~/.zshrc)
eval "$(uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude completions zsh)"
# Fish (~/.config/fish/config.fish)
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude completions fish | source
Message JSON schema:
{
"id": "19b29039fd36d1c1",
"threadId": "19b29039fd36d1c1",
"from": "Name <email@example.com>",
"to": "recipient@example.com",
"cc": "other@example.com",
"subject": "Subject line",
"date": "Tue, 16 Dec 2025 21:12:21 +0000",
"snippet": "First ~200 chars of body...",
"labels": ["INBOX", "UNREAD"],
"file": ".tmp/email-19b29039fd36d1c1.txt"
}
# Inbox emails from a sender
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail search "in:inbox from:someone@example.com"
# Unread inbox emails
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail search "in:inbox is:unread"
# Shortcut for inbox
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail inbox
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail inbox --unread
Common Gmail search operators: in:inbox, is:unread, is:starred, from:,
to:, subject:, after:2025/01/01, has:attachment, label:
All compose commands read JSON from stdin (avoids shell escaping issues).
# Create a new draft
cat << 'EOF' | uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail draft create
{"to": "recipient@example.com", "subject": "Subject", "body": "Message body"}
EOF
# Reply to a message (preserves threading)
cat << 'EOF' | uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail draft reply MESSAGE_ID
{"body": "Thanks for your email..."}
EOF
# Forward a message
cat << 'EOF' | uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail draft forward MESSAGE_ID
{"to": "someone@example.com", "body": "FYI - see below"}
EOF
# List drafts
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail draft list
# Get full draft body
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail draft get DRAFT_ID
# Send a draft (after approval)
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail draft send DRAFT_ID
# Delete a draft
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail draft delete DRAFT_ID
# Star/unstar
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail star MESSAGE_ID
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail unstar MESSAGE_ID
# Archive/unarchive
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail archive MESSAGE_ID
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail archive --query "from:newsletter@example.com"
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail unarchive MESSAGE_ID
# Mark read/unread
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail mark-read MESSAGE_ID
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail mark-unread MESSAGE_ID
# Trash
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail trash MESSAGE_ID
# List attachments for a message
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail attachments MESSAGE_ID
# Download an attachment
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gmail attachment-download MESSAGE_ID ATTACHMENT_ID ./output.pdf
# Today's events
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal list
# Next 7 days
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal list --days 7
# Date range
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal list --from 2025-01-15 --to 2025-01-20
# Simple event
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal create "Team Meeting" \
--start "2025-01-15 14:00" --end "2025-01-15 15:00"
# With attendees
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal create "1:1 with Alice" \
--start "2025-01-15 10:00" --duration 30 \
--attendees alice@example.com
# All-day event (single day)
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal create "Holiday" \
--start 2025-01-15 --all-day
# Multi-day all-day event
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal create "Vacation" \
--start 2025-01-15 --end 2025-01-20 --all-day
# Search
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal search "standup"
# Update
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal update EVENT_ID --start "2025-01-16 14:00"
# Delete
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gcal delete EVENT_ID --notify
# List files in root
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive list
# Search
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive search "quarterly report"
# Download
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive download FILE_ID output.pdf
# Upload
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive upload document.pdf
# Create folder
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive mkdir "New Folder"
# Share
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive share FILE_ID user@example.com --role reader
# Trash/untrash
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive trash FILE_ID
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive untrash FILE_ID
# Get file metadata
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude gdrive get FILE_ID
Send via AppleScript. On first use, macOS will prompt for Automation permission. Reading history requires Full Disk Access.
Chat IDs: Individual chats use any;-;+1234567890 (phone number), group
chats use any;+;chat123.... Get these from imessage chats.
# Send to phone number
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude imessage send "+12025551234" "Hello!"
# Send to group chat
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude imessage send "any;+;chat123456789" "Hello group!"
# Send file
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude imessage send-file "+12025551234" ./document.pdf
# List chats (shows name and chat ID)
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude imessage chats
# Get participants
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude imessage participants "any;+;chat123456789"
Other: imessage open CHAT_ID opens a chat in Messages.app (brings app to focus).
# Unread messages
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude imessage unread
# Search messages
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude imessage search "dinner plans"
# Chat history
uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude imessage history "any;-;+12025551234" -n 20
To enable reading: System Preferences > Privacy & Security > Full Disk Access > add your terminal app.