Skip to content

Repository files navigation

gws

Unified CLI for Google Workspace — Gmail, Calendar, Drive, Docs, Sheets, Slides, Tasks, and more from your terminal.

CI License: MIT Go Version

gws gives developers and AI agents a structured, token-efficient interface to 10+ Google Workspace services. Every command returns consistent JSON (or YAML or human-readable text), making it ideal for scripting, automation, and agent toolchains.

Built for AI & automation: Drop gws into Claude Code, Codex, or shell scripts and they inherit structured output, predictable flags, and safe defaults — no wrapper code required.

Features

  • 10+ Google services — Gmail, Calendar, Drive, Docs, Sheets, Slides, Tasks, Chat, Forms, Contacts, Custom Search.
  • Scriptable output--format json (default), --format yaml, --format text for human-readable tables, or --quiet to suppress output.
  • OAuth2 + PKCE — Secure browser-based auth with automatic token refresh and 0600 file permissions.
  • Single auth flow — Authenticate once to access all services; scopes based on --services flag, config, or all by default.
  • Lazy clients — Service clients are initialized on-demand with mutex protection.

Installation

Go Install

go install github.com/omriariav/workspace-cli/cmd/gws@latest

From Source

git clone https://github.com/omriariav/workspace-cli.git
cd workspace-cli
make build    # produces ./bin/gws
./bin/gws --help

Prerequisites

  1. A Google Cloud Project with an OAuth 2.0 Client ID (Desktop type).
  2. Enable the APIs you need in the API Library:
    • Gmail, Calendar, Drive, Docs, Sheets, Slides, Tasks (core)
    • Chat, Forms (optional — require additional setup)

Quickstart

1. Configure credentials

export GWS_CLIENT_ID="your-client-id.apps.googleusercontent.com"
export GWS_CLIENT_SECRET="your-client-secret"

Or create ~/.config/gws/config.yaml:

client_id: "your-client-id.apps.googleusercontent.com"
client_secret: "your-client-secret"

2. Authenticate

gws auth login          # Opens browser for OAuth consent
gws auth status         # Verify: shows email and token expiry

3. Use it

gws gmail list --max 5 --query "is:unread"
gws calendar events --days 7
gws drive search "quarterly report" --max 10
gws docs read <document-id>
gws sheets read <spreadsheet-id> "Sheet1!A1:D10"
gws tasks lists

Add --format text for human-readable output, or --format yaml for YAML.

Commands

Auth

Command Description
gws auth login Authenticate via OAuth2 + PKCE
gws auth status Show current auth status and email
gws auth logout Remove stored credentials

Hooks

Command Description
gws hooks status Show safe effective hook state, auth readiness, source gaps, and duplicate time injectors; never prints cached context or tokens
gws hooks enable --time --workspace --scope user Preview enabling one or both opt-in providers; add --apply only after approval
gws hooks configure Preview preferences; --enabled, --time, and --workspace are user-scope-only consent controls, while workspace scope is limited to source, timezone, and TTL preferences
gws hooks test --event UserPromptSubmit Run an on-demand, read-only health check with metadata-only output
gws hooks disable --scope user Preview disabling hook fetching without changing normal GWS commands or authentication

Gmail

