cloudinary-image-host
将本地图片上传到 Cloudinary,获取永久 HTTP 链接,用于替换文章中的本地图片引用。 支持单张图片上传、从文章提取图片、目录扫描三种模式,自动替换图片引用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
将本地图片上传到 Cloudinary,获取永久 HTTP 链接,用于替换文章中的本地图片引用。 支持单张图片上传、从文章提取图片、目录扫描三种模式,自动替换图片引用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
将 Markdown 内容转换为微信公众号兼容的 HTML 格式。 支持内联 CSS 样式、多种主题(airbnb/apple/binance/claude/coinbase/mastercard/notion/opencode.ai/pinterest/shopify/spacex/stripe/vercel)、智能配图和代码高亮。 同时支持对现有 HTML 进行排版优化(统一样式 + 微信兼容性修复)。 可自动分析内容选择合适的模板和主题,支持 Unsplash API 获取配图。
将 HTML 富文本文章发布到微信公众号草稿箱。 支持多种封面图片获取方式(自动提取/Unsplash 搜索/AI 生成/指定 URL),自动处理封面上传并获取 media_id。
抓取微信公众号文章并转换为 Markdown 格式。 支持模拟微信 iPhone 客户端请求头绕过反爬,自动重试机制,提取标题/作者/发布时间/正文内容。 支持 CLI 和 Web 界面使用。
| name | cloudinary-image-host |
| description | 将本地图片上传到 Cloudinary,获取永久 HTTP 链接,用于替换文章中的本地图片引用。 支持单张图片上传、从文章提取图片、目录扫描三种模式,自动替换图片引用。 |
| allowed-tools | ["Read","Write","Edit","Bash","Glob","Grep"] |
| metadata | {"trigger":"上传本地图片到 Cloudinary,获取永久链接","category":"image-hosting","version":"1.0.0"} |
将本地图片上传到 Cloudinary,获取永久 HTTP 链接,用于替换文章中的本地图片引用。
为 markdowns/ 和 contents/ 目录下的本地图片生成永久可访问的 Cloudinary 链接。主要用途:
| 模式 | 参数 | 必填 | 说明 |
|---|---|---|---|
| 单张图片 | image | 是 | 直接指定图片文件路径 |
| 文章提取 | article | 是 | 指定 Markdown/HTML 文件,提取其中的本地图片 |
| 目录扫描 | directory | 是 | 扫描目录,列出所有本地图片供选择 |
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
replace | boolean | 否 | 是否自动替换原文件中的图片引用,默认 false |
backup | boolean | 否 | 替换时是否创建备份,默认 true |
output | string | 否 | 输出文件路径(仅替换模式有效) |
dry-run | boolean | 否 | 试运行模式,仅扫描不上传,默认 false |
max-uploads | number | 否 | 最大上传数量,防止超限,默认 10 |
folder | string | 否 | Cloudinary 中的文件夹路径,默认 deeptalk/articles |
# 模式1:上传单张图片
使用 cloudinary-image-host 技能 --image "./contents/images/ev-battery.png"
# 模式2:从文章提取图片
使用 cloudinary-image-host 技能 --article "./markdowns/春节后新能源汽车观察.md"
# 模式3:扫描目录
使用 cloudinary-image-host 技能 --directory "./contents/images/"
| 变量名 | 必填 | 说明 |
|---|---|---|
CLOUDINARY_CLOUD_NAME | 是 | Cloudinary Cloud Name |
CLOUDINARY_API_KEY | 是 | Cloudinary API Key |
CLOUDINARY_API_SECRET | 是 | Cloudinary API Secret |
获取 API 凭证:
免费套餐限制:
{
"success": true,
"uploads": [
{
"localPath": "./contents/images/ev-battery.png",
"cloudinaryUrl": "https://res.cloudinary.com/{cloud_name}/image/upload/v1234567890/deeptalk/articles/ev-battery.png",
"secureUrl": "https://res.cloudinary.com/{cloud_name}/image/upload/v1234567890/deeptalk/articles/ev-battery.png",
"publicId": "deeptalk/articles/ev-battery",
"format": "png",
"width": 1200,
"height": 800,
"bytes": 123456,
"createdAt": "2024-01-01T12:00:00Z"
}
],
"replacements": [
{
"file": "./markdowns/春节后新能源汽车观察.md",
"original": "",
"replaced": ""
}
],
"stats": {
"totalUploaded": 1,
"totalReplaced": 1,
"totalBytes": 123456
}
}
如果启用替换模式,会生成:
原文件.backup.md)cloudinary-mapping.json(图片映射关系)模式A:单张图片
模式B:文章提取
<img src="./path/to/image.png">模式C:目录扫描
对于每张选中的图片:
API 验证
CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET 环境变量图片准备
上传图片
POST https://api.cloudinary.com/v1_1/{cloud_name}/image/upload
Content-Type: multipart/form-data
file=@image.png
api_key={api_key}
timestamp={timestamp}
signature={signature}
folder=deeptalk/articles
处理响应
配额管理
如果启用 replace 参数:
backup) 为 src="./path" 为 src="cloudinary-url"cloudinary-mapping.json控制台输出
文件输出
| 错误类型 | 原因 | 处理方式 |
|---|---|---|
| API Key 无效 | 环境变量未设置或无效 | 提示用户设置正确的 API 凭证 |
| 图片文件不存在 | 文件路径错误 | 跳过该图片,继续处理其他 |
| 图片格式不支持 | 非标准图片格式 | 跳过该图片,列出支持的格式 |
| 文件大小超限 | Cloudinary 文件大小限制 | 提示用户压缩图片 |
| API 配额用尽 | 达到每月限制 | 停止上传,显示剩余时间 |
| 网络错误 | 连接超时或中断 | 重试 3 次,然后跳过 |
使用 cloudinary-image-host 技能 --image "./contents/images/market-dashboard.png"
输出:
✅ 图片上传成功!
📁 本地文件: ./contents/images/market-dashboard.png
🔗 Cloudinary URL: https://res.cloudinary.com/{cloud_name}/image/upload/v1234567890/deeptalk/articles/market-dashboard.png
📐 尺寸: 1200x800
📦 大小: 123.5 KB
📊 配额使用: 1/25 credits (本月)
使用 cloudinary-image-host 技能 \
--article "./markdowns/春节后新能源汽车观察.md" \
--replace \
--backup \
--output "./markdowns/春节后新能源汽车观察-cloudinary.md"
交互流程:
📄 正在分析文章: 春节后新能源汽车观察.md
🔍 找到 3 张本地图片:
1. ./images/ev-battery.png (电池技术)
2. ./images/technology-chip.png (芯片技术)
3. ./images/market-dashboard.png (市场概览)
请选择要上传的图片(输入编号,多个用逗号分隔,或输入 all):
> 1,2
📤 上传中...
✅ 已上传: ev-battery.png → https://res.cloudinary.com/...
✅ 已上传: technology-chip.png → https://res.cloudinary.com/...
🔄 正在替换文件引用...
✅ 已创建备份: 春节后新能源汽车观察.md.backup
✅ 已生成新文件: 春节后新能源汽车观察-cloudinary.md
✅ 已保存映射: cloudinary-mapping.json
使用 cloudinary-image-host 技能 \
--directory "./contents/images/" \
--dry-run \
--max-uploads 5
输出:
🔍 扫描目录: ./contents/images/
📁 找到 8 张图片:
1. ev-battery.png (2.1 MB)
2. market-dashboard.png (1.3 MB)
3. technology-chip.png (1.7 MB)
... (5 more)
⚠️ 试运行模式,不会实际上传
📊 预计上传: 5 张图片(受 max-uploads 限制)
⏱️ 预计时间: 约 30 秒
📈 预计配额使用: 5/25 credits
要实际执行上传,请移除 --dry-run 参数
--dry-run 先预览要上传的图片--max-uploads 限制单次上传数量--folder 参数组织图片--folder "deeptalk/2024/articles"--backup 参数以防意外wechat-article 技能:
# 生成文章后上传图片
使用 wechat-article 技能 --content "..."
使用 cloudinary-image-host 技能 --article "output/article.html" --replace
wechat-publisher 技能:
# 发布前确保图片有永久链接
使用 cloudinary-image-host 技能 --article "article.md" --replace
使用 wechat-publisher 技能 --html "article-cloudinary.html"
wechat-fetcher 技能:
# 抓取文章后上传其中的图片
使用 wechat-fetcher 技能 --url "..."
使用 cloudinary-image-host 技能 --article "fetched-article.md" --replace
创建脚本 upload-images.sh:
#!/bin/bash
# 自动上传新图片并替换引用
# 1. 查找最近修改的 Markdown 文件
ARTICLE=$(find ./markdowns -name "*.md" -mtime -1 | head -1)
# 2. 上传图片
if [ -n "$ARTICLE" ]; then
echo "处理文章: $ARTICLE"
使用 cloudinary-image-host 技能 --article "$ARTICLE" --replace --backup
else
echo "没有找到新文章"
fi
Q: 上传失败,提示 "Invalid API Key"
A: 检查 CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET 环境变量是否正确设置
Q: 图片上传成功但链接无法访问 A: 检查 Cloudinary 控制台中的访问权限设置
Q: 替换后文章格式混乱 A: 使用备份文件恢复,检查图片引用格式是否正确
Q: 达到 API 限制 A: 等待下个月或升级到付费计划
添加 --verbose 参数查看详细日志:
使用 cloudinary-image-host 技能 --image "test.png" --verbose
查看详细帮助:
使用 cloudinary-image-host 技能 --help
检查环境变量(安全模式,不输出密钥值):
# 安全检查环境变量是否存在(不输出密钥值)
!node -e "
const cloudName = process.env.CLOUDINARY_CLOUD_NAME;
const apiKey = process.env.CLOUDINARY_API_KEY;
const apiSecret = process.env.CLOUDINARY_API_SECRET;
console.log('CLOUDINARY_CLOUD_NAME:', cloudName ? '已设置' : '未设置');
console.log('CLOUDINARY_API_KEY:', apiKey ? '已设置' : '未设置');
console.log('CLOUDINARY_API_SECRET:', apiSecret ? '已设置' : '未设置');
if (!cloudName || !apiKey || !apiSecret) {
console.log('❌ 请设置所有 Cloudinary 环境变量');
console.log(' 参考 .env.example 文件配置以下变量:');
console.log(' - CLOUDINARY_CLOUD_NAME');
console.log(' - CLOUDINARY_API_KEY');
console.log(' - CLOUDINARY_API_SECRET');
process.exit(1);
} else {
console.log('✅ Cloudinary 环境变量已正确设置');
}
"
测试 API 连接(注意:此命令会在命令历史中记录密钥,建议仅在安全环境下使用):
# 警告:此命令会在命令历史中记录 API 密钥
# 建议仅在安全环境下临时使用,或使用其他方式测试
curl -s "https://api.cloudinary.com/v1_1/$CLOUDINARY_CLOUD_NAME/resources/image" \
-u "$CLOUDINARY_API_KEY:$CLOUDINARY_API_SECRET" \
| jq -r '.resources[0:3] | length as $count | "找到 \($count) 个图片资源"'