← Back to Skills Marketplace
cto1

Clawemail

by cto1 · GitHub ↗ · v1.0.1
cross-platform ⚠ suspicious
1745
Downloads
0
Stars
5
Active Installs
2
Versions
Install in OpenClaw
/install clawemail
Description
Google Workspace via ClawEmail.com service — Gmail, Drive, Docs, Sheets, Slides, Calendar, Forms. Use PROACTIVELY when the user asks to send email, create documents, manage files, schedule events, or work with any Google service.
README (SKILL.md)

Claw — Google Workspace for AI Agents

Use claw for Gmail, Drive, Docs, Sheets, Slides, Calendar, and Forms via your @clawemail.com account.

Setup

  1. Save your ClawEmail credentials JSON to ~/.config/clawemail/credentials.json
  2. Set the environment variable: export CLAWEMAIL_CREDENTIALS=~/.config/clawemail/credentials.json

Get credentials at https://clawemail.com — sign up, then visit /connect/YOUR_PREFIX to authorize OAuth.

Getting an Access Token

All API calls need a Bearer token. Use the helper script to refresh and cache it:

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)

The script caches tokens for 50 minutes. Always assign to TOKEN before making API calls.


Gmail

Search emails

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://gmail.googleapis.com/gmail/v1/users/me/messages?q=newer_than:7d&maxResults=10" | python3 -m json.tool

Common query operators: from:, to:, subject:, newer_than:, older_than:, is:unread, has:attachment, label:, in:inbox.

Read a message

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://gmail.googleapis.com/gmail/v1/users/me/messages/MESSAGE_ID?format=full" | python3 -m json.tool

For plain text body only, use format=minimal and decode the payload. For readable output:

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://gmail.googleapis.com/gmail/v1/users/me/messages/MESSAGE_ID?format=full" \
  | python3 -c "
import json,sys,base64
m=json.load(sys.stdin)
hdrs={h['name']:h['value'] for h in m['payload']['headers']}
print(f\"From: {hdrs.get('From','')}\
To: {hdrs.get('To','')}\
Subject: {hdrs.get('Subject','')}\
Date: {hdrs.get('Date','')}\
\")
def get_body(part):
    if part.get('body',{}).get('data'):
        return base64.urlsafe_b64decode(part['body']['data']).decode('utf-8','replace')
    for p in part.get('parts',[]):
        if p['mimeType']=='text/plain': return get_body(p)
    for p in part.get('parts',[]):
        b=get_body(p)
        if b: return b
    return ''
print(get_body(m['payload']))
"

Send an email

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
python3 -c "
import base64,json
raw = base64.urlsafe_b64encode(
    b'To: [email protected]\r\
Subject: Hello\r\
Content-Type: text/plain; charset=utf-8\r\
\r\
Message body here'
).decode()
print(json.dumps({'raw': raw}))
" | curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @- \
  "https://gmail.googleapis.com/gmail/v1/users/me/messages/send"

For HTML emails, replace Content-Type: text/plain with Content-Type: text/html and use HTML in the body.

Reply to a message

Same as send, but add In-Reply-To: and References: headers from the original message, and include threadId in the JSON body:

python3 -c "
import base64,json
raw = base64.urlsafe_b64encode(
    b'To: [email protected]\r\
Subject: Re: Original Subject\r\
In-Reply-To: \x3Coriginal-message-id>\r\
References: \x3Coriginal-message-id>\r\
Content-Type: text/plain; charset=utf-8\r\
\r\
Reply body'
).decode()
print(json.dumps({'raw': raw, 'threadId': 'THREAD_ID'}))
" | curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @- \
  "https://gmail.googleapis.com/gmail/v1/users/me/messages/send"

List labels

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://gmail.googleapis.com/gmail/v1/users/me/labels" | python3 -m json.tool

Add/remove labels

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"addLabelIds":["LABEL_ID"],"removeLabelIds":["INBOX"]}' \
  "https://gmail.googleapis.com/gmail/v1/users/me/messages/MESSAGE_ID/modify"

Google Drive

List files

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/drive/v3/files?pageSize=20&fields=files(id,name,mimeType,modifiedTime,size)&orderBy=modifiedTime desc" | python3 -m json.tool

Search files

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/drive/v3/files?q=name+contains+'report'&fields=files(id,name,mimeType,modifiedTime)" | python3 -m json.tool

