| name | gws-gmail |
| version | 1.2.0 |
| description | Google Gmail CLI operations via gws. Use when users need to list emails, read messages, send email, manage labels, drafts, attachments, batch operations, or trash messages. Triggers: gmail, email, inbox, send email, mail, labels, archive, trash, drafts, attachments. |
| metadata | {"short-description":"Google Gmail CLI operations","compatibility":"claude-code, codex-cli"} |
Google Gmail (gws gmail)
gws gmail provides CLI access to Gmail with structured JSON output.
Disclaimer: gws is not the official Google CLI. This is an independent, open-source project not endorsed by or affiliated with Google.
Dependency Check
Before executing any gws command, verify the CLI is installed:
gws version
If not found, install: go install github.com/omriariav/workspace-cli/cmd/gws@latest
Authentication
Requires OAuth2 credentials. Run gws auth status to check.
If not authenticated: gws auth login (opens browser for OAuth consent).
For initial setup, see the gws-auth skill.
Quick Command Reference
| Task | Command |
|---|
| List recent emails | gws gmail list |
| List with labels | gws gmail list --include-labels |
| List all matches | gws gmail list --query "label:work" --all |
| List unread emails | gws gmail list --query "is:unread" |
| Search emails | gws gmail list --query "from:user@example.com" |
| Read a message | gws gmail read <message-id> |
| Extract HTML links | gws gmail links <message-id> |
| Read full thread | gws gmail thread <thread-id> |
| Send an email | gws gmail send --to user@example.com --subject "Hi" --body "Hello" |
| List all labels | gws gmail labels |
| Get label details | gws gmail label-info --id Label_1 |
| Create a label | gws gmail create-label --name "MyLabel" |
| Update a label | gws gmail update-label --id Label_1 --name "NewName" |
| Delete a label | gws gmail delete-label --id Label_1 |
| Add labels | gws gmail label <message-id> --add "STARRED" |
| Remove labels | gws gmail label <message-id> --remove "UNREAD" |
| Batch modify labels | gws gmail batch-modify --ids "msg1,msg2" --add-labels "STARRED" |
| Archive a message | gws gmail archive <message-id> |
| Archive a thread | gws gmail archive-thread <thread-id> |
| Trash a message | gws gmail trash <message-id> |
| Untrash a message | gws gmail untrash <message-id> |
| Delete a message | gws gmail delete <message-id> |
| Batch delete | gws gmail batch-delete --ids "msg1,msg2" |
| Trash a thread | gws gmail trash-thread <thread-id> |
| Untrash a thread | gws gmail untrash-thread <thread-id> |
| Delete a thread | gws gmail delete-thread <thread-id> |
| Reply to a message | gws gmail reply <message-id> --body "Thanks!" |
| Reply to all | gws gmail reply <message-id> --body "Got it" --all |
| Forward a message | gws gmail forward <message-id> --to "user@example.com" |
| Extract event ID | gws gmail event-id <message-id> |
| List drafts | gws gmail drafts |
| Get a draft | gws gmail draft --id <draft-id> |
| Create a draft | gws gmail create-draft --to user@example.com --subject "Hi" --body "Hello" |
| Update a draft | gws gmail update-draft --id <draft-id> --body "Updated body" |
| Send a draft | gws gmail send-draft --id <draft-id> |
| Delete a draft | gws gmail delete-draft --id <draft-id> |
| Download attachment | gws gmail attachment --message-id <msg-id> --id <att-id> --output file.pdf |
Detailed Usage
list โ List recent messages/threads
gws gmail list [flags]
Lists recent email threads from your inbox. Each result includes:
thread_id โ Thread ID (use with gws gmail thread)
message_id โ Latest message ID (use with read, label, archive, trash)
message_count โ Number of messages in the thread
Flags:
--max int โ Maximum number of results (default 10, use --all for unlimited)
--all โ Fetch all matching results (may take time for large result sets)
--query string โ Gmail search query (e.g., is:unread, from:someone@example.com)
--include-labels โ Include Gmail label IDs in the output for each thread
Examples:
gws gmail list --max 5
gws gmail list --query "is:unread"
gws gmail list --query "from:boss@company.com subject:urgent"
gws gmail list --query "after:2024/01/01 has:attachment"
gws gmail list --include-labels
gws gmail list --query "label:work" --all
thread โ Read a full thread
gws gmail thread <thread-id>
Reads and displays all messages in a Gmail thread (conversation). Use the thread_id from gws gmail list output. Returns all messages with headers, body, labels, and attachments (when present) โ each entry exposes filename, mime_type, size, attachment_id, and part_id.
read โ Read a message
gws gmail read <message-id>
Reads and displays the content of a specific email message. Use the message_id from gws gmail list output. When the message has attachments, the response includes an attachments array. Each entry has filename, mime_type, size, attachment_id, and part_id; pass attachment_id to gws gmail attachment --id <id> to download.
ATT_ID=$(gws gmail read <msg-id> --format json | jq -r '.attachments[0].attachment_id')
gws gmail attachment --message-id <msg-id> --id "$ATT_ID" --output file.pdf
send โ Send an email
gws gmail send --to <email> --subject <subject> --body <body> [flags]
Flags:
--to string โ Recipient email address (required)
--subject string โ Email subject (required)
--body string โ Email body (required)
--cc string โ CC recipients (comma-separated)
--bcc string โ BCC recipients (comma-separated)
--attachment string โ File path to attach (repeatable)
Examples:
gws gmail send --to user@example.com --subject "Meeting" --body "Let's meet at 3pm"
gws gmail send --to user@example.com --cc team@example.com --subject "Update" --body "Status update"
gws gmail send --to user@example.com --subject "Report" --body "See attached" --attachment /tmp/report.pdf
gws gmail send --to user@example.com --subject "Files" --body "Multiple" --attachment /tmp/a.pdf --attachment /tmp/b.png
labels โ List all labels
gws gmail labels
Lists all Gmail labels in the account, including system labels (INBOX, SENT, etc.) and user-created labels.
label โ Add or remove labels
gws gmail label <message-id> [flags]
Flags:
--add string โ Label names to add (comma-separated)
--remove string โ Label names to remove (comma-separated)
Use gws gmail labels to see available label names.
Examples:
gws gmail label 18abc123 --add "STARRED"
gws gmail label 18abc123 --add "ActionNeeded,IMPORTANT" --remove "INBOX"
gws gmail label 18abc123 --remove "UNREAD"
archive โ Archive a message
gws gmail archive <message-id>
Archives a Gmail message by removing the INBOX label. The message remains accessible via search and labels.
archive-thread โ Archive all messages in a thread
gws gmail archive-thread <thread-id>
Archives all messages in a Gmail thread by removing the INBOX label and marking all messages as read. Use the thread_id from gws gmail list output. More efficient than archiving individual messages for multi-message threads.
trash โ Trash a message
gws gmail trash <message-id>
Moves a Gmail message to the trash. Messages in trash are permanently deleted after 30 days.
reply โ Reply to a message
gws gmail reply <message-id> --body <body> [flags]
Replies to an existing email message within its thread. Automatically sets threading headers (In-Reply-To, References), thread ID, and Re: subject prefix.
Flags:
--body string โ Reply body (required)
--cc string โ CC recipients (comma-separated)
--bcc string โ BCC recipients (comma-separated)
--all โ Reply to all recipients
Examples:
gws gmail reply 18abc123 --body "Thanks, got it!"
gws gmail reply 18abc123 --body "Adding someone" --cc extra@example.com
gws gmail reply 18abc123 --body "Sounds good" --all
forward โ Forward a message
gws gmail forward <message-id> --to <recipients> [flags]
Forwards an existing email message to new recipients. Preserves the original message content and attachments. Adds a "Fwd:" prefix to the subject.
Flags:
--to string โ Recipient email addresses (comma-separated, required)
--body string โ Optional note above the forwarded content
--cc string โ CC recipients (comma-separated)
--bcc string โ BCC recipients (comma-separated)
Examples:
gws gmail forward 18abc123 --to "user@example.com"
gws gmail forward 18abc123 --to "user1@example.com,user2@example.com" --body "FYI"
gws gmail forward 18abc123 --to "user@example.com" --cc "manager@example.com"
event-id โ Extract calendar event ID from an invite email
gws gmail event-id <message-id>
Extracts the Google Calendar event ID from a calendar invite email by parsing the eid parameter from Google Calendar URLs in the email body and base64 decoding it.
Examples:
gws gmail event-id 19c041be3fcd1b79
gws gmail event-id 19c041be3fcd1b79 | jq -r '.event_id' | xargs -I{} gws calendar rsvp {} --response accepted
Output Modes
gws gmail list --format json
gws gmail list --format yaml
gws gmail list --format text
untrash โ Remove a message from trash
gws gmail untrash <message-id>
Removes a Gmail message from the trash, restoring it to its previous location.
delete โ Permanently delete a message
gws gmail delete <message-id>
Permanently deletes a Gmail message. This action cannot be undone.
batch-modify โ Modify labels on multiple messages
gws gmail batch-modify --ids <comma-separated-ids> [flags]
Flags:
--ids string โ Comma-separated message IDs (required)
--add-labels string โ Label names to add (comma-separated)
--remove-labels string โ Label names to remove (comma-separated)
Examples:
gws gmail batch-modify --ids "msg1,msg2,msg3" --add-labels "STARRED"
gws gmail batch-modify --ids "msg1,msg2" --remove-labels "INBOX,UNREAD"
gws gmail batch-modify --ids "msg1,msg2" --add-labels "ActionNeeded" --remove-labels "INBOX"
batch-delete โ Permanently delete multiple messages
gws gmail batch-delete --ids <comma-separated-ids>
Flags:
--ids string โ Comma-separated message IDs (required)
trash-thread โ Move a thread to trash
gws gmail trash-thread <thread-id>
Moves all messages in a Gmail thread to the trash.
untrash-thread โ Remove a thread from trash
gws gmail untrash-thread <thread-id>
Removes all messages in a Gmail thread from the trash.
delete-thread โ Permanently delete a thread
gws gmail delete-thread <thread-id>
Permanently deletes all messages in a Gmail thread. This action cannot be undone.
label-info โ Get label details
gws gmail label-info --id <label-id>
Flags:
--id string โ Label ID (required)
Returns detailed information including message/thread counts and visibility settings.
create-label โ Create a new label
gws gmail create-label --name <label-name> [flags]
Flags:
--name string โ Label name (required)
--visibility string โ Message visibility: labelShow, labelShowIfUnread, labelHide
--list-visibility string โ Label list visibility: labelShow, labelHide
Examples:
gws gmail create-label --name "ProjectX"
gws gmail create-label --name "Archive/2024" --visibility labelHide
update-label โ Update a label
gws gmail update-label --id <label-id> [flags]
Flags:
--id string โ Label ID (required)
--name string โ New label name
--visibility string โ Message visibility: labelShow, labelShowIfUnread, labelHide
--list-visibility string โ Label list visibility: labelShow, labelHide
delete-label โ Delete a label
gws gmail delete-label --id <label-id>
Flags:
--id string โ Label ID (required)
Permanently deletes a Gmail label. Messages with this label are not deleted.
drafts โ List drafts
gws gmail drafts [flags]
Flags:
--max int โ Maximum number of results (default 10)
--query string โ Gmail search query
draft โ Get a draft by ID
gws gmail draft --id <draft-id>
Flags:
--id string โ Draft ID (required)
Returns full draft content including headers and body.
create-draft โ Create a draft
gws gmail create-draft --to <email> [flags]
Flags:
--to string โ Recipient email address (required)
--subject string โ Email subject
--body string โ Email body
--cc string โ CC recipients (comma-separated)
--bcc string โ BCC recipients (comma-separated)
--thread-id string โ Thread ID for reply draft
--attachment string โ File path to attach (repeatable)
Examples:
gws gmail create-draft --to user@example.com --subject "Draft" --body "Work in progress"
gws gmail create-draft --to user@example.com --subject "Re: Topic" --thread-id thread123
gws gmail create-draft --to user@example.com --subject "Draft" --body "See attached" --attachment /tmp/file.pdf
update-draft โ Update a draft
gws gmail update-draft --id <draft-id> [flags]
Flags:
--id string โ Draft ID (required)
--to string โ Recipient email address
--subject string โ Email subject
--body string โ Email body
--cc string โ CC recipients (comma-separated)
--bcc string โ BCC recipients (comma-separated)
send-draft โ Send an existing draft
gws gmail send-draft --id <draft-id>
Flags:
--id string โ Draft ID (required)
delete-draft โ Delete a draft
gws gmail delete-draft --id <draft-id>
Flags:
--id string โ Draft ID (required)
attachment โ Download an attachment
gws gmail attachment --message-id <msg-id> --id <attachment-id> --output <file-path>
Flags:
--message-id string โ Message ID (required)
--id string โ Attachment ID (required)
--output string โ Output file path (required)
Discover the --id value from the attachments array on gws gmail read or gws gmail thread output. Each entry includes filename, mime_type, size, attachment_id, and part_id.
Examples:
gws gmail attachment --message-id 18abc123 --id ANGjdJ9x --output report.pdf
ATT_ID=$(gws gmail read 18abc123 --format json | jq -r '.attachments[0].attachment_id')
gws gmail attachment --message-id 18abc123 --id "$ATT_ID" --output report.pdf
links โ Extract HTML anchor links from a message
gws gmail links <message-id>
Fetches the full message and extracts <a href> anchors from text/html MIME parts. Useful when a message's plain text body contains visible labels like "Notes by Gemini" or "Open meeting notes" but the underlying URL is only present in the HTML part.
Returns message_id and a links array in document order. Each entry has:
text โ Visible anchor text
href โ Full URL
mime_part โ Always "text/html"
google_docs_id โ (Google Docs only) document ID parsed from the URL path
query โ (Google Docs only) raw query string, e.g. usp=sharing
fragment โ (Google Docs only) URL fragment including #, e.g. #heading=h.abc
tab_id โ (Google Docs only) tab ID from the tab query parameter, e.g. t.0
All non-empty href anchors are returned, including mailto: links. Google Docs metadata fields are only present when applicable.
Examples:
gws gmail links 18abc123 --format json
DOC_URL=$(gws gmail links 18abc123 --format json | jq -r '.links[] | select(.text == "Notes by Gemini") | .href')
DOC_ID=$(gws gmail links 18abc123 --format json | jq -r '.links[] | select(.google_docs_id) | .google_docs_id' | head -1)
gws docs read "$DOC_ID"
Tips for AI Agents
- Always use
--format json (the default) for programmatic parsing
- Use
gws gmail list to get IDs: message_id for read/label/archive/trash, thread_id for thread
- Use
gws gmail thread <thread-id> to view full conversations with all messages
- Gmail search query syntax supports operators like
is:, from:, to:, subject:, after:, before:, has:, label:
- When managing labels, run
gws gmail labels first to see available label names and IDs
- Archive is a shortcut for
gws gmail label <id> --remove "INBOX"
- Use
gws gmail archive-thread <thread-id> to archive all messages in a conversation at once (archives + marks read)
- To mark as read:
gws gmail label <id> --remove "UNREAD"
- To star a message:
gws gmail label <id> --add "STARRED"
- Use
--include-labels with list to see which Gmail labels are applied to each thread
- Use
--all with list to fetch every matching result (bypasses the default 10 limit)
- Use
--quiet on any command to suppress JSON output (useful for scripted archive/label actions)