Command Description
gws gmail list List threads with thread_id and message_id (--max, --query, --all, --include-labels, --raw, --params). Under --raw switches to users.messages.list shape.
gws gmail read <id> Read message body and headers
gws gmail thread [id] Read full thread conversation (--raw, --params; id may be supplied via --params id)
gws gmail send Send email (--to, --subject, --body, --cc, --bcc, --thread-id, --reply-to-message-id, --attachment)
gws gmail reply <id> Reply to message (--body, --cc, --bcc, --all)
gws gmail forward <id> Forward message (--to, --body, --cc, --bcc)
gws gmail event-id <id> Extract calendar event ID from invite email
gws gmail labels List all labels
gws gmail label <id> Add/remove labels (--add, --remove)
gws gmail archive <id> Archive message (remove from inbox)
gws gmail archive-thread <id> Archive all messages in thread (archives + marks read)
gws gmail trash <id> Move message to trash
gws gmail untrash <id> Remove message from trash
gws gmail delete <id> Permanently delete message
gws gmail batch-modify Modify labels on multiple messages (--ids, --add-labels, --remove-labels)
gws gmail batch-delete Permanently delete multiple messages (--ids)
gws gmail trash-thread <id> Move thread to trash
gws gmail untrash-thread <id> Remove thread from trash
gws gmail delete-thread <id> Permanently delete thread
gws gmail label-info <id> Get label details
gws gmail create-label Create label (--name, --visibility, --list-visibility)
gws gmail update-label Update label (--id, --name, --visibility, --list-visibility)
gws gmail delete-label <id> Delete a label
gws gmail drafts List drafts (--max, --query)
gws gmail draft <id> Get draft by ID
gws gmail create-draft Create draft (--to, --subject, --body, --cc, --bcc, --attachment)
gws gmail update-draft Update draft (--id, --to, --subject, --body)
gws gmail send-draft <id> Send an existing draft
gws gmail delete-draft <id> Delete a draft
gws gmail attachment Download attachment (--message-id, --id, --output)
gws gmail links <id> Extract HTML anchor links from a message

Calendar

Command Description
gws calendar list List all calendars
gws calendar events List events (--days, --from, --calendar-id, --max, --pending, --query, --event-types, --show-deleted, --timezone, --updated-min)
gws calendar create Create event (--title, --start, --end, --attendees, --add-self)
gws calendar update <id> Update event (--title, --start, --end, --add-attendees)
gws calendar delete <id> Delete event
gws calendar rsvp <id> RSVP to invite (--response accepted/declined/tentative, --message)
gws calendar get Get event by ID (--calendar-id, --id)
gws calendar quick-add Quick add event from text (--text)
gws calendar instances List instances of recurring event (--id, --max, --from, --to)
gws calendar move Move event to another calendar (--id, --destination)
gws calendar get-calendar Get calendar metadata (--id)
gws calendar create-calendar Create secondary calendar (--summary, --description, --timezone)
gws calendar update-calendar Update calendar (--id, --summary, --description, --timezone)
gws calendar delete-calendar Delete secondary calendar (--id)
gws calendar clear Clear all events from a calendar (--calendar-id)
gws calendar subscribe Subscribe to a public calendar (--id)
gws calendar unsubscribe Unsubscribe from calendar (--id)
gws calendar calendar-info Get calendar subscription info (--id)
gws calendar update-subscription Update subscription settings (--id, --color-id, --hidden)
gws calendar acl List access control rules (--calendar-id)
gws calendar share Share calendar (--calendar-id, --email, --role)
gws calendar unshare Remove access (--calendar-id, --rule-id)
gws calendar update-acl Update access rule (--calendar-id, --rule-id, --role)
gws calendar freebusy Query free/busy (--from, --to, --calendars)
gws calendar colors List available calendar colors
gws calendar settings List user calendar settings

Tasks

Command Description
gws tasks lists List task lists
gws tasks list <id> List tasks in a list (--show-completed)
gws tasks list-info <id> Get task list details
gws tasks create Create task (--title, --tasklist, --due); accepts YYYY-MM-DD dates
gws tasks create-list Create a task list (--title)
gws tasks update <list> <task> Update task (--title, --notes, --due); preserves its existing completion status
gws tasks update-list <id> Update task list title (--title)
gws tasks delete-list <id> Delete a task list
gws tasks get <list> <task> Get task details
gws tasks delete <list> <task> Delete a task
gws tasks complete <list> <task> Mark task as done
gws tasks reopen <list> <task> Reopen task (sets status to needsAction)
gws tasks move <list> <task> Move/reorder task (--parent, --previous, --destination-list)
gws tasks clear <id> Clear completed tasks from a list

Drive

