mcpField
H
hey

hey

github.com/basecamp生产力84229 次安装1 天前更新
代码仓库

关于 hey

hey skill 为 Agent 使用 HEY CLI 提供操作指引,涵盖邮件、联系人、日历项目及相关工作流。它强调查阅命令帮助、正确处理 ID、明确选择输出模式,并遵守认证和邮件发送方面的安全规则。

主要功能

  1. 01按命令查阅帮助
  2. 02邮件、联系人与日历工作流
  3. 03结构化输出与筛选
  4. 04ID 与分页安全规则
  5. 05发送邮件与认证规则

适用场景

  1. 01为任务查找合适的 HEY 命令
  2. 02阅读或整理邮件会话
  3. 03创建或查看日历项目
  4. 04遵循发送保护规则撰写邮件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/basecamp/skills --skill hey

安装后在 Claude Code 中输入/hey确认已加载。

详细介绍

/hey - HEY 邮件工作流命令

HEY 命令行工具:邮箱、标签、集合、邮件会话、联系人、回复、撰写、日历、待办事项、习惯、时间跟踪和日志条目。

请将已安装的命令行工具用作命令参考。本技能包含适用于各命令的规则;不复制命令目录,因为二进制文件自带的帮助信息才是权威来源,并且始终与当前运行的版本一致。

先探索的工作流

对于每项任务:

  1. 根据用户的描述,推断最可能的最深层叶子命令。

  2. 除非本次对话中的工具结果已明确其参数和标志,否则先查看该叶子命令的帮助,再运行它:

    hey <group> <subcommand> --agent --help
    
  3. 如果该叶子命令不存在,则查看最近的父命令组。只有在无法确定顶层命令组时,才查看根命令的帮助:

    hey <group> --agent --help   # fallback
    hey --agent --help           # last resort
    hey commands --json          # every command with its agent_notes
    
  4. 将叶子命令的 short、long、agent_notes 和 flags 视为权威信息。不要猜测位置参数、标志、可接受的值或限制。

  5. 使用明确的输出模式运行命令,然后先查看结构化错误,再决定下一步操作。

查看叶子命令的帮助开销很小;根命令的帮助和 hey commands --json 会打印整个目录,开销较大。全局标志(--json、--jq、--quiet、--account、--stats)适用于支持它们的所有命令。

不可妥协的规则

  1. 选择正确的结构化输出。 使用 --jq '<expression>' 筛选或提取字段,使用 --json 获取完整响应。切勿通过管道传给外部 jq;--jq 是内置功能,并且会隐式启用 --json。
  2. 复用已存储的身份验证信息。 运行用户请求的数据命令;它会使用已存储的凭据,并自动刷新即将过期的 OAuth 令牌。如果返回身份验证错误,请先按照身份验证中的重试步骤操作,再报告任务受阻。需要明确检查身份验证时,使用 hey auth status --json(它会报告已存储的凭据,不会联系 HEY)。无人值守时切勿运行 hey auth login;仅在用户在场时将其用于交互式恢复。
  3. 已关联的邮件账户共用一次登录。 使用 hey account list --json,然后在任务需要针对某个账户时使用 --account <id|all>。
  4. 本地 HEY 配置需要获得用户信任。 未经用户明确批准,切勿运行 hey config trust-local。
  5. 发送失败并返回 not_delivered 时,切勿重新发送。 请参阅发送。
  6. 修改邮箱项目时先确认。 请参阅ID:HEY 不会报告未匹配到任何项目的 ID。

输出

--jq 会筛选完整的 JSON 成功响应封装,因此结果数据位于 .data 下。字符串结果会以纯文本形式打印;对象和数组会以格式化后的 JSON 形式打印。如果表达式应直接作用于结果数据,请使用 --quiet --jq。错误会保留完整的结构化响应封装。具有自身原始输出的命令(auth token、shell-completion generate、setup、skill、tui、--version,以及不带 --output 的 timetrack export)不接受 --jq。hey watch 每行写入一个原始 JSON 事件,不带响应封装,也不应用 --jq。

