Medium Blog Post Creator

通过GitHub Pages将博客文章导入Medium,无需API密钥。

已扫描
适合谁
技术博主、自由写作者
不适合谁
需要私密发布内容的用户、无法访问GitHub或Medium账户的人
国内可用性
需网络配置。可能需要网络配置或第三方服务可访问。
安装难度
新手友好(★☆☆)。基于终端操作、依赖、API Key 和本地环境要求的初步判断。

安装与下载

openclaw skills install @ylnhari/medium-blog-post-creator

Skill 说明

命令、参数、文件名以原文为准

Medium 博客文章创建器

无需 API 密钥即可将格式完整的博客文章发布到 Medium

2025 年 1 月 1 日起,Medium 停止发放新的集成令牌。本技能通过唯一仍稳定的导入路径绕过此限制:编写一个受限的 HTML 文章,将其作为公开 URL 部署至 GitHub Pages,再由 Medium 自身的 URL 导入工具抓取并转换为可编辑区块。

该流程为 端到端代理驱动 —— 无需记忆外部仓库或本地路径。它会向用户询问所需信息,在用户的 GitHub 账户中搭建静态博客仓库,将每篇博文部署至 GitHub Pages,并自动操控浏览器完成 Medium 的导入流程,直至草稿准备就绪以供审阅。始终在 草稿状态 停止 —— 永不自动发布。

参考资料

当工作流指向这些文件时,请加载它们:

  • references/html-standards.md:Medium 导入器接受的 HTML 子集。撰写文章前请务必阅读。
  • references/configuration.md:持久化配置的模式、解析规则和重置方式(用于第 0 步)。
  • assets/post-template.html:实现所有 HTML 规则的可填写文章模板。
  • assets/meta.template.json:每篇文章的元数据侧边文件结构。

使用场景

当用户说出以下任意语句时触发:

  • “写一篇关于 X 的博客文章”
  • “创建一篇关于 X 的 Medium 文章”
  • “将关于 X 的内容发布为 Medium 草稿”
  • “聊聊 X”
  • “将此内容跨发至 Medium”

或提供内容(Markdown、大纲、笔记),并提及 Medium。

本技能不做的事

  • 不自动发布。始终停在 草稿 状态,等待人工审阅。
  • 无需 Medium API 密钥。使用公开的 URL 导入接口。
  • 无需预先存在的博客仓库。从零开始搭建。
  • 不假设操作系统。路径基于用户输入和当前工作目录;支持 Windows、macOS 和 Linux。

先决条件(从用户处收集)

必需项原因
GitHub 账号用于托管静态博客仓库并通过 GitHub Pages 提供服务
Medium 账号文章导入的目标位置
**gh CLI**(已认证)代理在 shell 中创建/克隆/推送仓库
**git**标准仓库操作
**OpenClaw browser 工具**(已登录 Medium)控制 Medium 的 URL 导入界面

ghgit 在 frontmatter 的 requires.bins 中声明,以便 OpenClaw 检测。但仍需在运行时验证:gh auth status 必须显示已认证用户,且浏览器工具必须已登录 Medium。若任一先决条件缺失,立即停止并告知用户需安装或登录的内容。不得使用占位符继续。

用户输入(一次性收集,工作开始前)

请一次性向用户询问以下内容;若部分信息缺失,使用默认值,并明确说明你的假设后再继续:

  1. 主题 / 标题(必填)。
  2. 目标受众technical / general / beginner。默认:technical
  3. 语气风格casual / formal / tutorial。默认:casual
  4. 文章长度short(约 500 字) / medium(约 1000 字) / long(约 2000 字以上)。默认:medium
  5. 必须涵盖的关键章节或要点列表
  6. 用于托管博客仓库的 GitHub 用户名或组织名(必填)。示例:octocat
  7. 仓库名称。默认建议:blog — 一个普通项目仓库,通过 https://<username>.github.io/blog/ 访问。