Command Description
gws drive list List files (--folder, --max, --order)
gws drive search <query> Full-text search (or valid V3 query syntax with --raw)
gws drive info <id> File metadata, owners, permissions
gws drive download <id> Download file (--output); auto-exports Google formats
gws drive upload <file> Upload file (--folder, --name, --mime-type); supports Shared Drives
gws drive create-folder Create folder (--name, --parent)
gws drive move <id> Move file to folder (--to)
gws drive delete <id> Delete file (--permanent for hard delete)
gws drive comments <id> List comments and replies (--include-resolved, --include-deleted)
gws drive approvals <id> List file approvals (--max)
gws drive approval <id> <approval-id> Get a file approval
gws drive start-approval Start approval workflow (--file-id, --reviewers, --due-time, --message, --lock-file)
gws drive approve Approve a file approval (--file-id, --approval-id, --message)
gws drive decline Decline a file approval (--file-id, --approval-id, --message)
gws drive reassign-approval Add or replace approval reviewers (--add-reviewer, --replace-reviewer)
gws drive cancel-approval Cancel a file approval (--file-id, --approval-id, --message)
gws drive comment-approval Comment on a file approval (--file-id, --approval-id, --message)
gws drive permissions List permissions on a file (--file-id)
gws drive share Share file (--file-id, --type, --role, --email, --domain)
gws drive unshare Remove permission (--file-id, --permission-id)
gws drive permission Get permission details (--file-id, --permission-id)
gws drive update-permission Update permission role (--file-id, --permission-id, --role)
gws drive revisions List file revisions (--file-id)
gws drive revision Get revision details (--file-id, --revision-id)
gws drive delete-revision Delete a revision (--file-id, --revision-id)
gws drive replies List replies to a comment (--file-id, --comment-id)
gws drive reply Create reply (--file-id, --comment-id, --content)
gws drive get-reply Get a specific reply (--file-id, --comment-id, --reply-id)
gws drive delete-reply Delete a reply (--file-id, --comment-id, --reply-id)
gws drive comment Get a single comment (--file-id, --comment-id)
gws drive add-comment Add comment to file (--file-id, --content)
gws drive delete-comment Delete comment (--file-id, --comment-id)
gws drive resolve-comment Resolve a comment (--file-id, --comment-id)
gws drive unresolve-comment Unresolve a comment (--file-id, --comment-id)
gws drive convert <id> Convert Office file to Google format (--to, --name, --folder)
gws drive export Export Google Workspace file (--file-id, --mime-type, --output)
gws drive empty-trash Empty trash permanently
gws drive update Update file metadata (--file-id, --name, --description, --starred, --trashed)
gws drive shared-drives List shared drives (--max, --query)
gws drive shared-drive Get shared drive details (--id)
gws drive create-drive Create shared drive (--name)
gws drive delete-drive Delete shared drive (--id)
gws drive update-drive Update shared drive (--id, --name)
gws drive about Get drive storage and user info
gws drive changes List recent file changes (--max, --page-token)
gws drive activity Query activity history (--item-id, --folder-id, --filter, --days, --max)

Docs

Command Description
gws docs read <id> Extract document text (--include-formatting)
gws docs info <id> Document metadata and styles
gws docs create Create new document (--title, --text)
gws docs append <id> Append text to document (--text, --newline)
gws docs insert <id> Insert text at position (--text, --at)
gws docs replace <id> Find and replace text (--find, --replace, --match-case)
gws docs replace-content <id> Replace entire document body (--text or --file, --content-format)
gws docs delete <id> Delete content range (--from, --to)
gws docs add-table <id> Insert table (--rows, --cols, --at)
gws docs format <id> Format text (--from, --to, --bold, --italic, --font-size, --color)
gws docs set-paragraph-style <id> Paragraph style (--from, --to, --alignment, --line-spacing)
gws docs add-list <id> Add bullet/numbered list (--at, --type, --items)
gws docs remove-list <id> Remove list formatting (--from, --to)
gws docs trash <id> Trash document (--permanent for hard delete)
gws docs add-tab <id> Add a tab (--title, --index)
gws docs delete-tab <id> Delete a tab (--tab-id)
gws docs rename-tab <id> Rename a tab (--tab-id, --title)
gws docs add-image <id> Insert image (--uri, --at, --width, --height)
gws docs insert-table-row <id> Insert table row (--table-start, --row, --col)
gws docs delete-table-row <id> Delete table row (--table-start, --row, --col)
gws docs insert-table-col <id> Insert table column (--table-start, --row, --col)
gws docs delete-table-col <id> Delete table column (--table-start, --row, --col)
gws docs merge-cells <id> Merge table cells (--table-start, --row, --col, --row-span, --col-span)
gws docs unmerge-cells <id> Unmerge table cells (--table-start, --row, --col, --row-span, --col-span)
gws docs pin-rows <id> Pin header rows (--table-start, --count)
gws docs page-break <id> Insert page break (--at)
gws docs section-break <id> Insert section break (--at, --type)
gws docs add-header <id> Add header (--type)
gws docs delete-header <id> <hid> Delete header
gws docs add-footer <id> Add footer (--type)
gws docs delete-footer <id> <fid> Delete footer
gws docs add-named-range <id> Create named range (--name, --from, --to)
gws docs delete-named-range <id> Delete named range (--name or --id)
gws docs add-footnote <id> Insert footnote (--at)
gws docs delete-object <id> <oid> Delete positioned object
gws docs replace-image <id> Replace image (--object-id, --uri)
gws docs replace-named-range <id> Replace named range text (--name/--id, --text)
gws docs update-style <id> Update doc margins (--margin-top/bottom/left/right)
gws docs update-section-style <id> Update section style (--from, --to, --column-count)
gws docs update-table-cell-style <id> Update cell style (--table-start, --row, --col, --bg-color)
gws docs update-table-col-properties <id> Update column width (--table-start, --col-index, --width)
gws docs update-table-row-style <id> Update row style (--table-start, --row, --min-height)