Query operators: name contains 'term', mimeType='application/vnd.google-apps.document', 'FOLDER_ID' in parents, trashed=false, modifiedTime > '2025-01-01'.

Common MIME types:

  • Document: application/vnd.google-apps.document
  • Spreadsheet: application/vnd.google-apps.spreadsheet
  • Presentation: application/vnd.google-apps.presentation
  • Folder: application/vnd.google-apps.folder
  • Form: application/vnd.google-apps.form

Create a folder

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"My Folder","mimeType":"application/vnd.google-apps.folder"}' \
  "https://www.googleapis.com/drive/v3/files?fields=id,name" | python3 -m json.tool

Upload a file

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -F "metadata={\"name\":\"report.pdf\"};type=application/json" \
  -F "file=@/path/to/report.pdf;type=application/pdf" \
  "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name" | python3 -m json.tool

Download a file

For Google Docs/Sheets/Slides (export):

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/drive/v3/files/FILE_ID/export?mimeType=application/pdf" -o output.pdf

Export formats: text/plain, text/html, application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document (docx), text/csv (sheets).

For binary files (download):

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/drive/v3/files/FILE_ID?alt=media" -o output.file

Share a file

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"role":"writer","type":"user","emailAddress":"[email protected]"}' \
  "https://www.googleapis.com/drive/v3/files/FILE_ID/permissions"

Roles: reader, commenter, writer, owner. Types: user, group, domain, anyone.

Delete a file

curl -s -X DELETE -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/drive/v3/files/FILE_ID"

Google Docs

Create a document

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"My Document"}' \
  "https://docs.googleapis.com/v1/documents" | python3 -m json.tool

Read a document

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://docs.googleapis.com/v1/documents/DOCUMENT_ID" | python3 -m json.tool

For plain text extraction:

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://docs.googleapis.com/v1/documents/DOCUMENT_ID" \
  | python3 -c "
import json,sys
doc=json.load(sys.stdin)
text=''
for el in doc.get('body',{}).get('content',[]):
    for p in el.get('paragraph',{}).get('elements',[]):
        text+=p.get('textRun',{}).get('content','')
print(text)
"

Append text to a document

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests":[{"insertText":{"location":{"index":1},"text":"Hello, world!\
"}}]}' \
  "https://docs.googleapis.com/v1/documents/DOCUMENT_ID:batchUpdate"

Replace text in a document

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests":[{"replaceAllText":{"containsText":{"text":"OLD_TEXT","matchCase":true},"replaceText":"NEW_TEXT"}}]}' \
  "https://docs.googleapis.com/v1/documents/DOCUMENT_ID:batchUpdate"

Insert a heading

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests":[{"insertText":{"location":{"index":1},"text":"My Heading\
"}},{"updateParagraphStyle":{"range":{"startIndex":1,"endIndex":12},"paragraphStyle":{"namedStyleType":"HEADING_1"},"fields":"namedStyleType"}}]}' \
  "https://docs.googleapis.com/v1/documents/DOCUMENT_ID:batchUpdate"

Heading styles: HEADING_1 through HEADING_6, TITLE, SUBTITLE, NORMAL_TEXT.


Google Sheets

Create a spreadsheet

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"properties":{"title":"My Spreadsheet"}}' \
  "https://sheets.googleapis.com/v4/spreadsheets" | python3 -m json.tool

Read cells

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID/values/Sheet1!A1:D10" | python3 -m json.tool

Write cells

curl -s -X PUT -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"values":[["Name","Age","City"],["Alice","30","NYC"],["Bob","25","LA"]]}' \
  "https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID/values/Sheet1!A1:C3?valueInputOption=USER_ENTERED" | python3 -m json.tool

Append rows

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"values":[["Charlie","35","Chicago"]]}' \
  "https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID/values/Sheet1!A:C:append?valueInputOption=USER_ENTERED&insertDataOption=INSERT_ROWS" | python3 -m json.tool

Clear a range

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  "https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID/values/Sheet1!A1:D10:clear"

Get spreadsheet metadata

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID?fields=properties.title,sheets.properties" | python3 -m json.tool

Google Slides

Create a presentation

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"My Presentation"}' \
  "https://slides.googleapis.com/v1/presentations" | python3 -m json.tool

Get presentation info

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://slides.googleapis.com/v1/presentations/PRESENTATION_ID" | python3 -m json.tool