hey box list --jq '.data[] | {id, name}'
hey search "quarterly planning" --jq '.data[].topic_id'
hey box list --quiet --jq '.[].name'
  • 空结果是空数组,而不是 null,因此在没有找到任何内容的列表上使用 .data[] 是安全的。
  • HEY 的回答中未包含的字段会保持缺省,不会猜测补全。帖子的 seen 仅在值为 true 时才会出现,因此可用 .seen != true 检查未读项。
  • --ids-only 每行打印一个 ID,--count 则只打印一个数字。它们适用于列表:所有 list 命令、主题列表、hey workflow view、hey search、hey screener history、hey event day|week、hey timetrack categories、hey attachment list,以及 hey thread read(其条目从索引读取,不含正文)。两者都只针对已读取的内容返回结果;除非使用 --all 或 --limit 读取更多内容,否则读取的都是第一页。并非所有列表都会提示还有更多页面;例外是 hey screener list --count,它会统计整个队列。对于主题列表,它们统计的是帖子数量,而不是帖子周围的邮箱、标签或联系人数量。
  • --all 会在达到页面上限时停止,具体上限可在各列表的帮助中查看。达到上限的读取会说明如何继续:对于 hey box view 这类游标列表,使用 next_page;对于 hey search 或 hey contact list 这类编号列表,则根据 notice 中指出的 --page 值继续。请从那里继续,而不要将列表视为完整列表。
  • --html 会将 hey thread read、hey journal read 和联系人私人备注的原始 HTML 写入管道或文件;不允许写入终端。

ID

每个邮件线程都有两个 ID:id,即其邮箱条目 ID(某个邮箱中的一封邮件),以及 topic_id,即其线程 ID。线程列表中的每封邮件都包含 id、topic_id、kind(汇总行时为 bundle)、name(主题)、created_at 和 app_url;线程行还包含 contacts、summary 和 visible_entry_count。

  • 邮箱条目 ID(id):hey seen、unseen、move、label add|remove|create、trash、spam、ignore、stop-ignoring、bubble up|pop、set-aside group、bulk-reply 和 bundle view。
  • 线程 ID(topic_id):hey thread read|update、share、unshare、attachment list、reply、forward、compose --thread-id、collection add|remove 和 workflow add|move|remove。
  • 邮件条目 ID:来自 hey thread read 的邮件条目 id;hey clip create 需要此 ID,且邮件正文中必须包含对应片段。
  • 来自 hey contact list 或联系人数据的联系人 ID、来自 hey screener list 的审核 ID(其中还会提供决策前要读取的线程的 topic_id)、来自 hey box list 的邮箱 ID、来自 hey label list 的标签 ID。切勿混用不同类型的 ID,也不要用电子邮件地址代替联系人 ID。

线程列表(hey box view、label view、collection view、bundle view、contact threads、search)会同时提供这两个 ID,但有两个例外:汇总行可能不包含 topic_id;如果搜索结果对应的线程在你的邮箱中没有条目,则会省略 id。

传入错误类型的 ID 不会自动重定向。不会报告不匹配的 ID:HEY 只会检查调用中是否有任意一个邮箱条目 ID 属于你,并对所有匹配项执行更改。只有当所有 ID 都不匹配时,hey trash、spam、label add|remove|create 和 bubble up|pop 才会返回 not_found;hey seen、unseen、move、ignore、stop-ignoring 和 set-aside group create|add|remove 则从不检查(如果没有匹配的 ID,group create 会留下一个空组)。因此,混合批次即使只部分成功,也会被报告为整体成功;输入错误会被静默跳过;恰好与某个邮箱条目 ID 相同的 topic_id 会作用于不相关的线程;同样,传给 hey thread read 的邮箱条目 ID 也可能读取不相关的线程。应进行确认,而不要只相信响应:

hey box view imbox --json --all --jq '{notice, next_page: .data.next_page, match: [.data.postings[] | select(.id == 12345) | {id, topic_id, seen}]}'

如需确认标记操作,可检查标记状态;如需确认移动操作,可读取目标邮箱。如果 match 为空但仍设置了 next_page,则说明邮箱内容多于 --all 读取的范围:请使用 --page <next_page> 继续读取,而不要将其判定为不匹配。

汇总行。 当一封邮件的 kind 为 bundle 时,表示将同一发件人的邮件汇总到一行中,该行显示的是发件人,而非线程。只有当其中恰好包含一个未读线程时,才会提供 topic_id。切勿将汇总行的 id 传给 hey thread read。hey bundle view <id> 会列出其中未读线程的 topic_id;hey contact threads <contact_id> 会列出该发件人的所有线程,无论是否已读;邮件被读取后,只有这里会继续列出汇总中的邮件。使用 hey contact bundle|unbundle <contact_id> 更改分组方式。

发送

  • 发送(compose、reply、forward、draft send)会返回新消息的 id 和消息所属会话的 topic_id;使用 hey thread read <topic_id> 读取该会话。
  • delayed: true 表示“撤回发送”仍在暂缓发送;在消息发出之前,HEY 不会将它放入会话中:hey thread read 会显示不含该消息的会话,或者对于由该消息发起的会话返回 not_found。请稍后再次读取,不要误以为发送失败。
  • 如果 HEY 拒绝发送(通常是因为账户达到发送上限),发送会以 not_delivered 失败(退出码 7)。HEY 会将消息保留为草稿,并在错误中以 draft_id 标明;稍后使用 hey draft send <draft_id> 发送。不要重新发送消息,否则会创建第二份草稿。
  • 如果希望任何内容发出前都由他人审核,请在 compose 或 reply 中添加 --draft;返回结果会附带草稿 ID,可用于 hey draft show|edit|send|delete。他人可以在任意 HEY 应用中审核并发送,也可以由你稍后使用 hey draft send 发送。
  • hey bulk-reply:先运行 preview,再运行 send。如果误发了邮件,可以在撤回窗口仍开启时使用 hey bulk-reply undo <delivery_id> 撤回。

