Compare commits

...

22 Commits

Author SHA1 Message Date
Jim Liu 宝玉 e4d4ec8334 chore: release v1.58.0 2026-03-08 22:30:46 -05:00
Jim Liu 宝玉 4935dc8b1a fix: surface agent-browser startup errors 2026-03-08 22:25:34 -05:00
Jim Liu 宝玉 c43ed57ffc Merge pull request #69 from liby/feat/xdg-config-path
feat: add XDG config path support for EXTEND.md
2026-03-08 22:19:52 -05:00
Jim Liu 宝玉 d96368492e Merge pull request #66 from luojiyin1987/fix/harden-command-exec-and-js-escaping
fix: harden command execution and JS literal escaping
2026-03-08 22:10:45 -05:00
Jim Liu 宝玉 cfc647fd38 Merge pull request #68 from luojiyin1987/docs/sync-readme-and-claude-deps
docs: sync README utility skills and CLAUDE dependency notes
2026-03-08 22:04:40 -05:00
Jim Liu 宝玉 5144335916 chore: release v1.57.0 2026-03-08 19:24:45 -05:00
Jim Liu 宝玉 fa82c3d910 refactor(baoyu-xhs-images): use skill interface instead of direct script invocation for image generation 2026-03-08 19:24:03 -05:00
Jim Liu 宝玉 90730bc551 refactor(baoyu-comic): use skill interface instead of direct script invocation for image generation 2026-03-08 19:24:02 -05:00
Jim Liu 宝玉 154ccfe3ff refactor: add openclaw metadata and rename SKILL_DIR to baseDir across all skills 2026-03-08 19:22:24 -05:00
Jim Liu 宝玉 93efa5aeb1 refactor(baoyu-comic): add openclaw metadata, baseDir rename, and decouple image skill path 2026-03-08 19:22:19 -05:00
Jim Liu 宝玉 40ccbed74a refactor(baoyu-danger-x-to-markdown): add openclaw metadata, baseDir rename, and dynamic script path 2026-03-08 19:22:18 -05:00
Jim Liu 宝玉 fbf2bc02c5 refactor(baoyu-danger-gemini-web): add openclaw metadata, baseDir rename, and dynamic script path 2026-03-08 19:22:18 -05:00
Jim Liu 宝玉 a37c80e142 feat: add ClawHub/OpenClaw publishing support 2026-03-08 19:22:13 -05:00
Jim Liu 宝玉 2e68aa64a4 chore: release v1.56.1 2026-03-08 17:42:38 -05:00
Bryan Lee a702513487 feat: add XDG config path support for EXTEND.md
Add $XDG_CONFIG_HOME/baoyu-skills/<skill>/EXTEND.md as second priority
path between project-level and legacy $HOME/.baoyu-skills/ paths.

Priority order:
1. .baoyu-skills/<skill>/EXTEND.md (project)
2. $XDG_CONFIG_HOME/baoyu-skills/<skill>/EXTEND.md (XDG, new)
3. $HOME/.baoyu-skills/<skill>/EXTEND.md (legacy fallback)