Add a new slide

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests":[{"createSlide":{"slideLayoutReference":{"predefinedLayout":"TITLE_AND_BODY"}}}]}' \
  "https://slides.googleapis.com/v1/presentations/PRESENTATION_ID:batchUpdate" | python3 -m json.tool

Layouts: BLANK, TITLE, TITLE_AND_BODY, TITLE_AND_TWO_COLUMNS, TITLE_ONLY, SECTION_HEADER, ONE_COLUMN_TEXT, MAIN_POINT, BIG_NUMBER.

Add text to a slide

First get the slide's page object IDs, then insert text into a placeholder:

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests":[{"insertText":{"objectId":"PLACEHOLDER_OBJECT_ID","text":"Hello from ClawEmail!","insertionIndex":0}}]}' \
  "https://slides.googleapis.com/v1/presentations/PRESENTATION_ID:batchUpdate"

Add an image to a slide

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests":[{"createImage":{"url":"https://example.com/image.png","elementProperties":{"pageObjectId":"SLIDE_ID","size":{"width":{"magnitude":3000000,"unit":"EMU"},"height":{"magnitude":2000000,"unit":"EMU"}},"transform":{"scaleX":1,"scaleY":1,"translateX":1000000,"translateY":1500000,"unit":"EMU"}}}}]}' \
  "https://slides.googleapis.com/v1/presentations/PRESENTATION_ID:batchUpdate"

Google Calendar

List upcoming events

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=$(date -u +%Y-%m-%dT%H:%M:%SZ)&maxResults=10&singleEvents=true&orderBy=startTime" | python3 -m json.tool

Get events in a date range

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=2025-03-01T00:00:00Z&timeMax=2025-03-31T23:59:59Z&singleEvents=true&orderBy=startTime" | python3 -m json.tool

Create an event

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "summary": "Team Meeting",
    "description": "Weekly standup",
    "start": {"dateTime": "2025-03-15T10:00:00-05:00", "timeZone": "America/New_York"},
    "end": {"dateTime": "2025-03-15T11:00:00-05:00", "timeZone": "America/New_York"},
    "attendees": [{"email": "[email protected]"}]
  }' \
  "https://www.googleapis.com/calendar/v3/calendars/primary/events" | python3 -m json.tool

Update an event

curl -s -X PATCH -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"summary":"Updated Meeting Title","location":"Conference Room A"}' \
  "https://www.googleapis.com/calendar/v3/calendars/primary/events/EVENT_ID" | python3 -m json.tool

Delete an event

curl -s -X DELETE -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/calendar/v3/calendars/primary/events/EVENT_ID"

List calendars

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://www.googleapis.com/calendar/v3/users/me/calendarList" | python3 -m json.tool

Google Forms

Create a form

TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"info":{"title":"Feedback Form"}}' \
  "https://forms.googleapis.com/v1/forms" | python3 -m json.tool

Add questions

curl -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests":[{"createItem":{"item":{"title":"How would you rate this?","questionItem":{"question":{"required":true,"scaleQuestion":{"low":1,"high":5,"lowLabel":"Poor","highLabel":"Excellent"}}}},"location":{"index":0}}}]}' \
  "https://forms.googleapis.com/v1/forms/FORM_ID:batchUpdate"

Get form responses

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://forms.googleapis.com/v1/forms/FORM_ID/responses" | python3 -m json.tool

Tips

  • Always refresh token first: Start every sequence with TOKEN=$(~/.openclaw/skills/clawemail/scripts/token.sh)
  • JSON output: Pipe through python3 -m json.tool for readable output, or | python3 -c "import json,sys;..." for extraction
  • Pagination: Most list endpoints return nextPageToken. Pass it as ?pageToken=TOKEN for the next page
  • Batch operations: Docs, Sheets, and Slides support batchUpdate — send multiple operations in one request
  • Error 401: Token expired. Re-run token.sh to refresh
  • Error 403: Scope not authorized. The ClawEmail OAuth includes Gmail, Drive, Docs, Sheets, Slides, Calendar, and Forms scopes
  • Rate limits: Google APIs have per-user rate limits. Add brief delays between rapid successive calls
  • File IDs: Google Docs/Sheets/Slides URLs contain the file ID: https://docs.google.com/document/d/FILE_ID/edit

When to Use

  • User asks to send, read, or search email
  • User wants to create or edit documents, spreadsheets, or presentations
  • User needs to manage files in Google Drive
  • User wants to schedule or check calendar events
  • User asks to create forms or review form responses
  • Any task involving Google Workspace services