(进阶用法:将仓库命名为 <username>.github.io 可使博客位于账户根目录 https://<username>.github.io/,但会占用唯一的用户站点,因此大多数人仍保留 blog 名称。)

  1. 本地工作目录,用于克隆仓库。默认:当前工作目录。
  2. Medium 标签(2–5 个简短关键词)。
  3. 可选:封面图片 URL。若未提供,将自动选择一张相关且免费授权的 Unsplash 图片。

工作流程

共 11 步(第 0 步至第 10 步)。即使首次运行也不可跳过第 0 步。

第 0 步 — 加载或初始化持久化配置

加载每安装实例的配置($MEDIUM_BLOG_CONFIG,否则为每用户配置目录),并检查是否已克隆博客仓库,若有,则读取其本地标记文件(<repo-local-path>/.medium-skill-config.json)。完整模式与规则详见 references/configuration.md。随后:

  • **若全局配置中设置了 last_repo(即命名了仓库)**:复用该仓库。跳过所有设置问题,直接进入第 2 步,确保本地克隆存在(新克隆会携带标记)。<repo-local-path> = <default_working_dir>/<github_repo>
  • **若标记文件可读但 last_repo 未设置**(例如代理已在博客仓库内):采用标记中的仓库,并保存 last_repo —— 不重新提问。
  • **首次在本机运行(无 last_repo,无有效标记)**:询问上述全部输入;第 2 步将创建仓库,写入标记,并将 last_repo 保存至全局配置,以便后续运行跳过设置。
  • 临时覆盖:若用户本次指定不同仓库,仅在此调用中使用该仓库;不修改 last_repo

第 1 步 — 确认先决条件

在代理的 shell 中验证:gh --versiongh auth status(需已认证)、git --version,以及 OpenClaw browser 工具是否可达。任一检查失败,立即停止并报告具体缺失项。

第 2 步 — 搭建博客仓库

构建一个 最小化的静态网站:仅包含一个列出文章的页面,每篇文章独立存放于文件夹中。不使用框架,无构建步骤 —— 仅使用原生 HTML、CSS 和 JSON 索引文件。<repo-local-path> 是克隆仓库的本地路径(通常为 <default_working_dir>/<github_repo>)。

**确定 <pages-base-url>**(用于每篇文章的 URL 及标记文件中的 pages_url)。GitHub 为用户/组织站点和项目站点提供不同路径,因此需一次性计算并重复使用:

  • <github_repo> 等于 <github_owner>.github.io(即 用户/组织站点),则基础地址为 https://<github_owner>.github.io/
  • 否则(即 项目站点),基础地址为 https://<github_owner>.github.io/<github_repo>/

Keep结尾斜杠。文章将位于

<pages-base-url>posts/<YYYY-MM-DD>-<slug>/

切勿无条件手动构建 https://<owner>.github.io/<repo>/... —— 对于 owner.github.io 类型的仓库,这会导致错误的双重路径。

**如果仓库已知(last_repo 已设置,或存在标记文件):**

该仓库已存在,且在初始设置时已启用 Pages。跳过创建和启用 Pages 的步骤;只需确保本地克隆存在且为最新状态:

mkdir -p "<default_working_dir>"
if [ ! -d "<repo-local-path>" ]; then
  gh repo clone <github_owner>/<github_repo> "<repo-local-path>"
else
  cd "<repo-local-path>" && git pull --rebase origin <branch>
fi

如果尚未知道任何仓库(全新设置):

  1. 创建并克隆仓库(从 <default_working_dir> 运行,使克隆结果落在 <repo-local-path>):
   mkdir -p "<default_working_dir>"
   cd "<default_working_dir>"
   gh repo create <github_owner>/<github_repo> \
     --public \
     --description "Static blog for Medium cross-posting" \
     --clone \
     --add-readme
   # 现在克隆到 <default_working_dir>/<github_repo> = <repo-local-path>
  1. 如果仓库已在 GitHub 上存在但本地克隆缺失,回退使用 gh repo clone <github_owner>/<github_repo> "<repo-local-path>"
  1. 写入每仓库标记文件(格式见 references/configuration.md):
   # 在 Unix 系统(bash)
   printf '%s\n' '{' \
     '  "schema_version": 1,' \
     "  \"github_owner\": \"<github_owner>\"," \
     "  \"github_repo\": \"<github_repo>\"," \
     "  \"pages_url\": \"<pages-base-url>\"," \
     "  \"default_author\": \"<github_owner>\"," \
     "  \"branch\": \"<branch>\"" \
     '}' > "<repo-local-path>/.medium-skill-config.json"
   # 在 Windows 系统(PowerShell)
   @{
     schema_version = 1
     github_owner    = "<github_owner>"
     github_repo     = "<github_repo>"
     pages_url       = "<pages-base-url>"
     default_author  = "<github_owner>"
     branch          = "<branch>"
   } | ConvertTo-Json | Set-Content "<repo-local-path>\.medium-skill-config.json"
  1. 在仓库根目录创建一个空的 .nojekyll 文件,以确保 GitHub Pages 直接服务 HTML(不进行 Jekyll 处理),然后将其与标记文件一起提交:
   cd "<repo-local-path>"
   touch .nojekyll          # Windows PowerShell: New-Item -ItemType File .nojekyll
   git add .nojekyll .medium-skill-config.json
   git commit -m "chore: mark repo as managed by medium-blog-post-creator + add .nojekyll"
   git push origin <branch>
  1. 启用 GitHub Pages(在撰写任何文章前执行):
  • 用户/组织站点<github_repo> == <github_owner>.github.io):Pages 会自动在域名根路径启用。无需额外操作。
  • 项目站点(其他名称):通过 API 启用 Pages。此操作是幂等的——返回 409 表示已启用,属于正常情况:
     gh api -X POST "repos/<github_owner>/<github_repo>/pages" \
       --input - <<'JSON' || true
     {"source":{"branch":"<branch>","path":"/"}}
     JSON

