关于 send-message
send-message 是通过 MTProto 从个人 Telegram 账号发送消息的技能,涵盖授权检查、主题选择、HTML 格式、长消息拆分及编辑决策。
主要功能
- 01检查 Telegram 会话授权
- 02发送到指定群组主题
- 03使用 Telegram HTML 格式
- 04自动拆分长消息
- 05指导编辑与更正补充
适用场景
- 01在合适的群组主题发布更新
- 02发送含代码或标题的格式化消息
- 03将长内容拆分为连续消息
- 04避免静默改写已读消息
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill send-message安装后在 Claude Code 中输入/send-message确认已加载。
详细介绍
发送 Telegram 消息
通过 MTProto 从你的个人 Telegram 账号(而非机器人)发送消息。
自进化技能:此技能会在使用过程中不断改进。如果说明有误、参数已变更,或需要采用变通方案,请立即修复此文件,不要拖延。仅在遇到真实、可复现的问题时才更新。
发送前检查
发送前,请确认会话已授权(不只是确认文件存在):
bun "$SCRIPT" check-auth
如果状态为 EXPIRED,请先运行 /tlg:setup(使用 3 步非交互式授权模式)。
超级群优先方法
Bruntwork 群组(-1003958083153)是一个带有话题的超级群。发送到此群组的所有消息都必须指定特定话题,绝不能直接发送到不带话题的超级群。
超级群优于普通聊天的原因:
- 服务器全局消息 ID。 每位成员看到的每条消息都有相同的
id=N。双方的 Claude Code 都能以相同方式解析引用,无需查看者限定,也不会产生跨边界歧义。 - 话题命名空间。 政策不会淹没在每日签到消息中。每个主题都有独立、可搜索的线程和置顶消息。
- AI Agent 可寻址性。 Claude Code 可以通过
reply_to_msg_id针对特定话题读取或发送消息,从而实现精确路由,例如“将此错误报告发送到 Bug Reports”或“在 Policies 中搜索关于例外条款的决策”。 - 表情符号回应可用作确认信号。 可通过
message.reactions.results以编程方式读取回应,从而轻松检查确认状态,无需对方回复文字。
话题选择规范: 撰写消息时,请从下方的话题注册表中选择最具体的话题。仅在没有更合适话题时才使用 General。绝不要将同一条消息发送到多个话题。
引用规范: 裸写的 id=N 引用对所有成员的解析结果都相同。引用之前的消息时,请注明其 ID。双方的 Claude Code 都可以通过 client.get_messages(supergroup_id, ids=N) 自行查找。
通过 tg-cli.ts 发送到话题: 使用 --reply-to 标志,并指定该话题的 root_msg_id。root_msg_id 的值请参见下方的话题注册表部分。
bun "$SCRIPT" send --html --reply-to 5 -1003958083153 "<b>Policy update</b> ..."
长消息自动拆分
Telegram 每条消息的硬性限制为解析后 4096 个字符。tg-cli.ts 的 send 和 draft 都会自动拆分超过约 3900 个纯文本字符的消息,生成多个依次发送的消息,同时保留 HTML 格式和章节结构。
拆分算法:在能够满足所有消息块长度限制的前提下,选择最细粒度的安全边界进行拆分:
\n\n━━━━━━━━━━━━━━\n\n(主要章节分隔符,优先使用)\n━━━━━━━━━━━━━━\n(章节分隔符)\n\n(段落分隔符)\n(换行符)- 按字符硬拆分(最后手段——会打印警告,且可能拆断标签)
每个续发消息块前都会添加 <i>(Part N/M)</i> 标题,让收件人清楚地看到消息顺序。所有部分都使用相同的 --reply-to 目标,确保多段消息保留在同一个话题线程中。
现在无需再手动拆分消息。 将完整 HTML 编写为一个字符串并传给 send,拆分器会自动处理。
按长度规划内容的建议:尽量让消息能够放在单条消息中(≤ 3900 个纯文本字符),因为拆分后会因部分标题而增加视觉负担。如果消息内容本身较长(例如置顶参考资料),就让拆分器处理。使用 ━━━━━━━━━━━━━━ 分隔章节,以便在逻辑章节之间整齐拆分。
用法:tg-cli.ts(会话有效时)
拿不准时,使用
--html。 如果你的消息包含以下任何内容:<b>、<i>、<code>、<pre>、<a href>、粗体标题、行内代码或 Markdown 风格的**粗体**/`代码`,你必须传入--html(并先将 Markdown 转换为 HTML 标签),或者去掉这些修饰。发送 Telegram 风格的 Markdown 时,如果不使用--html,收件人看到的会是原样的星号和反引号。对于包含标题、分隔符和代码片段的多段消息,始终使用--html。如果已经发送了格式混乱的消息,可按以下模式补救:发送一条以
Correction — earlier message rendered as raw text, corrected version below:开头的后续消息,然后附上正确使用 HTML 格式的内容。如果消息已被阅读,切勿悄悄编辑(见下文“编辑规范”)。
/usr/bin/env bash << 'SEND_EOF'
ROOT="$(cc-plugin-root tlg)"
SCRIPT="$ROOT/scripts/tg-cli.ts"
# Default: plain text (use only for single-line unformatted messages)
bun "$SCRIPT" send @username "Hello"
# HTML formatting — the recommended default for any structured message
bun "$SCRIPT" send --html -1003958083153 "<b>Bold header</b>
Body with <code>inline code</code> and <a href='https://example.com'>a link</a>."
# By chat ID (groups use negative IDs)
bun "$SCRIPT" send -1003958083153 "Hello group"
# Specific profile
bun "$SCRIPT" -p personal send @username "Hello"
# Edit a message by ID
bun "$SCRIPT" edit -1003958083153 12345 "<b>Updated text</b>"
# Delete a message by ID
bun "$SCRIPT" delete -1003958083153 12345
SEND_EOF
较长的 HTML 消息:tg-cli.ts send --html 会在达到 3900 个纯文本字符的阈值时自动拆分。将完整 HTML 写成一个字符串,让拆分器处理。参见上文“长消息的自动拆分”。
编辑规范——未读与已读
核心原则:只有当你确信收件人尚未阅读消息时,才悄悄编辑。有人看过消息后再编辑,可能会造成错误记录并引起困惑(他们记得原文,但聊天中现在显示的是不同内容)。
| 情况 | 操作 |
|---|---|
| 你在不到 30 秒前于活跃的异步聊天中发送了消息,且期间没有人操作 Telegram | 可以安全编辑——可自由迭代 |
| 你刚发送的消息有错别字或事实错误,且收件人尚未回复 | 可以安全编辑——他们很可能还没看过 |
| 收件人已回复你的消息 | 切勿悄悄编辑——发送补充 |
| 收件人已读消息但尚未回复(你看到已读回执,或他们的输入状态提示出现后又消失) | 切勿悄悄编辑——发送补充 |
| 你不确定收件人是否已读 | 默认发送补充——这样更不容易造成困惑 |
| 聊天中的其他人已引用该消息 | 切勿编辑——引用内容现在已成为过时上下文;应改为发送补充 |
补充消息模式(编辑不安全时):
Correction on my previous message: <specific change>
或
Update to what I said above: <new info that supersedes>
补充消息应当自成一体,让回看聊天记录的读者无需交叉参照也能理解。
为何这很重要:悄悄编辑已读消息是聊天系统中最令人困惑的用户体验反模式之一。收件人记得“特里告诉我 X”,现在却看到“X'”,于是会怀疑是自己记错了,还是有人在操纵他们。编辑应当在对方看到消息之前使用,而不是用来篡改历史记录。
如何判断消息是否已读:Telegram 的 MTProto 会通过 messages.readHistoryOutbox 更新,在一对一和小型群聊中提供已读回执,但在大型群聊中并不可靠。最稳妥的判断方法是结合时间和活跃情况:如果已过去约 60 秒以上,和/或收件人曾在聊天中活跃,就假设他们已经看过消息。
Telegram HTML 格式参考
GramJS 使用 HTML,而非 Markdown:
| 标签 | 渲染效果 |
|---|---|
<b>text</b> | 粗体 |
<i>text</i> | 斜体 |
<u>text</u> | 下划线 |
<s>text</s> | |
<code>text</code> | Inline code |
<pre>text</pre> | 代码块 |
<a href="url">text</a> | 超链接 |
<tg-spoiler>text</tg-spoiler> | 剧透内容 |
水平分隔线规则(强制约定)
在较长消息的各个部分之间使用 ━(U+2501)作为水平分隔线。
长度规则:建议使用 14 个字符,绝对上限为 22 个字符。
- 建议长度:
━━━━━━━━━━━━━━(14 个━) - 可接受上限:
━━━━━━━━━━━━━━━━━━━━━━(22 个━,= 14 + 8) - 切勿超过 22 个字符——较长的分隔线在移动客户端上看起来不平衡,还会使正文内容超出屏幕。
原因:Telegram 移动客户端会重新排布正文,但不会换行显示由制表符画线字符组成的分隔线。在窄屏手机上,28 个字符的分隔线会导致水平滚动;14 个字符的分隔线可在所有视口中清晰显示,并仍能起到明确的分隔作用。如果需要更醒目的视觉效果,请在分隔线前使用标题(<b>...</b>),而不是加长分隔线。
支持表情符号,但用户可能更喜欢不带表情符号的装饰——请改用 <pre> 块和制表符画线字符。
配置文件
| 配置文件 | 账号 | 用户 ID |
|---|---|---|
work (default) | @ExampleOpsAccount | |
personal | @personal_account |
已知群聊 ID
| 群组 | 聊天 ID | 类型 |
|---|---|---|
| Terry & MD (Bruntwork) | -1003958083153 | 超级群组 |
| Terry & MD (Bruntwork) | -1003958083153 | 旧版基础群聊(2026-04-16 之前,旧消息只读) |
话题注册表(Bruntwork 超级群组)
若要向特定话题发送消息,请在 send_message() 中传入 reply_to=<root_msg_id>,或在 tg-cli.ts 中使用 --reply-to。
| 话题 | root_msg_id | 范围 |
|---|---|---|
| 常规 | 1 | 通用事项、快速提问 |
| 任务与交付物 | 2 | 任务定义、PR 审查、Block 签到 |
| 日常运营 | 3 | 入职/离职、轮班状态 |
| 入职与访问 | 4 | 仓库访问权限、SSH/Tailscale、工具配置 |
| 政策与标准 | 5 | cc-skills 例外条款、约定、纪律 |
| Bug 报告与事故 | 6 | 合并冲突、钩子 Bug、流水线故障 |
| 工具设置与配置 | 7 | example-service、example-app、example-pipeline |
| 知识库与学习 | 8 | 知识库页面、研究材料、技能参考 |
| 人力资源与排班 | 9 | 轮班时长、Bruntwork 协调 |
| 会话监控 | 185 | Claude Code 会话实时摘要(CC Nasim Bot) |
反模式(绝不可这样做)
| 反模式 | 失败原因 |
|---|---|
未先检查身份验证就运行 bun "$SCRIPT" | 如果会话已过期,身份验证会失败 |
| 预检时只检查会话文件是否存在 | 会话文件可能存在但已过期——必须使用 check-auth 检查 |
| 使用纯文本发送格式化消息 | GramJS 使用 HTML,而不是 Markdown。使用 --html 标志进行格式化 |
错误处理
| 错误 | 原因 | 修复 |
|---|---|---|
Unknown profile | -p 值无效 | 使用 work 或 personal |
Cannot find any entity | 用户名或 ID 无效 | 使用 dialogs 命令验证,或使用 find-user 解析 |
message cannot be empty | 传入了空字符串 | 提供消息文本 |
Session expired | 会话不再有效 | 运行 /tlg:setup 以非交互方式重新进行身份验证 |
执行后检查
此技能完成后,在结束前检查:
- 命令是否成功?——如果没有,请修复导致失败的说明或错误表。
- 参数或输出是否有变化?——如果 tg-cli.ts 的接口发生变化,请更新 Usage 示例和 Parameters 表,使其保持一致。
- 是否需要变通方案?——如果你不得不临时变通(使用不同的标志、增加额外步骤),请更新此 SKILL.md,避免下次调用时还需要相同的变通方案。
仅在问题确实存在且可复现时更新,不要基于推测更新。