编写内容

默认情况下,消息正文、草稿、日志条目、片段和联系人备注都使用 Markdown(无论通过 -m、--content、--note、位置参数内容、stdin 还是 $EDITOR);发送时会将其转换为富文本。剪藏内容、事件备注和时间跟踪备注则是纯文本。每个 Markdown 标志都有对应的 HTML 标志(例如 --message-html、--note-html、--content-html),用于输入原始 HTML;同一对标志不能同时使用。围栏代码块的语言会保留,但仅限 HEY 支持语法高亮的语言(Ruby、Python、JavaScript、TypeScript、Go、Rust、Java、C#、C++、PHP、Swift、HTML 和 CSS);其他语言标记会被丢弃。

日历中的所有内容都是一条记录,每种记录都有自己的命令:hey event、hey todo、hey journal、hey habit、hey timetrack。如果不指定日期,这些命令会读取账户时区以确定今天;指定日期即可跳过读取账户信息。

向整篇内容中添加内容

hey contact note set 和 hey journal write 会替换整条备注或日志条目,不支持追加。若要添加内容,请先读取,再修改,然后写回完整内容。请保留 &&:读取失败时不得继续写入。读取和写入不是原子操作,因此读取后应立即写入。

联系人备注。 当 note_markdown_lossless 为 true 时,note_markdown 包含完整备注;读取操作会检查此标志本身,如果它为 false 则会失败,因此不会写入任何内容:

note=$(hey contact note show 12345 --jq 'if .data.note_markdown_lossless then .data.note_markdown else error("note_markdown would drop part of this note: change note_html with --note-html") end') &&
  printf '%s\n\nMoved to the Lisbon office in March.\n' "$note" | hey contact note set 12345

当它为 false 时,备注中包含 Markdown 无法保留的标记。请改为添加到 HTML 中:

note=$(hey contact note show 12345 --jq '.data.note_html') &&
  hey contact note set 12345 --note-html "$note<p>Moved to the Lisbon office in March.</p>"

日志条目。 处理方式相同,使用 content_markdown_lossless;如果某天没有日志条目,读取也会失败:

entry=$(hey journal read 2026-03-15 --jq 'if .data.content_markdown_lossless then .data.content_markdown else error("content_markdown would drop part of this entry, or there is none: change content with --content-html") end') &&
  printf '%s\n\nBooked the venue for the second day.\n' "$entry" | hey journal write 2026-03-15
entry=$(hey journal read 2026-03-15 --jq '.data.content // error("no journal entry for this day")') &&
  hey journal write 2026-03-15 --content-html "$entry<p>Booked the venue for the second day.</p>"

身份验证

数据命令会使用 HEY 已存储的凭据,并自动刷新即将过期的 OAuth 令牌。无需先执行登录检查,直接运行所需的数据命令即可。

如果数据命令返回退出代码 3,且包含 "code": "auth",或失败并提示 could not read stored credentials,则该进程无法进行身份验证。在 macOS 上使用 Codex 时,沙盒可能会隐藏 HEY CLI 存储在 Keychain 中的凭据。在报告任务受阻之前,请使用执行环境的常规审批流程,在提升沙盒权限的情况下重试一次 hey auth status --json。仅对此只读命令提升权限。如果响应中的 data.authenticated 为 true,请通过单独的一次性命令审批,仅重新运行用户请求的那条确切 hey 命令。如果 data.authenticated 为 false,请报告任务受阻,并告知用户在 Terminal 中运行 hey auth login;不要在无人监督的情况下代用户运行。如果状态命令失败,例如出现 exit status 36 之类的密钥环错误,则问题并非登录所致,hey auth login 也无法解决;请报告任务受阻,转达错误中的 hint,然后停止。

绝不要运行 macOS 的 security 命令读取 Keychain 内容、打印或复制凭据,或将凭据移入文件;绝不要全局禁用沙盒;绝不要将 HEY_NO_KEYRING=1 作为身份验证的变通方法。

通过管道运行的命令、机器输出命令和非 TTY 命令都不会提示登录。当 Agent 执行环境通过 PTY 运行命令时,请设置 HEY_NONINTERACTIVE=1,这样缺少登录信息时会返回相同的可操作身份验证错误,而不会打开交互式提示。

评论

支持 Markdown