Usage Guidance
This skill is coherent with its description, but you should treat the CLAWEMAIL_CREDENTIALS file as highly sensitive: it contains a client_secret and refresh_token that can be used to access your Google account. Only install/use this skill if you trust the issuer (ClawEmail.com). Before installing: (1) inspect the credentials JSON and the included scripts (token.sh) — the script is short and only exchanges the refresh token at https://oauth2.googleapis.com/token and caches the access token; (2) ensure the credentials file and cache files have restrictive filesystem permissions so others on the machine cannot read them; (3) consider requesting least-privilege OAuth scopes from the provider instead of full account scopes; (4) be aware the skill will be used proactively for many Google actions if you allow autonomous invocation — only enable that if you want the agent to act on your Gmail/Drive/Calendar/etc.; (5) if you ever suspect misuse, revoke the refresh_token from your Google account (or delete the OAuth client) to cut off access.
Capability Analysis
Type: OpenClaw Skill Name: clawemail Version: 1.0.1 The skill is classified as suspicious due to the extensive use of `curl` and `python3 -c` commands in `SKILL.md` with placeholders (e.g., `MESSAGE_ID`, `FILE_ID`, email content). These commands, if populated by the AI agent with unsanitized user input, present a significant risk of shell injection or command injection. While the `scripts/token.sh` handles sensitive OAuth credentials and performs network requests to legitimate Google endpoints, the overall design exposes a broad attack surface for prompt injection against the agent if input sanitization is not rigorously applied by the agent itself.
Capability Assessment
Purpose & Capability
The name/description promise (Google Workspace access via a ClawEmail account) lines up with the actual behavior: SKILL.md issues curl calls to gmail.googleapis.com, drive.googleapis.com, etc. The only required credential (CLAWEMAIL_CREDENTIALS) is exactly what an OAuth-based Google integration would need.
Instruction Scope
Runtime instructions are focused on storing a credentials JSON, using the included token.sh to exchange its refresh_token for a Google access token, and calling Google APIs. The instructions reference only the credentials file (~/.config/clawemail/credentials.json), the token cache (~/.cache/clawemail/access_token), and Google endpoints. Note: the skill tells the agent to 'use PROACTIVELY' for any Google-related user requests — that broad invocation policy is intentional but means the skill will be used frequently for many Google operations if allowed.
Install Mechanism
This is instruction-only with a small helper script included. No network installs, package downloads, or archive extraction occur. The helper script uses curl and python3 (already assumed available in SKILL.md examples), which is proportional to the task.
Credentials
Only one env var (CLAWEMAIL_CREDENTIALS) is required, which is appropriate. However that credentials JSON contains client_id, client_secret, and refresh_token — highly sensitive data that grants broad access to the user's Google Workspace. The credential requirement is justified by the described functionality but carries significant privilege and must be protected.
Persistence & Privilege
The skill is not always-enabled and does not request system-wide privileges. It caches the access token under the user's XDG cache directory (~/.cache/clawemail/access_token) and does not modify other skills or system settings.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install clawemail
  3. After installation, invoke the skill by name or use /clawemail
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.1
- Renamed skill from "claw" to "clawemail" throughout documentation. - Updated all example file paths from `claw` to `clawemail` for setup and script usage. - Revised description to clarify this skill uses the ClawEmail.com service. - No functional changes to API usage examples or core documentation content.
v1.0.0
Google Workspace API for AI agents — Gmail, Drive, Docs, Sheets, Slides, Calendar, Forms with OAuth token refresh.
Metadata
Slug clawemail
Version 1.0.1
License
All-time Installs 7
Active Installs 5
Total Versions 2
Frequently Asked Questions

What is Clawemail?

Google Workspace via ClawEmail.com service — Gmail, Drive, Docs, Sheets, Slides, Calendar, Forms. Use PROACTIVELY when the user asks to send email, create documents, manage files, schedule events, or work with any Google service. It is an AI Agent Skill for Claude Code / OpenClaw, with 1745 downloads so far.

How do I install Clawemail?

Run "/install clawemail" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Clawemail free?

Yes, Clawemail is completely free (open-source). You can download, install and use it at no cost.

Which platforms does Clawemail support?

Clawemail is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Clawemail?

It is built and maintained by cto1 (@cto1); the current version is v1.0.1.

💬 Comments