google-workspace について
google-workspaceは、OAuthとCLIラッパーを通じてGmail、Calendar、Drive、Contacts、Sheets、Docsを操作するHermesスキルです。gwsがあれば実行基盤として使い、なければ同梱のPythonクライアントに切り替え、結果をJSONで返します。
主な機能
- 01Gmailメッセージの検索と読み取り
- 02Calendar予定の一覧表示と作成
- 03Driveファイルの検索、アップロード、管理
- 04Contacts、Sheets、Docsの操作
- 05OAuth設定とトークン管理
- 06CLI経由のJSON出力
活用シーン
- 01未読メールや急ぎのメールの確認
- 02予定の確認と会議の準備
- 03Driveファイルの検索と管理
- 04スプレッドシートや文書の読み取り・作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nousresearch/ hermes-agent --skill google-workspaceインストール後、Claude Code で/google-workspaceを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/daily-brief.mdgmail-search-syntax.mdscripts/_hermes_home.pygoogle_api.pygws_bridge.pysetup.py詳細
Google Workspace
Hermes が管理する OAuth と軽量な CLI ラッパーを通じて、Gmail、Calendar、Drive、Contacts、Sheets、Docs を利用できます。gws がインストールされている場合、このスキルはより広範な Google Workspace 対応の実行バックエンドとして gws を使用します。インストールされていない場合は、同梱の Python クライアント実装にフォールバックします。
参考資料
references/gmail-search-syntax.md— Gmail の検索演算子(is:unread、from:、newer_than: など)references/daily-brief.md— 日次/朝のブリーフィング手順:予定+競合+会議の準備+Gmail と Calendar の緊急メール。朝のブリーフィング、会議の準備、または「カレンダーの予定と対応が必要なメールは何か」をユーザーが尋ねたときに読み込んでください。
スクリプト
scripts/setup.py— OAuth2 のセットアップ(認証のため、1 回だけ実行します)scripts/google_api.py— 互換性を保つ CLI ラッパーです。利用可能な場合は操作にgwsを優先して使用しつつ、Hermes の既存の JSON 出力仕様を維持します。
初回セットアップ
セットアップは完全に非対話式です。CLI、Telegram、Discord など、どのプラットフォームでも動作するよう、手順を順番に進めます。
無関係なシステムの Python ではなく、Hermes 環境の Python でセットアップスクリプトを実行してください。--install-deps は PM を通じて Hermes が宣言している Google 拡張機能を同期します。同期後に Hermes を再起動し、OAuth コマンドを再実行してください。Hermes をインポートできない場合は、pip でパッケージをインストールするのではなく、まず hermes setup を実行してください。
まず、短縮形を定義します。
GSETUP="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/setup.py"
ステップ 0:セットアップ済みか確認する
$GSETUP --check
AUTHENTICATED と表示された場合は、「使用方法」に進んでください。セットアップは完了しています。
ステップ 1:要件を確認する — 必要なサービスをユーザーに尋ねる
OAuth のセットアップを始める前に、ユーザーに次の 2 つの質問をしてください。
質問 1:「必要な Google サービスは何ですか?メールだけですか?それとも Calendar/Drive/Sheets/Docs も必要ですか?」
-
メールのみ → このスキルは必要ありません。代わりに
himalayaスキルを使用してください。Gmail のアプリ パスワード(Settings → Security → App Passwords)で動作し、セットアップは 2 分で完了します。Google Cloud プロジェクトは不要です。himalaya スキルを読み込み、セットアップ手順に従ってください。 -
メール+Calendar → このスキルを続けて使用しますが、認証時に
--services email,calendarを指定し、同意画面に必要なスコープだけが表示されるようにしてください。 -
Calendar/Drive/Sheets/Docs のみ → このスキルを続けて使用し、
calendar,drive,sheets,docsのように、より限定した--servicesの組み合わせを使用してください。 -
Workspace の全機能へのアクセス → このスキルを続けて使用し、デフォルトの
allサービスセットを使用してください。
質問 2:「Google アカウントで高度な保護機能(サインインにハードウェア セキュリティ キーが必要な機能)を使用していますか?わからない場合、おそらく使用していません。これは明示的に登録して有効にする機能です。」
- いいえ/不明 → 通常のセットアップです。以下に進んでください。
- はい → ステップ 4 を実行する前に、Workspace 管理者が OAuth クライアント ID を組織の許可済みアプリのリストに追加する必要があります。事前にその旨をユーザーに伝えてください。
ステップ 2:OAuth 認証情報を作成する(初回のみ、約 5 分)
ユーザーに次のように伝えてください。
Google Cloud OAuth クライアントが必要です。これは初回のみの設定です。
- プロジェクトを作成するか、選択します。 https://console.cloud.google.com/projectselector2/home/dashboard
- API ライブラリから必要な API を有効にします。 https://console.cloud.google.com/apis/library 有効にする API:Gmail API、Google Calendar API、Google Drive API、 Google Sheets API、Google Docs API、People API
- こちらから OAuth クライアントを作成します。 https://console.cloud.google.com/apis/credentials 認証情報 → 認証情報を作成 → OAuth 2.0 クライアント ID
- アプリケーションの種類:「デスクトップアプリ」→ 作成
- アプリがまだテスト中の場合は、こちらからユーザーの Google アカウントをテストユーザーとして追加します。 https://console.cloud.google.com/auth/audience 対象ユーザー → テストユーザー → ユーザーを追加
- JSON ファイルをダウンロードして、ファイルのパスを教えてください。
Hermes CLI に関する重要な注意:ファイルパスが
/で始まる場合、CLI でパスだけを単独のメッセージとして送らないでください。スラッシュコマンドと誤認される可能性があります。代わりに、次のような文に含めて送ってください。The JSON file path is: ~/Downloads/client_secret_....json
パスを受け取ったら、次を実行します。
$GSETUP --client-secret /path/to/client_secret.json
ファイルパスではなく、クライアント ID/クライアントシークレットの値をそのまま貼り付けた場合は、有効なデスクトップ OAuth JSON ファイルをご自身で作成し、(たとえば ~/Downloads/hermes-google-client-secret.json のように)明示的な場所に保存してから、そのファイルを指定して --client-secret を実行します。
ステップ 3:認証 URL を取得する
ステップ 1 で選んだサービスセットを使用します。例:
$GSETUP --auth-url --services email,calendar --format json
$GSETUP --auth-url --services calendar,drive,sheets,docs --format json
$GSETUP --auth-url --services all --format json
このコマンドは、auth_url フィールドを含む JSON を返し、正確な URL を ~/.hermes/google_oauth_last_url.txt にも保存します。
このステップでのエージェントのルール:
auth_urlフィールドを抽出し、その正確な URL を 1 行でユーザーに送ります。- 承認後、ブラウザーで
http://localhost:1がエラーになる可能性が高いものの、これは想定どおりであることをユーザーに伝えます。 - ブラウザーのアドレスバーに表示されたリダイレクト後の URL 全体をコピーするよう、ユーザーに伝えます。
- ユーザーに
Error 403: access_deniedが表示された場合は、テストユーザーとして自身を追加できるよう、直接https://console.cloud.google.com/auth/audienceに案内します。
ステップ 4:コードを交換する
ユーザーは http://localhost:1/?code=4/0A...&scope=... のような URL、またはコード文字列だけを貼り付けます。どちらでも機能します。--auth-url のステップでは、一時的な保留中の OAuth セッションがローカルに保存されるため、ヘッドレスシステムでも後から --auth-code で PKCE 交換を完了できます。
$GSETUP --auth-code "THE_URL_OR_CODE_THE_USER_PASTED" --format json
コードの期限切れ、使用済み、または古いブラウザータブから取得されたことが原因で --auth-code が失敗した場合、新しい fresh_auth_url が返されるようになりました。その場合は、新しい URL をすぐにユーザーに送り、ブラウザーで最新のリダイレクト後 URL のみを使って再試行するよう伝えます。
ステップ 5:確認する
$GSETUP --check
AUTHENTICATED と表示されるはずです。セットアップは完了です。以降、トークンは自動的に更新されます。
注意事項
- トークンは
~/.hermes/google_token.jsonに保存され、自動的に更新されます。 - 保留中の OAuth セッション状態/検証子は、交換が完了するまで一時的に
~/.hermes/google_oauth_pending.jsonに保存されます。 gwsがインストールされている場合、google_api.pyは同じ~/.hermes/google_token.json認証情報ファイルを使用するように設定します。ユーザーが別途gws auth loginの手順を実行する必要はありません。- 取り消すには:
$GSETUP --revoke
使い方
すべてのコマンドは API スクリプトを通じて実行します。省略形として GAPI を設定します。
GAPI="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/google_api.py"
Gmail
# Search (returns JSON array with id, from, subject, date, snippet)
$GAPI gmail search "is:unread" --max 10
$GAPI gmail search "from:[email protected] newer_than:1d"
$GAPI gmail search "has:attachment filename:pdf newer_than:7d"
# Read full message (returns JSON with body text)
$GAPI gmail get MESSAGE_ID
# Send
$GAPI gmail send --to [email protected] --subject "Hello" --body "Message text"
$GAPI gmail send --to [email protected] --subject "Report" --body "<h1>Q4</h1><p>Details...</p>" --html
$GAPI gmail send --to [email protected] --subject "Hello" --from '"Research Agent" <[email protected]>' --body "Message text"
# Reply (automatically threads and sets In-Reply-To)
$GAPI gmail reply MESSAGE_ID --body "Thanks, that works for me."
$GAPI gmail reply MESSAGE_ID --from '"Support Bot" <[email protected]>' --body "Thanks"
# Labels
$GAPI gmail labels
$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID
$GAPI gmail modify MESSAGE_ID --remove-labels UNREAD
Calendar
# List events (defaults to next 7 days)
$GAPI calendar list
$GAPI calendar list --start 2026-03-01T00:00:00Z --end 2026-03-07T23:59:59Z
# Create event (ISO 8601 with timezone required)
$GAPI calendar create --summary "Team Standup" --start 2026-03-01T10:00:00-06:00 --end 2026-03-01T10:30:00-06:00
$GAPI calendar create --summary "Lunch" --start 2026-03-01T12:00:00Z --end 2026-03-01T13:00:00Z --location "Cafe"
$GAPI calendar create --summary "Review" --start 2026-03-01T14:00:00Z --end 2026-03-01T15:00:00Z --attendees "[email protected],[email protected]"
# Delete event
$GAPI calendar delete EVENT_ID
Drive
# Search existing files
$GAPI drive search "quarterly report" --max 10
$GAPI drive search "mimeType='application/pdf'" --raw-query --max 5
# Get metadata for a single file
$GAPI drive get FILE_ID
# Upload a local file (auto-detects MIME type)
$GAPI drive upload /path/to/report.pdf
$GAPI drive upload /path/to/image.png --name "Logo.png" --parent FOLDER_ID
# Download (binary files download as-is; Google-native files export to a
# sensible default — Docs→pdf, Sheets→csv, Slides→pdf, Drawings→png)
$GAPI drive download FILE_ID
$GAPI drive download DOC_ID --output ~/doc.pdf
$GAPI drive download DOC_ID --export-mime text/plain --output ~/doc.txt
# Create a folder
$GAPI drive create-folder "Reports"
$GAPI drive create-folder "Q4" --parent FOLDER_ID
# Share
$GAPI drive share FILE_ID --email [email protected] --role reader
$GAPI drive share FILE_ID --email [email protected] --role writer --notify
$GAPI drive share FILE_ID --type anyone --role reader # anyone with link
$GAPI drive share FILE_ID --type domain --domain example.com --role reader
# Delete — defaults to trash (reversible). Use --permanent to skip the trash.
$GAPI drive delete FILE_ID
$GAPI drive delete FILE_ID --permanent
Contacts
$GAPI contacts list --max 20
Sheets
# Create a new spreadsheet
$GAPI sheets create --title "Q4 Budget"
$GAPI sheets create --title "Inventory" --sheet-name "Stock"
# Read
$GAPI sheets get SHEET_ID "Sheet1!A1:D10"
# Write
$GAPI sheets update SHEET_ID "Sheet1!A1:B2" --values '[["Name","Score"],["Alice","95"]]'
# Append rows
$GAPI sheets append SHEET_ID "Sheet1!A:C" --values '[["new","row","data"]]'
Docs
# Read (a tabbed Doc returns a "tabs" array; single-tab and legacy Docs also return "body")
$GAPI docs get DOC_ID
$GAPI docs get DOC_ID --tab TAB_ID # read one tab of a tabbed Doc
# Create a new Doc (optionally seeded with body text)
$GAPI docs create --title "Meeting Notes"
$GAPI docs create --title "Draft" --body "First paragraph..."
# Append text to the end of an existing Doc
$GAPI docs append DOC_ID --text "Additional content to append"
$GAPI docs append DOC_ID --tab TAB_ID --text "..." # --tab required when the Doc has multiple tabs
出力形式
すべてのコマンドは JSON を返します。jq で解析するか、直接読み取ってください。主なフィールド:
- Gmail の検索:
[{id, threadId, from, to, subject, date, snippet, labels}] - Gmail の取得:
{id, threadId, from, to, subject, date, labels, body} - Gmail の送信/返信:
{status: "sent", id, threadId} - カレンダーの一覧:
[{id, summary, start, end, location, description, htmlLink}] - カレンダーの作成:
{status: "created", id, summary, htmlLink} - Drive の検索:
[{id, name, mimeType, modifiedTime, webViewLink}] - Drive の取得:
{id, name, mimeType, modifiedTime, size, webViewLink, parents, owners} - Drive へのアップロード:
{status: "uploaded", id, name, mimeType, webViewLink} - Drive からのダウンロード:
{status: "downloaded", id, name, path, mimeType} - Drive フォルダーの作成:
{status: "created", id, name, webViewLink} - Drive の共有:
{status: "shared", permissionId, fileId, role, type} - Drive の削除:
{status: "trashed" | "deleted", fileId, permanent} - 連絡先の一覧:
[{name, emails: [...], phones: [...]}] - Sheets の取得:
[[cell, cell, ...], ...] - Sheets の作成:
{status: "created", spreadsheetId, title, spreadsheetUrl} - Docs の作成:
{status: "created", documentId, title, url} - Docs への追記:
{status: "appended", documentId, inserted_at, characters}
ルール
- ユーザーに事前確認せずに、メールの送信、カレンダーイベントの作成/削除、Drive ファイルの削除/共有、Docs/Sheets の変更を行わないでください。 実行内容(宛先、ファイル ID、内容、共有ロール)を提示し、承認を求めてください。
drive deleteでは、--permanentではなく、既定のゴミ箱への移動(復元可能)を優先してください。 - 初回使用前に認証を確認してください —
setup.py --checkを実行します。失敗した場合は、ユーザーにセットアップ手順を案内してください。 - 複雑なクエリでは、Gmail 検索構文のリファレンスを使用してください —
skill_view("google-workspace", file_path="references/gmail-search-syntax.md")で読み込みます。 - カレンダーの時刻にはタイムゾーンを含めてください — 常にオフセット付きの ISO 8601(例:
2026-03-01T10:00:00-06:00)または UTC(Z)を使用してください。 - レート制限を守ってください — API 呼び出しを短時間に連続して行わないでください。可能な場合は読み取りをまとめて行ってください。
トラブルシューティング
| 問題 | 対処方法 |
|---|---|
NOT_AUTHENTICATED | 上記のセットアップ手順 2~5 を実行してください |
REFRESH_FAILED | トークンが取り消されたか、有効期限が切れています — 手順 3~5 をやり直してください |
HttpError 403: Insufficient Permission | API スコープが不足しています — $GSETUP --revoke を実行してから、手順 3~5 をやり直してください |
AUTHENTICATED (partial) または "Token missing scopes" | 新しい書き込み機能(Drive の書き込み/削除、Docs の作成/編集)には、再認証が必要です。$GSETUP --revoke を実行してから、手順 3~5 をやり直し、更新されたスコープを許可してください。 |
HttpError 403: Access Not Configured | API が有効になっていません — ユーザーは Google Cloud Console で有効にする必要があります |
ModuleNotFoundError | $GSETUP --install-deps を実行してください |
| Advanced Protection によって認証がブロックされる | Workspace 管理者が OAuth クライアント ID を許可リストに追加する必要があります |
アクセスの取り消し
$GSETUP --revoke