如果调用因任何原因失败(非“已启用”错误),请引导用户手动在以下地址启用 Pages:

https://github.com/<github_owner>/<github_repo>/settings/pages

(来源:部署源<branch> / /(根目录)),并在确认后继续。

  1. 将仓库保存到安装级配置,以便后续运行可复用而无需再次询问:将 last_repo(包含 github_ownergithub_repopages_url = <pages-base-url>branch)写入安装级配置文件。格式见 references/configuration.md

第三步 —— 创建文章 HTML 文件

**请先阅读 references/html-standards.md**,然后基于 assets/post-template.html 编写文章,输出至:

<repo-local-path>/posts/<YYYY-MM-DD>-<slug>/index.html

<slug> 由标题生成:全小写,仅允许连字符,最多 60 个字符(例如:running-llms-locally)。正文应包含:

  • 开头引子;
  • 3–6 个 <h2> 小节;
  • 相关代码示例;
  • 至少一张 Unsplash 图片;
  • 加粗/斜体强调;
  • 一个 <blockquote>
  • 结尾行动号召。

禁止虚构事实、填充内容或 LLM 虚假陈述。

第四步 —— 创建元数据侧车文件

根据 assets/meta.template.json 写入 <repo-local-path>/posts/<YYYY-MM-DD>-<slug>/meta.json

{
  "title": "完整文章标题",
  "date": "YYYY-MM-DD",
  "author": "<github-用户名或组织>",
  "description": "1–2 句摘要,最多 200 字符",
  "tags": ["标签1", "标签2", "标签3"],
  "status": "draft",
  "medium_url": null,
  "cover_image": "https://images.unsplash.com/photo-...?w=1200&q=80"
}

medium_url 在第 8 步填写,以实现端到端追踪。

第五步 —— 更新文章索引

仓库维护一个顶层的 posts/index.json(按时间倒序排列):

  1. 读取 posts/index.json;若不存在,创建为空数组 []
  2. 在开头插入新条目。不要重新排序已有条目。
  3. 写回文件。

条目结构如下:

{
  "slug": "YYYY-MM-DD-slug",
  "title": "完整文章标题",
  "date": "YYYY-MM-DD",
  "description": "1–2 句摘要,最多 200 字符",
  "tags": ["标签1", "标签2"],
  "cover_image": "https://images.unsplash.com/photo-...?w=1200&q=80",
  "status": "draft",
  "medium_url": null
}

第六步 —— 提交并推送

cd "<repo-local-path>"
git add posts/<YYYY-MM-DD>-<slug>/ posts/index.json
git commit -m "feat(posts): add \"<POST TITLE>\" [<YYYY-MM-DD>]"
git push origin <branch>

如果推送因认证错误失败,请提示用户运行 gh auth login 并重试(最多尝试 2 次),随后报告错误并停止。

第七步 —— 等待 GitHub Pages 部署完成

Pages 已在第二步中启用,因此本步骤仅需等待新提交上线。

根据第二步中解析的 <pages-base-url> 构建文章 URL —— 切勿手动拼接路径。

Medium 博客文章创建器

概述

本技能用于将博客文章从 GitHub Pages 部署到 Medium 平台。整个流程包括:生成文章、等待页面可访问、通过浏览器导入到 Medium、更新元数据并报告结果。


步骤 1 — 确保已安装并配置 gh 命令行工具