Sheets

Command Description
gws sheets info <id> Spreadsheet metadata
gws sheets list <id> List sheets in a spreadsheet
gws sheets read <id> <range> Read cell values (--output-format=csv, --headers)
gws sheets create Create spreadsheet (--title, --sheet-names)
gws sheets write <id> <range> Write cell values (--values, --values-json)
gws sheets append <id> <range> Append rows (--values, --values-json)
gws sheets add-sheet <id> Add sheet (--name, --rows, --cols)
gws sheets delete-sheet <id> Delete sheet (--name or --sheet-id)
gws sheets clear <id> <range> Clear cell values (keeps formatting)
gws sheets insert-rows <id> Insert rows (--sheet, --at, --count)
gws sheets delete-rows <id> Delete rows (--sheet, --from, --to)
gws sheets insert-cols <id> Insert columns (--sheet, --at, --count)
gws sheets delete-cols <id> Delete columns (--sheet, --from, --to)
gws sheets rename-sheet <id> Rename sheet (--sheet, --name)
gws sheets duplicate-sheet <id> Duplicate sheet (--sheet, --new-name)
gws sheets merge <id> <range> Merge cells
gws sheets unmerge <id> <range> Unmerge cells
gws sheets sort <id> <range> Sort data (--by, --desc, --has-header)
gws sheets find-replace <id> Find and replace (--find, --replace, --sheet, --match-case)
gws sheets format <id> <range> Format cells (--bold, --italic, --bg-color, --color, --font-size)
gws sheets set-column-width <id> Set column width (--sheet, --col, --width)
gws sheets set-row-height <id> Set row height (--sheet, --row, --height)
gws sheets freeze <id> Freeze panes (--sheet, --rows, --cols)
gws sheets copy-to <id> Copy sheet to another spreadsheet (--sheet-id, --destination)
gws sheets batch-read <id> Read multiple ranges (--ranges, --value-render)
gws sheets batch-write <id> Write multiple ranges (--ranges, --values, --value-input)
gws sheets add-named-range <id> <range> Add named range (--name)
gws sheets list-named-ranges <id> List all named ranges
gws sheets delete-named-range <id> Delete named range (--named-range-id)
gws sheets add-filter <id> <range> Set basic filter on range
gws sheets clear-filter <id> Clear basic filter (--sheet)
gws sheets add-filter-view <id> <range> Add filter view (--name)
gws sheets add-chart <id> Add embedded chart (--type, --data, --title, --sheet)
gws sheets list-charts <id> List all charts in a spreadsheet
gws sheets delete-chart <id> Delete a chart (--chart-id)
gws sheets add-conditional-format <id> <range> Add conditional format rule (--rule, --value, --bg-color, --bold)
gws sheets list-conditional-formats <id> List conditional format rules (--sheet)
gws sheets delete-conditional-format <id> Delete conditional format rule (--sheet, --index)