Updated: CLAUDE.md template, 16 SKILL.md files, 2 workflow.md
references, and 2 extend-config.ts runtime loaders.
2026-03-09 04:54:26 +08:00
Jim Liu 宝玉 059ebc759c fix(baoyu-post-to-weibo): simplify article image insertion with Backspace-based placeholder deletion 2026-03-08 15:49:54 -05:00
luojiyin 6b2b28b421 docs: fix CLAUDE dependency statement 2026-03-08 21:21:54 +08:00
luojiyin 0df63c3a0b docs: add markdown-to-html to README.zh utility skills 2026-03-08 21:21:54 +08:00
luojiyin 7834d632e0 docs: add markdown-to-html to README utility skills 2026-03-08 21:21:47 +08:00
luojiyin ca9a0a1404 fix: harden wechat agent-browser command and eval handling 2026-03-08 20:34:43 +08:00
luojiyin 366e7b5403 fix: use execFileSync for google curl requests 2026-03-08 20:34:39 +08:00
luojiyin 709e026be1 fix: use spawnSync for autocorrect command 2026-03-08 20:34:35 +08:00
39 changed files with 675 additions and 295 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
},
"metadata": {
"description": "Skills shared by Baoyu for improving daily work efficiency",
"version": "1.56.0"
"version": "1.58.0"
},
"plugins": [
{
+3
View File
@@ -161,3 +161,6 @@ posts/
*.ipr
.claude/skills/baoyu-skill-evolution
# ClawHub local state (current and legacy directory names from the official CLI)
.clawhub/
.clawdhub/
+31
View File
@@ -2,6 +2,37 @@
English | [中文](./CHANGELOG.zh.md)
## 1.58.0 - 2026-03-08
### Features
- Add XDG config path support for EXTEND.md (by @liby)
### Fixes
- `baoyu-post-to-wechat`: surface agent-browser startup errors
- `baoyu-post-to-wechat`: harden agent-browser command and eval handling (by @luojiyin1987)
- `baoyu-image-gen`: use execFileSync for google curl requests (by @luojiyin1987)
- `baoyu-format-markdown`: use spawnSync for autocorrect command (by @luojiyin1987)
### Documentation
- Fix CLAUDE dependency statement (by @luojiyin1987)
- Add markdown-to-html to README utility skills (by @luojiyin1987)
## 1.57.0 - 2026-03-08
### Features
- Add ClawHub/OpenClaw publishing support with sync script and README documentation
### Refactor
- Add openclaw metadata to all skill frontmatter for ClawHub registry compatibility
- Rename `SKILL_DIR` to `baseDir` across all skills for consistency
- `baoyu-danger-gemini-web`, `baoyu-danger-x-to-markdown`: dynamic script path in usage display
- `baoyu-comic`, `baoyu-xhs-images`: use skill interface instead of direct script invocation for image generation
## 1.56.1 - 2026-03-08
### Fixes
- `baoyu-post-to-weibo`: simplify article image insertion with Backspace-based placeholder deletion for ProseMirror compatibility
## 1.56.0 - 2026-03-08
### Features
+31
View File
@@ -2,6 +2,37 @@
[English](./CHANGELOG.md) | 中文
## 1.58.0 - 2026-03-08
### 新功能
- 新增 EXTEND.md 的 XDG 配置路径支持 (by @liby)
### 修复
- `baoyu-post-to-wechat`:暴露 agent-browser 启动错误信息
- `baoyu-post-to-wechat`:加固 agent-browser 命令和 eval 处理 (by @luojiyin1987)
- `baoyu-image-gen`:使用 execFileSync 替代 shell 执行 Google curl 请求 (by @luojiyin1987)
- `baoyu-format-markdown`:使用 spawnSync 替代 shell 执行 autocorrect 命令 (by @luojiyin1987)
### 文档
- 修正 CLAUDE 依赖说明 (by @luojiyin1987)
- 将 markdown-to-html 添加到 README 工具技能列表 (by @luojiyin1987)
## 1.57.0 - 2026-03-08
### 新功能
- 新增 ClawHub/OpenClaw 发布支持,包含同步脚本和 README 文档
### 重构
- 为所有 skill 前言添加 openclaw 元数据,兼容 ClawHub 注册表
- 全部 skill 中将 `SKILL_DIR` 统一重命名为 `baseDir`
- `baoyu-danger-gemini-web``baoyu-danger-x-to-markdown`:使用动态脚本路径显示用法
- `baoyu-comic``baoyu-xhs-images`:通过 skill 接口调用图片生成,不再直接调用脚本
## 1.56.1 - 2026-03-08
### 修复
- `baoyu-post-to-weibo`:简化头条文章图片插入逻辑,使用 Backspace 按键替代复杂的 deleteContents 方案,兼容 ProseMirror 编辑器
## 1.56.0 - 2026-03-08
### 新功能
+14 -8
View File
@@ -89,7 +89,7 @@ ${BUN_X} skills/baoyu-danger-gemini-web/scripts/main.ts --promptfiles system.md
- **Bun**: TypeScript runtime (native `bun` preferred, fallback `npx -y bun`)
- **Chrome**: Required for `baoyu-danger-gemini-web` auth and `baoyu-post-to-x` automation
- **No npm packages**: Self-contained TypeScript, no external dependencies
- **npm packages (per skill)**: Some skill subprojects include `package.json`/lockfiles and require dependency installation in their own `scripts/` directories
## Chrome Profile (Unified)
@@ -472,22 +472,27 @@ Check EXTEND.md existence (priority order):
\`\`\`bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/<skill-name>/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/<skill-name>/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/<skill-name>/EXTEND.md" && echo "user"
\`\`\`
\`\`\`powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/<skill-name>/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/<skill-name>/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/<skill-name>/EXTEND.md") { "user" }
\`\`\`
┌───────────────────────────────────────────────────────────────┐
Path Location │
├───────────────────────────────────────────────────────────────┤
│ .baoyu-skills/<skill-name>/EXTEND.md │ Project directory │
├───────────────────────────────────────────────────────────────┤
│ $HOME/.baoyu-skills/<skill-name>/EXTEND.md │ User home
───────────────────────────────────────────────────────────────
┌────────────────────────────────────────────────────────┬──────────────────────────┐
Path Location
├────────────────────────────────────────────────────────┼──────────────────────────┤
│ .baoyu-skills/<skill-name>/EXTEND.md │ Project directory
├────────────────────────────────────────────────────────┼──────────────────────────┤
│ $XDG_CONFIG_HOME/baoyu-skills/<skill-name>/EXTEND.md │ XDG config (~/.config)
├────────────────────────────────────────────────────────┼──────────────────────────
│ $HOME/.baoyu-skills/<skill-name>/EXTEND.md │ User home (legacy) │
└────────────────────────────────────────────────────────┴──────────────────────────┘
┌───────────┬───────────────────────────────────────────────────────────────────────────┐
│ Result │ Action │
@@ -523,5 +528,6 @@ Custom configurations via EXTEND.md. See **Preferences** section for paths and s
**Notes**:
- Replace `<skill-name>` with actual skill name (e.g., `baoyu-cover-image`)
- Use `$HOME` instead of `~` for cross-platform compatibility (macOS/Linux/WSL/PowerShell)
- `$XDG_CONFIG_HOME` defaults to `~/.config` when unset
- Use `test -f` (Bash) or `Test-Path` (PowerShell) for explicit file existence check
- ASCII tables for clear visual formatting
+37 -1
View File
@@ -17,6 +17,27 @@ Skills shared by Baoyu for improving daily work efficiency with Claude Code.
npx skills add jimliu/baoyu-skills
```
### Publish to ClawHub / OpenClaw
This repository now supports publishing each `skills/baoyu-*` directory as an individual ClawHub skill.
```bash
# Preview what would be published
./scripts/sync-clawhub.sh --dry-run
# Publish all changed skills from ./skills
./scripts/sync-clawhub.sh --all
```
ClawHub installs skills individually, not as one marketplace bundle. After publishing, users can install specific skills such as:
```bash
clawhub install baoyu-image-gen
clawhub install baoyu-markdown-to-html
```
Publishing to ClawHub releases the published skill under `MIT-0`, per ClawHub's registry rules.
### Register as Plugin Marketplace
Run the following command in Claude Code:
@@ -55,7 +76,7 @@ Simply tell Claude Code:
|--------|-------------|--------|
| **content-skills** | Content generation and publishing | [xhs-images](#baoyu-xhs-images), [infographic](#baoyu-infographic), [cover-image](#baoyu-cover-image), [slide-deck](#baoyu-slide-deck), [comic](#baoyu-comic), [article-illustrator](#baoyu-article-illustrator), [post-to-x](#baoyu-post-to-x), [post-to-wechat](#baoyu-post-to-wechat), [post-to-weibo](#baoyu-post-to-weibo) |
| **ai-generation-skills** | AI-powered generation backends | [image-gen](#baoyu-image-gen), [danger-gemini-web](#baoyu-danger-gemini-web) |
| **utility-skills** | Utility tools for content processing | [url-to-markdown](#baoyu-url-to-markdown), [danger-x-to-markdown](#baoyu-danger-x-to-markdown), [compress-image](#baoyu-compress-image), [format-markdown](#baoyu-format-markdown), [translate](#baoyu-translate) |
| **utility-skills** | Utility tools for content processing | [url-to-markdown](#baoyu-url-to-markdown), [danger-x-to-markdown](#baoyu-danger-x-to-markdown), [compress-image](#baoyu-compress-image), [format-markdown](#baoyu-format-markdown), [markdown-to-html](#baoyu-markdown-to-html), [translate](#baoyu-translate) |
## Update Skills
@@ -777,6 +798,21 @@ Format plain text or markdown files with proper frontmatter, titles, summaries,
| Code/commands | `` `inline` `` or ` ```block``` ` |
| Quotes | `>` blockquote |
#### baoyu-markdown-to-html
Convert markdown files into styled HTML with WeChat-compatible themes, syntax highlighting, and optional bottom citations for external links.
```bash
# Basic conversion
/baoyu-markdown-to-html article.md
# Theme + color
/baoyu-markdown-to-html article.md --theme grace --color red
# Convert ordinary external links to bottom citations
/baoyu-markdown-to-html article.md --cite
```
#### baoyu-translate
Translate articles and documents between languages with three modes: quick (direct), normal (analysis-informed), and refined (full publication-quality workflow with review and polish).
+37 -1
View File
@@ -17,6 +17,27 @@
npx skills add jimliu/baoyu-skills
```
### 发布到 ClawHub / OpenClaw
现在这个仓库支持把每个 `skills/baoyu-*` 目录作为独立 ClawHub skill 发布。
```bash
# 预览将要发布的变更
./scripts/sync-clawhub.sh --dry-run
# 发布 ./skills 下所有已变更的 skill
./scripts/sync-clawhub.sh --all
```
ClawHub 按“单个 skill”安装,不是把整个 marketplace 一次性装进去。发布后,用户可以按需安装:
```bash
clawhub install baoyu-image-gen
clawhub install baoyu-markdown-to-html
```
根据 ClawHub 的 registry 规则,发布到 ClawHub 的 skill 会以 `MIT-0` 许可分发。
### 注册插件市场
在 Claude Code 中运行:
@@ -55,7 +76,7 @@ npx skills add jimliu/baoyu-skills
|------|------|----------|
| **content-skills** | 内容生成和发布 | [xhs-images](#baoyu-xhs-images), [infographic](#baoyu-infographic), [cover-image](#baoyu-cover-image), [slide-deck](#baoyu-slide-deck), [comic](#baoyu-comic), [article-illustrator](#baoyu-article-illustrator), [post-to-x](#baoyu-post-to-x), [post-to-wechat](#baoyu-post-to-wechat), [post-to-weibo](#baoyu-post-to-weibo) |
| **ai-generation-skills** | AI 生成后端 | [image-gen](#baoyu-image-gen), [danger-gemini-web](#baoyu-danger-gemini-web) |
| **utility-skills** | 内容处理工具 | [url-to-markdown](#baoyu-url-to-markdown), [danger-x-to-markdown](#baoyu-danger-x-to-markdown), [compress-image](#baoyu-compress-image), [format-markdown](#baoyu-format-markdown), [translate](#baoyu-translate) |
| **utility-skills** | 内容处理工具 | [url-to-markdown](#baoyu-url-to-markdown), [danger-x-to-markdown](#baoyu-danger-x-to-markdown), [compress-image](#baoyu-compress-image), [format-markdown](#baoyu-format-markdown), [markdown-to-html](#baoyu-markdown-to-html), [translate](#baoyu-translate) |
## 更新技能
@@ -777,6 +798,21 @@ AI 驱动的生成后端。
| 代码/命令 | `` `行内` `` 或 ` ```代码块``` ` |
| 引用 | `>` 引用块 |
#### baoyu-markdown-to-html
将 Markdown 文件转换为样式化 HTML,支持微信公众号兼容主题、代码高亮,以及可选的外链底部引用。
```bash
# 基础转换
/baoyu-markdown-to-html article.md
# 主题 + 颜色
/baoyu-markdown-to-html article.md --theme grace --color red
# 将普通外链转换为文末引用
/baoyu-markdown-to-html article.md --cite
```
#### baoyu-translate
三模式翻译技能:快速(直接翻译)、标准(分析后翻译)、精翻(完整出版级工作流,含审校与润色)。
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SKILLS_DIR="${ROOT_DIR}/skills"
if command -v clawhub >/dev/null 2>&1; then
CLAWHUB_CMD=(clawhub)
elif command -v npx >/dev/null 2>&1; then
CLAWHUB_CMD=(npx -y clawhub)
else
echo "Error: neither clawhub nor npx is available."
echo "See https://docs.openclaw.ai/zh-CN/tools/clawhub"
exit 1
fi
if [ "$#" -eq 0 ]; then
set -- --all
fi
exec "${CLAWHUB_CMD[@]}" sync --root "${SKILLS_DIR}" "$@"
@@ -1,6 +1,10 @@
---
name: baoyu-article-illustrator
description: Analyzes article structure, identifies positions requiring visual aids, generates illustrations with Type × Style two-dimension approach. Use when user asks to "illustrate article", "add images", "generate images for article", or "为文章配图".
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-article-illustrator
---
# Article Illustrator
@@ -51,12 +55,15 @@ See [references/styles.md](references/styles.md) for Core Styles, full gallery,
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-article-illustrator/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-article-illustrator/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-article-illustrator/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-article-illustrator/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-article-illustrator/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-article-illustrator/EXTEND.md") { "user" }
```
@@ -88,12 +88,15 @@ Check preferences and existing state, then ask ALL needed questions in ONE AskUs
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-article-illustrator/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-article-illustrator/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-article-illustrator/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-article-illustrator/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-article-illustrator/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-article-illustrator/EXTEND.md") { "user" }
```
+21 -17
View File
@@ -1,6 +1,14 @@
---
name: baoyu-comic
description: Knowledge comic creator supporting multiple art styles and tones. Creates original educational comics with detailed panel layouts and sequential image generation. Use when user asks to create "知识漫画", "教育漫画", "biography comic", "tutorial comic", or "Logicomix-style comic".
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-comic
requires:
anyBins:
- bun
- npx
---
# Knowledge Comic Creator
@@ -104,9 +112,9 @@ Details: [references/auto-selection.md](references/auto-selection.md)
**Important**: All scripts are located in the `scripts/` subdirectory of this skill.
**Agent Execution Instructions**:
1. Determine this SKILL.md file's directory path as `SKILL_DIR`
2. Script path = `${SKILL_DIR}/scripts/<script-name>.ts`
3. Replace all `${SKILL_DIR}` in this document with the actual path
1. Determine this SKILL.md file's directory path as `{baseDir}`
2. Script path = `{baseDir}/scripts/<script-name>.ts`
3. Replace all `{baseDir}` in this document with the actual path
4. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun
**Script Reference**:
@@ -208,12 +216,11 @@ Analyze → [Check Existing?] → [Confirm: Style + Reviews] → Storyboard →
**7.1 Generate character sheet first**:
- **Backup rule**: If `characters/characters.png` exists, rename to `characters/characters-backup-YYYYMMDD-HHMMSS.png`
```bash
# Use Reference Sheet Prompt from characters/characters.md
${BUN_X} ${SKILL_DIR}/../baoyu-image-gen/scripts/main.ts \
--promptfiles characters/characters.md \
--image characters/characters.png --ar 4:3
```
- Invoke an installed image generation skill such as `baoyu-image-gen`
- Read that skill's `SKILL.md` and follow its documented interface rather than calling its scripts directly
- Use `characters/characters.md` as the prompt-file input
- Save output to `characters/characters.png`
- Use aspect ratio `4:3`
**Compress character sheet** (recommended):
Compress to reduce token usage when used as reference image:
@@ -231,14 +238,11 @@ Compress to reduce token usage when used as reference image:
**Backup rules for page generation**:
- If prompt file exists: rename to `prompts/NN-{cover|page}-[slug]-backup-YYYYMMDD-HHMMSS.md`
- If image file exists: rename to `NN-{cover|page}-[slug]-backup-YYYYMMDD-HHMMSS.png`
```bash
# Example: ALWAYS include --ref for consistency
${BUN_X} ${SKILL_DIR}/../baoyu-image-gen/scripts/main.ts \
--promptfiles prompts/01-page-xxx.md \
--image 01-page-xxx.png --ar 3:4 \
--ref characters/characters.png
```
- Invoke the installed image generation skill for each page
- Use `prompts/01-page-xxx.md` as the prompt-file input
- Save output to `01-page-xxx.png`
- Use aspect ratio `3:4`
- If the chosen skill supports reference images, pass `characters/characters.png` as `--ref`
**Full workflow details**: [references/workflow.md](references/workflow.md)
+10 -9
View File
@@ -39,12 +39,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-comic/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-comic/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-comic/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-comic/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-comic/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-comic/EXTEND.md") { "user" }
```
@@ -433,14 +436,12 @@ With confirmed prompts from Step 5/6:
**Strategy A: Using `--ref` parameter** (e.g., baoyu-image-gen)
```bash
# Each page generation MUST include --ref
${BUN_X} ${SKILL_DIR}/../baoyu-image-gen/scripts/main.ts \
--promptfiles prompts/01-page-xxx.md \
--image 01-page-xxx.png \
--ar 3:4 \
--ref characters/characters.png
```
- Read the chosen image generation skill's `SKILL.md`
- Invoke that installed skill via its documented interface, not by calling its scripts directly
- For every page, use `prompts/01-page-xxx.md` as the prompt-file input
- Save output to `01-page-xxx.png`
- Use aspect ratio `3:4`
- Pass `characters/characters.png` as `--ref` on every page generation
**Strategy B: Embedding character descriptions in prompt**
@@ -478,7 +479,7 @@ If image generation skill supports `--sessionId`:
After all images generated:
```bash
${BUN_X} ${SKILL_DIR}/scripts/merge-to-pdf.ts <comic-dir>
${BUN_X} {baseDir}/scripts/merge-to-pdf.ts <comic-dir>
```
Creates `{topic-slug}.pdf` with all pages as full-page images.
+17 -6
View File
@@ -1,6 +1,14 @@
---
name: baoyu-compress-image
description: Compresses images to WebP (default) or PNG with automatic tool selection. Use when user asks to "compress image", "optimize image", "convert to webp", or reduce image file size.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-compress-image
requires:
anyBins:
- bun
- npx
---
# Image Compressor
@@ -9,7 +17,7 @@ Compresses images using best available tool (sips → cwebp → ImageMagick →
## Script Directory
Scripts in `scripts/` subdirectory. `${SKILL_DIR}` = this SKILL.md's directory path. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun. Replace `${SKILL_DIR}` and `${BUN_X}` with actual values.
Scripts in `scripts/` subdirectory. `{baseDir}` = this SKILL.md's directory path. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun. Replace `{baseDir}` and `${BUN_X}` with actual values.
| Script | Purpose |
|--------|---------|
@@ -22,12 +30,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-compress-image/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-compress-image/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-compress-image/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-compress-image/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-compress-image/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-compress-image/EXTEND.md") { "user" }
```
@@ -52,7 +63,7 @@ if (Test-Path "$HOME/.baoyu-skills/baoyu-compress-image/EXTEND.md") { "user" }
## Usage
```bash
${BUN_X} ${SKILL_DIR}/scripts/main.ts <input> [options]
${BUN_X} {baseDir}/scripts/main.ts <input> [options]
```
## Options
@@ -71,16 +82,16 @@ ${BUN_X} ${SKILL_DIR}/scripts/main.ts <input> [options]
```bash
# Single file → WebP (replaces original)
${BUN_X} ${SKILL_DIR}/scripts/main.ts image.png
${BUN_X} {baseDir}/scripts/main.ts image.png
# Keep PNG format
${BUN_X} ${SKILL_DIR}/scripts/main.ts image.png -f png --keep
${BUN_X} {baseDir}/scripts/main.ts image.png -f png --keep
# Directory recursive
${BUN_X} ${SKILL_DIR}/scripts/main.ts ./images/ -r -q 75
${BUN_X} {baseDir}/scripts/main.ts ./images/ -r -q 75
# JSON output
${BUN_X} ${SKILL_DIR}/scripts/main.ts image.png --json
${BUN_X} {baseDir}/scripts/main.ts image.png --json
```
**Output**:
+7
View File
@@ -1,6 +1,10 @@
---
name: baoyu-cover-image
description: Generates article cover images with 5 dimensions (type, palette, rendering, text, mood) combining 10 color palettes and 7 rendering styles. Supports cinematic (2.35:1), widescreen (16:9), and square (1:1) aspects. Use when user asks to "generate cover image", "create article cover", or "make cover".
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-cover-image
---
# Cover Image Generator
@@ -130,12 +134,15 @@ Check EXTEND.md existence (priority: project → user):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-cover-image/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-cover-image/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-cover-image/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-cover-image/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-cover-image/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-cover-image/EXTEND.md") { "user" }
```
+23 -12
View File
@@ -1,6 +1,14 @@
---
name: baoyu-danger-gemini-web
description: Generates images and text via reverse-engineered Gemini Web API. Supports text generation, image generation from prompts, reference images for vision input, and multi-turn conversations. Use when other skills need image generation backend, or when user requests "generate image with Gemini", "Gemini text generation", or needs vision-capable AI generation.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-danger-gemini-web
requires:
anyBins:
- bun
- npx
---
# Gemini Web Client
@@ -12,10 +20,10 @@ Text/image generation via Gemini Web API. Supports reference images and multi-tu
**Important**: All scripts are located in the `scripts/` subdirectory of this skill.
**Agent Execution Instructions**:
1. Determine this SKILL.md file's directory path as `SKILL_DIR`
2. Script path = `${SKILL_DIR}/scripts/<script-name>.ts`
1. Determine this SKILL.md file's directory path as `{baseDir}`
2. Script path = `{baseDir}/scripts/<script-name>.ts`
3. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun
4. Replace all `${SKILL_DIR}` and `${BUN_X}` in this document with actual values
4. Replace all `{baseDir}` and `${BUN_X}` in this document with actual values
**Script Reference**:
| Script | Purpose |
@@ -49,12 +57,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-danger-gemini-web/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-danger-gemini-web/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-danger-gemini-web/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-danger-gemini-web/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-danger-gemini-web/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-danger-gemini-web/EXTEND.md") { "user" }
```
@@ -80,23 +91,23 @@ if (Test-Path "$HOME/.baoyu-skills/baoyu-danger-gemini-web/EXTEND.md") { "user"
```bash
# Text generation
${BUN_X} ${SKILL_DIR}/scripts/main.ts "Your prompt"
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "Your prompt" --model gemini-3-flash
${BUN_X} {baseDir}/scripts/main.ts "Your prompt"
${BUN_X} {baseDir}/scripts/main.ts --prompt "Your prompt" --model gemini-3-flash
# Image generation
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A cute cat" --image cat.png
${BUN_X} ${SKILL_DIR}/scripts/main.ts --promptfiles system.md content.md --image out.png
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cute cat" --image cat.png
${BUN_X} {baseDir}/scripts/main.ts --promptfiles system.md content.md --image out.png
# Vision input (reference images)
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "Describe this" --reference image.png
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "Create variation" --reference a.png --image out.png
${BUN_X} {baseDir}/scripts/main.ts --prompt "Describe this" --reference image.png
${BUN_X} {baseDir}/scripts/main.ts --prompt "Create variation" --reference a.png --image out.png
# Multi-turn conversation
${BUN_X} ${SKILL_DIR}/scripts/main.ts "Remember: 42" --sessionId session-abc
${BUN_X} ${SKILL_DIR}/scripts/main.ts "What number?" --sessionId session-abc
${BUN_X} {baseDir}/scripts/main.ts "Remember: 42" --sessionId session-abc
${BUN_X} {baseDir}/scripts/main.ts "What number?" --sessionId session-abc
# JSON output
${BUN_X} ${SKILL_DIR}/scripts/main.ts "Hello" --json
${BUN_X} {baseDir}/scripts/main.ts "Hello" --json
```
## Options
+21 -6
View File
@@ -59,16 +59,31 @@ function normalizeSessionMetadata(input: unknown): Array<string | null> {
return [null, null, null];
}
function formatScriptCommand(fallback: string): string {
const raw = process.argv[1];
const displayPath = raw
? (() => {
const relative = path.relative(process.cwd(), raw);
return relative && !relative.startsWith("..") ? relative : raw;
})()
: fallback;
const quotedPath = displayPath.includes(" ")
? `"${displayPath.replace(/"/g, '\\"')}"`
: displayPath;
return `npx -y bun ${quotedPath}`;
}
function printUsage(cookiePath: string, profileDir: string): void {
const cmd = formatScriptCommand("scripts/main.ts");
console.log(`Usage:
npx -y bun skills/baoyu-danger-gemini-web/scripts/main.ts --prompt "Hello"
npx -y bun skills/baoyu-danger-gemini-web/scripts/main.ts "Hello"
npx -y bun skills/baoyu-danger-gemini-web/scripts/main.ts --prompt "A cute cat" --image generated.png
npx -y bun skills/baoyu-danger-gemini-web/scripts/main.ts --promptfiles system.md content.md --image out.png
${cmd} --prompt "Hello"
${cmd} "Hello"
${cmd} --prompt "A cute cat" --image generated.png
${cmd} --promptfiles system.md content.md --image out.png
Multi-turn conversation (agent generates unique sessionId):
npx -y bun skills/baoyu-danger-gemini-web/scripts/main.ts "Remember 42" --sessionId abc123
npx -y bun skills/baoyu-danger-gemini-web/scripts/main.ts "What number?" --sessionId abc123
${cmd} "Remember 42" --sessionId abc123
${cmd} "What number?" --sessionId abc123
Options:
-p, --prompt <text> Prompt text
+17 -6
View File
@@ -1,6 +1,14 @@
---
name: baoyu-danger-x-to-markdown
description: Converts X (Twitter) tweets and articles to markdown with YAML front matter. Uses reverse-engineered API requiring user consent. Use when user mentions "X to markdown", "tweet to markdown", "save tweet", or provides x.com/twitter.com URLs for conversion.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-danger-x-to-markdown
requires:
anyBins:
- bun
- npx
---
# X to Markdown
@@ -14,8 +22,8 @@ Converts X content to markdown:
Scripts located in `scripts/` subdirectory.
**Path Resolution**:
1. `SKILL_DIR` = this SKILL.md's directory
2. Script path = `${SKILL_DIR}/scripts/main.ts`
1. `{baseDir}` = this SKILL.md's directory
2. Script path = `{baseDir}/scripts/main.ts`
3. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun
## Consent Requirement
@@ -75,12 +83,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-danger-x-to-markdown/EXTEND.md") { "user" }
```
@@ -140,10 +151,10 @@ Full reference: [references/config/first-time-setup.md](references/config/first-
## Usage
```bash
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url>
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url> -o output.md
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url> --download-media
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url> --json
${BUN_X} {baseDir}/scripts/main.ts <url>
${BUN_X} {baseDir}/scripts/main.ts <url> -o output.md
${BUN_X} {baseDir}/scripts/main.ts <url> --download-media
${BUN_X} {baseDir}/scripts/main.ts <url> --json
```
## Options
@@ -30,8 +30,22 @@ type ConsentRecord = {
const DISCLAIMER_VERSION = "1.0";
function formatScriptCommand(fallback: string): string {
const raw = process.argv[1];
const displayPath = raw
? (() => {
const relative = path.relative(process.cwd(), raw);
return relative && !relative.startsWith("..") ? relative : raw;
})()
: fallback;
const quotedPath = displayPath.includes(" ")
? `"${displayPath.replace(/"/g, '\\"')}"`
: displayPath;
return `npx -y bun ${quotedPath}`;
}
function printUsage(exitCode: number): never {
const cmd = "npx -y bun skills/baoyu-danger-x-to-markdown/scripts/main.ts";
const cmd = formatScriptCommand("scripts/main.ts");
console.log(`X (Twitter) to Markdown
Usage:
@@ -36,6 +36,20 @@ function normalizeInputUrl(input: string): string {
}
}
function formatScriptCommand(fallback: string): string {
const raw = process.argv[1];
const displayPath = raw
? (() => {
const relative = path.relative(process.cwd(), raw);
return relative && !relative.startsWith("..") ? relative : raw;
})()
: fallback;
const quotedPath = displayPath.includes(" ")
? `"${displayPath.replace(/"/g, '\\"')}"`
: displayPath;
return `npx -y bun ${quotedPath}`;
}
function parseTweetId(input: string): string | null {
const trimmed = input.trim();
if (!trimmed) return null;
@@ -179,7 +193,7 @@ async function main() {
const { url } = parseArgs();
if (!url) {
console.error("Usage:");
console.error(" npx -y bun skills/baoyu-danger-x-to-markdown/scripts/tweet-to-markdown.ts <tweet url>");
console.error(` ${formatScriptCommand("scripts/tweet-to-markdown.ts")} <tweet url>`);
process.exit(1);
}
+16 -5
View File
@@ -1,6 +1,14 @@
---
name: baoyu-format-markdown
description: Formats plain text or markdown files with frontmatter, titles, summaries, headings, bold, lists, and code blocks. Use when user asks to "format markdown", "beautify article", "add formatting", or improve article layout. Outputs to {filename}-formatted.md.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-format-markdown
requires:
anyBins:
- bun
- npx
---
# Markdown Formatter
@@ -11,7 +19,7 @@ Transforms plain text or markdown into well-structured, reader-friendly markdown
## Script Directory
Scripts in `scripts/` subdirectory. `${SKILL_DIR}` = this SKILL.md's directory path. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun. Replace `${SKILL_DIR}` and `${BUN_X}` with actual values.
Scripts in `scripts/` subdirectory. `{baseDir}` = this SKILL.md's directory path. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun. Replace `{baseDir}` and `${BUN_X}` with actual values.
| Script | Purpose |
|--------|---------|
@@ -26,12 +34,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-format-markdown/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-format-markdown/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-format-markdown/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-format-markdown/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-format-markdown/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-format-markdown/EXTEND.md") { "user" }
```
@@ -296,7 +307,7 @@ fi
Run the formatting script on the output file:
```bash
${BUN_X} ${SKILL_DIR}/scripts/main.ts {output-file-path} [options]
${BUN_X} {baseDir}/scripts/main.ts {output-file-path} [options]
```
**Script Options:**
@@ -314,13 +325,13 @@ ${BUN_X} ${SKILL_DIR}/scripts/main.ts {output-file-path} [options]
```bash
# Default: spacing + emphasis enabled, quotes disabled
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md
${BUN_X} {baseDir}/scripts/main.ts article.md
# Enable all features including quote replacement
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md --quotes
${BUN_X} {baseDir}/scripts/main.ts article.md --quotes
# Only fix emphasis issues, skip spacing
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md --no-spacing
${BUN_X} {baseDir}/scripts/main.ts article.md --no-spacing
```
**Script performs (based on options):**
@@ -1,10 +1,10 @@
import { execSync } from "child_process";
import { spawnSync } from "node:child_process";
import process from "node:process";
export function applyAutocorrect(filePath: string): boolean {
try {
execSync(`npx autocorrect-node --fix "${filePath}"`, { stdio: "inherit" });
return true;
} catch {
return false;
}
const npxCmd = process.platform === "win32" ? "npx.cmd" : "npx";
const result = spawnSync(npxCmd, ["autocorrect-node", "--fix", filePath], {
stdio: "inherit",
});
return result.status === 0;
}
+25 -14
View File
@@ -1,6 +1,14 @@
---
name: baoyu-image-gen
description: AI image generation with OpenAI, Google, DashScope and Replicate APIs. Supports text-to-image, reference images, aspect ratios. Sequential by default; parallel generation available on request. Use when user asks to generate, create, or draw images.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-image-gen
requires:
anyBins:
- bun
- npx
---
# Image Generation (AI SDK)
@@ -10,8 +18,8 @@ Official API-based image generation. Supports OpenAI, Google, DashScope (阿里
## Script Directory
**Agent Execution**:
1. `SKILL_DIR` = this SKILL.md file's directory
2. Script path = `${SKILL_DIR}/scripts/main.ts`
1. `{baseDir}` = this SKILL.md file's directory
2. Script path = `{baseDir}/scripts/main.ts`
3. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun
## Step 0: Load Preferences ⛔ BLOCKING
@@ -23,12 +31,15 @@ Check EXTEND.md existence (priority: project → user):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-image-gen/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-image-gen/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-image-gen/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-image-gen/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-image-gen/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-image-gen/EXTEND.md") { "user" }
```
@@ -52,34 +63,34 @@ Schema: `references/config/preferences-schema.md`
```bash
# Basic
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A cat" --image cat.png
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image cat.png
# With aspect ratio
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A landscape" --image out.png --ar 16:9
${BUN_X} {baseDir}/scripts/main.ts --prompt "A landscape" --image out.png --ar 16:9
# High quality
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A cat" --image out.png --quality 2k
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --quality 2k
# From prompt files
${BUN_X} ${SKILL_DIR}/scripts/main.ts --promptfiles system.md content.md --image out.png
${BUN_X} {baseDir}/scripts/main.ts --promptfiles system.md content.md --image out.png
# With reference images (Google multimodal or OpenAI edits)
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "Make blue" --image out.png --ref source.png
${BUN_X} {baseDir}/scripts/main.ts --prompt "Make blue" --image out.png --ref source.png
# With reference images (explicit provider/model)
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "Make blue" --image out.png --provider google --model gemini-3-pro-image-preview --ref source.png
${BUN_X} {baseDir}/scripts/main.ts --prompt "Make blue" --image out.png --provider google --model gemini-3-pro-image-preview --ref source.png
# Specific provider
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A cat" --image out.png --provider openai
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider openai
# DashScope (阿里通义万象)
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "一只可爱的猫" --image out.png --provider dashscope
${BUN_X} {baseDir}/scripts/main.ts --prompt "一只可爱的猫" --image out.png --provider dashscope
# Replicate (google/nano-banana-pro)
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A cat" --image out.png --provider replicate
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider replicate
# Replicate with specific model
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A cat" --image out.png --provider replicate --model google/nano-banana
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider replicate --model google/nano-banana
```
## Options
@@ -144,10 +155,10 @@ Examples:
```bash
# Use Replicate default model
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A cat" --image out.png --provider replicate
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider replicate
# Override model explicitly
${BUN_X} ${SKILL_DIR}/scripts/main.ts --prompt "A cat" --image out.png --provider replicate --model google/nano-banana
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider replicate --model google/nano-banana
```
## Provider Selection
@@ -1,6 +1,6 @@
import path from "node:path";
import { readFile } from "node:fs/promises";
import { execSync } from "node:child_process";
import { execFileSync } from "node:child_process";
import type { CliArgs } from "../types";
const GOOGLE_MULTIMODAL_MODELS = [
@@ -76,14 +76,43 @@ async function postGoogleJsonViaCurl<T>(
): Promise<T> {
const proxy = getHttpProxy();
const bodyStr = JSON.stringify(body);
const proxyArgs = proxy ? `-x "${proxy}"` : "";
const args = [
"-s",
"--connect-timeout",
"30",
"--max-time",
"300",
...(proxy ? ["-x", proxy] : []),
url,
"-H",
"Content-Type: application/json",
"-H",
`x-goog-api-key: ${apiKey}`,
"-d",
"@-",
];
const result = execSync(
`curl -s --connect-timeout 30 --max-time 300 ${proxyArgs} "${url}" -H "Content-Type: application/json" -H "x-goog-api-key: ${apiKey}" -d @-`,
{ input: bodyStr, maxBuffer: 100 * 1024 * 1024, timeout: 310000 },
);
let result = "";
try {
result = execFileSync("curl", args, {
input: bodyStr,
encoding: "utf8",
maxBuffer: 100 * 1024 * 1024,
timeout: 310000,
});
} catch (error) {
const e = error as { message?: string; stderr?: string | Buffer };
const stderrText =
typeof e.stderr === "string"
? e.stderr
: e.stderr
? e.stderr.toString("utf8")
: "";
const details = stderrText.trim() || e.message || "curl request failed";
throw new Error(`Google API request failed via curl: ${details}`);
}
const parsed = JSON.parse(result.toString()) as any;
const parsed = JSON.parse(result) as any;
if (parsed.error) {
throw new Error(
`Google API error (${parsed.error.code}): ${parsed.error.message}`,
+7
View File
@@ -1,6 +1,10 @@
---
name: baoyu-infographic
description: Generates professional infographics with 21 layout types and 20 visual styles. Analyzes content, recommends layout×style combinations, and generates publication-ready infographics. Use when user asks to create "infographic", "信息图", "visual summary", "可视化", or "高密度信息大图".
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-infographic
---
# Infographic Generator
@@ -143,12 +147,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-infographic/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-infographic/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-infographic/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-infographic/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-infographic/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-infographic/EXTEND.md") { "user" }
```
+20 -9
View File
@@ -1,6 +1,14 @@
---
name: baoyu-markdown-to-html
description: Converts Markdown to styled HTML with WeChat-compatible themes. Supports code highlighting, math, PlantUML, footnotes, alerts, infographics, and optional bottom citations for external links. Use when user asks for "markdown to html", "convert md to html", "md转html", "微信外链转底部引用", or needs styled HTML output from markdown.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-markdown-to-html
requires:
anyBins:
- bun
- npx
---
# Markdown to HTML Converter
@@ -9,7 +17,7 @@ Converts Markdown files to beautifully styled HTML with inline CSS, optimized fo
## Script Directory
**Agent Execution**: Determine this SKILL.md directory as `SKILL_DIR`. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun. Replace `${SKILL_DIR}` and `${BUN_X}` with actual values.
**Agent Execution**: Determine this SKILL.md directory as `{baseDir}`. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun. Replace `{baseDir}` and `${BUN_X}` with actual values.
| Script | Purpose |
|--------|---------|
@@ -22,12 +30,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-markdown-to-html/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-markdown-to-html/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-markdown-to-html/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-markdown-to-html/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-markdown-to-html/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-markdown-to-html/EXTEND.md") { "user" }
```
@@ -117,7 +128,7 @@ if (Test-Path "$HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md") { Select-Str
### Step 2: Convert
```bash
${BUN_X} ${SKILL_DIR}/scripts/main.ts <markdown_file> --theme <theme> [--cite]
${BUN_X} {baseDir}/scripts/main.ts <markdown_file> --theme <theme> [--cite]
```
### Step 3: Report Result
@@ -127,7 +138,7 @@ Display the output path from JSON result. If backup was created, mention it.
## Usage
```bash
${BUN_X} ${SKILL_DIR}/scripts/main.ts <markdown_file> [options]
${BUN_X} {baseDir}/scripts/main.ts <markdown_file> [options]
```
**Options:**
@@ -165,22 +176,22 @@ ${BUN_X} ${SKILL_DIR}/scripts/main.ts <markdown_file> [options]
```bash
# Basic conversion (uses default theme, removes first heading)
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md
${BUN_X} {baseDir}/scripts/main.ts article.md
# With specific theme
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md --theme grace
${BUN_X} {baseDir}/scripts/main.ts article.md --theme grace
# Theme with custom color
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md --theme modern --color red
${BUN_X} {baseDir}/scripts/main.ts article.md --theme modern --color red
# Enable bottom citations for ordinary external links
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md --cite
${BUN_X} {baseDir}/scripts/main.ts article.md --cite
# Keep the first heading in content
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md --keep-title
${BUN_X} {baseDir}/scripts/main.ts article.md --keep-title
# Override title
${BUN_X} ${SKILL_DIR}/scripts/main.ts article.md --title "My Article"
${BUN_X} {baseDir}/scripts/main.ts article.md --title "My Article"
```
## Output
@@ -37,6 +37,10 @@ function parseExtendYaml(yaml: string): Partial<ExtendConfig> {
export function loadExtendConfig(): Partial<ExtendConfig> {
const paths = [
path.join(process.cwd(), ".baoyu-skills", "baoyu-markdown-to-html", "EXTEND.md"),
path.join(
process.env.XDG_CONFIG_HOME || path.join(homedir(), ".config"),
"baoyu-skills", "baoyu-markdown-to-html", "EXTEND.md"
),
path.join(homedir(), ".baoyu-skills", "baoyu-markdown-to-html", "EXTEND.md"),
];
for (const p of paths) {
+18 -7
View File
@@ -1,6 +1,14 @@
---
name: baoyu-post-to-wechat
description: Posts content to WeChat Official Account (微信公众号) via API or Chrome CDP. Supports article posting (文章) with HTML, markdown, or plain text input, and image-text posting (贴图, formerly 图文) with multiple images. Markdown article workflows default to converting ordinary external links into bottom citations for WeChat-friendly output. Use when user mentions "发布公众号", "post to wechat", "微信公众号", or "贴图/图文/文章".
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-post-to-wechat
requires:
anyBins:
- bun
- npx
---
# Post to WeChat Official Account
@@ -11,7 +19,7 @@ description: Posts content to WeChat Official Account (微信公众号) via API
## Script Directory
**Agent Execution**: Determine this SKILL.md directory as `SKILL_DIR`, then use `${SKILL_DIR}/scripts/<name>.ts`. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun.
**Agent Execution**: Determine this SKILL.md directory as `{baseDir}`, then use `{baseDir}/scripts/<name>.ts`. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun.
| Script | Purpose |
|--------|---------|
@@ -28,12 +36,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-post-to-wechat/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-post-to-wechat/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-post-to-wechat/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-post-to-wechat/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-post-to-wechat/EXTEND.md") { "user" }
```
@@ -92,7 +103,7 @@ chrome_profile_path: /path/to/chrome/profile
Before first use, suggest running the environment check. User can skip if they prefer.
```bash
${BUN_X} ${SKILL_DIR}/scripts/check-permissions.ts
${BUN_X} {baseDir}/scripts/check-permissions.ts
```
Checks: Chrome, profile isolation, Bun, Accessibility, clipboard, paste keystroke, API credentials, Chrome conflicts.
@@ -115,8 +126,8 @@ Checks: Chrome, profile isolation, Bun, Accessibility, clipboard, paste keystrok
For short posts with multiple images (up to 9):
```bash
${BUN_X} ${SKILL_DIR}/scripts/wechat-browser.ts --markdown article.md --images ./images/
${BUN_X} ${SKILL_DIR}/scripts/wechat-browser.ts --title "标题" --content "内容" --image img.png --submit
${BUN_X} {baseDir}/scripts/wechat-browser.ts --markdown article.md --images ./images/
${BUN_X} {baseDir}/scripts/wechat-browser.ts --title "标题" --content "内容" --image img.png --submit
```
See [references/image-text-posting.md](references/image-text-posting.md) for details.
@@ -260,7 +271,7 @@ WECHAT_APP_SECRET=<user_input>
**API method** (accepts `.md` or `.html`):
```bash
${BUN_X} ${SKILL_DIR}/scripts/wechat-api.ts <file> --theme <theme> [--color <color>] [--title <title>] [--summary <summary>] [--author <author>] [--cover <cover_path>] [--no-cite]
${BUN_X} {baseDir}/scripts/wechat-api.ts <file> --theme <theme> [--color <color>] [--title <title>] [--summary <summary>] [--author <author>] [--cover <cover_path>] [--no-cite]
```
**CRITICAL**: Always include `--theme` parameter. Never omit it, even if using `default`. Only include `--color` if explicitly set by user or EXTEND.md.
@@ -279,8 +290,8 @@ If script parameters do not expose the two comment fields, still ensure final AP
**Browser method** (accepts `--markdown` or `--html`):
```bash
${BUN_X} ${SKILL_DIR}/scripts/wechat-article.ts --markdown <markdown_file> --theme <theme> [--color <color>] [--no-cite]
${BUN_X} ${SKILL_DIR}/scripts/wechat-article.ts --html <html_file>
${BUN_X} {baseDir}/scripts/wechat-article.ts --markdown <markdown_file> --theme <theme> [--color <color>] [--no-cite]
${BUN_X} {baseDir}/scripts/wechat-article.ts --html <html_file>
```
### Step 5: Completion Report
@@ -37,6 +37,10 @@ function parseExtendYaml(yaml: string): Partial<ExtendConfig> {
export function loadExtendConfig(): Partial<ExtendConfig> {
const paths = [
path.join(process.cwd(), ".baoyu-skills", "baoyu-markdown-to-html", "EXTEND.md"),
path.join(
process.env.XDG_CONFIG_HOME || path.join(homedir(), ".config"),
"baoyu-skills", "baoyu-markdown-to-html", "EXTEND.md"
),
path.join(homedir(), ".baoyu-skills", "baoyu-markdown-to-html", "EXTEND.md"),
];
for (const p of paths) {
@@ -1,4 +1,4 @@
import { execSync, spawnSync } from 'node:child_process';
import { spawnSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
@@ -10,30 +10,51 @@ function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function ab(cmd: string, json = false): string {
const fullCmd = `agent-browser --session ${SESSION} ${cmd}${json ? ' --json' : ''}`;
console.log(`[ab] ${fullCmd}`);
try {
const result = execSync(fullCmd, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
return result.trim();
} catch (e: unknown) {
const err = e as { stdout?: string; stderr?: string; message?: string };
console.error(`[ab] Error: ${err.stderr || err.message}`);
return err.stdout || '';
}
function quoteForLog(arg: string): string {
return /[\s"'\\]/.test(arg) ? JSON.stringify(arg) : arg;
}
function abRaw(args: string[]): { success: boolean; output: string } {
function toSafeJsStringLiteral(value: string): string {
return JSON.stringify(value)
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029');
}
function runAgentBrowser(args: string[]): {
success: boolean;
output: string;
spawnError?: string;
} {
const result = spawnSync('agent-browser', ['--session', SESSION, ...args], {
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe']
});
const spawnError = result.error?.message?.trim();
const output = result.stdout || result.stderr || '';
return {
success: result.status === 0,
output: result.stdout || result.stderr || ''
output: output || spawnError || '',
spawnError
};
}
function ab(args: string[], json = false): string {
const fullArgs = json ? [...args, '--json'] : args;
console.log(`[ab] agent-browser --session ${SESSION} ${fullArgs.map(quoteForLog).join(' ')}`);
const result = runAgentBrowser(fullArgs);
if (result.spawnError) {
throw new Error(`agent-browser failed to start: ${result.spawnError}`);
}
if (!result.success) {
console.error(`[ab] Error: ${result.output.trim()}`);
}
return result.output.trim();
}
function abRaw(args: string[]): { success: boolean; output: string } {
return runAgentBrowser(args);
}
interface SnapshotElement {
ref: string;
role: string;
@@ -99,17 +120,17 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
}
console.log('[wechat] Opening WeChat Official Account...');
ab(`open ${WECHAT_URL} --headed`);
ab(['open', WECHAT_URL, '--headed']);
await sleep(5000);
console.log('[wechat] Checking login status...');
let url = ab('get url');
let url = ab(['get', 'url']);
console.log(`[wechat] Current URL: ${url}`);
const waitForLogin = async (timeoutMs = 120_000): Promise<boolean> => {
const start = Date.now();
while (Date.now() - start < timeoutMs) {
url = ab('get url');
url = ab(['get', 'url']);
if (url.includes('/cgi-bin/home')) return true;
console.log('[wechat] Waiting for login...');
await sleep(3000);
@@ -126,7 +147,7 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
await sleep(2000);
console.log('[wechat] Getting page snapshot...');
let snapshot = ab('snapshot');
let snapshot = ab(['snapshot']);
console.log(snapshot);
console.log('[wechat] Looking for "图文" menu...');
@@ -134,16 +155,16 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
if (!tuWenRef) {
console.log('[wechat] Using eval to find and click menu...');
ab(`eval "document.querySelectorAll('.new-creation__menu .new-creation__menu-item')[2].click()"`);
ab(['eval', "document.querySelectorAll('.new-creation__menu .new-creation__menu-item')[2].click()"]);
} else {
console.log(`[wechat] Clicking menu ref: ${tuWenRef}`);
ab(`click ${tuWenRef}`);
ab(['click', tuWenRef]);
}
await sleep(4000);
console.log('[wechat] Checking for new tab...');
const tabsOutput = ab('tab');
const tabsOutput = ab(['tab']);
console.log(`[wechat] Tabs: ${tabsOutput}`);
const tabLines = tabsOutput.split('\n');
@@ -153,14 +174,14 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
const tabMatch = tabsOutput.match(/\[(\d+)\].*(?:appmsg|edit)/i);
if (tabMatch) {
console.log(`[wechat] Switching to editor tab ${tabMatch[1]}...`);
ab(`tab ${tabMatch[1]}`);
ab(['tab', tabMatch[1]]);
} else {
const lastTabMatch = tabsOutput.match(/\[(\d+)\]/g);
if (lastTabMatch && lastTabMatch.length > 1) {
const lastTab = lastTabMatch[lastTabMatch.length - 1].match(/\d+/)?.[0];
if (lastTab) {
console.log(`[wechat] Switching to last tab ${lastTab}...`);
ab(`tab ${lastTab}`);
ab(['tab', lastTab]);
}
}
}
@@ -168,38 +189,44 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
await sleep(3000);
url = ab('get url');
url = ab(['get', 'url']);
console.log(`[wechat] Editor URL: ${url}`);
console.log('[wechat] Getting editor snapshot...');
snapshot = ab('snapshot');
snapshot = ab(['snapshot']);
console.log(snapshot.substring(0, 2000));
console.log('[wechat] Uploading images...');
const fileInputSelector = '.js_upload_btn_container input[type=file]';
const fileInputSelectorJs = toSafeJsStringLiteral(fileInputSelector);
ab(`eval "document.querySelector('${fileInputSelector}').style.display = 'block'"`);
ab(['eval', `{
const input = document.querySelector(${fileInputSelectorJs});
if (input) input.style.display = 'block';
}`]);
await sleep(500);
const uploadResult = abRaw(['upload', `"${fileInputSelector}"`, ...absoluteImages]);
const uploadResult = abRaw(['upload', fileInputSelector, ...absoluteImages]);
console.log(`[wechat] Upload result: ${uploadResult.output}`);
if (!uploadResult.success) {
console.log('[wechat] Using alternative upload method...');
for (const img of absoluteImages) {
console.log(`[wechat] Uploading: ${img}`);
ab(`eval "
const input = document.querySelector('${fileInputSelector}');
const imgUrlJs = toSafeJsStringLiteral(`file://${img}`);
const imgFileNameJs = toSafeJsStringLiteral(path.basename(img));
ab(['eval', `
const input = document.querySelector(${fileInputSelectorJs});
if (input) {
const dt = new DataTransfer();
fetch('file://${img}').then(r => r.blob()).then(b => {
const file = new File([b], '${path.basename(img)}', { type: 'image/png' });
fetch(${imgUrlJs}).then(r => r.blob()).then(b => {
const file = new File([b], ${imgFileNameJs}, { type: 'image/png' });
dt.items.add(file);
input.files = dt.files;
input.dispatchEvent(new Event('change', { bubbles: true }));
});
}
"`);
`]);
await sleep(2000);
}
}
@@ -208,13 +235,14 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
await sleep(10000);
console.log('[wechat] Filling title...');
snapshot = ab('snapshot -i');
snapshot = ab(['snapshot', '-i']);
const titleRef = findElementByText(snapshot, 'title') || findElementByText(snapshot, '标题');
if (titleRef) {
ab(`fill ${titleRef} "${title.replace(/"/g, '\\"')}"`);
ab(['fill', titleRef, title]);
} else {
ab(`eval "const t = document.querySelector('#title'); if(t) { t.value = '${title.replace(/'/g, "\\'")}'; t.dispatchEvent(new Event('input', {bubbles: true})); }"`);
const titleJs = toSafeJsStringLiteral(title);
ab(['eval', `const t = document.querySelector('#title'); if(t) { t.value = ${titleJs}; t.dispatchEvent(new Event('input', {bubbles: true})); }`]);
}
await sleep(500);
@@ -222,9 +250,9 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
const editorRef = findElementByText(snapshot, 'js_pmEditorArea') || findElementByText(snapshot, 'textbox');
if (editorRef) {
ab(`click ${editorRef}`);
ab(['click', editorRef]);
} else {
ab(`eval "document.querySelector('.js_pmEditorArea')?.click()"`);
ab(['eval', "document.querySelector('.js_pmEditorArea')?.click()"]);
}
await sleep(500);
@@ -233,11 +261,11 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.length > 0) {
const escapedLine = line.replace(/"/g, '\\"').replace(/'/g, "\\'");
ab(`eval "document.execCommand('insertText', false, '${escapedLine}')"`);
const lineJs = toSafeJsStringLiteral(line);
ab(['eval', `document.execCommand('insertText', false, ${lineJs})`]);
}
if (i < lines.length - 1) {
ab('press Enter');
ab(['press', 'Enter']);
}
await sleep(100);
}
@@ -249,9 +277,9 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
console.log('[wechat] Saving as draft...');
const submitRef = findElementByText(snapshot, 'js_submit') || findElementByText(snapshot, '保存');
if (submitRef) {
ab(`click ${submitRef}`);
ab(['click', submitRef]);
} else {
ab(`eval "document.querySelector('#js_submit')?.click()"`);
ab(['eval', "document.querySelector('#js_submit')?.click()"]);
}
await sleep(3000);
console.log('[wechat] Draft saved!');
@@ -261,7 +289,7 @@ async function postToWeChat(options: WeChatOptions): Promise<void> {
if (!keepOpen) {
console.log('[wechat] Closing browser...');
ab('close');
ab(['close']);
} else {
console.log('[wechat] Done. Browser window left open.');
}
+18 -7
View File
@@ -1,6 +1,14 @@
---
name: baoyu-post-to-weibo
description: Posts content to Weibo (微博). Supports regular posts with text, images, and videos, and headline articles (头条文章) with Markdown input via Chrome CDP. Use when user asks to "post to Weibo", "发微博", "发布微博", "publish to Weibo", "share on Weibo", "写微博", or "微博头条文章".
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-post-to-weibo
requires:
anyBins:
- bun
- npx
---
# Post to Weibo
@@ -12,9 +20,9 @@ Posts text, images, videos, and long-form articles to Weibo via real Chrome brow
**Important**: All scripts are located in the `scripts/` subdirectory of this skill.
**Agent Execution Instructions**:
1. Determine this SKILL.md file's directory path as `SKILL_DIR`
2. Script path = `${SKILL_DIR}/scripts/<script-name>.ts`
3. Replace all `${SKILL_DIR}` in this document with the actual path
1. Determine this SKILL.md file's directory path as `{baseDir}`
2. Script path = `{baseDir}/scripts/<script-name>.ts`
3. Replace all `{baseDir}` in this document with the actual path
4. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun
**Script Reference**:
@@ -32,12 +40,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-post-to-weibo/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-post-to-weibo/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-post-to-weibo/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-post-to-weibo/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-post-to-weibo/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-post-to-weibo/EXTEND.md") { "user" }
```
@@ -72,8 +83,8 @@ if (Test-Path "$HOME/.baoyu-skills/baoyu-post-to-weibo/EXTEND.md") { "user" }
Text + images/videos (max 18 files total). Posted on Weibo homepage.
```bash
${BUN_X} ${SKILL_DIR}/scripts/weibo-post.ts "Hello Weibo!" --image ./photo.png
${BUN_X} ${SKILL_DIR}/scripts/weibo-post.ts "Watch this" --video ./clip.mp4
${BUN_X} {baseDir}/scripts/weibo-post.ts "Hello Weibo!" --image ./photo.png
${BUN_X} {baseDir}/scripts/weibo-post.ts "Watch this" --video ./clip.mp4
```
**Parameters**:
@@ -93,8 +104,8 @@ ${BUN_X} ${SKILL_DIR}/scripts/weibo-post.ts "Watch this" --video ./clip.mp4
Long-form Markdown articles published at `https://card.weibo.com/article/v3/editor`.
```bash
${BUN_X} ${SKILL_DIR}/scripts/weibo-article.ts article.md
${BUN_X} ${SKILL_DIR}/scripts/weibo-article.ts article.md --cover ./cover.jpg
${BUN_X} {baseDir}/scripts/weibo-article.ts article.md
${BUN_X} {baseDir}/scripts/weibo-article.ts article.md --cover ./cover.jpg
```
**Parameters**:
@@ -459,7 +459,7 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
if (charAfter === undefined || !/\\d/.test(charAfter)) {
const parentElement = node.parentElement;
if (parentElement) {
parentElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
parentElement.scrollIntoView({ behavior: 'instant', block: 'center' });
}
const range = document.createRange();
@@ -500,112 +500,56 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
return false;
};
// Step A: Copy image to clipboard first (slow due to Swift compilation)
console.log(`[weibo-article] Copying image to clipboard: ${path.basename(img.localPath)}`);
if (!copyImageToClipboard(img.localPath)) {
console.warn(`[weibo-article] Failed to copy image to clipboard`);
continue;
}
await sleep(500);
// Step B: Select placeholder text (paste will replace the selection)
const selected = await selectPlaceholder(3);
if (!selected) {
console.warn(`[weibo-article] Skipping image - could not select placeholder: ${img.placeholder}`);
continue;
}
console.log(`[weibo-article] Copying image: ${path.basename(img.localPath)}`);
if (!copyImageToClipboard(img.localPath)) {
console.warn(`[weibo-article] Failed to copy image to clipboard`);
continue;
}
await sleep(1000);
// Delete placeholder by replacing selection with empty text
console.log(`[weibo-article] Deleting placeholder...`);
await cdp.send('Runtime.evaluate', {
expression: `(() => {
const sel = window.getSelection();
if (!sel || sel.isCollapsed) return false;
const range = sel.getRangeAt(0);
range.deleteContents();
sel.collapseToStart();
return true;
})()`,
returnByValue: true,
}, { sessionId });
await sleep(300);
// Fallback: send Backspace key if placeholder still exists
const stillExists = await cdp!.send<{ result: { value: boolean } }>('Runtime.evaluate', {
expression: `(() => {
const editor = document.querySelector('div[contenteditable="true"]');
if (!editor) return false;
const placeholder = ${JSON.stringify(img.placeholder)};
const regex = new RegExp(placeholder + '(?!\\\\d)');
return regex.test(editor.innerText);
})()`,
returnByValue: true,
}, { sessionId });
if (stillExists.result.value) {
console.log('[weibo-article] Placeholder survived deleteContents, trying Input.insertText replacement...');
// Re-select and replace with empty via Input.insertText
await cdp!.send('Runtime.evaluate', {
expression: `(() => {
const editor = document.querySelector('div[contenteditable="true"]');
if (!editor) return false;
const placeholder = ${JSON.stringify(img.placeholder)};
const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, null, false);
let node;
while ((node = walker.nextNode())) {
const text = node.textContent || '';
let searchStart = 0;
let idx;
while ((idx = text.indexOf(placeholder, searchStart)) !== -1) {
const afterIdx = idx + placeholder.length;
const charAfter = text[afterIdx];
if (charAfter === undefined || !/\\d/.test(charAfter)) {
const range = document.createRange();
range.setStart(node, idx);
range.setEnd(node, idx + placeholder.length);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
return true;
}
searchStart = afterIdx;
}
}
return false;
})()`,
}, { sessionId });
await sleep(200);
await cdp!.send('Input.insertText', { text: '' }, { sessionId });
await sleep(300);
}
await sleep(200);
// Step C: Delete selected placeholder via Backspace (ProseMirror-compatible)
console.log(`[weibo-article] Deleting placeholder via Backspace...`);
await cdp.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Backspace', code: 'Backspace', windowsVirtualKeyCode: 8 }, { sessionId });
await cdp.send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Backspace', code: 'Backspace', windowsVirtualKeyCode: 8 }, { sessionId });
await sleep(500);
// Verify placeholder was deleted
const afterDelete = await cdp.send<{ result: { value: boolean } }>('Runtime.evaluate', {
const placeholderGone = await cdp.send<{ result: { value: boolean } }>('Runtime.evaluate', {
expression: `(() => {
const editor = document.querySelector('div[contenteditable="true"]');
if (!editor) return true;
const text = editor.innerText;
const placeholder = ${JSON.stringify(img.placeholder)};
const regex = new RegExp(placeholder + '(?!\\\\d)');
return !regex.test(text);
return !regex.test(editor.innerText);
})()`,
returnByValue: true,
}, { sessionId });
if (afterDelete.result.value) {
if (placeholderGone.result.value) {
console.log(`[weibo-article] Placeholder deleted`);
} else {
console.warn(`[weibo-article] Placeholder may still exist after delete`);
console.warn(`[weibo-article] Placeholder may still exist, trying execCommand delete...`);
// Re-select and delete via execCommand
await selectPlaceholder(1);
await cdp.send('Runtime.evaluate', {
expression: `document.execCommand('delete')`,
}, { sessionId });
await sleep(300);
}
// Focus editor for paste
// Step D: Focus editor and paste image
await cdp.send('Runtime.evaluate', {
expression: `document.querySelector('div[contenteditable="true"]')?.focus()`,
}, { sessionId });
await sleep(300);
await sleep(200);
// Count images before paste
const imgCountBefore = await cdp.send<{ result: { value: number } }>('Runtime.evaluate', {
@@ -613,7 +557,7 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
returnByValue: true,
}, { sessionId });
// Paste image
// Paste image at cursor position (where placeholder was)
console.log(`[weibo-article] Pasting image...`);
if (pasteFromClipboard('Google Chrome', 5, 1000)) {
console.log(`[weibo-article] Paste keystroke sent for: ${path.basename(img.localPath)}`);
+20 -9
View File
@@ -1,6 +1,14 @@
---
name: baoyu-post-to-x
description: Posts content and articles to X (Twitter). Supports regular posts with images/videos and X Articles (long-form Markdown). Uses real Chrome with CDP to bypass anti-automation. Use when user asks to "post to X", "tweet", "publish to Twitter", or "share on X".
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-post-to-x
requires:
anyBins:
- bun
- npx
---
# Post to X (Twitter)
@@ -12,9 +20,9 @@ Posts text, images, videos, and long-form articles to X via real Chrome browser
**Important**: All scripts are located in the `scripts/` subdirectory of this skill.
**Agent Execution Instructions**:
1. Determine this SKILL.md file's directory path as `SKILL_DIR`
2. Script path = `${SKILL_DIR}/scripts/<script-name>.ts`
3. Replace all `${SKILL_DIR}` in this document with the actual path
1. Determine this SKILL.md file's directory path as `{baseDir}`
2. Script path = `{baseDir}/scripts/<script-name>.ts`
3. Replace all `{baseDir}` in this document with the actual path
4. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun
**Script Reference**:
@@ -36,12 +44,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-post-to-x/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-post-to-x/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-post-to-x/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-post-to-x/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-post-to-x/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-post-to-x/EXTEND.md") { "user" }
```
@@ -74,7 +85,7 @@ if (Test-Path "$HOME/.baoyu-skills/baoyu-post-to-x/EXTEND.md") { "user" }
Before first use, suggest running the environment check. User can skip if they prefer.
```bash
${BUN_X} ${SKILL_DIR}/scripts/check-paste-permissions.ts
${BUN_X} {baseDir}/scripts/check-paste-permissions.ts
```
Checks: Chrome, profile isolation, Bun, Accessibility, clipboard, paste keystroke, Chrome conflicts.
@@ -107,7 +118,7 @@ Unless the user explicitly specifies the post type:
## Regular Posts
```bash
${BUN_X} ${SKILL_DIR}/scripts/x-browser.ts "Hello!" --image ./photo.png
${BUN_X} {baseDir}/scripts/x-browser.ts "Hello!" --image ./photo.png
```
**Parameters**:
@@ -126,7 +137,7 @@ ${BUN_X} ${SKILL_DIR}/scripts/x-browser.ts "Hello!" --image ./photo.png
Text + video file.
```bash
${BUN_X} ${SKILL_DIR}/scripts/x-video.ts "Check this out!" --video ./clip.mp4
${BUN_X} {baseDir}/scripts/x-video.ts "Check this out!" --video ./clip.mp4
```
**Parameters**:
@@ -147,7 +158,7 @@ ${BUN_X} ${SKILL_DIR}/scripts/x-video.ts "Check this out!" --video ./clip.mp4
Quote an existing tweet with comment.
```bash
${BUN_X} ${SKILL_DIR}/scripts/x-quote.ts https://x.com/user/status/123 "Great insight!"
${BUN_X} {baseDir}/scripts/x-quote.ts https://x.com/user/status/123 "Great insight!"
```
**Parameters**:
@@ -166,8 +177,8 @@ ${BUN_X} ${SKILL_DIR}/scripts/x-quote.ts https://x.com/user/status/123 "Great in
Long-form Markdown articles (requires X Premium).
```bash
${BUN_X} ${SKILL_DIR}/scripts/x-article.ts article.md
${BUN_X} ${SKILL_DIR}/scripts/x-article.ts article.md --cover ./cover.jpg
${BUN_X} {baseDir}/scripts/x-article.ts article.md
${BUN_X} {baseDir}/scripts/x-article.ts article.md --cover ./cover.jpg
```
**Parameters**:
@@ -12,13 +12,13 @@ Publish Markdown articles to X Articles editor with rich text formatting and ima
```bash
# Publish markdown article (preview mode)
${BUN_X} ${SKILL_DIR}/scripts/x-article.ts article.md
${BUN_X} {baseDir}/scripts/x-article.ts article.md
# With custom cover image
${BUN_X} ${SKILL_DIR}/scripts/x-article.ts article.md --cover ./cover.jpg
${BUN_X} {baseDir}/scripts/x-article.ts article.md --cover ./cover.jpg
# Actually publish
${BUN_X} ${SKILL_DIR}/scripts/x-article.ts article.md --submit
${BUN_X} {baseDir}/scripts/x-article.ts article.md --submit
```
## Markdown Format
@@ -76,13 +76,13 @@ Convert markdown and inspect structure:
```bash
# Get JSON with all metadata
${BUN_X} ${SKILL_DIR}/scripts/md-to-html.ts article.md
${BUN_X} {baseDir}/scripts/md-to-html.ts article.md
# Output HTML only
${BUN_X} ${SKILL_DIR}/scripts/md-to-html.ts article.md --html-only
${BUN_X} {baseDir}/scripts/md-to-html.ts article.md --html-only
# Save HTML to file
${BUN_X} ${SKILL_DIR}/scripts/md-to-html.ts article.md --save-html /tmp/article.html
${BUN_X} {baseDir}/scripts/md-to-html.ts article.md --save-html /tmp/article.html
```
JSON output:
@@ -161,7 +161,7 @@ Claude:
- **No create button**: Ensure X Premium subscription is active
- **Cover upload fails**: Check file path and format (PNG, JPEG)
- **Images not inserting**: Verify placeholders exist in pasted content
- **Content not pasting**: Check HTML clipboard: `${BUN_X} ${SKILL_DIR}/scripts/copy-to-clipboard.ts html --file /tmp/test.html`
- **Content not pasting**: Check HTML clipboard: `${BUN_X} {baseDir}/scripts/copy-to-clipboard.ts html --file /tmp/test.html`
## How It Works
@@ -9,20 +9,20 @@ If you prefer step-by-step control:
### Step 1: Copy Image to Clipboard
```bash
${BUN_X} ${SKILL_DIR}/scripts/copy-to-clipboard.ts image /path/to/image.png
${BUN_X} {baseDir}/scripts/copy-to-clipboard.ts image /path/to/image.png
```
### Step 2: Paste from Clipboard
```bash
# Simple paste to frontmost app
${BUN_X} ${SKILL_DIR}/scripts/paste-from-clipboard.ts
${BUN_X} {baseDir}/scripts/paste-from-clipboard.ts
# Paste to Chrome with retries
${BUN_X} ${SKILL_DIR}/scripts/paste-from-clipboard.ts --app "Google Chrome" --retries 5
${BUN_X} {baseDir}/scripts/paste-from-clipboard.ts --app "Google Chrome" --retries 5
# Quick paste with shorter delay
${BUN_X} ${SKILL_DIR}/scripts/paste-from-clipboard.ts --delay 200
${BUN_X} {baseDir}/scripts/paste-from-clipboard.ts --delay 200
```
### Step 3: Use Playwright MCP (if Chrome session available)
@@ -59,7 +59,7 @@ mcp__playwright__browser_take_screenshot filename="preview.png"
User: /post-to-x "Hello from Claude!" --image ./screenshot.png
Claude:
1. Runs: ${BUN_X} ${SKILL_DIR}/scripts/x-browser.ts "Hello from Claude!" --image ./screenshot.png
1. Runs: ${BUN_X} {baseDir}/scripts/x-browser.ts "Hello from Claude!" --image ./screenshot.png
2. Chrome opens with X compose page
3. Text is typed into editor
4. Image is copied to clipboard and pasted
@@ -72,7 +72,7 @@ Claude:
- **Chrome not found**: Set `X_BROWSER_CHROME_PATH` environment variable
- **Not logged in**: First run opens Chrome - log in manually, cookies are saved
- **Image paste fails**:
- Verify clipboard script: `${BUN_X} ${SKILL_DIR}/scripts/copy-to-clipboard.ts image <path>`
- Verify clipboard script: `${BUN_X} {baseDir}/scripts/copy-to-clipboard.ts image <path>`
- On macOS, grant "Accessibility" permission to Terminal/iTerm in System Settings > Privacy & Security > Accessibility
- Keep Chrome window visible and in front during paste operations
- **osascript permission denied**: Grant Terminal accessibility permissions in System Preferences
+15 -4
View File
@@ -1,6 +1,14 @@
---
name: baoyu-slide-deck
description: Generates professional slide deck images from content. Creates outlines with style instructions, then generates individual slide images. Use when user asks to "create slides", "make a presentation", "generate deck", "slide deck", or "PPT".
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-slide-deck
requires:
anyBins:
- bun
- npx
---
# Slide Deck Generator
@@ -22,8 +30,8 @@ Transform content into professional slide deck images.
## Script Directory
**Agent Execution Instructions**:
1. Determine this SKILL.md file's directory path as `SKILL_DIR`
2. Script path = `${SKILL_DIR}/scripts/<script-name>.ts`
1. Determine this SKILL.md file's directory path as `{baseDir}`
2. Script path = `{baseDir}/scripts/<script-name>.ts`
3. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun
| Script | Purpose |
@@ -195,12 +203,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-slide-deck/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-slide-deck/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-slide-deck/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-slide-deck/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-slide-deck/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-slide-deck/EXTEND.md") { "user" }
```
@@ -555,8 +566,8 @@ options:
### Step 8: Merge to PPTX and PDF
```bash
${BUN_X} ${SKILL_DIR}/scripts/merge-to-pptx.ts <slide-deck-dir>
${BUN_X} ${SKILL_DIR}/scripts/merge-to-pdf.ts <slide-deck-dir>
${BUN_X} {baseDir}/scripts/merge-to-pptx.ts <slide-deck-dir>
${BUN_X} {baseDir}/scripts/merge-to-pdf.ts <slide-deck-dir>
```
### Step 9: Output Summary
+13 -2
View File
@@ -1,6 +1,14 @@
---
name: baoyu-translate
description: Translates articles and documents between languages with three modes - quick (direct), normal (analyze then translate), and refined (analyze, translate, review, polish). Supports custom glossaries and terminology consistency via EXTEND.md. Use when user asks to "translate", "翻译", "精翻", "translate article", "translate to Chinese/English", "改成中文", "改成英文", "convert to Chinese", "localize", "本地化", or needs any document translation. Also triggers for "refined translation", "精细翻译", "proofread translation", "快速翻译", "快翻", "这篇文章翻译一下", or when a URL or file is provided with translation intent.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-translate
requires:
anyBins:
- bun
- npx
---
# Translator
@@ -9,7 +17,7 @@ Three-mode translation skill: **quick** for direct translation, **normal** for a
## Script Directory
Scripts in `scripts/` subdirectory. `${SKILL_DIR}` = this SKILL.md's directory path. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun. Replace `${SKILL_DIR}` and `${BUN_X}` with actual values.
Scripts in `scripts/` subdirectory. `{baseDir}` = this SKILL.md's directory path. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun. Replace `{baseDir}` and `${BUN_X}` with actual values.
| Script | Purpose |
|--------|---------|
@@ -22,12 +30,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-translate/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-translate/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-translate/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-translate/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-translate/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-translate/EXTEND.md") { "user" }
```
@@ -172,7 +183,7 @@ Before translating chunks:
1. **Extract terminology**: Scan entire document for proper nouns, technical terms, recurring phrases
2. **Build session glossary**: Merge extracted terms with loaded glossaries, establish consistent translations
3. **Split into chunks**: Use `${BUN_X} ${SKILL_DIR}/scripts/chunk.ts <file> [--max-words <chunk_max_words>] [--output-dir <output-dir>]`
3. **Split into chunks**: Use `${BUN_X} {baseDir}/scripts/chunk.ts <file> [--max-words <chunk_max_words>] [--output-dir <output-dir>]`
- Parses markdown AST (headings, paragraphs, lists, code blocks, tables, etc.)
- Splits at markdown block boundaries to preserve structure
- If a single block exceeds the threshold, falls back to line splitting, then word splitting
+19 -8
View File
@@ -1,6 +1,14 @@
---
name: baoyu-url-to-markdown
description: Fetch any URL and convert to markdown using Chrome CDP. Saves the rendered HTML snapshot alongside the markdown, and automatically falls back to the pre-Defuddle HTML-to-Markdown pipeline when Defuddle fails. Supports two modes - auto-capture on page load, or wait for user signal (for pages requiring login). Use when user wants to save a webpage as markdown.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-url-to-markdown
requires:
anyBins:
- bun
- npx
---
# URL to Markdown
@@ -12,10 +20,10 @@ Fetches any URL via Chrome CDP, saves the rendered HTML snapshot, and converts i
**Important**: All scripts are located in the `scripts/` subdirectory of this skill.
**Agent Execution Instructions**:
1. Determine this SKILL.md file's directory path as `SKILL_DIR`
2. Script path = `${SKILL_DIR}/scripts/<script-name>.ts`
1. Determine this SKILL.md file's directory path as `{baseDir}`
2. Script path = `{baseDir}/scripts/<script-name>.ts`
3. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun
4. Replace all `${SKILL_DIR}` and `${BUN_X}` in this document with actual values
4. Replace all `{baseDir}` and `${BUN_X}` in this document with actual values
**Script Reference**:
| Script | Purpose |
@@ -30,12 +38,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-url-to-markdown/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-url-to-markdown/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-url-to-markdown/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-url-to-markdown/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-url-to-markdown/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-url-to-markdown/EXTEND.md") { "user" }
```
@@ -112,19 +123,19 @@ Full reference: [references/config/first-time-setup.md](references/config/first-
```bash
# Auto mode (default) - capture when page loads
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url>
${BUN_X} {baseDir}/scripts/main.ts <url>
# Wait mode - wait for user signal before capture
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url> --wait
${BUN_X} {baseDir}/scripts/main.ts <url> --wait
# Save to specific file
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url> -o output.md
${BUN_X} {baseDir}/scripts/main.ts <url> -o output.md
# Save to a custom output directory (auto-generates filename)
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url> --output-dir ./posts/
${BUN_X} {baseDir}/scripts/main.ts <url> --output-dir ./posts/
# Download images and videos to local directories
${BUN_X} ${SKILL_DIR}/scripts/main.ts <url> --download-media
${BUN_X} {baseDir}/scripts/main.ts <url> --download-media
```
## Options
+7
View File
@@ -1,6 +1,10 @@
---
name: baoyu-xhs-images
description: Generates Xiaohongshu (Little Red Book) infographic series with 11 visual styles and 8 layouts. Breaks content into 1-10 cartoon-style images optimized for XHS engagement. Use when user mentions "小红书图片", "XHS images", "RedNote infographics", "小红书种草", or wants social media infographics for Chinese platforms.
version: 1.56.1
metadata:
openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-xhs-images
---
# Xiaohongshu Infographic Series Generator
@@ -274,12 +278,15 @@ Check EXTEND.md existence (priority order):
```bash
# macOS, Linux, WSL, Git Bash
test -f .baoyu-skills/baoyu-xhs-images/EXTEND.md && echo "project"
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills/baoyu-xhs-images/EXTEND.md" && echo "xdg"
test -f "$HOME/.baoyu-skills/baoyu-xhs-images/EXTEND.md" && echo "user"
```
```powershell
# PowerShell (Windows)
if (Test-Path .baoyu-skills/baoyu-xhs-images/EXTEND.md) { "project" }
$xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" }
if (Test-Path "$xdg/baoyu-skills/baoyu-xhs-images/EXTEND.md") { "xdg" }
if (Test-Path "$HOME/.baoyu-skills/baoyu-xhs-images/EXTEND.md") { "user" }
```
@@ -211,13 +211,9 @@ If preferences include watermark:
When generating multiple images in a series:
1. **Image 1 (cover)**: Generate without `--ref` — this establishes the visual anchor
2. **Images 2+**: Always pass image 1 as `--ref` to the image generation skill:
```bash
${BUN_X} ${SKILL_DIR}/scripts/main.ts \
--promptfiles prompts/02-content-xxx.md \
--ref path/to/01-cover-xxx.png \
--image 02-content-xxx.png --ar 3:4 --quality 2k
```
2. **Images 2+**: Always pass image 1 as `--ref` to the installed image generation skill.
Read that skill's `SKILL.md` and use its documented interface rather than calling its scripts directly.
For each later image, use the assembled prompt file as input, set the output image path, keep aspect ratio `3:4`, use quality `2k`, and pass image 1 as the reference.
This ensures the AI maintains the same character design, illustration style, and color rendering across the series.
### Step 6: Combine