请确认已安装 [GitHub CLI](https://cli.github.com)(gh),并完成身份验证:

gh auth status

如果未认证,请运行:

gh auth login

步骤 2 — 创建或克隆目标仓库

若仓库不存在,尝试创建它;否则直接克隆现有仓库。

注意:若创建失败(如仓库已存在),请自动切换为克隆模式。


步骤 3 — 提交文章内容至仓库

将文章文件(如 posts/YYYY-MM-DD-slug/ 目录)添加到 Git,并提交:

git add posts/<YYYY-MM-DD>-<slug>/
git commit -m "feat(posts): add new blog post <POST TITLE>"
git push origin <branch>

步骤 4 — 等待 GitHub Pages 部署完成

等待页面部署生效。使用以下脚本轮询检查是否返回 HTTP 200。

PowerShell 7+(Windows、macOS、Linux)

$url = "<pages-base-url>posts/<YYYY-MM-DD>-<slug>/"
$deadline = (Get-Date).AddMinutes(3)
while ((Get-Date) -lt $deadline) {
  try {
    $code = (Invoke-WebRequest -Uri $url -UseBasicParsing -MaximumRedirection 5 -ErrorAction Stop).StatusCode
    if ($code -eq 200) { exit 0 }
  } catch {
    $code = 404
  }
  if ($code -eq 200) { exit 0 }
  Start-Sleep -Seconds 15
}
exit 1

macOS / Linux

deadline=$(( $(date +%s) + 180 ))
url="<pages-base-url>posts/<YYYY-MM-DD>-<slug>/"
while [ "$(date +%s)" -lt "$deadline" ]; do
  code=$(curl -fsS -o /dev/null -w "%{http_code}" "$url" 2>/dev/null || echo 000)
  if [ "$code" = "200" ]; then exit 0; fi
  sleep 15
done
exit 1

⚠️ 若超时(仍返回 404),请引导用户前往仓库的 Actions 页面(https://github.com/<github_owner>/<github_repo>/actions)查看构建状态,并重新尝试。

**在 URL 返回 200 之前,不得进入下一步。**


步骤 8 — 通过浏览器将文章导入 Medium

使用 OpenClaw 的 browser 工具操作 Medium 的导入功能。

  1. 打开 https://medium.com/p/import,等待页面完全加载。
  2. 在 URL 输入框中粘贴 <pages-base-url>posts/<YYYY-MM-DD>-<slug>/

(注意:必须包含末尾斜杠 —— Medium 导入器对路径格式敏感)。

  1. 点击 Import
  2. 等待提示“Imported the story”等成功信息。
  3. 点击 See your storyOpen draft,进入草稿编辑器页面:

https://medium.com/p/<draft-id>/edit

  1. 不要点击 Publish,保持为草稿状态。
  2. 复制该草稿编辑器的 URL。

标签处理规则:

  • 如果用户提供了标签,尝试逐个添加。
  • 若某个标签被 Medium UI 拒绝,跳过该标签并继续。
  • 不得重复尝试超过两次;一旦失败即跳过。

步骤 9 — 更新元数据以关联 Medium 草稿链接

  1. posts/<YYYY-MM-DD>-<slug>/meta.json 中的 medium_url 字段设置为草稿编辑器 URL。
  2. 同样更新 posts/index.json 中对应文章的 medium_url
  3. 提交更改:
git add posts/<YYYY-MM-DD>-<slug>/meta.json posts/index.json
git commit -m "chore(posts): link medium draft for \"<POST TITLE>\""
git push origin <branch>

步骤 10 — 向用户报告结果

✅ Post created: "<TITLE>"
📄 GitHub Pages: <pages-base-url>posts/<YYYY-MM-DD>-<slug>/
📝 Medium draft: <draft-editor-url>

The draft is ready for your review. Open the Medium link, make any edits, and
click Publish when you're happy with it.

✅ 成功消息仅在所有步骤正常完成后输出。

❌ 若任一步骤失败,请明确指出具体步骤、错误详情及下一步操作。禁止虚构成功提示。


错误恢复指南

问题解决方法
gh 未安装请用户安装:https://cli.github.com
gh auth status 显示未认证运行 gh auth login
仓库创建失败(已存在)改为克隆已有仓库
Git 推送因权限失败运行 gh auth login 后重试(最多 2 次)
GitHub Pages 返回 404等待 60 秒后重试。若 3 分钟内仍失败,请检查 Actions 页
Medium 导入内容为空确保页面是静态 HTML,先在浏览器中打开 Pages 地址验证
Medium 导入静默失败确认 Pages 地址返回 HTTP 200 且包含末尾斜杠
posts/index.json 出现合并冲突执行 git pull --rebase origin <branch>,然后重新添加变更
浏览器在 Medium 页面超时关闭标签页,新开一个,重新执行导航步骤
Medium UI 无法添加某标签跳过该标签,继续处理其他标签。不进行循环重试

安全与隐私说明

  • 文章在导入 Medium 前会公开发布于 GitHub Pages —— 由于 Medium 导入器要求可公开访问的 URL,这是设计使然。请勿使用此技能处理包含机密信息或用户不愿公开的内容。
  • 本技能不会存储任何凭据。认证由 gh auth login 和用户当前浏览器会话负责。
  • 本技能不调用任何第三方 API,仅访问用户自己的 GitHub 仓库和 Medium 的公开导入接口。

使用频率限制

Medium 对每日发布有配额限制(截至 2026 年初:每天最多 2 篇文章 + 100 条回复)。

本技能仅生成草稿,因此不会触发发布限制。但用户应避免每天通过本技能自动发布超过 2 篇文章。

Y
@ylnhari

已收录 1 个 Skill

相关推荐