Slides

Command Description
gws slides info <id> Presentation metadata (--notes for speaker notes)
gws slides list <id> List slides with text content (--notes for speaker notes)
gws slides read <id> [n] Read slide text (specific or all, --notes for speaker notes)
gws slides create Create new presentation (--title)
gws slides add-slide <id> Add slide (--title, --body, --layout, --layout-id)
gws slides delete-slide <id> Delete slide (--slide-id or --slide-number)
gws slides duplicate-slide <id> Duplicate slide (--slide-id or --slide-number)
gws slides add-shape <id> Add shape (--slide-id/--slide-number, --type, --x, --y, --width, --height)
gws slides add-image <id> Add image (--slide-id/--slide-number, --url, --x, --y, --width)
gws slides add-text <id> Insert text into shape, table cell, or speaker notes (--object-id, --table-id/--row/--col, or --notes/--slide-number)
gws slides replace-text <id> Find and replace text (--find, --replace, --match-case)
gws slides delete-object <id> Delete any page element (--object-id)
gws slides delete-text <id> Clear text from shape or speaker notes (--object-id or --notes/--slide-number)
gws slides update-text-style <id> Style text (--object-id, --bold, --italic, --font-size, --color)
gws slides update-transform <id> Move/scale/rotate element (--object-id, --x, --y, --scale-x, --rotate)
gws slides create-table <id> Add table (--slide-id/--slide-number, --rows, --cols)
gws slides insert-table-rows <id> Insert rows (--table-id, --at, --count)
gws slides delete-table-row <id> Delete row (--table-id, --row)
gws slides update-table-cell <id> Style cell (--table-id, --row, --col, --background-color)
gws slides update-table-border <id> Style border (--table-id, --row, --col, --border, --color)
gws slides update-paragraph-style <id> Paragraph style (--object-id, --alignment, --line-spacing)
gws slides update-shape <id> Shape properties (--object-id, --background-color, --outline-color)
gws slides reorder-slides <id> Reorder slides (--slide-ids, --to)
gws slides update-slide-background <id> Set slide background (--slide-id/--slide-number, --color or --image-url)
gws slides list-layouts <id> List available layouts from presentation masters
gws slides add-line <id> Add line/connector (--slide-id/--slide-number, --type accepts STRAIGHT/BENT/CURVED, --start-x/y, --end-x/y)
gws slides group <id> Group elements (--object-ids; comma-separated IDs with no blank entries)
gws slides ungroup <id> Ungroup elements (--group-id; must not be blank)
gws slides thumbnail <id> Get slide thumbnail (--slide, --size, --download)

Chat

Requires Chat App configuration in Google Cloud Console.

Command Description
gws chat list List spaces (--filter, --page-size, --raw, --params)
gws chat spaces list List spaces (API-shape friendly path; same as chat list with --raw / --params documented examples)
gws chat recent Recap messages across active spaces (--since, --max, --max-per-space, --max-spaces)
gws chat messages [space] List messages (--max, --filter, --order-by, --show-deleted, --after, --before, --resolve-senders, --raw, --params; space may be supplied via --params parent)
gws chat messages list List messages by parent via --params (programmatic path)
gws chat members [space] List members with display names + emails via People API (--max, --filter, --show-groups, --show-invited, --raw, --params; space may be supplied via --params parent)
gws chat members list List members by parent via --params (programmatic path)
gws chat send Send message (--space, --text, --quote, --quote-type, --notify; force/silent are rejected until Chat app authentication is supported)
gws chat get <message> Get a single message (--resolve-senders)
gws chat update <message> Update message text (--text)
gws chat delete <message> Delete a message (--force)
gws chat reactions <message> List reactions (--filter, --page-size)
gws chat react <message> Add emoji reaction (--emoji)
gws chat unreact <reaction> Remove a reaction
gws chat get-space <space> Get space details
gws chat create-space Create a space (--display-name, --type, --description)
gws chat delete-space <space> Delete a space
gws chat update-space <space> Update a space (--display-name, --description)
gws chat search-spaces Search spaces — admin only (--query, --page-size)
gws chat find-dm Find DM space with a user (--user, --email)
gws chat setup-space Create space with initial members (--display-name, --type, --members)
gws chat get-member <member> Get member details
gws chat add-member <space> Add a member (--user, --role)
gws chat remove-member <member> Remove a member
gws chat update-member <member> Update member role (--role)
gws chat read-state <space> Get space read state
gws chat mark-read <space> Mark space as read (--time)
gws chat thread-read-state <thread> Get thread read state
gws chat unread <space> List unread messages (--max, --mark-read, --resolve-senders)
gws chat attachment <attachment> Get attachment metadata
gws chat upload <space> Upload a file (--file)
gws chat download <resource> Download media (--output)
gws chat events <space> List space events (--filter, --page-size)
gws chat event <event> Get event details
gws chat build-cache Build space-members cache (--type)
gws chat find-group Find group chats by member emails (--members, --refresh)
gws chat find-space Find spaces by display name substring (--name, --type, --refresh)

