Markdown Article Formatter
JimLiu/baoyu-skills
Reformats plain text or Markdown articles with frontmatter, a title, a summary, headings, bold, lists and code blocks, and saves a separate formatted copy.
何时用:仅当用户明确指向企业微信(给企微同事/群发消息、查企微会话)时使用;泛指发消息默认走本地通讯工具,邮件走 wecomcli-email。查询可发消息的聊天会话范围,向单聊/群聊发送文本、Markdown、图片、文件、语音、视频消息。
$ npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Pinvou/pinvou-agent wecomcli-message --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Pinvou/pinvou-agent.git skills-src && mkdir -p .claude/skills && cp -r skills-src/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message .claude/skills/wecomcli-message && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "wecomcli-message" agent skill from https://github.com/Pinvou/pinvou-agent/tree/main/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message into .claude/skills/wecomcli-message/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wecomcli-message", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Pinvou/pinvou-agent/tree/main/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-messageType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Pinvou/pinvou-agent wecomcli-message --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Pinvou/pinvou-agent.git skills-src && mkdir -p .agents/skills && cp -r skills-src/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message .agents/skills/wecomcli-message && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "wecomcli-message" agent skill from https://github.com/Pinvou/pinvou-agent/tree/main/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message into .agents/skills/wecomcli-message/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wecomcli-message", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Pinvou/pinvou-agent wecomcli-message --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Pinvou/pinvou-agent.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message .cursor/skills/wecomcli-message && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "wecomcli-message" agent skill from https://github.com/Pinvou/pinvou-agent/tree/main/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message into .cursor/skills/wecomcli-message/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wecomcli-message", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Pinvou/pinvou-agent.git --path pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Pinvou/pinvou-agent wecomcli-message --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Pinvou/pinvou-agent.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message .gemini/skills/wecomcli-message && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "wecomcli-message" agent skill from https://github.com/Pinvou/pinvou-agent/tree/main/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message into .gemini/skills/wecomcli-message/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wecomcli-message", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Pinvou/pinvou-agent wecomcli-messageInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Pinvou/pinvou-agent.git skills-src && mkdir -p .github/skills && cp -r skills-src/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message .github/skills/wecomcli-message && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "wecomcli-message" agent skill from https://github.com/Pinvou/pinvou-agent/tree/main/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message into .github/skills/wecomcli-message/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wecomcli-message", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Pinvou/pinvou-agent wecomcli-message --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Pinvou/pinvou-agent.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message .opencode/skills/wecomcli-message && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "wecomcli-message" agent skill from https://github.com/Pinvou/pinvou-agent/tree/main/pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message into .opencode/skills/wecomcli-message/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "wecomcli-message", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
wecomcli-message何时用:仅当用户明确指向企业微信(给企微同事/群发消息、查企微会话)时使用;泛指发消息默认走本地通讯工具,邮件走 wecomcli-email。查询可发消息的聊天会话范围,向单聊/群聊发送文本、Markdown、图片、文件、语音、视频消息。
Wecomcli Message is an agent skill from Pinvou/pinvou-agent. 何时用:仅当用户明确指向企业微信(给企微同事/群发消息、查企微会话)时使用;泛指发消息默认走本地通讯工具,邮件走 wecomcli-email。查询可发消息的聊天会话范围,向单聊/群聊发送文本、Markdown、图片、文件、语音、视频消息。
Its SKILL.md is about 1.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Documents & Office, covering Markdown. The repository describes itself as: Open-source desktop AI agent for tools, files, knowledge, workflows, and real deliverables. The licence is MIT.
2 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 76cb1db. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are bash).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Wecomcli Message loads about 1.2k tokens when it runs. Until then it costs about 34 tokens; SKILL.md has 299 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Pinvou/pinvou-agent at commit 76cb1db, republished under its MIT licence (© Pinvou). 299 words, ~1,226 tokens.
.claude/skills/wecomcli-message/SKILL.md (or your agent's skills folder).执行任何
wecom-cli命令前,必须先读取并完成wecomcli-shared技能的公共前置检查。
wecom-cli identity whoami 获取授权人ID,可作为 chat_id 使用,无需调用 sessions list。sessions list 返回结果中 → 告知用户当前只能向最近活跃的会话或授权人发送调用依赖技能前,必须先完整读取对应 SKILL.md。
| 依赖技能 | 触发场景 | 数据流向 |
|---|---|---|
wecomcli-media | 发送图片、文件、语音或视频时只有本地文件路径,没有可直接复用的 media_id | 包含媒体上传接口,如没有已有的 media_id,必须先阅读该技能获取 media_id。media upload 以本地 file_path 上传,type 为可选入参(image/voice/video/file);发送时以上传响应返回的 type 对齐 msg_type |
wecom-cli message aibot sessions list| 字段 | 类型 | 说明 |
|---|---|---|
sessions | array | 会话列表,按最后一条消息时间从新到旧排序,具体数量以实际回包为准 |
sessions[].chat_id | string | 会话 ID |
sessions[].chat_name | string | 群名称或单聊名称 |
sessions[].chat_type | string | single 单聊或 group 群聊 |
sessions[].last_msg_time | string | 最后一条消息时间,格式 YYYY-MM-DD HH:MM:SS |
sessions_count | integer | sessions 数组元素数量 |
chat_id 来源向授权人以外的用户发送消息,调用 wecom-cli message aibot send 前,需要先调用一次 sessions list,然后从本次返回的 sessions[] 中选定目标项,把该项的 chat_id 原样复制到 send.chat_id。
以下值都不能直接作为 send.chat_id:
chat_idwecomcli-contact 返回的 userid这些值最多只能作为匹配线索;最终发送参数必须重新取自本次 sessions list 的匹配项。
sessions[] 中按非空 chat_name 精确匹配;不能精确匹配需要向用户反问确认发送目标,唯一命中时从匹配项复制 chat_id。sessions[] 原始顺序选择用户明确指定的项。sessions[].chat_id 做完全相等校验;命中后仍从匹配项复制 chat_id,不能直接复用用户输入值。匹配结果处理:
sessions list,再用选定对象匹配当次返回值。chat_id 绕过限制。sessions_count=0 时停止发送,告知当前没有可发送的最近会话。chat_id。调用本接口前必须完成以下步骤:
wecom-cli message aibot sessions list获取 chat_id 或 wecom-cli identity whoami 获取授权人ID。sessions[].chat_id。media_id。在目标会话匹配成功前,不上传媒体,也不调用 send。
wecom-cli message aibot send --json '<JSON 参数>'| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
chat_id | string | 是 | 必须取自 wecom-cli identity whoami 或当前发送流程中刚调用的 sessions list 返回的目标 sessions[].chat_id |
msg_type | string | 是 | markdown / image / file / voice / video |
markdown | object | 条件必填 | 仅 msg_type="markdown" 时传 |
image | object | 条件必填 | 仅 msg_type="image" 时传 |
file | object | 条件必填 | 仅 msg_type="file" 时传 |
voice | object | 条件必填 | 仅 msg_type="voice" 时传 |
video | object | 条件必填 | 仅 msg_type="video" 时传 |
每次请求必须且只能携带一个与 msg_type 同名的内容对象。不要传空对象,也不要同时传多个消息对象。
markdown.content 必填,最长 20480 UTF-8 字节。普通文本也按 Markdown 发送。
wecom-cli message aibot send --json '{
"chat_id": "<本次 sessions[].chat_id>",
"msg_type": "markdown",
"markdown": {
"content": "<markdown 消息内容>"
}
}'image.media_id 必填,必须来自媒体上传接口上传后返回 type=image 的结果。
wecom-cli message aibot send --json '{
"chat_id": "<本次 sessions[].chat_id>",
"msg_type": "image",
"image": {
"media_id": "<media_id>"
}
}'file.media_id 必填,必须来自媒体上传接口上传后返回 type=file 的结果;文件名取上传时的原始文件名。
wecom-cli message aibot send --json '{
"chat_id": "<本次 sessions[].chat_id>",
"msg_type": "file",
"file": {
"media_id": "<media_id>"
}
}'voice.media_id 必填,必须来自媒体上传接口上传后返回 type=voice 的结果;源文件仅支持 AMR 格式,不能只改扩展名冒充 AMR。
wecom-cli message aibot send --json '{
"chat_id": "<本次 sessions[].chat_id>",
"msg_type": "voice",
"voice": {
"media_id": "<media_id>"
}
}'| 字段 | 必填 | 说明 |
|---|---|---|
video.media_id | 是 | 来自媒体上传接口上传后返回 type=video 的结果 |
video.title | 否 | 最长 128 UTF-8 字节;省略时使用上传时的原始文件名 |
video.description | 否 | 最长 512 UTF-8 字节;省略时不展示描述 |
wecom-cli message aibot send --json '{
"chat_id": "<本次 sessions[].chat_id>",
"msg_type": "video",
"video": {
"media_id": "<media_id>",
"title": "产品演示",
"description": "本周版本的核心功能演示"
}
}'用户没有提供视频标题或描述时直接省略对应字段,不传空字符串,也不追问非必填字段。
send 前都重新调用 sessions list 或 wecom-cli identity whoami,但连续发送中途上下文发生压缩时重新调用确保 chat_id 正确。chat_id、userid、media_id 都是内部调用值,禁止面向用户展示。wecom-cli。© Pinvou, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message of Pinvou/pinvou-agent.
Open the folder on GitHubat commit 76cb1db
Wecomcli Message next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Wecomcli Message this skillPinvou/pinvou-agent | 2.4k | — | ~1.2k | Automated safety check: Pass | MIT | |
| Markdown Article FormatterJimLiu/baoyu-skills | 26k | 7 repos | ~3.5k | Automated safety check: Pass | MIT | |
| MarkitdownImCa0/just-laws | 781 | 14 repos | ~3.2k | Automated safety check: Notes | MIT | |
| Obsidian MarkdownAtmosphere/atmosphere | 3.8k | 20 repos | ~1.3k | Automated safety check: Pass | Apache-2.0 | |
| Gzh Designisjiamu/gzh-design-skill | 3.9k | 1 repos | ~2.2k | Automated safety check: Pass | AGPL-3.0 | |
| Crosspostingwasp-lang/wasp | 19k | — | ~1.1k | Automated safety check: Pass | MIT |
JimLiu/baoyu-skills
Reformats plain text or Markdown articles with frontmatter, a title, a summary, headings, bold, lists and code blocks, and saves a separate formatted copy.
ImCa0/just-laws
Convert files and office documents to Markdown. An agent skill from ImCa0/just-laws.
Atmosphere/atmosphere
Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax.
isjiamu/gzh-design-skill
微信公众号文章排版引擎,将 Markdown 转换为可直接粘贴到公众号编辑器的 HTML。主题风格从 references/theme-index.md 注册的自定义主题库中选取,自动章节编号、关键词下划线标记、引言卡片、目录导航、代码块、图片/GIF、作者签名。支持 Markdown / Word(.docx) / PDF / 纯文本输入(非 Markdown…
wasp-lang/wasp
Crosspost Wasp blog articles (MDX) to DEV.to and Medium. An agent skill from wasp-lang/wasp.
supabase/supabase
Review Supabase docs changes locally in your supabase/supabase checkout — either an open PR (triage, classify, verify) or your own branch before opening a PR (local self-review).
Pinvou/pinvou-agent
何时用:用户明确要通过命令行操作腾讯会议(tmeet),或 Agent 遇到工具缺失/调用失败/能力不足想反馈平台时。OAuth 登录/登出/状态、会议管理(创建/更新/取消/查询/搜索/受邀者)、录制管理(列表/播放地址/智能纪要/转写/权限申请)、元宝纪要(按关键词/时间搜索、稳态/瞬态详情)、会议报告(参会人/等候室/导出明细/异步任务)、通讯录(仅限会议邀请/呼叫入会前置解析,严禁单独查…
Pinvou/pinvou-agent
何时用:仅当用户明确指定 doc/docx/word/在线文档/office文档或提供 doc.weixin.qq.com/doc/ 链接时使用;泛指「做个文档/写文档/整理成文档」默认走 wecomcli-smartpage 或本地工具,本技能不得抢占。doc 内容操作:新建、导入(.doc/.docx/.txt)、读取、追加、覆盖写入;结构化数据需求改用智能文档/智能表格;公共管理走…
Pinvou/pinvou-agent
【何时用:仅当用户明确指向钉钉/DingTalk(钉钉文档、钉钉日程等)时使用;泛指做文档/表格/待办/审批默认走本地工具,不要误用钉钉】用 dws CLI 管理钉钉:AI表格/AI搜问(找人首选)/目标管理(Agoal)/组织大脑/日历/通讯录/群聊与机器人消息/待办/审批/考勤/日志(日报周报)/DING消息/钉钉文档/云盘/Markdown文件/AI听记/邮箱/在线电子表格(axls)/知…
Pinvou/pinvou-agent
【何时用:仅当用户明确指向飞书/Lark 电子表格;泛指做表格默认走本地工具】创建/操作飞书电子表格:工作表与行列结构、读写单元格(值/公式/样式/批注/图片)、查找替换、批量更新、图表/透视表/条件格式/筛选/迷你图/浮动图片。按名称搜索云空间表格文件改用 lark-drive 的 drive +search。doubao.com 的 /sheets/ URL 也走本 skill。不适用本地…
Pinvou/pinvou-agent
【何时用:仅当用户明确指向飞书/Lark(发到飞书、飞书文档等)时使用;泛指做个文档或PPT或表格或方案默认走本地工具,不要误用飞书】飞书多维表格(Base)操作:建表、字段、记录、视图、统计、公式/lookup、表单、仪表盘、BaseApp 应用模式(页面与组件)、Workspace 目录、workflow、角色权限、模板中心(模板分类/列表/搜索);遇到…
Pinvou/pinvou-agent
【何时用:仅当用户明确指向飞书/Lark(发到飞书、飞书文档等)时使用;泛指做个文档或PPT或表格或方案默认走本地工具,不要误用飞书】飞书日历:管理日程和会议室。查看/搜索日程、创建/更新日程、管理参会人、查询忙闲和推荐时段、预定会议室。不负责:查询视频会议记录(本 skill 只覆盖日程;lark-vc 技能未随包收录,可 CLI 直连,见意图路由)、待办任务(走 lark-task)。
Categories
何时用:仅当用户明确指向企业微信(给企微同事/群发消息、查企微会话)时使用;泛指发消息默认走本地通讯工具,邮件走 wecomcli-email。查询可发消息的聊天会话范围,向单聊/群聊发送文本、Markdown、图片、文件、语音、视频消息。. Wecomcli Message is an agent skill from Pinvou/pinvou-agent.
Wecomcli Message fits situations like: tasks that involve Markdown.
Run `npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a claude-code`. Or copy the skill folder (pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message in Pinvou/pinvou-agent) into .claude/skills/wecomcli-message in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a codex`. Or copy the skill folder (pinvou3-app/src-tauri/resources/common/bundle/wecom-skills/wecomcli-message in Pinvou/pinvou-agent) into .agents/skills/wecomcli-message in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Pinvou/pinvou-agent --skill wecomcli-message -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/wecomcli-message, .gemini/skills/wecomcli-message, .github/skills/wecomcli-message and .opencode/skills/wecomcli-message in your project.
SKILL.md names no scripts, command-line tools or credentials: Wecomcli Message is instructions for the agent only. Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Wecomcli Message is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 1.2k tokens (SKILL.md is roughly 4.9k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Wecomcli Message: Markdown Article Formatter (JimLiu/baoyu-skills, 26k stars), Markitdown (ImCa0/just-laws, 781 stars), Obsidian Markdown (Atmosphere/atmosphere, 3.8k stars) and Gzh Design (isjiamu/gzh-design-skill, 3.9k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Pinvou (a GitHub organization) maintains it in Pinvou/pinvou-agent, which has 2,377 GitHub stars. The repository holds 28 skills in this directory. The repository was last updated on October 8, 2026.
Source: Pinvou/pinvou-agent on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.