{"id":"97ce3aaf-33be-4c64-ba37-61d2f8f0b780","entityType":"agent","slug":"clawhub-yangchao228-md-img-r2","name":"Markdown Images to R2","canonicalUrl":"https://www.xpersona.co/agent/clawhub-yangchao228-md-img-r2","canonicalPath":"/agent/clawhub-yangchao228-md-img-r2","generatedAt":"2026-10-11T01:48:23.835Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T23:12:46.348Z","emptyReason":null},"description":"Prepare local image references in Markdown for Cloudflare R2 or another S3-compatible object store, upload them only after explicit confirmation, and replace...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.2K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17cxs692g9xb5kx8rt4snej7183xms3:md-img-r2","sourceUrl":"https://clawhub.ai/yangchao228/md-img-r2","homepage":"https://clawhub.ai/yangchao228/skills/md-img-r2","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/yangchao228/md-img-r2","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/yangchao228/skills/md-img-r2","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":62,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Markdown Images to R2 technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T23:12:46.348Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T23:12:46.348Z","emptyReason":null},"stars":null,"forks":null,"downloads":1233,"packageName":null,"latestVersion":"1.0.4","tractionLabel":"1.2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T23:12:46.275Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T23:12:46.348Z","lastCrawledAt":"2026-10-10T23:12:46.275Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T23:12:46.275Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.4","createdAt":"2026-07-23T14:01:55.359Z","changelog":"Refresh public safety boundaries, creator channels, source metadata, examples, and explicit catalog categories and topics.","fileCount":9,"zipByteSize":11038},{"version":"1.0.3","createdAt":"2026-05-20T08:48:01.756Z","changelog":"Document bash run.sh usage so ClawHub zip installs work without executable permissions.","fileCount":8,"zipByteSize":11809},{"version":"1.0.2","createdAt":"2026-05-20T08:44:14.127Z","changelog":"Ship the R2 config template as r2-config.env so it is included in ClawHub packages.","fileCount":7,"zipByteSize":10751},{"version":"1.0.1","createdAt":"2026-05-20T08:41:37.258Z","changelog":"Include a non-hidden env.example template for ClawHub packages and update setup guidance.","fileCount":6,"zipByteSize":10471},{"version":"1.0.0","createdAt":"2026-05-20T08:38:07.388Z","changelog":"Initial release: upload local Markdown images to Cloudflare R2 and replace them with public URLs.","fileCount":6,"zipByteSize":10465}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17cxs692g9xb5kx8rt4snej7183xms3:md-img-r2","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17cxs692g9xb5kx8rt4snej7183xms3:md-img-r2` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/yangchao228/md-img-r2 before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T01:48:23.834Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-yangchao228-md-img-r2/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T23:12:46.348Z","emptyReason":null},"readme":"Skill: Markdown Images to R2\n\nOwner: yangchao228\n\nSummary: Prepare local image references in Markdown for Cloudflare R2 or another S3-compatible object store, upload them only after explicit confirmation, and replace...\n\nTags: image-upload:1.0.4, latest:1.0.4, markdown:1.0.4, r2:1.0.4\n\nVersion history:\n\nv1.0.4 | 2026-07-23T14:01:55.359Z | user\n\nRefresh public safety boundaries, creator channels, source metadata, examples, and explicit catalog categories and topics.\n\nv1.0.3 | 2026-05-20T08:48:01.756Z | user\n\nDocument bash run.sh usage so ClawHub zip installs work without executable permissions.\n\nv1.0.2 | 2026-05-20T08:44:14.127Z | user\n\nShip the R2 config template as r2-config.env so it is included in ClawHub packages.\n\nv1.0.1 | 2026-05-20T08:41:37.258Z | user\n\nInclude a non-hidden env.example template for ClawHub packages and update setup guidance.\n\nv1.0.0 | 2026-05-20T08:38:07.388Z | user\n\nInitial release: upload local Markdown images to Cloudflare R2 and replace them with public URLs.\n\nArchive index:\n\nArchive v1.0.4: 9 files, 11038 bytes\n\nFiles: agents/openai.yaml (232b), examples/expected-output-notes.md (935b), examples/minimal-input.md (811b), run.sh (137b), scripts/md_img_r2.py (16704b), skill-card.md (2644b), skill.json (804b), SKILL.md (3967b), _meta.json (128b)\n\nFile v1.0.4:SKILL.md\n\n---\nname: md-img-r2\ndescription: Prepare local image references in Markdown for Cloudflare R2 or another S3-compatible object store, upload them only after explicit confirmation, and replace references with public URLs. Use when a user wants to publish Markdown images for a blog, Zhihu, Xiaohongshu, WeChat, or other distribution channels; inspect image paths; create a dry-run replacement plan; or safely apply image URL replacements. Follow/关注作者：微信公众号「AI生命克劳德」｜X @yangchao228｜GitHub https://github.com/yangchao228\nversion: 1.0.4\nmetadata:\n  openclaw:\n    homepage: https://github.com/yangchao228/my_open_skills/tree/main/skills/publishing/md-img-r2\n---\n\n# Markdown Images to R2\n\nPrepare Markdown image references for public distribution without exposing private configuration or changing files by default.\n\n## Position In A Publishing Workflow\n\nUse this skill after reviewed local images have been inserted into the target Markdown with relative paths. It is the image transport and URL-rewrite layer; illustration decisions, image generation, captions, tags, and final publish approval belong to upstream or downstream content skills.\n\nWhen an image manifest exists, compare its target Markdown files, local paths, and R2 states with the generated plan. Return the plan or replacement report to the final publish check.\n\n## Workflow\n\n1. Read the target Markdown and identify local Markdown, HTML, and reference-style image links.\n2. Run the bundled script without `--apply` first. It writes an image-publish plan and predicts stable public URLs without uploading or rewriting.\n3. Review missing files, skipped remote URLs, object keys, and the planned replacements.\n4. Choose one apply path:\n   - Upload to an R2 or S3-compatible endpoint with `--apply --confirm-upload`.\n   - Apply a reviewed URL map with `--apply --confirm-write --url-map`.\n5. Inspect the backup and replacement report after every applied change.\n6. Verify required public URLs separately, update the manifest to `verified`, and hand the report to the final publish check.\n\n## Commands\n\n```bash\n# Default: plan only. No upload and no Markdown rewrite.\n./run.sh path/to/article.md\n\n# Scan a directory.\n./run.sh path/to/posts --recursive\n\n# Upload only after an explicit confirmation gate.\n# Set reviewed R2_* values through your secure shell environment first.\n./run.sh path/to/article.md --apply --confirm-upload\n\n# Apply a previously reviewed URL map without contacting object storage.\n./run.sh path/to/article.md --apply --confirm-write --url-map replacements.json\n```\n\nThe script uses `R2_REGION=auto` and `R2_KEY_PREFIX=md-assets` when they are not supplied. `R2_ACCOUNT_ID` is optional when `R2_ENDPOINT` is set.\n\n## Output Contract\n\n- Plan mode writes `<article>.image-publish-plan.json` and leaves the Markdown unchanged.\n- Apply mode creates `<article>.bak`, writes the same plan with result details, and changes only successful local-image references.\n- Object keys use a content hash plus a sanitized filename so repeat runs are stable.\n- Remote URLs, data URLs, and missing files stay unchanged and are recorded in the report.\n- A successful upload or rewrite is not a publish approval; the downstream release gate still decides readiness.\n\n## Boundaries\n\n- Do not use it to publish private material, account credentials, or local paths.\n- Do not run `--apply` until the user has reviewed the plan and explicitly confirmed the upload or write path.\n- Do not infer a public base URL, bucket, endpoint, or key prefix from a personal environment.\n- Stop when a local image is missing, outside the reviewed project root, or the planned URL is not acceptable for the target platform.\n- Verify the resulting public URLs separately when a publishing workflow requires network acceptance.\n\n## 作者入口\n\n- 微信公众号：`AI生命克劳德`\n- X：[@yangchao228](https://x.com/yangchao228)\n- GitHub：[yangchao228](https://github.com/yangchao228)\n\nFile v1.0.4:_meta.json\n\n{\n  \"ownerId\": \"kn7f1pktwnvde1msfd8c4vz97h8254w6\",\n  \"slug\": \"md-img-r2\",\n  \"version\": \"1.0.4\",\n  \"publishedAt\": 1784815315359\n}\n\nFile v1.0.4:examples/expected-output-notes.md\n\nExpected plan-mode behavior:\n\n- Discovers three local images and skips the already-public URL.\n- Calculates one stable object key for each local file.\n- Writes `article.md.image-publish-plan.json`.\n- Does not change `article.md`, upload data, or create a backup.\n\nExpected reviewed-map apply behavior:\n\n- Requires both `--apply` and `--confirm-write`.\n- Creates `article.md.bak` before rewriting.\n- Replaces the three local image references while preserving the Markdown title and HTML attributes.\n- Keeps the existing public URL unchanged.\n- Records replacement details and any missing files in the plan report.\n\nSafety checks:\n\n- An upload attempt requires `--apply --confirm-upload` and all required `R2_*` environment variables.\n- A missing local image, a path outside the reviewed project root, or an incomplete URL map stops that file from being rewritten.\n- The report must never include access-key values or secret-key values.\n\nFile v1.0.4:examples/minimal-input.md\n\nTarget file: `article.md`\n\n```md\n# A reusable content workflow\n\n![Cover](./images/cover.png)\n\n<img src=\"./images/diagram.png\" alt=\"workflow diagram\">\n\n![Architecture][arch]\n\n[arch]: ./images/architecture.png \"architecture\"\n\n![Existing](https://img.example.com/already-public.png)\n```\n\nRun the first inspection without external writes:\n\n```bash\n./run.sh article.md\n```\n\nFor a reviewed local replacement test, create `replacements.json`:\n\n```json\n{\n  \"./images/cover.png\": \"https://img.example.com/md-assets/cover.png\",\n  \"./images/diagram.png\": \"https://img.example.com/md-assets/diagram.png\",\n  \"./images/architecture.png\": \"https://img.example.com/md-assets/architecture.png\"\n}\n```\n\nThen apply only after reviewing that map:\n\n```bash\n./run.sh article.md --apply --confirm-write --url-map replacements.json\n```\n\nFile v1.0.4:skill-card.md\n\n## Description:\n\nMarkdown Images to R2 helps agents inspect local Markdown image references, create dry-run publishing plans, and, after explicit confirmation, upload or rewrite those references for Cloudflare R2 or S3-compatible public URLs.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[yangchao228](https://clawhub.ai/user/yangchao228)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, publishing operators, and content creators use this skill to prepare Markdown files with local images for public distribution. It supports plan-first review, confirmed R2 or S3-compatible uploads, and reviewed URL-map rewrites before downstream publishing approval.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Private images, sensitive local paths, or credentials could be exposed if the skill is used on unreviewed content or with overly broad storage credentials.\n\nMitigation: Review the generated plan first, avoid private images, use least-privilege R2 credentials, and confirm that reports do not contain access-key or secret-key values.\n\nRisk: Markdown could be rewritten with incorrect or unacceptable public URLs.\n\nMitigation: Use plan mode before applying changes, require explicit upload or write confirmation, inspect the backup and replacement report, and verify resulting public URLs separately when required.\n\nRisk: Images outside the intended project root could be uploaded if outside-root access is allowed without review.\n\nMitigation: Keep outside-root access disabled by default and use --allow-outside-root only after checking the referenced paths.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/yangchao228/skills/md-img-r2)\n- [Publisher Profile](https://clawhub.ai/user/yangchao228)\n- [Project Homepage](https://github.com/yangchao228/my_open_skills/tree/main/skills/publishing/md-img-r2)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with shell commands plus JSON image-publish plan and replacement reports]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Plan mode leaves Markdown unchanged; apply mode creates a backup and rewrites only confirmed local-image references.]\n\n## Skill Version(s):\n\n1.0.4 (source: SKILL.md frontmatter and server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.0.4:skill.json\n\n{\n  \"slug\": \"md-img-r2\",\n  \"title\": \"Markdown Images to R2\",\n  \"category\": \"publishing\",\n  \"summary\": \"Prepare local Markdown images for R2 or S3-compatible public URLs with dry-run planning, explicit upload confirmation, backups, and reports.\",\n  \"keywords\": [\n    \"Markdown images\",\n    \"Cloudflare R2\",\n    \"object storage\",\n    \"image URLs\",\n    \"content distribution\"\n  ],\n  \"user_needs\": [\n    \"inspect local image references before publishing Markdown\",\n    \"upload article images to R2 after reviewing a plan\",\n    \"replace local image paths with public URLs safely\",\n    \"prepare image assets for multi-platform content distribution\"\n  ],\n  \"source_dir\": \"skills/publishing/md-img-r2\",\n  \"entry\": \"SKILL.md\",\n  \"package_strategy\": \"on-demand\",\n  \"package_format\": \"skill\",\n  \"status\": \"ready\"\n}\n\nFile v1.0.4:agents/openai.yaml\n\ninterface:\n  display_name: \"Markdown Images to R2\"\n  short_description: \"Safely plan and apply Markdown image URL publishing\"\n  default_prompt: \"Use $md-img-r2 to inspect local Markdown images and create a dry-run publishing plan.\"\n\nArchive v1.0.3: 8 files, 11809 bytes\n\nFiles: r2-config.env (235b), README.md (5879b), run.sh (152b), scripts/md_img_r2.py (18732b), skill-card.md (2001b), skill.json (550b), SKILL.md (1417b), _meta.json (128b)\n\nFile v1.0.3:SKILL.md\n\n---\nname: md-img-r2\ndescription: Upload local images in Markdown directly to Cloudflare R2 and replace paths with public URLs.\n---\n\n# md-img-r2\n\n将 Markdown 文件中的本地图片直接上传到 Cloudflare R2，并把本地路径替换为公开 URL。\n\n## 适用场景\n- 你已经有 Cloudflare R2 桶和可公开访问域名\n- 你不想依赖 PicList Desktop\n- 你希望把这个能力作为可分发 skill 交给别人使用\n\n## 前置条件\n1. 已有可写入的 Cloudflare R2 凭证\n2. 已有桶名和公开访问域名或 CDN 域名\n3. 运行环境有 `python3`\n\n## 推荐配置\n优先用环境变量或项目根目录的 `.env` 提供配置：\n\n- `CF_R2_ACCOUNT_ID`\n- `CF_R2_ACCESS_KEY_ID`\n- `CF_R2_SECRET_ACCESS_KEY`\n- `CF_R2_BUCKET`\n- `CF_R2_PUBLIC_BASE_URL`\n- `CF_R2_REGION`，默认 `auto`\n- `CF_R2_ENDPOINT`，默认 `https://<account_id>.r2.cloudflarestorage.com`\n- `CF_R2_KEY_PREFIX`，默认 `md-assets`\n- `--env-file` 可显式指定 `.env` 路径；不传时会优先读取 skill 目录下的 `.env`，再从目标目录向上查找\n\n## 用法\n### 单文件\nbash run.sh path/to/article.md\n\n### 目录批处理\nbash run.sh path/to/dir --recursive\n\n### Dry run\nbash run.sh path/to/article.md --dry-run\n\n### 临时覆盖 key 前缀\nbash run.sh path/to/article.md --key-prefix posts/2026-04\n\n## 输出\n- 默认原地修改，并生成备份：`xxx.md.bak`\n- 生成报告：`xxx.md.replace-report.json`\n\nFile v1.0.3:README.md\n\n# md-img-r2\n\n把 Markdown 里的本地图片直接上传到 Cloudflare R2，并将引用路径替换为公开 URL。它不依赖 PicList Desktop，只需要 Python 3 和一组 R2 配置。配置既可以来自环境变量，也可以来自 `.env` 文件。\n\n---\n\n## 设计目标\n\n- 少依赖：不要求 PicList、Node.js 或第三方 Python 包\n- 可分发：别人拿到整个目录后，补齐环境变量或 `.env` 就能用\n- 可沉淀：对象 key 默认基于文件内容哈希生成，方便长期复用和避免重复命名冲突\n\n---\n\n## 支持的图片写法\n\n- Markdown：`![](./imgs/a.png)`\n- Markdown（带 title）：`![](./imgs/a.png \"title\")`\n- HTML：`<img src=\"./imgs/a.png\" width=\"300\">`\n- 引用式定义：\n\n  ```md\n  ![][img1]\n  [img1]: ./imgs/a.png\n  [img2]: <./imgs/b c.png> \"title\"\n  ```\n\n---\n\n## 前置条件\n\n你需要提前准备好 Cloudflare R2 的这些信息：\n\n1. `CF_R2_ACCOUNT_ID`\n2. `CF_R2_ACCESS_KEY_ID`\n3. `CF_R2_SECRET_ACCESS_KEY`\n4. `CF_R2_BUCKET`\n5. `CF_R2_PUBLIC_BASE_URL`\n\n可选配置：\n\n- `CF_R2_REGION`\n  默认 `auto`\n- `CF_R2_ENDPOINT`\n  默认 `https://<account_id>.r2.cloudflarestorage.com`\n- `CF_R2_KEY_PREFIX`\n  默认 `md-assets`\n\n其中 `CF_R2_PUBLIC_BASE_URL` 应该是对外可访问的地址，例如：\n\n```text\nhttps://img.example.com\n```\n\n或者：\n\n```text\nhttps://pub-xxxxxxxx.r2.dev\n```\n\n---\n\n## 目录结构\n\n```text\nmd-img-r2/\n  SKILL.md\n  skill.json\n  run.sh\n  r2-config.env\n  scripts/\n    md_img_r2.py\n  README.md\n```\n\n---\n\n## 安装与准备\n\n### 1) 放到你的项目中\n\n```text\n<repo>/.codex/skills/md-img-r2/\n```\n\n### 2) 确认入口脚本可运行\n\n```bash\nbash .codex/skills/md-img-r2/run.sh --help\n```\n\n### 3) 配置环境变量或 `.env`\n\n推荐在项目根目录放一个 `.env` 文件：\n\n```dotenv\nCF_R2_ACCOUNT_ID=your-account-id\nCF_R2_ACCESS_KEY_ID=your-access-key-id\nCF_R2_SECRET_ACCESS_KEY=your-secret-access-key\nCF_R2_BUCKET=your-bucket\nCF_R2_PUBLIC_BASE_URL=https://img.example.com\nCF_R2_KEY_PREFIX=articles\n```\n\n也可以继续用 shell 环境变量：\n\n```bash\nexport CF_R2_ACCOUNT_ID=your-account-id\nexport CF_R2_ACCESS_KEY_ID=your-access-key-id\nexport CF_R2_SECRET_ACCESS_KEY=your-secret-access-key\nexport CF_R2_BUCKET=your-bucket\nexport CF_R2_PUBLIC_BASE_URL=https://img.example.com\nexport CF_R2_KEY_PREFIX=articles\n```\n\n`.env` 的作用很简单：\n\n- 它是一个“项目级配置文件”\n- 用来存放 R2 桶名、公开域名、访问密钥这类不应该写进代码的配置\n- 这样你和别人分发同一个 skill 时，只需要各自换掉自己的 `.env`\n- 一般应把 `.env` 加进 `.gitignore`，不要提交真实密钥\n\n### 4) 先做一次 dry-run\n\n```bash\nbash .codex/skills/md-img-r2/run.sh ./article.md --dry-run\n```\n\n脚本会按这个顺序取配置：\n\n1. 命令行参数\n2. 当前 shell 环境变量\n3. `.env` 文件\n4. 默认值\n\n如果没有显式传 `--env-file`，脚本默认按这个顺序找 `.env`：\n\n1. `md-img-r2/.env`\n2. `target` 所在目录向上查找最近的 `.env`\n3. 当前工作目录下的 `.env`\n\n---\n\n## 使用方式\n\n### 单文件替换\n\n```bash\nbash run.sh ./article.md\n```\n\n### 目录批处理\n\n```bash\nbash run.sh ./posts --recursive\n```\n\n### Dry run\n\n```bash\nbash run.sh ./article.md --dry-run\n```\n\n### 指定对象 key 前缀\n\n```bash\nbash run.sh ./article.md --key-prefix posts/2026-04\n```\n\n### 临时覆盖公开域名\n\n```bash\nbash run.sh ./article.md --public-base-url https://img.example.com\n```\n\n---\n\n## 运行机制\n\n- 脚本扫描 Markdown、HTML `img` 和引用式定义里的本地图片\n- 同一文件内相同路径只上传一次\n- 默认使用 `内容哈希 + 文件名` 生成对象 key\n- 上传成功后，把原始本地路径替换成公开 URL\n- 非 `--dry-run` 模式下会生成 `.bak` 备份和替换报告\n\n默认 key 形式类似：\n\n```text\narticles/6d8f1e2ab4c9d011-cover.png\n```\n\n---\n\n## 参数说明\n\n| 参数 | 说明 |\n| --- | --- |\n| `target` | 必填。Markdown 文件路径或目录路径 |\n| `--recursive` | target 为目录时递归处理所有 `*.md` |\n| `--dry-run` | 不修改文件，只生成报告 |\n| `--key-prefix` | 覆盖默认对象 key 前缀 |\n| `--public-base-url` | 覆盖 `CF_R2_PUBLIC_BASE_URL` |\n| `--endpoint` | 覆盖 `CF_R2_ENDPOINT` |\n| `--bucket` | 覆盖 `CF_R2_BUCKET` |\n| `--account-id` | 覆盖 `CF_R2_ACCOUNT_ID` |\n| `--access-key-id` | 覆盖 `CF_R2_ACCESS_KEY_ID` |\n| `--secret-access-key` | 覆盖 `CF_R2_SECRET_ACCESS_KEY` |\n| `--region` | 覆盖 `CF_R2_REGION` |\n| `--env-file` | 指定 `.env` 文件路径；不传时自动向上查找 |\n\n---\n\n## 对外分发建议\n\n- 优先分享整个 `md-img-r2/` 目录，而不是只拷脚本\n- 把 R2 配置要求写进使用说明，不要把密钥写进 skill 源码\n- 推荐同时给对方一份 `r2-config.env` 模板，不要直接给真实 `.env`\n- 分发前至少用一篇带本地图片的 Markdown 跑一次 `--dry-run`\n- 如果平台要求上传压缩包，直接压缩整个 `md-img-r2/` 目录；不要把本地 `.env`、`.bak` 或 `.replace-report.json` 一起打包\n\n---\n\n## 常见问题\n\n### 为什么上传成功了，但图片访问不到？\n\n通常不是脚本问题，而是公开访问域名没有配好。先检查：\n\n- `CF_R2_PUBLIC_BASE_URL` 是否是对外可访问的域名\n- R2 桶是否已经绑定公开域名或可用的 `r2.dev` 地址\n- CDN / 自定义域是否已经生效\n\n### 为什么建议用环境变量而不是把配置写进代码？\n\n因为这个 skill 的目标是可分发。配置放环境变量，才能让别人拿到 skill 后替换自己的桶和域名，不会把你的凭证一起带走。\n\n### `.env` 和环境变量有什么区别？\n\n本质上都是给脚本提供配置。\n\n- 环境变量更适合临时执行或 CI\n- `.env` 更适合项目本地长期使用\n- 对这个 skill 来说，`.env` 只是把那几项环境变量写进一个文件，方便复用和分发\n\nFile v1.0.3:_meta.json\n\n{\n  \"ownerId\": \"kn7f1pktwnvde1msfd8c4vz97h8254w6\",\n  \"slug\": \"md-img-r2\",\n  \"version\": \"1.0.3\",\n  \"publishedAt\": 1779266881756\n}\n\nFile v1.0.3:skill-card.md\n\n## Description: <br>\nUpload local images referenced in Markdown to Cloudflare R2 and replace the paths with public URLs. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[yangchao228](https://clawhub.ai/user/yangchao228) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nDevelopers and content publishers use this skill to prepare Markdown articles for publication by uploading local image assets to their own Cloudflare R2 bucket and rewriting references to public URLs. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Local images referenced by processed Markdown can be uploaded and made publicly accessible through the configured public URL. <br>\nMitigation: Run with --dry-run first and process only Markdown whose local image paths are intended for publication. <br>\nRisk: Cloudflare R2 credentials are required to upload files. <br>\nMitigation: Keep real R2 credentials in environment variables or a private .env file, and do not commit credentials into the skill source. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/yangchao228/md-img-r2) <br>\n- [README.md](artifact/README.md) <br>\n- [SKILL.md](artifact/SKILL.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [markdown, shell commands, configuration, JSON] <br>\n**Output Format:** [Markdown files rewritten in place, shell status output, and JSON replacement reports] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Creates .bak backups for modified Markdown files and .replace-report.json reports for processed files.] <br>\n\n## Skill Version(s): <br>\n1.0.3 (source: server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v1.0.3:skill.json\n\n{\n  \"slug\": \"md-img-r2\",\n  \"title\": \"Markdown 图片直传 R2\",\n  \"category\": \"tooling\",\n  \"summary\": \"扫描 Markdown 中的本地图片，直接上传到 Cloudflare R2，并回写可公开访问的 URL。\",\n  \"keywords\": [\"Markdown\", \"Cloudflare R2\", \"S3\", \"图床替换\"],\n  \"user_needs\": [\"批量上传 Markdown 本地图片到 R2\", \"不依赖 PicList 替换图片链接\", \"处理文章多图发布流程\"],\n  \"source_dir\": \"md-img-r2\",\n  \"entry\": \"SKILL.md\",\n  \"package_strategy\": \"on-demand\",\n  \"package_format\": \"skill\",\n  \"status\": \"ready\"\n}\n\nArchive v1.0.2: 7 files, 10751 bytes\n\nFiles: r2-config.env (235b), README.md (5862b), run.sh (152b), scripts/md_img_r2.py (18732b), skill.json (550b), SKILL.md (1405b), _meta.json (128b)\n\nFile v1.0.2:SKILL.md\n\n---\nname: md-img-r2\ndescription: Upload local images in Markdown directly to Cloudflare R2 and replace paths with public URLs.\n---\n\n# md-img-r2\n\n将 Markdown 文件中的本地图片直接上传到 Cloudflare R2，并把本地路径替换为公开 URL。\n\n## 适用场景\n- 你已经有 Cloudflare R2 桶和可公开访问域名\n- 你不想依赖 PicList Desktop\n- 你希望把这个能力作为可分发 skill 交给别人使用\n\n## 前置条件\n1. 已有可写入的 Cloudflare R2 凭证\n2. 已有桶名和公开访问域名或 CDN 域名\n3. 运行环境有 `python3`\n\n## 推荐配置\n优先用环境变量或项目根目录的 `.env` 提供配置：\n\n- `CF_R2_ACCOUNT_ID`\n- `CF_R2_ACCESS_KEY_ID`\n- `CF_R2_SECRET_ACCESS_KEY`\n- `CF_R2_BUCKET`\n- `CF_R2_PUBLIC_BASE_URL`\n- `CF_R2_REGION`，默认 `auto`\n- `CF_R2_ENDPOINT`，默认 `https://<account_id>.r2.cloudflarestorage.com`\n- `CF_R2_KEY_PREFIX`，默认 `md-assets`\n- `--env-file` 可显式指定 `.env` 路径；不传时会优先读取 skill 目录下的 `.env`，再从目标目录向上查找\n\n## 用法\n### 单文件\n./run.sh path/to/article.md\n\n### 目录批处理\n./run.sh path/to/dir --recursive\n\n### Dry run\n./run.sh path/to/article.md --dry-run\n\n### 临时覆盖 key 前缀\n./run.sh path/to/article.md --key-prefix posts/2026-04\n\n## 输出\n- 默认原地修改，并生成备份：`xxx.md.bak`\n- 生成报告：`xxx.md.replace-report.json`\n\nFile v1.0.2:README.md\n\n# md-img-r2\n\n把 Markdown 里的本地图片直接上传到 Cloudflare R2，并将引用路径替换为公开 URL。它不依赖 PicList Desktop，只需要 Python 3 和一组 R2 配置。配置既可以来自环境变量，也可以来自 `.env` 文件。\n\n---\n\n## 设计目标\n\n- 少依赖：不要求 PicList、Node.js 或第三方 Python 包\n- 可分发：别人拿到整个目录后，补齐环境变量或 `.env` 就能用\n- 可沉淀：对象 key 默认基于文件内容哈希生成，方便长期复用和避免重复命名冲突\n\n---\n\n## 支持的图片写法\n\n- Markdown：`![](./imgs/a.png)`\n- Markdown（带 title）：`![](./imgs/a.png \"title\")`\n- HTML：`<img src=\"./imgs/a.png\" width=\"300\">`\n- 引用式定义：\n\n  ```md\n  ![][img1]\n  [img1]: ./imgs/a.png\n  [img2]: <./imgs/b c.png> \"title\"\n  ```\n\n---\n\n## 前置条件\n\n你需要提前准备好 Cloudflare R2 的这些信息：\n\n1. `CF_R2_ACCOUNT_ID`\n2. `CF_R2_ACCESS_KEY_ID`\n3. `CF_R2_SECRET_ACCESS_KEY`\n4. `CF_R2_BUCKET`\n5. `CF_R2_PUBLIC_BASE_URL`\n\n可选配置：\n\n- `CF_R2_REGION`\n  默认 `auto`\n- `CF_R2_ENDPOINT`\n  默认 `https://<account_id>.r2.cloudflarestorage.com`\n- `CF_R2_KEY_PREFIX`\n  默认 `md-assets`\n\n其中 `CF_R2_PUBLIC_BASE_URL` 应该是对外可访问的地址，例如：\n\n```text\nhttps://img.example.com\n```\n\n或者：\n\n```text\nhttps://pub-xxxxxxxx.r2.dev\n```\n\n---\n\n## 目录结构\n\n```text\nmd-img-r2/\n  SKILL.md\n  skill.json\n  run.sh\n  r2-config.env\n  scripts/\n    md_img_r2.py\n  README.md\n```\n\n---\n\n## 安装与准备\n\n### 1) 放到你的项目中\n\n```text\n<repo>/.codex/skills/md-img-r2/\n```\n\n### 2) 赋予 `run.sh` 可执行权限\n\n```bash\nchmod +x .codex/skills/md-img-r2/run.sh\n```\n\n### 3) 配置环境变量或 `.env`\n\n推荐在项目根目录放一个 `.env` 文件：\n\n```dotenv\nCF_R2_ACCOUNT_ID=your-account-id\nCF_R2_ACCESS_KEY_ID=your-access-key-id\nCF_R2_SECRET_ACCESS_KEY=your-secret-access-key\nCF_R2_BUCKET=your-bucket\nCF_R2_PUBLIC_BASE_URL=https://img.example.com\nCF_R2_KEY_PREFIX=articles\n```\n\n也可以继续用 shell 环境变量：\n\n```bash\nexport CF_R2_ACCOUNT_ID=your-account-id\nexport CF_R2_ACCESS_KEY_ID=your-access-key-id\nexport CF_R2_SECRET_ACCESS_KEY=your-secret-access-key\nexport CF_R2_BUCKET=your-bucket\nexport CF_R2_PUBLIC_BASE_URL=https://img.example.com\nexport CF_R2_KEY_PREFIX=articles\n```\n\n`.env` 的作用很简单：\n\n- 它是一个“项目级配置文件”\n- 用来存放 R2 桶名、公开域名、访问密钥这类不应该写进代码的配置\n- 这样你和别人分发同一个 skill 时，只需要各自换掉自己的 `.env`\n- 一般应把 `.env` 加进 `.gitignore`，不要提交真实密钥\n\n### 4) 先做一次 dry-run\n\n```bash\n./.codex/skills/md-img-r2/run.sh ./article.md --dry-run\n```\n\n脚本会按这个顺序取配置：\n\n1. 命令行参数\n2. 当前 shell 环境变量\n3. `.env` 文件\n4. 默认值\n\n如果没有显式传 `--env-file`，脚本默认按这个顺序找 `.env`：\n\n1. `md-img-r2/.env`\n2. `target` 所在目录向上查找最近的 `.env`\n3. 当前工作目录下的 `.env`\n\n---\n\n## 使用方式\n\n### 单文件替换\n\n```bash\n./run.sh ./article.md\n```\n\n### 目录批处理\n\n```bash\n./run.sh ./posts --recursive\n```\n\n### Dry run\n\n```bash\n./run.sh ./article.md --dry-run\n```\n\n### 指定对象 key 前缀\n\n```bash\n./run.sh ./article.md --key-prefix posts/2026-04\n```\n\n### 临时覆盖公开域名\n\n```bash\n./run.sh ./article.md --public-base-url https://img.example.com\n```\n\n---\n\n## 运行机制\n\n- 脚本扫描 Markdown、HTML `img` 和引用式定义里的本地图片\n- 同一文件内相同路径只上传一次\n- 默认使用 `内容哈希 + 文件名` 生成对象 key\n- 上传成功后，把原始本地路径替换成公开 URL\n- 非 `--dry-run` 模式下会生成 `.bak` 备份和替换报告\n\n默认 key 形式类似：\n\n```text\narticles/6d8f1e2ab4c9d011-cover.png\n```\n\n---\n\n## 参数说明\n\n| 参数 | 说明 |\n| --- | --- |\n| `target` | 必填。Markdown 文件路径或目录路径 |\n| `--recursive` | target 为目录时递归处理所有 `*.md` |\n| `--dry-run` | 不修改文件，只生成报告 |\n| `--key-prefix` | 覆盖默认对象 key 前缀 |\n| `--public-base-url` | 覆盖 `CF_R2_PUBLIC_BASE_URL` |\n| `--endpoint` | 覆盖 `CF_R2_ENDPOINT` |\n| `--bucket` | 覆盖 `CF_R2_BUCKET` |\n| `--account-id` | 覆盖 `CF_R2_ACCOUNT_ID` |\n| `--access-key-id` | 覆盖 `CF_R2_ACCESS_KEY_ID` |\n| `--secret-access-key` | 覆盖 `CF_R2_SECRET_ACCESS_KEY` |\n| `--region` | 覆盖 `CF_R2_REGION` |\n| `--env-file` | 指定 `.env` 文件路径；不传时自动向上查找 |\n\n---\n\n## 对外分发建议\n\n- 优先分享整个 `md-img-r2/` 目录，而不是只拷脚本\n- 把 R2 配置要求写进使用说明，不要把密钥写进 skill 源码\n- 推荐同时给对方一份 `r2-config.env` 模板，不要直接给真实 `.env`\n- 分发前至少用一篇带本地图片的 Markdown 跑一次 `--dry-run`\n- 如果平台要求上传压缩包，直接压缩整个 `md-img-r2/` 目录；不要把本地 `.env`、`.bak` 或 `.replace-report.json` 一起打包\n\n---\n\n## 常见问题\n\n### 为什么上传成功了，但图片访问不到？\n\n通常不是脚本问题，而是公开访问域名没有配好。先检查：\n\n- `CF_R2_PUBLIC_BASE_URL` 是否是对外可访问的域名\n- R2 桶是否已经绑定公开域名或可用的 `r2.dev` 地址\n- CDN / 自定义域是否已经生效\n\n### 为什么建议用环境变量而不是把配置写进代码？\n\n因为这个 skill 的目标是可分发。配置放环境变量，才能让别人拿到 skill 后替换自己的桶和域名，不会把你的凭证一起带走。\n\n### `.env` 和环境变量有什么区别？\n\n本质上都是给脚本提供配置。\n\n- 环境变量更适合临时执行或 CI\n- `.env` 更适合项目本地长期使用\n- 对这个 skill 来说，`.env` 只是把那几项环境变量写进一个文件，方便复用和分发\n\nFile v1.0.2:_meta.json\n\n{\n  \"ownerId\": \"kn7f1pktwnvde1msfd8c4vz97h8254w6\",\n  \"slug\": \"md-img-r2\",\n  \"version\": \"1.0.2\",\n  \"publishedAt\": 1779266654127\n}\n\nFile v1.0.2:skill.json\n\n{\n  \"slug\": \"md-img-r2\",\n  \"title\": \"Markdown 图片直传 R2\",\n  \"category\": \"tooling\",\n  \"summary\": \"扫描 Markdown 中的本地图片，直接上传到 Cloudflare R2，并回写可公开访问的 URL。\",\n  \"keywords\": [\"Markdown\", \"Cloudflare R2\", \"S3\", \"图床替换\"],\n  \"user_needs\": [\"批量上传 Markdown 本地图片到 R2\", \"不依赖 PicList 替换图片链接\", \"处理文章多图发布流程\"],\n  \"source_dir\": \"md-img-r2\",\n  \"entry\": \"SKILL.md\",\n  \"package_strategy\": \"on-demand\",\n  \"package_format\": \"skill\",\n  \"status\": \"ready\"\n}\n\nArchive v1.0.1: 6 files, 10471 bytes\n\nFiles: README.md (5858b), run.sh (152b), scripts/md_img_r2.py (18728b), skill.json (550b), SKILL.md (1405b), _meta.json (128b)\n\nFile v1.0.1:SKILL.md\n\n---\nname: md-img-r2\ndescription: Upload local images in Markdown directly to Cloudflare R2 and replace paths with public URLs.\n---\n\n# md-img-r2\n\n将 Markdown 文件中的本地图片直接上传到 Cloudflare R2，并把本地路径替换为公开 URL。\n\n## 适用场景\n- 你已经有 Cloudflare R2 桶和可公开访问域名\n- 你不想依赖 PicList Desktop\n- 你希望把这个能力作为可分发 skill 交给别人使用\n\n## 前置条件\n1. 已有可写入的 Cloudflare R2 凭证\n2. 已有桶名和公开访问域名或 CDN 域名\n3. 运行环境有 `python3`\n\n## 推荐配置\n优先用环境变量或项目根目录的 `.env` 提供配置：\n\n- `CF_R2_ACCOUNT_ID`\n- `CF_R2_ACCESS_KEY_ID`\n- `CF_R2_SECRET_ACCESS_KEY`\n- `CF_R2_BUCKET`\n- `CF_R2_PUBLIC_BASE_URL`\n- `CF_R2_REGION`，默认 `auto`\n- `CF_R2_ENDPOINT`，默认 `https://<account_id>.r2.cloudflarestorage.com`\n- `CF_R2_KEY_PREFIX`，默认 `md-assets`\n- `--env-file` 可显式指定 `.env` 路径；不传时会优先读取 skill 目录下的 `.env`，再从目标目录向上查找\n\n## 用法\n### 单文件\n./run.sh path/to/article.md\n\n### 目录批处理\n./run.sh path/to/dir --recursive\n\n### Dry run\n./run.sh path/to/article.md --dry-run\n\n### 临时覆盖 key 前缀\n./run.sh path/to/article.md --key-prefix posts/2026-04\n\n## 输出\n- 默认原地修改，并生成备份：`xxx.md.bak`\n- 生成报告：`xxx.md.replace-report.json`\n\nFile v1.0.1:README.md\n\n# md-img-r2\n\n把 Markdown 里的本地图片直接上传到 Cloudflare R2，并将引用路径替换为公开 URL。它不依赖 PicList Desktop，只需要 Python 3 和一组 R2 配置。配置既可以来自环境变量，也可以来自 `.env` 文件。\n\n---\n\n## 设计目标\n\n- 少依赖：不要求 PicList、Node.js 或第三方 Python 包\n- 可分发：别人拿到整个目录后，补齐环境变量或 `.env` 就能用\n- 可沉淀：对象 key 默认基于文件内容哈希生成，方便长期复用和避免重复命名冲突\n\n---\n\n## 支持的图片写法\n\n- Markdown：`![](./imgs/a.png)`\n- Markdown（带 title）：`![](./imgs/a.png \"title\")`\n- HTML：`<img src=\"./imgs/a.png\" width=\"300\">`\n- 引用式定义：\n\n  ```md\n  ![][img1]\n  [img1]: ./imgs/a.png\n  [img2]: <./imgs/b c.png> \"title\"\n  ```\n\n---\n\n## 前置条件\n\n你需要提前准备好 Cloudflare R2 的这些信息：\n\n1. `CF_R2_ACCOUNT_ID`\n2. `CF_R2_ACCESS_KEY_ID`\n3. `CF_R2_SECRET_ACCESS_KEY`\n4. `CF_R2_BUCKET`\n5. `CF_R2_PUBLIC_BASE_URL`\n\n可选配置：\n\n- `CF_R2_REGION`\n  默认 `auto`\n- `CF_R2_ENDPOINT`\n  默认 `https://<account_id>.r2.cloudflarestorage.com`\n- `CF_R2_KEY_PREFIX`\n  默认 `md-assets`\n\n其中 `CF_R2_PUBLIC_BASE_URL` 应该是对外可访问的地址，例如：\n\n```text\nhttps://img.example.com\n```\n\n或者：\n\n```text\nhttps://pub-xxxxxxxx.r2.dev\n```\n\n---\n\n## 目录结构\n\n```text\nmd-img-r2/\n  SKILL.md\n  skill.json\n  run.sh\n  env.example\n  scripts/\n    md_img_r2.py\n  README.md\n```\n\n---\n\n## 安装与准备\n\n### 1) 放到你的项目中\n\n```text\n<repo>/.codex/skills/md-img-r2/\n```\n\n### 2) 赋予 `run.sh` 可执行权限\n\n```bash\nchmod +x .codex/skills/md-img-r2/run.sh\n```\n\n### 3) 配置环境变量或 `.env`\n\n推荐在项目根目录放一个 `.env` 文件：\n\n```dotenv\nCF_R2_ACCOUNT_ID=your-account-id\nCF_R2_ACCESS_KEY_ID=your-access-key-id\nCF_R2_SECRET_ACCESS_KEY=your-secret-access-key\nCF_R2_BUCKET=your-bucket\nCF_R2_PUBLIC_BASE_URL=https://img.example.com\nCF_R2_KEY_PREFIX=articles\n```\n\n也可以继续用 shell 环境变量：\n\n```bash\nexport CF_R2_ACCOUNT_ID=your-account-id\nexport CF_R2_ACCESS_KEY_ID=your-access-key-id\nexport CF_R2_SECRET_ACCESS_KEY=your-secret-access-key\nexport CF_R2_BUCKET=your-bucket\nexport CF_R2_PUBLIC_BASE_URL=https://img.example.com\nexport CF_R2_KEY_PREFIX=articles\n```\n\n`.env` 的作用很简单：\n\n- 它是一个“项目级配置文件”\n- 用来存放 R2 桶名、公开域名、访问密钥这类不应该写进代码的配置\n- 这样你和别人分发同一个 skill 时，只需要各自换掉自己的 `.env`\n- 一般应把 `.env` 加进 `.gitignore`，不要提交真实密钥\n\n### 4) 先做一次 dry-run\n\n```bash\n./.codex/skills/md-img-r2/run.sh ./article.md --dry-run\n```\n\n脚本会按这个顺序取配置：\n\n1. 命令行参数\n2. 当前 shell 环境变量\n3. `.env` 文件\n4. 默认值\n\n如果没有显式传 `--env-file`，脚本默认按这个顺序找 `.env`：\n\n1. `md-img-r2/.env`\n2. `target` 所在目录向上查找最近的 `.env`\n3. 当前工作目录下的 `.env`\n\n---\n\n## 使用方式\n\n### 单文件替换\n\n```bash\n./run.sh ./article.md\n```\n\n### 目录批处理\n\n```bash\n./run.sh ./posts --recursive\n```\n\n### Dry run\n\n```bash\n./run.sh ./article.md --dry-run\n```\n\n### 指定对象 key 前缀\n\n```bash\n./run.sh ./article.md --key-prefix posts/2026-04\n```\n\n### 临时覆盖公开域名\n\n```bash\n./run.sh ./article.md --public-base-url https://img.example.com\n```\n\n---\n\n## 运行机制\n\n- 脚本扫描 Markdown、HTML `img` 和引用式定义里的本地图片\n- 同一文件内相同路径只上传一次\n- 默认使用 `内容哈希 + 文件名` 生成对象 key\n- 上传成功后，把原始本地路径替换成公开 URL\n- 非 `--dry-run` 模式下会生成 `.bak` 备份和替换报告\n\n默认 key 形式类似：\n\n```text\narticles/6d8f1e2ab4c9d011-cover.png\n```\n\n---\n\n## 参数说明\n\n| 参数 | 说明 |\n| --- | --- |\n| `target` | 必填。Markdown 文件路径或目录路径 |\n| `--recursive` | target 为目录时递归处理所有 `*.md` |\n| `--dry-run` | 不修改文件，只生成报告 |\n| `--key-prefix` | 覆盖默认对象 key 前缀 |\n| `--public-base-url` | 覆盖 `CF_R2_PUBLIC_BASE_URL` |\n| `--endpoint` | 覆盖 `CF_R2_ENDPOINT` |\n| `--bucket` | 覆盖 `CF_R2_BUCKET` |\n| `--account-id` | 覆盖 `CF_R2_ACCOUNT_ID` |\n| `--access-key-id` | 覆盖 `CF_R2_ACCESS_KEY_ID` |\n| `--secret-access-key` | 覆盖 `CF_R2_SECRET_ACCESS_KEY` |\n| `--region` | 覆盖 `CF_R2_REGION` |\n| `--env-file` | 指定 `.env` 文件路径；不传时自动向上查找 |\n\n---\n\n## 对外分发建议\n\n- 优先分享整个 `md-img-r2/` 目录，而不是只拷脚本\n- 把 R2 配置要求写进使用说明，不要把密钥写进 skill 源码\n- 推荐同时给对方一份 `env.example` 模板，不要直接给真实 `.env`\n- 分发前至少用一篇带本地图片的 Markdown 跑一次 `--dry-run`\n- 如果平台要求上传压缩包，直接压缩整个 `md-img-r2/` 目录；不要把本地 `.env`、`.bak` 或 `.replace-report.json` 一起打包\n\n---\n\n## 常见问题\n\n### 为什么上传成功了，但图片访问不到？\n\n通常不是脚本问题，而是公开访问域名没有配好。先检查：\n\n- `CF_R2_PUBLIC_BASE_URL` 是否是对外可访问的域名\n- R2 桶是否已经绑定公开域名或可用的 `r2.dev` 地址\n- CDN / 自定义域是否已经生效\n\n### 为什么建议用环境变量而不是把配置写进代码？\n\n因为这个 skill 的目标是可分发。配置放环境变量，才能让别人拿到 skill 后替换自己的桶和域名，不会把你的凭证一起带走。\n\n### `.env` 和环境变量有什么区别？\n\n本质上都是给脚本提供配置。\n\n- 环境变量更适合临时执行或 CI\n- `.env` 更适合项目本地长期使用\n- 对这个 skill 来说，`.env` 只是把那几项环境变量写进一个文件，方便复用和分发\n\nFile v1.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn7f1pktwnvde1msfd8c4vz97h8254w6\",\n  \"slug\": \"md-img-r2\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1779266497258\n}\n\nFile v1.0.1:skill.json\n\n{\n  \"slug\": \"md-img-r2\",\n  \"title\": \"Markdown 图片直传 R2\",\n  \"category\": \"tooling\",\n  \"summary\": \"扫描 Markdown 中的本地图片，直接上传到 Cloudflare R2，并回写可公开访问的 URL。\",\n  \"keywords\": [\"Markdown\", \"Cloudflare R2\", \"S3\", \"图床替换\"],\n  \"user_needs\": [\"批量上传 Markdown 本地图片到 R2\", \"不依赖 PicList 替换图片链接\", \"处理文章多图发布流程\"],\n  \"source_dir\": \"md-img-r2\",\n  \"entry\": \"SKILL.md\",\n  \"package_strategy\": \"on-demand\",\n  \"package_format\": \"skill\",\n  \"status\": \"ready\"\n}\n\nArchive v1.0.0: 6 files, 10465 bytes\n\nFiles: README.md (5845b), run.sh (152b), scripts/md_img_r2.py (18730b), skill.json (550b), SKILL.md (1405b), _meta.json (128b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: md-img-r2\ndescription: Upload local images in Markdown directly to Cloudflare R2 and replace paths with public URLs.\n---\n\n# md-img-r2\n\n将 Markdown 文件中的本地图片直接上传到 Cloudflare R2，并把本地路径替换为公开 URL。\n\n## 适用场景\n- 你已经有 Cloudflare R2 桶和可公开访问域名\n- 你不想依赖 PicList Desktop\n- 你希望把这个能力作为可分发 skill 交给别人使用\n\n## 前置条件\n1. 已有可写入的 Cloudflare R2 凭证\n2. 已有桶名和公开访问域名或 CDN 域名\n3. 运行环境有 `python3`\n\n## 推荐配置\n优先用环境变量或项目根目录的 `.env` 提供配置：\n\n- `CF_R2_ACCOUNT_ID`\n- `CF_R2_ACCESS_KEY_ID`\n- `CF_R2_SECRET_ACCESS_KEY`\n- `CF_R2_BUCKET`\n- `CF_R2_PUBLIC_BASE_URL`\n- `CF_R2_REGION`，默认 `auto`\n- `CF_R2_ENDPOINT`，默认 `https://<account_id>.r2.cloudflarestorage.com`\n- `CF_R2_KEY_PREFIX`，默认 `md-assets`\n- `--env-file` 可显式指定 `.env` 路径；不传时会优先读取 skill 目录下的 `.env`，再从目标目录向上查找\n\n## 用法\n### 单文件\n./run.sh path/to/article.md\n\n### 目录批处理\n./run.sh path/to/dir --recursive\n\n### Dry run\n./run.sh path/to/article.md --dry-run\n\n### 临时覆盖 key 前缀\n./run.sh path/to/article.md --key-prefix posts/2026-04\n\n## 输出\n- 默认原地修改，并生成备份：`xxx.md.bak`\n- 生成报告：`xxx.md.replace-report.json`\n\nFile v1.0.0:README.md\n\n# md-img-r2\n\n把 Markdown 里的本地图片直接上传到 Cloudflare R2，并将引用路径替换为公开 URL。它不依赖 PicList Desktop，只需要 Python 3 和一组 R2 配置。配置既可以来自环境变量，也可以来自 `.env` 文件。\n\n---\n\n## 设计目标\n\n- 少依赖：不要求 PicList、Node.js 或第三方 Python 包\n- 可分发：别人拿到整个目录后，补齐环境变量或 `.env` 就能用\n- 可沉淀：对象 key 默认基于文件内容哈希生成，方便长期复用和避免重复命名冲突\n\n---\n\n## 支持的图片写法\n\n- Markdown：`![](./imgs/a.png)`\n- Markdown（带 title）：`![](./imgs/a.png \"title\")`\n- HTML：`<img src=\"./imgs/a.png\" width=\"300\">`\n- 引用式定义：\n\n  ```md\n  ![][img1]\n  [img1]: ./imgs/a.png\n  [img2]: <./imgs/b c.png> \"title\"\n  ```\n\n---\n\n## 前置条件\n\n你需要提前准备好 Cloudflare R2 的这些信息：\n\n1. `CF_R2_ACCOUNT_ID`\n2. `CF_R2_ACCESS_KEY_ID`\n3. `CF_R2_SECRET_ACCESS_KEY`\n4. `CF_R2_BUCKET`\n5. `CF_R2_PUBLIC_BASE_URL`\n\n可选配置：\n\n- `CF_R2_REGION`\n  默认 `auto`\n- `CF_R2_ENDPOINT`\n  默认 `https://<account_id>.r2.cloudflarestorage.com`\n- `CF_R2_KEY_PREFIX`\n  默认 `md-assets`\n\n其中 `CF_R2_PUBLIC_BASE_URL` 应该是对外可访问的地址，例如：\n\n```text\nhttps://img.example.com\n```\n\n或者：\n\n```text\nhttps://pub-xxxxxxxx.r2.dev\n```\n\n---\n\n## 目录结构\n\n```text\nmd-img-r2/\n  SKILL.md\n  skill.json\n  run.sh\n  scripts/\n    md_img_r2.py\n  README.md\n```\n\n---\n\n## 安装与准备\n\n### 1) 放到你的项目中\n\n```text\n<repo>/.codex/skills/md-img-r2/\n```\n\n### 2) 赋予 `run.sh` 可执行权限\n\n```bash\nchmod +x .codex/skills/md-img-r2/run.sh\n```\n\n### 3) 配置环境变量或 `.env`\n\n推荐在项目根目录放一个 `.env` 文件：\n\n```dotenv\nCF_R2_ACCOUNT_ID=your-account-id\nCF_R2_ACCESS_KEY_ID=your-access-key-id\nCF_R2_SECRET_ACCESS_KEY=your-secret-access-key\nCF_R2_BUCKET=your-bucket\nCF_R2_PUBLIC_BASE_URL=https://img.example.com\nCF_R2_KEY_PREFIX=articles\n```\n\n也可以继续用 shell 环境变量：\n\n```bash\nexport CF_R2_ACCOUNT_ID=your-account-id\nexport CF_R2_ACCESS_KEY_ID=your-access-key-id\nexport CF_R2_SECRET_ACCESS_KEY=your-secret-access-key\nexport CF_R2_BUCKET=your-bucket\nexport CF_R2_PUBLIC_BASE_URL=https://img.example.com\nexport CF_R2_KEY_PREFIX=articles\n```\n\n`.env` 的作用很简单：\n\n- 它是一个“项目级配置文件”\n- 用来存放 R2 桶名、公开域名、访问密钥这类不应该写进代码的配置\n- 这样你和别人分发同一个 skill 时，只需要各自换掉自己的 `.env`\n- 一般应把 `.env` 加进 `.gitignore`，不要提交真实密钥\n\n### 4) 先做一次 dry-run\n\n```bash\n./.codex/skills/md-img-r2/run.sh ./article.md --dry-run\n```\n\n脚本会按这个顺序取配置：\n\n1. 命令行参数\n2. 当前 shell 环境变量\n3. `.env` 文件\n4. 默认值\n\n如果没有显式传 `--env-file`，脚本默认按这个顺序找 `.env`：\n\n1. `md-img-r2/.env`\n2. `target` 所在目录向上查找最近的 `.env`\n3. 当前工作目录下的 `.env`\n\n---\n\n## 使用方式\n\n### 单文件替换\n\n```bash\n./run.sh ./article.md\n```\n\n### 目录批处理\n\n```bash\n./run.sh ./posts --recursive\n```\n\n### Dry run\n\n```bash\n./run.sh ./article.md --dry-run\n```\n\n### 指定对象 key 前缀\n\n```bash\n./run.sh ./article.md --key-prefix posts/2026-04\n```\n\n### 临时覆盖公开域名\n\n```bash\n./run.sh ./article.md --public-base-url https://img.example.com\n```\n\n---\n\n## 运行机制\n\n- 脚本扫描 Markdown、HTML `img` 和引用式定义里的本地图片\n- 同一文件内相同路径只上传一次\n- 默认使用 `内容哈希 + 文件名` 生成对象 key\n- 上传成功后，把原始本地路径替换成公开 URL\n- 非 `--dry-run` 模式下会生成 `.bak` 备份和替换报告\n\n默认 key 形式类似：\n\n```text\narticles/6d8f1e2ab4c9d011-cover.png\n```\n\n---\n\n## 参数说明\n\n| 参数 | 说明 |\n| --- | --- |\n| `target` | 必填。Markdown 文件路径或目录路径 |\n| `--recursive` | target 为目录时递归处理所有 `*.md` |\n| `--dry-run` | 不修改文件，只生成报告 |\n| `--key-prefix` | 覆盖默认对象 key 前缀 |\n| `--public-base-url` | 覆盖 `CF_R2_PUBLIC_BASE_URL` |\n| `--endpoint` | 覆盖 `CF_R2_ENDPOINT` |\n| `--bucket` | 覆盖 `CF_R2_BUCKET` |\n| `--account-id` | 覆盖 `CF_R2_ACCOUNT_ID` |\n| `--access-key-id` | 覆盖 `CF_R2_ACCESS_KEY_ID` |\n| `--secret-access-key` | 覆盖 `CF_R2_SECRET_ACCESS_KEY` |\n| `--region` | 覆盖 `CF_R2_REGION` |\n| `--env-file` | 指定 `.env` 文件路径；不传时自动向上查找 |\n\n---\n\n## 对外分发建议\n\n- 优先分享整个 `md-img-r2/` 目录，而不是只拷脚本\n- 把 R2 配置要求写进使用说明，不要把密钥写进 skill 源码\n- 推荐同时给对方一份 `.env.example` 模板，不要直接给真实 `.env`\n- 分发前至少用一篇带本地图片的 Markdown 跑一次 `--dry-run`\n- 如果平台要求上传压缩包，直接压缩整个 `md-img-r2/` 目录；不要把本地 `.env`、`.bak` 或 `.replace-report.json` 一起打包\n\n---\n\n## 常见问题\n\n### 为什么上传成功了，但图片访问不到？\n\n通常不是脚本问题，而是公开访问域名没有配好。先检查：\n\n- `CF_R2_PUBLIC_BASE_URL` 是否是对外可访问的域名\n- R2 桶是否已经绑定公开域名或可用的 `r2.dev` 地址\n- CDN / 自定义域是否已经生效\n\n### 为什么建议用环境变量而不是把配置写进代码？\n\n因为这个 skill 的目标是可分发。配置放环境变量，才能让别人拿到 skill 后替换自己的桶和域名，不会把你的凭证一起带走。\n\n### `.env` 和环境变量有什么区别？\n\n本质上都是给脚本提供配置。\n\n- 环境变量更适合临时执行或 CI\n- `.env` 更适合项目本地长期使用\n- 对这个 skill 来说，`.env` 只是把那几项环境变量写进一个文件，方便复用和分发\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn7f1pktwnvde1msfd8c4vz97h8254w6\",\n  \"slug\": \"md-img-r2\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1779266287388\n}\n\nFile v1.0.0:skill.json\n\n{\n  \"slug\": \"md-img-r2\",\n  \"title\": \"Markdown 图片直传 R2\",\n  \"category\": \"tooling\",\n  \"summary\": \"扫描 Markdown 中的本地图片，直接上传到 Cloudflare R2，并回写可公开访问的 URL。\",\n  \"keywords\": [\"Markdown\", \"Cloudflare R2\", \"S3\", \"图床替换\"],\n  \"user_needs\": [\"批量上传 Markdown 本地图片到 R2\", \"不依赖 PicList 替换图片链接\", \"处理文章多图发布流程\"],\n  \"source_dir\": \"md-img-r2\",\n  \"entry\": \"SKILL.md\",\n  \"package_strategy\": \"on-demand\",\n  \"package_format\": \"skill\",\n  \"status\": \"ready\"\n}","readmeExcerpt":"Skill: Markdown Images to R2 Owner: yangchao228 Summary: Prepare local image references in Markdown for Cloudflare R2 or another S3-compatible object store, upload them only after explicit confirmation, and replace... Tags: image-upload:1.0.4, latest:1.0.4, markdown:1.0.4, r2:1.0.4 Version history: v1.0.4 | 2026-07-23T14:01:55.359Z | user Refresh public safety boundaries, creator channels, source metadata, examples, ","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"# Default: plan only. No upload and no Markdown rewrite.\n./run.sh path/to/article.md\n\n# Scan a directory.\n./run.sh path/to/posts --recursive\n\n# Upload only after an explicit confirmation gate.\n# Set reviewed R2_* values through your secure shell environment first.\n./run.sh path/to/article.md --apply --confirm-upload\n\n# Apply a previously reviewed URL map without contacting object storage.\n./run.sh path/to/article.md --apply --confirm-write --url-map replacements.json"},{"language":"md","snippet":"# A reusable content workflow\n\n![Cover](./images/cover.png)\n\n<img src=\"./images/diagram.png\" alt=\"workflow diagram\">\n\n![Architecture][arch]\n\n[arch]: ./images/architecture.png \"architecture\"\n\n![Existing](https://img.example.com/already-public.png)"},{"language":"bash","snippet":"./run.sh article.md"},{"language":"json","snippet":"{\n  \"./images/cover.png\": \"https://img.example.com/md-assets/cover.png\",\n  \"./images/diagram.png\": \"https://img.example.com/md-assets/diagram.png\",\n  \"./images/architecture.png\": \"https://img.example.com/md-assets/architecture.png\"\n}"},{"language":"bash","snippet":"./run.sh article.md --apply --confirm-write --url-map replacements.json"},{"language":"md","snippet":"![][img1]\n  [img1]: ./imgs/a.png\n  [img2]: <./imgs/b c.png> \"title\""}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: md-img-r2\ndescription: Prepare local image references in Markdown for Cloudflare R2 or another S3-compatible object store, upload them only after explicit confirmation, and replace references with public URLs. Use when a user wants to publish Markdown images for a blog, Zhihu, Xiaohongshu, WeChat, or other distribution channels; inspect image paths; create a dry-run replacement plan; or safely apply image URL replacements. Follow/关注作者：微信公众号「AI生命克劳德」｜X @yangchao228｜GitHub https://github.com/yangchao228\nversion: 1.0.4\nmetadata:\n  openclaw:\n    homepage: https://github.com/yangchao228/my_open_skills/tree/main/skills/publishing/md-img-r2\n---\n\n# Markdown Images to R2\n\nPrepare Markdown image references for public distribution without exposing private configuration or changing files by default.\n\n## Position In A Publishing Workflow\n\nUse this skill after reviewed local images have been inserted into the target Markdown with relative paths. It is the image transport and URL-rewrite layer; illustration decisions, image generation, captions, tags, and final publish approval belong to upstream or downstream content skills.\n\nWhen an image manifest exists, compare its target Markdown files, local paths, and R2 states with the generated plan. Return the plan or replacement report to the final publish check.\n\n## Workflow\n\n1. Read the target Markdown and identify local Markdown, HTML, and reference-style image links.\n2. Run the bundled script without `--apply` first. It writes an image-publish plan and predicts stable public URLs without uploading or rewriting.\n3. Review missing files, skipped remote URLs, object keys, and the planned replacements.\n4. Choose one apply path:\n   - Upload to an R2 or S3-compatible endpoint with `--apply --confirm-upload`.\n   - Apply a reviewed URL map with `--apply --confirm-write --url-map`.\n5. Inspect the backup and replacement report after every applied change.\n6. Verify required public URLs separately, update the manifest to `verified`, and hand the report to the final publish check.\n\n## Commands\n\n```bash\n# Default: plan only. No upload and no Markdown rewrite.\n./run.sh path/to/article.md\n\n# Scan a directory.\n./run.sh path/to/posts --recursive\n\n# Upload only after an explicit confirmation gate.\n# Set reviewed R2_* values through your secure shell environment first.\n./run.sh path/to/article.md --apply --confirm-upload\n\n# Apply a previously reviewed URL map without contacting object storage.\n./run.sh path/to/article.md --apply --confirm-write --url-map replacements.json\n```\n\nThe script uses `R2_REGION=auto` and `R2_KEY_PREFIX=md-assets` when they are not supplied. `R2_ACCOUNT_ID` is optional when `R2_ENDPOINT` is set.\n\n## Output Contract\n\n- Plan mode writes `<article>.image-publish-plan.json` and leaves the Markdown unchanged.\n- Apply mode creates `<article>.bak`, writes the same plan with result details, and changes only successful local-image references.\n- Object keys use a content hash plus a sanitized filename so rep"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7f1pktwnvde1msfd8c4vz97h8254w6\",\n  \"slug\": \"md-img-r2\",\n  \"version\": \"1.0.4\",\n  \"publishedAt\": 1784815315359\n}"},{"path":"examples/expected-output-notes.md","content":"Expected plan-mode behavior:\n\n- Discovers three local images and skips the already-public URL.\n- Calculates one stable object key for each local file.\n- Writes `article.md.image-publish-plan.json`.\n- Does not change `article.md`, upload data, or create a backup.\n\nExpected reviewed-map apply behavior:\n\n- Requires both `--apply` and `--confirm-write`.\n- Creates `article.md.bak` before rewriting.\n- Replaces the three local image references while preserving the Markdown title and HTML attributes.\n- Keeps the existing public URL unchanged.\n- Records replacement details and any missing files in the plan report.\n\nSafety checks:\n\n- An upload attempt requires `--apply --confirm-upload` and all required `R2_*` environment variables.\n- A missing local image, a path outside the reviewed project root, or an incomplete URL map stops that file from being rewritten.\n- The report must never include access-key values or secret-key values."},{"path":"examples/minimal-input.md","content":"Target file: `article.md`\n\n```md\n# A reusable content workflow\n\n![Cover](./images/cover.png)\n\n<img src=\"./images/diagram.png\" alt=\"workflow diagram\">\n\n![Architecture][arch]\n\n[arch]: ./images/architecture.png \"architecture\"\n\n![Existing](https://img.example.com/already-public.png)\n```\n\nRun the first inspection without external writes:\n\n```bash\n./run.sh article.md\n```\n\nFor a reviewed local replacement test, create `replacements.json`:\n\n```json\n{\n  \"./images/cover.png\": \"https://img.example.com/md-assets/cover.png\",\n  \"./images/diagram.png\": \"https://img.example.com/md-assets/diagram.png\",\n  \"./images/architecture.png\": \"https://img.example.com/md-assets/architecture.png\"\n}\n```\n\nThen apply only after reviewing that map:\n\n```bash\n./run.sh article.md --apply --confirm-write --url-map replacements.json\n```"},{"path":"skill-card.md","content":"## Description:\n\nMarkdown Images to R2 helps agents inspect local Markdown image references, create dry-run publishing plans, and, after explicit confirmation, upload or rewrite those references for Cloudflare R2 or S3-compatible public URLs.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[yangchao228](https://clawhub.ai/user/yangchao228)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, publishing operators, and content creators use this skill to prepare Markdown files with local images for public distribution. It supports plan-first review, confirmed R2 or S3-compatible uploads, and reviewed URL-map rewrites before downstream publishing approval.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Private images, sensitive local paths, or credentials could be exposed if the skill is used on unreviewed content or with overly broad storage credentials.\n\nMitigation: Review the generated plan first, avoid private images, use least-privilege R2 credentials, and confirm that reports do not contain access-key or secret-key values.\n\nRisk: Markdown could be rewritten with incorrect or unacceptable public URLs.\n\nMitigation: Use plan mode before applying changes, require explicit upload or write confirmation, inspect the backup and replacement report, and verify resulting public URLs separately when required.\n\nRisk: Images outside the intended project root could be uploaded if outside-root access is allowed without review.\n\nMitigation: Keep outside-root access disabled by default and use --allow-outside-root only after checking the referenced paths.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/yangchao228/skills/md-img-r2)\n- [Publisher Profile](https://clawhub.ai/user/yangchao228)\n- [Project Homepage](https://github.com/yangchao228/my_open_skills/tree/main/skills/publishing/md-img-r2)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with shell commands plus JSON image-publish plan and replacement reports]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Plan mode leaves Markdown unchanged; apply mode creates a backup and rewrites only confirmed local-image references.]\n\n## Skill Version(s):\n\n1.0.4 (source: SKILL.md frontmatter and server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1337,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T23:12:46.348Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T23:12:46.348Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T01:48:23.835Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}