Forms

Requires enabling the Google Forms API.

Command Description
gws forms info <id> Form structure and questions
gws forms responses <id> All form responses with answers

Contacts

Command Description
gws contacts list List contacts (--max)
gws contacts search <query> Search contacts by name/email/phone
gws contacts get [resource-name] Get contact details (--raw, --params; resource-name may be supplied via --params resourceName)
gws contacts create Create contact (--name, --email, --phone)
gws contacts delete <resource-name> Delete a contact

People (programmatic People API)

Command Description
gws people get [resource-name] Direct People.Get wrapper for programmatic use (--raw, --params, --person-fields). Use --params '{"resourceName":"people/me","personFields":"emailAddresses"}'.

Groups

Requires Admin SDK API enabled and Workspace admin privileges.

Command Description
gws groups list List groups in domain (--max, --domain, --user-email)
gws groups members <group-email> List group members (--max, --role)

Keep

Requires Keep API enabled and Workspace Enterprise plan.

Command Description
gws keep list List notes (--max)
gws keep get <note-id> Get a note
gws keep create Create note (--title, --text)

Custom Search

Requires a Programmable Search Engine ID and API key.

Command Description
gws search <query> Search the web (--max, --site, --type)

Version

Command Description
gws version Print version, commit, and build date
gws version --check Check GitHub for the latest release and report whether gws is up to date

gws will also print a low-noise stale-version notice on stderr when a newer release is available. The notice is suppressed by --quiet and by setting GWS_NO_UPDATE_CHECK=1. The latest-release lookup is cached for 24 hours at ~/.config/gws/version-cache.json and dev/pseudo builds skip the comparison entirely.

Structured Output

Every command returns JSON by default for machine consumption:

$ gws calendar events --days 1
{
  "count": 3,
  "events": [
    {"id": "abc123", "summary": "Team standup", "start": "2024-01-15T09:00:00Z"},
    ...
  ]
}

Programmatic mode: --raw and --params

Several list/get commands accept two extra flags for scripting:

  • --raw emits the unmodified Google API response JSON (no field renaming, no base64 decoding, no header collapsing). Default ergonomic output is untouched when the flag is not set.
  • --params <json> accepts a JSON object whose keys map directly to the underlying API request parameters. Keys supplied here override the equivalent CLI flags (params win).

Under --all, raw mode concatenates the top-level list field across pages (messages / spaces / memberships) and drops nextPageToken from the final output.

Supported in this release:

Command Wraps
gmail list users.messages.list (under --raw)
gmail thread <id> users.threads.get
chat spaces list spaces.list
chat members list spaces.members.list
chat messages list spaces.messages.list
people get people.get

Examples:

gws gmail list --query "in:sent" --max 5 --raw
gws gmail thread 18abc --raw
gws chat spaces list --params '{"pageSize":50}' --all --raw
gws chat messages list --params '{"parent":"spaces/AAA","pageSize":50,"filter":"createTime > \"2025-01-01T00:00:00Z\""}' --all --raw
gws people get --params '{"resourceName":"people/me","personFields":"emailAddresses"}' --raw

Development

Project Layout

cmd/              # Cobra command implementations
internal/
  auth/           # OAuth2 + PKCE flow, token management
  client/         # Lazy-initialized Google API service factory
  config/         # Viper configuration and path resolution
  printer/        # JSON, YAML, and text output formatters
