# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Claude Code marketplace plugin providing AI-powered content generation skills. Current version: **1.59.1**. Skills use official AI APIs (OpenAI, Google, DashScope, Replicate) or the reverse-engineered Gemini Web API for text/image generation, and Chrome CDP for browser automation. ## Architecture Skills are organized into three plugin categories in `.claude-plugin/marketplace.json`: ``` skills/ ├── [content-skills] # Content generation and publishing │ ├── baoyu-xhs-images/ # Xiaohongshu infographic series (1-10 images) │ ├── baoyu-cover-image/ # Article cover images (2.35:1 aspect) │ ├── baoyu-slide-deck/ # Presentation slides with outlines │ ├── baoyu-article-illustrator/ # Smart illustration placement │ ├── baoyu-comic/ # Knowledge comics (Logicomix/Ohmsha style) │ ├── baoyu-post-to-x/ # X/Twitter posting automation │ ├── baoyu-post-to-wechat/ # WeChat Official Account posting │ ├── baoyu-post-to-weibo/ # Weibo posting (text, images, videos, articles) │ └── baoyu-infographic/ # Professional infographics (21 layouts × 20 styles) │ ├── [ai-generation-skills] # AI-powered generation backends │ ├── baoyu-danger-gemini-web/ # Gemini Web API wrapper (text + image gen) │ └── baoyu-image-gen/ # Official API image gen (OpenAI, Google, DashScope, Replicate) │ └── [utility-skills] # Utility tools for content processing ├── baoyu-danger-x-to-markdown/ # X/Twitter content to markdown ├── baoyu-compress-image/ # Image compression (WebP/PNG via sips/cwebp/Sharp) ├── baoyu-url-to-markdown/ # Fetch any URL → markdown via Chrome CDP ├── baoyu-format-markdown/ # Format/beautify plain text or markdown files ├── baoyu-markdown-to-html/ # Markdown → styled HTML (WeChat-compatible themes) └── baoyu-translate/ # Multi-mode translation (quick/normal/refined) ``` Top-level `scripts/` directory contains repository maintenance utilities: - `scripts/sync-clawhub.sh` - Publish skills to ClawHub/OpenClaw registry - `scripts/sync-shared-skill-packages.mjs` - Sync committed `vendor/` copies of shared workspace packages into skill script directories - `scripts/install-git-hooks.mjs` - Configure `.githooks/` as the repository-local git hooks path - `scripts/prepare-skill-artifact.mjs` - Build one releasable skill artifact from the already self-contained skill tree - `scripts/publish-skill-artifact.mjs` - Publish one prepared skill artifact - `scripts/sync-md-to-wechat.sh` - Sync markdown content to WeChat **Plugin Categories**: | Category | Description | |----------|-------------| | `content-skills` | Skills that generate or publish content (images, slides, comics, posts) | | `ai-generation-skills` | Backend skills providing AI generation capabilities | | `utility-skills` | Helper tools for content processing (conversion, compression) | Each skill contains: - `SKILL.md` - YAML front matter (name, description, version, openclaw metadata) + documentation - `scripts/` - TypeScript implementations (optional, pure-prompt skills omit this) - `references/` - Extended reference files linked from SKILL.md (optional) - `prompts/` - AI prompt templates (optional, used by some content skills) ## Running Skills All scripts are TypeScript, executed via Bun runtime (no build step). ### Runtime Detection (`${BUN_X}`) Before running any script, the agent MUST detect the runtime **once per session** and set `${BUN_X}`: ```bash # Detect runtime (run once, reuse result) if command -v bun &>/dev/null; then BUN_X="bun" elif command -v npx &>/dev/null; then BUN_X="npx -y bun" else echo "Error: Neither bun nor npx found. Install bun: brew install oven-sh/bun/bun (macOS) or npm install -g bun" exit 1 fi ``` | Priority | Condition | `${BUN_X}` value | Notes | |----------|-----------|-------------------|-------| | 1 | `bun` installed | `bun` | Fastest, native execution | | 2 | `npx` available | `npx -y bun` | Downloads bun on first run via npm | | 3 | Neither found | Error + install guide | `brew install oven-sh/bun/bun` (macOS) or `npm install -g bun` | ### Script Execution ```bash ${BUN_X} skills//scripts/main.ts [options] ``` Examples: ```bash # Text generation ${BUN_X} skills/baoyu-danger-gemini-web/scripts/main.ts "Hello" # Image generation ${BUN_X} skills/baoyu-danger-gemini-web/scripts/main.ts --prompt "A cat" --image cat.png # From prompt files ${BUN_X} skills/baoyu-danger-gemini-web/scripts/main.ts --promptfiles system.md content.md --image out.png ``` ## Key Dependencies - **Bun**: TypeScript runtime (native `bun` preferred, fallback `npx -y bun`) - **Chrome**: Required for `baoyu-danger-gemini-web` auth, `baoyu-post-to-x`, `baoyu-post-to-wechat`, `baoyu-post-to-weibo`, and `baoyu-url-to-markdown` - **npm packages (per skill)**: Some skill subprojects include `package.json`/lockfiles and require dependency installation in their own `scripts/` directories - **Image generation APIs**: `baoyu-image-gen` requires at least one API key (OpenAI, Google, DashScope, or Replicate) ## Chrome Profile (Unified) All skills that use Chrome CDP share a **single** profile directory. Do NOT create per-skill profiles. | Platform | Default Path | |----------|-------------| | macOS | `~/Library/Application Support/baoyu-skills/chrome-profile` | | Linux | `$XDG_DATA_HOME/baoyu-skills/chrome-profile` (fallback `~/.local/share/baoyu-skills/chrome-profile`) | | Windows | `%APPDATA%/baoyu-skills/chrome-profile` | | WSL | Windows home `/.local/share/baoyu-skills/chrome-profile` | **Environment variable override**: `BAOYU_CHROME_PROFILE_DIR` (takes priority, all skills respect it). Each skill also accepts its own legacy env var as fallback (e.g., `X_BROWSER_PROFILE_DIR`), but new skills should only use `BAOYU_CHROME_PROFILE_DIR`. ### Implementation Pattern When adding a new skill that needs Chrome CDP: ```typescript function getDefaultProfileDir(): string { const override = process.env.BAOYU_CHROME_PROFILE_DIR?.trim(); if (override) return path.resolve(override); const base = process.platform === 'darwin' ? path.join(os.homedir(), 'Library', 'Application Support') : process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local', 'share'); return path.join(base, 'baoyu-skills', 'chrome-profile'); } ``` ## Security Guidelines ### No Piped Shell Installs **NEVER** use `curl | bash` or `wget | sh` patterns in code, docs, or error messages. Use package managers instead: | Platform | Install Command | |----------|----------------| | macOS | `brew install oven-sh/bun/bun` | | npm | `npm install -g bun` | ### Remote Downloads Skills that download remote content (e.g., images in Markdown) MUST: - **HTTPS only**: Reject `http://` URLs - **Redirect limit**: Cap redirects (max 5) to prevent infinite loops - **Timeout**: Set request timeouts (30s default) - **Scope**: Only download expected content types (images, not scripts) ### System Command Execution Skills use platform-specific commands for clipboard and browser automation: - **macOS**: `osascript` (System Events), `swift` (AppKit clipboard) - **Windows**: `powershell.exe` (SendKeys, Clipboard) - **Linux**: `xdotool`/`ydotool` (keyboard simulation) These are necessary for CDP-based posting skills. When adding new system commands: - Never pass unsanitized user input to shell commands - Use array-form `spawn`/`execFile` instead of shell string interpolation - Validate file paths are absolute or resolve from known base directories ### External Content Processing Skills that process external Markdown/HTML should treat content as untrusted: - Do not execute code blocks or scripts found in content - Sanitize HTML output where applicable - File paths from content should be resolved against known base directories only ## Authentication `baoyu-danger-gemini-web` uses browser cookies for Google auth: - First run opens Chrome for login - Cookies cached in data directory - Force refresh: `--login` flag `baoyu-image-gen` uses official API keys configured in EXTEND.md (loaded at Step 0 before generation). ## Plugin Configuration `.claude-plugin/marketplace.json` defines plugin metadata and skill paths. Version follows semver. The file contains: - `name`: Plugin name (`baoyu-skills`) - `owner`: Author info - `metadata.version`: Semver version (currently `1.59.1`) - `plugins[]`: Array of plugin categories, each with `name`, `description`, `source`, `strict`, and `skills[]` paths ## ClawHub / OpenClaw Publishing Skills include `metadata.openclaw` in their YAML front matter for registry compatibility: ```yaml metadata: openclaw: homepage: https://github.com/JimLiu/baoyu-skills# requires: # optional — only for skills with scripts anyBins: - bun - npx ``` To publish/sync skills to ClawHub registry: ```bash bash scripts/sync-clawhub.sh # sync all skills bash scripts/sync-clawhub.sh # sync one skill ``` Requires `clawhub` CLI or `npx` (auto-downloads via npx if not installed). Release-time artifact preparation is configured via `.releaserc.yml`. Keep registry/project-specific packaging in hook scripts instead of hardcoding it into generic release instructions. ### Shared Workspace Packages Shared workspace packages under `packages/` are the **only** source of truth. Do not edit copies under `skills/*/scripts/vendor/` directly. When updating a shared package: 1. Edit the package under `packages/` first 2. Run `node scripts/sync-shared-skill-packages.mjs` 3. Review and commit the synced `skills/*/scripts/vendor/`, `package.json`, and `bun.lock` changes together Use `node scripts/install-git-hooks.mjs` to enable the repository `pre-push` hook. The hook reruns the sync and blocks push if the committed vendor copies are stale. The release flow assumes `main` already contains the final installable tree and only validates/copies it. ## Skill Loading Rules **IMPORTANT**: When working in this project, follow these rules: | Rule | Description | |------|-------------| | **Load project skills first** | MUST load all skills from `skills/` directory in current project. Project skills take priority over system/user-level skills with same name. | | **Default image generation** | When image generation is needed, use `skills/baoyu-image-gen/SKILL.md` by default (unless user specifies otherwise). | **Loading Priority** (highest → lowest): 1. Current project `skills/` directory 2. User-level skills (`$HOME/.baoyu-skills/`) 3. System-level skills ## Release Process **IMPORTANT**: When user requests release/发布/push, ALWAYS use `/release-skills` workflow. If `.releaserc.yml` defines `release.hooks.prepare_artifact` / `publish_artifact`, use those hooks to build and publish the final skill artifact. **Never skip**: 1. `CHANGELOG.md` + `CHANGELOG.zh.md` - Both must be updated 2. `marketplace.json` version bump 3. `README.md` + `README.zh.md` if applicable 4. All files committed together before tag ## Adding New Skills **IMPORTANT**: All skills MUST use `baoyu-` prefix to avoid conflicts when users import this plugin. **REQUIRED READING**: Before creating a new skill, read the official [Skill authoring best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices). ### Key Requirements from Official Best Practices | Requirement | Details | |-------------|---------| | **Concise is key** | Claude is smart—only add context it doesn't have. Challenge each token. | | **name field** | Max 64 chars, lowercase letters/numbers/hyphens only, no "anthropic"/"claude" | | **description field** | Max 1024 chars, non-empty, MUST be third person, include what + when to use | | **SKILL.md body** | Keep under 500 lines; use separate files for additional content | | **Naming convention** | Gerund form preferred (e.g., `processing-pdfs`), but `baoyu-` prefix required here | | **References** | Keep one level deep from SKILL.md; avoid nested references | | **No time-sensitive info** | Avoid dates/versions that become outdated | ### SKILL.md Frontmatter Template ```yaml --- name: baoyu- description: version: metadata: openclaw: homepage: https://github.com/JimLiu/baoyu-skills#baoyu- requires: # include only if skill has scripts anyBins: - bun - npx --- ``` ### Steps 1. Create `skills/baoyu-/SKILL.md` with YAML front matter (see template above) - Directory name: `baoyu-` - SKILL.md `name` field: `baoyu-` - Always include `metadata.openclaw.homepage` - Include `metadata.openclaw.requires.anyBins` only when the skill has executable scripts 2. Add TypeScript in `skills/baoyu-/scripts/` (if applicable) 3. Add prompt templates in `skills/baoyu-/prompts/` if needed 4. **Choose the appropriate category** and register in `marketplace.json`: - `content-skills`: For content generation/publishing (images, slides, posts) - `ai-generation-skills`: For AI backend capabilities - `utility-skills`: For helper tools (conversion, compression) - If none fit, create a new category with descriptive name 5. **Add Script Directory section** to SKILL.md (see template below) if skill has scripts 6. **Add openclaw metadata** to SKILL.md frontmatter (required for ClawHub registry) ### Choosing a Category | If your skill... | Use category | |------------------|--------------| | Generates visual content (images, slides, comics, infographics) | `content-skills` | | Publishes to platforms (X, WeChat, Weibo, etc.) | `content-skills` | | Provides AI generation backend (official API or reverse-engineered) | `ai-generation-skills` | | Converts or processes content (URL→md, md→html, format) | `utility-skills` | | Compresses or optimizes files | `utility-skills` | | Translates documents | `utility-skills` | **Creating a new category**: If the skill doesn't fit existing categories, add a new plugin object to `marketplace.json` with: - `name`: Descriptive kebab-case name (e.g., `analytics-skills`) - `description`: Brief description of the category - `skills`: Array with the skill path ### Writing Effective Descriptions **MUST write in third person** (not "I can help you" or "You can use this"): ```yaml # Good description: Generates Xiaohongshu infographic series from content. Use when user asks for "小红书图片", "XHS images", or "RedNote infographics". # Bad description: I can help you create Xiaohongshu images description: You can use this to generate XHS content ``` Include both **what** the skill does and **when** to use it (triggers/keywords). ### Script Directory Template Every SKILL.md with scripts MUST include this section after Usage: ```markdown ## Script Directory **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 `{baseDir}` 2. Script path = `{baseDir}/scripts/.ts` 3. Resolve `${BUN_X}` runtime: if `bun` installed → `bun`; if `npx` available → `npx -y bun`; else suggest installing bun 4. Replace all `{baseDir}` and `${BUN_X}` in this document with actual values **Script Reference**: | Script | Purpose | |--------|---------| | `scripts/main.ts` | Main entry point | | `scripts/other.ts` | Other functionality | ``` When referencing scripts in workflow sections, use `${BUN_X} {baseDir}/scripts/.ts` so agents can resolve the correct runtime and path. > **Note**: The path variable was renamed from `SKILL_DIR` / `${SKILL_DIR}` to `baseDir` / `{baseDir}` (no `${}` wrapper) in v1.57.0. All existing SKILL.md files use `{baseDir}`. ### Progressive Disclosure For skills with extensive content, use separate reference files: ``` skills/baoyu-example/ ├── SKILL.md # Main instructions (<500 lines) ├── references/ │ ├── styles.md # Style definitions (loaded as needed) │ └── examples.md # Usage examples (loaded as needed) └── scripts/ └── main.ts # Executable script ``` In SKILL.md, link to reference files (one level deep only): ```markdown **Available styles**: See [references/styles.md](references/styles.md) **Examples**: See [references/examples.md](references/examples.md) ``` ## Code Style - TypeScript throughout, no comments - Async/await patterns - Short variable names - Type-safe interfaces ## Image Generation Guidelines Skills that require image generation MUST delegate to available image generation skills rather than implementing their own. ### Image Generation Skill Selection **Default**: Use `skills/baoyu-image-gen/SKILL.md` (unless user specifies otherwise). 1. Read `skills/baoyu-image-gen/SKILL.md` for parameters and capabilities 2. If user explicitly requests a different skill, check `skills/` directory for alternatives 3. Only ask user to choose when they haven't specified and multiple viable options exist ### Generation Flow Template Use this template when implementing image generation in skills: ```markdown ### Step N: Generate Images **Skill Selection**: 1. Check available image generation skills (`baoyu-image-gen` default, or `baoyu-danger-gemini-web`) 2. Read selected skill's SKILL.md for parameter reference 3. If multiple skills available, ask user to choose **Generation Flow**: 1. Call selected image generation skill with: - Prompt file path (or inline prompt) - Output image path - Any skill-specific parameters (refer to skill's SKILL.md) 2. Generate images sequentially by default (one at a time) - Use batch parallel mode only when user already has multiple prompts or explicitly wants parallel throughput 3. After each image, output progress: "Generated X/N" 4. On failure, auto-retry once before reporting error ``` **Batch Parallel Generation** (`baoyu-image-gen` only): supports concurrent workers with per-provider throttling. Configure via `batch.max_workers` and `batch.provider_limits` in EXTEND.md. Default: sequential. ### Output Path Convention Each session creates an independent directory. Even the same source file generates a new directory per session. **Output Directory**: ``` // ``` - ``: Skill name suffix (e.g., `xhs-images`, `cover-image`, `slide-deck`, `comic`) - ``: Generated from content topic (2-4 words, kebab-case) - Example: `xhs-images/ai-future-trends/` **Slug Generation**: 1. Extract main topic from content (2-4 words, kebab-case) 2. Example: "Introduction to Machine Learning" → `intro-machine-learning` **Conflict Resolution**: If `//` already exists: - Append timestamp: `-YYYYMMDD-HHMMSS` - Example: `ai-future` exists → `ai-future-20260118-143052` **Source Files**: - Copy all sources to `//` with naming: `source-{slug}.{ext}` - Multiple sources supported: text, images, files from conversation - Examples: - `source-article.md` (main text content) - `source-reference.png` (image from conversation) - `source-data.csv` (additional file) - Original source files remain unchanged ### Image Naming Convention Image filenames MUST include meaningful slugs for readability: **Format**: `NN-{type}-[slug].png` - `NN`: Two-digit sequence number (01, 02, ...) - `{type}`: Image type (cover, content, page, slide, illustration, etc.) - `[slug]`: Descriptive kebab-case slug derived from content **Examples**: ``` 01-cover-ai-future.png 02-content-key-benefits.png 03-page-enigma-machine.png 04-slide-architecture-overview.png ``` **Slug Rules**: - Derived from image purpose or content (kebab-case) - Must be unique within the output directory - 2-5 words, concise but descriptive - When content changes significantly, update slug accordingly ### Best Practices - Always read the image generation skill's SKILL.md before calling - Pass parameters exactly as documented in the skill - Handle failures gracefully with retry logic - Provide clear progress feedback to user ## Style Maintenance (baoyu-comic) When adding, updating, or deleting styles for `baoyu-comic`, follow this workflow: ### Adding a New Style 1. **Create style definition**: `skills/baoyu-comic/references/styles/.md` 2. **Update SKILL.md**: - Add style to `--style` options table - Add auto-selection entry if applicable 3. **Generate showcase image**: ```bash ${BUN_X} skills/baoyu-danger-gemini-web/scripts/main.ts \ --prompt "A single comic book page in style showing [appropriate scene]. Features: [style characteristics from style definition]. 3:4 portrait aspect ratio comic page." \ --image screenshots/comic-styles/.png ``` 4. **Compress to WebP**: ```bash ${BUN_X} skills/baoyu-compress-image/scripts/main.ts screenshots/comic-styles/.png ``` 5. **Update both READMEs** (`README.md` and `README.zh.md`): - Add style to `--style` options - Add row to style description table - Add image to style preview grid ### Updating an Existing Style 1. **Update style definition**: `skills/baoyu-comic/references/styles/.md` 2. **Regenerate showcase image** (if visual characteristics changed): - Follow steps 3-4 from "Adding a New Style" 3. **Update READMEs** if description changed ### Deleting a Style 1. **Delete style definition**: `skills/baoyu-comic/references/styles/.md` 2. **Delete showcase image**: `screenshots/comic-styles/.webp` 3. **Update SKILL.md**: - Remove from `--style` options - Remove auto-selection entry 4. **Update both READMEs**: - Remove from `--style` options - Remove from style description table - Remove from style preview grid ### Style Preview Grid Format READMEs use 3-column tables for style previews: ```markdown | | | | |:---:|:---:|:---:| | ![style1](./screenshots/comic-styles/style1.webp) | ![style2](./screenshots/comic-styles/style2.webp) | ![style3](./screenshots/comic-styles/style3.webp) | | style1 | style2 | style3 | ``` ## Extension Support Every SKILL.md MUST include two parts for extension support: ### 1. Load Preferences Section (in Step 1 or as "Preferences" section) For skills with workflows, add as Step 1.1. For utility skills, add as "Preferences (EXTEND.md)" section before Usage: ```markdown **1.1 Load Preferences (EXTEND.md)** Check EXTEND.md existence (priority order): \`\`\`bash # macOS, Linux, WSL, Git Bash test -f .baoyu-skills//EXTEND.md && echo "project" test -f "${XDG_CONFIG_HOME:-$HOME/.config}/baoyu-skills//EXTEND.md" && echo "xdg" test -f "$HOME/.baoyu-skills//EXTEND.md" && echo "user" \`\`\` \`\`\`powershell # PowerShell (Windows) if (Test-Path .baoyu-skills//EXTEND.md) { "project" } $xdg = if ($env:XDG_CONFIG_HOME) { $env:XDG_CONFIG_HOME } else { "$HOME/.config" } if (Test-Path "$xdg/baoyu-skills//EXTEND.md") { "xdg" } if (Test-Path "$HOME/.baoyu-skills//EXTEND.md") { "user" } \`\`\` ┌────────────────────────────────────────────────────────┬──────────────────────────┐ │ Path │ Location │ ├────────────────────────────────────────────────────────┼──────────────────────────┤ │ .baoyu-skills//EXTEND.md │ Project directory │ ├────────────────────────────────────────────────────────┼──────────────────────────┤ │ $XDG_CONFIG_HOME/baoyu-skills//EXTEND.md │ XDG config (~/.config) │ ├────────────────────────────────────────────────────────┼──────────────────────────┤ │ $HOME/.baoyu-skills//EXTEND.md │ User home (legacy) │ └────────────────────────────────────────────────────────┴──────────────────────────┘ ┌───────────┬───────────────────────────────────────────────────────────────────────────┐ │ Result │ Action │ ├───────────┼───────────────────────────────────────────────────────────────────────────┤ │ Found │ Read, parse, display summary │ ├───────────┼───────────────────────────────────────────────────────────────────────────┤ │ Not found │ Ask user with AskUserQuestion (see references/config/first-time-setup.md) │ └───────────┴───────────────────────────────────────────────────────────────────────────┘ **EXTEND.md Supports**: [List supported configuration options for this skill] Schema: `references/config/preferences-schema.md` ``` ### 2. Extension Support Section (at the end) Simplified section that references the preferences section: ```markdown ## Extension Support Custom configurations via EXTEND.md. See **Step 1.1** for paths and supported options. ``` Or for utility skills without workflow steps: ```markdown ## Extension Support Custom configurations via EXTEND.md. See **Preferences** section for paths and supported options. ``` **Notes**: - Replace `` 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