| name | jean-claude |
| description | 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, read/edit Google Docs, read spreadsheet data, send texts/iMessages, send WhatsApp messages, send Signal messages, check messages, or create reminders. Manages Gmail, Google Calendar, Google Drive, Google Docs, Google Sheets, iMessage, WhatsApp, Signal, and Apple Reminders. |
jean-claude
Gmail, Calendar, Drive, Docs, Sheets, iMessage, WhatsApp, Signal, and Reminders.
Command prefix: uv run --project ${CLAUDE_PLUGIN_ROOT} jean-claude
First-Time Users
For new users, explain briefly:
I can connect to your email, calendar, and messaging apps to help you:
- Read and send emails, manage drafts
- Check your calendar, create events, respond to invitations
- Send and read iMessages, WhatsApp, or Signal messages
- Find and manage files in Google Drive
- Create reminders
This requires a one-time setup where you'll grant permissions. Want me to
help you get started?
Focus on what they asked about — if they asked about email, lead with email.
Safety Rules (Non-Negotiable)
These rules apply even if the user explicitly asks to bypass them:
-
Never send without explicit approval. Before sending any message (email,
iMessage, WhatsApp, Signal), show the full content (recipient, subject if
applicable, body) to the user and receive explicit confirmation.
-
Verify recipients carefully. Sends are instant and cannot be undone.
Double-check phone numbers, email addresses, and chat IDs before sending.
-
Never send to ambiguous recipients. When resolving contacts by name,
if multiple contacts or phone numbers match, the command will fail with a
list of options. Use an unambiguous identifier rather than guessing.
-
Load prose skills when drafting. Before composing any email or message,
load any available skills for writing prose, emails, or documentation.
-
Never create automation without explicit approval. Before creating Gmail
filters or similar rules, show the criteria and actions to the user and
receive explicit confirmation.
-
Limit bulk operations. Avoid sending to many recipients at once. Prefer
drafts for review.
Email workflow:
- Load any available prose/writing skills
- If replying to an infrequent contact: Research first (see "Research First" under Orchestration)
- Compose via subagent (see "Drafting with a Subagent") — quick replies excepted
- Show the original message first — Quote the full text (see "When to Show Full Content")
- Show the user: To, Subject, and full Body
- Ask: "Send this email?" and wait for explicit approval
- Call
jean-claude gmail draft send DRAFT_ID
- If replying, archive the original:
jean-claude gmail archive THREAD_ID
Session Start (Always Run First)
Every time this skill loads, run status with JSON output first:
jean-claude status --json
If Status Command Fails
If the status command fails entirely (not just showing services as disabled):
"uv: command not found" — The uv package manager isn't installed. Tell the
user:
jean-claude requires the uv package manager. Let me install it for you.
Then run:
curl -LsSf https://astral.sh/uv/install.sh | sh
After installation, restart the terminal or source the shell config
(source ~/.zshrc on macOS, source ~/.bashrc on Linux).
Other errors — The plugin may be misconfigured. Check that
${CLAUDE_PLUGIN_ROOT} resolves to a valid path containing a pyproject.toml.
Branching Based on Status
If setup_completed: false — This is a new user. Skip personalization
skills (they won't have any yet) and go straight to onboarding:
cat ${CLAUDE_PLUGIN_ROOT}/skills/jean-claude/ONBOARDING.md
Follow the onboarding guide to help set up services. After setup completes:
jean-claude config set setup_completed true
Then re-run status and continue to the setup_completed: true branch below.
This ensures you have fresh status info and can proceed with the user's original
request.
If setup_completed: true — Check for partial setup and load personalization:
-
Surface any auth warnings — If services show authenticated: false,
missing scopes, or errors, briefly mention it even if unrelated to the
user's request. Don't derail—just note the issue and offer to fix later:
"By the way, your Google Contacts permission is missing — I can't show
contact names in emails. Want me to help fix that after your request?"
-
Check for missing services — If the user asks for a service that shows
authenticated: false or enabled: false, guide them through just that
service's setup from ONBOARDING.md. After partial setup completes, continue
to step 3.
-
Load personalization skills — Check if user skills like managing-messages
exist (look at available skills for anything mentioning inbox, email, message,
or communication). If found, load them—user preferences override defaults.
-
Offer to create preferences — If no personalization skill was found in
step 3, offer to create one after completing the user's immediate request.
See PREFERENCES.md for the creation flow. Don't interrupt
the user's task—help them first, then offer.
-
Proceed with the user's request — Execute whatever task prompted loading
this skill (check inbox, send message, etc.).
Before Using Messaging (iMessage/WhatsApp/Signal)
Load the platform guide before using any messaging commands. Each platform
has different commands and options. Gmail is documented in this file, but
messaging platforms have separate guides:
cat ${CLAUDE_PLUGIN_ROOT}/skills/jean-claude/platforms/imessage.md
cat ${CLAUDE_PLUGIN_ROOT}/skills/jean-claude/platforms/whatsapp.md
cat ${CLAUDE_PLUGIN_ROOT}/skills/jean-claude/platforms/signal.md
Don't guess command syntax — each platform is different. iMessage and WhatsApp
have different flags and subcommands despite similar functionality.
Understanding the Status
For users with setup complete, interpret the status output to understand their
workflow. Run human-readable status if needed for counts:
jean-claude status
Gmail:
- 13 inbox, 11 unread → inbox zero person, wants to triage everything
- 2,847 inbox, 89 unread → not inbox zero, focus on recent/unread/starred
- 5 drafts → has pending drafts to review or send
Calendar:
- 3 today, 12 this week → busy schedule, may need help with conflicts
- 0 today → open day, good time for focused work
Reminders:
- 7 incomplete → has pending tasks, may want to review or complete them
Messaging:
- 54 unread across 12 WhatsApp chats → active messaging, may want summary
- 1,353 unread across 113 iMessage chats → backlog, focus on recent/important
Apple services (Contacts, iMessage, Reminders): These are disabled by default.
If enabled: false in status, enable with:
jean-claude config set enable_contacts true
jean-claude config set enable_imessage true
jean-claude config set enable_reminders true
Once enabled, status checks full permissions (may trigger macOS permission
dialogs on first run). If permission is missing, guide the user through
System Settings > Privacy & Security > Automation.
Refreshing State
Summaries become stale immediately. Once you present an inbox summary, that
snapshot is already potentially outdated. State changes constantly:
- New messages arrive
- Messages get read/sent from other devices or apps
- The user takes actions outside this conversation
- You took actions earlier in the conversation that you may not be tracking
Verify before making claims. When the user asks about current state — "did I
reply?", "is that still unread?", "how many are left?" — re-check rather than
relying on your memory of earlier summaries. Your memory is of what was true
when you last checked, not what's true now.
User: "Did I reply to the Acme email?"
Agent: recalls earlier summary where it wasn't replied to
"No, that thread is still waiting for your reply."
User: "Did I reply to the Acme email?"
Agent: searches for sent messages to Acme
"Yes — you replied today at 12:27pm following up on their question."
Re-fetch when:
- User asks about current counts or status
- User asks "did I..." or "is it still..."
- Presenting a summary after taking actions
- You need metadata (dates, IDs, recipients) — conversation summaries lose it,
so re-query the API rather than inferring from content
General principle: Verify claims from the source. Re-fetching is cheap;
wrong information is expensive.
jean-claude gmail inbox
jean-claude gmail inbox --since yesterday
jean-claude gmail search "in:sent to:someone@example.com" -n 5
jean-claude imessage messages --unread
jean-claude whatsapp messages --unread
Choosing between filtered and full inbox:
--since yesterday — Use for "what's new" or daily triage. Shows recent
arrivals only. After archiving these, there may still be older emails in inbox.
- No filter — Use when reporting inbox state ("inbox cleared", "X emails
left") or when the user wants to see everything, not just recent.
Defaults
User personalization skills override these defaults. If no personalization skill
exists, use these behaviors:
Email Defaults
- Fetch both read and unread messages (context helps)
- Present messages neutrally — don't assume priority
- No automatic archiving without user guidance
iMessage Defaults
- Prioritize known contacts over unknown senders
Response Drafting Defaults
- Load prose/writing skills before composing
- No assumed tone or style — ask if unclear
- Show full message for approval before sending
Working with Messages
Presenting Messages
When showing messages (inbox, unread, search results), group by category and use
group-letter numbering so the user can reference items individually
("archive A1", "reply to B2") or by group ("archive all of C", "archive B1-B3").
Group-letter numbering. Pick a small set of categories (typically 3–5) that
fit the messages at hand — common ones are Needs attention, Travel /
receipts, Newsletters, In progress. Label each group with a letter (A, B,
C, ...) and number items within the group starting at 1:
**Needs attention:**
A1: Flo critical alert — water shutoff at the main valve
A2: Zach Perret (yesterday) — Invite to dinner Thursday
**Travel & receipts:**
B1: Delta (today at 10:37 AM) — LAX → TUS trip details Apr 22
B2: Waymo (yesterday) — Ride receipts (4 messages)
**Newsletters:**
C1: The Economist (today) — Weekly edition
C2: The Browser (today) — Sunday Supplement
Use manual N: formatting, not markdown lists. Markdown numbered lists
auto-correct to be sequential — if you write "3. 4. 5. 7. 15. 16." the renderer
displays "3. 4. 5. 6. 7. 8." causing a mismatch between what you wrote and what
the user sees. The A1: / B2: form sidesteps the renderer entirely.
Keep items compact — no blank lines between them. Blank lines waste vertical
space and make the list harder to scan. Items within a group should be on
consecutive lines; one blank line separates groups.
Preserve identifiers through the session. After archiving A1 and A3, show
the remaining items as A2, A4, A5 — don't renumber. This gives items stable
identifiers across operations.
Always include dates conversationally. Check today's date before formatting:
date "+%Y-%m-%d %H:%M %Z"
Date formatting rules:
- < 1 hour ago: "35 min ago"
- Today (> 1 hour): "today at 9:15 AM" — not "3 hours ago"
- Yesterday: "yesterday at 2:30 PM"
- This week: "Thursday at 4:30 PM" (day name, not date)
- Beyond this week: "Dec 15" or "Nov 15 at 3pm" (if time matters)
Example (assuming today is Sunday, Dec 29):
**Needs attention:**
A1: Jordan Lee (Nov 15) — Forwarded: Fellowship nomination, asks for response by Jan 5
A2: Squarespace (yesterday at 9:15 AM) — Domain transfer rejected for example.com
**Receipts & confirmations:**
B1: DoorDash (35 min ago) — Your order from Superba
B2: GitHub (Friday at 4:30 PM) — PR merged: fix-auth-flow
**Newsletters:**
C1: Goodreads (today at 10:30 AM) — Book newsletter
Accuracy in Summaries
Never fabricate details not present in the data.
- Never invent names. If an email says "your child", say "your child"
- If a sender's relationship isn't stated, don't assume it
- If a time/date isn't specified, say so — don't guess
- Quote or paraphrase what's actually there
- Never use "likely", "probably", or "appears to" when describing message
content. If you don't know what a message says, read it — don't guess.
Read multi-message threads before summarizing. The inbox response only
contains metadata and the latest message's snippet. For threads with multiple
messages, read the thread (gmail thread THREAD_ID) to know what the other
messages actually say. Never infer thread content from the snippet alone.
Bad: "3-message thread — likely includes Effie's reply"
Good: reads thread first → "Kristin nominated Effie; Effie replied accepting
and asking about travel logistics; Kristin confirmed hotel is covered"
When uncertain, say so: "The email doesn't specify who the assessment is for."
Accurate Counts
Use the total_threads and total_unread fields from the inbox response.
The inbox command returns accurate counts from Gmail's label stats:
{"total_threads": 32, "total_unread": 28, "threads": [...]}
When reporting counts, use these fields — not the number of threads returned.
The -n flag limits how many threads are fetched, not how many exist.
Prefer --since over -n for complete results. If you need emails from
today, use --since today rather than -n 20. The -n flag returns the
N most recent threads but may miss older unread emails in the inbox.
The --since flag accepts human-readable dates like "yesterday", "3 days ago",
"last week", or explicit dates like "2026-01-21".
Filtered Results
When --since or --unread is used, the threads array is a subset of
the full inbox. The total_threads and total_unread fields still reflect the
full inbox, not the filtered results.
Report filtered results accurately:
- "6 threads from yesterday (32 total in inbox, 28 unread)"
- "Archived 6 threads from yesterday"
Never claim "inbox cleared" after archiving filtered results. If you
archived 6 threads from --since yesterday and total_threads was 32, there
are still 26 other threads in the inbox. To check true inbox state after
triaging recent emails, run jean-claude gmail inbox without filters.
Hallucinated details erode trust. The user can't distinguish fabrications from
real data.
When to Show Full Content
Show the full email text (not a summary) when:
- Drafting a reply — The user needs to see exactly what they're responding to
- User asks for a specific email — "read the email from X", "show me that message"
- User asks what they're replying to — "what's the original?", "what did they say?"
Summaries are appropriate when:
- Showing inbox/search results (the numbered list format with snippets)
- The user asks for a specific detail — "when is the meeting?", "did they confirm?"
- Triaging multiple messages — giving the user an overview to decide what to act on
The test: If the user might need to quote, reference, or respond to the exact
wording, show the full text. If they just need to understand the gist, summarize.
Presenting Individual Emails
When showing the full text of an email, include all relevant headers:
From: Sender Name <sender@example.com>
To: Recipient <recipient@example.com>
Date: Yesterday at 9:54 PM
Subject: Meeting follow-up
[email body]
Always include:
- From — Who sent it
- To — Who it was sent to (important for context, especially forwarded emails)
- Date — When it was sent (use conversational format per date rules above)
- Subject — The email subject
Include when present:
- CC — If others were copied
The To field helps the user understand context — was this sent directly to them,
to a group, or forwarded from somewhere else?
User: "Reply to Alex's email and say I can't make it"
Agent: reads email, immediately drafts reply
"Alex's email was about NY logistics. Draft reply:
Hi Alex,
Unfortunately I won't be able to join..."
User: "Reply to Alex's email and say I can't make it"