main.go           # Entry point

Building & Testing

make build      # Build binary to ./bin/gws
make test       # Run unit tests
make test-race  # Run tests with race detector
make vet        # Static analysis
make fmt        # Format code
make tidy       # Tidy go modules

Credential Storage

File Permissions Contents
~/.config/gws/config.yaml 0600 OAuth client ID/secret, preferences
~/.config/gws/token.json 0600 OAuth access/refresh tokens

Note: After upgrading gws to a version with new features (e.g., Docs/Slides write commands), you may need to re-authenticate to grant the new OAuth scopes:

gws auth logout && gws auth login

Claude Code Plugin

gws ships with a Claude Code plugin that teaches Claude how to use every command. Install it to get context-aware help for all 10+ services:

# From Claude Code, run:
/install-plugin omriariav/workspace-cli

The plugin includes 15 skills (one per Google service + auth setup, plus gws-setup), each with quick reference tables, detailed flag documentation, and AI agent tips.

Codex Plugin

gws also ships with a repo-local Codex plugin under plugins/gws, registered through .agents/plugins/marketplace.json. It mirrors the Claude Code skills with Codex-valid SKILL.md frontmatter and agents/openai.yaml metadata, so Codex can invoke skills such as $gws-gmail, $gws-calendar, and $gws-drive.

The Codex plugin is intentionally self-contained: its skill docs live under plugins/gws/skills/, while the original Claude Code skill docs remain under skills/.

Optional Session Context Hooks

The Claude Code and Codex plugins package the same optional hook workflow. Installing or updating either plugin remains inert: hooks are disabled by default, must be reviewed and trusted by the host, and make no Workspace API calls until a user explicitly enables a provider.

Use /gws-setup in Claude Code or $gws-setup in Codex to inspect and preview setup. The underlying CLI is also available directly:

# Inspect only. It never prints tokens, secrets, or cached context.
gws hooks status

# Preview provider selection. No files change without --apply.
gws hooks enable --time --workspace --scope user

# Apply only after reviewing and approving that exact preview.
gws hooks enable --time --workspace --scope user --apply

# Verify with a read-only, on-demand event invocation.
gws hooks test --event UserPromptSubmit

Applying this configuration does not itself activate lifecycle hooks. In Codex, use /hooks to inspect the gws SessionStart and UserPromptSubmit entries and explicitly approve them as a separate host-level action. Until that review/approval is complete, the GWS hook configuration remains inert.

time and workspace are independent providers. Time is recomputed for every hook event using an explicit configured timezone or a portable system-local fallback, and it never needs Google authentication. Workspace context refreshes only on SessionStart or the first prompt after its configured TTL, never on a background timer. Its allowlisted sources are read-only Calendar, Gmail, sent-mail, Tasks, and explicit Chat-space reads; per-source and overall time bounds keep hook failures nonblocking.

Preferences use this precedence: built-in defaults, user config ~/.config/gws/hooks.json, workspace config .gws/hooks.json, then GWS_HOOKS_ENABLED and GWS_HOOKS_TIMEZONE. User scope exclusively owns the global hook gate and both provider enablement settings. A repository .gws/hooks.json may contain only consent-free preferences such as timezone, Workspace refresh TTL, and source selection or limits; it cannot enable hooks, a provider, or private Workspace reads. Writes are atomic, merge-only, and mode-restricted. Workspace configuration never accepts credentials, tokens, or cached content. Private, volatile snapshots live outside the repository with restrictive permissions, and a degraded refresh retains a more useful previous snapshot instead of clobbering it.

Enable or disable hooks and providers only with --scope user. After a user has authorized the Workspace provider, a repository may preview consent-free source, limit, TTL, timezone, task-list, or Chat-space preferences with gws hooks configure --scope workspace, then repeat the exact command with --apply after approval. To stop all hook fetches without changing normal gws commands or authentication, preview and then apply gws hooks disable --scope user. Status detects likely personal time injectors such as ~/.codex/hooks/inject-time.sh; it reports them but never silently modifies them.

License

gws is available under the MIT License.

About

Unofficial Google Workspace CLI

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages