一键导入
google-workspace
Gmail, Calendar, Tasks, Sheets, Docs, Drive, Contacts — OAuth2 with auto-refresh; works with Hermes, OpenClaw, and any terminal agent/CLI.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Gmail, Calendar, Tasks, Sheets, Docs, Drive, Contacts — OAuth2 with auto-refresh; works with Hermes, OpenClaw, and any terminal agent/CLI.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | google-workspace |
| description | Gmail, Calendar, Tasks, Sheets, Docs, Drive, Contacts — OAuth2 with auto-refresh; works with Hermes, OpenClaw, and any terminal agent/CLI. |
| version | 2.2.0 |
| author | Hermes Agent Community |
| license | MIT |
| tags | ["Google","Gmail","Calendar","Tasks","Sheets","Docs","Drive","Contacts","OAuth"] |
| required_credential_files | [{"path":"google_token.json","description":"Google OAuth2 access token(自动刷新,setup.py 管理)"},{"path":"google_client_secret.json","description":"Google OAuth2 客户端凭证(从 Google Cloud Console 下载)"}] |
| optional_credential_files | [{"path":"google_oauth_pending.json","description":"OAuth 流程中间状态(授权完成后自动删除)"}] |
| metadata | {"hermes":{"homepage":"https://github.com/BruceLanLan/hermes-google-workspace","platform":["cli","telegram","slack","discord","whatsapp","openclaw","cursor"],"profile_scoped":true}} |
Gmail、Calendar、Tasks、Sheets、Docs、Drive、Contacts — 通过 Google OAuth2 集成到任意能跑终端命令的 Agent(Hermes、OpenClaw、Claude Code、Cursor 等)。Token 存放在可配置的 profile 目录,支持自动刷新。
| 服务 | 读取 | 写入 | 备注 |
|---|---|---|---|
| Gmail | ✅ search (--format ids), get (--format json/text/markdown), labels | ✅ send / reply(--attachment, HTML), modify | 发送前建议由 Agent 确认 |
| Calendar | ✅ list | ✅ create / update / delete | ISO 8601 带时区;create --duration 30m 可省 --end |
| Tasks | ✅ tasklists, list | ✅ add(insert+patch), complete | google_api.py tasks … |
| Sheets | ✅ get | ✅ update, append | 需先查 tab 名 |
| Docs | ✅ get(纯文本) | ❌ | 只读 |
| Drive | ✅ search | ❌ | 只读 |
| Contacts | ✅ list | ❌ | 只读 |
scripts/setup.py — OAuth 配置(check / client-secret / auth-url / auth-code / revoke)scripts/google_api.py — Google API 的 CLI 封装scripts/scopes.py — 唯一的 OAuth scope 列表(setup.py 与 google_api.py 均从这里导入)scripts/_gws_env.py — 解析 token 存放目录(Hermes / OpenClaw / 自定义)scripts/_gws_common.py — 共享的错误装饰器、scope 比对、JSON 输出tests/test_pure_helpers.py — 纯逻辑单元测试(不触网)references/gmail-search-syntax.md — Gmail 搜索操作符完整参考hermes skills install google-workspace
手动安装:
HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}"
mkdir -p "$HERMES_HOME/skills/productivity/google-workspace"/{scripts,references}
# 复制 scripts 和 references 目录内容到上述路径
配置 shorthand(按需把 GWORKSPACE_SKILL_DIR 换成你克隆本仓库的路径):
GWORKSPACE_SKILL_DIR="$HOME/src/hermes-google-workspace"
PYTHON_BIN="${HERMES_PYTHON:-python3}"
GSETUP="$PYTHON_BIN $GWORKSPACE_SKILL_DIR/scripts/setup.py"
GAPI="$PYTHON_BIN $GWORKSPACE_SKILL_DIR/scripts/google_api.py"
可选:用 npm 提供的入口(需本仓库在本地或已通过 npm install -g / npx 解析到含 scripts/ 的包目录):
# 已发布到 npm 时(或先用本地路径调试:`npx -y -p /path/to/hermes-google-workspace …`)
GSETUP="npx -y -p hermes-google-workspace gws-setup"
GAPI="npx -y -p hermes-google-workspace gws"
# 从 GitHub 安装:`npx -y -p github:BruceLanLan/hermes-google-workspace gws-setup`
Token 目录解析顺序见 scripts/_gws_env.py。常用覆盖:
GOOGLE_WORKSPACE_STATE_DIR — 显式指定目录(推荐用于非 Hermes 的 CLI)HERMES_HOME / OPENCLAW_HOME — 与对应 Agent 的 profile 对齐$GSETUP --check
# AUTHENTICATED → 已完成,跳过本节
--client-secret$GSETUP --client-secret /path/to/client_secret.json
默认列表在 scripts/scopes.py。setup.py 与 google_api.py 已强制从该文件导入,避免再出现「授权范围与 CLI 不一致」的问题。若你不需要某项能力,可从列表中删除对应 scope,然后重新走 OAuth。
$GSETUP --auth-url
# 输出一个 URL,发给用户让其在浏览器打开
用户授权后浏览器跳转到 http://localhost:1/?...,用户粘贴完整 URL:
$GSETUP --auth-code "用户粘贴的URL"
$GSETUP --check
# 搜索
$GAPI gmail search "is:unread newer_than:1d" --max 10
# 读取
$GAPI gmail get MESSAGE_ID
# 发送(发送前展示草稿并确认);--attachment 可多次
$GAPI gmail send --to user@example.com --subject "Report" --body "<h1>Q4</h1>" --html \
--attachment ~/slides.pdf --attachment ~/notes.txt
# 供 Agent 总结:--format markdown / text;或用 --format ids 管道化
$GAPI gmail get MESSAGE_ID --format markdown
$GAPI gmail search "from:boss is:unread" --format ids | xargs -I{} $GAPI gmail modify {} --add-labels STARRED
# 回复(自动 threading + In-Reply-To)
$GAPI gmail reply MESSAGE_ID --body "Got it, thanks!"
# 标签管理
$GAPI gmail labels
$GAPI gmail modify MESSAGE_ID --add-labels STARRED --remove-labels UNREAD
# 列表(默认未来7天)
$GAPI calendar list
# 创建:--end 或 --duration 二选一
$GAPI calendar create \
--summary "Sprint Planning" \
--start 2026-04-21T10:00:00-05:00 \
--duration 1h30m \
--location "Google Meet" \
--attendees "team@co.com" # 传 --attendees 时自动 sendUpdates=all
# 更新(改时间 / 议程 / 参会人,只改传入的字段)
$GAPI calendar update EVENT_ID --start 2026-04-21T11:00:00-05:00 --duration 45m
# 删除;--notify 给参会人发送取消通知
$GAPI calendar delete EVENT_ID --notify
$GAPI tasks tasklists
$GAPI tasks list --tasklist TASKLIST_ID
$GAPI tasks add --tasklist TASKLIST_ID --title "Review deck" --notes "Friday" --due "2026-04-20T00:00:00.000Z"
$GAPI tasks complete --tasklist TASKLIST_ID --task TASK_ID
# 读取(注意:先查 tab 名,不要硬写 "Sheet1")
$GAPI sheets get "SHEET_ID" "Sheet1!A1:D10"
# 写入
$GAPI sheets update "SHEET_ID" "Sheet1!A1:B2" --values '[["Alice","100"],["Bob","95"]]'
# 追加
$GAPI sheets append "SHEET_ID" "Sheet1!A:C" --values '[["Carol","88"]]'
$GAPI docs get DOC_ID
# 全文搜索
$GAPI drive search "budget report" --max 10
# MIME 类型筛选
$GAPI drive search "mimeType='application/vnd.google-apps.spreadsheet'" --raw-query --max 5
scripts/scopes.py$GSETUP --auth-url(重新获取 URL)$GSETUP --auth-code "URL"(用户重新授权)$GSETUP --check# WRONG: 永远是空的
for block in doc_content.get("content", []):
# CORRECT
for block in doc_content.get("body", {}).get("content", []):
for elem in block.get("paragraph", {}).get("elements", []):
if "textRun" in elem:
text += elem["textRun"].get("content", "")
先查 metadata:
meta = sheets.spreadsheets().get(spreadsheetId=ID).execute()
tabs = [s["properties"]["title"] for s in meta.get("sheets", [])]
tab = tabs[0] # 用第一个 tab 名
必须分两步:先 insert,再 patch:
# Fails
tasks.tasks().insert(tasklist=ID, body={"title": "x", "due": "2026-04-14T00:00:00Z"})
# Works
t = tasks.tasks().insert(tasklist=ID, body={"title": "x"}).execute()
tasks.tasks().patch(tasklist=ID, task=t["id"], body={"due": "..."}).execute()
文件所有者没有和你的 OAuth 客户端共享。请求访问权限或换个已共享的文件。
| 问题 | 诊断命令 | 解决方法 |
|---|---|---|
NOT_AUTHENTICATED | $GSETUP --check | 完成 OAuth Step 4 |
REFRESH_FAILED | — | Token 被 Google 撤销,重新授权 |
HttpError 403: Insufficient Permission | 检查 scopes | 重新授权 |
HttpError 403: Access Not Configured | Google Cloud Console | 启用对应 API |
ModuleNotFoundError | — | $GSETUP --install-deps |
| Advanced Protection 阻止 | — | Workspace 管理员白名单 OAuth 客户端 ID |
$GSETUP --revoke