{"owner":"netease-youdao","repo":"LobsterAI","hasSkills":true,"totalSkillsCount":92,"totalTokensCount":60275,"categories":["anthropic-skill","root-instruction","plugin-manifest","subagent-persona"],"hasMcp":true,"mcpConfig":{"mcpServers":{"LobsterAI":{"command":"npx","args":["-y","@modelcontextprotocol/server-LobsterAI"]}}},"found":["SKILLs/remotion/SKILL.md","SKILLs/playwright/SKILL.md","SKILLs/skill-vetter/SKILL.md","SKILLs/seedance/SKILL.md","SKILLs/seedream/SKILL.md","SKILLs/pptx/SKILL.md","SKILLs/skill-creator/SKILL.md","SKILLs/pdf/SKILL.md","SKILLs/frontend-design/SKILL.md","SKILLs/imap-smtp-email/SKILL.md","SKILLs/local-tools/SKILL.md","SKILLs/films-search/SKILL.md","SKILLs/docx/SKILL.md","SKILLs/develop-web-game/SKILL.md","SKILLs/daily-trending/SKILL.md","SKILLs/create-plan/SKILL.md","SKILLs/content-planner/SKILL.md","SKILLs/canvas-design/SKILL.md","SKILLs/article-writer/SKILL.md","SKILLs/stock-analyzer/SKILL.md","SKILLs/stock-announcements/SKILL.md","SKILLs/stock-explorer/SKILL.md","SKILLs/technology-news-search/SKILL.md","SKILLs/weather/SKILL.md","SKILLs/web-search/SKILL.md","SKILLs/xlsx/SKILL.md","SKILLs/youdaonote/SKILL.md","AGENTS.md","SKILLs/skills.config.json","openclaw-extensions/mcp-bridge/openclaw.plugin.json","openclaw-extensions/ask-user-question/openclaw.plugin.json","SKILLs/skill-vetter/_meta.json","SKILLs/pptx/html2pptx.md","SKILLs/pptx/ooxml.md","SKILLs/pptx/package.json","SKILLs/pdf/forms.md","SKILLs/pdf/reference.md","SKILLs/imap-smtp-email/_meta.json","SKILLs/imap-smtp-email/package.json","SKILLs/imap-smtp-email/README.md","SKILLs/docx/docx-js.md","SKILLs/docx/ooxml.md","SKILLs/web-search/DEPLOYMENT.md","SKILLs/web-search/IMPLEMENTATION.md","SKILLs/web-search/package.json","SKILLs/web-search/README.md","SKILLs/web-search/TEST.md","SKILLs/web-search/tsconfig.json","SKILLs/skill-creator/agents/analyzer.md","SKILLs/skill-creator/agents/comparator.md","SKILLs/skill-creator/agents/grader.md","SKILLs/skill-creator/references/schemas.md","SKILLs/remotion/rules/3d.md","SKILLs/remotion/rules/animations.md","SKILLs/remotion/rules/assets.md","SKILLs/remotion/rules/audio.md","SKILLs/remotion/rules/calculate-metadata.md","SKILLs/remotion/rules/can-decode.md","SKILLs/remotion/rules/charts.md","SKILLs/remotion/rules/compositions.md","SKILLs/remotion/rules/display-captions.md","SKILLs/remotion/rules/extract-frames.md","SKILLs/remotion/rules/fonts.md","SKILLs/remotion/rules/get-audio-duration.md","SKILLs/remotion/rules/get-video-dimensions.md","SKILLs/remotion/rules/get-video-duration.md","SKILLs/remotion/rules/gifs.md","SKILLs/remotion/rules/images.md","SKILLs/remotion/rules/import-srt-captions.md","SKILLs/remotion/rules/light-leaks.md","SKILLs/remotion/rules/lottie.md","SKILLs/remotion/rules/maps.md","SKILLs/remotion/rules/measuring-dom-nodes.md","SKILLs/remotion/rules/measuring-text.md","SKILLs/remotion/rules/parameters.md","SKILLs/remotion/rules/sequencing.md","SKILLs/remotion/rules/subtitles.md","SKILLs/remotion/rules/tailwind.md","SKILLs/remotion/rules/text-animations.md","SKILLs/remotion/rules/timing.md","SKILLs/remotion/rules/transcribe-captions.md","SKILLs/remotion/rules/transitions.md","SKILLs/remotion/rules/transparent-videos.md","SKILLs/remotion/rules/trimming.md","SKILLs/remotion/rules/videos.md","SKILLs/playwright/agents/openai.yaml","SKILLs/playwright/references/cli.md","SKILLs/playwright/references/workflows.md","SKILLs/develop-web-game/agents/openai.yaml","SKILLs/develop-web-game/references/action_payloads.json","SKILLs/technology-news-search/references/sources.json","SKILLs/web-search/examples/basic-search.md"],"skills":{"SKILLs/remotion/SKILL.md":"---\nname: remotion-best-practices\ndescription: Best practices for Remotion - Video creation in React\nofficial: true\nmetadata:\n  tags: remotion, video, react, animation, composition\n---\n\n## When to use\n\nUse this skills whenever you are dealing with Remotion code to obtain the domain-specific knowledge.\n\n## Captions\n\nWhen dealing with captions or subtitles, load the [./rules/subtitles.md](./rules/subtitles.md) file for more information.\n\n## How to use\n\nRead individual rule files for detailed explanations and code examples:\n\n- [rules/3d.md](rules/3d.md) - 3D content in Remotion using Three.js and React Three Fiber\n- [rules/animations.md](rules/animations.md) - Fundamental animation skills for Remotion\n- [rules/assets.md](rules/assets.md) - Importing images, videos, audio, and fonts into Remotion\n- [rules/audio.md](rules/audio.md) - Using audio and sound in Remotion - importing, trimming, volume, speed, pitch\n- [rules/calculate-metadata.md](rules/calculate-metadata.md) - Dynamically set composition duration, dimensions, and props\n- [rules/can-decode.md](rules/can-decode.md) - Check if a video can be decoded by the browser using Mediabunny\n- [rules/charts.md](rules/charts.md) - Chart and data visualization patterns for Remotion\n- [rules/compositions.md](rules/compositions.md) - Defining compositions, stills, folders, default props and dynamic metadata\n- [rules/extract-frames.md](rules/extract-frames.md) - Extract frames from videos at specific timestamps using Mediabunny\n- [rules/fonts.md](rules/fonts.md) - Loading Google Fonts and local fonts in Remotion\n- [rules/get-audio-duration.md](rules/get-audio-duration.md) - Getting the duration of an audio file in seconds with Mediabunny\n- [rules/get-video-dimensions.md](rules/get-video-dimensions.md) - Getting the width and height of a video file with Mediabunny\n- [rules/get-video-duration.md](rules/get-video-duration.md) - Getting the duration of a video file in seconds with Mediabunny\n- [rules/gifs.md](rules/gifs.md) - Displaying GIFs synchronized with Remotion's timeline\n- [rules/images.md](rules/images.md) - Embedding images in Remotion using the Img component\n- [rules/light-leaks.md](rules/light-leaks.md) - Light leak overlay effects using @remotion/light-leaks\n- [rules/lottie.md](rules/lottie.md) - Embedding Lottie animations in Remotion\n- [rules/measuring-dom-nodes.md](rules/measuring-dom-nodes.md) - Measuring DOM element dimensions in Remotion\n- [rules/measuring-text.md](rules/measuring-text.md) - Measuring text dimensions, fitting text to containers, and checking overflow\n- [rules/sequencing.md](rules/sequencing.md) - Sequencing patterns for Remotion - delay, trim, limit duration of items\n- [rules/tailwind.md](rules/tailwind.md) - Using TailwindCSS in Remotion\n- [rules/text-animations.md](rules/text-animations.md) - Typography and text animation patterns for Remotion\n- [rules/timing.md](rules/timing.md) - Interpolation curves in Remotion - linear, easing, spring animations\n- [rules/transitions.md](rules/transitions.md) - Scene transition patterns for Remotion\n- [rules/transparent-videos.md](rules/transparent-videos.md) - Rendering out a video with transparency\n- [rules/trimming.md](rules/trimming.md) - Trimming patterns for Remotion - cut the beginning or end of animations\n- [rules/videos.md](rules/videos.md) - Embedding videos in Remotion - trimming, volume, speed, looping, pitch\n- [rules/parameters.md](rules/parameters.md) - Make a video parametrizable by adding a Zod schema\n- [rules/maps.md](rules/maps.md) - Add a map using Mapbox and animate it\n","SKILLs/playwright/SKILL.md":"---\nname: \"playwright\"\ndescription: \"Use when the task requires automating a real browser from the terminal (navigation, form filling, snapshots, screenshots, data extraction, UI-flow debugging) via `playwright-cli` or the bundled wrapper script.\"\nofficial: true\n---\n\n\n# Playwright CLI Skill\n\nDrive a real browser from the terminal using `playwright-cli`. Prefer the bundled wrapper script so the CLI works even when it is not globally installed.\nTreat this skill as CLI-first automation. Do not pivot to `@playwright/test` unless the user explicitly asks for test files.\n\n## Prerequisite check (required)\n\nBefore proposing commands, check whether `npx` is available (the wrapper depends on it):\n\n```bash\ncommand -v npx >/dev/null 2>&1\n```\n\nIf it is not available, pause and ask the user to install Node.js/npm (which provides `npx`). Provide these steps verbatim:\n\n```bash\n# Verify Node/npm are installed\nnode --version\nnpm --version\n\n# If missing, install Node.js/npm, then:\nnpm install -g @playwright/mcp@latest\nplaywright-cli --help\n```\n\nOnce `npx` is present, proceed with the wrapper script. A global install of `playwright-cli` is optional.\n\n## Skill path (set once)\n\n```bash\nexport SKILLS_ROOT=\"${LOBSTERAI_SKILLS_ROOT:-${SKILLS_ROOT:-$HOME/Library/Application Support/LobsterAI/SKILLs}}\"\nexport PWCLI=\"$SKILLS_ROOT/playwright/scripts/playwright_cli.sh\"\n```\n\nInstalled skills resolve from `$LOBSTERAI_SKILLS_ROOT` / `$SKILLS_ROOT` (production default: app `userData/SKILLs`, macOS usually `~/Library/Application Support/LobsterAI/SKILLs`).\n\n## Quick start\n\nUse the wrapper script:\n\n```bash\n\"$PWCLI\" open https://playwright.dev --headed\n\"$PWCLI\" snapshot\n\"$PWCLI\" click e15\n\"$PWCLI\" type \"Playwright\"\n\"$PWCLI\" press Enter\n\"$PWCLI\" screenshot\n```\n\nIf the user prefers a global install, this is also valid:\n\n```bash\nnpm install -g @playwright/mcp@latest\nplaywright-cli --help\n```\n\n## Core workflow\n\n1. Open the page.\n2. Snapshot to get stable element refs.\n3. Interact using refs from the latest snapshot.\n4. Re-snapshot after navigation or significant DOM changes.\n5. Capture artifacts (screenshot, pdf, traces) when useful.\n\nMinimal loop:\n\n```bash\n\"$PWCLI\" open https://example.com\n\"$PWCLI\" snapshot\n\"$PWCLI\" click e3\n\"$PWCLI\" snapshot\n```\n\n## When to snapshot again\n\nSnapshot again after:\n\n- navigation\n- clicking elements that change the UI substantially\n- opening/closing modals or menus\n- tab switches\n\nRefs can go stale. When a command fails due to a missing ref, snapshot again.\n\n## Recommended patterns\n\n### Form fill and submit\n\n```bash\n\"$PWCLI\" open https://example.com/form\n\"$PWCLI\" snapshot\n\"$PWCLI\" fill e1 \"user@example.com\"\n\"$PWCLI\" fill e2 \"password123\"\n\"$PWCLI\" click e3\n\"$PWCLI\" snapshot\n```\n\n### Debug a UI flow with traces\n\n```bash\n\"$PWCLI\" open https://example.com --headed\n\"$PWCLI\" tracing-start\n# ...interactions...\n\"$PWCLI\" tracing-stop\n```\n\n### Multi-tab work\n\n```bash\n\"$PWCLI\" tab-new https://example.com\n\"$PWCLI\" tab-list\n\"$PWCLI\" tab-select 0\n\"$PWCLI\" snapshot\n```\n\n## Wrapper script\n\nThe wrapper script uses `npx --package @playwright/mcp playwright-cli` so the CLI can run without a global install:\n\n```bash\n\"$PWCLI\" --help\n```\n\nPrefer the wrapper unless the repository already standardizes on a global install.\n\n## References\n\nOpen only what you need:\n\n- CLI command reference: `references/cli.md`\n- Practical workflows and troubleshooting: `references/workflows.md`\n\n## Guardrails\n\n- Always snapshot before referencing element ids like `e12`.\n- Re-snapshot when refs seem stale.\n- Prefer explicit commands over `eval` and `run-code` unless needed.\n- When you do not have a fresh snapshot, use placeholder refs like `eX` and say why; do not bypass refs with `run-code`.\n- Use `--headed` when a visual check will help.\n- When capturing artifacts in this repo, use `output/playwright/` and avoid introducing new top-level artifact folders.\n- Default to CLI commands and workflows, not Playwright test specs.\n","SKILLs/skill-vetter/SKILL.md":"---\nname: skill-vetter\nversion: 1.0.0\ndescription: Security-first skill vetting for AI agents. Use before installing any skill from ClawdHub, GitHub, or other sources. Checks for red flags, permission scope, and suspicious patterns.\n---\n\n# Skill Vetter 🔒\n\nSecurity-first vetting protocol for AI agent skills. **Never install a skill without vetting it first.**\n\n## When to Use\n\n- Before installing any skill from ClawdHub\n- Before running skills from GitHub repos\n- When evaluating skills shared by other agents\n- Anytime you're asked to install unknown code\n\n## Vetting Protocol\n\n### Step 1: Source Check\n\n```\nQuestions to answer:\n- [ ] Where did this skill come from?\n- [ ] Is the author known/reputable?\n- [ ] How many downloads/stars does it have?\n- [ ] When was it last updated?\n- [ ] Are there reviews from other agents?\n```\n\n### Step 2: Code Review (MANDATORY)\n\nRead ALL files in the skill. Check for these **RED FLAGS**:\n\n```\n🚨 REJECT IMMEDIATELY IF YOU SEE:\n─────────────────────────────────────────\n• curl/wget to unknown URLs\n• Sends data to external servers\n• Requests credentials/tokens/API keys\n• Reads ~/.ssh, ~/.aws, ~/.config without clear reason\n• Accesses MEMORY.md, USER.md, SOUL.md, IDENTITY.md\n• Uses base64 decode on anything\n• Uses eval() or exec() with external input\n• Modifies system files outside workspace\n• Installs packages without listing them\n• Network calls to IPs instead of domains\n• Obfuscated code (compressed, encoded, minified)\n• Requests elevated/sudo permissions\n• Accesses browser cookies/sessions\n• Touches credential files\n─────────────────────────────────────────\n```\n\n### Step 3: Permission Scope\n\n```\nEvaluate:\n- [ ] What files does it need to read?\n- [ ] What files does it need to write?\n- [ ] What commands does it run?\n- [ ] Does it need network access? To where?\n- [ ] Is the scope minimal for its stated purpose?\n```\n\n### Step 4: Risk Classification\n\n| Risk Level | Examples | Action |\n|------------|----------|--------|\n| 🟢 LOW | Notes, weather, formatting | Basic review, install OK |\n| 🟡 MEDIUM | File ops, browser, APIs | Full code review required |\n| 🔴 HIGH | Credentials, trading, system | Human approval required |\n| ⛔ EXTREME | Security configs, root access | Do NOT install |\n\n## Output Format\n\nAfter vetting, produce this report:\n\n```\nSKILL VETTING REPORT\n═══════════════════════════════════════\nSkill: [name]\nSource: [ClawdHub / GitHub / other]\nAuthor: [username]\nVersion: [version]\n───────────────────────────────────────\nMETRICS:\n• Downloads/Stars: [count]\n• Last Updated: [date]\n• Files Reviewed: [count]\n───────────────────────────────────────\nRED FLAGS: [None / List them]\n\nPERMISSIONS NEEDED:\n• Files: [list or \"None\"]\n• Network: [list or \"None\"]  \n• Commands: [list or \"None\"]\n───────────────────────────────────────\nRISK LEVEL: [🟢 LOW / 🟡 MEDIUM / 🔴 HIGH / ⛔ EXTREME]\n\nVERDICT: [✅ SAFE TO INSTALL / ⚠️ INSTALL WITH CAUTION / ❌ DO NOT INSTALL]\n\nNOTES: [Any observations]\n═══════════════════════════════════════\n```\n\n## Quick Vet Commands\n\nFor GitHub-hosted skills:\n```bash\n# Check repo stats\ncurl -s \"https://api.github.com/repos/OWNER/REPO\" | jq '{stars: .stargazers_count, forks: .forks_count, updated: .updated_at}'\n\n# List skill files\ncurl -s \"https://api.github.com/repos/OWNER/REPO/contents/skills/SKILL_NAME\" | jq '.[].name'\n\n# Fetch and review SKILL.md\ncurl -s \"https://raw.githubusercontent.com/OWNER/REPO/main/skills/SKILL_NAME/SKILL.md\"\n```\n\n## Trust Hierarchy\n\n1. **Official OpenClaw skills** → Lower scrutiny (still review)\n2. **High-star repos (1000+)** → Moderate scrutiny\n3. **Known authors** → Moderate scrutiny\n4. **New/unknown sources** → Maximum scrutiny\n5. **Skills requesting credentials** → Human approval always\n\n## Remember\n\n- No skill is worth compromising security\n- When in doubt, don't install\n- Ask your human for high-risk decisions\n- Document what you vet for future reference\n\n---\n\n*Paranoia is a feature.* 🔒🦀\n","SKILLs/seedance/SKILL.md":"---\nname: seedance\ndescription: Generate AI videos using Volcengine Seedance model. Supports text-to-video (T2V), image-to-video (I2V), and audio-synced video generation. Use this skill when the user wants to create or generate videos.\nofficial: true\nversion: 1.0.1\n---\n\n# Seedance 视频生成\n\n使用火山引擎 Seedance 模型生成高质量 AI 视频，支持文本生成视频（T2V）、图片生成视频（I2V）、音画同步等多种创作模式。\n\n> ✨ **Node.js 版本**：此脚本使用 Node.js 实现，无需 Python 环境。通过入口脚本自动检测 Node.js 运行时（优先使用系统 node，回退到 LobsterAI 内置运行时），Windows 和 Mac 用户都可以开箱即用。\n\n## 配置\n\n- **Base URL**: `https://ark.cn-beijing.volces.com/api/v3`\n- **API Key**: 从环境变量 `ARK_API_KEY` 读取\n- **认证方式**: `Authorization: Bearer {API_KEY}`\n- **SDK**: 兼容火山方舟 Python SDK\n\n### 如何配置 API Key\n\n**方式一：通过环境变量配置（推荐）**\n\n在终端中设置环境变量：\n\n```bash\n# macOS/Linux\nexport ARK_API_KEY=\"你的API密钥\"\n\n# 或者添加到 ~/.zshrc 或 ~/.bashrc 以永久生效\necho 'export ARK_API_KEY=\"你的API密钥\"' >> ~/.zshrc\nsource ~/.zshrc\n```\n\n```powershell\n# Windows PowerShell\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 或者设置系统环境变量以永久生效\n[System.Environment]::SetEnvironmentVariable('ARK_API_KEY', '你的API密钥', 'User')\n```\n\n**方式二：通过 LobsterAI 启动时注入**\n\nLobsterAI 会自动读取系统环境变量，确保在启动 LobsterAI 前已设置 `ARK_API_KEY`。\n\n**如何获取 API Key：**\n1. 访问火山方舟控制台：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n2. 创建新的 API Key\n3. 复制密钥并设置为环境变量\n\n## 前置检查\n\n**无需安装任何依赖！** 该脚本已兼容 Node.js 内置模块。\n\nLobsterAI 已包含 Node.js 运行时，所有必要的依赖已被自动打包。Windows 和 Mac 用户无需额外配置。\n\n## 工作流程\n\nSeedance 视频生成是一个异步过程：\n\n1. **提交任务** - 调用 API 创建视频生成任务，获得 `task_id`\n2. **轮询状态** - 每隔几秒查询任务状态，直到状态变为 `succeeded`\n3. **下载视频** - 从 `video_url` 字段下载生成的 MP4 文件\n\n## 配额和限制\n\n### 免费额度\n\n所有 Seedance 模型在 **default 模式（在线推理）**下提供：\n- **200万 token** 免费额度\n- flex 模式（离线推理）无免费额度\n\n**注意**：文档中未明确说明 200万 token 能生成多少个视频，消耗取决于视频时长、分辨率和是否使用图片/音频。建议先小批量测试。\n\n### 限流限制\n\n| 模型系列 | RPM（每分钟请求数） | 并发数 | TPD（离线模式每日token） |\n|---------|-------------------|--------|----------------------|\n| Pro 系列 | 600 | 10 | 5000亿 |\n| Lite 系列 | 300 | 5 | 2500亿 |\n\n- **RPM 限流**：账号下同模型每分钟允许创建的任务数量上限\n- **并发数限制**：同一时刻在处理中的任务数量上限\n- **TPD 限流**：flex 模式下一天内对同一模型的总调用 token 上限\n\n### 视频保存时间\n\n⚠️ **重要提醒**：\n- 任务数据（包括视频URL）仅保留 **24 小时**\n- 超时后会被自动清除\n- **务必及时下载保存生成的视频**\n\n## 使用示例\n\n**路径说明**：下面的示例使用 `$SKILLS_ROOT` 环境变量来引用脚本路径。LobsterAI 会自动设置这个变量，指向实际的 SKILLs 目录位置，因此无需手动修改路径。\n\n### 1. 文本生成视频（T2V）\n\n根据文字描述生成视频，适合创意激发和概念验证。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"一只小猫在草地上玩耍，阳光明媚，镜头缓缓推进\" \\\n  --duration 5 \\\n  --output generated_video.mp4\n```\n\n**示例提示词：**\n- \"写实风格，晴朗的蓝天之下，一大片白色的雏菊花田，镜头逐渐拉近，最终定格在一朵雏菊花的特写上，花瓣上有几颗晶莹的露珠\"\n- \"一辆地铁轰隆隆驶过，书页飞扬，镜头开始环绕着女孩360度旋转\"\n- \"海边日落，海浪轻拍沙滩，宁静祥和的氛围\"\n\n### 2. 图片生成视频（I2V）- 首帧引导\n\n基于首帧图片生成动态视频，**支持本地图片和网络URL**。\n\n```bash\n# 使用本地图片\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"女孩睁开眼，温柔地看向镜头，头发被风吹动\" \\\n  --image \"/Users/yourname/Pictures/girl.jpg\" \\\n  --duration 5 \\\n  --output i2v_video.mp4\n\n# 使用网络图片\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"女孩睁开眼，温柔地看向镜头，头发被风吹动\" \\\n  --image \"https://example.com/first_frame.jpg\" \\\n  --duration 5 \\\n  --output i2v_video.mp4\n```\n\n**支持的图片来源：**\n- ✅ 本地文件：`/path/to/image.jpg`\n- ✅ 网络URL：`https://example.com/image.jpg`\n- ✅ file://协议：`file:///path/to/image.jpg`\n\n**支持的图片格式：**\n- jpg, jpeg, png, gif, webp, bmp, tiff, heic\n\n### 3. 图片生成视频（I2V）- 首尾帧引导\n\n提供首帧和尾帧，生成过渡动画。**支持本地图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"360度环绕运镜，流畅过渡\" \\\n  --image \"/Users/yourname/Pictures/first_frame.jpg\" \\\n  --image \"/Users/yourname/Pictures/last_frame.jpg\" \\\n  --duration 5 \\\n  --output transition_video.mp4\n```\n\n### 4. 多参考图生成视频\n\n融合多张参考图的特征生成视频。**支持混合使用本地图片和网络图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"[图1]戴着眼镜穿着蓝色T恤的男生和[图2]的柯基小狗，坐在[图3]的草坪上，视频卡通风格\" \\\n  --image \"/Users/yourname/Pictures/person.jpg\" \\\n  --image \"https://example.com/dog.jpg\" \\\n  --image \"/Users/yourname/Pictures/grass.jpg\" \\\n  --model \"doubao-seedance-1-0-lite-i2v-250428\" \\\n  --duration 5 \\\n  --output multi_ref_video.mp4\n```\n\n### 5. 音画同步视频生成（仅 1.5 pro）\n\n生成包含音频的视频（环境音、动作音、背景音乐等）。**支持本地图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"镜头围绕人物推镜头拉近，特写人物面部，她正在用京剧唱腔唱'月移花影，疑是玉人来'，唱词充满情感\" \\\n  --image \"/Users/yourname/Pictures/actress.jpg\" \\\n  --audio \\\n  --duration 5 \\\n  --model \"doubao-seedance-1-5-pro-251215\" \\\n  --output audio_video.mp4\n```\n\n## 参数说明\n\n### 必需参数\n\n| 参数 | 说明 | 示例 |\n|-----|------|------|\n| `--prompt` | 视频描述提示词（必需） | \"小猫在玩耍\" |\n\n### 可选参数\n\n| 参数 | 说明 | 默认值 | 可选值 |\n|-----|------|-------|--------|\n| `--image` | 参考图片路径或URL（可多次使用） | 无 | 本地文件路径或URL |\n| `--model` | 模型ID | `doubao-seedance-1-5-pro-251215` | 见模型列表 |\n| `--duration` | 视频时长（秒） | 5 | 2-12（不同模型范围不同） |\n| `--ratio` | 宽高比 | `adaptive` | `adaptive`, `16:9`, `9:16`, `1:1` |\n| `--audio` | 生成音频（仅1.5 pro支持） | 否 | 标志参数 |\n| `--no-watermark` | 不添加水印 | 否 | 标志参数 |\n| `--output` | 输出文件路径 | `generated_video.mp4` | 文件路径 |\n| `--poll-interval` | 状态查询间隔（秒） | 5 | 1-10 |\n| `--timeout` | 最大等待时间（秒） | 300 | 60-600 |\n\n## 模型选择\n\n选择合适的模型以平衡质量、速度和成本：\n\n### Seedance 1.5 pro（推荐）\n\n- **模型ID**: `doubao-seedance-1-5-pro-251215`\n- **特点**: 音画同生，最高质量\n- **支持**: 文生视频、图生视频、首尾帧、有声视频\n- **输出**: 480p-1080p，24fps，4-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 pro\n\n- **模型ID**: `doubao-seedance-1-0-pro-250528`\n- **特点**: 高质量标准版本\n- **支持**: 文生视频、图生视频、首尾帧\n- **输出**: 480p-1080p，24fps，2-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 pro fast\n\n- **模型ID**: `doubao-seedance-1-0-pro-fast-251015`\n- **特点**: 快速生成，成本更低\n- **支持**: 文生视频、图生视频\n- **输出**: 480p-1080p，24fps，2-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 lite（轻量版）\n\n- **文生视频**: `doubao-seedance-1-0-lite-t2v-250428`\n- **图生视频**: `doubao-seedance-1-0-lite-i2v-250428`\n- **特点**: 更快速度，支持多参考图\n- **限流**: RPM 300，并发5\n\n### Seedance 2.0（即将支持）\n\n- **模型ID**: `doubao-seedance-2-0-260128`\n- **特点**: 下一代视频生成模型，质量和性能全面提升\n- **可用性**: ⏰ 预计 **2026年2月24日18点** 开放 API 调用\n- **当前状态**: 仅在 [控制台体验中心](https://console.volcengine.com/ark/region:ark+cn-beijing/experience/vision?modelId=doubao-seedance-2-0-260128&tab=GenVideo) 可用\n\n**使用方式（2月24日后）：**\n\n```bash\n# 命令行方式\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"你的提示词\" \\\n  --model \"doubao-seedance-2-0-260128\" \\\n  --duration 5\n```\n\n或在 LobsterAI 对话中说：\"用 Seedance 2.0 生成视频...\"\n\n**推荐使用场景：**\n- 追求最高质量 + 音画同步 → 1.5 pro\n- 标准高质量视频 → 1.0 pro\n- 快速生成预览 → 1.0 pro fast\n- 多参考图融合 → 1.0 lite\n- 下一代最新模型（2月24日后）→ 2.0\n\n## 高级选项\n\n### 自定义宽高比\n\n根据使用场景选择合适的宽高比：\n\n```bash\n# 横屏视频（适合 YouTube、B站）\n--ratio \"16:9\"\n\n# 竖屏视频（适合抖音、快手）\n--ratio \"9:16\"\n\n# 正方形视频（适合 Instagram）\n--ratio \"1:1\"\n\n# 自适应（根据内容自动选择）\n--ratio \"adaptive\"\n```\n\n### 自定义视频时长\n\n不同模型支持的时长范围不同：\n\n```bash\n# 短视频（快速生成）\n--duration 2\n\n# 标准时长\n--duration 5\n\n# 长视频（内容更丰富）\n--duration 10\n```\n\n**注意：**\n- Seedance 1.5 pro 支持 4-12 秒\n- Seedance 1.0 系列支持 2-12 秒\n- 时长越长，生成时间越久\n\n### 去除水印\n\n生成无水印视频（用于商业用途）：\n\n```bash\n--no-watermark\n```\n\n### 轮询和超时控制\n\n调整轮询策略以适应不同场景：\n\n```bash\n# 快速查询（适合短视频）\n--poll-interval 3 --timeout 180\n\n# 标准配置\n--poll-interval 5 --timeout 300\n\n# 耐心等待（适合长视频或高峰期）\n--poll-interval 10 --timeout 600\n```\n\n## 状态说明\n\n生成过程中可能出现的任务状态：\n\n| 状态 | 说明 | 操作 |\n|------|------|------|\n| `queued` | 任务排队中 | 继续等待 |\n| `running` | 正在生成视频 | 继续等待 |\n| `succeeded` | 生成成功 | 下载视频 |\n| `failed` | 生成失败 | 查看错误信息 |\n\n## 错误处理\n\n### 常见错误及解决方案\n\n**错误：未设置环境变量 ARK_API_KEY**\n- 原因：未配置 API Key\n- 解决：按照\"如何配置 API Key\"部分的说明进行配置\n\n**错误：任务创建失败 (HTTP 401)**\n- 原因：API Key 无效或已过期\n- 解决：检查 API Key 是否正确，或在控制台重新生成\n\n**错误：任务创建失败 (HTTP 400)**\n- 原因：参数错误（如 duration 超出范围）\n- 解决：检查参数是否符合模型要求\n\n**错误：任务超时**\n- 原因：生成时间过长或 API 繁忙\n- 解决：增加 `--timeout` 值，或稍后重试\n\n**错误：任务失败**\n- 原因：内容违规、提示词不清晰、图片格式错误等\n- 解决：检查提示词内容，确保图片URL可访问\n\n**错误：限流 (HTTP 429)**\n- 原因：超过 RPM 或并发限制\n- 解决：等待1分钟后重试，或升级配额\n\n## 输出格式\n\n生成的视频具有以下特征：\n\n- **格式**: MP4\n- **编码**: H.264\n- **分辨率**: 480p / 720p / 1080p（根据模型自动选择）\n- **帧率**: 24 fps\n- **音频**: AAC（如果启用 `--audio`）\n- **文件大小**: 约 2-5 MB/秒（1080p）\n\n## 提示词最佳实践\n\n### 优秀提示词的特点\n\n1. **清晰的场景描述** - 说明环境、时间、氛围\n2. **具体的动作细节** - 描述物体或人物的具体动作\n3. **镜头运动** - 说明推拉摇移、特写等镜头语言\n4. **风格指定** - 写实、卡通、动漫等风格说明\n\n### 提示词模板\n\n```\n[风格]，[场景描述]，[主体动作]，[镜头运动]，[氛围/情绪]\n```\n\n**示例：**\n```\n写实风格，海边日落，一只海鸥在空中盘旋，镜头从远处缓缓推进到海鸥特写，宁静祥和的氛围\n```\n\n### 提示词注意事项\n\n- ✅ 具体描述：\"小猫追逐蝴蝶\" 而非 \"小猫玩耍\"\n- ✅ 镜头语言：\"镜头360度环绕\" 而非 \"旋转\"\n- ✅ 情绪氛围：\"温暖明亮的阳光\" 而非 \"好天气\"\n- ❌ 避免模糊：过于抽象的描述会导致随机性增加\n- ❌ 避免过长：保持在 200 字以内效果最佳\n- ❌ 避免违规：不要包含暴力、色情等违规内容\n\n## 常见使用场景\n\n### 短视频创作\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"产品展示：智能手表从不同角度旋转展示\" \\\n  --ratio \"9:16\" \\\n  --duration 5\n```\n\n### 动画短片\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"卡通风格，小兔子在森林里蹦蹦跳跳\" \\\n  --ratio \"16:9\" \\\n  --duration 8 \\\n  --model \"doubao-seedance-1-0-pro-250528\"\n```\n\n### 社交媒体内容\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"美食特写：热气腾腾的拉面，筷子夹起面条\" \\\n  --ratio \"1:1\" \\\n  --duration 3\n```\n\n### 教学演示\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"科普动画：地球自转，太阳光照射地球表面\" \\\n  --ratio \"16:9\" \\\n  --duration 10\n```\n\n## 参考资料\n\n- API 参考：https://www.volcengine.com/docs/82379/1520758\n- 控制台：https://console.volcengine.com/ark\n- API Key 管理：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n\n## 技术支持\n\n如遇到问题，可以：\n1. 查看脚本输出的错误信息\n2. 检查 API Key 配置是否正确\n3. 访问火山方舟控制台查看任务详情\n4. 参考官网文档了解更多细节\n","SKILLs/seedream/SKILL.md":"---\nname: seedream\ndescription: Generate AI images using Volcengine Seedream model. Supports text-to-image (T2I), image editing (I2I), multi-image fusion, and web-search-based generation. Use this skill when the user wants to create, generate, or edit images.\nofficial: true\nversion: 1.0.1\n---\n\n# Seedream 图片生成\n\n使用火山引擎 Seedream 模型生成高质量 AI 图片，支持文本生成图片（T2I）、图片编辑（I2I）、多图融合、组图生成、联网搜索等多种创作模式。\n\n> ✨ **Node.js 版本**：此脚本使用 Node.js 实现，无需 Python 环境。通过入口脚本自动检测 Node.js 运行时（优先使用系统 node，回退到 LobsterAI 内置运行时），Windows 和 Mac 用户都可以开箱即用。\n\n## 配置\n\n- **Base URL**: `https://ark.cn-beijing.volces.com/api/v3`\n- **API Key**: 从环境变量 `ARK_API_KEY` 读取\n- **认证方式**: `Authorization: Bearer {API_KEY}`\n- **SDK**: 兼容火山方舟 Python SDK\n\n### 快速开始\n\n**第一步：设置 API Key**\n\n```bash\n# macOS / Linux - 当前终端临时生效（立即使用）\nexport ARK_API_KEY=\"你的API密钥\"\n\n# Windows PowerShell - 当前会话临时生效\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 验证设置成功（macOS/Linux）\necho $ARK_API_KEY\n\n# 验证设置成功（Windows）\necho $env:ARK_API_KEY\n```\n\n**第二步：生成你的第一张图片**\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"一只可爱的橘色小猫\"\n```\n\n### 如何配置 API Key\n\n**方式一：通过环境变量配置（推荐）**\n\n在终端中设置环境变量：\n\n```bash\n# macOS/Linux\nexport ARK_API_KEY=\"你的API密钥\"\n\n# 或者添加到 ~/.zshrc 或 ~/.bashrc 以永久生效\necho 'export ARK_API_KEY=\"你的API密钥\"' >> ~/.zshrc\nsource ~/.zshrc\n```\n\n```powershell\n# Windows PowerShell\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 或者设置系统环境变量以永久生效\n[System.Environment]::SetEnvironmentVariable('ARK_API_KEY', '你的API密钥', 'User')\n```\n\n**方式二：通过 LobsterAI 启动时注入**\n\nLobsterAI 会自动读取系统环境变量，确保在启动 LobsterAI 前已设置 `ARK_API_KEY`。\n\n**如何获取 API Key：**\n1. 访问火山方舟控制台：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n2. 创建新的 API Key\n3. 复制密钥并设置为环境变量\n\n## 前置检查\n\n**无需安装任何依赖！** 该脚本已兼容 Node.js 内置模块。\n\nLobsterAI 已包含 Node.js 运行时，所有必要的依赖已被自动打包。Windows 和 Mac 用户无需额外配置。\n\n## 工作流程\n\nSeedream 图片生成采用**同步模式**，流程简单高效：\n\n1. **提交请求** - 调用 API 提交图片生成请求\n2. **等待生成** - API 直接处理并生成图片（通常 30-60 秒）\n3. **下载图片** - 从返回的 URL 下载生成的图片文件\n\n相比异步模式，同步模式更简单直接，无需轮询任务状态。\n\n## 配额和限制\n\n### 免费额度\n\n所有 Seedream 模型提供免费额度，具体请参见火山方舟控制台。\n\n### 限流限制\n\n- **IPM（每分钟图片数）**: 500 张/分钟（Seedream 4.5, 4.0）\n- 不同模型的限流不同，请参见官方文档\n\n### 图片保存时间\n\n⚠️ **重要提醒**：\n- 任务数据（包括图片URL）仅保留 **24 小时**\n- 超时后会被自动清除\n- **务必及时下载保存生成的图片**\n\n## 使用示例\n\n**路径说明**：下面的示例使用 `$SKILLS_ROOT` 环境变量来引用脚本路径。LobsterAI 会自动设置这个变量，指向实际的 SKILLs 目录位置，因此无需手动修改路径。\n\n### 1. 文本生成图片（T2I）\n\n根据文字描述生成图片，适合创意激发和概念设计。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"充满活力的特写编辑肖像，模特眼神犀利，头戴雕塑感帽子，色彩拼接丰富，景深较浅，Vogue杂志封面美学风格\" \\\n  --output portrait.png\n```\n\n**示例提示词：**\n- \"写实风格，晴朗的蓝天之下，一大片白色的雏菊花田，镜头逐渐拉近，最终定格在一朵雏菊花的特写上\"\n- \"卡通风格，一只橘色小猫坐在窗台上，阳光洒在身上，温暖治愈的氛围\"\n- \"赛博朋克风格，未来城市夜景，霓虹灯闪烁，高楼林立\"\n\n### 2. 图片编辑（I2I）- 单图输入\n\n基于已有图片，结合文字指令进行图像编辑。**支持本地图片和网络URL**。\n\n```bash\n# 使用本地图片\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"保持模特姿势不变，将服装材质改为透明玻璃质感\" \\\n  --image \"/Users/yourname/Pictures/model.jpg\" \\\n  --output edited_model.png\n\n# 使用网络图片\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"将背景改为海边日落场景\" \\\n  --image \"https://example.com/photo.jpg\" \\\n  --output beach_sunset.png\n```\n\n**支持的图片来源：**\n- ✅ 本地文件：`/path/to/image.jpg`\n- ✅ 网络URL：`https://example.com/image.jpg`\n- ✅ file://协议：`file:///path/to/image.jpg`\n\n**支持的图片格式：**\n- jpg, jpeg, png, gif, webp, bmp, tiff, heic\n\n### 3. 多图融合（多图输入单图输出）\n\n融合多张参考图的特征生成新图像。**支持混合使用本地图片和网络图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"将图1的服装换为图2的服装\" \\\n  --image \"/Users/yourname/Pictures/person.jpg\" \\\n  --image \"https://example.com/clothes.jpg\" \\\n  --output fusion_result.png\n```\n\n**常见使用场景：**\n- 服装试穿：人物图 + 服装图 → 穿搭效果图\n- 风格迁移：照片 + 风格参考图 → 风格化作品\n- 场景融合：人物 + 背景 → 合成场景\n\n### 4. 组图生成（多图输出）\n\n生成一组内容关联的图片，适合漫画分镜、品牌视觉等。\n\n#### 文生组图\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"生成一组共4张连贯插画，核心为同一庭院一角的四季变迁，以统一风格展现四季独特色彩、元素与氛围\" \\\n  --sequential \\\n  --max-images 4 \\\n  --output seasons.png\n```\n\n输出文件会自动编号：`seasons_1.png`, `seasons_2.png`, `seasons_3.png`, `seasons_4.png`\n\n#### 单图生组图\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"参考这个LOGO，做一套户外运动品牌视觉设计，品牌名称为'GREEN'，包括包装袋、帽子、卡片、挂绳等\" \\\n  --image \"/Users/yourname/Pictures/logo.png\" \\\n  --sequential \\\n  --max-images 4 \\\n  --output brand_design.png\n```\n\n### 5. 联网搜索增强生成（Seedream 5.0 lite）\n\n启用实时网络搜索，融合最新网络信息。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"搜索下近期热门的白鸭子单手拿着风车形象，以极具冲击力的视角，设计成巨型装置\" \\\n  --search \\\n  --output search_result.png\n```\n\n**注意**：\n- 联网搜索功能仅限 Seedream 5.0 lite 模型\n- 使用 `--search` 参数会自动切换到 5.0 lite 模型\n- 适合需要融合实时信息的创作场景\n\n## 参数说明\n\n### 必需参数\n\n| 参数 | 说明 | 示例 |\n|-----|------|------|\n| `--prompt` | 图片描述提示词（必需） | \"一只可爱的小猫\" |\n\n### 可选参数\n\n| 参数 | 说明 | 默认值 | 可选值 |\n|-----|------|-------|--------|\n| `--image` | 参考图片路径或URL（可多次使用） | 无 | 本地文件路径或URL |\n| `--model` | 模型ID | `doubao-seedream-4-5-251128` | 见模型列表 |\n| `--size` | 图片尺寸 | `2K` | `1K`, `2K`, `4K` |\n| `--no-watermark` | 不添加水印 | 否 | 标志参数 |\n| `--sequential` | 生成组图 | 否 | 标志参数 |\n| `--max-images` | 组图数量 | 4 | 1-8 |\n| `--search` | 启用联网搜索 | 否 | 标志参数 |\n| `--output` | 输出文件路径 | `generated_image.png` | 文件路径 |\n| `--poll-interval` | 状态查询间隔（秒） | 5 | 1-10 |\n| `--timeout` | 最大等待时间（秒） | 300 | 60-600 |\n\n## 模型选择\n\n选择合适的模型以平衡质量、速度和成本：\n\n### Seedream 4.5（推荐）\n\n- **模型ID**: `doubao-seedream-4-5-251128`\n- **特点**: 最新版本，综合质量最佳\n- **支持**: 文生图、图生图、多图融合、组图生成\n- **输出**: 1K-4K分辨率可选\n- **限流**: IPM 500\n\n### Seedream 4.0\n\n- **模型ID**: `doubao-seedream-4-0-250828`\n- **特点**: 成熟稳定版本\n- **支持**: 文生图、图生图、多图融合、组图生成\n- **输出**: 1K-4K分辨率可选\n- **限流**: IPM 500\n\n### Seedream 5.0 lite（联网搜索专用）\n\n- **模型ID**: `doubao-seedream-5-0-260128`\n- **特点**: 支持联网搜索，融合实时网络信息\n- **使用**: 通过 `--search` 参数自动启用\n- **注意**: 2026年2月24日18点后正式开放 API\n\n**推荐使用场景：**\n- 追求最高质量 → 4.5\n- 稳定生产环境 → 4.0\n- 需要实时信息 → 5.0 lite（使用 `--search`）\n\n## 高级选项\n\n### 自定义图片尺寸\n\n根据使用场景选择合适的尺寸：\n\n```bash\n# 小尺寸（快速预览）\n--size \"1K\"\n\n# 标准尺寸（推荐）\n--size \"2K\"\n\n# 高清晰度\n--size \"4K\"\n```\n\n**注意：**\n- 尺寸越大，生成时间越长\n- 4K 图片可能需要 40-60 秒\n\n### 去除水印\n\n生成无水印图片（用于商业用途）：\n\n```bash\n--no-watermark\n```\n\n### 轮询和超时控制\n\n调整轮询策略以适应不同场景：\n\n```bash\n# 快速查询（适合小图）\n--poll-interval 3 --timeout 180\n\n# 标准配置\n--poll-interval 5 --timeout 300\n\n# 耐心等待（适合4K或组图）\n--poll-interval 10 --timeout 600\n```\n\n## 状态说明\n\n生成过程中可能出现的任务状态：\n\n| 状态 | 说明 | 操作 |\n|------|------|------|\n| `queued` | 任务排队中 | 继续等待 |\n| `running` | 正在生成图片 | 继续等待 |\n| `succeeded` | 生成成功 | 下载图片 |\n| `failed` | 生成失败 | 查看错误信息 |\n\n## 错误处理\n\n### 常见错误及解决方案\n\n**错误：未设置环境变量 ARK_API_KEY**\n- 原因：未配置 API Key\n- 解决：按照\"如何配置 API Key\"部分的说明进行配置\n\n**错误：任务创建失败 (HTTP 401)**\n- 原因：API Key 无效或已过期\n- 解决：检查 API Key 是否正确，或在控制台重新生成\n\n**错误：任务创建失败 (HTTP 400)**\n- 原因：参数错误（如 size 不支持、prompt 为空等）\n- 解决：检查参数是否符合要求\n\n**错误：任务超时**\n- 原因：生成时间过长或 API 繁忙\n- 解决：增加 `--timeout` 值，或稍后重试\n\n**错误：任务失败**\n- 原因：内容违规、提示词不清晰、图片格式错误等\n- 解决：检查提示词内容，确保图片URL可访问\n\n**错误：限流 (HTTP 429)**\n- 原因：超过 IPM 限制\n- 解决：等待1分钟后重试，或升级配额\n\n**错误：图片文件不存在**\n- 原因：本地图片路径错误\n- 解决：检查文件路径是否正确，使用绝对路径\n\n## 输出格式\n\n生成的图片具有以下特征：\n\n- **格式**: PNG, JPEG（根据output参数自动识别）\n- **分辨率**: 1K / 2K / 4K（根据 size 参数）\n- **文件大小**: 约 0.5-10 MB（取决于尺寸和复杂度）\n- **命名规则**:\n  - 单图：指定的文件名\n  - 组图：`文件名_1.png`, `文件名_2.png`, ...\n\n## 提示词最佳实践\n\n### 优秀提示词的特点\n\n1. **清晰的主体描述** - 说明画面的主要内容\n2. **具体的风格指定** - 写实、卡通、赛博朋克等\n3. **细节补充** - 色彩、光线、氛围等\n4. **构图说明** - 特写、全景、俯视等视角\n\n### 提示词模板\n\n```\n[风格]，[主体描述]，[细节补充]，[构图/氛围]\n```\n\n**示例：**\n```\n写实风格，一只橘色小猫坐在木制窗台上，阳光从左侧洒进来，温暖治愈的氛围，特写构图\n```\n\n### 提示词注意事项\n\n- ✅ 具体描述：\"小猫在追逐蝴蝶\" 而非 \"小猫玩耍\"\n- ✅ 风格说明：\"赛博朋克风格\" 而非 \"好看的\"\n- ✅ 细节丰富：\"橘色长毛小猫，蓝色眼睛\" 而非 \"猫\"\n- ❌ 避免模糊：过于抽象的描述会导致随机性增加\n- ❌ 避免过长：保持在 200 字以内效果最佳\n- ❌ 避免违规：不要包含暴力、色情等违规内容\n\n## 常见使用场景\n\n### 产品设计\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"现代简约风格，智能手表产品展示，白色背景，工作室灯光\" \\\n  --size \"4K\"\n```\n\n### 艺术创作\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"超现实主义，漂浮的岛屿，瀑布从天而降，梦幻色彩\" \\\n  --size \"2K\"\n```\n\n### 社交媒体内容\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"美食特写，热气腾腾的拉面，筷子夹起面条，暖色调\" \\\n  --size \"2K\"\n```\n\n### 品牌视觉设计\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"参考logo，生成一套完整的品牌视觉系统，包括名片、海报、包装设计\" \\\n  --image brand_logo.png \\\n  --sequential \\\n  --max-images 4\n```\n\n## 参考资料\n\n- API 参考：https://www.volcengine.com/docs/82379/1541523\n- 控制台：https://console.volcengine.com/ark\n- API Key 管理：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n- 模型列表：https://www.volcengine.com/docs/82379/1330310\n\n## 技术支持\n\n如遇到问题，可以：\n1. 查看脚本输出的错误信息\n2. 检查 API Key 配置是否正确\n3. 访问火山方舟控制台查看任务详情\n4. 参考官网文档了解更多细节\n","SKILLs/pptx/SKILL.md":"---\nname: pptx\ndescription: \"Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks\"\nlicense: Proprietary. LICENSE.txt has complete terms\nofficial: true\n---\n\n# PPTX creation, editing, and analysis\n\n## Overview\n\nA user may ask you to create, edit, or analyze the contents of a .pptx file. A .pptx file is essentially a ZIP archive containing XML files and other resources that you can read or edit. You have different tools and workflows available for different tasks.\n\n## Reading and analyzing content\n\n### Text extraction\nIf you just need to read the text contents of a presentation, you should convert the document to markdown:\n\n```bash\n# Convert document to markdown\npython -m markitdown path-to-file.pptx\n```\n\n### Raw XML access\nYou need raw XML access for: comments, speaker notes, slide layouts, animations, design elements, and complex formatting. For any of these features, you'll need to unpack a presentation and read its raw XML contents.\n\n#### Unpacking a file\n`python ooxml/scripts/unpack.py <office_file> <output_dir>`\n\n**Note**: Resolve script paths from this skill directory. Prefer `$SKILLS_ROOT/pptx/ooxml/scripts/unpack.py` when `$SKILLS_ROOT` is available; otherwise resolve `ooxml/scripts/unpack.py` relative to this `SKILL.md` file's directory. Do not assume a workspace-relative `skills/pptx/...` path.\n\n#### Key file structures\n* `ppt/presentation.xml` - Main presentation metadata and slide references\n* `ppt/slides/slide{N}.xml` - Individual slide contents (slide1.xml, slide2.xml, etc.)\n* `ppt/notesSlides/notesSlide{N}.xml` - Speaker notes for each slide\n* `ppt/comments/modernComment_*.xml` - Comments for specific slides\n* `ppt/slideLayouts/` - Layout templates for slides\n* `ppt/slideMasters/` - Master slide templates\n* `ppt/theme/` - Theme and styling information\n* `ppt/media/` - Images and other media files\n\n#### Typography and color extraction\n**When given an example design to emulate**: Always analyze the presentation's typography and colors first using the methods below:\n1. **Read theme file**: Check `ppt/theme/theme1.xml` for colors (`<a:clrScheme>`) and fonts (`<a:fontScheme>`)\n2. **Sample slide content**: Examine `ppt/slides/slide1.xml` for actual font usage (`<a:rPr>`) and colors\n3. **Search for patterns**: Use grep to find color (`<a:solidFill>`, `<a:srgbClr>`) and font references across all XML files\n\n## Creating a new PowerPoint presentation **without a template**\n\nWhen creating a new PowerPoint presentation from scratch, use the **html2pptx** workflow to convert HTML slides to PowerPoint with accurate positioning.\n\n### Design Principles\n\n**CRITICAL**: Before creating any presentation, analyze the content and choose appropriate design elements:\n1. **Consider the subject matter**: What is this presentation about? What tone, industry, or mood does it suggest?\n2. **Check for branding**: If the user mentions a company/organization, consider their brand colors and identity\n3. **Match palette to content**: Select colors that reflect the subject\n4. **State your approach**: Explain your design choices before writing code\n\n**Requirements**:\n- ✅ State your content-informed design approach BEFORE writing code\n- ✅ Use web-safe fonts only: Arial, Helvetica, Times New Roman, Georgia, Courier New, Verdana, Tahoma, Trebuchet MS, Impact\n- ✅ Create clear visual hierarchy through size, weight, and color\n- ✅ Ensure readability: strong contrast, appropriately sized text, clean alignment\n- ✅ Be consistent: repeat patterns, spacing, and visual language across slides\n\n#### Color Palette Selection\n\n**Choosing colors creatively**:\n- **Think beyond defaults**: What colors genuinely match this specific topic? Avoid autopilot choices.\n- **Consider multiple angles**: Topic, industry, mood, energy level, target audience, brand identity (if mentioned)\n- **Be adventurous**: Try unexpected combinations - a healthcare presentation doesn't have to be green, finance doesn't have to be navy\n- **Build your palette**: Pick 3-5 colors that work together (dominant colors + supporting tones + accent)\n- **Ensure contrast**: Text must be clearly readable on backgrounds\n\n**Example color palettes** (use these to spark creativity - choose one, adapt it, or create your own):\n\n1. **Classic Blue**: Deep navy (#1C2833), slate gray (#2E4053), silver (#AAB7B8), off-white (#F4F6F6)\n2. **Teal & Coral**: Teal (#5EA8A7), deep teal (#277884), coral (#FE4447), white (#FFFFFF)\n3. **Bold Red**: Red (#C0392B), bright red (#E74C3C), orange (#F39C12), yellow (#F1C40F), green (#2ECC71)\n4. **Warm Blush**: Mauve (#A49393), blush (#EED6D3), rose (#E8B4B8), cream (#FAF7F2)\n5. **Burgundy Luxury**: Burgundy (#5D1D2E), crimson (#951233), rust (#C15937), gold (#997929)\n6. **Deep Purple & Emerald**: Purple (#B165FB), dark blue (#181B24), emerald (#40695B), white (#FFFFFF)\n7. **Cream & Forest Green**: Cream (#FFE1C7), forest green (#40695B), white (#FCFCFC)\n8. **Pink & Purple**: Pink (#F8275B), coral (#FF574A), rose (#FF737D), purple (#3D2F68)\n9. **Lime & Plum**: Lime (#C5DE82), plum (#7C3A5F), coral (#FD8C6E), blue-gray (#98ACB5)\n10. **Black & Gold**: Gold (#BF9A4A), black (#000000), cream (#F4F6F6)\n11. **Sage & Terracotta**: Sage (#87A96B), terracotta (#E07A5F), cream (#F4F1DE), charcoal (#2C2C2C)\n12. **Charcoal & Red**: Charcoal (#292929), red (#E33737), light gray (#CCCBCB)\n13. **Vibrant Orange**: Orange (#F96D00), light gray (#F2F2F2), charcoal (#222831)\n14. **Forest Green**: Black (#191A19), green (#4E9F3D), dark green (#1E5128), white (#FFFFFF)\n15. **Retro Rainbow**: Purple (#722880), pink (#D72D51), orange (#EB5C18), amber (#F08800), gold (#DEB600)\n16. **Vintage Earthy**: Mustard (#E3B448), sage (#CBD18F), forest green (#3A6B35), cream (#F4F1DE)\n17. **Coastal Rose**: Old rose (#AD7670), beaver (#B49886), eggshell (#F3ECDC), ash gray (#BFD5BE)\n18. **Orange & Turquoise**: Light orange (#FC993E), grayish turquoise (#667C6F), white (#FCFCFC)\n\n#### Visual Details Options\n\n**Geometric Patterns**:\n- Diagonal section dividers instead of horizontal\n- Asymmetric column widths (30/70, 40/60, 25/75)\n- Rotated text headers at 90° or 270°\n- Circular/hexagonal frames for images\n- Triangular accent shapes in corners\n- Overlapping shapes for depth\n\n**Border & Frame Treatments**:\n- Thick single-color borders (10-20pt) on one side only\n- Double-line borders with contrasting colors\n- Corner brackets instead of full frames\n- L-shaped borders (top+left or bottom+right)\n- Underline accents beneath headers (3-5pt thick)\n\n**Typography Treatments**:\n- Extreme size contrast (72pt headlines vs 11pt body)\n- All-caps headers with wide letter spacing\n- Numbered sections in oversized display type\n- Monospace (Courier New) for data/stats/technical content\n- Condensed fonts (Arial Narrow) for dense information\n- Outlined text for emphasis\n\n**Chart & Data Styling**:\n- Monochrome charts with single accent color for key data\n- Horizontal bar charts instead of vertical\n- Dot plots instead of bar charts\n- Minimal gridlines or none at all\n- Data labels directly on elements (no legends)\n- Oversized numbers for key metrics\n\n**Layout Innovations**:\n- Full-bleed images with text overlays\n- Sidebar column (20-30% width) for navigation/context\n- Modular grid systems (3×3, 4×4 blocks)\n- Z-pattern or F-pattern content flow\n- Floating text boxes over colored shapes\n- Magazine-style multi-column layouts\n\n**Background Treatments**:\n- Solid color blocks occupying 40-60% of slide\n- Gradient fills (vertical or diagonal only)\n- Split backgrounds (two colors, diagonal or vertical)\n- Edge-to-edge color bands\n- Negative space as a design element\n\n### Layout Tips\n**When creating slides with charts or tables:**\n- **Two-column layout (PREFERRED)**: Use a header spanning the full width, then two columns below - text/bullets in one column and the featured content in the other. This provides better balance and makes charts/tables more readable. Use flexbox with unequal column widths (e.g., 40%/60% split) to optimize space for each content type.\n- **Full-slide layout**: Let the featured content (chart/table) take up the entire slide for maximum impact and readability\n- **NEVER vertically stack**: Do not place charts/tables below text in a single column - this causes poor readability and layout issues\n\n### Workflow\n1. **MANDATORY - READ ENTIRE FILE**: Read `html2pptx.md` from the same directory as this `SKILL.md` (installed default: `$SKILLS_ROOT/pptx/html2pptx.md`) completely from start to finish. **NEVER set any range limits when reading this file.** Read the full file content for detailed syntax, critical formatting rules, and best practices before proceeding with presentation creation.\n2. Create an HTML file for each slide with proper dimensions (e.g., 720pt × 405pt for 16:9)\n   - Use `<p>`, `<h1>`-`<h6>`, `<ul>`, `<ol>` for all text content\n   - Use `class=\"placeholder\"` for areas where charts/tables will be added (render with gray background for visibility)\n   - **CRITICAL**: Rasterize gradients and icons as PNG images FIRST using Sharp, then reference in HTML\n   - **LAYOUT**: For slides with charts/tables/images, use either full-slide layout or two-column layout for better readability\n3. Create and run a JavaScript file using the [`html2pptx.js`](scripts/html2pptx.js) library to convert HTML slides to PowerPoint and save the presentation\n   - Use the `html2pptx()` function to process each HTML file\n   - Add charts and tables to placeholder areas using PptxGenJS API\n   - Save the presentation using `pptx.writeFile()`\n4. **Visual validation**: Generate thumbnails and inspect for layout issues\n   - Create thumbnail grid: `python scripts/thumbnail.py output.pptx workspace/thumbnails --cols 4`\n   - Read and carefully examine the thumbnail image for:\n     - **Text cutoff**: Text being cut off by header bars, shapes, or slide edges\n     - **Text overlap**: Text overlapping with other text or shapes\n     - **Positioning issues**: Content too close to slide boundaries or other elements\n     - **Contrast issues**: Insufficient contrast between text and backgrounds\n   - If issues found, adjust HTML margins/spacing/colors and regenerate the presentation\n   - Repeat until all slides are visually correct\n\n## Live editing in LobsterAI\n\nWhen the `ppt_read` and `ppt_edit` tools exist, change existing presentations through them instead of unpacking and repacking the file. The presentation opens in LobsterAI's right-side PowerPoint editor, edits appear there immediately, the theme, layouts, animations and everything the tools do not touch are preserved, and the file saves automatically.\n\n1. Call `ppt_read` with the absolute `path` (and `slides` such as `\"2-4\"` for long decks). It returns `revision`, the layout names, and for each slide its number, layout, speaker notes and shapes: `id`, `name`, `kind`, placeholder role, position and size in points, `text` (one line per paragraph, leading tabs give the bullet level) and table cells. It also returns the user's current `selection` (\"改这里\" means that slide and shape).\n2. Call `ppt_edit` with the same `path`, `expectedRevision` from the read, and a list of `edits`; slides are numbered from 1 and shapes are addressed by their `id`:\n   - `replace_text` `{slide?, shape?, find, replace, occurrence?}` for wording changes; it keeps the formatting around the phrase.\n   - `set_text` `{slide, shape, text}` rewrites a shape's text and keeps its formatting; `set_table_cell` `{slide, shape, row, column, text}`.\n   - `format_text` (bold, italic, underline, strike, color, size in pt, font) on a `find` phrase, a `paragraph` or the whole shape; `format_paragraph` (alignment, bullet `level`).\n   - `set_bounds` `{slide, shape, x?, y?, width?, height?}` in points, `delete_shape`, `add_text_box`.\n   - `add_slide` `{after?, layout?, title?, body?}` with a layout name from the read, `duplicate_slide`, `move_slide` `{slide, position}`, `delete_slide`, `set_notes`.\n3. Edits in one call apply in order as one undoable step, and slide numbers in later edits refer to the deck after the earlier ones. If the call is refused because the revision changed, the user edited the presentation meanwhile: read again and redo the edit. If any edit fails, nothing is applied; fix the reported edit and retry.\n\nUse the OOXML workflow below only for what these tools cannot do: pictures, charts, SmartArt, new designs, or presentations LobsterAI reports as read-only.\n\n## Editing an existing PowerPoint presentation\n\nWhen edit slides in an existing PowerPoint presentation, you need to work with the raw Office Open XML (OOXML) format. This involves unpacking the .pptx file, editing the XML content, and repacking it.\n\n### Workflow\n1. **MANDATORY - READ ENTIRE FILE**: Read `ooxml.md` from the same directory as this `SKILL.md` (installed default: `$SKILLS_ROOT/pptx/ooxml.md`) (~500 lines) completely from start to finish.  **NEVER set any range limits when reading this file.**  Read the full file content for detailed guidance on OOXML structure and editing workflows before any presentation editing.\n2. Unpack the presentation: `python ooxml/scripts/unpack.py <office_file> <output_dir>`\n3. Edit the XML files (primarily `ppt/slides/slide{N}.xml` and related files)\n4. **CRITICAL**: Validate immediately after each edit and fix any validation errors before proceeding: `python ooxml/scripts/validate.py <dir> --original <file>`\n5. Pack the final presentation: `python ooxml/scripts/pack.py <input_directory> <office_file>`\n\n## Creating a new PowerPoint presentation **using a template**\n\nWhen you need to create a presentation that follows an existing template's design, you'll need to duplicate and re-arrange template slides before then replacing placeholder context.\n\n### Workflow\n1. **Extract template text AND create visual thumbnail grid**:\n   * Extract text: `python -m markitdown template.pptx > template-content.md`\n   * Read `template-content.md`: Read the entire file to understand the contents of the template presentation. **NEVER set any range limits when reading this file.**\n   * Create thumbnail grids: `python scripts/thumbnail.py template.pptx`\n   * See [Creating Thumbnail Grids](#creating-thumbnail-grids) section for more details\n\n2. **Analyze template and save inventory to a file**:\n   * **Visual Analysis**: Review thumbnail grid(s) to understand slide layouts, design patterns, and visual structure\n   * Create and save a template inventory file at `template-inventory.md` containing:\n     ```markdown\n     # Template Inventory Analysis\n     **Total Slides: [count]**\n     **IMPORTANT: Slides are 0-indexed (first slide = 0, last slide = count-1)**\n\n     ## [Category Name]\n     - Slide 0: [Layout code if available] - Description/purpose\n     - Slide 1: [Layout code] - Description/purpose\n     - Slide 2: [Layout code] - Description/purpose\n     [... EVERY slide must be listed individually with its index ...]\n     ```\n   * **Using the thumbnail grid**: Reference the visual thumbnails to identify:\n     - Layout patterns (title slides, content layouts, section dividers)\n     - Image placeholder locations and counts\n     - Design consistency across slide groups\n     - Visual hierarchy and structure\n   * This inventory file is REQUIRED for selecting appropriate templates in the next step\n\n3. **Create presentation outline based on template inventory**:\n   * Review available templates from step 2.\n   * Choose an intro or title template for the first slide. This should be one of the first templates.\n   * Choose safe, text-based layouts for the other slides.\n   * **CRITICAL: Match layout structure to actual content**:\n     - Single-column layouts: Use for unified narrative or single topic\n     - Two-column layouts: Use ONLY when you have exactly 2 distinct items/concepts\n     - Three-column layouts: Use ONLY when you have exactly 3 distinct items/concepts\n     - Image + text layouts: Use ONLY when you have actual images to insert\n     - Quote layouts: Use ONLY for actual quotes from people (with attribution), never for emphasis\n     - Never use layouts with more placeholders than you have content\n     - If you have 2 items, don't force them into a 3-column layout\n     - If you have 4+ items, consider breaking into multiple slides or using a list format\n   * Count your actual content pieces BEFORE selecting the layout\n   * Verify each placeholder in the chosen layout will be filled with meaningful content\n   * Select one option representing the **best** layout for each content section.\n   * Save `outline.md` with content AND template mapping that leverages available designs\n   * Example template mapping:\n      ```\n      # Template slides to use (0-based indexing)\n      # WARNING: Verify indices are within range! Template with 73 slides has indices 0-72\n      # Mapping: slide numbers from outline -> template slide indices\n      template_mapping = [\n          0,   # Use slide 0 (Title/Cover)\n          34,  # Use slide 34 (B1: Title and body)\n          34,  # Use slide 34 again (duplicate for second B1)\n          50,  # Use slide 50 (E1: Quote)\n          54,  # Use slide 54 (F2: Closing + Text)\n      ]\n      ```\n\n4. **Duplicate, reorder, and delete slides using `rearrange.py`**:\n   * Use the `scripts/rearrange.py` script to create a new presentation with slides in the desired order:\n     ```bash\n     python scripts/rearrange.py template.pptx working.pptx 0,34,34,50,52\n     ```\n   * The script handles duplicating repeated slides, deleting unused slides, and reordering automatically\n   * Slide indices are 0-based (first slide is 0, second is 1, etc.)\n   * The same slide index can appear multiple times to duplicate that slide\n\n5. **Extract ALL text using the `inventory.py` script**:\n   * **Run inventory extraction**:\n     ```bash\n     python scripts/inventory.py working.pptx text-inventory.json\n     ```\n   * **Read text-inventory.json**: Read the entire text-inventory.json file to understand all shapes and their properties. **NEVER set any range limits when reading this file.**\n\n   * The inventory JSON structure:\n      ```json\n        {\n          \"slide-0\": {\n            \"shape-0\": {\n              \"placeholder_type\": \"TITLE\",  // or null for non-placeholders\n              \"left\": 1.5,                  // position in inches\n              \"top\": 2.0,\n              \"width\": 7.5,\n              \"height\": 1.2,\n              \"paragraphs\": [\n                {\n                  \"text\": \"Paragraph text\",\n                  // Optional properties (only included when non-default):\n                  \"bullet\": true,           // explicit bullet detected\n                  \"level\": 0,               // only included when bullet is true\n                  \"alignment\": \"CENTER\",    // CENTER, RIGHT (not LEFT)\n                  \"space_before\": 10.0,     // space before paragraph in points\n                  \"space_after\": 6.0,       // space after paragraph in points\n                  \"line_spacing\": 22.4,     // line spacing in points\n                  \"font_name\": \"Arial\",     // from first run\n                  \"font_size\": 14.0,        // in points\n                  \"bold\": true,\n                  \"italic\": false,\n                  \"underline\": false,\n                  \"color\": \"FF0000\"         // RGB color\n                }\n              ]\n            }\n          }\n        }\n      ```\n\n   * Key features:\n     - **Slides**: Named as \"slide-0\", \"slide-1\", etc.\n     - **Shapes**: Ordered by visual position (top-to-bottom, left-to-right) as \"shape-0\", \"shape-1\", etc.\n     - **Placeholder types**: TITLE, CENTER_TITLE, SUBTITLE, BODY, OBJECT, or null\n     - **Default font size**: `default_font_size` in points extracted from layout placeholders (when available)\n     - **Slide numbers are filtered**: Shapes with SLIDE_NUMBER placeholder type are automatically excluded from inventory\n     - **Bullets**: When `bullet: true`, `level` is always included (even if 0)\n     - **Spacing**: `space_before`, `space_after`, and `line_spacing` in points (only included when set)\n     - **Colors**: `color` for RGB (e.g., \"FF0000\"), `theme_color` for theme colors (e.g., \"DARK_1\")\n     - **Properties**: Only non-default values are included in the output\n\n6. **Generate replacement text and save the data to a JSON file**\n   Based on the text inventory from the previous step:\n   - **CRITICAL**: First verify which shapes exist in the inventory - only reference shapes that are actually present\n   - **VALIDATION**: The replace.py script will validate that all shapes in your replacement JSON exist in the inventory\n     - If you reference a non-existent shape, you'll get an error showing available shapes\n     - If you reference a non-existent slide, you'll get an error indicating the slide doesn't exist\n     - All validation errors are shown at once before the script exits\n   - **IMPORTANT**: The replace.py script uses inventory.py internally to identify ALL text shapes\n   - **AUTOMATIC CLEARING**: ALL text shapes from the inventory will be cleared unless you provide \"paragraphs\" for them\n   - Add a \"paragraphs\" field to shapes that need content (not \"replacement_paragraphs\")\n   - Shapes without \"paragraphs\" in the replacement JSON will have their text cleared automatically\n   - Paragraphs with bullets will be automatically left aligned. Don't set the `alignment` property on when `\"bullet\": true`\n   - Generate appropriate replacement content for placeholder text\n   - Use shape size to determine appropriate content length\n   - **CRITICAL**: Include paragraph properties from the original inventory - don't just provide text\n   - **IMPORTANT**: When bullet: true, do NOT include bullet symbols (•, -, *) in text - they're added automatically\n   - **ESSENTIAL FORMATTING RULES**:\n     - Headers/titles should typically have `\"bold\": true`\n     - List items should have `\"bullet\": true, \"level\": 0` (level is required when bullet is true)\n     - Preserve any alignment properties (e.g., `\"alignment\": \"CENTER\"` for centered text)\n     - Include font properties when different from default (e.g., `\"font_size\": 14.0`, `\"font_name\": \"Lora\"`)\n     - Colors: Use `\"color\": \"FF0000\"` for RGB or `\"theme_color\": \"DARK_1\"` for theme colors\n     - The replacement script expects **properly formatted paragraphs**, not just text strings\n     - **Overlapping shapes**: Prefer shapes with larger default_font_size or more appropriate placeholder_type\n   - Save the updated inventory with replacements to `replacement-text.json`\n   - **WARNING**: Different template layouts have different shape counts - always check the actual inventory before creating replacements\n\n   Example paragraphs field showing proper formatting:\n   ```json\n   \"paragraphs\": [\n     {\n       \"text\": \"New presentation title text\",\n       \"alignment\": \"CENTER\",\n       \"bold\": true\n     },\n     {\n       \"text\": \"Section Header\",\n       \"bold\": true\n     },\n     {\n       \"text\": \"First bullet point without bullet symbol\",\n       \"bullet\": true,\n       \"level\": 0\n     },\n     {\n       \"text\": \"Red colored text\",\n       \"color\": \"FF0000\"\n     },\n     {\n       \"text\": \"Theme colored text\",\n       \"theme_color\": \"DARK_1\"\n     },\n     {\n       \"text\": \"Regular paragraph text without special formatting\"\n     }\n   ]\n   ```\n\n   **Shapes not listed in the replacement JSON are automatically cleared**:\n   ```json\n   {\n     \"slide-0\": {\n       \"shape-0\": {\n         \"paragraphs\": [...] // This shape gets new text\n       }\n       // shape-1 and shape-2 from inventory will be cleared automatically\n     }\n   }\n   ```\n\n   **Common formatting patterns for presentations**:\n   - Title slides: Bold text, sometimes centered\n   - Section headers within slides: Bold text\n   - Bullet lists: Each item needs `\"bullet\": true, \"level\": 0`\n   - Body text: Usually no special properties needed\n   - Quotes: May have special alignment or font properties\n\n7. **Apply replacements using the `replace.py` script**\n   ```bash\n   python scripts/replace.py working.pptx replacement-text.json output.pptx\n   ```\n\n   The script will:\n   - First extract the inventory of ALL text shapes using functions from inventory.py\n   - Validate that all shapes in the replacement JSON exist in the inventory\n   - Clear text from ALL shapes identified in the inventory\n   - Apply new text only to shapes with \"paragraphs\" defined in the replacement JSON\n   - Preserve formatting by applying paragraph properties from the JSON\n   - Handle bullets, alignment, font properties, and colors automatically\n   - Save the updated presentation\n\n   Example validation errors:\n   ```\n   ERROR: Invalid shapes in replacement JSON:\n     - Shape 'shape-99' not found on 'slide-0'. Available shapes: shape-0, shape-1, shape-4\n     - Slide 'slide-999' not found in inventory\n   ```\n\n   ```\n   ERROR: Replacement text made overflow worse in these shapes:\n     - slide-0/shape-2: overflow worsened by 1.25\" (was 0.00\", now 1.25\")\n   ```\n\n## Creating Thumbnail Grids\n\nTo create visual thumbnail grids of PowerPoint slides for quick analysis and reference:\n\n```bash\npython scripts/thumbnail.py template.pptx [output_prefix]\n```\n\n**Features**:\n- Creates: `thumbnails.jpg` (or `thumbnails-1.jpg`, `thumbnails-2.jpg`, etc. for large decks)\n- Default: 5 columns, max 30 slides per grid (5×6)\n- Custom prefix: `python scripts/thumbnail.py template.pptx my-grid`\n  - Note: The output prefix should include the path if you want output in a specific directory (e.g., `workspace/my-grid`)\n- Adjust columns: `--cols 4` (range: 3-6, affects slides per grid)\n- Grid limits: 3 cols = 12 slides/grid, 4 cols = 20, 5 cols = 30, 6 cols = 42\n- Slides are zero-indexed (Slide 0, Slide 1, etc.)\n\n**Use cases**:\n- Template analysis: Quickly understand slide layouts and design patterns\n- Content review: Visual overview of entire presentation\n- Navigation reference: Find specific slides by their visual appearance\n- Quality check: Verify all slides are properly formatted\n\n**Examples**:\n```bash\n# Basic usage\npython scripts/thumbnail.py presentation.pptx\n\n# Combine options: custom name, columns\npython scripts/thumbnail.py template.pptx analysis --cols 4\n```\n\n## Converting Slides to Images\n\nTo visually analyze PowerPoint slides, convert them to images using a two-step process:\n\n1. **Convert PPTX to PDF**:\n   ```bash\n   soffice --headless --convert-to pdf template.pptx\n   ```\n\n2. **Convert PDF pages to JPEG images**:\n   ```bash\n   pdftoppm -jpeg -r 150 template.pdf slide\n   ```\n   This creates files like `slide-1.jpg`, `slide-2.jpg`, etc.\n\nOptions:\n- `-r 150`: Sets resolution to 150 DPI (adjust for quality/size balance)\n- `-jpeg`: Output JPEG format (use `-png` for PNG if preferred)\n- `-f N`: First page to convert (e.g., `-f 2` starts from page 2)\n- `-l N`: Last page to convert (e.g., `-l 5` stops at page 5)\n- `slide`: Prefix for output files\n\nExample for specific range:\n```bash\npdftoppm -jpeg -r 150 -f 2 -l 5 template.pdf slide  # Converts only pages 2-5\n```\n\n## Code Style Guidelines\n**IMPORTANT**: When generating code for PPTX operations:\n- Write concise code\n- Avoid verbose variable names and redundant operations\n- Avoid unnecessary print statements\n\n## Dependencies\n\nRequired dependencies (should already be installed):\n\n- **markitdown**: `pip install \"markitdown[pptx]\"` (for text extraction from presentations)\n- **pptxgenjs**: `npm install -g pptxgenjs` (for creating presentations via html2pptx)\n- **playwright**: `npm install -g playwright` (for HTML rendering in html2pptx)\n- **react-icons**: `npm install -g react-icons react react-dom` (for icons)\n- **sharp**: `npm install -g sharp` (for SVG rasterization and image processing)\n- **LibreOffice**: `sudo apt-get install libreoffice` (for PDF conversion)\n- **Poppler**: `sudo apt-get install poppler-utils` (for pdftoppm to convert PDF to images)\n- **defusedxml**: `pip install defusedxml` (for secure XML parsing)\n","SKILLs/skill-creator/SKILL.md":"---\nname: skill-creator\ndescription: Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, update or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.\nofficial: true\nversion: 1.0.1\n---\n\n# Skill Creator\n\nA skill for creating new skills and iteratively improving them.\n\nAt a high level, the process of creating a skill goes like this:\n\n- Decide what you want the skill to do and roughly how it should do it\n- Write a draft of the skill\n- Create a few test prompts and run claude-with-access-to-the-skill on them\n- Help the user evaluate the results both qualitatively and quantitatively\n  - While the runs happen in the background, draft some quantitative evals if there aren't any (if there are some, you can either use as is or modify if you feel something needs to change about them). Then explain them to the user (or if they already existed, explain the ones that already exist)\n  - Use the `eval-viewer/generate_review.py` script to show the user the results for them to look at, and also let them look at the quantitative metrics\n- Rewrite the skill based on feedback from the user's evaluation of the results (and also if there are any glaring flaws that become apparent from the quantitative benchmarks)\n- Repeat until you're satisfied\n- Expand the test set and try again at larger scale\n\nYour job when using this skill is to figure out where the user is in this process and then jump in and help them progress through these stages. So for instance, maybe they're like \"I want to make a skill for X\". You can help narrow down what they mean, write a draft, write the test cases, figure out how they want to evaluate, run all the prompts, and repeat.\n\nOn the other hand, maybe they already have a draft of the skill. In this case you can go straight to the eval/iterate part of the loop.\n\nOf course, you should always be flexible and if the user is like \"I don't need to run a bunch of evaluations, just vibe with me\", you can do that instead.\n\nThen after the skill is done (but again, the order is flexible), you can also run the skill description improver, which we have a whole separate script for, to optimize the triggering of the skill.\n\nCool? Cool.\n\n## Communicating with the user\n\nThe skill creator is liable to be used by people across a wide range of familiarity with coding jargon. If you haven't heard (and how could you, it's only very recently that it started), there's a trend now where the power of Claude is inspiring plumbers to open up their terminals, parents and grandparents to google \"how to install npm\". On the other hand, the bulk of users are probably fairly computer-literate.\n\nSo please pay attention to context cues to understand how to phrase your communication! In the default case, just to give you some idea:\n\n- \"evaluation\" and \"benchmark\" are borderline, but OK\n- for \"JSON\" and \"assertion\" you want to see serious cues from the user that they know what those things are before using them without explaining them\n\nIt's OK to briefly explain terms if you're in doubt, and feel free to clarify terms with a short definition if you're unsure if the user will get it.\n\n---\n\n## Creating a skill\n\n### Capture Intent\n\nStart by understanding the user's intent. The current conversation might already contain a workflow the user wants to capture (e.g., they say \"turn this into a skill\"). If so, extract answers from the conversation history first — the tools used, the sequence of steps, corrections the user made, input/output formats observed. The user may need to fill the gaps, and should confirm before proceeding to the next step.\n\n1. What should this skill enable Claude to do?\n2. When should this skill trigger? (what user phrases/contexts)\n3. What's the expected output format?\n4. Should we set up test cases to verify the skill works? Skills with objectively verifiable outputs (file transforms, data extraction, code generation, fixed workflow steps) benefit from test cases. Skills with subjective outputs (writing style, art) often don't need them. Suggest the appropriate default based on the skill type, but let the user decide.\n\n### Interview and Research\n\nProactively ask questions about edge cases, input/output formats, example files, success criteria, and dependencies. Wait to write test prompts until you've got this part ironed out.\n\nCheck available MCPs - if useful for research (searching docs, finding similar skills, looking up best practices), research in parallel via subagents if available, otherwise inline. Come prepared with context to reduce burden on the user.\n\n### Write the SKILL.md\n\nBased on the user interview, fill in these components:\n\n- **name**: Skill identifier\n- **description**: When to trigger, what it does. This is the primary triggering mechanism - include both what the skill does AND specific contexts for when to use it. All \"when to use\" info goes here, not in the body. Note: currently Claude has a tendency to \"undertrigger\" skills -- to not use them when they'd be useful. To combat this, please make the skill descriptions a little bit \"pushy\". So for instance, instead of \"How to build a simple fast dashboard to display internal Anthropic data.\", you might write \"How to build a simple fast dashboard to display internal Anthropic data. Make sure to use this skill whenever the user mentions dashboards, data visualization, internal metrics, or wants to display any kind of company data, even if they don't explicitly ask for a 'dashboard.'\"\n- **compatibility**: Required tools, dependencies (optional, rarely needed)\n- **the rest of the skill :)**\n\n### Skill Writing Guide\n\n#### Anatomy of a Skill\n\n```\nskill-name/\n├── SKILL.md (required)\n│   ├── YAML frontmatter (name, description required)\n│   └── Markdown instructions\n└── Bundled Resources (optional)\n    ├── scripts/    - Executable code for deterministic/repetitive tasks\n    ├── references/ - Docs loaded into context as needed\n    └── assets/     - Files used in output (templates, icons, fonts)\n```\n\n#### Progressive Disclosure\n\nSkills use a three-level loading system:\n1. **Metadata** (name + description) - Always in context (~100 words)\n2. **SKILL.md body** - In context whenever skill triggers (<500 lines ideal)\n3. **Bundled resources** - As needed (unlimited, scripts can execute without loading)\n\nThese word counts are approximate and you can feel free to go longer if needed.\n\n**Key patterns:**\n- Keep SKILL.md under 500 lines; if you're approaching this limit, add an additional layer of hierarchy along with clear pointers about where the model using the skill should go next to follow up.\n- Reference files clearly from SKILL.md with guidance on when to read them\n- For large reference files (>300 lines), include a table of contents\n\n**Domain organization**: When a skill supports multiple domains/frameworks, organize by variant:\n```\ncloud-deploy/\n├── SKILL.md (workflow + selection)\n└── references/\n    ├── aws.md\n    ├── gcp.md\n    └── azure.md\n```\nClaude reads only the relevant reference file.\n\n#### Principle of Lack of Surprise\n\nThis goes without saying, but skills must not contain malware, exploit code, or any content that could compromise system security. A skill's contents should not surprise the user in their intent if described. Don't go along with requests to create misleading skills or skills designed to facilitate unauthorized access, data exfiltration, or other malicious activities. Things like a \"roleplay as an XYZ\" are OK though.\n\n#### Writing Patterns\n\nPrefer using the imperative form in instructions.\n\n**Defining output formats** - You can do it like this:\n```markdown\n## Report structure\nALWAYS use this exact template:\n# [Title]\n## Executive summary\n## Key findings\n## Recommendations\n```\n\n**Examples pattern** - It's useful to include examples. You can format them like this (but if \"Input\" and \"Output\" are in the examples you might want to deviate a little):\n```markdown\n## Commit message format\n**Example 1:**\nInput: Added user authentication with JWT tokens\nOutput: feat(auth): implement JWT-based authentication\n```\n\n### Writing Style\n\nTry to explain to the model why things are important in lieu of heavy-handed musty MUSTs. Use theory of mind and try to make the skill general and not super-narrow to specific examples. Start by writing a draft and then look at it with fresh eyes and improve it.\n\n### Test Cases\n\nAfter writing the skill draft, come up with 2-3 realistic test prompts — the kind of thing a real user would actually say. Share them with the user: [you don't have to use this exact language] \"Here are a few test cases I'd like to try. Do these look right, or do you want to add more?\" Then run them.\n\nSave test cases to `evals/evals.json`. Don't write assertions yet — just the prompts. You'll draft assertions in the next step while the runs are in progress.\n\n```json\n{\n  \"skill_name\": \"example-skill\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"prompt\": \"User's task prompt\",\n      \"expected_output\": \"Description of expected result\",\n      \"files\": []\n    }\n  ]\n}\n```\n\nSee `references/schemas.md` for the full schema (including the `assertions` field, which you'll add later).\n\n## Running and evaluating test cases\n\nThis section is one continuous sequence — don't stop partway through. Do NOT use `/skill-test` or any other testing skill.\n\nPut results in `<skill-name>-workspace/` as a sibling to the skill directory. Within the workspace, organize results by iteration (`iteration-1/`, `iteration-2/`, etc.) and within that, each test case gets a directory (`eval-0/`, `eval-1/`, etc.). Don't create all of this upfront — just create directories as you go.\n\n### Step 1: Spawn all runs (with-skill AND baseline) in the same turn\n\nFor each test case, spawn two subagents in the same turn — one with the skill, one without. This is important: don't spawn the with-skill runs first and then come back for baselines later. Launch everything at once so it all finishes around the same time.\n\n**With-skill run:**\n\n```\nExecute this task:\n- Skill path: <path-to-skill>\n- Task: <eval prompt>\n- Input files: <eval files if any, or \"none\">\n- Save outputs to: <workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/\n- Outputs to save: <what the user cares about — e.g., \"the .docx file\", \"the final CSV\">\n```\n\n**Baseline run** (same prompt, but the baseline depends on context):\n- **Creating a new skill**: no skill at all. Same prompt, no skill path, save to `without_skill/outputs/`.\n- **Improving an existing skill**: the old version. Before editing, snapshot the skill (`cp -r <skill-path> <workspace>/skill-snapshot/`), then point the baseline subagent at the snapshot. Save to `old_skill/outputs/`.\n\nWrite an `eval_metadata.json` for each test case (assertions can be empty for now). Give each eval a descriptive name based on what it's testing — not just \"eval-0\". Use this name for the directory too. If this iteration uses new or modified eval prompts, create these files for each new eval directory — don't assume they carry over from previous iterations.\n\n```json\n{\n  \"eval_id\": 0,\n  \"eval_name\": \"descriptive-name-here\",\n  \"prompt\": \"The user's task prompt\",\n  \"assertions\": []\n}\n```\n\n### Step 2: While runs are in progress, draft assertions\n\nDon't just wait for the runs to finish — you can use this time productively. Draft quantitative assertions for each test case and explain them to the user. If assertions already exist in `evals/evals.json`, review them and explain what they check.\n\nGood assertions are objectively verifiable and have descriptive names — they should read clearly in the benchmark viewer so someone glancing at the results immediately understands what each one checks. Subjective skills (writing style, design quality) are better evaluated qualitatively — don't force assertions onto things that need human judgment.\n\nUpdate the `eval_metadata.json` files and `evals/evals.json` with the assertions once drafted. Also explain to the user what they'll see in the viewer — both the qualitative outputs and the quantitative benchmark.\n\n### Step 3: As runs complete, capture timing data\n\nWhen each subagent task completes, you receive a notification containing `total_tokens` and `duration_ms`. Save this data immediately to `timing.json` in the run directory:\n\n```json\n{\n  \"total_tokens\": 84852,\n  \"duration_ms\": 23332,\n  \"total_duration_seconds\": 23.3\n}\n```\n\nThis is the only opportunity to capture this data — it comes through the task notification and isn't persisted elsewhere. Process each notification as it arrives rather than trying to batch them.\n\n### Step 4: Grade, aggregate, and launch the viewer\n\nOnce all runs are done:\n\n1. **Grade each run** — spawn a grader subagent (or grade inline) that reads `agents/grader.md` and evaluates each assertion against the outputs. Save results to `grading.json` in each run directory. The grading.json expectations array must use the fields `text`, `passed`, and `evidence` (not `name`/`met`/`details` or other variants) — the viewer depends on these exact field names. For assertions that can be checked programmatically, write and run a script rather than eyeballing it — scripts are faster, more reliable, and can be reused across iterations.\n\n2. **Aggregate into benchmark** — run the aggregation script from the skill-creator directory:\n   ```bash\n   python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>\n   ```\n   This produces `benchmark.json` and `benchmark.md` with pass_rate, time, and tokens for each configuration, with mean ± stddev and the delta. If generating benchmark.json manually, see `references/schemas.md` for the exact schema the viewer expects.\nPut each with_skill version before its baseline counterpart.\n\n3. **Do an analyst pass** — read the benchmark data and surface patterns the aggregate stats might hide. See `agents/analyzer.md` (the \"Analyzing Benchmark Results\" section) for what to look for — things like assertions that always pass regardless of skill (non-discriminating), high-variance evals (possibly flaky), and time/token tradeoffs.\n\n4. **Launch the viewer** with both qualitative outputs and quantitative data:\n   ```bash\n   nohup python <skill-creator-path>/eval-viewer/generate_review.py \\\n     <workspace>/iteration-N \\\n     --skill-name \"my-skill\" \\\n     --benchmark <workspace>/iteration-N/benchmark.json \\\n     > /dev/null 2>&1 &\n   VIEWER_PID=$!\n   ```\n   For iteration 2+, also pass `--previous-workspace <workspace>/iteration-<N-1>`.\n\n   **Cowork / headless environments:** If `webbrowser.open()` is not available or the environment has no display, use `--static <output_path>` to write a standalone HTML file instead of starting a server. Feedback will be downloaded as a `feedback.json` file when the user clicks \"Submit All Reviews\". After download, copy `feedback.json` into the workspace directory for the next iteration to pick up.\n\nNote: please use generate_review.py to create the viewer; there's no need to write custom HTML.\n\n5. **Tell the user** something like: \"I've opened the results in your browser. There are two tabs — 'Outputs' lets you click through each test case and leave feedback, 'Benchmark' shows the quantitative comparison. When you're done, come back here and let me know.\"\n\n### What the user sees in the viewer\n\nThe \"Outputs\" tab shows one test case at a time:\n- **Prompt**: the task that was given\n- **Output**: the files the skill produced, rendered inline where possible\n- **Previous Output** (iteration 2+): collapsed section showing last iteration's output\n- **Formal Grades** (if grading was run): collapsed section showing assertion pass/fail\n- **Feedback**: a textbox that auto-saves as they type\n- **Previous Feedback** (iteration 2+): their comments from last time, shown below the textbox\n\nThe \"Benchmark\" tab shows the stats summary: pass rates, timing, and token usage for each configuration, with per-eval breakdowns and analyst observations.\n\nNavigation is via prev/next buttons or arrow keys. When done, they click \"Submit All Reviews\" which saves all feedback to `feedback.json`.\n\n### Step 5: Read the feedback\n\nWhen the user tells you they're done, read `feedback.json`:\n\n```json\n{\n  \"reviews\": [\n    {\"run_id\": \"eval-0-with_skill\", \"feedback\": \"the chart is missing axis labels\", \"timestamp\": \"...\"},\n    {\"run_id\": \"eval-1-with_skill\", \"feedback\": \"\", \"timestamp\": \"...\"},\n    {\"run_id\": \"eval-2-with_skill\", \"feedback\": \"perfect, love this\", \"timestamp\": \"...\"}\n  ],\n  \"status\": \"complete\"\n}\n```\n\nEmpty feedback means the user thought it was fine. Focus your improvements on the test cases where the user had specific complaints.\n\nKill the viewer server when you're done with it:\n\n```bash\nkill $VIEWER_PID 2>/dev/null\n```\n\n---\n\n## Improving the skill\n\nThis is the heart of the loop. You've run the test cases, the user has reviewed the results, and now you need to make the skill better based on their feedback.\n\n### How to think about improvements\n\n1. **Generalize from the feedback.** The big picture thing that's happening here is that we're trying to create skills that can be used a million times (maybe literally, maybe even more who knows) across many different prompts. Here you and the user are iterating on only a few examples over and over again because it helps move faster. The user knows these examples in and out and it's quick for them to assess new outputs. But if the skill you and the user are codeveloping works only for those examples, it's useless. Rather than put in fiddly overfitty changes, or oppressively constrictive MUSTs, if there's some stubborn issue, you might try branching out and using different metaphors, or recommending different patterns of working. It's relatively cheap to try and maybe you'll land on something great.\n\n2. **Keep the prompt lean.** Remove things that aren't pulling their weight. Make sure to read the transcripts, not just the final outputs — if it looks like the skill is making the model waste a bunch of time doing things that are unproductive, you can try getting rid of the parts of the skill that are making it do that and seeing what happens.\n\n3. **Explain the why.** Try hard to explain the **why** behind everything you're asking the model to do. Today's LLMs are *smart*. They have good theory of mind and when given a good harness can go beyond rote instructions and really make things happen. Even if the feedback from the user is terse or frustrated, try to actually understand the task and why the user is writing what they wrote, and what they actually wrote, and then transmit this understanding into the instructions. If you find yourself writing ALWAYS or NEVER in all caps, or using super rigid structures, that's a yellow flag — if possible, reframe and explain the reasoning so that the model understands why the thing you're asking for is important. That's a more humane, powerful, and effective approach.\n\n4. **Look for repeated work across test cases.** Read the transcripts from the test runs and notice if the subagents all independently wrote similar helper scripts or took the same multi-step approach to something. If all 3 test cases resulted in the subagent writing a `create_docx.py` or a `build_chart.py`, that's a strong signal the skill should bundle that script. Write it once, put it in `scripts/`, and tell the skill to use it. This saves every future invocation from reinventing the wheel.\n\nThis task is pretty important (we are trying to create billions a year in economic value here!) and your thinking time is not the blocker; take your time and really mull things over. I'd suggest writing a draft revision and then looking at it anew and making improvements. Really do your best to get into the head of the user and understand what they want and need.\n\n### The iteration loop\n\nAfter improving the skill:\n\n1. Apply your improvements to the skill\n2. Rerun all test cases into a new `iteration-<N+1>/` directory, including baseline runs. If you're creating a new skill, the baseline is always `without_skill` (no skill) — that stays the same across iterations. If you're improving an existing skill, use your judgment on what makes sense as the baseline: the original version the user came in with, or the previous iteration.\n3. Launch the reviewer with `--previous-workspace` pointing at the previous iteration\n4. Wait for the user to review and tell you they're done\n5. Read the new feedback, improve again, repeat\n\nKeep going until:\n- The user says they're happy\n- The feedback is all empty (everything looks good)\n- You're not making meaningful progress\n\n---\n\n## Advanced: Blind comparison\n\nFor situations where you want a more rigorous comparison between two versions of a skill (e.g., the user asks \"is the new version actually better?\"), there's a blind comparison system. Read `agents/comparator.md` and `agents/analyzer.md` for the details. The basic idea is: give two outputs to an independent agent without telling it which is which, and let it judge quality. Then analyze why the winner won.\n\nThis is optional, requires subagents, and most users won't need it. The human review loop is usually sufficient.\n\n---\n\n## Description Optimization\n\nThe description field in SKILL.md frontmatter is the primary mechanism that determines whether Claude invokes a skill. After creating or improving a skill, offer to optimize the description for better triggering accuracy.\n\n### Step 1: Generate trigger eval queries\n\nCreate 20 eval queries — a mix of should-trigger and should-not-trigger. Save as JSON:\n\n```json\n[\n  {\"query\": \"the user prompt\", \"should_trigger\": true},\n  {\"query\": \"another prompt\", \"should_trigger\": false}\n]\n```\n\nThe queries must be realistic and something a Claude Code or Claude.ai user would actually type. Not abstract requests, but requests that are concrete and specific and have a good amount of detail. For instance, file paths, personal context about the user's job or situation, column names and values, company names, URLs. A little bit of backstory. Some might be in lowercase or contain abbreviations or typos or casual speech. Use a mix of different lengths, and focus on edge cases rather than making them clear-cut (the user will get a chance to sign off on them).\n\nBad: `\"Format this data\"`, `\"Extract text from PDF\"`, `\"Create a chart\"`\n\nGood: `\"ok so my boss just sent me this xlsx file (its in my downloads, called something like 'Q4 sales final FINAL v2.xlsx') and she wants me to add a column that shows the profit margin as a percentage. The revenue is in column C and costs are in column D i think\"`\n\nFor the **should-trigger** queries (8-10), think about coverage. You want different phrasings of the same intent — some formal, some casual. Include cases where the user doesn't explicitly name the skill or file type but clearly needs it. Throw in some uncommon use cases and cases where this skill competes with another but should win.\n\nFor the **should-not-trigger** queries (8-10), the most valuable ones are the near-misses — queries that share keywords or concepts with the skill but actually need something different. Think adjacent domains, ambiguous phrasing where a naive keyword match would trigger but shouldn't, and cases where the query touches on something the skill does but in a context where another tool is more appropriate.\n\nThe key thing to avoid: don't make should-not-trigger queries obviously irrelevant. \"Write a fibonacci function\" as a negative test for a PDF skill is too easy — it doesn't test anything. The negative cases should be genuinely tricky.\n\n### Step 2: Review with user\n\nPresent the eval set to the user for review using the HTML template:\n\n1. Read the template from `assets/eval_review.html`\n2. Replace the placeholders:\n   - `__EVAL_DATA_PLACEHOLDER__` → the JSON array of eval items (no quotes around it — it's a JS variable assignment)\n   - `__SKILL_NAME_PLACEHOLDER__` → the skill's name\n   - `__SKILL_DESCRIPTION_PLACEHOLDER__` → the skill's current description\n3. Write to a temp file (e.g., `/tmp/eval_review_<skill-name>.html`) and open it: `open /tmp/eval_review_<skill-name>.html`\n4. The user can edit queries, toggle should-trigger, add/remove entries, then click \"Export Eval Set\"\n5. The file downloads to `~/Downloads/eval_set.json` — check the Downloads folder for the most recent version in case there are multiple (e.g., `eval_set (1).json`)\n\nThis step matters — bad eval queries lead to bad descriptions.\n\n### Step 3: Run the optimization loop\n\nTell the user: \"This will take some time — I'll run the optimization loop in the background and check on it periodically.\"\n\nSave the eval set to the workspace, then run in the background:\n\n```bash\npython -m scripts.run_loop \\\n  --eval-set <path-to-trigger-eval.json> \\\n  --skill-path <path-to-skill> \\\n  --model <model-id-powering-this-session> \\\n  --max-iterations 5 \\\n  --verbose\n```\n\nUse the model ID from your system prompt (the one powering the current session) so the triggering test matches what the user actually experiences.\n\nWhile it runs, periodically tail the output to give the user updates on which iteration it's on and what the scores look like.\n\nThis handles the full optimization loop automatically. It splits the eval set into 60% train and 40% held-out test, evaluates the current description (running each query 3 times to get a reliable trigger rate), then calls Claude with extended thinking to propose improvements based on what failed. It re-evaluates each new description on both train and test, iterating up to 5 times. When it's done, it opens an HTML report in the browser showing the results per iteration and returns JSON with `best_description` — selected by test score rather than train score to avoid overfitting.\n\n### How skill triggering works\n\nUnderstanding the triggering mechanism helps design better eval queries. Skills appear in Claude's `available_skills` list with their name + description, and Claude decides whether to consult a skill based on that description. The important thing to know is that Claude only consults skills for tasks it can't easily handle on its own — simple, one-step queries like \"read this PDF\" may not trigger a skill even if the description matches perfectly, because Claude can handle them directly with basic tools. Complex, multi-step, or specialized queries reliably trigger skills when the description matches.\n\nThis means your eval queries should be substantive enough that Claude would actually benefit from consulting a skill. Simple queries like \"read file X\" are poor test cases — they won't trigger skills regardless of description quality.\n\n### Step 4: Apply the result\n\nTake `best_description` from the JSON output and update the skill's SKILL.md frontmatter. Show the user before/after and report the scores.\n\n---\n\n### Package and Present (only if `present_files` tool is available)\n\nCheck whether you have access to the `present_files` tool. If you don't, skip this step. If you do, package the skill and present the .skill file to the user:\n\n```bash\npython -m scripts.package_skill <path/to/skill-folder>\n```\n\nAfter packaging, direct the user to the resulting `.skill` file path so they can install it.\n\n---\n\n## Claude.ai-specific instructions\n\nIn Claude.ai, the core workflow is the same (draft → test → review → improve → repeat), but because Claude.ai doesn't have subagents, some mechanics change. Here's what to adapt:\n\n**Running test cases**: No subagents means no parallel execution. For each test case, read the skill's SKILL.md, then follow its instructions to accomplish the test prompt yourself. Do them one at a time. This is less rigorous than independent subagents (you wrote the skill and you're also running it, so you have full context), but it's a useful sanity check — and the human review step compensates. Skip the baseline runs — just use the skill to complete the task as requested.\n\n**Reviewing results**: If you can't open a browser (e.g., Claude.ai's VM has no display, or you're on a remote server), skip the browser reviewer entirely. Instead, present results directly in the conversation. For each test case, show the prompt and the output. If the output is a file the user needs to see (like a .docx or .xlsx), save it to the filesystem and tell them where it is so they can download and inspect it. Ask for feedback inline: \"How does this look? Anything you'd change?\"\n\n**Benchmarking**: Skip the quantitative benchmarking — it relies on baseline comparisons which aren't meaningful without subagents. Focus on qualitative feedback from the user.\n\n**The iteration loop**: Same as before — improve the skill, rerun the test cases, ask for feedback — just without the browser reviewer in the middle. You can still organize results into iteration directories on the filesystem if you have one.\n\n**Description optimization**: This section requires the `claude` CLI tool (specifically `claude -p`) which is only available in Claude Code. Skip it if you're on Claude.ai.\n\n**Blind comparison**: Requires subagents. Skip it.\n\n**Packaging**: The `package_skill.py` script works anywhere with Python and a filesystem. On Claude.ai, you can run it and the user can download the resulting `.skill` file.\n\n---\n\n## Cowork-Specific Instructions\n\nIf you're in Cowork, the main things to know are:\n\n- You have subagents, so the main workflow (spawn test cases in parallel, run baselines, grade, etc.) all works. (However, if you run into severe problems with timeouts, it's OK to run the test prompts in series rather than parallel.)\n- You don't have a browser or display, so when generating the eval viewer, use `--static <output_path>` to write a standalone HTML file instead of starting a server. Then proffer a link that the user can click to open the HTML in their browser.\n- For whatever reason, the Cowork setup seems to disincline Claude from generating the eval viewer after running the tests, so just to reiterate: whether you're in Cowork or in Claude Code, after running tests, you should always generate the eval viewer for the human to look at examples before revising the skill yourself and trying to make corrections, using `generate_review.py` (not writing your own boutique html code). Sorry in advance but I'm gonna go all caps here: GENERATE THE EVAL VIEWER *BEFORE* evaluating inputs yourself. You want to get them in front of the human ASAP!\n- Feedback works differently: since there's no running server, the viewer's \"Submit All Reviews\" button will download `feedback.json` as a file. You can then read it from there (you may have to request access first).\n- Packaging works — `package_skill.py` just needs Python and a filesystem.\n- Description optimization (`run_loop.py` / `run_eval.py`) should work in Cowork just fine since it uses `claude -p` via subprocess, not a browser, but please save it until you've fully finished making the skill and the user agrees it's in good shape.\n\n---\n\n## Reference files\n\nThe agents/ directory contains instructions for specialized subagents. Read them when you need to spawn the relevant subagent.\n\n- `agents/grader.md` — How to evaluate assertions against outputs\n- `agents/comparator.md` — How to do blind A/B comparison between two outputs\n- `agents/analyzer.md` — How to analyze why one version beat another\n\nThe references/ directory has additional documentation:\n- `references/schemas.md` — JSON structures for evals.json, grading.json, etc.\n\n---\n\nRepeating one more time the core loop here for emphasis:\n\n- Figure out what the skill is about\n- Draft or edit the skill\n- Run claude-with-access-to-the-skill on test prompts\n- With the user, evaluate the outputs:\n  - Create benchmark.json and run `eval-viewer/generate_review.py` to help the user review them\n  - Run quantitative evals\n- Repeat until you and the user are satisfied\n- Package the final skill and return it to the user.\n\nPlease add steps to your TodoList, if you have such a thing, to make sure you don't forget. If you're in Cowork, please specifically put \"Create evals JSON and run `eval-viewer/generate_review.py` so human can review test cases\" in your TodoList to make sure it happens.\n\nGood luck!\n","SKILLs/pdf/SKILL.md":"---\nname: pdf\ndescription: Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.\nlicense: Proprietary. LICENSE.txt has complete terms\nofficial: true\n---\n\n# PDF Processing Guide\n\n## Overview\n\nThis guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see reference.md. If you need to fill out a PDF form, read forms.md and follow its instructions.\n\n## Quick Start\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Read a PDF\nreader = PdfReader(\"document.pdf\")\nprint(f\"Pages: {len(reader.pages)}\")\n\n# Extract text\ntext = \"\"\nfor page in reader.pages:\n    text += page.extract_text()\n```\n\n## Python Libraries\n\n### pypdf - Basic Operations\n\n#### Merge PDFs\n```python\nfrom pypdf import PdfWriter, PdfReader\n\nwriter = PdfWriter()\nfor pdf_file in [\"doc1.pdf\", \"doc2.pdf\", \"doc3.pdf\"]:\n    reader = PdfReader(pdf_file)\n    for page in reader.pages:\n        writer.add_page(page)\n\nwith open(\"merged.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n#### Split PDF\n```python\nreader = PdfReader(\"input.pdf\")\nfor i, page in enumerate(reader.pages):\n    writer = PdfWriter()\n    writer.add_page(page)\n    with open(f\"page_{i+1}.pdf\", \"wb\") as output:\n        writer.write(output)\n```\n\n#### Extract Metadata\n```python\nreader = PdfReader(\"document.pdf\")\nmeta = reader.metadata\nprint(f\"Title: {meta.title}\")\nprint(f\"Author: {meta.author}\")\nprint(f\"Subject: {meta.subject}\")\nprint(f\"Creator: {meta.creator}\")\n```\n\n#### Rotate Pages\n```python\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\npage = reader.pages[0]\npage.rotate(90)  # Rotate 90 degrees clockwise\nwriter.add_page(page)\n\nwith open(\"rotated.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### pdfplumber - Text and Table Extraction\n\n#### Extract Text with Layout\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        text = page.extract_text()\n        print(text)\n```\n\n#### Extract Tables\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for i, page in enumerate(pdf.pages):\n        tables = page.extract_tables()\n        for j, table in enumerate(tables):\n            print(f\"Table {j+1} on page {i+1}:\")\n            for row in table:\n                print(row)\n```\n\n#### Advanced Table Extraction\n```python\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    all_tables = []\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            if table:  # Check if table is not empty\n                df = pd.DataFrame(table[1:], columns=table[0])\n                all_tables.append(df)\n\n# Combine all tables\nif all_tables:\n    combined_df = pd.concat(all_tables, ignore_index=True)\n    combined_df.to_excel(\"extracted_tables.xlsx\", index=False)\n```\n\n### reportlab - Create PDFs\n\n#### Basic PDF Creation\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.pdfgen import canvas\n\nc = canvas.Canvas(\"hello.pdf\", pagesize=letter)\nwidth, height = letter\n\n# Add text\nc.drawString(100, height - 100, \"Hello World!\")\nc.drawString(100, height - 120, \"This is a PDF created with reportlab\")\n\n# Add a line\nc.line(100, height - 140, 400, height - 140)\n\n# Save\nc.save()\n```\n\n#### Create PDF with Multiple Pages\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak\nfrom reportlab.lib.styles import getSampleStyleSheet\n\ndoc = SimpleDocTemplate(\"report.pdf\", pagesize=letter)\nstyles = getSampleStyleSheet()\nstory = []\n\n# Add content\ntitle = Paragraph(\"Report Title\", styles['Title'])\nstory.append(title)\nstory.append(Spacer(1, 12))\n\nbody = Paragraph(\"This is the body of the report. \" * 20, styles['Normal'])\nstory.append(body)\nstory.append(PageBreak())\n\n# Page 2\nstory.append(Paragraph(\"Page 2\", styles['Heading1']))\nstory.append(Paragraph(\"Content for page 2\", styles['Normal']))\n\n# Build PDF\ndoc.build(story)\n```\n\n## Command-Line Tools\n\n### pdftotext (poppler-utils)\n```bash\n# Extract text\npdftotext input.pdf output.txt\n\n# Extract text preserving layout\npdftotext -layout input.pdf output.txt\n\n# Extract specific pages\npdftotext -f 1 -l 5 input.pdf output.txt  # Pages 1-5\n```\n\n### qpdf\n```bash\n# Merge PDFs\nqpdf --empty --pages file1.pdf file2.pdf -- merged.pdf\n\n# Split pages\nqpdf input.pdf --pages . 1-5 -- pages1-5.pdf\nqpdf input.pdf --pages . 6-10 -- pages6-10.pdf\n\n# Rotate pages\nqpdf input.pdf output.pdf --rotate=+90:1  # Rotate page 1 by 90 degrees\n\n# Remove password\nqpdf --password=mypassword --decrypt encrypted.pdf decrypted.pdf\n```\n\n### pdftk (if available)\n```bash\n# Merge\npdftk file1.pdf file2.pdf cat output merged.pdf\n\n# Split\npdftk input.pdf burst\n\n# Rotate\npdftk input.pdf rotate 1east output rotated.pdf\n```\n\n## Common Tasks\n\n### Extract Text from Scanned PDFs\n```python\n# Requires: pip install pytesseract pdf2image\nimport pytesseract\nfrom pdf2image import convert_from_path\n\n# Convert PDF to images\nimages = convert_from_path('scanned.pdf')\n\n# OCR each page\ntext = \"\"\nfor i, image in enumerate(images):\n    text += f\"Page {i+1}:\\n\"\n    text += pytesseract.image_to_string(image)\n    text += \"\\n\\n\"\n\nprint(text)\n```\n\n### Add Watermark\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Create watermark (or load existing)\nwatermark = PdfReader(\"watermark.pdf\").pages[0]\n\n# Apply to all pages\nreader = PdfReader(\"document.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    page.merge_page(watermark)\n    writer.add_page(page)\n\nwith open(\"watermarked.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### Extract Images\n```bash\n# Using pdfimages (poppler-utils)\npdfimages -j input.pdf output_prefix\n\n# This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc.\n```\n\n### Password Protection\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    writer.add_page(page)\n\n# Add password\nwriter.encrypt(\"userpassword\", \"ownerpassword\")\n\nwith open(\"encrypted.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n## Quick Reference\n\n| Task | Best Tool | Command/Code |\n|------|-----------|--------------|\n| Merge PDFs | pypdf | `writer.add_page(page)` |\n| Split PDFs | pypdf | One page per file |\n| Extract text | pdfplumber | `page.extract_text()` |\n| Extract tables | pdfplumber | `page.extract_tables()` |\n| Create PDFs | reportlab | Canvas or Platypus |\n| Command line merge | qpdf | `qpdf --empty --pages ...` |\n| OCR scanned PDFs | pytesseract | Convert to image first |\n| Fill PDF forms | pdf-lib or pypdf (see forms.md) | See forms.md |\n\n## Next Steps\n\n- For advanced pypdfium2 usage, see reference.md\n- For JavaScript libraries (pdf-lib), see reference.md\n- If you need to fill out a PDF form, follow the instructions in forms.md\n- For troubleshooting guides, see reference.md\n","SKILLs/frontend-design/SKILL.md":"---\nname: frontend-design\ndescription: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.\nlicense: Complete terms in LICENSE.txt\nofficial: true\n---\n\nThis skill guides creation of distinctive, production-grade frontend interfaces that avoid generic \"AI slop\" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.\n\nThe user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.\n\n## Design Thinking\n\nBefore coding, understand the context and commit to a BOLD aesthetic direction:\n- **Purpose**: What problem does this interface solve? Who uses it?\n- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.\n- **Constraints**: Technical requirements (framework, performance, accessibility).\n- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?\n\n**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.\n\nThen implement working code (HTML/CSS/JS, React, Vue, etc.) that is:\n- Production-grade and functional\n- Visually striking and memorable\n- Cohesive with a clear aesthetic point-of-view\n- Meticulously refined in every detail\n\n## Frontend Aesthetics Guidelines\n\nFocus on:\n- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.\n- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.\n- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.\n- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.\n- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.\n\nNEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.\n\nInterpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.\n\n**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.\n\nRemember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.\n","SKILLs/imap-smtp-email/SKILL.md":"---\nname: imap-smtp-email\ndescription: Read and send email via IMAP/SMTP. Check for new/unread messages, fetch content, search mailboxes, mark as read/unread, and send emails with attachments. Works with any IMAP/SMTP server including Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, and vip.188.com.\nofficial: true\nversion: 1.0.7\n---\n\n# IMAP/SMTP Email Tool\n\nRead, search, and manage email via IMAP protocol. Send email via SMTP. Supports Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, vip.188.com, and any standard IMAP/SMTP server.\n\n## Important: Configuration is Pre-configured\n\nThe `accounts.json` configuration file is automatically managed by LobsterAI Settings (邮箱设置). Legacy `.env` configuration is still supported as a fallback for older users. **Do NOT ask the user to create or edit these files — just run the commands directly.** If credentials are wrong, the scripts will return a clear error message; only then should you inform the user to check their email settings.\n\nThe configuration files are located in this skill's directory (same folder as this SKILL.md file). The scripts load them automatically via absolute paths, regardless of the current working directory.\n\nUse the provided scripts as the only email transport interface. Do not write temporary IMAP/SMTP scripts, do not use raw sockets, OpenSSL, `net`, `tls`, or alternate mail clients, and do not inspect `.env`, `accounts.json`, or script source unless the official command output explicitly reports missing configuration and the user asks you to diagnose it. If an official command fails or times out, report that command result and suggest checking LobsterAI Settings; do not implement a fallback protocol client.\n\nDo not claim that `node-imap`, `nodemailer`, or another dependency is broken unless an official script or verified stack trace proves it. A successful command means the configured email account works; a timeout means the current command timed out, not that the dependency is defective.\n\nCommand results intentionally redact account metadata. In user-facing replies, use the redacted account label/email from the JSON result and do not repeat full configured email addresses unless the user explicitly asks for the exact address. Email content fields such as sender, subject, and message body may still be shown when they are the requested result.\n\nNever ask the user to send an email authorization code, app password, account password, or other credential in chat. If an account is disabled, incomplete, or has invalid credentials, ask the user to enable or update it in LobsterAI Settings > Email Settings, then rerun the official command.\n\nFor multi-account setups:\n- Run `node scripts/imap.js accounts` or `node scripts/smtp.js accounts` to list configured account IDs without exposing secrets.\n- Omit `--account` to use the default enabled account.\n- Pass `--account <id>` to use a specific account.\n- Pass `--all-accounts` only for read/list commands that support fan-out (`check`, `search`, `list-mailboxes`).\n- JSON results for read/list commands include `success`, redacted account metadata, `command`, `count`, and result arrays such as `messages` or `mailboxes`.\n\nFor sending email, always review recipient, subject, sender account, and body with the user first. Sending is blocked unless `--confirmed` is passed.\n\nFor SMTP send results, `success: true` means the sending SMTP server accepted the message for processing. Do not claim final delivery or inbox receipt. Report it as \"submitted to the SMTP server\" and mention that the recipient provider may still reject it later via a bounce message. If `rejected` or `pending` recipients are present, call them out explicitly.\n\nNever use a redacted account email such as `ab***@example.com` as a recipient address. If the user asks to send to another configured email account, use that account's `id` with `--to-account <id>` so the script resolves the real address internally without exposing it.\n\n## Configuration Reference\n\nCreate `.env` in the skill folder or set environment variables:\n\n```bash\n# IMAP Configuration (receiving email)\nIMAP_HOST=imap.gmail.com          # Server hostname\nIMAP_PORT=993                     # Server port\nIMAP_USER=your@email.com\nIMAP_PASS=your_password\nIMAP_TLS=true                     # Use TLS/SSL connection\nIMAP_REJECT_UNAUTHORIZED=true     # Set to false for self-signed certs\nIMAP_MAILBOX=INBOX                # Default mailbox\n\n# SMTP Configuration (sending email)\nSMTP_HOST=smtp.gmail.com          # SMTP server hostname\nSMTP_PORT=587                     # SMTP port (587 for STARTTLS, 465 for SSL)\nSMTP_SECURE=false                 # true for SSL (465), false for STARTTLS (587)\nSMTP_USER=your@gmail.com          # Your email address\nSMTP_PASS=your_password           # Your password or app password\nSMTP_FROM=your@gmail.com          # Default sender email (optional)\nSMTP_REJECT_UNAUTHORIZED=true     # Set to false for self-signed certs\n```\n\n## Common Email Servers\n\n| Provider | IMAP Host | IMAP Port | SMTP Host | SMTP Port |\n|----------|-----------|-----------|-----------|-----------|\n| 163.com | imap.163.com | 993 | smtp.163.com | 465 |\n| vip.163.com | imap.vip.163.com | 993 | smtp.vip.163.com | 465 |\n| 126.com | imap.126.com | 993 | smtp.126.com | 465 |\n| vip.126.com | imap.vip.126.com | 993 | smtp.vip.126.com | 465 |\n| 188.com | imap.188.com | 993 | smtp.188.com | 465 |\n| vip.188.com | imap.vip.188.com | 993 | smtp.vip.188.com | 465 |\n| yeah.net | imap.yeah.net | 993 | smtp.yeah.net | 465 |\n| Gmail | imap.gmail.com | 993 | smtp.gmail.com | 587 |\n| Outlook | outlook.office365.com | 993 | smtp.office365.com | 587 |\n| QQ Mail | imap.qq.com | 993 | smtp.qq.com | 587 |\n\n**Important for 163.com:**\n- Use **authorization code** (授权码), not account password\n- Enable IMAP/SMTP in web settings first\n\n## IMAP Commands (Receiving Email)\n\n### accounts\nList configured email accounts without exposing passwords.\n\n```bash\nnode scripts/imap.js accounts\n```\n\n### check\nCheck for new/unread emails.\n\n```bash\nnode scripts/imap.js check [--limit 10] [--mailbox INBOX] [--recent 2h]\nnode scripts/imap.js check --all-accounts [--limit 10]\n```\n\nOptions:\n- `--account <id>`: Use a specific configured account\n- `--all-accounts`: Check every enabled account\n- `--limit <n>`: Max results (default: 10)\n- `--mailbox <name>`: Mailbox to check (default: INBOX)\n- `--recent <time>`: Only show emails from last X time (e.g., 30m, 2h, 7d)\n\n### fetch\nFetch full email content by UID.\n\n```bash\nnode scripts/imap.js fetch <uid> [--mailbox INBOX]\nnode scripts/imap.js fetch <uid> --account <id> [--mailbox INBOX]\n```\n\n### download\nDownload all attachments from an email, or a specific attachment.\n\n```bash\nnode scripts/imap.js download <uid> [--mailbox INBOX] [--dir <path>] [--file <filename>]\nnode scripts/imap.js download <uid> --account <id> [--mailbox INBOX] [--dir <path>] [--file <filename>]\n```\n\nOptions:\n- `--mailbox <name>`: Mailbox (default: INBOX)\n- `--dir <path>`: Output directory (default: current directory)\n- `--file <filename>`: Download only the specified attachment (default: download all)\n\n### search\nSearch emails with filters.\n\n```bash\nnode scripts/imap.js search [options]\n\nOptions:\n  --unseen           Only unread messages\n  --seen             Only read messages\n  --from <email>     From address contains\n  --subject <text>   Subject contains\n  --recent <time>    From last X time (e.g., 30m, 2h, 7d)\n  --since <date>     After date (YYYY-MM-DD)\n  --before <date>    Before date (YYYY-MM-DD)\n  --limit <n>        Max results (default: 20)\n  --mailbox <name>   Mailbox to search (default: INBOX)\n  --account <id>     Use a specific configured account\n  --all-accounts     Search every enabled account\n```\n\n### mark-read / mark-unread\nMark message(s) as read or unread.\n\n```bash\nnode scripts/imap.js mark-read <uid> [uid2 uid3...]\nnode scripts/imap.js mark-unread <uid> [uid2 uid3...]\nnode scripts/imap.js mark-read --account <id> <uid> [uid2 uid3...]\n```\n\n### list-mailboxes\nList all available mailboxes/folders.\n\n```bash\nnode scripts/imap.js list-mailboxes\nnode scripts/imap.js list-mailboxes --all-accounts\n```\n\n## SMTP Commands (Sending Email)\n\n### accounts\nList configured email accounts without exposing passwords.\n\n```bash\nnode scripts/smtp.js accounts\n```\n\n### send\nSubmit email via SMTP. A successful command means the SMTP server accepted the message for processing, not that the recipient inbox has received it.\n\n```bash\nnode scripts/smtp.js send --to <email> --subject <text> --confirmed [options]\n```\n\n**Required:**\n- `--to <email>`: Recipient (comma-separated for multiple)\n- `--subject <text>`: Email subject, or `--subject-file <file>`\n\n**Optional:**\n- `--body <text>`: Plain text body\n- `--html`: Send body as HTML\n- `--body-file <file>`: Read body from file\n- `--html-file <file>`: Read HTML from file\n- `--cc <email>`: CC recipients\n- `--bcc <email>`: BCC recipients\n- `--attach <file>`: Attachments (comma-separated)\n- `--from <email>`: Override default sender\n- `--account <id>`: Send from a specific configured account\n- `--to-account <id>`: Send to a configured account by ID without exposing its full email address\n- `--confirmed`: Required after the user confirms the email details\n\n**Examples:**\n```bash\n# Simple text email\nnode scripts/smtp.js send --to recipient@example.com --subject \"Hello\" --body \"World\"\n\n# HTML email\nnode scripts/smtp.js send --to recipient@example.com --subject \"Newsletter\" --html --body \"<h1>Welcome</h1>\"\n\n# Email with attachment\nnode scripts/smtp.js send --to recipient@example.com --subject \"Report\" --body \"Please find attached\" --attach report.pdf\n\n# Multiple recipients\nnode scripts/smtp.js send --to \"a@example.com,b@example.com\" --cc \"c@example.com\" --subject \"Update\" --body \"Team update\"\n\n# Send to another configured account by ID\nnode scripts/smtp.js send --account default --to-account account-2 --subject \"Hello\" --body \"World\"\n```\n\n### test\nTest SMTP connection by sending a test email to yourself.\n\n```bash\nnode scripts/smtp.js test\n```\n\n## Dependencies\n\n```bash\nnpm install\n```\n\n## Security Notes\n\n- Store credentials in `.env` (add to `.gitignore`)\n- For Gmail: use App Password if 2FA is enabled\n- For 163.com: use authorization code (授权码), not account password\n- Downloaded attachment filenames are normalized to a safe local filename and cannot create directories outside the account/UID download folder.\n\n## Troubleshooting\n\n**Connection timeout:**\n- Verify server is running and accessible\n- Check host/port configuration\n\n**Authentication failed:**\n- Verify username (usually full email address)\n- Check password is correct\n- For 163.com: use authorization code, not account password\n- For Gmail: use App Password if 2FA enabled\n\n**TLS/SSL errors:**\n- Match `IMAP_TLS`/`SMTP_SECURE` setting to server requirements\n- For self-signed certs: set `IMAP_REJECT_UNAUTHORIZED=false` or `SMTP_REJECT_UNAUTHORIZED=false`\n","SKILLs/local-tools/SKILL.md":"---\nname: local-tools\ndescription: Access local system resources including Calendar on macOS and Windows. Use this skill when you need to manage user's schedule directly on their device.\nofficial: true\n---\n\n# Local Tools Skill\n\n## When to Use This Skill\n\nUse the local-tools skill when you need to:\n\n- **Calendar Management** - View, create, update, or delete calendar events\n\n**Examples of when to use:**\n- User: \"Show me my schedule for tomorrow\"\n- User: \"Create a meeting at 3 PM\"\n- User: \"Search for calendar events containing 'project'\"\n- User: \"Delete tomorrow's meeting\"\n\n## How It Works\n\n```\n┌──────────┐    Bash/PowerShell    ┌─────────────────────────────────────────────────────────────┐\n│  Claude  │──────────────────────▶│  calendar.sh / calendar.ps1                                 │\n│          │                       │  ├─ macOS: osascript -l JavaScript (JXA) ──▶ Calendar.app   │\n│          │                       │  └─ Windows: PowerShell ──▶ Outlook COM API                 │\n└──────────┘                       └─────────────────────────────────────────────────────────────┘\n```\n\n**Architecture:**\n1. **CLI Scripts** - Platform-specific scripts, no HTTP server needed\n   - `calendar.sh` - Bash script for macOS\n   - `calendar.ps1` - PowerShell script for Windows\n\n2. **Local Calendar Access** - Direct access to system calendar\n   - macOS: Uses JXA (JavaScript for Automation) to control Calendar.app\n   - Windows: Uses PowerShell COM API to control Microsoft Outlook\n\n3. **JSON Output** - Structured data format for easy parsing\n\n## Platform Support\n\n| Platform | Implementation | Calendar App | Status |\n|----------|---------------|--------------|--------|\n| **macOS 10.10+** | JXA + Calendar.app | Calendar.app | ✅ Fully Supported |\n| **Windows 7+** | PowerShell + COM | Microsoft Outlook | ✅ Fully Supported |\n| **Linux** | - | - | ❌ Not Supported |\n\n## Permissions\n\n### macOS\n- Requires \"Calendar\" access permission\n- User will be prompted on first use\n- Can be managed in: System Settings > Privacy & Security > Calendar\n\n### Windows\n- Requires Microsoft Outlook to be installed\n- May require administrative privileges for COM access\n\n## Calendar Operations\n\n**IMPORTANT: How to Locate the Script**\n\nWhen you read this SKILL.md file using the Read tool, you receive its absolute path (e.g., `/Users/username/.../SKILLs/local-tools/SKILL.md`).\n\n**To construct the script path:**\n1. Take the directory of this SKILL.md file\n2. Append `/scripts/calendar.sh` (macOS) or `/scripts/calendar.ps1` (Windows)\n\n**Example:**\n```bash\n# If SKILL.md is at: /Users/username/path/to/SKILLs/local-tools/SKILL.md\n# Then the script is: /Users/username/path/to/SKILLs/local-tools/scripts/calendar.sh\n\nbash \"/Users/username/path/to/SKILLs/local-tools/scripts/calendar.sh\" <operation> [options]\n```\n\nIn all examples below, `<skill-dir>/scripts/calendar.sh` is a placeholder. Replace it with the actual absolute path.\n\n### Best Practices for AI Assistant\n\n**DO:**\n- ✅ Execute commands directly without showing trial-and-error process\n- ✅ If command fails, inform user about permission issues without showing technical errors\n- ✅ Use `search` command for searching birthdays/anniversaries\n- ✅ If no calendar name specified, script will automatically use first available calendar\n\n**DON'T:**\n- ❌ Don't repeatedly try different command combinations\n- ❌ Don't show error stacks or technical details to users\n- ❌ Don't read script source code to analyze issues\n- ❌ Don't ask users for calendar name, use default behavior\n\n**Example - Searching for birthdays:**\n```bash\n# Correct approach: Search directly, don't trial-and-error\nbash \"<skill-dir>/scripts/calendar.sh\" search --query \"birthday\"\n\n# If permission error returned, directly tell user:\n# \"Calendar access permission is required. Please open System Settings > Privacy & Security > Calendar, and authorize Terminal or LobsterAI\"\n```\n\n### List Events\n\n```bash\n# List events for next 7 days (default)\nbash \"<skill-dir>/scripts/calendar.sh\" list\n\n# List events for specific date range\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-12T00:00:00\" \\\n  --end \"2026-02-19T23:59:59\"\n\n# List events from specific calendar (macOS)\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --calendar \"Work\"\n```\n\n### Create Event\n\n```bash\n# Create a simple event\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Team Meeting\" \\\n  --start \"2026-02-13T14:00:00\" \\\n  --end \"2026-02-13T15:00:00\"\n\n# Create event with location and notes\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Client Call\" \\\n  --start \"2026-02-14T10:00:00\" \\\n  --end \"2026-02-14T11:00:00\" \\\n  --calendar \"Work\" \\\n  --location \"Conference Room A\" \\\n  --notes \"Discuss Q1 roadmap\"\n```\n\n### Update Event\n\n```bash\n# Update event title\nbash \"<skill-dir>/scripts/calendar.sh\" update \\\n  --id \"EVENT-ID\" \\\n  --title \"Updated Meeting Title\"\n\n# Update event time\nbash \"<skill-dir>/scripts/calendar.sh\" update \\\n  --id \"EVENT-ID\" \\\n  --start \"2026-02-13T15:00:00\" \\\n  --end \"2026-02-13T16:00:00\"\n```\n\n### Delete Event\n\n```bash\nbash \"<skill-dir>/scripts/calendar.sh\" delete \\\n  --id \"EVENT-ID\"\n```\n\n### Search Events\n\n```bash\n# Search for events containing keyword (searches ALL calendars)\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"meeting\"\n\n# Search in specific calendar only\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"project\" \\\n  --calendar \"Work\"\n```\n\n**Note:** When `--calendar` is not specified, the search operation will look through **all available calendars** on both macOS and Windows.\n\n## Output Format\n\nAll commands return JSON with the following structure:\n\n### Success Response\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"events\": [\n      {\n        \"eventId\": \"E621F8C4-...\",\n        \"title\": \"Team Meeting\",\n        \"startTime\": \"2026-02-13T14:00:00.000Z\",\n        \"endTime\": \"2026-02-13T15:00:00.000Z\",\n        \"location\": \"Conference Room\",\n        \"notes\": \"Weekly sync\",\n        \"calendar\": \"Work\",\n        \"allDay\": false\n      }\n    ],\n    \"count\": 1\n  }\n}\n```\n\n### Error Response\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CALENDAR_ACCESS_ERROR\",\n    \"message\": \"Calendar access permission is required...\",\n    \"recoverable\": true,\n    \"permissionRequired\": true\n  }\n}\n```\n\n### Error Codes\n\n| Code | Meaning | Recoverable |\n|------|---------|-------------|\n| `CALENDAR_ACCESS_ERROR` | Permission denied or calendar not accessible | Yes |\n| `INVALID_INPUT` | Missing required parameters | No |\n| `EVENT_NOT_FOUND` | Event ID not found | No |\n| `OUTLOOK_NOT_AVAILABLE` | Microsoft Outlook not installed (Windows) | Yes |\n\n## Date Format Guidelines\n\n### Important: Date Format Guidelines\n\nWhen using the `list` command with time ranges:\n\n1. **Always use ISO 8601 format**: `YYYY-MM-DDTHH:mm:ss`\n2. **Use local timezone**: Do NOT use UTC or timezone suffixes (like +08:00 or Z)\n3. **Calculate dates yourself**: Do NOT use shell command substitution like `$(date ...)`\n4. **Claude should compute dates**: Based on current date, calculate target dates directly\n5. **Examples**:\n   - Today at midnight: `2026-02-13T00:00:00`\n   - Today at end of day: `2026-02-13T23:59:59`\n   - Tomorrow morning: `2026-02-14T09:00:00`\n   - Next week Monday: `2026-02-16T00:00:00`\n\n**Why**: The script expects local time strings that match your system timezone. Shell substitutions may not execute correctly in all environments.\n\n## Common Patterns\n\n### Pattern 1: Schedule Management\n\n```bash\n# User asks: \"What meetings do I have today?\"\n# Claude's approach: Calculate today's date and query full day from 00:00 to 23:59\n# IMPORTANT: Claude should replace 2026-02-13 with the actual current date\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-13T00:00:00\" \\\n  --end \"2026-02-13T23:59:59\"\n\n# User asks: \"What's on my schedule tomorrow?\"\n# Claude should calculate tomorrow's date (e.g., if today is 2026-02-13, tomorrow is 2026-02-14)\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-14T00:00:00\" \\\n  --end \"2026-02-14T23:59:59\"\n```\n\n### Pattern 2: Meeting Scheduling\n\n```bash\n# User asks: \"Schedule a meeting for tomorrow at 3 PM\"\n# Claude's approach:\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Meeting\" \\\n  --start \"2026-02-13T15:00:00\" \\\n  --end \"2026-02-13T16:00:00\" \\\n  --calendar \"Work\"\n```\n\n### Pattern 3: Event Search\n\n```bash\n# User asks: \"Find all meetings about the project\"\n# Claude's approach:\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"project\" \\\n  --calendar \"Work\"\n```\n\n### Pattern 4: Availability Check\n\n```bash\n# User asks: \"Am I free tomorrow afternoon?\"\n# Claude's approach:\n# 1. List tomorrow's events\n# 2. Analyze time slots\n# 3. Report availability\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-14T00:00:00\" \\\n  --end \"2026-02-14T23:59:59\"\n```\n\n## Known Behaviors\n\n### Time Range Matching\n\nThe `list` command uses **interval overlap detection**:\n- Returns events that have **any overlap** with the query time range\n- Does NOT require events to be fully contained within the range\n\n**Examples:**\n- Query: 2026-02-13 00:00:00 to 23:59:59\n- Returns:\n  - ✅ Events fully on Feb 13 (e.g., 10:00-11:00)\n  - ✅ Multi-day events spanning Feb 13 (e.g., Feb 12 10:00 - Feb 14 10:00)\n  - ✅ Events crossing midnight (e.g., Feb 13 23:30 - Feb 14 00:30)\n  - ❌ Events entirely before Feb 13 (e.g., Feb 12 10:00-11:00)\n  - ❌ Events entirely after Feb 13 (e.g., Feb 14 10:00-11:00)\n\n### All-Day Events\n\n- Treated as spanning from 00:00:00 to 23:59:59 on their date(s)\n- Multi-day all-day events (e.g., Feb 12-14) will appear when querying any date within that range\n\n### Time Precision\n\n- Comparisons use second-level precision\n- Milliseconds are ignored in date comparisons\n\n### Recurring Events\n\n- Each occurrence is treated as a separate event instance\n- The script returns individual occurrences within the queried time range\n\n## Best Practices\n\n### 1. Always Check Before Creating\n\nBefore creating an event, list existing events to avoid conflicts:\n\n```bash\n# First check existing events\nbash \"<skill-dir>/scripts/calendar.sh\" list\n\n# Then create if no conflict\nbash \"<skill-dir>/scripts/calendar.sh\" create ...\n```\n\n### 2. Use Specific Calendars (macOS)\n\nSpecify the calendar to keep events organized:\n\n```bash\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Team Meeting\" \\\n  --calendar \"Work\" \\\n  ...\n```\n\n### 3. Search Before Updating/Deleting\n\nAlways search first to get the correct event ID:\n\n```bash\n# Search to find event ID\nbash \"<skill-dir>/scripts/calendar.sh\" search --query \"meeting\"\n\n# Then update or delete\nbash \"<skill-dir>/scripts/calendar.sh\" update --id \"FOUND-ID\" ...\n```\n\n### 4. Handle Errors Gracefully\n\nParse the response and handle errors:\n\n```bash\nresult=$(bash \"<skill-dir>/scripts/calendar.sh\" list)\nif echo \"$result\" | grep -q '\"success\":true'; then\n  # Process events\n  events=$(echo \"$result\" | jq '.data.events')\nelse\n  # Handle error\n  error=$(echo \"$result\" | jq '.error.message')\n  echo \"Failed: $error\"\nfi\n```\n\n## Limitations\n\n### macOS\n- Requires macOS 10.10 Yosemite or later (for JXA support)\n- Requires Calendar access permission\n- Does not support advanced recurring event queries\n- Cannot modify recurring event rules\n\n### Windows\n- Requires Microsoft Outlook to be installed\n- Does not support other calendar applications (Windows Calendar, Google Calendar, etc.)\n- May require COM access permissions in corporate environments\n- Folder enumeration may skip restricted calendars\n\n### General\n- All dates must be in ISO 8601 format (`YYYY-MM-DDTHH:mm:ss`)\n- Uses local timezone for all operations\n- Return values are converted to UTC (ISO 8601 with Z suffix)\n- No support for attendees or meeting invitations\n\n## Troubleshooting\n\n### macOS\n\n**Permission Denied:**\n```\nError: Calendar access permission is required\n```\n**Solution:** Open System Settings > Privacy & Security > Calendar, authorize Terminal or LobsterAI\n\n**Script Not Found:**\n```\nbash: calendar.sh: No such file or directory\n```\n**Solution:** Ensure you're using the absolute path from SKILL.md's directory + `/scripts/calendar.sh`\n\n### Windows\n\n**Outlook Not Found:**\n```\nError: Microsoft Outlook is not installed or not accessible\n```\n**Solution:** Install Microsoft Outlook and ensure it's properly configured\n\n**PowerShell Execution Policy:**\n```\nError: Execution of scripts is disabled on this system\n```\n**Solution:** Run PowerShell as Administrator and execute:\n```powershell\nSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser\n```\n\n## Technical Details\n\n### macOS Implementation\n\n**JXA (JavaScript for Automation):**\n- Uses `osascript -l JavaScript` to execute JXA code\n- Controls Calendar.app via Apple Events\n- Works on both Intel and Apple Silicon Macs\n- Requires user permission for Calendar access\n\n**Date Handling:**\n- Uses BSD date command (macOS native)\n- Format: `date +%Y-%m-%dT%H:%M:%S` (local timezone)\n- Relative dates: `date -v+7d` (7 days from now)\n\n### Windows Implementation\n\n**PowerShell + COM:**\n- Uses Outlook COM API via PowerShell\n- Requires Outlook to be installed and configured\n- Works with all Outlook-compatible calendars\n\n**Date Handling:**\n- Uses PowerShell `[DateTime]::Parse()` for date parsing\n- Automatically handles local timezone\n\n### Cross-Platform Consistency\n\nBoth implementations:\n- Use identical JSON output format\n- Support the same operations (list, create, update, delete, search)\n- Handle dates in local timezone\n- Return UTC timestamps in ISO 8601 format\n\n## Related Skills\n\n- **imap-smtp-email** - For email-based meeting invitations\n","SKILLs/films-search/SKILL.md":"# films-search\n\nPath: `SKILLs/films-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/films-search/SKILL.md)","SKILLs/docx/SKILL.md":"# docx\n\nPath: `SKILLs/docx/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/SKILL.md)","SKILLs/develop-web-game/SKILL.md":"# develop-web-game\n\nPath: `SKILLs/develop-web-game/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/SKILL.md)","SKILLs/daily-trending/SKILL.md":"# daily-trending\n\nPath: `SKILLs/daily-trending/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/daily-trending/SKILL.md)","SKILLs/create-plan/SKILL.md":"# create-plan\n\nPath: `SKILLs/create-plan/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/create-plan/SKILL.md)","SKILLs/content-planner/SKILL.md":"# content-planner\n\nPath: `SKILLs/content-planner/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/content-planner/SKILL.md)","SKILLs/canvas-design/SKILL.md":"# canvas-design\n\nPath: `SKILLs/canvas-design/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/canvas-design/SKILL.md)","SKILLs/article-writer/SKILL.md":"# article-writer\n\nPath: `SKILLs/article-writer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/article-writer/SKILL.md)","SKILLs/stock-analyzer/SKILL.md":"# stock-analyzer\n\nPath: `SKILLs/stock-analyzer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-analyzer/SKILL.md)","SKILLs/stock-announcements/SKILL.md":"# stock-announcements\n\nPath: `SKILLs/stock-announcements/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-announcements/SKILL.md)","SKILLs/stock-explorer/SKILL.md":"# stock-explorer\n\nPath: `SKILLs/stock-explorer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-explorer/SKILL.md)","SKILLs/technology-news-search/SKILL.md":"# technology-news-search\n\nPath: `SKILLs/technology-news-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/technology-news-search/SKILL.md)","SKILLs/weather/SKILL.md":"# weather\n\nPath: `SKILLs/weather/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/weather/SKILL.md)","SKILLs/web-search/SKILL.md":"# web-search\n\nPath: `SKILLs/web-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/SKILL.md)","SKILLs/xlsx/SKILL.md":"# xlsx\n\nPath: `SKILLs/xlsx/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/xlsx/SKILL.md)","SKILLs/youdaonote/SKILL.md":"# youdaonote\n\nPath: `SKILLs/youdaonote/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/youdaonote/SKILL.md)","AGENTS.md":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/AGENTS.md)","SKILLs/skills.config.json":"# SKILLs Skill\n\nPath: `SKILLs/skills.config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skills.config.json)","openclaw-extensions/mcp-bridge/openclaw.plugin.json":"# mcp-bridge Plugin Manifest\n\nPath: `openclaw-extensions/mcp-bridge/openclaw.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/openclaw-extensions/mcp-bridge/openclaw.plugin.json)","openclaw-extensions/ask-user-question/openclaw.plugin.json":"# ask-user-question Plugin Manifest\n\nPath: `openclaw-extensions/ask-user-question/openclaw.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/openclaw-extensions/ask-user-question/openclaw.plugin.json)","SKILLs/skill-vetter/_meta.json":"# Skill-vetter Skill\n\nPath: `SKILLs/skill-vetter/_meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-vetter/_meta.json)","SKILLs/pptx/html2pptx.md":"# Pptx Skill\n\nPath: `SKILLs/pptx/html2pptx.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/html2pptx.md)","SKILLs/pptx/ooxml.md":"# Pptx Skill\n\nPath: `SKILLs/pptx/ooxml.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/ooxml.md)","SKILLs/pptx/package.json":"# Pptx Skill\n\nPath: `SKILLs/pptx/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/package.json)","SKILLs/pdf/forms.md":"# Pdf Skill\n\nPath: `SKILLs/pdf/forms.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/forms.md)","SKILLs/pdf/reference.md":"# Pdf Skill\n\nPath: `SKILLs/pdf/reference.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/reference.md)","SKILLs/imap-smtp-email/_meta.json":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/_meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/_meta.json)","SKILLs/imap-smtp-email/package.json":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/package.json)","SKILLs/imap-smtp-email/README.md":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/README.md)","SKILLs/docx/docx-js.md":"# Docx Skill\n\nPath: `SKILLs/docx/docx-js.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/docx-js.md)","SKILLs/docx/ooxml.md":"# Docx Skill\n\nPath: `SKILLs/docx/ooxml.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/ooxml.md)","SKILLs/web-search/DEPLOYMENT.md":"# Web-search Skill\n\nPath: `SKILLs/web-search/DEPLOYMENT.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/DEPLOYMENT.md)","SKILLs/web-search/IMPLEMENTATION.md":"# Web-search Skill\n\nPath: `SKILLs/web-search/IMPLEMENTATION.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/IMPLEMENTATION.md)","SKILLs/web-search/package.json":"# Web-search Skill\n\nPath: `SKILLs/web-search/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/package.json)","SKILLs/web-search/README.md":"# Web-search Skill\n\nPath: `SKILLs/web-search/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/README.md)","SKILLs/web-search/TEST.md":"# Web-search Skill\n\nPath: `SKILLs/web-search/TEST.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/TEST.md)","SKILLs/web-search/tsconfig.json":"# Web-search Skill\n\nPath: `SKILLs/web-search/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/tsconfig.json)","SKILLs/skill-creator/agents/analyzer.md":"# Subagent: analyzer\n\nPath: `SKILLs/skill-creator/agents/analyzer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/analyzer.md)","SKILLs/skill-creator/agents/comparator.md":"# Subagent: comparator\n\nPath: `SKILLs/skill-creator/agents/comparator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/comparator.md)","SKILLs/skill-creator/agents/grader.md":"# Subagent: grader\n\nPath: `SKILLs/skill-creator/agents/grader.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/grader.md)","SKILLs/skill-creator/references/schemas.md":"# References Skill\n\nPath: `SKILLs/skill-creator/references/schemas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/references/schemas.md)","SKILLs/remotion/rules/3d.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/3d.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/3d.md)","SKILLs/remotion/rules/animations.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/animations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/animations.md)","SKILLs/remotion/rules/assets.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/assets.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/assets.md)","SKILLs/remotion/rules/audio.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/audio.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/audio.md)","SKILLs/remotion/rules/calculate-metadata.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/calculate-metadata.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/calculate-metadata.md)","SKILLs/remotion/rules/can-decode.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/can-decode.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/can-decode.md)","SKILLs/remotion/rules/charts.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/charts.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/charts.md)","SKILLs/remotion/rules/compositions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/compositions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/compositions.md)","SKILLs/remotion/rules/display-captions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/display-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/display-captions.md)","SKILLs/remotion/rules/extract-frames.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/extract-frames.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/extract-frames.md)","SKILLs/remotion/rules/fonts.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/fonts.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/fonts.md)","SKILLs/remotion/rules/get-audio-duration.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-audio-duration.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-audio-duration.md)","SKILLs/remotion/rules/get-video-dimensions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-video-dimensions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-video-dimensions.md)","SKILLs/remotion/rules/get-video-duration.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-video-duration.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-video-duration.md)","SKILLs/remotion/rules/gifs.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/gifs.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/gifs.md)","SKILLs/remotion/rules/images.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/images.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/images.md)","SKILLs/remotion/rules/import-srt-captions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/import-srt-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/import-srt-captions.md)","SKILLs/remotion/rules/light-leaks.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/light-leaks.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/light-leaks.md)","SKILLs/remotion/rules/lottie.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/lottie.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/lottie.md)","SKILLs/remotion/rules/maps.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/maps.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/maps.md)","SKILLs/remotion/rules/measuring-dom-nodes.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/measuring-dom-nodes.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/measuring-dom-nodes.md)","SKILLs/remotion/rules/measuring-text.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/measuring-text.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/measuring-text.md)","SKILLs/remotion/rules/parameters.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/parameters.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/parameters.md)","SKILLs/remotion/rules/sequencing.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/sequencing.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/sequencing.md)","SKILLs/remotion/rules/subtitles.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/subtitles.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/subtitles.md)","SKILLs/remotion/rules/tailwind.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/tailwind.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/tailwind.md)","SKILLs/remotion/rules/text-animations.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/text-animations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/text-animations.md)","SKILLs/remotion/rules/timing.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/timing.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/timing.md)","SKILLs/remotion/rules/transcribe-captions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transcribe-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transcribe-captions.md)","SKILLs/remotion/rules/transitions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transitions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transitions.md)","SKILLs/remotion/rules/transparent-videos.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transparent-videos.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transparent-videos.md)","SKILLs/remotion/rules/trimming.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/trimming.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/trimming.md)","SKILLs/remotion/rules/videos.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/videos.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/videos.md)","SKILLs/playwright/agents/openai.yaml":"# Agents Skill\n\nPath: `SKILLs/playwright/agents/openai.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/agents/openai.yaml)","SKILLs/playwright/references/cli.md":"# References Skill\n\nPath: `SKILLs/playwright/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/cli.md)","SKILLs/playwright/references/workflows.md":"# References Skill\n\nPath: `SKILLs/playwright/references/workflows.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/workflows.md)","SKILLs/develop-web-game/agents/openai.yaml":"# Agents Skill\n\nPath: `SKILLs/develop-web-game/agents/openai.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/agents/openai.yaml)","SKILLs/develop-web-game/references/action_payloads.json":"# References Skill\n\nPath: `SKILLs/develop-web-game/references/action_payloads.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/references/action_payloads.json)","SKILLs/technology-news-search/references/sources.json":"# References Skill\n\nPath: `SKILLs/technology-news-search/references/sources.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/technology-news-search/references/sources.json)","SKILLs/web-search/examples/basic-search.md":"# Examples Skill\n\nPath: `SKILLs/web-search/examples/basic-search.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/examples/basic-search.md)"},"files":{"SKILLs/remotion/SKILL.md":"---\nname: remotion-best-practices\ndescription: Best practices for Remotion - Video creation in React\nofficial: true\nmetadata:\n  tags: remotion, video, react, animation, composition\n---\n\n## When to use\n\nUse this skills whenever you are dealing with Remotion code to obtain the domain-specific knowledge.\n\n## Captions\n\nWhen dealing with captions or subtitles, load the [./rules/subtitles.md](./rules/subtitles.md) file for more information.\n\n## How to use\n\nRead individual rule files for detailed explanations and code examples:\n\n- [rules/3d.md](rules/3d.md) - 3D content in Remotion using Three.js and React Three Fiber\n- [rules/animations.md](rules/animations.md) - Fundamental animation skills for Remotion\n- [rules/assets.md](rules/assets.md) - Importing images, videos, audio, and fonts into Remotion\n- [rules/audio.md](rules/audio.md) - Using audio and sound in Remotion - importing, trimming, volume, speed, pitch\n- [rules/calculate-metadata.md](rules/calculate-metadata.md) - Dynamically set composition duration, dimensions, and props\n- [rules/can-decode.md](rules/can-decode.md) - Check if a video can be decoded by the browser using Mediabunny\n- [rules/charts.md](rules/charts.md) - Chart and data visualization patterns for Remotion\n- [rules/compositions.md](rules/compositions.md) - Defining compositions, stills, folders, default props and dynamic metadata\n- [rules/extract-frames.md](rules/extract-frames.md) - Extract frames from videos at specific timestamps using Mediabunny\n- [rules/fonts.md](rules/fonts.md) - Loading Google Fonts and local fonts in Remotion\n- [rules/get-audio-duration.md](rules/get-audio-duration.md) - Getting the duration of an audio file in seconds with Mediabunny\n- [rules/get-video-dimensions.md](rules/get-video-dimensions.md) - Getting the width and height of a video file with Mediabunny\n- [rules/get-video-duration.md](rules/get-video-duration.md) - Getting the duration of a video file in seconds with Mediabunny\n- [rules/gifs.md](rules/gifs.md) - Displaying GIFs synchronized with Remotion's timeline\n- [rules/images.md](rules/images.md) - Embedding images in Remotion using the Img component\n- [rules/light-leaks.md](rules/light-leaks.md) - Light leak overlay effects using @remotion/light-leaks\n- [rules/lottie.md](rules/lottie.md) - Embedding Lottie animations in Remotion\n- [rules/measuring-dom-nodes.md](rules/measuring-dom-nodes.md) - Measuring DOM element dimensions in Remotion\n- [rules/measuring-text.md](rules/measuring-text.md) - Measuring text dimensions, fitting text to containers, and checking overflow\n- [rules/sequencing.md](rules/sequencing.md) - Sequencing patterns for Remotion - delay, trim, limit duration of items\n- [rules/tailwind.md](rules/tailwind.md) - Using TailwindCSS in Remotion\n- [rules/text-animations.md](rules/text-animations.md) - Typography and text animation patterns for Remotion\n- [rules/timing.md](rules/timing.md) - Interpolation curves in Remotion - linear, easing, spring animations\n- [rules/transitions.md](rules/transitions.md) - Scene transition patterns for Remotion\n- [rules/transparent-videos.md](rules/transparent-videos.md) - Rendering out a video with transparency\n- [rules/trimming.md](rules/trimming.md) - Trimming patterns for Remotion - cut the beginning or end of animations\n- [rules/videos.md](rules/videos.md) - Embedding videos in Remotion - trimming, volume, speed, looping, pitch\n- [rules/parameters.md](rules/parameters.md) - Make a video parametrizable by adding a Zod schema\n- [rules/maps.md](rules/maps.md) - Add a map using Mapbox and animate it\n","SKILLs/playwright/SKILL.md":"---\nname: \"playwright\"\ndescription: \"Use when the task requires automating a real browser from the terminal (navigation, form filling, snapshots, screenshots, data extraction, UI-flow debugging) via `playwright-cli` or the bundled wrapper script.\"\nofficial: true\n---\n\n\n# Playwright CLI Skill\n\nDrive a real browser from the terminal using `playwright-cli`. Prefer the bundled wrapper script so the CLI works even when it is not globally installed.\nTreat this skill as CLI-first automation. Do not pivot to `@playwright/test` unless the user explicitly asks for test files.\n\n## Prerequisite check (required)\n\nBefore proposing commands, check whether `npx` is available (the wrapper depends on it):\n\n```bash\ncommand -v npx >/dev/null 2>&1\n```\n\nIf it is not available, pause and ask the user to install Node.js/npm (which provides `npx`). Provide these steps verbatim:\n\n```bash\n# Verify Node/npm are installed\nnode --version\nnpm --version\n\n# If missing, install Node.js/npm, then:\nnpm install -g @playwright/mcp@latest\nplaywright-cli --help\n```\n\nOnce `npx` is present, proceed with the wrapper script. A global install of `playwright-cli` is optional.\n\n## Skill path (set once)\n\n```bash\nexport SKILLS_ROOT=\"${LOBSTERAI_SKILLS_ROOT:-${SKILLS_ROOT:-$HOME/Library/Application Support/LobsterAI/SKILLs}}\"\nexport PWCLI=\"$SKILLS_ROOT/playwright/scripts/playwright_cli.sh\"\n```\n\nInstalled skills resolve from `$LOBSTERAI_SKILLS_ROOT` / `$SKILLS_ROOT` (production default: app `userData/SKILLs`, macOS usually `~/Library/Application Support/LobsterAI/SKILLs`).\n\n## Quick start\n\nUse the wrapper script:\n\n```bash\n\"$PWCLI\" open https://playwright.dev --headed\n\"$PWCLI\" snapshot\n\"$PWCLI\" click e15\n\"$PWCLI\" type \"Playwright\"\n\"$PWCLI\" press Enter\n\"$PWCLI\" screenshot\n```\n\nIf the user prefers a global install, this is also valid:\n\n```bash\nnpm install -g @playwright/mcp@latest\nplaywright-cli --help\n```\n\n## Core workflow\n\n1. Open the page.\n2. Snapshot to get stable element refs.\n3. Interact using refs from the latest snapshot.\n4. Re-snapshot after navigation or significant DOM changes.\n5. Capture artifacts (screenshot, pdf, traces) when useful.\n\nMinimal loop:\n\n```bash\n\"$PWCLI\" open https://example.com\n\"$PWCLI\" snapshot\n\"$PWCLI\" click e3\n\"$PWCLI\" snapshot\n```\n\n## When to snapshot again\n\nSnapshot again after:\n\n- navigation\n- clicking elements that change the UI substantially\n- opening/closing modals or menus\n- tab switches\n\nRefs can go stale. When a command fails due to a missing ref, snapshot again.\n\n## Recommended patterns\n\n### Form fill and submit\n\n```bash\n\"$PWCLI\" open https://example.com/form\n\"$PWCLI\" snapshot\n\"$PWCLI\" fill e1 \"user@example.com\"\n\"$PWCLI\" fill e2 \"password123\"\n\"$PWCLI\" click e3\n\"$PWCLI\" snapshot\n```\n\n### Debug a UI flow with traces\n\n```bash\n\"$PWCLI\" open https://example.com --headed\n\"$PWCLI\" tracing-start\n# ...interactions...\n\"$PWCLI\" tracing-stop\n```\n\n### Multi-tab work\n\n```bash\n\"$PWCLI\" tab-new https://example.com\n\"$PWCLI\" tab-list\n\"$PWCLI\" tab-select 0\n\"$PWCLI\" snapshot\n```\n\n## Wrapper script\n\nThe wrapper script uses `npx --package @playwright/mcp playwright-cli` so the CLI can run without a global install:\n\n```bash\n\"$PWCLI\" --help\n```\n\nPrefer the wrapper unless the repository already standardizes on a global install.\n\n## References\n\nOpen only what you need:\n\n- CLI command reference: `references/cli.md`\n- Practical workflows and troubleshooting: `references/workflows.md`\n\n## Guardrails\n\n- Always snapshot before referencing element ids like `e12`.\n- Re-snapshot when refs seem stale.\n- Prefer explicit commands over `eval` and `run-code` unless needed.\n- When you do not have a fresh snapshot, use placeholder refs like `eX` and say why; do not bypass refs with `run-code`.\n- Use `--headed` when a visual check will help.\n- When capturing artifacts in this repo, use `output/playwright/` and avoid introducing new top-level artifact folders.\n- Default to CLI commands and workflows, not Playwright test specs.\n","SKILLs/skill-vetter/SKILL.md":"---\nname: skill-vetter\nversion: 1.0.0\ndescription: Security-first skill vetting for AI agents. Use before installing any skill from ClawdHub, GitHub, or other sources. Checks for red flags, permission scope, and suspicious patterns.\n---\n\n# Skill Vetter 🔒\n\nSecurity-first vetting protocol for AI agent skills. **Never install a skill without vetting it first.**\n\n## When to Use\n\n- Before installing any skill from ClawdHub\n- Before running skills from GitHub repos\n- When evaluating skills shared by other agents\n- Anytime you're asked to install unknown code\n\n## Vetting Protocol\n\n### Step 1: Source Check\n\n```\nQuestions to answer:\n- [ ] Where did this skill come from?\n- [ ] Is the author known/reputable?\n- [ ] How many downloads/stars does it have?\n- [ ] When was it last updated?\n- [ ] Are there reviews from other agents?\n```\n\n### Step 2: Code Review (MANDATORY)\n\nRead ALL files in the skill. Check for these **RED FLAGS**:\n\n```\n🚨 REJECT IMMEDIATELY IF YOU SEE:\n─────────────────────────────────────────\n• curl/wget to unknown URLs\n• Sends data to external servers\n• Requests credentials/tokens/API keys\n• Reads ~/.ssh, ~/.aws, ~/.config without clear reason\n• Accesses MEMORY.md, USER.md, SOUL.md, IDENTITY.md\n• Uses base64 decode on anything\n• Uses eval() or exec() with external input\n• Modifies system files outside workspace\n• Installs packages without listing them\n• Network calls to IPs instead of domains\n• Obfuscated code (compressed, encoded, minified)\n• Requests elevated/sudo permissions\n• Accesses browser cookies/sessions\n• Touches credential files\n─────────────────────────────────────────\n```\n\n### Step 3: Permission Scope\n\n```\nEvaluate:\n- [ ] What files does it need to read?\n- [ ] What files does it need to write?\n- [ ] What commands does it run?\n- [ ] Does it need network access? To where?\n- [ ] Is the scope minimal for its stated purpose?\n```\n\n### Step 4: Risk Classification\n\n| Risk Level | Examples | Action |\n|------------|----------|--------|\n| 🟢 LOW | Notes, weather, formatting | Basic review, install OK |\n| 🟡 MEDIUM | File ops, browser, APIs | Full code review required |\n| 🔴 HIGH | Credentials, trading, system | Human approval required |\n| ⛔ EXTREME | Security configs, root access | Do NOT install |\n\n## Output Format\n\nAfter vetting, produce this report:\n\n```\nSKILL VETTING REPORT\n═══════════════════════════════════════\nSkill: [name]\nSource: [ClawdHub / GitHub / other]\nAuthor: [username]\nVersion: [version]\n───────────────────────────────────────\nMETRICS:\n• Downloads/Stars: [count]\n• Last Updated: [date]\n• Files Reviewed: [count]\n───────────────────────────────────────\nRED FLAGS: [None / List them]\n\nPERMISSIONS NEEDED:\n• Files: [list or \"None\"]\n• Network: [list or \"None\"]  \n• Commands: [list or \"None\"]\n───────────────────────────────────────\nRISK LEVEL: [🟢 LOW / 🟡 MEDIUM / 🔴 HIGH / ⛔ EXTREME]\n\nVERDICT: [✅ SAFE TO INSTALL / ⚠️ INSTALL WITH CAUTION / ❌ DO NOT INSTALL]\n\nNOTES: [Any observations]\n═══════════════════════════════════════\n```\n\n## Quick Vet Commands\n\nFor GitHub-hosted skills:\n```bash\n# Check repo stats\ncurl -s \"https://api.github.com/repos/OWNER/REPO\" | jq '{stars: .stargazers_count, forks: .forks_count, updated: .updated_at}'\n\n# List skill files\ncurl -s \"https://api.github.com/repos/OWNER/REPO/contents/skills/SKILL_NAME\" | jq '.[].name'\n\n# Fetch and review SKILL.md\ncurl -s \"https://raw.githubusercontent.com/OWNER/REPO/main/skills/SKILL_NAME/SKILL.md\"\n```\n\n## Trust Hierarchy\n\n1. **Official OpenClaw skills** → Lower scrutiny (still review)\n2. **High-star repos (1000+)** → Moderate scrutiny\n3. **Known authors** → Moderate scrutiny\n4. **New/unknown sources** → Maximum scrutiny\n5. **Skills requesting credentials** → Human approval always\n\n## Remember\n\n- No skill is worth compromising security\n- When in doubt, don't install\n- Ask your human for high-risk decisions\n- Document what you vet for future reference\n\n---\n\n*Paranoia is a feature.* 🔒🦀\n","SKILLs/seedance/SKILL.md":"---\nname: seedance\ndescription: Generate AI videos using Volcengine Seedance model. Supports text-to-video (T2V), image-to-video (I2V), and audio-synced video generation. Use this skill when the user wants to create or generate videos.\nofficial: true\nversion: 1.0.1\n---\n\n# Seedance 视频生成\n\n使用火山引擎 Seedance 模型生成高质量 AI 视频，支持文本生成视频（T2V）、图片生成视频（I2V）、音画同步等多种创作模式。\n\n> ✨ **Node.js 版本**：此脚本使用 Node.js 实现，无需 Python 环境。通过入口脚本自动检测 Node.js 运行时（优先使用系统 node，回退到 LobsterAI 内置运行时），Windows 和 Mac 用户都可以开箱即用。\n\n## 配置\n\n- **Base URL**: `https://ark.cn-beijing.volces.com/api/v3`\n- **API Key**: 从环境变量 `ARK_API_KEY` 读取\n- **认证方式**: `Authorization: Bearer {API_KEY}`\n- **SDK**: 兼容火山方舟 Python SDK\n\n### 如何配置 API Key\n\n**方式一：通过环境变量配置（推荐）**\n\n在终端中设置环境变量：\n\n```bash\n# macOS/Linux\nexport ARK_API_KEY=\"你的API密钥\"\n\n# 或者添加到 ~/.zshrc 或 ~/.bashrc 以永久生效\necho 'export ARK_API_KEY=\"你的API密钥\"' >> ~/.zshrc\nsource ~/.zshrc\n```\n\n```powershell\n# Windows PowerShell\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 或者设置系统环境变量以永久生效\n[System.Environment]::SetEnvironmentVariable('ARK_API_KEY', '你的API密钥', 'User')\n```\n\n**方式二：通过 LobsterAI 启动时注入**\n\nLobsterAI 会自动读取系统环境变量，确保在启动 LobsterAI 前已设置 `ARK_API_KEY`。\n\n**如何获取 API Key：**\n1. 访问火山方舟控制台：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n2. 创建新的 API Key\n3. 复制密钥并设置为环境变量\n\n## 前置检查\n\n**无需安装任何依赖！** 该脚本已兼容 Node.js 内置模块。\n\nLobsterAI 已包含 Node.js 运行时，所有必要的依赖已被自动打包。Windows 和 Mac 用户无需额外配置。\n\n## 工作流程\n\nSeedance 视频生成是一个异步过程：\n\n1. **提交任务** - 调用 API 创建视频生成任务，获得 `task_id`\n2. **轮询状态** - 每隔几秒查询任务状态，直到状态变为 `succeeded`\n3. **下载视频** - 从 `video_url` 字段下载生成的 MP4 文件\n\n## 配额和限制\n\n### 免费额度\n\n所有 Seedance 模型在 **default 模式（在线推理）**下提供：\n- **200万 token** 免费额度\n- flex 模式（离线推理）无免费额度\n\n**注意**：文档中未明确说明 200万 token 能生成多少个视频，消耗取决于视频时长、分辨率和是否使用图片/音频。建议先小批量测试。\n\n### 限流限制\n\n| 模型系列 | RPM（每分钟请求数） | 并发数 | TPD（离线模式每日token） |\n|---------|-------------------|--------|----------------------|\n| Pro 系列 | 600 | 10 | 5000亿 |\n| Lite 系列 | 300 | 5 | 2500亿 |\n\n- **RPM 限流**：账号下同模型每分钟允许创建的任务数量上限\n- **并发数限制**：同一时刻在处理中的任务数量上限\n- **TPD 限流**：flex 模式下一天内对同一模型的总调用 token 上限\n\n### 视频保存时间\n\n⚠️ **重要提醒**：\n- 任务数据（包括视频URL）仅保留 **24 小时**\n- 超时后会被自动清除\n- **务必及时下载保存生成的视频**\n\n## 使用示例\n\n**路径说明**：下面的示例使用 `$SKILLS_ROOT` 环境变量来引用脚本路径。LobsterAI 会自动设置这个变量，指向实际的 SKILLs 目录位置，因此无需手动修改路径。\n\n### 1. 文本生成视频（T2V）\n\n根据文字描述生成视频，适合创意激发和概念验证。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"一只小猫在草地上玩耍，阳光明媚，镜头缓缓推进\" \\\n  --duration 5 \\\n  --output generated_video.mp4\n```\n\n**示例提示词：**\n- \"写实风格，晴朗的蓝天之下，一大片白色的雏菊花田，镜头逐渐拉近，最终定格在一朵雏菊花的特写上，花瓣上有几颗晶莹的露珠\"\n- \"一辆地铁轰隆隆驶过，书页飞扬，镜头开始环绕着女孩360度旋转\"\n- \"海边日落，海浪轻拍沙滩，宁静祥和的氛围\"\n\n### 2. 图片生成视频（I2V）- 首帧引导\n\n基于首帧图片生成动态视频，**支持本地图片和网络URL**。\n\n```bash\n# 使用本地图片\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"女孩睁开眼，温柔地看向镜头，头发被风吹动\" \\\n  --image \"/Users/yourname/Pictures/girl.jpg\" \\\n  --duration 5 \\\n  --output i2v_video.mp4\n\n# 使用网络图片\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"女孩睁开眼，温柔地看向镜头，头发被风吹动\" \\\n  --image \"https://example.com/first_frame.jpg\" \\\n  --duration 5 \\\n  --output i2v_video.mp4\n```\n\n**支持的图片来源：**\n- ✅ 本地文件：`/path/to/image.jpg`\n- ✅ 网络URL：`https://example.com/image.jpg`\n- ✅ file://协议：`file:///path/to/image.jpg`\n\n**支持的图片格式：**\n- jpg, jpeg, png, gif, webp, bmp, tiff, heic\n\n### 3. 图片生成视频（I2V）- 首尾帧引导\n\n提供首帧和尾帧，生成过渡动画。**支持本地图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"360度环绕运镜，流畅过渡\" \\\n  --image \"/Users/yourname/Pictures/first_frame.jpg\" \\\n  --image \"/Users/yourname/Pictures/last_frame.jpg\" \\\n  --duration 5 \\\n  --output transition_video.mp4\n```\n\n### 4. 多参考图生成视频\n\n融合多张参考图的特征生成视频。**支持混合使用本地图片和网络图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"[图1]戴着眼镜穿着蓝色T恤的男生和[图2]的柯基小狗，坐在[图3]的草坪上，视频卡通风格\" \\\n  --image \"/Users/yourname/Pictures/person.jpg\" \\\n  --image \"https://example.com/dog.jpg\" \\\n  --image \"/Users/yourname/Pictures/grass.jpg\" \\\n  --model \"doubao-seedance-1-0-lite-i2v-250428\" \\\n  --duration 5 \\\n  --output multi_ref_video.mp4\n```\n\n### 5. 音画同步视频生成（仅 1.5 pro）\n\n生成包含音频的视频（环境音、动作音、背景音乐等）。**支持本地图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"镜头围绕人物推镜头拉近，特写人物面部，她正在用京剧唱腔唱'月移花影，疑是玉人来'，唱词充满情感\" \\\n  --image \"/Users/yourname/Pictures/actress.jpg\" \\\n  --audio \\\n  --duration 5 \\\n  --model \"doubao-seedance-1-5-pro-251215\" \\\n  --output audio_video.mp4\n```\n\n## 参数说明\n\n### 必需参数\n\n| 参数 | 说明 | 示例 |\n|-----|------|------|\n| `--prompt` | 视频描述提示词（必需） | \"小猫在玩耍\" |\n\n### 可选参数\n\n| 参数 | 说明 | 默认值 | 可选值 |\n|-----|------|-------|--------|\n| `--image` | 参考图片路径或URL（可多次使用） | 无 | 本地文件路径或URL |\n| `--model` | 模型ID | `doubao-seedance-1-5-pro-251215` | 见模型列表 |\n| `--duration` | 视频时长（秒） | 5 | 2-12（不同模型范围不同） |\n| `--ratio` | 宽高比 | `adaptive` | `adaptive`, `16:9`, `9:16`, `1:1` |\n| `--audio` | 生成音频（仅1.5 pro支持） | 否 | 标志参数 |\n| `--no-watermark` | 不添加水印 | 否 | 标志参数 |\n| `--output` | 输出文件路径 | `generated_video.mp4` | 文件路径 |\n| `--poll-interval` | 状态查询间隔（秒） | 5 | 1-10 |\n| `--timeout` | 最大等待时间（秒） | 300 | 60-600 |\n\n## 模型选择\n\n选择合适的模型以平衡质量、速度和成本：\n\n### Seedance 1.5 pro（推荐）\n\n- **模型ID**: `doubao-seedance-1-5-pro-251215`\n- **特点**: 音画同生，最高质量\n- **支持**: 文生视频、图生视频、首尾帧、有声视频\n- **输出**: 480p-1080p，24fps，4-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 pro\n\n- **模型ID**: `doubao-seedance-1-0-pro-250528`\n- **特点**: 高质量标准版本\n- **支持**: 文生视频、图生视频、首尾帧\n- **输出**: 480p-1080p，24fps，2-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 pro fast\n\n- **模型ID**: `doubao-seedance-1-0-pro-fast-251015`\n- **特点**: 快速生成，成本更低\n- **支持**: 文生视频、图生视频\n- **输出**: 480p-1080p，24fps，2-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 lite（轻量版）\n\n- **文生视频**: `doubao-seedance-1-0-lite-t2v-250428`\n- **图生视频**: `doubao-seedance-1-0-lite-i2v-250428`\n- **特点**: 更快速度，支持多参考图\n- **限流**: RPM 300，并发5\n\n### Seedance 2.0（即将支持）\n\n- **模型ID**: `doubao-seedance-2-0-260128`\n- **特点**: 下一代视频生成模型，质量和性能全面提升\n- **可用性**: ⏰ 预计 **2026年2月24日18点** 开放 API 调用\n- **当前状态**: 仅在 [控制台体验中心](https://console.volcengine.com/ark/region:ark+cn-beijing/experience/vision?modelId=doubao-seedance-2-0-260128&tab=GenVideo) 可用\n\n**使用方式（2月24日后）：**\n\n```bash\n# 命令行方式\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"你的提示词\" \\\n  --model \"doubao-seedance-2-0-260128\" \\\n  --duration 5\n```\n\n或在 LobsterAI 对话中说：\"用 Seedance 2.0 生成视频...\"\n\n**推荐使用场景：**\n- 追求最高质量 + 音画同步 → 1.5 pro\n- 标准高质量视频 → 1.0 pro\n- 快速生成预览 → 1.0 pro fast\n- 多参考图融合 → 1.0 lite\n- 下一代最新模型（2月24日后）→ 2.0\n\n## 高级选项\n\n### 自定义宽高比\n\n根据使用场景选择合适的宽高比：\n\n```bash\n# 横屏视频（适合 YouTube、B站）\n--ratio \"16:9\"\n\n# 竖屏视频（适合抖音、快手）\n--ratio \"9:16\"\n\n# 正方形视频（适合 Instagram）\n--ratio \"1:1\"\n\n# 自适应（根据内容自动选择）\n--ratio \"adaptive\"\n```\n\n### 自定义视频时长\n\n不同模型支持的时长范围不同：\n\n```bash\n# 短视频（快速生成）\n--duration 2\n\n# 标准时长\n--duration 5\n\n# 长视频（内容更丰富）\n--duration 10\n```\n\n**注意：**\n- Seedance 1.5 pro 支持 4-12 秒\n- Seedance 1.0 系列支持 2-12 秒\n- 时长越长，生成时间越久\n\n### 去除水印\n\n生成无水印视频（用于商业用途）：\n\n```bash\n--no-watermark\n```\n\n### 轮询和超时控制\n\n调整轮询策略以适应不同场景：\n\n```bash\n# 快速查询（适合短视频）\n--poll-interval 3 --timeout 180\n\n# 标准配置\n--poll-interval 5 --timeout 300\n\n# 耐心等待（适合长视频或高峰期）\n--poll-interval 10 --timeout 600\n```\n\n## 状态说明\n\n生成过程中可能出现的任务状态：\n\n| 状态 | 说明 | 操作 |\n|------|------|------|\n| `queued` | 任务排队中 | 继续等待 |\n| `running` | 正在生成视频 | 继续等待 |\n| `succeeded` | 生成成功 | 下载视频 |\n| `failed` | 生成失败 | 查看错误信息 |\n\n## 错误处理\n\n### 常见错误及解决方案\n\n**错误：未设置环境变量 ARK_API_KEY**\n- 原因：未配置 API Key\n- 解决：按照\"如何配置 API Key\"部分的说明进行配置\n\n**错误：任务创建失败 (HTTP 401)**\n- 原因：API Key 无效或已过期\n- 解决：检查 API Key 是否正确，或在控制台重新生成\n\n**错误：任务创建失败 (HTTP 400)**\n- 原因：参数错误（如 duration 超出范围）\n- 解决：检查参数是否符合模型要求\n\n**错误：任务超时**\n- 原因：生成时间过长或 API 繁忙\n- 解决：增加 `--timeout` 值，或稍后重试\n\n**错误：任务失败**\n- 原因：内容违规、提示词不清晰、图片格式错误等\n- 解决：检查提示词内容，确保图片URL可访问\n\n**错误：限流 (HTTP 429)**\n- 原因：超过 RPM 或并发限制\n- 解决：等待1分钟后重试，或升级配额\n\n## 输出格式\n\n生成的视频具有以下特征：\n\n- **格式**: MP4\n- **编码**: H.264\n- **分辨率**: 480p / 720p / 1080p（根据模型自动选择）\n- **帧率**: 24 fps\n- **音频**: AAC（如果启用 `--audio`）\n- **文件大小**: 约 2-5 MB/秒（1080p）\n\n## 提示词最佳实践\n\n### 优秀提示词的特点\n\n1. **清晰的场景描述** - 说明环境、时间、氛围\n2. **具体的动作细节** - 描述物体或人物的具体动作\n3. **镜头运动** - 说明推拉摇移、特写等镜头语言\n4. **风格指定** - 写实、卡通、动漫等风格说明\n\n### 提示词模板\n\n```\n[风格]，[场景描述]，[主体动作]，[镜头运动]，[氛围/情绪]\n```\n\n**示例：**\n```\n写实风格，海边日落，一只海鸥在空中盘旋，镜头从远处缓缓推进到海鸥特写，宁静祥和的氛围\n```\n\n### 提示词注意事项\n\n- ✅ 具体描述：\"小猫追逐蝴蝶\" 而非 \"小猫玩耍\"\n- ✅ 镜头语言：\"镜头360度环绕\" 而非 \"旋转\"\n- ✅ 情绪氛围：\"温暖明亮的阳光\" 而非 \"好天气\"\n- ❌ 避免模糊：过于抽象的描述会导致随机性增加\n- ❌ 避免过长：保持在 200 字以内效果最佳\n- ❌ 避免违规：不要包含暴力、色情等违规内容\n\n## 常见使用场景\n\n### 短视频创作\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"产品展示：智能手表从不同角度旋转展示\" \\\n  --ratio \"9:16\" \\\n  --duration 5\n```\n\n### 动画短片\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"卡通风格，小兔子在森林里蹦蹦跳跳\" \\\n  --ratio \"16:9\" \\\n  --duration 8 \\\n  --model \"doubao-seedance-1-0-pro-250528\"\n```\n\n### 社交媒体内容\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"美食特写：热气腾腾的拉面，筷子夹起面条\" \\\n  --ratio \"1:1\" \\\n  --duration 3\n```\n\n### 教学演示\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"科普动画：地球自转，太阳光照射地球表面\" \\\n  --ratio \"16:9\" \\\n  --duration 10\n```\n\n## 参考资料\n\n- API 参考：https://www.volcengine.com/docs/82379/1520758\n- 控制台：https://console.volcengine.com/ark\n- API Key 管理：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n\n## 技术支持\n\n如遇到问题，可以：\n1. 查看脚本输出的错误信息\n2. 检查 API Key 配置是否正确\n3. 访问火山方舟控制台查看任务详情\n4. 参考官网文档了解更多细节\n","SKILLs/seedream/SKILL.md":"---\nname: seedream\ndescription: Generate AI images using Volcengine Seedream model. Supports text-to-image (T2I), image editing (I2I), multi-image fusion, and web-search-based generation. Use this skill when the user wants to create, generate, or edit images.\nofficial: true\nversion: 1.0.1\n---\n\n# Seedream 图片生成\n\n使用火山引擎 Seedream 模型生成高质量 AI 图片，支持文本生成图片（T2I）、图片编辑（I2I）、多图融合、组图生成、联网搜索等多种创作模式。\n\n> ✨ **Node.js 版本**：此脚本使用 Node.js 实现，无需 Python 环境。通过入口脚本自动检测 Node.js 运行时（优先使用系统 node，回退到 LobsterAI 内置运行时），Windows 和 Mac 用户都可以开箱即用。\n\n## 配置\n\n- **Base URL**: `https://ark.cn-beijing.volces.com/api/v3`\n- **API Key**: 从环境变量 `ARK_API_KEY` 读取\n- **认证方式**: `Authorization: Bearer {API_KEY}`\n- **SDK**: 兼容火山方舟 Python SDK\n\n### 快速开始\n\n**第一步：设置 API Key**\n\n```bash\n# macOS / Linux - 当前终端临时生效（立即使用）\nexport ARK_API_KEY=\"你的API密钥\"\n\n# Windows PowerShell - 当前会话临时生效\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 验证设置成功（macOS/Linux）\necho $ARK_API_KEY\n\n# 验证设置成功（Windows）\necho $env:ARK_API_KEY\n```\n\n**第二步：生成你的第一张图片**\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"一只可爱的橘色小猫\"\n```\n\n### 如何配置 API Key\n\n**方式一：通过环境变量配置（推荐）**\n\n在终端中设置环境变量：\n\n```bash\n# macOS/Linux\nexport ARK_API_KEY=\"你的API密钥\"\n\n# 或者添加到 ~/.zshrc 或 ~/.bashrc 以永久生效\necho 'export ARK_API_KEY=\"你的API密钥\"' >> ~/.zshrc\nsource ~/.zshrc\n```\n\n```powershell\n# Windows PowerShell\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 或者设置系统环境变量以永久生效\n[System.Environment]::SetEnvironmentVariable('ARK_API_KEY', '你的API密钥', 'User')\n```\n\n**方式二：通过 LobsterAI 启动时注入**\n\nLobsterAI 会自动读取系统环境变量，确保在启动 LobsterAI 前已设置 `ARK_API_KEY`。\n\n**如何获取 API Key：**\n1. 访问火山方舟控制台：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n2. 创建新的 API Key\n3. 复制密钥并设置为环境变量\n\n## 前置检查\n\n**无需安装任何依赖！** 该脚本已兼容 Node.js 内置模块。\n\nLobsterAI 已包含 Node.js 运行时，所有必要的依赖已被自动打包。Windows 和 Mac 用户无需额外配置。\n\n## 工作流程\n\nSeedream 图片生成采用**同步模式**，流程简单高效：\n\n1. **提交请求** - 调用 API 提交图片生成请求\n2. **等待生成** - API 直接处理并生成图片（通常 30-60 秒）\n3. **下载图片** - 从返回的 URL 下载生成的图片文件\n\n相比异步模式，同步模式更简单直接，无需轮询任务状态。\n\n## 配额和限制\n\n### 免费额度\n\n所有 Seedream 模型提供免费额度，具体请参见火山方舟控制台。\n\n### 限流限制\n\n- **IPM（每分钟图片数）**: 500 张/分钟（Seedream 4.5, 4.0）\n- 不同模型的限流不同，请参见官方文档\n\n### 图片保存时间\n\n⚠️ **重要提醒**：\n- 任务数据（包括图片URL）仅保留 **24 小时**\n- 超时后会被自动清除\n- **务必及时下载保存生成的图片**\n\n## 使用示例\n\n**路径说明**：下面的示例使用 `$SKILLS_ROOT` 环境变量来引用脚本路径。LobsterAI 会自动设置这个变量，指向实际的 SKILLs 目录位置，因此无需手动修改路径。\n\n### 1. 文本生成图片（T2I）\n\n根据文字描述生成图片，适合创意激发和概念设计。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"充满活力的特写编辑肖像，模特眼神犀利，头戴雕塑感帽子，色彩拼接丰富，景深较浅，Vogue杂志封面美学风格\" \\\n  --output portrait.png\n```\n\n**示例提示词：**\n- \"写实风格，晴朗的蓝天之下，一大片白色的雏菊花田，镜头逐渐拉近，最终定格在一朵雏菊花的特写上\"\n- \"卡通风格，一只橘色小猫坐在窗台上，阳光洒在身上，温暖治愈的氛围\"\n- \"赛博朋克风格，未来城市夜景，霓虹灯闪烁，高楼林立\"\n\n### 2. 图片编辑（I2I）- 单图输入\n\n基于已有图片，结合文字指令进行图像编辑。**支持本地图片和网络URL**。\n\n```bash\n# 使用本地图片\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"保持模特姿势不变，将服装材质改为透明玻璃质感\" \\\n  --image \"/Users/yourname/Pictures/model.jpg\" \\\n  --output edited_model.png\n\n# 使用网络图片\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"将背景改为海边日落场景\" \\\n  --image \"https://example.com/photo.jpg\" \\\n  --output beach_sunset.png\n```\n\n**支持的图片来源：**\n- ✅ 本地文件：`/path/to/image.jpg`\n- ✅ 网络URL：`https://example.com/image.jpg`\n- ✅ file://协议：`file:///path/to/image.jpg`\n\n**支持的图片格式：**\n- jpg, jpeg, png, gif, webp, bmp, tiff, heic\n\n### 3. 多图融合（多图输入单图输出）\n\n融合多张参考图的特征生成新图像。**支持混合使用本地图片和网络图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"将图1的服装换为图2的服装\" \\\n  --image \"/Users/yourname/Pictures/person.jpg\" \\\n  --image \"https://example.com/clothes.jpg\" \\\n  --output fusion_result.png\n```\n\n**常见使用场景：**\n- 服装试穿：人物图 + 服装图 → 穿搭效果图\n- 风格迁移：照片 + 风格参考图 → 风格化作品\n- 场景融合：人物 + 背景 → 合成场景\n\n### 4. 组图生成（多图输出）\n\n生成一组内容关联的图片，适合漫画分镜、品牌视觉等。\n\n#### 文生组图\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"生成一组共4张连贯插画，核心为同一庭院一角的四季变迁，以统一风格展现四季独特色彩、元素与氛围\" \\\n  --sequential \\\n  --max-images 4 \\\n  --output seasons.png\n```\n\n输出文件会自动编号：`seasons_1.png`, `seasons_2.png`, `seasons_3.png`, `seasons_4.png`\n\n#### 单图生组图\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"参考这个LOGO，做一套户外运动品牌视觉设计，品牌名称为'GREEN'，包括包装袋、帽子、卡片、挂绳等\" \\\n  --image \"/Users/yourname/Pictures/logo.png\" \\\n  --sequential \\\n  --max-images 4 \\\n  --output brand_design.png\n```\n\n### 5. 联网搜索增强生成（Seedream 5.0 lite）\n\n启用实时网络搜索，融合最新网络信息。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"搜索下近期热门的白鸭子单手拿着风车形象，以极具冲击力的视角，设计成巨型装置\" \\\n  --search \\\n  --output search_result.png\n```\n\n**注意**：\n- 联网搜索功能仅限 Seedream 5.0 lite 模型\n- 使用 `--search` 参数会自动切换到 5.0 lite 模型\n- 适合需要融合实时信息的创作场景\n\n## 参数说明\n\n### 必需参数\n\n| 参数 | 说明 | 示例 |\n|-----|------|------|\n| `--prompt` | 图片描述提示词（必需） | \"一只可爱的小猫\" |\n\n### 可选参数\n\n| 参数 | 说明 | 默认值 | 可选值 |\n|-----|------|-------|--------|\n| `--image` | 参考图片路径或URL（可多次使用） | 无 | 本地文件路径或URL |\n| `--model` | 模型ID | `doubao-seedream-4-5-251128` | 见模型列表 |\n| `--size` | 图片尺寸 | `2K` | `1K`, `2K`, `4K` |\n| `--no-watermark` | 不添加水印 | 否 | 标志参数 |\n| `--sequential` | 生成组图 | 否 | 标志参数 |\n| `--max-images` | 组图数量 | 4 | 1-8 |\n| `--search` | 启用联网搜索 | 否 | 标志参数 |\n| `--output` | 输出文件路径 | `generated_image.png` | 文件路径 |\n| `--poll-interval` | 状态查询间隔（秒） | 5 | 1-10 |\n| `--timeout` | 最大等待时间（秒） | 300 | 60-600 |\n\n## 模型选择\n\n选择合适的模型以平衡质量、速度和成本：\n\n### Seedream 4.5（推荐）\n\n- **模型ID**: `doubao-seedream-4-5-251128`\n- **特点**: 最新版本，综合质量最佳\n- **支持**: 文生图、图生图、多图融合、组图生成\n- **输出**: 1K-4K分辨率可选\n- **限流**: IPM 500\n\n### Seedream 4.0\n\n- **模型ID**: `doubao-seedream-4-0-250828`\n- **特点**: 成熟稳定版本\n- **支持**: 文生图、图生图、多图融合、组图生成\n- **输出**: 1K-4K分辨率可选\n- **限流**: IPM 500\n\n### Seedream 5.0 lite（联网搜索专用）\n\n- **模型ID**: `doubao-seedream-5-0-260128`\n- **特点**: 支持联网搜索，融合实时网络信息\n- **使用**: 通过 `--search` 参数自动启用\n- **注意**: 2026年2月24日18点后正式开放 API\n\n**推荐使用场景：**\n- 追求最高质量 → 4.5\n- 稳定生产环境 → 4.0\n- 需要实时信息 → 5.0 lite（使用 `--search`）\n\n## 高级选项\n\n### 自定义图片尺寸\n\n根据使用场景选择合适的尺寸：\n\n```bash\n# 小尺寸（快速预览）\n--size \"1K\"\n\n# 标准尺寸（推荐）\n--size \"2K\"\n\n# 高清晰度\n--size \"4K\"\n```\n\n**注意：**\n- 尺寸越大，生成时间越长\n- 4K 图片可能需要 40-60 秒\n\n### 去除水印\n\n生成无水印图片（用于商业用途）：\n\n```bash\n--no-watermark\n```\n\n### 轮询和超时控制\n\n调整轮询策略以适应不同场景：\n\n```bash\n# 快速查询（适合小图）\n--poll-interval 3 --timeout 180\n\n# 标准配置\n--poll-interval 5 --timeout 300\n\n# 耐心等待（适合4K或组图）\n--poll-interval 10 --timeout 600\n```\n\n## 状态说明\n\n生成过程中可能出现的任务状态：\n\n| 状态 | 说明 | 操作 |\n|------|------|------|\n| `queued` | 任务排队中 | 继续等待 |\n| `running` | 正在生成图片 | 继续等待 |\n| `succeeded` | 生成成功 | 下载图片 |\n| `failed` | 生成失败 | 查看错误信息 |\n\n## 错误处理\n\n### 常见错误及解决方案\n\n**错误：未设置环境变量 ARK_API_KEY**\n- 原因：未配置 API Key\n- 解决：按照\"如何配置 API Key\"部分的说明进行配置\n\n**错误：任务创建失败 (HTTP 401)**\n- 原因：API Key 无效或已过期\n- 解决：检查 API Key 是否正确，或在控制台重新生成\n\n**错误：任务创建失败 (HTTP 400)**\n- 原因：参数错误（如 size 不支持、prompt 为空等）\n- 解决：检查参数是否符合要求\n\n**错误：任务超时**\n- 原因：生成时间过长或 API 繁忙\n- 解决：增加 `--timeout` 值，或稍后重试\n\n**错误：任务失败**\n- 原因：内容违规、提示词不清晰、图片格式错误等\n- 解决：检查提示词内容，确保图片URL可访问\n\n**错误：限流 (HTTP 429)**\n- 原因：超过 IPM 限制\n- 解决：等待1分钟后重试，或升级配额\n\n**错误：图片文件不存在**\n- 原因：本地图片路径错误\n- 解决：检查文件路径是否正确，使用绝对路径\n\n## 输出格式\n\n生成的图片具有以下特征：\n\n- **格式**: PNG, JPEG（根据output参数自动识别）\n- **分辨率**: 1K / 2K / 4K（根据 size 参数）\n- **文件大小**: 约 0.5-10 MB（取决于尺寸和复杂度）\n- **命名规则**:\n  - 单图：指定的文件名\n  - 组图：`文件名_1.png`, `文件名_2.png`, ...\n\n## 提示词最佳实践\n\n### 优秀提示词的特点\n\n1. **清晰的主体描述** - 说明画面的主要内容\n2. **具体的风格指定** - 写实、卡通、赛博朋克等\n3. **细节补充** - 色彩、光线、氛围等\n4. **构图说明** - 特写、全景、俯视等视角\n\n### 提示词模板\n\n```\n[风格]，[主体描述]，[细节补充]，[构图/氛围]\n```\n\n**示例：**\n```\n写实风格，一只橘色小猫坐在木制窗台上，阳光从左侧洒进来，温暖治愈的氛围，特写构图\n```\n\n### 提示词注意事项\n\n- ✅ 具体描述：\"小猫在追逐蝴蝶\" 而非 \"小猫玩耍\"\n- ✅ 风格说明：\"赛博朋克风格\" 而非 \"好看的\"\n- ✅ 细节丰富：\"橘色长毛小猫，蓝色眼睛\" 而非 \"猫\"\n- ❌ 避免模糊：过于抽象的描述会导致随机性增加\n- ❌ 避免过长：保持在 200 字以内效果最佳\n- ❌ 避免违规：不要包含暴力、色情等违规内容\n\n## 常见使用场景\n\n### 产品设计\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"现代简约风格，智能手表产品展示，白色背景，工作室灯光\" \\\n  --size \"4K\"\n```\n\n### 艺术创作\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"超现实主义，漂浮的岛屿，瀑布从天而降，梦幻色彩\" \\\n  --size \"2K\"\n```\n\n### 社交媒体内容\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"美食特写，热气腾腾的拉面，筷子夹起面条，暖色调\" \\\n  --size \"2K\"\n```\n\n### 品牌视觉设计\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"参考logo，生成一套完整的品牌视觉系统，包括名片、海报、包装设计\" \\\n  --image brand_logo.png \\\n  --sequential \\\n  --max-images 4\n```\n\n## 参考资料\n\n- API 参考：https://www.volcengine.com/docs/82379/1541523\n- 控制台：https://console.volcengine.com/ark\n- API Key 管理：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n- 模型列表：https://www.volcengine.com/docs/82379/1330310\n\n## 技术支持\n\n如遇到问题，可以：\n1. 查看脚本输出的错误信息\n2. 检查 API Key 配置是否正确\n3. 访问火山方舟控制台查看任务详情\n4. 参考官网文档了解更多细节\n","SKILLs/pptx/SKILL.md":"---\nname: pptx\ndescription: \"Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks\"\nlicense: Proprietary. LICENSE.txt has complete terms\nofficial: true\n---\n\n# PPTX creation, editing, and analysis\n\n## Overview\n\nA user may ask you to create, edit, or analyze the contents of a .pptx file. A .pptx file is essentially a ZIP archive containing XML files and other resources that you can read or edit. You have different tools and workflows available for different tasks.\n\n## Reading and analyzing content\n\n### Text extraction\nIf you just need to read the text contents of a presentation, you should convert the document to markdown:\n\n```bash\n# Convert document to markdown\npython -m markitdown path-to-file.pptx\n```\n\n### Raw XML access\nYou need raw XML access for: comments, speaker notes, slide layouts, animations, design elements, and complex formatting. For any of these features, you'll need to unpack a presentation and read its raw XML contents.\n\n#### Unpacking a file\n`python ooxml/scripts/unpack.py <office_file> <output_dir>`\n\n**Note**: Resolve script paths from this skill directory. Prefer `$SKILLS_ROOT/pptx/ooxml/scripts/unpack.py` when `$SKILLS_ROOT` is available; otherwise resolve `ooxml/scripts/unpack.py` relative to this `SKILL.md` file's directory. Do not assume a workspace-relative `skills/pptx/...` path.\n\n#### Key file structures\n* `ppt/presentation.xml` - Main presentation metadata and slide references\n* `ppt/slides/slide{N}.xml` - Individual slide contents (slide1.xml, slide2.xml, etc.)\n* `ppt/notesSlides/notesSlide{N}.xml` - Speaker notes for each slide\n* `ppt/comments/modernComment_*.xml` - Comments for specific slides\n* `ppt/slideLayouts/` - Layout templates for slides\n* `ppt/slideMasters/` - Master slide templates\n* `ppt/theme/` - Theme and styling information\n* `ppt/media/` - Images and other media files\n\n#### Typography and color extraction\n**When given an example design to emulate**: Always analyze the presentation's typography and colors first using the methods below:\n1. **Read theme file**: Check `ppt/theme/theme1.xml` for colors (`<a:clrScheme>`) and fonts (`<a:fontScheme>`)\n2. **Sample slide content**: Examine `ppt/slides/slide1.xml` for actual font usage (`<a:rPr>`) and colors\n3. **Search for patterns**: Use grep to find color (`<a:solidFill>`, `<a:srgbClr>`) and font references across all XML files\n\n## Creating a new PowerPoint presentation **without a template**\n\nWhen creating a new PowerPoint presentation from scratch, use the **html2pptx** workflow to convert HTML slides to PowerPoint with accurate positioning.\n\n### Design Principles\n\n**CRITICAL**: Before creating any presentation, analyze the content and choose appropriate design elements:\n1. **Consider the subject matter**: What is this presentation about? What tone, industry, or mood does it suggest?\n2. **Check for branding**: If the user mentions a company/organization, consider their brand colors and identity\n3. **Match palette to content**: Select colors that reflect the subject\n4. **State your approach**: Explain your design choices before writing code\n\n**Requirements**:\n- ✅ State your content-informed design approach BEFORE writing code\n- ✅ Use web-safe fonts only: Arial, Helvetica, Times New Roman, Georgia, Courier New, Verdana, Tahoma, Trebuchet MS, Impact\n- ✅ Create clear visual hierarchy through size, weight, and color\n- ✅ Ensure readability: strong contrast, appropriately sized text, clean alignment\n- ✅ Be consistent: repeat patterns, spacing, and visual language across slides\n\n#### Color Palette Selection\n\n**Choosing colors creatively**:\n- **Think beyond defaults**: What colors genuinely match this specific topic? Avoid autopilot choices.\n- **Consider multiple angles**: Topic, industry, mood, energy level, target audience, brand identity (if mentioned)\n- **Be adventurous**: Try unexpected combinations - a healthcare presentation doesn't have to be green, finance doesn't have to be navy\n- **Build your palette**: Pick 3-5 colors that work together (dominant colors + supporting tones + accent)\n- **Ensure contrast**: Text must be clearly readable on backgrounds\n\n**Example color palettes** (use these to spark creativity - choose one, adapt it, or create your own):\n\n1. **Classic Blue**: Deep navy (#1C2833), slate gray (#2E4053), silver (#AAB7B8), off-white (#F4F6F6)\n2. **Teal & Coral**: Teal (#5EA8A7), deep teal (#277884), coral (#FE4447), white (#FFFFFF)\n3. **Bold Red**: Red (#C0392B), bright red (#E74C3C), orange (#F39C12), yellow (#F1C40F), green (#2ECC71)\n4. **Warm Blush**: Mauve (#A49393), blush (#EED6D3), rose (#E8B4B8), cream (#FAF7F2)\n5. **Burgundy Luxury**: Burgundy (#5D1D2E), crimson (#951233), rust (#C15937), gold (#997929)\n6. **Deep Purple & Emerald**: Purple (#B165FB), dark blue (#181B24), emerald (#40695B), white (#FFFFFF)\n7. **Cream & Forest Green**: Cream (#FFE1C7), forest green (#40695B), white (#FCFCFC)\n8. **Pink & Purple**: Pink (#F8275B), coral (#FF574A), rose (#FF737D), purple (#3D2F68)\n9. **Lime & Plum**: Lime (#C5DE82), plum (#7C3A5F), coral (#FD8C6E), blue-gray (#98ACB5)\n10. **Black & Gold**: Gold (#BF9A4A), black (#000000), cream (#F4F6F6)\n11. **Sage & Terracotta**: Sage (#87A96B), terracotta (#E07A5F), cream (#F4F1DE), charcoal (#2C2C2C)\n12. **Charcoal & Red**: Charcoal (#292929), red (#E33737), light gray (#CCCBCB)\n13. **Vibrant Orange**: Orange (#F96D00), light gray (#F2F2F2), charcoal (#222831)\n14. **Forest Green**: Black (#191A19), green (#4E9F3D), dark green (#1E5128), white (#FFFFFF)\n15. **Retro Rainbow**: Purple (#722880), pink (#D72D51), orange (#EB5C18), amber (#F08800), gold (#DEB600)\n16. **Vintage Earthy**: Mustard (#E3B448), sage (#CBD18F), forest green (#3A6B35), cream (#F4F1DE)\n17. **Coastal Rose**: Old rose (#AD7670), beaver (#B49886), eggshell (#F3ECDC), ash gray (#BFD5BE)\n18. **Orange & Turquoise**: Light orange (#FC993E), grayish turquoise (#667C6F), white (#FCFCFC)\n\n#### Visual Details Options\n\n**Geometric Patterns**:\n- Diagonal section dividers instead of horizontal\n- Asymmetric column widths (30/70, 40/60, 25/75)\n- Rotated text headers at 90° or 270°\n- Circular/hexagonal frames for images\n- Triangular accent shapes in corners\n- Overlapping shapes for depth\n\n**Border & Frame Treatments**:\n- Thick single-color borders (10-20pt) on one side only\n- Double-line borders with contrasting colors\n- Corner brackets instead of full frames\n- L-shaped borders (top+left or bottom+right)\n- Underline accents beneath headers (3-5pt thick)\n\n**Typography Treatments**:\n- Extreme size contrast (72pt headlines vs 11pt body)\n- All-caps headers with wide letter spacing\n- Numbered sections in oversized display type\n- Monospace (Courier New) for data/stats/technical content\n- Condensed fonts (Arial Narrow) for dense information\n- Outlined text for emphasis\n\n**Chart & Data Styling**:\n- Monochrome charts with single accent color for key data\n- Horizontal bar charts instead of vertical\n- Dot plots instead of bar charts\n- Minimal gridlines or none at all\n- Data labels directly on elements (no legends)\n- Oversized numbers for key metrics\n\n**Layout Innovations**:\n- Full-bleed images with text overlays\n- Sidebar column (20-30% width) for navigation/context\n- Modular grid systems (3×3, 4×4 blocks)\n- Z-pattern or F-pattern content flow\n- Floating text boxes over colored shapes\n- Magazine-style multi-column layouts\n\n**Background Treatments**:\n- Solid color blocks occupying 40-60% of slide\n- Gradient fills (vertical or diagonal only)\n- Split backgrounds (two colors, diagonal or vertical)\n- Edge-to-edge color bands\n- Negative space as a design element\n\n### Layout Tips\n**When creating slides with charts or tables:**\n- **Two-column layout (PREFERRED)**: Use a header spanning the full width, then two columns below - text/bullets in one column and the featured content in the other. This provides better balance and makes charts/tables more readable. Use flexbox with unequal column widths (e.g., 40%/60% split) to optimize space for each content type.\n- **Full-slide layout**: Let the featured content (chart/table) take up the entire slide for maximum impact and readability\n- **NEVER vertically stack**: Do not place charts/tables below text in a single column - this causes poor readability and layout issues\n\n### Workflow\n1. **MANDATORY - READ ENTIRE FILE**: Read `html2pptx.md` from the same directory as this `SKILL.md` (installed default: `$SKILLS_ROOT/pptx/html2pptx.md`) completely from start to finish. **NEVER set any range limits when reading this file.** Read the full file content for detailed syntax, critical formatting rules, and best practices before proceeding with presentation creation.\n2. Create an HTML file for each slide with proper dimensions (e.g., 720pt × 405pt for 16:9)\n   - Use `<p>`, `<h1>`-`<h6>`, `<ul>`, `<ol>` for all text content\n   - Use `class=\"placeholder\"` for areas where charts/tables will be added (render with gray background for visibility)\n   - **CRITICAL**: Rasterize gradients and icons as PNG images FIRST using Sharp, then reference in HTML\n   - **LAYOUT**: For slides with charts/tables/images, use either full-slide layout or two-column layout for better readability\n3. Create and run a JavaScript file using the [`html2pptx.js`](scripts/html2pptx.js) library to convert HTML slides to PowerPoint and save the presentation\n   - Use the `html2pptx()` function to process each HTML file\n   - Add charts and tables to placeholder areas using PptxGenJS API\n   - Save the presentation using `pptx.writeFile()`\n4. **Visual validation**: Generate thumbnails and inspect for layout issues\n   - Create thumbnail grid: `python scripts/thumbnail.py output.pptx workspace/thumbnails --cols 4`\n   - Read and carefully examine the thumbnail image for:\n     - **Text cutoff**: Text being cut off by header bars, shapes, or slide edges\n     - **Text overlap**: Text overlapping with other text or shapes\n     - **Positioning issues**: Content too close to slide boundaries or other elements\n     - **Contrast issues**: Insufficient contrast between text and backgrounds\n   - If issues found, adjust HTML margins/spacing/colors and regenerate the presentation\n   - Repeat until all slides are visually correct\n\n## Live editing in LobsterAI\n\nWhen the `ppt_read` and `ppt_edit` tools exist, change existing presentations through them instead of unpacking and repacking the file. The presentation opens in LobsterAI's right-side PowerPoint editor, edits appear there immediately, the theme, layouts, animations and everything the tools do not touch are preserved, and the file saves automatically.\n\n1. Call `ppt_read` with the absolute `path` (and `slides` such as `\"2-4\"` for long decks). It returns `revision`, the layout names, and for each slide its number, layout, speaker notes and shapes: `id`, `name`, `kind`, placeholder role, position and size in points, `text` (one line per paragraph, leading tabs give the bullet level) and table cells. It also returns the user's current `selection` (\"改这里\" means that slide and shape).\n2. Call `ppt_edit` with the same `path`, `expectedRevision` from the read, and a list of `edits`; slides are numbered from 1 and shapes are addressed by their `id`:\n   - `replace_text` `{slide?, shape?, find, replace, occurrence?}` for wording changes; it keeps the formatting around the phrase.\n   - `set_text` `{slide, shape, text}` rewrites a shape's text and keeps its formatting; `set_table_cell` `{slide, shape, row, column, text}`.\n   - `format_text` (bold, italic, underline, strike, color, size in pt, font) on a `find` phrase, a `paragraph` or the whole shape; `format_paragraph` (alignment, bullet `level`).\n   - `set_bounds` `{slide, shape, x?, y?, width?, height?}` in points, `delete_shape`, `add_text_box`.\n   - `add_slide` `{after?, layout?, title?, body?}` with a layout name from the read, `duplicate_slide`, `move_slide` `{slide, position}`, `delete_slide`, `set_notes`.\n3. Edits in one call apply in order as one undoable step, and slide numbers in later edits refer to the deck after the earlier ones. If the call is refused because the revision changed, the user edited the presentation meanwhile: read again and redo the edit. If any edit fails, nothing is applied; fix the reported edit and retry.\n\nUse the OOXML workflow below only for what these tools cannot do: pictures, charts, SmartArt, new designs, or presentations LobsterAI reports as read-only.\n\n## Editing an existing PowerPoint presentation\n\nWhen edit slides in an existing PowerPoint presentation, you need to work with the raw Office Open XML (OOXML) format. This involves unpacking the .pptx file, editing the XML content, and repacking it.\n\n### Workflow\n1. **MANDATORY - READ ENTIRE FILE**: Read `ooxml.md` from the same directory as this `SKILL.md` (installed default: `$SKILLS_ROOT/pptx/ooxml.md`) (~500 lines) completely from start to finish.  **NEVER set any range limits when reading this file.**  Read the full file content for detailed guidance on OOXML structure and editing workflows before any presentation editing.\n2. Unpack the presentation: `python ooxml/scripts/unpack.py <office_file> <output_dir>`\n3. Edit the XML files (primarily `ppt/slides/slide{N}.xml` and related files)\n4. **CRITICAL**: Validate immediately after each edit and fix any validation errors before proceeding: `python ooxml/scripts/validate.py <dir> --original <file>`\n5. Pack the final presentation: `python ooxml/scripts/pack.py <input_directory> <office_file>`\n\n## Creating a new PowerPoint presentation **using a template**\n\nWhen you need to create a presentation that follows an existing template's design, you'll need to duplicate and re-arrange template slides before then replacing placeholder context.\n\n### Workflow\n1. **Extract template text AND create visual thumbnail grid**:\n   * Extract text: `python -m markitdown template.pptx > template-content.md`\n   * Read `template-content.md`: Read the entire file to understand the contents of the template presentation. **NEVER set any range limits when reading this file.**\n   * Create thumbnail grids: `python scripts/thumbnail.py template.pptx`\n   * See [Creating Thumbnail Grids](#creating-thumbnail-grids) section for more details\n\n2. **Analyze template and save inventory to a file**:\n   * **Visual Analysis**: Review thumbnail grid(s) to understand slide layouts, design patterns, and visual structure\n   * Create and save a template inventory file at `template-inventory.md` containing:\n     ```markdown\n     # Template Inventory Analysis\n     **Total Slides: [count]**\n     **IMPORTANT: Slides are 0-indexed (first slide = 0, last slide = count-1)**\n\n     ## [Category Name]\n     - Slide 0: [Layout code if available] - Description/purpose\n     - Slide 1: [Layout code] - Description/purpose\n     - Slide 2: [Layout code] - Description/purpose\n     [... EVERY slide must be listed individually with its index ...]\n     ```\n   * **Using the thumbnail grid**: Reference the visual thumbnails to identify:\n     - Layout patterns (title slides, content layouts, section dividers)\n     - Image placeholder locations and counts\n     - Design consistency across slide groups\n     - Visual hierarchy and structure\n   * This inventory file is REQUIRED for selecting appropriate templates in the next step\n\n3. **Create presentation outline based on template inventory**:\n   * Review available templates from step 2.\n   * Choose an intro or title template for the first slide. This should be one of the first templates.\n   * Choose safe, text-based layouts for the other slides.\n   * **CRITICAL: Match layout structure to actual content**:\n     - Single-column layouts: Use for unified narrative or single topic\n     - Two-column layouts: Use ONLY when you have exactly 2 distinct items/concepts\n     - Three-column layouts: Use ONLY when you have exactly 3 distinct items/concepts\n     - Image + text layouts: Use ONLY when you have actual images to insert\n     - Quote layouts: Use ONLY for actual quotes from people (with attribution), never for emphasis\n     - Never use layouts with more placeholders than you have content\n     - If you have 2 items, don't force them into a 3-column layout\n     - If you have 4+ items, consider breaking into multiple slides or using a list format\n   * Count your actual content pieces BEFORE selecting the layout\n   * Verify each placeholder in the chosen layout will be filled with meaningful content\n   * Select one option representing the **best** layout for each content section.\n   * Save `outline.md` with content AND template mapping that leverages available designs\n   * Example template mapping:\n      ```\n      # Template slides to use (0-based indexing)\n      # WARNING: Verify indices are within range! Template with 73 slides has indices 0-72\n      # Mapping: slide numbers from outline -> template slide indices\n      template_mapping = [\n          0,   # Use slide 0 (Title/Cover)\n          34,  # Use slide 34 (B1: Title and body)\n          34,  # Use slide 34 again (duplicate for second B1)\n          50,  # Use slide 50 (E1: Quote)\n          54,  # Use slide 54 (F2: Closing + Text)\n      ]\n      ```\n\n4. **Duplicate, reorder, and delete slides using `rearrange.py`**:\n   * Use the `scripts/rearrange.py` script to create a new presentation with slides in the desired order:\n     ```bash\n     python scripts/rearrange.py template.pptx working.pptx 0,34,34,50,52\n     ```\n   * The script handles duplicating repeated slides, deleting unused slides, and reordering automatically\n   * Slide indices are 0-based (first slide is 0, second is 1, etc.)\n   * The same slide index can appear multiple times to duplicate that slide\n\n5. **Extract ALL text using the `inventory.py` script**:\n   * **Run inventory extraction**:\n     ```bash\n     python scripts/inventory.py working.pptx text-inventory.json\n     ```\n   * **Read text-inventory.json**: Read the entire text-inventory.json file to understand all shapes and their properties. **NEVER set any range limits when reading this file.**\n\n   * The inventory JSON structure:\n      ```json\n        {\n          \"slide-0\": {\n            \"shape-0\": {\n              \"placeholder_type\": \"TITLE\",  // or null for non-placeholders\n              \"left\": 1.5,                  // position in inches\n              \"top\": 2.0,\n              \"width\": 7.5,\n              \"height\": 1.2,\n              \"paragraphs\": [\n                {\n                  \"text\": \"Paragraph text\",\n                  // Optional properties (only included when non-default):\n                  \"bullet\": true,           // explicit bullet detected\n                  \"level\": 0,               // only included when bullet is true\n                  \"alignment\": \"CENTER\",    // CENTER, RIGHT (not LEFT)\n                  \"space_before\": 10.0,     // space before paragraph in points\n                  \"space_after\": 6.0,       // space after paragraph in points\n                  \"line_spacing\": 22.4,     // line spacing in points\n                  \"font_name\": \"Arial\",     // from first run\n                  \"font_size\": 14.0,        // in points\n                  \"bold\": true,\n                  \"italic\": false,\n                  \"underline\": false,\n                  \"color\": \"FF0000\"         // RGB color\n                }\n              ]\n            }\n          }\n        }\n      ```\n\n   * Key features:\n     - **Slides**: Named as \"slide-0\", \"slide-1\", etc.\n     - **Shapes**: Ordered by visual position (top-to-bottom, left-to-right) as \"shape-0\", \"shape-1\", etc.\n     - **Placeholder types**: TITLE, CENTER_TITLE, SUBTITLE, BODY, OBJECT, or null\n     - **Default font size**: `default_font_size` in points extracted from layout placeholders (when available)\n     - **Slide numbers are filtered**: Shapes with SLIDE_NUMBER placeholder type are automatically excluded from inventory\n     - **Bullets**: When `bullet: true`, `level` is always included (even if 0)\n     - **Spacing**: `space_before`, `space_after`, and `line_spacing` in points (only included when set)\n     - **Colors**: `color` for RGB (e.g., \"FF0000\"), `theme_color` for theme colors (e.g., \"DARK_1\")\n     - **Properties**: Only non-default values are included in the output\n\n6. **Generate replacement text and save the data to a JSON file**\n   Based on the text inventory from the previous step:\n   - **CRITICAL**: First verify which shapes exist in the inventory - only reference shapes that are actually present\n   - **VALIDATION**: The replace.py script will validate that all shapes in your replacement JSON exist in the inventory\n     - If you reference a non-existent shape, you'll get an error showing available shapes\n     - If you reference a non-existent slide, you'll get an error indicating the slide doesn't exist\n     - All validation errors are shown at once before the script exits\n   - **IMPORTANT**: The replace.py script uses inventory.py internally to identify ALL text shapes\n   - **AUTOMATIC CLEARING**: ALL text shapes from the inventory will be cleared unless you provide \"paragraphs\" for them\n   - Add a \"paragraphs\" field to shapes that need content (not \"replacement_paragraphs\")\n   - Shapes without \"paragraphs\" in the replacement JSON will have their text cleared automatically\n   - Paragraphs with bullets will be automatically left aligned. Don't set the `alignment` property on when `\"bullet\": true`\n   - Generate appropriate replacement content for placeholder text\n   - Use shape size to determine appropriate content length\n   - **CRITICAL**: Include paragraph properties from the original inventory - don't just provide text\n   - **IMPORTANT**: When bullet: true, do NOT include bullet symbols (•, -, *) in text - they're added automatically\n   - **ESSENTIAL FORMATTING RULES**:\n     - Headers/titles should typically have `\"bold\": true`\n     - List items should have `\"bullet\": true, \"level\": 0` (level is required when bullet is true)\n     - Preserve any alignment properties (e.g., `\"alignment\": \"CENTER\"` for centered text)\n     - Include font properties when different from default (e.g., `\"font_size\": 14.0`, `\"font_name\": \"Lora\"`)\n     - Colors: Use `\"color\": \"FF0000\"` for RGB or `\"theme_color\": \"DARK_1\"` for theme colors\n     - The replacement script expects **properly formatted paragraphs**, not just text strings\n     - **Overlapping shapes**: Prefer shapes with larger default_font_size or more appropriate placeholder_type\n   - Save the updated inventory with replacements to `replacement-text.json`\n   - **WARNING**: Different template layouts have different shape counts - always check the actual inventory before creating replacements\n\n   Example paragraphs field showing proper formatting:\n   ```json\n   \"paragraphs\": [\n     {\n       \"text\": \"New presentation title text\",\n       \"alignment\": \"CENTER\",\n       \"bold\": true\n     },\n     {\n       \"text\": \"Section Header\",\n       \"bold\": true\n     },\n     {\n       \"text\": \"First bullet point without bullet symbol\",\n       \"bullet\": true,\n       \"level\": 0\n     },\n     {\n       \"text\": \"Red colored text\",\n       \"color\": \"FF0000\"\n     },\n     {\n       \"text\": \"Theme colored text\",\n       \"theme_color\": \"DARK_1\"\n     },\n     {\n       \"text\": \"Regular paragraph text without special formatting\"\n     }\n   ]\n   ```\n\n   **Shapes not listed in the replacement JSON are automatically cleared**:\n   ```json\n   {\n     \"slide-0\": {\n       \"shape-0\": {\n         \"paragraphs\": [...] // This shape gets new text\n       }\n       // shape-1 and shape-2 from inventory will be cleared automatically\n     }\n   }\n   ```\n\n   **Common formatting patterns for presentations**:\n   - Title slides: Bold text, sometimes centered\n   - Section headers within slides: Bold text\n   - Bullet lists: Each item needs `\"bullet\": true, \"level\": 0`\n   - Body text: Usually no special properties needed\n   - Quotes: May have special alignment or font properties\n\n7. **Apply replacements using the `replace.py` script**\n   ```bash\n   python scripts/replace.py working.pptx replacement-text.json output.pptx\n   ```\n\n   The script will:\n   - First extract the inventory of ALL text shapes using functions from inventory.py\n   - Validate that all shapes in the replacement JSON exist in the inventory\n   - Clear text from ALL shapes identified in the inventory\n   - Apply new text only to shapes with \"paragraphs\" defined in the replacement JSON\n   - Preserve formatting by applying paragraph properties from the JSON\n   - Handle bullets, alignment, font properties, and colors automatically\n   - Save the updated presentation\n\n   Example validation errors:\n   ```\n   ERROR: Invalid shapes in replacement JSON:\n     - Shape 'shape-99' not found on 'slide-0'. Available shapes: shape-0, shape-1, shape-4\n     - Slide 'slide-999' not found in inventory\n   ```\n\n   ```\n   ERROR: Replacement text made overflow worse in these shapes:\n     - slide-0/shape-2: overflow worsened by 1.25\" (was 0.00\", now 1.25\")\n   ```\n\n## Creating Thumbnail Grids\n\nTo create visual thumbnail grids of PowerPoint slides for quick analysis and reference:\n\n```bash\npython scripts/thumbnail.py template.pptx [output_prefix]\n```\n\n**Features**:\n- Creates: `thumbnails.jpg` (or `thumbnails-1.jpg`, `thumbnails-2.jpg`, etc. for large decks)\n- Default: 5 columns, max 30 slides per grid (5×6)\n- Custom prefix: `python scripts/thumbnail.py template.pptx my-grid`\n  - Note: The output prefix should include the path if you want output in a specific directory (e.g., `workspace/my-grid`)\n- Adjust columns: `--cols 4` (range: 3-6, affects slides per grid)\n- Grid limits: 3 cols = 12 slides/grid, 4 cols = 20, 5 cols = 30, 6 cols = 42\n- Slides are zero-indexed (Slide 0, Slide 1, etc.)\n\n**Use cases**:\n- Template analysis: Quickly understand slide layouts and design patterns\n- Content review: Visual overview of entire presentation\n- Navigation reference: Find specific slides by their visual appearance\n- Quality check: Verify all slides are properly formatted\n\n**Examples**:\n```bash\n# Basic usage\npython scripts/thumbnail.py presentation.pptx\n\n# Combine options: custom name, columns\npython scripts/thumbnail.py template.pptx analysis --cols 4\n```\n\n## Converting Slides to Images\n\nTo visually analyze PowerPoint slides, convert them to images using a two-step process:\n\n1. **Convert PPTX to PDF**:\n   ```bash\n   soffice --headless --convert-to pdf template.pptx\n   ```\n\n2. **Convert PDF pages to JPEG images**:\n   ```bash\n   pdftoppm -jpeg -r 150 template.pdf slide\n   ```\n   This creates files like `slide-1.jpg`, `slide-2.jpg`, etc.\n\nOptions:\n- `-r 150`: Sets resolution to 150 DPI (adjust for quality/size balance)\n- `-jpeg`: Output JPEG format (use `-png` for PNG if preferred)\n- `-f N`: First page to convert (e.g., `-f 2` starts from page 2)\n- `-l N`: Last page to convert (e.g., `-l 5` stops at page 5)\n- `slide`: Prefix for output files\n\nExample for specific range:\n```bash\npdftoppm -jpeg -r 150 -f 2 -l 5 template.pdf slide  # Converts only pages 2-5\n```\n\n## Code Style Guidelines\n**IMPORTANT**: When generating code for PPTX operations:\n- Write concise code\n- Avoid verbose variable names and redundant operations\n- Avoid unnecessary print statements\n\n## Dependencies\n\nRequired dependencies (should already be installed):\n\n- **markitdown**: `pip install \"markitdown[pptx]\"` (for text extraction from presentations)\n- **pptxgenjs**: `npm install -g pptxgenjs` (for creating presentations via html2pptx)\n- **playwright**: `npm install -g playwright` (for HTML rendering in html2pptx)\n- **react-icons**: `npm install -g react-icons react react-dom` (for icons)\n- **sharp**: `npm install -g sharp` (for SVG rasterization and image processing)\n- **LibreOffice**: `sudo apt-get install libreoffice` (for PDF conversion)\n- **Poppler**: `sudo apt-get install poppler-utils` (for pdftoppm to convert PDF to images)\n- **defusedxml**: `pip install defusedxml` (for secure XML parsing)\n","SKILLs/skill-creator/SKILL.md":"---\nname: skill-creator\ndescription: Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, update or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.\nofficial: true\nversion: 1.0.1\n---\n\n# Skill Creator\n\nA skill for creating new skills and iteratively improving them.\n\nAt a high level, the process of creating a skill goes like this:\n\n- Decide what you want the skill to do and roughly how it should do it\n- Write a draft of the skill\n- Create a few test prompts and run claude-with-access-to-the-skill on them\n- Help the user evaluate the results both qualitatively and quantitatively\n  - While the runs happen in the background, draft some quantitative evals if there aren't any (if there are some, you can either use as is or modify if you feel something needs to change about them). Then explain them to the user (or if they already existed, explain the ones that already exist)\n  - Use the `eval-viewer/generate_review.py` script to show the user the results for them to look at, and also let them look at the quantitative metrics\n- Rewrite the skill based on feedback from the user's evaluation of the results (and also if there are any glaring flaws that become apparent from the quantitative benchmarks)\n- Repeat until you're satisfied\n- Expand the test set and try again at larger scale\n\nYour job when using this skill is to figure out where the user is in this process and then jump in and help them progress through these stages. So for instance, maybe they're like \"I want to make a skill for X\". You can help narrow down what they mean, write a draft, write the test cases, figure out how they want to evaluate, run all the prompts, and repeat.\n\nOn the other hand, maybe they already have a draft of the skill. In this case you can go straight to the eval/iterate part of the loop.\n\nOf course, you should always be flexible and if the user is like \"I don't need to run a bunch of evaluations, just vibe with me\", you can do that instead.\n\nThen after the skill is done (but again, the order is flexible), you can also run the skill description improver, which we have a whole separate script for, to optimize the triggering of the skill.\n\nCool? Cool.\n\n## Communicating with the user\n\nThe skill creator is liable to be used by people across a wide range of familiarity with coding jargon. If you haven't heard (and how could you, it's only very recently that it started), there's a trend now where the power of Claude is inspiring plumbers to open up their terminals, parents and grandparents to google \"how to install npm\". On the other hand, the bulk of users are probably fairly computer-literate.\n\nSo please pay attention to context cues to understand how to phrase your communication! In the default case, just to give you some idea:\n\n- \"evaluation\" and \"benchmark\" are borderline, but OK\n- for \"JSON\" and \"assertion\" you want to see serious cues from the user that they know what those things are before using them without explaining them\n\nIt's OK to briefly explain terms if you're in doubt, and feel free to clarify terms with a short definition if you're unsure if the user will get it.\n\n---\n\n## Creating a skill\n\n### Capture Intent\n\nStart by understanding the user's intent. The current conversation might already contain a workflow the user wants to capture (e.g., they say \"turn this into a skill\"). If so, extract answers from the conversation history first — the tools used, the sequence of steps, corrections the user made, input/output formats observed. The user may need to fill the gaps, and should confirm before proceeding to the next step.\n\n1. What should this skill enable Claude to do?\n2. When should this skill trigger? (what user phrases/contexts)\n3. What's the expected output format?\n4. Should we set up test cases to verify the skill works? Skills with objectively verifiable outputs (file transforms, data extraction, code generation, fixed workflow steps) benefit from test cases. Skills with subjective outputs (writing style, art) often don't need them. Suggest the appropriate default based on the skill type, but let the user decide.\n\n### Interview and Research\n\nProactively ask questions about edge cases, input/output formats, example files, success criteria, and dependencies. Wait to write test prompts until you've got this part ironed out.\n\nCheck available MCPs - if useful for research (searching docs, finding similar skills, looking up best practices), research in parallel via subagents if available, otherwise inline. Come prepared with context to reduce burden on the user.\n\n### Write the SKILL.md\n\nBased on the user interview, fill in these components:\n\n- **name**: Skill identifier\n- **description**: When to trigger, what it does. This is the primary triggering mechanism - include both what the skill does AND specific contexts for when to use it. All \"when to use\" info goes here, not in the body. Note: currently Claude has a tendency to \"undertrigger\" skills -- to not use them when they'd be useful. To combat this, please make the skill descriptions a little bit \"pushy\". So for instance, instead of \"How to build a simple fast dashboard to display internal Anthropic data.\", you might write \"How to build a simple fast dashboard to display internal Anthropic data. Make sure to use this skill whenever the user mentions dashboards, data visualization, internal metrics, or wants to display any kind of company data, even if they don't explicitly ask for a 'dashboard.'\"\n- **compatibility**: Required tools, dependencies (optional, rarely needed)\n- **the rest of the skill :)**\n\n### Skill Writing Guide\n\n#### Anatomy of a Skill\n\n```\nskill-name/\n├── SKILL.md (required)\n│   ├── YAML frontmatter (name, description required)\n│   └── Markdown instructions\n└── Bundled Resources (optional)\n    ├── scripts/    - Executable code for deterministic/repetitive tasks\n    ├── references/ - Docs loaded into context as needed\n    └── assets/     - Files used in output (templates, icons, fonts)\n```\n\n#### Progressive Disclosure\n\nSkills use a three-level loading system:\n1. **Metadata** (name + description) - Always in context (~100 words)\n2. **SKILL.md body** - In context whenever skill triggers (<500 lines ideal)\n3. **Bundled resources** - As needed (unlimited, scripts can execute without loading)\n\nThese word counts are approximate and you can feel free to go longer if needed.\n\n**Key patterns:**\n- Keep SKILL.md under 500 lines; if you're approaching this limit, add an additional layer of hierarchy along with clear pointers about where the model using the skill should go next to follow up.\n- Reference files clearly from SKILL.md with guidance on when to read them\n- For large reference files (>300 lines), include a table of contents\n\n**Domain organization**: When a skill supports multiple domains/frameworks, organize by variant:\n```\ncloud-deploy/\n├── SKILL.md (workflow + selection)\n└── references/\n    ├── aws.md\n    ├── gcp.md\n    └── azure.md\n```\nClaude reads only the relevant reference file.\n\n#### Principle of Lack of Surprise\n\nThis goes without saying, but skills must not contain malware, exploit code, or any content that could compromise system security. A skill's contents should not surprise the user in their intent if described. Don't go along with requests to create misleading skills or skills designed to facilitate unauthorized access, data exfiltration, or other malicious activities. Things like a \"roleplay as an XYZ\" are OK though.\n\n#### Writing Patterns\n\nPrefer using the imperative form in instructions.\n\n**Defining output formats** - You can do it like this:\n```markdown\n## Report structure\nALWAYS use this exact template:\n# [Title]\n## Executive summary\n## Key findings\n## Recommendations\n```\n\n**Examples pattern** - It's useful to include examples. You can format them like this (but if \"Input\" and \"Output\" are in the examples you might want to deviate a little):\n```markdown\n## Commit message format\n**Example 1:**\nInput: Added user authentication with JWT tokens\nOutput: feat(auth): implement JWT-based authentication\n```\n\n### Writing Style\n\nTry to explain to the model why things are important in lieu of heavy-handed musty MUSTs. Use theory of mind and try to make the skill general and not super-narrow to specific examples. Start by writing a draft and then look at it with fresh eyes and improve it.\n\n### Test Cases\n\nAfter writing the skill draft, come up with 2-3 realistic test prompts — the kind of thing a real user would actually say. Share them with the user: [you don't have to use this exact language] \"Here are a few test cases I'd like to try. Do these look right, or do you want to add more?\" Then run them.\n\nSave test cases to `evals/evals.json`. Don't write assertions yet — just the prompts. You'll draft assertions in the next step while the runs are in progress.\n\n```json\n{\n  \"skill_name\": \"example-skill\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"prompt\": \"User's task prompt\",\n      \"expected_output\": \"Description of expected result\",\n      \"files\": []\n    }\n  ]\n}\n```\n\nSee `references/schemas.md` for the full schema (including the `assertions` field, which you'll add later).\n\n## Running and evaluating test cases\n\nThis section is one continuous sequence — don't stop partway through. Do NOT use `/skill-test` or any other testing skill.\n\nPut results in `<skill-name>-workspace/` as a sibling to the skill directory. Within the workspace, organize results by iteration (`iteration-1/`, `iteration-2/`, etc.) and within that, each test case gets a directory (`eval-0/`, `eval-1/`, etc.). Don't create all of this upfront — just create directories as you go.\n\n### Step 1: Spawn all runs (with-skill AND baseline) in the same turn\n\nFor each test case, spawn two subagents in the same turn — one with the skill, one without. This is important: don't spawn the with-skill runs first and then come back for baselines later. Launch everything at once so it all finishes around the same time.\n\n**With-skill run:**\n\n```\nExecute this task:\n- Skill path: <path-to-skill>\n- Task: <eval prompt>\n- Input files: <eval files if any, or \"none\">\n- Save outputs to: <workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/\n- Outputs to save: <what the user cares about — e.g., \"the .docx file\", \"the final CSV\">\n```\n\n**Baseline run** (same prompt, but the baseline depends on context):\n- **Creating a new skill**: no skill at all. Same prompt, no skill path, save to `without_skill/outputs/`.\n- **Improving an existing skill**: the old version. Before editing, snapshot the skill (`cp -r <skill-path> <workspace>/skill-snapshot/`), then point the baseline subagent at the snapshot. Save to `old_skill/outputs/`.\n\nWrite an `eval_metadata.json` for each test case (assertions can be empty for now). Give each eval a descriptive name based on what it's testing — not just \"eval-0\". Use this name for the directory too. If this iteration uses new or modified eval prompts, create these files for each new eval directory — don't assume they carry over from previous iterations.\n\n```json\n{\n  \"eval_id\": 0,\n  \"eval_name\": \"descriptive-name-here\",\n  \"prompt\": \"The user's task prompt\",\n  \"assertions\": []\n}\n```\n\n### Step 2: While runs are in progress, draft assertions\n\nDon't just wait for the runs to finish — you can use this time productively. Draft quantitative assertions for each test case and explain them to the user. If assertions already exist in `evals/evals.json`, review them and explain what they check.\n\nGood assertions are objectively verifiable and have descriptive names — they should read clearly in the benchmark viewer so someone glancing at the results immediately understands what each one checks. Subjective skills (writing style, design quality) are better evaluated qualitatively — don't force assertions onto things that need human judgment.\n\nUpdate the `eval_metadata.json` files and `evals/evals.json` with the assertions once drafted. Also explain to the user what they'll see in the viewer — both the qualitative outputs and the quantitative benchmark.\n\n### Step 3: As runs complete, capture timing data\n\nWhen each subagent task completes, you receive a notification containing `total_tokens` and `duration_ms`. Save this data immediately to `timing.json` in the run directory:\n\n```json\n{\n  \"total_tokens\": 84852,\n  \"duration_ms\": 23332,\n  \"total_duration_seconds\": 23.3\n}\n```\n\nThis is the only opportunity to capture this data — it comes through the task notification and isn't persisted elsewhere. Process each notification as it arrives rather than trying to batch them.\n\n### Step 4: Grade, aggregate, and launch the viewer\n\nOnce all runs are done:\n\n1. **Grade each run** — spawn a grader subagent (or grade inline) that reads `agents/grader.md` and evaluates each assertion against the outputs. Save results to `grading.json` in each run directory. The grading.json expectations array must use the fields `text`, `passed`, and `evidence` (not `name`/`met`/`details` or other variants) — the viewer depends on these exact field names. For assertions that can be checked programmatically, write and run a script rather than eyeballing it — scripts are faster, more reliable, and can be reused across iterations.\n\n2. **Aggregate into benchmark** — run the aggregation script from the skill-creator directory:\n   ```bash\n   python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>\n   ```\n   This produces `benchmark.json` and `benchmark.md` with pass_rate, time, and tokens for each configuration, with mean ± stddev and the delta. If generating benchmark.json manually, see `references/schemas.md` for the exact schema the viewer expects.\nPut each with_skill version before its baseline counterpart.\n\n3. **Do an analyst pass** — read the benchmark data and surface patterns the aggregate stats might hide. See `agents/analyzer.md` (the \"Analyzing Benchmark Results\" section) for what to look for — things like assertions that always pass regardless of skill (non-discriminating), high-variance evals (possibly flaky), and time/token tradeoffs.\n\n4. **Launch the viewer** with both qualitative outputs and quantitative data:\n   ```bash\n   nohup python <skill-creator-path>/eval-viewer/generate_review.py \\\n     <workspace>/iteration-N \\\n     --skill-name \"my-skill\" \\\n     --benchmark <workspace>/iteration-N/benchmark.json \\\n     > /dev/null 2>&1 &\n   VIEWER_PID=$!\n   ```\n   For iteration 2+, also pass `--previous-workspace <workspace>/iteration-<N-1>`.\n\n   **Cowork / headless environments:** If `webbrowser.open()` is not available or the environment has no display, use `--static <output_path>` to write a standalone HTML file instead of starting a server. Feedback will be downloaded as a `feedback.json` file when the user clicks \"Submit All Reviews\". After download, copy `feedback.json` into the workspace directory for the next iteration to pick up.\n\nNote: please use generate_review.py to create the viewer; there's no need to write custom HTML.\n\n5. **Tell the user** something like: \"I've opened the results in your browser. There are two tabs — 'Outputs' lets you click through each test case and leave feedback, 'Benchmark' shows the quantitative comparison. When you're done, come back here and let me know.\"\n\n### What the user sees in the viewer\n\nThe \"Outputs\" tab shows one test case at a time:\n- **Prompt**: the task that was given\n- **Output**: the files the skill produced, rendered inline where possible\n- **Previous Output** (iteration 2+): collapsed section showing last iteration's output\n- **Formal Grades** (if grading was run): collapsed section showing assertion pass/fail\n- **Feedback**: a textbox that auto-saves as they type\n- **Previous Feedback** (iteration 2+): their comments from last time, shown below the textbox\n\nThe \"Benchmark\" tab shows the stats summary: pass rates, timing, and token usage for each configuration, with per-eval breakdowns and analyst observations.\n\nNavigation is via prev/next buttons or arrow keys. When done, they click \"Submit All Reviews\" which saves all feedback to `feedback.json`.\n\n### Step 5: Read the feedback\n\nWhen the user tells you they're done, read `feedback.json`:\n\n```json\n{\n  \"reviews\": [\n    {\"run_id\": \"eval-0-with_skill\", \"feedback\": \"the chart is missing axis labels\", \"timestamp\": \"...\"},\n    {\"run_id\": \"eval-1-with_skill\", \"feedback\": \"\", \"timestamp\": \"...\"},\n    {\"run_id\": \"eval-2-with_skill\", \"feedback\": \"perfect, love this\", \"timestamp\": \"...\"}\n  ],\n  \"status\": \"complete\"\n}\n```\n\nEmpty feedback means the user thought it was fine. Focus your improvements on the test cases where the user had specific complaints.\n\nKill the viewer server when you're done with it:\n\n```bash\nkill $VIEWER_PID 2>/dev/null\n```\n\n---\n\n## Improving the skill\n\nThis is the heart of the loop. You've run the test cases, the user has reviewed the results, and now you need to make the skill better based on their feedback.\n\n### How to think about improvements\n\n1. **Generalize from the feedback.** The big picture thing that's happening here is that we're trying to create skills that can be used a million times (maybe literally, maybe even more who knows) across many different prompts. Here you and the user are iterating on only a few examples over and over again because it helps move faster. The user knows these examples in and out and it's quick for them to assess new outputs. But if the skill you and the user are codeveloping works only for those examples, it's useless. Rather than put in fiddly overfitty changes, or oppressively constrictive MUSTs, if there's some stubborn issue, you might try branching out and using different metaphors, or recommending different patterns of working. It's relatively cheap to try and maybe you'll land on something great.\n\n2. **Keep the prompt lean.** Remove things that aren't pulling their weight. Make sure to read the transcripts, not just the final outputs — if it looks like the skill is making the model waste a bunch of time doing things that are unproductive, you can try getting rid of the parts of the skill that are making it do that and seeing what happens.\n\n3. **Explain the why.** Try hard to explain the **why** behind everything you're asking the model to do. Today's LLMs are *smart*. They have good theory of mind and when given a good harness can go beyond rote instructions and really make things happen. Even if the feedback from the user is terse or frustrated, try to actually understand the task and why the user is writing what they wrote, and what they actually wrote, and then transmit this understanding into the instructions. If you find yourself writing ALWAYS or NEVER in all caps, or using super rigid structures, that's a yellow flag — if possible, reframe and explain the reasoning so that the model understands why the thing you're asking for is important. That's a more humane, powerful, and effective approach.\n\n4. **Look for repeated work across test cases.** Read the transcripts from the test runs and notice if the subagents all independently wrote similar helper scripts or took the same multi-step approach to something. If all 3 test cases resulted in the subagent writing a `create_docx.py` or a `build_chart.py`, that's a strong signal the skill should bundle that script. Write it once, put it in `scripts/`, and tell the skill to use it. This saves every future invocation from reinventing the wheel.\n\nThis task is pretty important (we are trying to create billions a year in economic value here!) and your thinking time is not the blocker; take your time and really mull things over. I'd suggest writing a draft revision and then looking at it anew and making improvements. Really do your best to get into the head of the user and understand what they want and need.\n\n### The iteration loop\n\nAfter improving the skill:\n\n1. Apply your improvements to the skill\n2. Rerun all test cases into a new `iteration-<N+1>/` directory, including baseline runs. If you're creating a new skill, the baseline is always `without_skill` (no skill) — that stays the same across iterations. If you're improving an existing skill, use your judgment on what makes sense as the baseline: the original version the user came in with, or the previous iteration.\n3. Launch the reviewer with `--previous-workspace` pointing at the previous iteration\n4. Wait for the user to review and tell you they're done\n5. Read the new feedback, improve again, repeat\n\nKeep going until:\n- The user says they're happy\n- The feedback is all empty (everything looks good)\n- You're not making meaningful progress\n\n---\n\n## Advanced: Blind comparison\n\nFor situations where you want a more rigorous comparison between two versions of a skill (e.g., the user asks \"is the new version actually better?\"), there's a blind comparison system. Read `agents/comparator.md` and `agents/analyzer.md` for the details. The basic idea is: give two outputs to an independent agent without telling it which is which, and let it judge quality. Then analyze why the winner won.\n\nThis is optional, requires subagents, and most users won't need it. The human review loop is usually sufficient.\n\n---\n\n## Description Optimization\n\nThe description field in SKILL.md frontmatter is the primary mechanism that determines whether Claude invokes a skill. After creating or improving a skill, offer to optimize the description for better triggering accuracy.\n\n### Step 1: Generate trigger eval queries\n\nCreate 20 eval queries — a mix of should-trigger and should-not-trigger. Save as JSON:\n\n```json\n[\n  {\"query\": \"the user prompt\", \"should_trigger\": true},\n  {\"query\": \"another prompt\", \"should_trigger\": false}\n]\n```\n\nThe queries must be realistic and something a Claude Code or Claude.ai user would actually type. Not abstract requests, but requests that are concrete and specific and have a good amount of detail. For instance, file paths, personal context about the user's job or situation, column names and values, company names, URLs. A little bit of backstory. Some might be in lowercase or contain abbreviations or typos or casual speech. Use a mix of different lengths, and focus on edge cases rather than making them clear-cut (the user will get a chance to sign off on them).\n\nBad: `\"Format this data\"`, `\"Extract text from PDF\"`, `\"Create a chart\"`\n\nGood: `\"ok so my boss just sent me this xlsx file (its in my downloads, called something like 'Q4 sales final FINAL v2.xlsx') and she wants me to add a column that shows the profit margin as a percentage. The revenue is in column C and costs are in column D i think\"`\n\nFor the **should-trigger** queries (8-10), think about coverage. You want different phrasings of the same intent — some formal, some casual. Include cases where the user doesn't explicitly name the skill or file type but clearly needs it. Throw in some uncommon use cases and cases where this skill competes with another but should win.\n\nFor the **should-not-trigger** queries (8-10), the most valuable ones are the near-misses — queries that share keywords or concepts with the skill but actually need something different. Think adjacent domains, ambiguous phrasing where a naive keyword match would trigger but shouldn't, and cases where the query touches on something the skill does but in a context where another tool is more appropriate.\n\nThe key thing to avoid: don't make should-not-trigger queries obviously irrelevant. \"Write a fibonacci function\" as a negative test for a PDF skill is too easy — it doesn't test anything. The negative cases should be genuinely tricky.\n\n### Step 2: Review with user\n\nPresent the eval set to the user for review using the HTML template:\n\n1. Read the template from `assets/eval_review.html`\n2. Replace the placeholders:\n   - `__EVAL_DATA_PLACEHOLDER__` → the JSON array of eval items (no quotes around it — it's a JS variable assignment)\n   - `__SKILL_NAME_PLACEHOLDER__` → the skill's name\n   - `__SKILL_DESCRIPTION_PLACEHOLDER__` → the skill's current description\n3. Write to a temp file (e.g., `/tmp/eval_review_<skill-name>.html`) and open it: `open /tmp/eval_review_<skill-name>.html`\n4. The user can edit queries, toggle should-trigger, add/remove entries, then click \"Export Eval Set\"\n5. The file downloads to `~/Downloads/eval_set.json` — check the Downloads folder for the most recent version in case there are multiple (e.g., `eval_set (1).json`)\n\nThis step matters — bad eval queries lead to bad descriptions.\n\n### Step 3: Run the optimization loop\n\nTell the user: \"This will take some time — I'll run the optimization loop in the background and check on it periodically.\"\n\nSave the eval set to the workspace, then run in the background:\n\n```bash\npython -m scripts.run_loop \\\n  --eval-set <path-to-trigger-eval.json> \\\n  --skill-path <path-to-skill> \\\n  --model <model-id-powering-this-session> \\\n  --max-iterations 5 \\\n  --verbose\n```\n\nUse the model ID from your system prompt (the one powering the current session) so the triggering test matches what the user actually experiences.\n\nWhile it runs, periodically tail the output to give the user updates on which iteration it's on and what the scores look like.\n\nThis handles the full optimization loop automatically. It splits the eval set into 60% train and 40% held-out test, evaluates the current description (running each query 3 times to get a reliable trigger rate), then calls Claude with extended thinking to propose improvements based on what failed. It re-evaluates each new description on both train and test, iterating up to 5 times. When it's done, it opens an HTML report in the browser showing the results per iteration and returns JSON with `best_description` — selected by test score rather than train score to avoid overfitting.\n\n### How skill triggering works\n\nUnderstanding the triggering mechanism helps design better eval queries. Skills appear in Claude's `available_skills` list with their name + description, and Claude decides whether to consult a skill based on that description. The important thing to know is that Claude only consults skills for tasks it can't easily handle on its own — simple, one-step queries like \"read this PDF\" may not trigger a skill even if the description matches perfectly, because Claude can handle them directly with basic tools. Complex, multi-step, or specialized queries reliably trigger skills when the description matches.\n\nThis means your eval queries should be substantive enough that Claude would actually benefit from consulting a skill. Simple queries like \"read file X\" are poor test cases — they won't trigger skills regardless of description quality.\n\n### Step 4: Apply the result\n\nTake `best_description` from the JSON output and update the skill's SKILL.md frontmatter. Show the user before/after and report the scores.\n\n---\n\n### Package and Present (only if `present_files` tool is available)\n\nCheck whether you have access to the `present_files` tool. If you don't, skip this step. If you do, package the skill and present the .skill file to the user:\n\n```bash\npython -m scripts.package_skill <path/to/skill-folder>\n```\n\nAfter packaging, direct the user to the resulting `.skill` file path so they can install it.\n\n---\n\n## Claude.ai-specific instructions\n\nIn Claude.ai, the core workflow is the same (draft → test → review → improve → repeat), but because Claude.ai doesn't have subagents, some mechanics change. Here's what to adapt:\n\n**Running test cases**: No subagents means no parallel execution. For each test case, read the skill's SKILL.md, then follow its instructions to accomplish the test prompt yourself. Do them one at a time. This is less rigorous than independent subagents (you wrote the skill and you're also running it, so you have full context), but it's a useful sanity check — and the human review step compensates. Skip the baseline runs — just use the skill to complete the task as requested.\n\n**Reviewing results**: If you can't open a browser (e.g., Claude.ai's VM has no display, or you're on a remote server), skip the browser reviewer entirely. Instead, present results directly in the conversation. For each test case, show the prompt and the output. If the output is a file the user needs to see (like a .docx or .xlsx), save it to the filesystem and tell them where it is so they can download and inspect it. Ask for feedback inline: \"How does this look? Anything you'd change?\"\n\n**Benchmarking**: Skip the quantitative benchmarking — it relies on baseline comparisons which aren't meaningful without subagents. Focus on qualitative feedback from the user.\n\n**The iteration loop**: Same as before — improve the skill, rerun the test cases, ask for feedback — just without the browser reviewer in the middle. You can still organize results into iteration directories on the filesystem if you have one.\n\n**Description optimization**: This section requires the `claude` CLI tool (specifically `claude -p`) which is only available in Claude Code. Skip it if you're on Claude.ai.\n\n**Blind comparison**: Requires subagents. Skip it.\n\n**Packaging**: The `package_skill.py` script works anywhere with Python and a filesystem. On Claude.ai, you can run it and the user can download the resulting `.skill` file.\n\n---\n\n## Cowork-Specific Instructions\n\nIf you're in Cowork, the main things to know are:\n\n- You have subagents, so the main workflow (spawn test cases in parallel, run baselines, grade, etc.) all works. (However, if you run into severe problems with timeouts, it's OK to run the test prompts in series rather than parallel.)\n- You don't have a browser or display, so when generating the eval viewer, use `--static <output_path>` to write a standalone HTML file instead of starting a server. Then proffer a link that the user can click to open the HTML in their browser.\n- For whatever reason, the Cowork setup seems to disincline Claude from generating the eval viewer after running the tests, so just to reiterate: whether you're in Cowork or in Claude Code, after running tests, you should always generate the eval viewer for the human to look at examples before revising the skill yourself and trying to make corrections, using `generate_review.py` (not writing your own boutique html code). Sorry in advance but I'm gonna go all caps here: GENERATE THE EVAL VIEWER *BEFORE* evaluating inputs yourself. You want to get them in front of the human ASAP!\n- Feedback works differently: since there's no running server, the viewer's \"Submit All Reviews\" button will download `feedback.json` as a file. You can then read it from there (you may have to request access first).\n- Packaging works — `package_skill.py` just needs Python and a filesystem.\n- Description optimization (`run_loop.py` / `run_eval.py`) should work in Cowork just fine since it uses `claude -p` via subprocess, not a browser, but please save it until you've fully finished making the skill and the user agrees it's in good shape.\n\n---\n\n## Reference files\n\nThe agents/ directory contains instructions for specialized subagents. Read them when you need to spawn the relevant subagent.\n\n- `agents/grader.md` — How to evaluate assertions against outputs\n- `agents/comparator.md` — How to do blind A/B comparison between two outputs\n- `agents/analyzer.md` — How to analyze why one version beat another\n\nThe references/ directory has additional documentation:\n- `references/schemas.md` — JSON structures for evals.json, grading.json, etc.\n\n---\n\nRepeating one more time the core loop here for emphasis:\n\n- Figure out what the skill is about\n- Draft or edit the skill\n- Run claude-with-access-to-the-skill on test prompts\n- With the user, evaluate the outputs:\n  - Create benchmark.json and run `eval-viewer/generate_review.py` to help the user review them\n  - Run quantitative evals\n- Repeat until you and the user are satisfied\n- Package the final skill and return it to the user.\n\nPlease add steps to your TodoList, if you have such a thing, to make sure you don't forget. If you're in Cowork, please specifically put \"Create evals JSON and run `eval-viewer/generate_review.py` so human can review test cases\" in your TodoList to make sure it happens.\n\nGood luck!\n","SKILLs/pdf/SKILL.md":"---\nname: pdf\ndescription: Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.\nlicense: Proprietary. LICENSE.txt has complete terms\nofficial: true\n---\n\n# PDF Processing Guide\n\n## Overview\n\nThis guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see reference.md. If you need to fill out a PDF form, read forms.md and follow its instructions.\n\n## Quick Start\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Read a PDF\nreader = PdfReader(\"document.pdf\")\nprint(f\"Pages: {len(reader.pages)}\")\n\n# Extract text\ntext = \"\"\nfor page in reader.pages:\n    text += page.extract_text()\n```\n\n## Python Libraries\n\n### pypdf - Basic Operations\n\n#### Merge PDFs\n```python\nfrom pypdf import PdfWriter, PdfReader\n\nwriter = PdfWriter()\nfor pdf_file in [\"doc1.pdf\", \"doc2.pdf\", \"doc3.pdf\"]:\n    reader = PdfReader(pdf_file)\n    for page in reader.pages:\n        writer.add_page(page)\n\nwith open(\"merged.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n#### Split PDF\n```python\nreader = PdfReader(\"input.pdf\")\nfor i, page in enumerate(reader.pages):\n    writer = PdfWriter()\n    writer.add_page(page)\n    with open(f\"page_{i+1}.pdf\", \"wb\") as output:\n        writer.write(output)\n```\n\n#### Extract Metadata\n```python\nreader = PdfReader(\"document.pdf\")\nmeta = reader.metadata\nprint(f\"Title: {meta.title}\")\nprint(f\"Author: {meta.author}\")\nprint(f\"Subject: {meta.subject}\")\nprint(f\"Creator: {meta.creator}\")\n```\n\n#### Rotate Pages\n```python\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\npage = reader.pages[0]\npage.rotate(90)  # Rotate 90 degrees clockwise\nwriter.add_page(page)\n\nwith open(\"rotated.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### pdfplumber - Text and Table Extraction\n\n#### Extract Text with Layout\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        text = page.extract_text()\n        print(text)\n```\n\n#### Extract Tables\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for i, page in enumerate(pdf.pages):\n        tables = page.extract_tables()\n        for j, table in enumerate(tables):\n            print(f\"Table {j+1} on page {i+1}:\")\n            for row in table:\n                print(row)\n```\n\n#### Advanced Table Extraction\n```python\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    all_tables = []\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            if table:  # Check if table is not empty\n                df = pd.DataFrame(table[1:], columns=table[0])\n                all_tables.append(df)\n\n# Combine all tables\nif all_tables:\n    combined_df = pd.concat(all_tables, ignore_index=True)\n    combined_df.to_excel(\"extracted_tables.xlsx\", index=False)\n```\n\n### reportlab - Create PDFs\n\n#### Basic PDF Creation\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.pdfgen import canvas\n\nc = canvas.Canvas(\"hello.pdf\", pagesize=letter)\nwidth, height = letter\n\n# Add text\nc.drawString(100, height - 100, \"Hello World!\")\nc.drawString(100, height - 120, \"This is a PDF created with reportlab\")\n\n# Add a line\nc.line(100, height - 140, 400, height - 140)\n\n# Save\nc.save()\n```\n\n#### Create PDF with Multiple Pages\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak\nfrom reportlab.lib.styles import getSampleStyleSheet\n\ndoc = SimpleDocTemplate(\"report.pdf\", pagesize=letter)\nstyles = getSampleStyleSheet()\nstory = []\n\n# Add content\ntitle = Paragraph(\"Report Title\", styles['Title'])\nstory.append(title)\nstory.append(Spacer(1, 12))\n\nbody = Paragraph(\"This is the body of the report. \" * 20, styles['Normal'])\nstory.append(body)\nstory.append(PageBreak())\n\n# Page 2\nstory.append(Paragraph(\"Page 2\", styles['Heading1']))\nstory.append(Paragraph(\"Content for page 2\", styles['Normal']))\n\n# Build PDF\ndoc.build(story)\n```\n\n## Command-Line Tools\n\n### pdftotext (poppler-utils)\n```bash\n# Extract text\npdftotext input.pdf output.txt\n\n# Extract text preserving layout\npdftotext -layout input.pdf output.txt\n\n# Extract specific pages\npdftotext -f 1 -l 5 input.pdf output.txt  # Pages 1-5\n```\n\n### qpdf\n```bash\n# Merge PDFs\nqpdf --empty --pages file1.pdf file2.pdf -- merged.pdf\n\n# Split pages\nqpdf input.pdf --pages . 1-5 -- pages1-5.pdf\nqpdf input.pdf --pages . 6-10 -- pages6-10.pdf\n\n# Rotate pages\nqpdf input.pdf output.pdf --rotate=+90:1  # Rotate page 1 by 90 degrees\n\n# Remove password\nqpdf --password=mypassword --decrypt encrypted.pdf decrypted.pdf\n```\n\n### pdftk (if available)\n```bash\n# Merge\npdftk file1.pdf file2.pdf cat output merged.pdf\n\n# Split\npdftk input.pdf burst\n\n# Rotate\npdftk input.pdf rotate 1east output rotated.pdf\n```\n\n## Common Tasks\n\n### Extract Text from Scanned PDFs\n```python\n# Requires: pip install pytesseract pdf2image\nimport pytesseract\nfrom pdf2image import convert_from_path\n\n# Convert PDF to images\nimages = convert_from_path('scanned.pdf')\n\n# OCR each page\ntext = \"\"\nfor i, image in enumerate(images):\n    text += f\"Page {i+1}:\\n\"\n    text += pytesseract.image_to_string(image)\n    text += \"\\n\\n\"\n\nprint(text)\n```\n\n### Add Watermark\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Create watermark (or load existing)\nwatermark = PdfReader(\"watermark.pdf\").pages[0]\n\n# Apply to all pages\nreader = PdfReader(\"document.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    page.merge_page(watermark)\n    writer.add_page(page)\n\nwith open(\"watermarked.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### Extract Images\n```bash\n# Using pdfimages (poppler-utils)\npdfimages -j input.pdf output_prefix\n\n# This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc.\n```\n\n### Password Protection\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    writer.add_page(page)\n\n# Add password\nwriter.encrypt(\"userpassword\", \"ownerpassword\")\n\nwith open(\"encrypted.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n## Quick Reference\n\n| Task | Best Tool | Command/Code |\n|------|-----------|--------------|\n| Merge PDFs | pypdf | `writer.add_page(page)` |\n| Split PDFs | pypdf | One page per file |\n| Extract text | pdfplumber | `page.extract_text()` |\n| Extract tables | pdfplumber | `page.extract_tables()` |\n| Create PDFs | reportlab | Canvas or Platypus |\n| Command line merge | qpdf | `qpdf --empty --pages ...` |\n| OCR scanned PDFs | pytesseract | Convert to image first |\n| Fill PDF forms | pdf-lib or pypdf (see forms.md) | See forms.md |\n\n## Next Steps\n\n- For advanced pypdfium2 usage, see reference.md\n- For JavaScript libraries (pdf-lib), see reference.md\n- If you need to fill out a PDF form, follow the instructions in forms.md\n- For troubleshooting guides, see reference.md\n","SKILLs/frontend-design/SKILL.md":"---\nname: frontend-design\ndescription: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.\nlicense: Complete terms in LICENSE.txt\nofficial: true\n---\n\nThis skill guides creation of distinctive, production-grade frontend interfaces that avoid generic \"AI slop\" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.\n\nThe user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.\n\n## Design Thinking\n\nBefore coding, understand the context and commit to a BOLD aesthetic direction:\n- **Purpose**: What problem does this interface solve? Who uses it?\n- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.\n- **Constraints**: Technical requirements (framework, performance, accessibility).\n- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?\n\n**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.\n\nThen implement working code (HTML/CSS/JS, React, Vue, etc.) that is:\n- Production-grade and functional\n- Visually striking and memorable\n- Cohesive with a clear aesthetic point-of-view\n- Meticulously refined in every detail\n\n## Frontend Aesthetics Guidelines\n\nFocus on:\n- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.\n- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.\n- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.\n- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.\n- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.\n\nNEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.\n\nInterpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.\n\n**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.\n\nRemember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.\n","SKILLs/imap-smtp-email/SKILL.md":"---\nname: imap-smtp-email\ndescription: Read and send email via IMAP/SMTP. Check for new/unread messages, fetch content, search mailboxes, mark as read/unread, and send emails with attachments. Works with any IMAP/SMTP server including Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, and vip.188.com.\nofficial: true\nversion: 1.0.7\n---\n\n# IMAP/SMTP Email Tool\n\nRead, search, and manage email via IMAP protocol. Send email via SMTP. Supports Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, vip.188.com, and any standard IMAP/SMTP server.\n\n## Important: Configuration is Pre-configured\n\nThe `accounts.json` configuration file is automatically managed by LobsterAI Settings (邮箱设置). Legacy `.env` configuration is still supported as a fallback for older users. **Do NOT ask the user to create or edit these files — just run the commands directly.** If credentials are wrong, the scripts will return a clear error message; only then should you inform the user to check their email settings.\n\nThe configuration files are located in this skill's directory (same folder as this SKILL.md file). The scripts load them automatically via absolute paths, regardless of the current working directory.\n\nUse the provided scripts as the only email transport interface. Do not write temporary IMAP/SMTP scripts, do not use raw sockets, OpenSSL, `net`, `tls`, or alternate mail clients, and do not inspect `.env`, `accounts.json`, or script source unless the official command output explicitly reports missing configuration and the user asks you to diagnose it. If an official command fails or times out, report that command result and suggest checking LobsterAI Settings; do not implement a fallback protocol client.\n\nDo not claim that `node-imap`, `nodemailer`, or another dependency is broken unless an official script or verified stack trace proves it. A successful command means the configured email account works; a timeout means the current command timed out, not that the dependency is defective.\n\nCommand results intentionally redact account metadata. In user-facing replies, use the redacted account label/email from the JSON result and do not repeat full configured email addresses unless the user explicitly asks for the exact address. Email content fields such as sender, subject, and message body may still be shown when they are the requested result.\n\nNever ask the user to send an email authorization code, app password, account password, or other credential in chat. If an account is disabled, incomplete, or has invalid credentials, ask the user to enable or update it in LobsterAI Settings > Email Settings, then rerun the official command.\n\nFor multi-account setups:\n- Run `node scripts/imap.js accounts` or `node scripts/smtp.js accounts` to list configured account IDs without exposing secrets.\n- Omit `--account` to use the default enabled account.\n- Pass `--account <id>` to use a specific account.\n- Pass `--all-accounts` only for read/list commands that support fan-out (`check`, `search`, `list-mailboxes`).\n- JSON results for read/list commands include `success`, redacted account metadata, `command`, `count`, and result arrays such as `messages` or `mailboxes`.\n\nFor sending email, always review recipient, subject, sender account, and body with the user first. Sending is blocked unless `--confirmed` is passed.\n\nFor SMTP send results, `success: true` means the sending SMTP server accepted the message for processing. Do not claim final delivery or inbox receipt. Report it as \"submitted to the SMTP server\" and mention that the recipient provider may still reject it later via a bounce message. If `rejected` or `pending` recipients are present, call them out explicitly.\n\nNever use a redacted account email such as `ab***@example.com` as a recipient address. If the user asks to send to another configured email account, use that account's `id` with `--to-account <id>` so the script resolves the real address internally without exposing it.\n\n## Configuration Reference\n\nCreate `.env` in the skill folder or set environment variables:\n\n```bash\n# IMAP Configuration (receiving email)\nIMAP_HOST=imap.gmail.com          # Server hostname\nIMAP_PORT=993                     # Server port\nIMAP_USER=your@email.com\nIMAP_PASS=your_password\nIMAP_TLS=true                     # Use TLS/SSL connection\nIMAP_REJECT_UNAUTHORIZED=true     # Set to false for self-signed certs\nIMAP_MAILBOX=INBOX                # Default mailbox\n\n# SMTP Configuration (sending email)\nSMTP_HOST=smtp.gmail.com          # SMTP server hostname\nSMTP_PORT=587                     # SMTP port (587 for STARTTLS, 465 for SSL)\nSMTP_SECURE=false                 # true for SSL (465), false for STARTTLS (587)\nSMTP_USER=your@gmail.com          # Your email address\nSMTP_PASS=your_password           # Your password or app password\nSMTP_FROM=your@gmail.com          # Default sender email (optional)\nSMTP_REJECT_UNAUTHORIZED=true     # Set to false for self-signed certs\n```\n\n## Common Email Servers\n\n| Provider | IMAP Host | IMAP Port | SMTP Host | SMTP Port |\n|----------|-----------|-----------|-----------|-----------|\n| 163.com | imap.163.com | 993 | smtp.163.com | 465 |\n| vip.163.com | imap.vip.163.com | 993 | smtp.vip.163.com | 465 |\n| 126.com | imap.126.com | 993 | smtp.126.com | 465 |\n| vip.126.com | imap.vip.126.com | 993 | smtp.vip.126.com | 465 |\n| 188.com | imap.188.com | 993 | smtp.188.com | 465 |\n| vip.188.com | imap.vip.188.com | 993 | smtp.vip.188.com | 465 |\n| yeah.net | imap.yeah.net | 993 | smtp.yeah.net | 465 |\n| Gmail | imap.gmail.com | 993 | smtp.gmail.com | 587 |\n| Outlook | outlook.office365.com | 993 | smtp.office365.com | 587 |\n| QQ Mail | imap.qq.com | 993 | smtp.qq.com | 587 |\n\n**Important for 163.com:**\n- Use **authorization code** (授权码), not account password\n- Enable IMAP/SMTP in web settings first\n\n## IMAP Commands (Receiving Email)\n\n### accounts\nList configured email accounts without exposing passwords.\n\n```bash\nnode scripts/imap.js accounts\n```\n\n### check\nCheck for new/unread emails.\n\n```bash\nnode scripts/imap.js check [--limit 10] [--mailbox INBOX] [--recent 2h]\nnode scripts/imap.js check --all-accounts [--limit 10]\n```\n\nOptions:\n- `--account <id>`: Use a specific configured account\n- `--all-accounts`: Check every enabled account\n- `--limit <n>`: Max results (default: 10)\n- `--mailbox <name>`: Mailbox to check (default: INBOX)\n- `--recent <time>`: Only show emails from last X time (e.g., 30m, 2h, 7d)\n\n### fetch\nFetch full email content by UID.\n\n```bash\nnode scripts/imap.js fetch <uid> [--mailbox INBOX]\nnode scripts/imap.js fetch <uid> --account <id> [--mailbox INBOX]\n```\n\n### download\nDownload all attachments from an email, or a specific attachment.\n\n```bash\nnode scripts/imap.js download <uid> [--mailbox INBOX] [--dir <path>] [--file <filename>]\nnode scripts/imap.js download <uid> --account <id> [--mailbox INBOX] [--dir <path>] [--file <filename>]\n```\n\nOptions:\n- `--mailbox <name>`: Mailbox (default: INBOX)\n- `--dir <path>`: Output directory (default: current directory)\n- `--file <filename>`: Download only the specified attachment (default: download all)\n\n### search\nSearch emails with filters.\n\n```bash\nnode scripts/imap.js search [options]\n\nOptions:\n  --unseen           Only unread messages\n  --seen             Only read messages\n  --from <email>     From address contains\n  --subject <text>   Subject contains\n  --recent <time>    From last X time (e.g., 30m, 2h, 7d)\n  --since <date>     After date (YYYY-MM-DD)\n  --before <date>    Before date (YYYY-MM-DD)\n  --limit <n>        Max results (default: 20)\n  --mailbox <name>   Mailbox to search (default: INBOX)\n  --account <id>     Use a specific configured account\n  --all-accounts     Search every enabled account\n```\n\n### mark-read / mark-unread\nMark message(s) as read or unread.\n\n```bash\nnode scripts/imap.js mark-read <uid> [uid2 uid3...]\nnode scripts/imap.js mark-unread <uid> [uid2 uid3...]\nnode scripts/imap.js mark-read --account <id> <uid> [uid2 uid3...]\n```\n\n### list-mailboxes\nList all available mailboxes/folders.\n\n```bash\nnode scripts/imap.js list-mailboxes\nnode scripts/imap.js list-mailboxes --all-accounts\n```\n\n## SMTP Commands (Sending Email)\n\n### accounts\nList configured email accounts without exposing passwords.\n\n```bash\nnode scripts/smtp.js accounts\n```\n\n### send\nSubmit email via SMTP. A successful command means the SMTP server accepted the message for processing, not that the recipient inbox has received it.\n\n```bash\nnode scripts/smtp.js send --to <email> --subject <text> --confirmed [options]\n```\n\n**Required:**\n- `--to <email>`: Recipient (comma-separated for multiple)\n- `--subject <text>`: Email subject, or `--subject-file <file>`\n\n**Optional:**\n- `--body <text>`: Plain text body\n- `--html`: Send body as HTML\n- `--body-file <file>`: Read body from file\n- `--html-file <file>`: Read HTML from file\n- `--cc <email>`: CC recipients\n- `--bcc <email>`: BCC recipients\n- `--attach <file>`: Attachments (comma-separated)\n- `--from <email>`: Override default sender\n- `--account <id>`: Send from a specific configured account\n- `--to-account <id>`: Send to a configured account by ID without exposing its full email address\n- `--confirmed`: Required after the user confirms the email details\n\n**Examples:**\n```bash\n# Simple text email\nnode scripts/smtp.js send --to recipient@example.com --subject \"Hello\" --body \"World\"\n\n# HTML email\nnode scripts/smtp.js send --to recipient@example.com --subject \"Newsletter\" --html --body \"<h1>Welcome</h1>\"\n\n# Email with attachment\nnode scripts/smtp.js send --to recipient@example.com --subject \"Report\" --body \"Please find attached\" --attach report.pdf\n\n# Multiple recipients\nnode scripts/smtp.js send --to \"a@example.com,b@example.com\" --cc \"c@example.com\" --subject \"Update\" --body \"Team update\"\n\n# Send to another configured account by ID\nnode scripts/smtp.js send --account default --to-account account-2 --subject \"Hello\" --body \"World\"\n```\n\n### test\nTest SMTP connection by sending a test email to yourself.\n\n```bash\nnode scripts/smtp.js test\n```\n\n## Dependencies\n\n```bash\nnpm install\n```\n\n## Security Notes\n\n- Store credentials in `.env` (add to `.gitignore`)\n- For Gmail: use App Password if 2FA is enabled\n- For 163.com: use authorization code (授权码), not account password\n- Downloaded attachment filenames are normalized to a safe local filename and cannot create directories outside the account/UID download folder.\n\n## Troubleshooting\n\n**Connection timeout:**\n- Verify server is running and accessible\n- Check host/port configuration\n\n**Authentication failed:**\n- Verify username (usually full email address)\n- Check password is correct\n- For 163.com: use authorization code, not account password\n- For Gmail: use App Password if 2FA enabled\n\n**TLS/SSL errors:**\n- Match `IMAP_TLS`/`SMTP_SECURE` setting to server requirements\n- For self-signed certs: set `IMAP_REJECT_UNAUTHORIZED=false` or `SMTP_REJECT_UNAUTHORIZED=false`\n","SKILLs/local-tools/SKILL.md":"---\nname: local-tools\ndescription: Access local system resources including Calendar on macOS and Windows. Use this skill when you need to manage user's schedule directly on their device.\nofficial: true\n---\n\n# Local Tools Skill\n\n## When to Use This Skill\n\nUse the local-tools skill when you need to:\n\n- **Calendar Management** - View, create, update, or delete calendar events\n\n**Examples of when to use:**\n- User: \"Show me my schedule for tomorrow\"\n- User: \"Create a meeting at 3 PM\"\n- User: \"Search for calendar events containing 'project'\"\n- User: \"Delete tomorrow's meeting\"\n\n## How It Works\n\n```\n┌──────────┐    Bash/PowerShell    ┌─────────────────────────────────────────────────────────────┐\n│  Claude  │──────────────────────▶│  calendar.sh / calendar.ps1                                 │\n│          │                       │  ├─ macOS: osascript -l JavaScript (JXA) ──▶ Calendar.app   │\n│          │                       │  └─ Windows: PowerShell ──▶ Outlook COM API                 │\n└──────────┘                       └─────────────────────────────────────────────────────────────┘\n```\n\n**Architecture:**\n1. **CLI Scripts** - Platform-specific scripts, no HTTP server needed\n   - `calendar.sh` - Bash script for macOS\n   - `calendar.ps1` - PowerShell script for Windows\n\n2. **Local Calendar Access** - Direct access to system calendar\n   - macOS: Uses JXA (JavaScript for Automation) to control Calendar.app\n   - Windows: Uses PowerShell COM API to control Microsoft Outlook\n\n3. **JSON Output** - Structured data format for easy parsing\n\n## Platform Support\n\n| Platform | Implementation | Calendar App | Status |\n|----------|---------------|--------------|--------|\n| **macOS 10.10+** | JXA + Calendar.app | Calendar.app | ✅ Fully Supported |\n| **Windows 7+** | PowerShell + COM | Microsoft Outlook | ✅ Fully Supported |\n| **Linux** | - | - | ❌ Not Supported |\n\n## Permissions\n\n### macOS\n- Requires \"Calendar\" access permission\n- User will be prompted on first use\n- Can be managed in: System Settings > Privacy & Security > Calendar\n\n### Windows\n- Requires Microsoft Outlook to be installed\n- May require administrative privileges for COM access\n\n## Calendar Operations\n\n**IMPORTANT: How to Locate the Script**\n\nWhen you read this SKILL.md file using the Read tool, you receive its absolute path (e.g., `/Users/username/.../SKILLs/local-tools/SKILL.md`).\n\n**To construct the script path:**\n1. Take the directory of this SKILL.md file\n2. Append `/scripts/calendar.sh` (macOS) or `/scripts/calendar.ps1` (Windows)\n\n**Example:**\n```bash\n# If SKILL.md is at: /Users/username/path/to/SKILLs/local-tools/SKILL.md\n# Then the script is: /Users/username/path/to/SKILLs/local-tools/scripts/calendar.sh\n\nbash \"/Users/username/path/to/SKILLs/local-tools/scripts/calendar.sh\" <operation> [options]\n```\n\nIn all examples below, `<skill-dir>/scripts/calendar.sh` is a placeholder. Replace it with the actual absolute path.\n\n### Best Practices for AI Assistant\n\n**DO:**\n- ✅ Execute commands directly without showing trial-and-error process\n- ✅ If command fails, inform user about permission issues without showing technical errors\n- ✅ Use `search` command for searching birthdays/anniversaries\n- ✅ If no calendar name specified, script will automatically use first available calendar\n\n**DON'T:**\n- ❌ Don't repeatedly try different command combinations\n- ❌ Don't show error stacks or technical details to users\n- ❌ Don't read script source code to analyze issues\n- ❌ Don't ask users for calendar name, use default behavior\n\n**Example - Searching for birthdays:**\n```bash\n# Correct approach: Search directly, don't trial-and-error\nbash \"<skill-dir>/scripts/calendar.sh\" search --query \"birthday\"\n\n# If permission error returned, directly tell user:\n# \"Calendar access permission is required. Please open System Settings > Privacy & Security > Calendar, and authorize Terminal or LobsterAI\"\n```\n\n### List Events\n\n```bash\n# List events for next 7 days (default)\nbash \"<skill-dir>/scripts/calendar.sh\" list\n\n# List events for specific date range\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-12T00:00:00\" \\\n  --end \"2026-02-19T23:59:59\"\n\n# List events from specific calendar (macOS)\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --calendar \"Work\"\n```\n\n### Create Event\n\n```bash\n# Create a simple event\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Team Meeting\" \\\n  --start \"2026-02-13T14:00:00\" \\\n  --end \"2026-02-13T15:00:00\"\n\n# Create event with location and notes\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Client Call\" \\\n  --start \"2026-02-14T10:00:00\" \\\n  --end \"2026-02-14T11:00:00\" \\\n  --calendar \"Work\" \\\n  --location \"Conference Room A\" \\\n  --notes \"Discuss Q1 roadmap\"\n```\n\n### Update Event\n\n```bash\n# Update event title\nbash \"<skill-dir>/scripts/calendar.sh\" update \\\n  --id \"EVENT-ID\" \\\n  --title \"Updated Meeting Title\"\n\n# Update event time\nbash \"<skill-dir>/scripts/calendar.sh\" update \\\n  --id \"EVENT-ID\" \\\n  --start \"2026-02-13T15:00:00\" \\\n  --end \"2026-02-13T16:00:00\"\n```\n\n### Delete Event\n\n```bash\nbash \"<skill-dir>/scripts/calendar.sh\" delete \\\n  --id \"EVENT-ID\"\n```\n\n### Search Events\n\n```bash\n# Search for events containing keyword (searches ALL calendars)\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"meeting\"\n\n# Search in specific calendar only\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"project\" \\\n  --calendar \"Work\"\n```\n\n**Note:** When `--calendar` is not specified, the search operation will look through **all available calendars** on both macOS and Windows.\n\n## Output Format\n\nAll commands return JSON with the following structure:\n\n### Success Response\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"events\": [\n      {\n        \"eventId\": \"E621F8C4-...\",\n        \"title\": \"Team Meeting\",\n        \"startTime\": \"2026-02-13T14:00:00.000Z\",\n        \"endTime\": \"2026-02-13T15:00:00.000Z\",\n        \"location\": \"Conference Room\",\n        \"notes\": \"Weekly sync\",\n        \"calendar\": \"Work\",\n        \"allDay\": false\n      }\n    ],\n    \"count\": 1\n  }\n}\n```\n\n### Error Response\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CALENDAR_ACCESS_ERROR\",\n    \"message\": \"Calendar access permission is required...\",\n    \"recoverable\": true,\n    \"permissionRequired\": true\n  }\n}\n```\n\n### Error Codes\n\n| Code | Meaning | Recoverable |\n|------|---------|-------------|\n| `CALENDAR_ACCESS_ERROR` | Permission denied or calendar not accessible | Yes |\n| `INVALID_INPUT` | Missing required parameters | No |\n| `EVENT_NOT_FOUND` | Event ID not found | No |\n| `OUTLOOK_NOT_AVAILABLE` | Microsoft Outlook not installed (Windows) | Yes |\n\n## Date Format Guidelines\n\n### Important: Date Format Guidelines\n\nWhen using the `list` command with time ranges:\n\n1. **Always use ISO 8601 format**: `YYYY-MM-DDTHH:mm:ss`\n2. **Use local timezone**: Do NOT use UTC or timezone suffixes (like +08:00 or Z)\n3. **Calculate dates yourself**: Do NOT use shell command substitution like `$(date ...)`\n4. **Claude should compute dates**: Based on current date, calculate target dates directly\n5. **Examples**:\n   - Today at midnight: `2026-02-13T00:00:00`\n   - Today at end of day: `2026-02-13T23:59:59`\n   - Tomorrow morning: `2026-02-14T09:00:00`\n   - Next week Monday: `2026-02-16T00:00:00`\n\n**Why**: The script expects local time strings that match your system timezone. Shell substitutions may not execute correctly in all environments.\n\n## Common Patterns\n\n### Pattern 1: Schedule Management\n\n```bash\n# User asks: \"What meetings do I have today?\"\n# Claude's approach: Calculate today's date and query full day from 00:00 to 23:59\n# IMPORTANT: Claude should replace 2026-02-13 with the actual current date\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-13T00:00:00\" \\\n  --end \"2026-02-13T23:59:59\"\n\n# User asks: \"What's on my schedule tomorrow?\"\n# Claude should calculate tomorrow's date (e.g., if today is 2026-02-13, tomorrow is 2026-02-14)\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-14T00:00:00\" \\\n  --end \"2026-02-14T23:59:59\"\n```\n\n### Pattern 2: Meeting Scheduling\n\n```bash\n# User asks: \"Schedule a meeting for tomorrow at 3 PM\"\n# Claude's approach:\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Meeting\" \\\n  --start \"2026-02-13T15:00:00\" \\\n  --end \"2026-02-13T16:00:00\" \\\n  --calendar \"Work\"\n```\n\n### Pattern 3: Event Search\n\n```bash\n# User asks: \"Find all meetings about the project\"\n# Claude's approach:\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"project\" \\\n  --calendar \"Work\"\n```\n\n### Pattern 4: Availability Check\n\n```bash\n# User asks: \"Am I free tomorrow afternoon?\"\n# Claude's approach:\n# 1. List tomorrow's events\n# 2. Analyze time slots\n# 3. Report availability\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-14T00:00:00\" \\\n  --end \"2026-02-14T23:59:59\"\n```\n\n## Known Behaviors\n\n### Time Range Matching\n\nThe `list` command uses **interval overlap detection**:\n- Returns events that have **any overlap** with the query time range\n- Does NOT require events to be fully contained within the range\n\n**Examples:**\n- Query: 2026-02-13 00:00:00 to 23:59:59\n- Returns:\n  - ✅ Events fully on Feb 13 (e.g., 10:00-11:00)\n  - ✅ Multi-day events spanning Feb 13 (e.g., Feb 12 10:00 - Feb 14 10:00)\n  - ✅ Events crossing midnight (e.g., Feb 13 23:30 - Feb 14 00:30)\n  - ❌ Events entirely before Feb 13 (e.g., Feb 12 10:00-11:00)\n  - ❌ Events entirely after Feb 13 (e.g., Feb 14 10:00-11:00)\n\n### All-Day Events\n\n- Treated as spanning from 00:00:00 to 23:59:59 on their date(s)\n- Multi-day all-day events (e.g., Feb 12-14) will appear when querying any date within that range\n\n### Time Precision\n\n- Comparisons use second-level precision\n- Milliseconds are ignored in date comparisons\n\n### Recurring Events\n\n- Each occurrence is treated as a separate event instance\n- The script returns individual occurrences within the queried time range\n\n## Best Practices\n\n### 1. Always Check Before Creating\n\nBefore creating an event, list existing events to avoid conflicts:\n\n```bash\n# First check existing events\nbash \"<skill-dir>/scripts/calendar.sh\" list\n\n# Then create if no conflict\nbash \"<skill-dir>/scripts/calendar.sh\" create ...\n```\n\n### 2. Use Specific Calendars (macOS)\n\nSpecify the calendar to keep events organized:\n\n```bash\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Team Meeting\" \\\n  --calendar \"Work\" \\\n  ...\n```\n\n### 3. Search Before Updating/Deleting\n\nAlways search first to get the correct event ID:\n\n```bash\n# Search to find event ID\nbash \"<skill-dir>/scripts/calendar.sh\" search --query \"meeting\"\n\n# Then update or delete\nbash \"<skill-dir>/scripts/calendar.sh\" update --id \"FOUND-ID\" ...\n```\n\n### 4. Handle Errors Gracefully\n\nParse the response and handle errors:\n\n```bash\nresult=$(bash \"<skill-dir>/scripts/calendar.sh\" list)\nif echo \"$result\" | grep -q '\"success\":true'; then\n  # Process events\n  events=$(echo \"$result\" | jq '.data.events')\nelse\n  # Handle error\n  error=$(echo \"$result\" | jq '.error.message')\n  echo \"Failed: $error\"\nfi\n```\n\n## Limitations\n\n### macOS\n- Requires macOS 10.10 Yosemite or later (for JXA support)\n- Requires Calendar access permission\n- Does not support advanced recurring event queries\n- Cannot modify recurring event rules\n\n### Windows\n- Requires Microsoft Outlook to be installed\n- Does not support other calendar applications (Windows Calendar, Google Calendar, etc.)\n- May require COM access permissions in corporate environments\n- Folder enumeration may skip restricted calendars\n\n### General\n- All dates must be in ISO 8601 format (`YYYY-MM-DDTHH:mm:ss`)\n- Uses local timezone for all operations\n- Return values are converted to UTC (ISO 8601 with Z suffix)\n- No support for attendees or meeting invitations\n\n## Troubleshooting\n\n### macOS\n\n**Permission Denied:**\n```\nError: Calendar access permission is required\n```\n**Solution:** Open System Settings > Privacy & Security > Calendar, authorize Terminal or LobsterAI\n\n**Script Not Found:**\n```\nbash: calendar.sh: No such file or directory\n```\n**Solution:** Ensure you're using the absolute path from SKILL.md's directory + `/scripts/calendar.sh`\n\n### Windows\n\n**Outlook Not Found:**\n```\nError: Microsoft Outlook is not installed or not accessible\n```\n**Solution:** Install Microsoft Outlook and ensure it's properly configured\n\n**PowerShell Execution Policy:**\n```\nError: Execution of scripts is disabled on this system\n```\n**Solution:** Run PowerShell as Administrator and execute:\n```powershell\nSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser\n```\n\n## Technical Details\n\n### macOS Implementation\n\n**JXA (JavaScript for Automation):**\n- Uses `osascript -l JavaScript` to execute JXA code\n- Controls Calendar.app via Apple Events\n- Works on both Intel and Apple Silicon Macs\n- Requires user permission for Calendar access\n\n**Date Handling:**\n- Uses BSD date command (macOS native)\n- Format: `date +%Y-%m-%dT%H:%M:%S` (local timezone)\n- Relative dates: `date -v+7d` (7 days from now)\n\n### Windows Implementation\n\n**PowerShell + COM:**\n- Uses Outlook COM API via PowerShell\n- Requires Outlook to be installed and configured\n- Works with all Outlook-compatible calendars\n\n**Date Handling:**\n- Uses PowerShell `[DateTime]::Parse()` for date parsing\n- Automatically handles local timezone\n\n### Cross-Platform Consistency\n\nBoth implementations:\n- Use identical JSON output format\n- Support the same operations (list, create, update, delete, search)\n- Handle dates in local timezone\n- Return UTC timestamps in ISO 8601 format\n\n## Related Skills\n\n- **imap-smtp-email** - For email-based meeting invitations\n","SKILLs/films-search/SKILL.md":"# films-search\n\nPath: `SKILLs/films-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/films-search/SKILL.md)","SKILLs/docx/SKILL.md":"# docx\n\nPath: `SKILLs/docx/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/SKILL.md)","SKILLs/develop-web-game/SKILL.md":"# develop-web-game\n\nPath: `SKILLs/develop-web-game/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/SKILL.md)","SKILLs/daily-trending/SKILL.md":"# daily-trending\n\nPath: `SKILLs/daily-trending/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/daily-trending/SKILL.md)","SKILLs/create-plan/SKILL.md":"# create-plan\n\nPath: `SKILLs/create-plan/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/create-plan/SKILL.md)","SKILLs/content-planner/SKILL.md":"# content-planner\n\nPath: `SKILLs/content-planner/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/content-planner/SKILL.md)","SKILLs/canvas-design/SKILL.md":"# canvas-design\n\nPath: `SKILLs/canvas-design/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/canvas-design/SKILL.md)","SKILLs/article-writer/SKILL.md":"# article-writer\n\nPath: `SKILLs/article-writer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/article-writer/SKILL.md)","SKILLs/stock-analyzer/SKILL.md":"# stock-analyzer\n\nPath: `SKILLs/stock-analyzer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-analyzer/SKILL.md)","SKILLs/stock-announcements/SKILL.md":"# stock-announcements\n\nPath: `SKILLs/stock-announcements/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-announcements/SKILL.md)","SKILLs/stock-explorer/SKILL.md":"# stock-explorer\n\nPath: `SKILLs/stock-explorer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-explorer/SKILL.md)","SKILLs/technology-news-search/SKILL.md":"# technology-news-search\n\nPath: `SKILLs/technology-news-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/technology-news-search/SKILL.md)","SKILLs/weather/SKILL.md":"# weather\n\nPath: `SKILLs/weather/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/weather/SKILL.md)","SKILLs/web-search/SKILL.md":"# web-search\n\nPath: `SKILLs/web-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/SKILL.md)","SKILLs/xlsx/SKILL.md":"# xlsx\n\nPath: `SKILLs/xlsx/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/xlsx/SKILL.md)","SKILLs/youdaonote/SKILL.md":"# youdaonote\n\nPath: `SKILLs/youdaonote/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/youdaonote/SKILL.md)","AGENTS.md":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/AGENTS.md)","SKILLs/skills.config.json":"# SKILLs Skill\n\nPath: `SKILLs/skills.config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skills.config.json)","openclaw-extensions/mcp-bridge/openclaw.plugin.json":"# mcp-bridge Plugin Manifest\n\nPath: `openclaw-extensions/mcp-bridge/openclaw.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/openclaw-extensions/mcp-bridge/openclaw.plugin.json)","openclaw-extensions/ask-user-question/openclaw.plugin.json":"# ask-user-question Plugin Manifest\n\nPath: `openclaw-extensions/ask-user-question/openclaw.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/openclaw-extensions/ask-user-question/openclaw.plugin.json)","SKILLs/skill-vetter/_meta.json":"# Skill-vetter Skill\n\nPath: `SKILLs/skill-vetter/_meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-vetter/_meta.json)","SKILLs/pptx/html2pptx.md":"# Pptx Skill\n\nPath: `SKILLs/pptx/html2pptx.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/html2pptx.md)","SKILLs/pptx/ooxml.md":"# Pptx Skill\n\nPath: `SKILLs/pptx/ooxml.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/ooxml.md)","SKILLs/pptx/package.json":"# Pptx Skill\n\nPath: `SKILLs/pptx/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/package.json)","SKILLs/pdf/forms.md":"# Pdf Skill\n\nPath: `SKILLs/pdf/forms.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/forms.md)","SKILLs/pdf/reference.md":"# Pdf Skill\n\nPath: `SKILLs/pdf/reference.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/reference.md)","SKILLs/imap-smtp-email/_meta.json":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/_meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/_meta.json)","SKILLs/imap-smtp-email/package.json":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/package.json)","SKILLs/imap-smtp-email/README.md":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/README.md)","SKILLs/docx/docx-js.md":"# Docx Skill\n\nPath: `SKILLs/docx/docx-js.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/docx-js.md)","SKILLs/docx/ooxml.md":"# Docx Skill\n\nPath: `SKILLs/docx/ooxml.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/ooxml.md)","SKILLs/web-search/DEPLOYMENT.md":"# Web-search Skill\n\nPath: `SKILLs/web-search/DEPLOYMENT.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/DEPLOYMENT.md)","SKILLs/web-search/IMPLEMENTATION.md":"# Web-search Skill\n\nPath: `SKILLs/web-search/IMPLEMENTATION.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/IMPLEMENTATION.md)","SKILLs/web-search/package.json":"# Web-search Skill\n\nPath: `SKILLs/web-search/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/package.json)","SKILLs/web-search/README.md":"# Web-search Skill\n\nPath: `SKILLs/web-search/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/README.md)","SKILLs/web-search/TEST.md":"# Web-search Skill\n\nPath: `SKILLs/web-search/TEST.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/TEST.md)","SKILLs/web-search/tsconfig.json":"# Web-search Skill\n\nPath: `SKILLs/web-search/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/tsconfig.json)","SKILLs/skill-creator/agents/analyzer.md":"# Subagent: analyzer\n\nPath: `SKILLs/skill-creator/agents/analyzer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/analyzer.md)","SKILLs/skill-creator/agents/comparator.md":"# Subagent: comparator\n\nPath: `SKILLs/skill-creator/agents/comparator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/comparator.md)","SKILLs/skill-creator/agents/grader.md":"# Subagent: grader\n\nPath: `SKILLs/skill-creator/agents/grader.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/grader.md)","SKILLs/skill-creator/references/schemas.md":"# References Skill\n\nPath: `SKILLs/skill-creator/references/schemas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/references/schemas.md)","SKILLs/remotion/rules/3d.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/3d.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/3d.md)","SKILLs/remotion/rules/animations.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/animations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/animations.md)","SKILLs/remotion/rules/assets.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/assets.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/assets.md)","SKILLs/remotion/rules/audio.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/audio.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/audio.md)","SKILLs/remotion/rules/calculate-metadata.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/calculate-metadata.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/calculate-metadata.md)","SKILLs/remotion/rules/can-decode.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/can-decode.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/can-decode.md)","SKILLs/remotion/rules/charts.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/charts.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/charts.md)","SKILLs/remotion/rules/compositions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/compositions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/compositions.md)","SKILLs/remotion/rules/display-captions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/display-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/display-captions.md)","SKILLs/remotion/rules/extract-frames.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/extract-frames.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/extract-frames.md)","SKILLs/remotion/rules/fonts.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/fonts.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/fonts.md)","SKILLs/remotion/rules/get-audio-duration.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-audio-duration.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-audio-duration.md)","SKILLs/remotion/rules/get-video-dimensions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-video-dimensions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-video-dimensions.md)","SKILLs/remotion/rules/get-video-duration.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-video-duration.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-video-duration.md)","SKILLs/remotion/rules/gifs.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/gifs.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/gifs.md)","SKILLs/remotion/rules/images.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/images.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/images.md)","SKILLs/remotion/rules/import-srt-captions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/import-srt-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/import-srt-captions.md)","SKILLs/remotion/rules/light-leaks.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/light-leaks.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/light-leaks.md)","SKILLs/remotion/rules/lottie.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/lottie.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/lottie.md)","SKILLs/remotion/rules/maps.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/maps.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/maps.md)","SKILLs/remotion/rules/measuring-dom-nodes.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/measuring-dom-nodes.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/measuring-dom-nodes.md)","SKILLs/remotion/rules/measuring-text.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/measuring-text.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/measuring-text.md)","SKILLs/remotion/rules/parameters.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/parameters.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/parameters.md)","SKILLs/remotion/rules/sequencing.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/sequencing.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/sequencing.md)","SKILLs/remotion/rules/subtitles.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/subtitles.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/subtitles.md)","SKILLs/remotion/rules/tailwind.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/tailwind.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/tailwind.md)","SKILLs/remotion/rules/text-animations.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/text-animations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/text-animations.md)","SKILLs/remotion/rules/timing.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/timing.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/timing.md)","SKILLs/remotion/rules/transcribe-captions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transcribe-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transcribe-captions.md)","SKILLs/remotion/rules/transitions.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transitions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transitions.md)","SKILLs/remotion/rules/transparent-videos.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transparent-videos.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transparent-videos.md)","SKILLs/remotion/rules/trimming.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/trimming.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/trimming.md)","SKILLs/remotion/rules/videos.md":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/videos.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/videos.md)","SKILLs/playwright/agents/openai.yaml":"# Agents Skill\n\nPath: `SKILLs/playwright/agents/openai.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/agents/openai.yaml)","SKILLs/playwright/references/cli.md":"# References Skill\n\nPath: `SKILLs/playwright/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/cli.md)","SKILLs/playwright/references/workflows.md":"# References Skill\n\nPath: `SKILLs/playwright/references/workflows.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/workflows.md)","SKILLs/develop-web-game/agents/openai.yaml":"# Agents Skill\n\nPath: `SKILLs/develop-web-game/agents/openai.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/agents/openai.yaml)","SKILLs/develop-web-game/references/action_payloads.json":"# References Skill\n\nPath: `SKILLs/develop-web-game/references/action_payloads.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/references/action_payloads.json)","SKILLs/technology-news-search/references/sources.json":"# References Skill\n\nPath: `SKILLs/technology-news-search/references/sources.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/technology-news-search/references/sources.json)","SKILLs/web-search/examples/basic-search.md":"# Examples Skill\n\nPath: `SKILLs/web-search/examples/basic-search.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/examples/basic-search.md)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/AGENTS.md)","tokens":300,"sizeBytes":158},{"name":"SKILL.md","path":"SKILLs/article-writer/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/article-writer/SKILL.md","title":"article-writer","category":"anthropic-skill","format":"markdown","content":"# article-writer\n\nPath: `SKILLs/article-writer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/article-writer/SKILL.md)","tokens":300,"sizeBytes":182},{"name":"SKILL.md","path":"SKILLs/canvas-design/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/canvas-design/SKILL.md","title":"canvas-design","category":"anthropic-skill","format":"markdown","content":"# canvas-design\n\nPath: `SKILLs/canvas-design/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/canvas-design/SKILL.md)","tokens":300,"sizeBytes":179},{"name":"SKILL.md","path":"SKILLs/content-planner/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/content-planner/SKILL.md","title":"content-planner","category":"anthropic-skill","format":"markdown","content":"# content-planner\n\nPath: `SKILLs/content-planner/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/content-planner/SKILL.md)","tokens":300,"sizeBytes":185},{"name":"SKILL.md","path":"SKILLs/create-plan/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/create-plan/SKILL.md","title":"create-plan","category":"anthropic-skill","format":"markdown","content":"# create-plan\n\nPath: `SKILLs/create-plan/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/create-plan/SKILL.md)","tokens":300,"sizeBytes":173},{"name":"SKILL.md","path":"SKILLs/daily-trending/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/daily-trending/SKILL.md","title":"daily-trending","category":"anthropic-skill","format":"markdown","content":"# daily-trending\n\nPath: `SKILLs/daily-trending/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/daily-trending/SKILL.md)","tokens":300,"sizeBytes":182},{"name":"openai.yaml","path":"SKILLs/develop-web-game/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"# Agents Skill\n\nPath: `SKILLs/develop-web-game/agents/openai.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/agents/openai.yaml)","tokens":300,"sizeBytes":204},{"name":"action_payloads.json","path":"SKILLs/develop-web-game/references/action_payloads.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/references/action_payloads.json","title":"References Skill","category":"anthropic-skill","format":"json","content":"# References Skill\n\nPath: `SKILLs/develop-web-game/references/action_payloads.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/references/action_payloads.json)","tokens":300,"sizeBytes":234},{"name":"SKILL.md","path":"SKILLs/develop-web-game/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/SKILL.md","title":"develop-web-game","category":"anthropic-skill","format":"markdown","content":"# develop-web-game\n\nPath: `SKILLs/develop-web-game/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/SKILL.md)","tokens":300,"sizeBytes":188},{"name":"docx-js.md","path":"SKILLs/docx/docx-js.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/docx-js.md","title":"Docx Skill","category":"anthropic-skill","format":"markdown","content":"# Docx Skill\n\nPath: `SKILLs/docx/docx-js.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/docx-js.md)","tokens":300,"sizeBytes":162},{"name":"ooxml.md","path":"SKILLs/docx/ooxml.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/ooxml.md","title":"Docx Skill","category":"anthropic-skill","format":"markdown","content":"# Docx Skill\n\nPath: `SKILLs/docx/ooxml.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/ooxml.md)","tokens":300,"sizeBytes":158},{"name":"SKILL.md","path":"SKILLs/docx/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/SKILL.md","title":"docx","category":"anthropic-skill","format":"markdown","content":"# docx\n\nPath: `SKILLs/docx/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/SKILL.md)","tokens":300,"sizeBytes":152},{"name":"SKILL.md","path":"SKILLs/films-search/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/films-search/SKILL.md","title":"films-search","category":"anthropic-skill","format":"markdown","content":"# films-search\n\nPath: `SKILLs/films-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/films-search/SKILL.md)","tokens":300,"sizeBytes":176},{"name":"SKILL.md","path":"SKILLs/frontend-design/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/frontend-design/SKILL.md","title":"frontend-design","category":"anthropic-skill","format":"markdown","content":"---\nname: frontend-design\ndescription: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.\nlicense: Complete terms in LICENSE.txt\nofficial: true\n---\n\nThis skill guides creation of distinctive, production-grade frontend interfaces that avoid generic \"AI slop\" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.\n\nThe user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.\n\n## Design Thinking\n\nBefore coding, understand the context and commit to a BOLD aesthetic direction:\n- **Purpose**: What problem does this interface solve? Who uses it?\n- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.\n- **Constraints**: Technical requirements (framework, performance, accessibility).\n- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?\n\n**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.\n\nThen implement working code (HTML/CSS/JS, React, Vue, etc.) that is:\n- Production-grade and functional\n- Visually striking and memorable\n- Cohesive with a clear aesthetic point-of-view\n- Meticulously refined in every detail\n\n## Frontend Aesthetics Guidelines\n\nFocus on:\n- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.\n- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.\n- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.\n- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.\n- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.\n\nNEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.\n\nInterpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.\n\n**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.\n\nRemember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.\n","frontmatter":{"name":"frontend-design","description":"Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.","license":"Complete terms in LICENSE.txt","official":true},"isInternal":false,"tokens":862,"sizeBytes":4455},{"name":"_meta.json","path":"SKILLs/imap-smtp-email/_meta.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/_meta.json","title":"Imap-smtp-email Skill","category":"anthropic-skill","format":"json","content":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/_meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/_meta.json)","tokens":300,"sizeBytes":195},{"name":"package.json","path":"SKILLs/imap-smtp-email/package.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/package.json","title":"Imap-smtp-email Skill","category":"anthropic-skill","format":"json","content":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/package.json)","tokens":300,"sizeBytes":199},{"name":"README.md","path":"SKILLs/imap-smtp-email/README.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/README.md","title":"Imap-smtp-email Skill","category":"anthropic-skill","format":"markdown","content":"# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/README.md)","tokens":300,"sizeBytes":193},{"name":"SKILL.md","path":"SKILLs/imap-smtp-email/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/SKILL.md","title":"imap-smtp-email","category":"anthropic-skill","format":"markdown","content":"---\nname: imap-smtp-email\ndescription: Read and send email via IMAP/SMTP. Check for new/unread messages, fetch content, search mailboxes, mark as read/unread, and send emails with attachments. Works with any IMAP/SMTP server including Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, and vip.188.com.\nofficial: true\nversion: 1.0.7\n---\n\n# IMAP/SMTP Email Tool\n\nRead, search, and manage email via IMAP protocol. Send email via SMTP. Supports Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, vip.188.com, and any standard IMAP/SMTP server.\n\n## Important: Configuration is Pre-configured\n\nThe `accounts.json` configuration file is automatically managed by LobsterAI Settings (邮箱设置). Legacy `.env` configuration is still supported as a fallback for older users. **Do NOT ask the user to create or edit these files — just run the commands directly.** If credentials are wrong, the scripts will return a clear error message; only then should you inform the user to check their email settings.\n\nThe configuration files are located in this skill's directory (same folder as this SKILL.md file). The scripts load them automatically via absolute paths, regardless of the current working directory.\n\nUse the provided scripts as the only email transport interface. Do not write temporary IMAP/SMTP scripts, do not use raw sockets, OpenSSL, `net`, `tls`, or alternate mail clients, and do not inspect `.env`, `accounts.json`, or script source unless the official command output explicitly reports missing configuration and the user asks you to diagnose it. If an official command fails or times out, report that command result and suggest checking LobsterAI Settings; do not implement a fallback protocol client.\n\nDo not claim that `node-imap`, `nodemailer`, or another dependency is broken unless an official script or verified stack trace proves it. A successful command means the configured email account works; a timeout means the current command timed out, not that the dependency is defective.\n\nCommand results intentionally redact account metadata. In user-facing replies, use the redacted account label/email from the JSON result and do not repeat full configured email addresses unless the user explicitly asks for the exact address. Email content fields such as sender, subject, and message body may still be shown when they are the requested result.\n\nNever ask the user to send an email authorization code, app password, account password, or other credential in chat. If an account is disabled, incomplete, or has invalid credentials, ask the user to enable or update it in LobsterAI Settings > Email Settings, then rerun the official command.\n\nFor multi-account setups:\n- Run `node scripts/imap.js accounts` or `node scripts/smtp.js accounts` to list configured account IDs without exposing secrets.\n- Omit `--account` to use the default enabled account.\n- Pass `--account <id>` to use a specific account.\n- Pass `--all-accounts` only for read/list commands that support fan-out (`check`, `search`, `list-mailboxes`).\n- JSON results for read/list commands include `success`, redacted account metadata, `command`, `count`, and result arrays such as `messages` or `mailboxes`.\n\nFor sending email, always review recipient, subject, sender account, and body with the user first. Sending is blocked unless `--confirmed` is passed.\n\nFor SMTP send results, `success: true` means the sending SMTP server accepted the message for processing. Do not claim final delivery or inbox receipt. Report it as \"submitted to the SMTP server\" and mention that the recipient provider may still reject it later via a bounce message. If `rejected` or `pending` recipients are present, call them out explicitly.\n\nNever use a redacted account email such as `ab***@example.com` as a recipient address. If the user asks to send to another configured email account, use that account's `id` with `--to-account <id>` so the script resolves the real address internally without exposing it.\n\n## Configuration Reference\n\nCreate `.env` in the skill folder or set environment variables:\n\n```bash\n# IMAP Configuration (receiving email)\nIMAP_HOST=imap.gmail.com          # Server hostname\nIMAP_PORT=993                     # Server port\nIMAP_USER=your@email.com\nIMAP_PASS=your_password\nIMAP_TLS=true                     # Use TLS/SSL connection\nIMAP_REJECT_UNAUTHORIZED=true     # Set to false for self-signed certs\nIMAP_MAILBOX=INBOX                # Default mailbox\n\n# SMTP Configuration (sending email)\nSMTP_HOST=smtp.gmail.com          # SMTP server hostname\nSMTP_PORT=587                     # SMTP port (587 for STARTTLS, 465 for SSL)\nSMTP_SECURE=false                 # true for SSL (465), false for STARTTLS (587)\nSMTP_USER=your@gmail.com          # Your email address\nSMTP_PASS=your_password           # Your password or app password\nSMTP_FROM=your@gmail.com          # Default sender email (optional)\nSMTP_REJECT_UNAUTHORIZED=true     # Set to false for self-signed certs\n```\n\n## Common Email Servers\n\n| Provider | IMAP Host | IMAP Port | SMTP Host | SMTP Port |\n|----------|-----------|-----------|-----------|-----------|\n| 163.com | imap.163.com | 993 | smtp.163.com | 465 |\n| vip.163.com | imap.vip.163.com | 993 | smtp.vip.163.com | 465 |\n| 126.com | imap.126.com | 993 | smtp.126.com | 465 |\n| vip.126.com | imap.vip.126.com | 993 | smtp.vip.126.com | 465 |\n| 188.com | imap.188.com | 993 | smtp.188.com | 465 |\n| vip.188.com | imap.vip.188.com | 993 | smtp.vip.188.com | 465 |\n| yeah.net | imap.yeah.net | 993 | smtp.yeah.net | 465 |\n| Gmail | imap.gmail.com | 993 | smtp.gmail.com | 587 |\n| Outlook | outlook.office365.com | 993 | smtp.office365.com | 587 |\n| QQ Mail | imap.qq.com | 993 | smtp.qq.com | 587 |\n\n**Important for 163.com:**\n- Use **authorization code** (授权码), not account password\n- Enable IMAP/SMTP in web settings first\n\n## IMAP Commands (Receiving Email)\n\n### accounts\nList configured email accounts without exposing passwords.\n\n```bash\nnode scripts/imap.js accounts\n```\n\n### check\nCheck for new/unread emails.\n\n```bash\nnode scripts/imap.js check [--limit 10] [--mailbox INBOX] [--recent 2h]\nnode scripts/imap.js check --all-accounts [--limit 10]\n```\n\nOptions:\n- `--account <id>`: Use a specific configured account\n- `--all-accounts`: Check every enabled account\n- `--limit <n>`: Max results (default: 10)\n- `--mailbox <name>`: Mailbox to check (default: INBOX)\n- `--recent <time>`: Only show emails from last X time (e.g., 30m, 2h, 7d)\n\n### fetch\nFetch full email content by UID.\n\n```bash\nnode scripts/imap.js fetch <uid> [--mailbox INBOX]\nnode scripts/imap.js fetch <uid> --account <id> [--mailbox INBOX]\n```\n\n### download\nDownload all attachments from an email, or a specific attachment.\n\n```bash\nnode scripts/imap.js download <uid> [--mailbox INBOX] [--dir <path>] [--file <filename>]\nnode scripts/imap.js download <uid> --account <id> [--mailbox INBOX] [--dir <path>] [--file <filename>]\n```\n\nOptions:\n- `--mailbox <name>`: Mailbox (default: INBOX)\n- `--dir <path>`: Output directory (default: current directory)\n- `--file <filename>`: Download only the specified attachment (default: download all)\n\n### search\nSearch emails with filters.\n\n```bash\nnode scripts/imap.js search [options]\n\nOptions:\n  --unseen           Only unread messages\n  --seen             Only read messages\n  --from <email>     From address contains\n  --subject <text>   Subject contains\n  --recent <time>    From last X time (e.g., 30m, 2h, 7d)\n  --since <date>     After date (YYYY-MM-DD)\n  --before <date>    Before date (YYYY-MM-DD)\n  --limit <n>        Max results (default: 20)\n  --mailbox <name>   Mailbox to search (default: INBOX)\n  --account <id>     Use a specific configured account\n  --all-accounts     Search every enabled account\n```\n\n### mark-read / mark-unread\nMark message(s) as read or unread.\n\n```bash\nnode scripts/imap.js mark-read <uid> [uid2 uid3...]\nnode scripts/imap.js mark-unread <uid> [uid2 uid3...]\nnode scripts/imap.js mark-read --account <id> <uid> [uid2 uid3...]\n```\n\n### list-mailboxes\nList all available mailboxes/folders.\n\n```bash\nnode scripts/imap.js list-mailboxes\nnode scripts/imap.js list-mailboxes --all-accounts\n```\n\n## SMTP Commands (Sending Email)\n\n### accounts\nList configured email accounts without exposing passwords.\n\n```bash\nnode scripts/smtp.js accounts\n```\n\n### send\nSubmit email via SMTP. A successful command means the SMTP server accepted the message for processing, not that the recipient inbox has received it.\n\n```bash\nnode scripts/smtp.js send --to <email> --subject <text> --confirmed [options]\n```\n\n**Required:**\n- `--to <email>`: Recipient (comma-separated for multiple)\n- `--subject <text>`: Email subject, or `--subject-file <file>`\n\n**Optional:**\n- `--body <text>`: Plain text body\n- `--html`: Send body as HTML\n- `--body-file <file>`: Read body from file\n- `--html-file <file>`: Read HTML from file\n- `--cc <email>`: CC recipients\n- `--bcc <email>`: BCC recipients\n- `--attach <file>`: Attachments (comma-separated)\n- `--from <email>`: Override default sender\n- `--account <id>`: Send from a specific configured account\n- `--to-account <id>`: Send to a configured account by ID without exposing its full email address\n- `--confirmed`: Required after the user confirms the email details\n\n**Examples:**\n```bash\n# Simple text email\nnode scripts/smtp.js send --to recipient@example.com --subject \"Hello\" --body \"World\"\n\n# HTML email\nnode scripts/smtp.js send --to recipient@example.com --subject \"Newsletter\" --html --body \"<h1>Welcome</h1>\"\n\n# Email with attachment\nnode scripts/smtp.js send --to recipient@example.com --subject \"Report\" --body \"Please find attached\" --attach report.pdf\n\n# Multiple recipients\nnode scripts/smtp.js send --to \"a@example.com,b@example.com\" --cc \"c@example.com\" --subject \"Update\" --body \"Team update\"\n\n# Send to another configured account by ID\nnode scripts/smtp.js send --account default --to-account account-2 --subject \"Hello\" --body \"World\"\n```\n\n### test\nTest SMTP connection by sending a test email to yourself.\n\n```bash\nnode scripts/smtp.js test\n```\n\n## Dependencies\n\n```bash\nnpm install\n```\n\n## Security Notes\n\n- Store credentials in `.env` (add to `.gitignore`)\n- For Gmail: use App Password if 2FA is enabled\n- For 163.com: use authorization code (授权码), not account password\n- Downloaded attachment filenames are normalized to a safe local filename and cannot create directories outside the account/UID download folder.\n\n## Troubleshooting\n\n**Connection timeout:**\n- Verify server is running and accessible\n- Check host/port configuration\n\n**Authentication failed:**\n- Verify username (usually full email address)\n- Check password is correct\n- For 163.com: use authorization code, not account password\n- For Gmail: use App Password if 2FA enabled\n\n**TLS/SSL errors:**\n- Match `IMAP_TLS`/`SMTP_SECURE` setting to server requirements\n- For self-signed certs: set `IMAP_REJECT_UNAUTHORIZED=false` or `SMTP_REJECT_UNAUTHORIZED=false`\n","frontmatter":{"name":"imap-smtp-email","description":"Read and send email via IMAP/SMTP. Check for new/unread messages, fetch content, search mailboxes, mark as read/unread, and send emails with attachments. Works with any IMAP/SMTP server including Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, and vip.188.com.","official":true,"version":"1.0.7"},"isInternal":false,"tokens":2695,"sizeBytes":10966},{"name":"SKILL.md","path":"SKILLs/local-tools/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/local-tools/SKILL.md","title":"local-tools","category":"anthropic-skill","format":"markdown","content":"---\nname: local-tools\ndescription: Access local system resources including Calendar on macOS and Windows. Use this skill when you need to manage user's schedule directly on their device.\nofficial: true\n---\n\n# Local Tools Skill\n\n## When to Use This Skill\n\nUse the local-tools skill when you need to:\n\n- **Calendar Management** - View, create, update, or delete calendar events\n\n**Examples of when to use:**\n- User: \"Show me my schedule for tomorrow\"\n- User: \"Create a meeting at 3 PM\"\n- User: \"Search for calendar events containing 'project'\"\n- User: \"Delete tomorrow's meeting\"\n\n## How It Works\n\n```\n┌──────────┐    Bash/PowerShell    ┌─────────────────────────────────────────────────────────────┐\n│  Claude  │──────────────────────▶│  calendar.sh / calendar.ps1                                 │\n│          │                       │  ├─ macOS: osascript -l JavaScript (JXA) ──▶ Calendar.app   │\n│          │                       │  └─ Windows: PowerShell ──▶ Outlook COM API                 │\n└──────────┘                       └─────────────────────────────────────────────────────────────┘\n```\n\n**Architecture:**\n1. **CLI Scripts** - Platform-specific scripts, no HTTP server needed\n   - `calendar.sh` - Bash script for macOS\n   - `calendar.ps1` - PowerShell script for Windows\n\n2. **Local Calendar Access** - Direct access to system calendar\n   - macOS: Uses JXA (JavaScript for Automation) to control Calendar.app\n   - Windows: Uses PowerShell COM API to control Microsoft Outlook\n\n3. **JSON Output** - Structured data format for easy parsing\n\n## Platform Support\n\n| Platform | Implementation | Calendar App | Status |\n|----------|---------------|--------------|--------|\n| **macOS 10.10+** | JXA + Calendar.app | Calendar.app | ✅ Fully Supported |\n| **Windows 7+** | PowerShell + COM | Microsoft Outlook | ✅ Fully Supported |\n| **Linux** | - | - | ❌ Not Supported |\n\n## Permissions\n\n### macOS\n- Requires \"Calendar\" access permission\n- User will be prompted on first use\n- Can be managed in: System Settings > Privacy & Security > Calendar\n\n### Windows\n- Requires Microsoft Outlook to be installed\n- May require administrative privileges for COM access\n\n## Calendar Operations\n\n**IMPORTANT: How to Locate the Script**\n\nWhen you read this SKILL.md file using the Read tool, you receive its absolute path (e.g., `/Users/username/.../SKILLs/local-tools/SKILL.md`).\n\n**To construct the script path:**\n1. Take the directory of this SKILL.md file\n2. Append `/scripts/calendar.sh` (macOS) or `/scripts/calendar.ps1` (Windows)\n\n**Example:**\n```bash\n# If SKILL.md is at: /Users/username/path/to/SKILLs/local-tools/SKILL.md\n# Then the script is: /Users/username/path/to/SKILLs/local-tools/scripts/calendar.sh\n\nbash \"/Users/username/path/to/SKILLs/local-tools/scripts/calendar.sh\" <operation> [options]\n```\n\nIn all examples below, `<skill-dir>/scripts/calendar.sh` is a placeholder. Replace it with the actual absolute path.\n\n### Best Practices for AI Assistant\n\n**DO:**\n- ✅ Execute commands directly without showing trial-and-error process\n- ✅ If command fails, inform user about permission issues without showing technical errors\n- ✅ Use `search` command for searching birthdays/anniversaries\n- ✅ If no calendar name specified, script will automatically use first available calendar\n\n**DON'T:**\n- ❌ Don't repeatedly try different command combinations\n- ❌ Don't show error stacks or technical details to users\n- ❌ Don't read script source code to analyze issues\n- ❌ Don't ask users for calendar name, use default behavior\n\n**Example - Searching for birthdays:**\n```bash\n# Correct approach: Search directly, don't trial-and-error\nbash \"<skill-dir>/scripts/calendar.sh\" search --query \"birthday\"\n\n# If permission error returned, directly tell user:\n# \"Calendar access permission is required. Please open System Settings > Privacy & Security > Calendar, and authorize Terminal or LobsterAI\"\n```\n\n### List Events\n\n```bash\n# List events for next 7 days (default)\nbash \"<skill-dir>/scripts/calendar.sh\" list\n\n# List events for specific date range\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-12T00:00:00\" \\\n  --end \"2026-02-19T23:59:59\"\n\n# List events from specific calendar (macOS)\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --calendar \"Work\"\n```\n\n### Create Event\n\n```bash\n# Create a simple event\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Team Meeting\" \\\n  --start \"2026-02-13T14:00:00\" \\\n  --end \"2026-02-13T15:00:00\"\n\n# Create event with location and notes\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Client Call\" \\\n  --start \"2026-02-14T10:00:00\" \\\n  --end \"2026-02-14T11:00:00\" \\\n  --calendar \"Work\" \\\n  --location \"Conference Room A\" \\\n  --notes \"Discuss Q1 roadmap\"\n```\n\n### Update Event\n\n```bash\n# Update event title\nbash \"<skill-dir>/scripts/calendar.sh\" update \\\n  --id \"EVENT-ID\" \\\n  --title \"Updated Meeting Title\"\n\n# Update event time\nbash \"<skill-dir>/scripts/calendar.sh\" update \\\n  --id \"EVENT-ID\" \\\n  --start \"2026-02-13T15:00:00\" \\\n  --end \"2026-02-13T16:00:00\"\n```\n\n### Delete Event\n\n```bash\nbash \"<skill-dir>/scripts/calendar.sh\" delete \\\n  --id \"EVENT-ID\"\n```\n\n### Search Events\n\n```bash\n# Search for events containing keyword (searches ALL calendars)\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"meeting\"\n\n# Search in specific calendar only\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"project\" \\\n  --calendar \"Work\"\n```\n\n**Note:** When `--calendar` is not specified, the search operation will look through **all available calendars** on both macOS and Windows.\n\n## Output Format\n\nAll commands return JSON with the following structure:\n\n### Success Response\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"events\": [\n      {\n        \"eventId\": \"E621F8C4-...\",\n        \"title\": \"Team Meeting\",\n        \"startTime\": \"2026-02-13T14:00:00.000Z\",\n        \"endTime\": \"2026-02-13T15:00:00.000Z\",\n        \"location\": \"Conference Room\",\n        \"notes\": \"Weekly sync\",\n        \"calendar\": \"Work\",\n        \"allDay\": false\n      }\n    ],\n    \"count\": 1\n  }\n}\n```\n\n### Error Response\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CALENDAR_ACCESS_ERROR\",\n    \"message\": \"Calendar access permission is required...\",\n    \"recoverable\": true,\n    \"permissionRequired\": true\n  }\n}\n```\n\n### Error Codes\n\n| Code | Meaning | Recoverable |\n|------|---------|-------------|\n| `CALENDAR_ACCESS_ERROR` | Permission denied or calendar not accessible | Yes |\n| `INVALID_INPUT` | Missing required parameters | No |\n| `EVENT_NOT_FOUND` | Event ID not found | No |\n| `OUTLOOK_NOT_AVAILABLE` | Microsoft Outlook not installed (Windows) | Yes |\n\n## Date Format Guidelines\n\n### Important: Date Format Guidelines\n\nWhen using the `list` command with time ranges:\n\n1. **Always use ISO 8601 format**: `YYYY-MM-DDTHH:mm:ss`\n2. **Use local timezone**: Do NOT use UTC or timezone suffixes (like +08:00 or Z)\n3. **Calculate dates yourself**: Do NOT use shell command substitution like `$(date ...)`\n4. **Claude should compute dates**: Based on current date, calculate target dates directly\n5. **Examples**:\n   - Today at midnight: `2026-02-13T00:00:00`\n   - Today at end of day: `2026-02-13T23:59:59`\n   - Tomorrow morning: `2026-02-14T09:00:00`\n   - Next week Monday: `2026-02-16T00:00:00`\n\n**Why**: The script expects local time strings that match your system timezone. Shell substitutions may not execute correctly in all environments.\n\n## Common Patterns\n\n### Pattern 1: Schedule Management\n\n```bash\n# User asks: \"What meetings do I have today?\"\n# Claude's approach: Calculate today's date and query full day from 00:00 to 23:59\n# IMPORTANT: Claude should replace 2026-02-13 with the actual current date\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-13T00:00:00\" \\\n  --end \"2026-02-13T23:59:59\"\n\n# User asks: \"What's on my schedule tomorrow?\"\n# Claude should calculate tomorrow's date (e.g., if today is 2026-02-13, tomorrow is 2026-02-14)\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-14T00:00:00\" \\\n  --end \"2026-02-14T23:59:59\"\n```\n\n### Pattern 2: Meeting Scheduling\n\n```bash\n# User asks: \"Schedule a meeting for tomorrow at 3 PM\"\n# Claude's approach:\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Meeting\" \\\n  --start \"2026-02-13T15:00:00\" \\\n  --end \"2026-02-13T16:00:00\" \\\n  --calendar \"Work\"\n```\n\n### Pattern 3: Event Search\n\n```bash\n# User asks: \"Find all meetings about the project\"\n# Claude's approach:\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"project\" \\\n  --calendar \"Work\"\n```\n\n### Pattern 4: Availability Check\n\n```bash\n# User asks: \"Am I free tomorrow afternoon?\"\n# Claude's approach:\n# 1. List tomorrow's events\n# 2. Analyze time slots\n# 3. Report availability\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-14T00:00:00\" \\\n  --end \"2026-02-14T23:59:59\"\n```\n\n## Known Behaviors\n\n### Time Range Matching\n\nThe `list` command uses **interval overlap detection**:\n- Returns events that have **any overlap** with the query time range\n- Does NOT require events to be fully contained within the range\n\n**Examples:**\n- Query: 2026-02-13 00:00:00 to 23:59:59\n- Returns:\n  - ✅ Events fully on Feb 13 (e.g., 10:00-11:00)\n  - ✅ Multi-day events spanning Feb 13 (e.g., Feb 12 10:00 - Feb 14 10:00)\n  - ✅ Events crossing midnight (e.g., Feb 13 23:30 - Feb 14 00:30)\n  - ❌ Events entirely before Feb 13 (e.g., Feb 12 10:00-11:00)\n  - ❌ Events entirely after Feb 13 (e.g., Feb 14 10:00-11:00)\n\n### All-Day Events\n\n- Treated as spanning from 00:00:00 to 23:59:59 on their date(s)\n- Multi-day all-day events (e.g., Feb 12-14) will appear when querying any date within that range\n\n### Time Precision\n\n- Comparisons use second-level precision\n- Milliseconds are ignored in date comparisons\n\n### Recurring Events\n\n- Each occurrence is treated as a separate event instance\n- The script returns individual occurrences within the queried time range\n\n## Best Practices\n\n### 1. Always Check Before Creating\n\nBefore creating an event, list existing events to avoid conflicts:\n\n```bash\n# First check existing events\nbash \"<skill-dir>/scripts/calendar.sh\" list\n\n# Then create if no conflict\nbash \"<skill-dir>/scripts/calendar.sh\" create ...\n```\n\n### 2. Use Specific Calendars (macOS)\n\nSpecify the calendar to keep events organized:\n\n```bash\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Team Meeting\" \\\n  --calendar \"Work\" \\\n  ...\n```\n\n### 3. Search Before Updating/Deleting\n\nAlways search first to get the correct event ID:\n\n```bash\n# Search to find event ID\nbash \"<skill-dir>/scripts/calendar.sh\" search --query \"meeting\"\n\n# Then update or delete\nbash \"<skill-dir>/scripts/calendar.sh\" update --id \"FOUND-ID\" ...\n```\n\n### 4. Handle Errors Gracefully\n\nParse the response and handle errors:\n\n```bash\nresult=$(bash \"<skill-dir>/scripts/calendar.sh\" list)\nif echo \"$result\" | grep -q '\"success\":true'; then\n  # Process events\n  events=$(echo \"$result\" | jq '.data.events')\nelse\n  # Handle error\n  error=$(echo \"$result\" | jq '.error.message')\n  echo \"Failed: $error\"\nfi\n```\n\n## Limitations\n\n### macOS\n- Requires macOS 10.10 Yosemite or later (for JXA support)\n- Requires Calendar access permission\n- Does not support advanced recurring event queries\n- Cannot modify recurring event rules\n\n### Windows\n- Requires Microsoft Outlook to be installed\n- Does not support other calendar applications (Windows Calendar, Google Calendar, etc.)\n- May require COM access permissions in corporate environments\n- Folder enumeration may skip restricted calendars\n\n### General\n- All dates must be in ISO 8601 format (`YYYY-MM-DDTHH:mm:ss`)\n- Uses local timezone for all operations\n- Return values are converted to UTC (ISO 8601 with Z suffix)\n- No support for attendees or meeting invitations\n\n## Troubleshooting\n\n### macOS\n\n**Permission Denied:**\n```\nError: Calendar access permission is required\n```\n**Solution:** Open System Settings > Privacy & Security > Calendar, authorize Terminal or LobsterAI\n\n**Script Not Found:**\n```\nbash: calendar.sh: No such file or directory\n```\n**Solution:** Ensure you're using the absolute path from SKILL.md's directory + `/scripts/calendar.sh`\n\n### Windows\n\n**Outlook Not Found:**\n```\nError: Microsoft Outlook is not installed or not accessible\n```\n**Solution:** Install Microsoft Outlook and ensure it's properly configured\n\n**PowerShell Execution Policy:**\n```\nError: Execution of scripts is disabled on this system\n```\n**Solution:** Run PowerShell as Administrator and execute:\n```powershell\nSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser\n```\n\n## Technical Details\n\n### macOS Implementation\n\n**JXA (JavaScript for Automation):**\n- Uses `osascript -l JavaScript` to execute JXA code\n- Controls Calendar.app via Apple Events\n- Works on both Intel and Apple Silicon Macs\n- Requires user permission for Calendar access\n\n**Date Handling:**\n- Uses BSD date command (macOS native)\n- Format: `date +%Y-%m-%dT%H:%M:%S` (local timezone)\n- Relative dates: `date -v+7d` (7 days from now)\n\n### Windows Implementation\n\n**PowerShell + COM:**\n- Uses Outlook COM API via PowerShell\n- Requires Outlook to be installed and configured\n- Works with all Outlook-compatible calendars\n\n**Date Handling:**\n- Uses PowerShell `[DateTime]::Parse()` for date parsing\n- Automatically handles local timezone\n\n### Cross-Platform Consistency\n\nBoth implementations:\n- Use identical JSON output format\n- Support the same operations (list, create, update, delete, search)\n- Handle dates in local timezone\n- Return UTC timestamps in ISO 8601 format\n\n## Related Skills\n\n- **imap-smtp-email** - For email-based meeting invitations\n","frontmatter":{"name":"local-tools","description":"Access local system resources including Calendar on macOS and Windows. Use this skill when you need to manage user's schedule directly on their device.","official":true},"isInternal":false,"tokens":3538,"sizeBytes":14016},{"name":"forms.md","path":"SKILLs/pdf/forms.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/forms.md","title":"Pdf Skill","category":"anthropic-skill","format":"markdown","content":"# Pdf Skill\n\nPath: `SKILLs/pdf/forms.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/forms.md)","tokens":300,"sizeBytes":155},{"name":"reference.md","path":"SKILLs/pdf/reference.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/reference.md","title":"Pdf Skill","category":"anthropic-skill","format":"markdown","content":"# Pdf Skill\n\nPath: `SKILLs/pdf/reference.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/reference.md)","tokens":300,"sizeBytes":163},{"name":"SKILL.md","path":"SKILLs/pdf/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/SKILL.md","title":"pdf","category":"anthropic-skill","format":"markdown","content":"---\nname: pdf\ndescription: Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.\nlicense: Proprietary. LICENSE.txt has complete terms\nofficial: true\n---\n\n# PDF Processing Guide\n\n## Overview\n\nThis guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see reference.md. If you need to fill out a PDF form, read forms.md and follow its instructions.\n\n## Quick Start\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Read a PDF\nreader = PdfReader(\"document.pdf\")\nprint(f\"Pages: {len(reader.pages)}\")\n\n# Extract text\ntext = \"\"\nfor page in reader.pages:\n    text += page.extract_text()\n```\n\n## Python Libraries\n\n### pypdf - Basic Operations\n\n#### Merge PDFs\n```python\nfrom pypdf import PdfWriter, PdfReader\n\nwriter = PdfWriter()\nfor pdf_file in [\"doc1.pdf\", \"doc2.pdf\", \"doc3.pdf\"]:\n    reader = PdfReader(pdf_file)\n    for page in reader.pages:\n        writer.add_page(page)\n\nwith open(\"merged.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n#### Split PDF\n```python\nreader = PdfReader(\"input.pdf\")\nfor i, page in enumerate(reader.pages):\n    writer = PdfWriter()\n    writer.add_page(page)\n    with open(f\"page_{i+1}.pdf\", \"wb\") as output:\n        writer.write(output)\n```\n\n#### Extract Metadata\n```python\nreader = PdfReader(\"document.pdf\")\nmeta = reader.metadata\nprint(f\"Title: {meta.title}\")\nprint(f\"Author: {meta.author}\")\nprint(f\"Subject: {meta.subject}\")\nprint(f\"Creator: {meta.creator}\")\n```\n\n#### Rotate Pages\n```python\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\npage = reader.pages[0]\npage.rotate(90)  # Rotate 90 degrees clockwise\nwriter.add_page(page)\n\nwith open(\"rotated.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### pdfplumber - Text and Table Extraction\n\n#### Extract Text with Layout\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        text = page.extract_text()\n        print(text)\n```\n\n#### Extract Tables\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for i, page in enumerate(pdf.pages):\n        tables = page.extract_tables()\n        for j, table in enumerate(tables):\n            print(f\"Table {j+1} on page {i+1}:\")\n            for row in table:\n                print(row)\n```\n\n#### Advanced Table Extraction\n```python\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    all_tables = []\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            if table:  # Check if table is not empty\n                df = pd.DataFrame(table[1:], columns=table[0])\n                all_tables.append(df)\n\n# Combine all tables\nif all_tables:\n    combined_df = pd.concat(all_tables, ignore_index=True)\n    combined_df.to_excel(\"extracted_tables.xlsx\", index=False)\n```\n\n### reportlab - Create PDFs\n\n#### Basic PDF Creation\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.pdfgen import canvas\n\nc = canvas.Canvas(\"hello.pdf\", pagesize=letter)\nwidth, height = letter\n\n# Add text\nc.drawString(100, height - 100, \"Hello World!\")\nc.drawString(100, height - 120, \"This is a PDF created with reportlab\")\n\n# Add a line\nc.line(100, height - 140, 400, height - 140)\n\n# Save\nc.save()\n```\n\n#### Create PDF with Multiple Pages\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak\nfrom reportlab.lib.styles import getSampleStyleSheet\n\ndoc = SimpleDocTemplate(\"report.pdf\", pagesize=letter)\nstyles = getSampleStyleSheet()\nstory = []\n\n# Add content\ntitle = Paragraph(\"Report Title\", styles['Title'])\nstory.append(title)\nstory.append(Spacer(1, 12))\n\nbody = Paragraph(\"This is the body of the report. \" * 20, styles['Normal'])\nstory.append(body)\nstory.append(PageBreak())\n\n# Page 2\nstory.append(Paragraph(\"Page 2\", styles['Heading1']))\nstory.append(Paragraph(\"Content for page 2\", styles['Normal']))\n\n# Build PDF\ndoc.build(story)\n```\n\n## Command-Line Tools\n\n### pdftotext (poppler-utils)\n```bash\n# Extract text\npdftotext input.pdf output.txt\n\n# Extract text preserving layout\npdftotext -layout input.pdf output.txt\n\n# Extract specific pages\npdftotext -f 1 -l 5 input.pdf output.txt  # Pages 1-5\n```\n\n### qpdf\n```bash\n# Merge PDFs\nqpdf --empty --pages file1.pdf file2.pdf -- merged.pdf\n\n# Split pages\nqpdf input.pdf --pages . 1-5 -- pages1-5.pdf\nqpdf input.pdf --pages . 6-10 -- pages6-10.pdf\n\n# Rotate pages\nqpdf input.pdf output.pdf --rotate=+90:1  # Rotate page 1 by 90 degrees\n\n# Remove password\nqpdf --password=mypassword --decrypt encrypted.pdf decrypted.pdf\n```\n\n### pdftk (if available)\n```bash\n# Merge\npdftk file1.pdf file2.pdf cat output merged.pdf\n\n# Split\npdftk input.pdf burst\n\n# Rotate\npdftk input.pdf rotate 1east output rotated.pdf\n```\n\n## Common Tasks\n\n### Extract Text from Scanned PDFs\n```python\n# Requires: pip install pytesseract pdf2image\nimport pytesseract\nfrom pdf2image import convert_from_path\n\n# Convert PDF to images\nimages = convert_from_path('scanned.pdf')\n\n# OCR each page\ntext = \"\"\nfor i, image in enumerate(images):\n    text += f\"Page {i+1}:\\n\"\n    text += pytesseract.image_to_string(image)\n    text += \"\\n\\n\"\n\nprint(text)\n```\n\n### Add Watermark\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Create watermark (or load existing)\nwatermark = PdfReader(\"watermark.pdf\").pages[0]\n\n# Apply to all pages\nreader = PdfReader(\"document.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    page.merge_page(watermark)\n    writer.add_page(page)\n\nwith open(\"watermarked.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### Extract Images\n```bash\n# Using pdfimages (poppler-utils)\npdfimages -j input.pdf output_prefix\n\n# This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc.\n```\n\n### Password Protection\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    writer.add_page(page)\n\n# Add password\nwriter.encrypt(\"userpassword\", \"ownerpassword\")\n\nwith open(\"encrypted.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n## Quick Reference\n\n| Task | Best Tool | Command/Code |\n|------|-----------|--------------|\n| Merge PDFs | pypdf | `writer.add_page(page)` |\n| Split PDFs | pypdf | One page per file |\n| Extract text | pdfplumber | `page.extract_text()` |\n| Extract tables | pdfplumber | `page.extract_tables()` |\n| Create PDFs | reportlab | Canvas or Platypus |\n| Command line merge | qpdf | `qpdf --empty --pages ...` |\n| OCR scanned PDFs | pytesseract | Convert to image first |\n| Fill PDF forms | pdf-lib or pypdf (see forms.md) | See forms.md |\n\n## Next Steps\n\n- For advanced pypdfium2 usage, see reference.md\n- For JavaScript libraries (pdf-lib), see reference.md\n- If you need to fill out a PDF form, follow the instructions in forms.md\n- For troubleshooting guides, see reference.md\n","frontmatter":{"name":"pdf","description":"Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.","license":"Proprietary. LICENSE.txt has complete terms","official":true},"isInternal":false,"tokens":1808,"sizeBytes":7083},{"name":"openai.yaml","path":"SKILLs/playwright/agents/openai.yaml","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/agents/openai.yaml","title":"Agents Skill","category":"anthropic-skill","format":"yaml","content":"# Agents Skill\n\nPath: `SKILLs/playwright/agents/openai.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/agents/openai.yaml)","tokens":300,"sizeBytes":192},{"name":"cli.md","path":"SKILLs/playwright/references/cli.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/cli.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `SKILLs/playwright/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/cli.md)","tokens":300,"sizeBytes":194},{"name":"workflows.md","path":"SKILLs/playwright/references/workflows.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/workflows.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `SKILLs/playwright/references/workflows.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/workflows.md)","tokens":300,"sizeBytes":206},{"name":"SKILL.md","path":"SKILLs/playwright/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/SKILL.md","title":"playwright","category":"anthropic-skill","format":"markdown","content":"---\nname: \"playwright\"\ndescription: \"Use when the task requires automating a real browser from the terminal (navigation, form filling, snapshots, screenshots, data extraction, UI-flow debugging) via `playwright-cli` or the bundled wrapper script.\"\nofficial: true\n---\n\n\n# Playwright CLI Skill\n\nDrive a real browser from the terminal using `playwright-cli`. Prefer the bundled wrapper script so the CLI works even when it is not globally installed.\nTreat this skill as CLI-first automation. Do not pivot to `@playwright/test` unless the user explicitly asks for test files.\n\n## Prerequisite check (required)\n\nBefore proposing commands, check whether `npx` is available (the wrapper depends on it):\n\n```bash\ncommand -v npx >/dev/null 2>&1\n```\n\nIf it is not available, pause and ask the user to install Node.js/npm (which provides `npx`). Provide these steps verbatim:\n\n```bash\n# Verify Node/npm are installed\nnode --version\nnpm --version\n\n# If missing, install Node.js/npm, then:\nnpm install -g @playwright/mcp@latest\nplaywright-cli --help\n```\n\nOnce `npx` is present, proceed with the wrapper script. A global install of `playwright-cli` is optional.\n\n## Skill path (set once)\n\n```bash\nexport SKILLS_ROOT=\"${LOBSTERAI_SKILLS_ROOT:-${SKILLS_ROOT:-$HOME/Library/Application Support/LobsterAI/SKILLs}}\"\nexport PWCLI=\"$SKILLS_ROOT/playwright/scripts/playwright_cli.sh\"\n```\n\nInstalled skills resolve from `$LOBSTERAI_SKILLS_ROOT` / `$SKILLS_ROOT` (production default: app `userData/SKILLs`, macOS usually `~/Library/Application Support/LobsterAI/SKILLs`).\n\n## Quick start\n\nUse the wrapper script:\n\n```bash\n\"$PWCLI\" open https://playwright.dev --headed\n\"$PWCLI\" snapshot\n\"$PWCLI\" click e15\n\"$PWCLI\" type \"Playwright\"\n\"$PWCLI\" press Enter\n\"$PWCLI\" screenshot\n```\n\nIf the user prefers a global install, this is also valid:\n\n```bash\nnpm install -g @playwright/mcp@latest\nplaywright-cli --help\n```\n\n## Core workflow\n\n1. Open the page.\n2. Snapshot to get stable element refs.\n3. Interact using refs from the latest snapshot.\n4. Re-snapshot after navigation or significant DOM changes.\n5. Capture artifacts (screenshot, pdf, traces) when useful.\n\nMinimal loop:\n\n```bash\n\"$PWCLI\" open https://example.com\n\"$PWCLI\" snapshot\n\"$PWCLI\" click e3\n\"$PWCLI\" snapshot\n```\n\n## When to snapshot again\n\nSnapshot again after:\n\n- navigation\n- clicking elements that change the UI substantially\n- opening/closing modals or menus\n- tab switches\n\nRefs can go stale. When a command fails due to a missing ref, snapshot again.\n\n## Recommended patterns\n\n### Form fill and submit\n\n```bash\n\"$PWCLI\" open https://example.com/form\n\"$PWCLI\" snapshot\n\"$PWCLI\" fill e1 \"user@example.com\"\n\"$PWCLI\" fill e2 \"password123\"\n\"$PWCLI\" click e3\n\"$PWCLI\" snapshot\n```\n\n### Debug a UI flow with traces\n\n```bash\n\"$PWCLI\" open https://example.com --headed\n\"$PWCLI\" tracing-start\n# ...interactions...\n\"$PWCLI\" tracing-stop\n```\n\n### Multi-tab work\n\n```bash\n\"$PWCLI\" tab-new https://example.com\n\"$PWCLI\" tab-list\n\"$PWCLI\" tab-select 0\n\"$PWCLI\" snapshot\n```\n\n## Wrapper script\n\nThe wrapper script uses `npx --package @playwright/mcp playwright-cli` so the CLI can run without a global install:\n\n```bash\n\"$PWCLI\" --help\n```\n\nPrefer the wrapper unless the repository already standardizes on a global install.\n\n## References\n\nOpen only what you need:\n\n- CLI command reference: `references/cli.md`\n- Practical workflows and troubleshooting: `references/workflows.md`\n\n## Guardrails\n\n- Always snapshot before referencing element ids like `e12`.\n- Re-snapshot when refs seem stale.\n- Prefer explicit commands over `eval` and `run-code` unless needed.\n- When you do not have a fresh snapshot, use placeholder refs like `eX` and say why; do not bypass refs with `run-code`.\n- Use `--headed` when a visual check will help.\n- When capturing artifacts in this repo, use `output/playwright/` and avoid introducing new top-level artifact folders.\n- Default to CLI commands and workflows, not Playwright test specs.\n","frontmatter":{"name":"playwright","description":"Use when the task requires automating a real browser from the terminal (navigation, form filling, snapshots, screenshots, data extraction, UI-flow debugging) via `playwright-cli` or the bundled wrapper script.","official":true},"isInternal":false,"tokens":990,"sizeBytes":3943},{"name":"html2pptx.md","path":"SKILLs/pptx/html2pptx.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/html2pptx.md","title":"Pptx Skill","category":"anthropic-skill","format":"markdown","content":"# Pptx Skill\n\nPath: `SKILLs/pptx/html2pptx.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/html2pptx.md)","tokens":300,"sizeBytes":166},{"name":"ooxml.md","path":"SKILLs/pptx/ooxml.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/ooxml.md","title":"Pptx Skill","category":"anthropic-skill","format":"markdown","content":"# Pptx Skill\n\nPath: `SKILLs/pptx/ooxml.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/ooxml.md)","tokens":300,"sizeBytes":158},{"name":"package.json","path":"SKILLs/pptx/package.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/package.json","title":"Pptx Skill","category":"anthropic-skill","format":"json","content":"# Pptx Skill\n\nPath: `SKILLs/pptx/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/package.json)","tokens":300,"sizeBytes":166},{"name":"SKILL.md","path":"SKILLs/pptx/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/SKILL.md","title":"pptx","category":"anthropic-skill","format":"markdown","content":"---\nname: pptx\ndescription: \"Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks\"\nlicense: Proprietary. LICENSE.txt has complete terms\nofficial: true\n---\n\n# PPTX creation, editing, and analysis\n\n## Overview\n\nA user may ask you to create, edit, or analyze the contents of a .pptx file. A .pptx file is essentially a ZIP archive containing XML files and other resources that you can read or edit. You have different tools and workflows available for different tasks.\n\n## Reading and analyzing content\n\n### Text extraction\nIf you just need to read the text contents of a presentation, you should convert the document to markdown:\n\n```bash\n# Convert document to markdown\npython -m markitdown path-to-file.pptx\n```\n\n### Raw XML access\nYou need raw XML access for: comments, speaker notes, slide layouts, animations, design elements, and complex formatting. For any of these features, you'll need to unpack a presentation and read its raw XML contents.\n\n#### Unpacking a file\n`python ooxml/scripts/unpack.py <office_file> <output_dir>`\n\n**Note**: Resolve script paths from this skill directory. Prefer `$SKILLS_ROOT/pptx/ooxml/scripts/unpack.py` when `$SKILLS_ROOT` is available; otherwise resolve `ooxml/scripts/unpack.py` relative to this `SKILL.md` file's directory. Do not assume a workspace-relative `skills/pptx/...` path.\n\n#### Key file structures\n* `ppt/presentation.xml` - Main presentation metadata and slide references\n* `ppt/slides/slide{N}.xml` - Individual slide contents (slide1.xml, slide2.xml, etc.)\n* `ppt/notesSlides/notesSlide{N}.xml` - Speaker notes for each slide\n* `ppt/comments/modernComment_*.xml` - Comments for specific slides\n* `ppt/slideLayouts/` - Layout templates for slides\n* `ppt/slideMasters/` - Master slide templates\n* `ppt/theme/` - Theme and styling information\n* `ppt/media/` - Images and other media files\n\n#### Typography and color extraction\n**When given an example design to emulate**: Always analyze the presentation's typography and colors first using the methods below:\n1. **Read theme file**: Check `ppt/theme/theme1.xml` for colors (`<a:clrScheme>`) and fonts (`<a:fontScheme>`)\n2. **Sample slide content**: Examine `ppt/slides/slide1.xml` for actual font usage (`<a:rPr>`) and colors\n3. **Search for patterns**: Use grep to find color (`<a:solidFill>`, `<a:srgbClr>`) and font references across all XML files\n\n## Creating a new PowerPoint presentation **without a template**\n\nWhen creating a new PowerPoint presentation from scratch, use the **html2pptx** workflow to convert HTML slides to PowerPoint with accurate positioning.\n\n### Design Principles\n\n**CRITICAL**: Before creating any presentation, analyze the content and choose appropriate design elements:\n1. **Consider the subject matter**: What is this presentation about? What tone, industry, or mood does it suggest?\n2. **Check for branding**: If the user mentions a company/organization, consider their brand colors and identity\n3. **Match palette to content**: Select colors that reflect the subject\n4. **State your approach**: Explain your design choices before writing code\n\n**Requirements**:\n- ✅ State your content-informed design approach BEFORE writing code\n- ✅ Use web-safe fonts only: Arial, Helvetica, Times New Roman, Georgia, Courier New, Verdana, Tahoma, Trebuchet MS, Impact\n- ✅ Create clear visual hierarchy through size, weight, and color\n- ✅ Ensure readability: strong contrast, appropriately sized text, clean alignment\n- ✅ Be consistent: repeat patterns, spacing, and visual language across slides\n\n#### Color Palette Selection\n\n**Choosing colors creatively**:\n- **Think beyond defaults**: What colors genuinely match this specific topic? Avoid autopilot choices.\n- **Consider multiple angles**: Topic, industry, mood, energy level, target audience, brand identity (if mentioned)\n- **Be adventurous**: Try unexpected combinations - a healthcare presentation doesn't have to be green, finance doesn't have to be navy\n- **Build your palette**: Pick 3-5 colors that work together (dominant colors + supporting tones + accent)\n- **Ensure contrast**: Text must be clearly readable on backgrounds\n\n**Example color palettes** (use these to spark creativity - choose one, adapt it, or create your own):\n\n1. **Classic Blue**: Deep navy (#1C2833), slate gray (#2E4053), silver (#AAB7B8), off-white (#F4F6F6)\n2. **Teal & Coral**: Teal (#5EA8A7), deep teal (#277884), coral (#FE4447), white (#FFFFFF)\n3. **Bold Red**: Red (#C0392B), bright red (#E74C3C), orange (#F39C12), yellow (#F1C40F), green (#2ECC71)\n4. **Warm Blush**: Mauve (#A49393), blush (#EED6D3), rose (#E8B4B8), cream (#FAF7F2)\n5. **Burgundy Luxury**: Burgundy (#5D1D2E), crimson (#951233), rust (#C15937), gold (#997929)\n6. **Deep Purple & Emerald**: Purple (#B165FB), dark blue (#181B24), emerald (#40695B), white (#FFFFFF)\n7. **Cream & Forest Green**: Cream (#FFE1C7), forest green (#40695B), white (#FCFCFC)\n8. **Pink & Purple**: Pink (#F8275B), coral (#FF574A), rose (#FF737D), purple (#3D2F68)\n9. **Lime & Plum**: Lime (#C5DE82), plum (#7C3A5F), coral (#FD8C6E), blue-gray (#98ACB5)\n10. **Black & Gold**: Gold (#BF9A4A), black (#000000), cream (#F4F6F6)\n11. **Sage & Terracotta**: Sage (#87A96B), terracotta (#E07A5F), cream (#F4F1DE), charcoal (#2C2C2C)\n12. **Charcoal & Red**: Charcoal (#292929), red (#E33737), light gray (#CCCBCB)\n13. **Vibrant Orange**: Orange (#F96D00), light gray (#F2F2F2), charcoal (#222831)\n14. **Forest Green**: Black (#191A19), green (#4E9F3D), dark green (#1E5128), white (#FFFFFF)\n15. **Retro Rainbow**: Purple (#722880), pink (#D72D51), orange (#EB5C18), amber (#F08800), gold (#DEB600)\n16. **Vintage Earthy**: Mustard (#E3B448), sage (#CBD18F), forest green (#3A6B35), cream (#F4F1DE)\n17. **Coastal Rose**: Old rose (#AD7670), beaver (#B49886), eggshell (#F3ECDC), ash gray (#BFD5BE)\n18. **Orange & Turquoise**: Light orange (#FC993E), grayish turquoise (#667C6F), white (#FCFCFC)\n\n#### Visual Details Options\n\n**Geometric Patterns**:\n- Diagonal section dividers instead of horizontal\n- Asymmetric column widths (30/70, 40/60, 25/75)\n- Rotated text headers at 90° or 270°\n- Circular/hexagonal frames for images\n- Triangular accent shapes in corners\n- Overlapping shapes for depth\n\n**Border & Frame Treatments**:\n- Thick single-color borders (10-20pt) on one side only\n- Double-line borders with contrasting colors\n- Corner brackets instead of full frames\n- L-shaped borders (top+left or bottom+right)\n- Underline accents beneath headers (3-5pt thick)\n\n**Typography Treatments**:\n- Extreme size contrast (72pt headlines vs 11pt body)\n- All-caps headers with wide letter spacing\n- Numbered sections in oversized display type\n- Monospace (Courier New) for data/stats/technical content\n- Condensed fonts (Arial Narrow) for dense information\n- Outlined text for emphasis\n\n**Chart & Data Styling**:\n- Monochrome charts with single accent color for key data\n- Horizontal bar charts instead of vertical\n- Dot plots instead of bar charts\n- Minimal gridlines or none at all\n- Data labels directly on elements (no legends)\n- Oversized numbers for key metrics\n\n**Layout Innovations**:\n- Full-bleed images with text overlays\n- Sidebar column (20-30% width) for navigation/context\n- Modular grid systems (3×3, 4×4 blocks)\n- Z-pattern or F-pattern content flow\n- Floating text boxes over colored shapes\n- Magazine-style multi-column layouts\n\n**Background Treatments**:\n- Solid color blocks occupying 40-60% of slide\n- Gradient fills (vertical or diagonal only)\n- Split backgrounds (two colors, diagonal or vertical)\n- Edge-to-edge color bands\n- Negative space as a design element\n\n### Layout Tips\n**When creating slides with charts or tables:**\n- **Two-column layout (PREFERRED)**: Use a header spanning the full width, then two columns below - text/bullets in one column and the featured content in the other. This provides better balance and makes charts/tables more readable. Use flexbox with unequal column widths (e.g., 40%/60% split) to optimize space for each content type.\n- **Full-slide layout**: Let the featured content (chart/table) take up the entire slide for maximum impact and readability\n- **NEVER vertically stack**: Do not place charts/tables below text in a single column - this causes poor readability and layout issues\n\n### Workflow\n1. **MANDATORY - READ ENTIRE FILE**: Read `html2pptx.md` from the same directory as this `SKILL.md` (installed default: `$SKILLS_ROOT/pptx/html2pptx.md`) completely from start to finish. **NEVER set any range limits when reading this file.** Read the full file content for detailed syntax, critical formatting rules, and best practices before proceeding with presentation creation.\n2. Create an HTML file for each slide with proper dimensions (e.g., 720pt × 405pt for 16:9)\n   - Use `<p>`, `<h1>`-`<h6>`, `<ul>`, `<ol>` for all text content\n   - Use `class=\"placeholder\"` for areas where charts/tables will be added (render with gray background for visibility)\n   - **CRITICAL**: Rasterize gradients and icons as PNG images FIRST using Sharp, then reference in HTML\n   - **LAYOUT**: For slides with charts/tables/images, use either full-slide layout or two-column layout for better readability\n3. Create and run a JavaScript file using the [`html2pptx.js`](scripts/html2pptx.js) library to convert HTML slides to PowerPoint and save the presentation\n   - Use the `html2pptx()` function to process each HTML file\n   - Add charts and tables to placeholder areas using PptxGenJS API\n   - Save the presentation using `pptx.writeFile()`\n4. **Visual validation**: Generate thumbnails and inspect for layout issues\n   - Create thumbnail grid: `python scripts/thumbnail.py output.pptx workspace/thumbnails --cols 4`\n   - Read and carefully examine the thumbnail image for:\n     - **Text cutoff**: Text being cut off by header bars, shapes, or slide edges\n     - **Text overlap**: Text overlapping with other text or shapes\n     - **Positioning issues**: Content too close to slide boundaries or other elements\n     - **Contrast issues**: Insufficient contrast between text and backgrounds\n   - If issues found, adjust HTML margins/spacing/colors and regenerate the presentation\n   - Repeat until all slides are visually correct\n\n## Live editing in LobsterAI\n\nWhen the `ppt_read` and `ppt_edit` tools exist, change existing presentations through them instead of unpacking and repacking the file. The presentation opens in LobsterAI's right-side PowerPoint editor, edits appear there immediately, the theme, layouts, animations and everything the tools do not touch are preserved, and the file saves automatically.\n\n1. Call `ppt_read` with the absolute `path` (and `slides` such as `\"2-4\"` for long decks). It returns `revision`, the layout names, and for each slide its number, layout, speaker notes and shapes: `id`, `name`, `kind`, placeholder role, position and size in points, `text` (one line per paragraph, leading tabs give the bullet level) and table cells. It also returns the user's current `selection` (\"改这里\" means that slide and shape).\n2. Call `ppt_edit` with the same `path`, `expectedRevision` from the read, and a list of `edits`; slides are numbered from 1 and shapes are addressed by their `id`:\n   - `replace_text` `{slide?, shape?, find, replace, occurrence?}` for wording changes; it keeps the formatting around the phrase.\n   - `set_text` `{slide, shape, text}` rewrites a shape's text and keeps its formatting; `set_table_cell` `{slide, shape, row, column, text}`.\n   - `format_text` (bold, italic, underline, strike, color, size in pt, font) on a `find` phrase, a `paragraph` or the whole shape; `format_paragraph` (alignment, bullet `level`).\n   - `set_bounds` `{slide, shape, x?, y?, width?, height?}` in points, `delete_shape`, `add_text_box`.\n   - `add_slide` `{after?, layout?, title?, body?}` with a layout name from the read, `duplicate_slide`, `move_slide` `{slide, position}`, `delete_slide`, `set_notes`.\n3. Edits in one call apply in order as one undoable step, and slide numbers in later edits refer to the deck after the earlier ones. If the call is refused because the revision changed, the user edited the presentation meanwhile: read again and redo the edit. If any edit fails, nothing is applied; fix the reported edit and retry.\n\nUse the OOXML workflow below only for what these tools cannot do: pictures, charts, SmartArt, new designs, or presentations LobsterAI reports as read-only.\n\n## Editing an existing PowerPoint presentation\n\nWhen edit slides in an existing PowerPoint presentation, you need to work with the raw Office Open XML (OOXML) format. This involves unpacking the .pptx file, editing the XML content, and repacking it.\n\n### Workflow\n1. **MANDATORY - READ ENTIRE FILE**: Read `ooxml.md` from the same directory as this `SKILL.md` (installed default: `$SKILLS_ROOT/pptx/ooxml.md`) (~500 lines) completely from start to finish.  **NEVER set any range limits when reading this file.**  Read the full file content for detailed guidance on OOXML structure and editing workflows before any presentation editing.\n2. Unpack the presentation: `python ooxml/scripts/unpack.py <office_file> <output_dir>`\n3. Edit the XML files (primarily `ppt/slides/slide{N}.xml` and related files)\n4. **CRITICAL**: Validate immediately after each edit and fix any validation errors before proceeding: `python ooxml/scripts/validate.py <dir> --original <file>`\n5. Pack the final presentation: `python ooxml/scripts/pack.py <input_directory> <office_file>`\n\n## Creating a new PowerPoint presentation **using a template**\n\nWhen you need to create a presentation that follows an existing template's design, you'll need to duplicate and re-arrange template slides before then replacing placeholder context.\n\n### Workflow\n1. **Extract template text AND create visual thumbnail grid**:\n   * Extract text: `python -m markitdown template.pptx > template-content.md`\n   * Read `template-content.md`: Read the entire file to understand the contents of the template presentation. **NEVER set any range limits when reading this file.**\n   * Create thumbnail grids: `python scripts/thumbnail.py template.pptx`\n   * See [Creating Thumbnail Grids](#creating-thumbnail-grids) section for more details\n\n2. **Analyze template and save inventory to a file**:\n   * **Visual Analysis**: Review thumbnail grid(s) to understand slide layouts, design patterns, and visual structure\n   * Create and save a template inventory file at `template-inventory.md` containing:\n     ```markdown\n     # Template Inventory Analysis\n     **Total Slides: [count]**\n     **IMPORTANT: Slides are 0-indexed (first slide = 0, last slide = count-1)**\n\n     ## [Category Name]\n     - Slide 0: [Layout code if available] - Description/purpose\n     - Slide 1: [Layout code] - Description/purpose\n     - Slide 2: [Layout code] - Description/purpose\n     [... EVERY slide must be listed individually with its index ...]\n     ```\n   * **Using the thumbnail grid**: Reference the visual thumbnails to identify:\n     - Layout patterns (title slides, content layouts, section dividers)\n     - Image placeholder locations and counts\n     - Design consistency across slide groups\n     - Visual hierarchy and structure\n   * This inventory file is REQUIRED for selecting appropriate templates in the next step\n\n3. **Create presentation outline based on template inventory**:\n   * Review available templates from step 2.\n   * Choose an intro or title template for the first slide. This should be one of the first templates.\n   * Choose safe, text-based layouts for the other slides.\n   * **CRITICAL: Match layout structure to actual content**:\n     - Single-column layouts: Use for unified narrative or single topic\n     - Two-column layouts: Use ONLY when you have exactly 2 distinct items/concepts\n     - Three-column layouts: Use ONLY when you have exactly 3 distinct items/concepts\n     - Image + text layouts: Use ONLY when you have actual images to insert\n     - Quote layouts: Use ONLY for actual quotes from people (with attribution), never for emphasis\n     - Never use layouts with more placeholders than you have content\n     - If you have 2 items, don't force them into a 3-column layout\n     - If you have 4+ items, consider breaking into multiple slides or using a list format\n   * Count your actual content pieces BEFORE selecting the layout\n   * Verify each placeholder in the chosen layout will be filled with meaningful content\n   * Select one option representing the **best** layout for each content section.\n   * Save `outline.md` with content AND template mapping that leverages available designs\n   * Example template mapping:\n      ```\n      # Template slides to use (0-based indexing)\n      # WARNING: Verify indices are within range! Template with 73 slides has indices 0-72\n      # Mapping: slide numbers from outline -> template slide indices\n      template_mapping = [\n          0,   # Use slide 0 (Title/Cover)\n          34,  # Use slide 34 (B1: Title and body)\n          34,  # Use slide 34 again (duplicate for second B1)\n          50,  # Use slide 50 (E1: Quote)\n          54,  # Use slide 54 (F2: Closing + Text)\n      ]\n      ```\n\n4. **Duplicate, reorder, and delete slides using `rearrange.py`**:\n   * Use the `scripts/rearrange.py` script to create a new presentation with slides in the desired order:\n     ```bash\n     python scripts/rearrange.py template.pptx working.pptx 0,34,34,50,52\n     ```\n   * The script handles duplicating repeated slides, deleting unused slides, and reordering automatically\n   * Slide indices are 0-based (first slide is 0, second is 1, etc.)\n   * The same slide index can appear multiple times to duplicate that slide\n\n5. **Extract ALL text using the `inventory.py` script**:\n   * **Run inventory extraction**:\n     ```bash\n     python scripts/inventory.py working.pptx text-inventory.json\n     ```\n   * **Read text-inventory.json**: Read the entire text-inventory.json file to understand all shapes and their properties. **NEVER set any range limits when reading this file.**\n\n   * The inventory JSON structure:\n      ```json\n        {\n          \"slide-0\": {\n            \"shape-0\": {\n              \"placeholder_type\": \"TITLE\",  // or null for non-placeholders\n              \"left\": 1.5,                  // position in inches\n              \"top\": 2.0,\n              \"width\": 7.5,\n              \"height\": 1.2,\n              \"paragraphs\": [\n                {\n                  \"text\": \"Paragraph text\",\n                  // Optional properties (only included when non-default):\n                  \"bullet\": true,           // explicit bullet detected\n                  \"level\": 0,               // only included when bullet is true\n                  \"alignment\": \"CENTER\",    // CENTER, RIGHT (not LEFT)\n                  \"space_before\": 10.0,     // space before paragraph in points\n                  \"space_after\": 6.0,       // space after paragraph in points\n                  \"line_spacing\": 22.4,     // line spacing in points\n                  \"font_name\": \"Arial\",     // from first run\n                  \"font_size\": 14.0,        // in points\n                  \"bold\": true,\n                  \"italic\": false,\n                  \"underline\": false,\n                  \"color\": \"FF0000\"         // RGB color\n                }\n              ]\n            }\n          }\n        }\n      ```\n\n   * Key features:\n     - **Slides**: Named as \"slide-0\", \"slide-1\", etc.\n     - **Shapes**: Ordered by visual position (top-to-bottom, left-to-right) as \"shape-0\", \"shape-1\", etc.\n     - **Placeholder types**: TITLE, CENTER_TITLE, SUBTITLE, BODY, OBJECT, or null\n     - **Default font size**: `default_font_size` in points extracted from layout placeholders (when available)\n     - **Slide numbers are filtered**: Shapes with SLIDE_NUMBER placeholder type are automatically excluded from inventory\n     - **Bullets**: When `bullet: true`, `level` is always included (even if 0)\n     - **Spacing**: `space_before`, `space_after`, and `line_spacing` in points (only included when set)\n     - **Colors**: `color` for RGB (e.g., \"FF0000\"), `theme_color` for theme colors (e.g., \"DARK_1\")\n     - **Properties**: Only non-default values are included in the output\n\n6. **Generate replacement text and save the data to a JSON file**\n   Based on the text inventory from the previous step:\n   - **CRITICAL**: First verify which shapes exist in the inventory - only reference shapes that are actually present\n   - **VALIDATION**: The replace.py script will validate that all shapes in your replacement JSON exist in the inventory\n     - If you reference a non-existent shape, you'll get an error showing available shapes\n     - If you reference a non-existent slide, you'll get an error indicating the slide doesn't exist\n     - All validation errors are shown at once before the script exits\n   - **IMPORTANT**: The replace.py script uses inventory.py internally to identify ALL text shapes\n   - **AUTOMATIC CLEARING**: ALL text shapes from the inventory will be cleared unless you provide \"paragraphs\" for them\n   - Add a \"paragraphs\" field to shapes that need content (not \"replacement_paragraphs\")\n   - Shapes without \"paragraphs\" in the replacement JSON will have their text cleared automatically\n   - Paragraphs with bullets will be automatically left aligned. Don't set the `alignment` property on when `\"bullet\": true`\n   - Generate appropriate replacement content for placeholder text\n   - Use shape size to determine appropriate content length\n   - **CRITICAL**: Include paragraph properties from the original inventory - don't just provide text\n   - **IMPORTANT**: When bullet: true, do NOT include bullet symbols (•, -, *) in text - they're added automatically\n   - **ESSENTIAL FORMATTING RULES**:\n     - Headers/titles should typically have `\"bold\": true`\n     - List items should have `\"bullet\": true, \"level\": 0` (level is required when bullet is true)\n     - Preserve any alignment properties (e.g., `\"alignment\": \"CENTER\"` for centered text)\n     - Include font properties when different from default (e.g., `\"font_size\": 14.0`, `\"font_name\": \"Lora\"`)\n     - Colors: Use `\"color\": \"FF0000\"` for RGB or `\"theme_color\": \"DARK_1\"` for theme colors\n     - The replacement script expects **properly formatted paragraphs**, not just text strings\n     - **Overlapping shapes**: Prefer shapes with larger default_font_size or more appropriate placeholder_type\n   - Save the updated inventory with replacements to `replacement-text.json`\n   - **WARNING**: Different template layouts have different shape counts - always check the actual inventory before creating replacements\n\n   Example paragraphs field showing proper formatting:\n   ```json\n   \"paragraphs\": [\n     {\n       \"text\": \"New presentation title text\",\n       \"alignment\": \"CENTER\",\n       \"bold\": true\n     },\n     {\n       \"text\": \"Section Header\",\n       \"bold\": true\n     },\n     {\n       \"text\": \"First bullet point without bullet symbol\",\n       \"bullet\": true,\n       \"level\": 0\n     },\n     {\n       \"text\": \"Red colored text\",\n       \"color\": \"FF0000\"\n     },\n     {\n       \"text\": \"Theme colored text\",\n       \"theme_color\": \"DARK_1\"\n     },\n     {\n       \"text\": \"Regular paragraph text without special formatting\"\n     }\n   ]\n   ```\n\n   **Shapes not listed in the replacement JSON are automatically cleared**:\n   ```json\n   {\n     \"slide-0\": {\n       \"shape-0\": {\n         \"paragraphs\": [...] // This shape gets new text\n       }\n       // shape-1 and shape-2 from inventory will be cleared automatically\n     }\n   }\n   ```\n\n   **Common formatting patterns for presentations**:\n   - Title slides: Bold text, sometimes centered\n   - Section headers within slides: Bold text\n   - Bullet lists: Each item needs `\"bullet\": true, \"level\": 0`\n   - Body text: Usually no special properties needed\n   - Quotes: May have special alignment or font properties\n\n7. **Apply replacements using the `replace.py` script**\n   ```bash\n   python scripts/replace.py working.pptx replacement-text.json output.pptx\n   ```\n\n   The script will:\n   - First extract the inventory of ALL text shapes using functions from inventory.py\n   - Validate that all shapes in the replacement JSON exist in the inventory\n   - Clear text from ALL shapes identified in the inventory\n   - Apply new text only to shapes with \"paragraphs\" defined in the replacement JSON\n   - Preserve formatting by applying paragraph properties from the JSON\n   - Handle bullets, alignment, font properties, and colors automatically\n   - Save the updated presentation\n\n   Example validation errors:\n   ```\n   ERROR: Invalid shapes in replacement JSON:\n     - Shape 'shape-99' not found on 'slide-0'. Available shapes: shape-0, shape-1, shape-4\n     - Slide 'slide-999' not found in inventory\n   ```\n\n   ```\n   ERROR: Replacement text made overflow worse in these shapes:\n     - slide-0/shape-2: overflow worsened by 1.25\" (was 0.00\", now 1.25\")\n   ```\n\n## Creating Thumbnail Grids\n\nTo create visual thumbnail grids of PowerPoint slides for quick analysis and reference:\n\n```bash\npython scripts/thumbnail.py template.pptx [output_prefix]\n```\n\n**Features**:\n- Creates: `thumbnails.jpg` (or `thumbnails-1.jpg`, `thumbnails-2.jpg`, etc. for large decks)\n- Default: 5 columns, max 30 slides per grid (5×6)\n- Custom prefix: `python scripts/thumbnail.py template.pptx my-grid`\n  - Note: The output prefix should include the path if you want output in a specific directory (e.g., `workspace/my-grid`)\n- Adjust columns: `--cols 4` (range: 3-6, affects slides per grid)\n- Grid limits: 3 cols = 12 slides/grid, 4 cols = 20, 5 cols = 30, 6 cols = 42\n- Slides are zero-indexed (Slide 0, Slide 1, etc.)\n\n**Use cases**:\n- Template analysis: Quickly understand slide layouts and design patterns\n- Content review: Visual overview of entire presentation\n- Navigation reference: Find specific slides by their visual appearance\n- Quality check: Verify all slides are properly formatted\n\n**Examples**:\n```bash\n# Basic usage\npython scripts/thumbnail.py presentation.pptx\n\n# Combine options: custom name, columns\npython scripts/thumbnail.py template.pptx analysis --cols 4\n```\n\n## Converting Slides to Images\n\nTo visually analyze PowerPoint slides, convert them to images using a two-step process:\n\n1. **Convert PPTX to PDF**:\n   ```bash\n   soffice --headless --convert-to pdf template.pptx\n   ```\n\n2. **Convert PDF pages to JPEG images**:\n   ```bash\n   pdftoppm -jpeg -r 150 template.pdf slide\n   ```\n   This creates files like `slide-1.jpg`, `slide-2.jpg`, etc.\n\nOptions:\n- `-r 150`: Sets resolution to 150 DPI (adjust for quality/size balance)\n- `-jpeg`: Output JPEG format (use `-png` for PNG if preferred)\n- `-f N`: First page to convert (e.g., `-f 2` starts from page 2)\n- `-l N`: Last page to convert (e.g., `-l 5` stops at page 5)\n- `slide`: Prefix for output files\n\nExample for specific range:\n```bash\npdftoppm -jpeg -r 150 -f 2 -l 5 template.pdf slide  # Converts only pages 2-5\n```\n\n## Code Style Guidelines\n**IMPORTANT**: When generating code for PPTX operations:\n- Write concise code\n- Avoid verbose variable names and redundant operations\n- Avoid unnecessary print statements\n\n## Dependencies\n\nRequired dependencies (should already be installed):\n\n- **markitdown**: `pip install \"markitdown[pptx]\"` (for text extraction from presentations)\n- **pptxgenjs**: `npm install -g pptxgenjs` (for creating presentations via html2pptx)\n- **playwright**: `npm install -g playwright` (for HTML rendering in html2pptx)\n- **react-icons**: `npm install -g react-icons react react-dom` (for icons)\n- **sharp**: `npm install -g sharp` (for SVG rasterization and image processing)\n- **LibreOffice**: `sudo apt-get install libreoffice` (for PDF conversion)\n- **Poppler**: `sudo apt-get install poppler-utils` (for pdftoppm to convert PDF to images)\n- **defusedxml**: `pip install defusedxml` (for secure XML parsing)\n","frontmatter":{"name":"pptx","description":"Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks","license":"Proprietary. LICENSE.txt has complete terms","official":true},"isInternal":false,"tokens":6804,"sizeBytes":28026},{"name":"3d.md","path":"SKILLs/remotion/rules/3d.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/3d.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/3d.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/3d.md)","tokens":300,"sizeBytes":173},{"name":"animations.md","path":"SKILLs/remotion/rules/animations.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/animations.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/animations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/animations.md)","tokens":300,"sizeBytes":189},{"name":"assets.md","path":"SKILLs/remotion/rules/assets.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/assets.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/assets.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/assets.md)","tokens":300,"sizeBytes":181},{"name":"audio.md","path":"SKILLs/remotion/rules/audio.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/audio.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/audio.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/audio.md)","tokens":300,"sizeBytes":179},{"name":"calculate-metadata.md","path":"SKILLs/remotion/rules/calculate-metadata.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/calculate-metadata.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/calculate-metadata.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/calculate-metadata.md)","tokens":300,"sizeBytes":205},{"name":"can-decode.md","path":"SKILLs/remotion/rules/can-decode.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/can-decode.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/can-decode.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/can-decode.md)","tokens":300,"sizeBytes":189},{"name":"charts.md","path":"SKILLs/remotion/rules/charts.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/charts.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/charts.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/charts.md)","tokens":300,"sizeBytes":181},{"name":"compositions.md","path":"SKILLs/remotion/rules/compositions.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/compositions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/compositions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/compositions.md)","tokens":300,"sizeBytes":193},{"name":"display-captions.md","path":"SKILLs/remotion/rules/display-captions.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/display-captions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/display-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/display-captions.md)","tokens":300,"sizeBytes":201},{"name":"extract-frames.md","path":"SKILLs/remotion/rules/extract-frames.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/extract-frames.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/extract-frames.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/extract-frames.md)","tokens":300,"sizeBytes":197},{"name":"fonts.md","path":"SKILLs/remotion/rules/fonts.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/fonts.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/fonts.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/fonts.md)","tokens":300,"sizeBytes":179},{"name":"get-audio-duration.md","path":"SKILLs/remotion/rules/get-audio-duration.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-audio-duration.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-audio-duration.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-audio-duration.md)","tokens":300,"sizeBytes":205},{"name":"get-video-dimensions.md","path":"SKILLs/remotion/rules/get-video-dimensions.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-video-dimensions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-video-dimensions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-video-dimensions.md)","tokens":300,"sizeBytes":209},{"name":"get-video-duration.md","path":"SKILLs/remotion/rules/get-video-duration.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-video-duration.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/get-video-duration.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/get-video-duration.md)","tokens":300,"sizeBytes":205},{"name":"gifs.md","path":"SKILLs/remotion/rules/gifs.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/gifs.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/gifs.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/gifs.md)","tokens":300,"sizeBytes":177},{"name":"images.md","path":"SKILLs/remotion/rules/images.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/images.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/images.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/images.md)","tokens":300,"sizeBytes":181},{"name":"import-srt-captions.md","path":"SKILLs/remotion/rules/import-srt-captions.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/import-srt-captions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/import-srt-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/import-srt-captions.md)","tokens":300,"sizeBytes":207},{"name":"light-leaks.md","path":"SKILLs/remotion/rules/light-leaks.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/light-leaks.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/light-leaks.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/light-leaks.md)","tokens":300,"sizeBytes":191},{"name":"lottie.md","path":"SKILLs/remotion/rules/lottie.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/lottie.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/lottie.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/lottie.md)","tokens":300,"sizeBytes":181},{"name":"maps.md","path":"SKILLs/remotion/rules/maps.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/maps.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/maps.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/maps.md)","tokens":300,"sizeBytes":177},{"name":"measuring-dom-nodes.md","path":"SKILLs/remotion/rules/measuring-dom-nodes.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/measuring-dom-nodes.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/measuring-dom-nodes.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/measuring-dom-nodes.md)","tokens":300,"sizeBytes":207},{"name":"measuring-text.md","path":"SKILLs/remotion/rules/measuring-text.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/measuring-text.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/measuring-text.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/measuring-text.md)","tokens":300,"sizeBytes":197},{"name":"parameters.md","path":"SKILLs/remotion/rules/parameters.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/parameters.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/parameters.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/parameters.md)","tokens":300,"sizeBytes":189},{"name":"sequencing.md","path":"SKILLs/remotion/rules/sequencing.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/sequencing.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/sequencing.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/sequencing.md)","tokens":300,"sizeBytes":189},{"name":"subtitles.md","path":"SKILLs/remotion/rules/subtitles.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/subtitles.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/subtitles.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/subtitles.md)","tokens":300,"sizeBytes":187},{"name":"tailwind.md","path":"SKILLs/remotion/rules/tailwind.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/tailwind.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/tailwind.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/tailwind.md)","tokens":300,"sizeBytes":185},{"name":"text-animations.md","path":"SKILLs/remotion/rules/text-animations.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/text-animations.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/text-animations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/text-animations.md)","tokens":300,"sizeBytes":199},{"name":"timing.md","path":"SKILLs/remotion/rules/timing.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/timing.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/timing.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/timing.md)","tokens":300,"sizeBytes":181},{"name":"transcribe-captions.md","path":"SKILLs/remotion/rules/transcribe-captions.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transcribe-captions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transcribe-captions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transcribe-captions.md)","tokens":300,"sizeBytes":207},{"name":"transitions.md","path":"SKILLs/remotion/rules/transitions.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transitions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transitions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transitions.md)","tokens":300,"sizeBytes":191},{"name":"transparent-videos.md","path":"SKILLs/remotion/rules/transparent-videos.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transparent-videos.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/transparent-videos.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/transparent-videos.md)","tokens":300,"sizeBytes":205},{"name":"trimming.md","path":"SKILLs/remotion/rules/trimming.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/trimming.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/trimming.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/trimming.md)","tokens":300,"sizeBytes":185},{"name":"videos.md","path":"SKILLs/remotion/rules/videos.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/videos.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `SKILLs/remotion/rules/videos.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/rules/videos.md)","tokens":300,"sizeBytes":181},{"name":"SKILL.md","path":"SKILLs/remotion/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/remotion/SKILL.md","title":"remotion-best-practices","category":"anthropic-skill","format":"markdown","content":"---\nname: remotion-best-practices\ndescription: Best practices for Remotion - Video creation in React\nofficial: true\nmetadata:\n  tags: remotion, video, react, animation, composition\n---\n\n## When to use\n\nUse this skills whenever you are dealing with Remotion code to obtain the domain-specific knowledge.\n\n## Captions\n\nWhen dealing with captions or subtitles, load the [./rules/subtitles.md](./rules/subtitles.md) file for more information.\n\n## How to use\n\nRead individual rule files for detailed explanations and code examples:\n\n- [rules/3d.md](rules/3d.md) - 3D content in Remotion using Three.js and React Three Fiber\n- [rules/animations.md](rules/animations.md) - Fundamental animation skills for Remotion\n- [rules/assets.md](rules/assets.md) - Importing images, videos, audio, and fonts into Remotion\n- [rules/audio.md](rules/audio.md) - Using audio and sound in Remotion - importing, trimming, volume, speed, pitch\n- [rules/calculate-metadata.md](rules/calculate-metadata.md) - Dynamically set composition duration, dimensions, and props\n- [rules/can-decode.md](rules/can-decode.md) - Check if a video can be decoded by the browser using Mediabunny\n- [rules/charts.md](rules/charts.md) - Chart and data visualization patterns for Remotion\n- [rules/compositions.md](rules/compositions.md) - Defining compositions, stills, folders, default props and dynamic metadata\n- [rules/extract-frames.md](rules/extract-frames.md) - Extract frames from videos at specific timestamps using Mediabunny\n- [rules/fonts.md](rules/fonts.md) - Loading Google Fonts and local fonts in Remotion\n- [rules/get-audio-duration.md](rules/get-audio-duration.md) - Getting the duration of an audio file in seconds with Mediabunny\n- [rules/get-video-dimensions.md](rules/get-video-dimensions.md) - Getting the width and height of a video file with Mediabunny\n- [rules/get-video-duration.md](rules/get-video-duration.md) - Getting the duration of a video file in seconds with Mediabunny\n- [rules/gifs.md](rules/gifs.md) - Displaying GIFs synchronized with Remotion's timeline\n- [rules/images.md](rules/images.md) - Embedding images in Remotion using the Img component\n- [rules/light-leaks.md](rules/light-leaks.md) - Light leak overlay effects using @remotion/light-leaks\n- [rules/lottie.md](rules/lottie.md) - Embedding Lottie animations in Remotion\n- [rules/measuring-dom-nodes.md](rules/measuring-dom-nodes.md) - Measuring DOM element dimensions in Remotion\n- [rules/measuring-text.md](rules/measuring-text.md) - Measuring text dimensions, fitting text to containers, and checking overflow\n- [rules/sequencing.md](rules/sequencing.md) - Sequencing patterns for Remotion - delay, trim, limit duration of items\n- [rules/tailwind.md](rules/tailwind.md) - Using TailwindCSS in Remotion\n- [rules/text-animations.md](rules/text-animations.md) - Typography and text animation patterns for Remotion\n- [rules/timing.md](rules/timing.md) - Interpolation curves in Remotion - linear, easing, spring animations\n- [rules/transitions.md](rules/transitions.md) - Scene transition patterns for Remotion\n- [rules/transparent-videos.md](rules/transparent-videos.md) - Rendering out a video with transparency\n- [rules/trimming.md](rules/trimming.md) - Trimming patterns for Remotion - cut the beginning or end of animations\n- [rules/videos.md](rules/videos.md) - Embedding videos in Remotion - trimming, volume, speed, looping, pitch\n- [rules/parameters.md](rules/parameters.md) - Make a video parametrizable by adding a Zod schema\n- [rules/maps.md](rules/maps.md) - Add a map using Mapbox and animate it\n","frontmatter":{"name":"remotion-best-practices","description":"Best practices for Remotion - Video creation in React","official":true,"metadata":{"tags":"remotion, video, react, animation, composition"}},"isInternal":false,"tokens":872,"sizeBytes":3562},{"name":"SKILL.md","path":"SKILLs/seedance/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/seedance/SKILL.md","title":"seedance","category":"anthropic-skill","format":"markdown","content":"---\nname: seedance\ndescription: Generate AI videos using Volcengine Seedance model. Supports text-to-video (T2V), image-to-video (I2V), and audio-synced video generation. Use this skill when the user wants to create or generate videos.\nofficial: true\nversion: 1.0.1\n---\n\n# Seedance 视频生成\n\n使用火山引擎 Seedance 模型生成高质量 AI 视频，支持文本生成视频（T2V）、图片生成视频（I2V）、音画同步等多种创作模式。\n\n> ✨ **Node.js 版本**：此脚本使用 Node.js 实现，无需 Python 环境。通过入口脚本自动检测 Node.js 运行时（优先使用系统 node，回退到 LobsterAI 内置运行时），Windows 和 Mac 用户都可以开箱即用。\n\n## 配置\n\n- **Base URL**: `https://ark.cn-beijing.volces.com/api/v3`\n- **API Key**: 从环境变量 `ARK_API_KEY` 读取\n- **认证方式**: `Authorization: Bearer {API_KEY}`\n- **SDK**: 兼容火山方舟 Python SDK\n\n### 如何配置 API Key\n\n**方式一：通过环境变量配置（推荐）**\n\n在终端中设置环境变量：\n\n```bash\n# macOS/Linux\nexport ARK_API_KEY=\"你的API密钥\"\n\n# 或者添加到 ~/.zshrc 或 ~/.bashrc 以永久生效\necho 'export ARK_API_KEY=\"你的API密钥\"' >> ~/.zshrc\nsource ~/.zshrc\n```\n\n```powershell\n# Windows PowerShell\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 或者设置系统环境变量以永久生效\n[System.Environment]::SetEnvironmentVariable('ARK_API_KEY', '你的API密钥', 'User')\n```\n\n**方式二：通过 LobsterAI 启动时注入**\n\nLobsterAI 会自动读取系统环境变量，确保在启动 LobsterAI 前已设置 `ARK_API_KEY`。\n\n**如何获取 API Key：**\n1. 访问火山方舟控制台：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n2. 创建新的 API Key\n3. 复制密钥并设置为环境变量\n\n## 前置检查\n\n**无需安装任何依赖！** 该脚本已兼容 Node.js 内置模块。\n\nLobsterAI 已包含 Node.js 运行时，所有必要的依赖已被自动打包。Windows 和 Mac 用户无需额外配置。\n\n## 工作流程\n\nSeedance 视频生成是一个异步过程：\n\n1. **提交任务** - 调用 API 创建视频生成任务，获得 `task_id`\n2. **轮询状态** - 每隔几秒查询任务状态，直到状态变为 `succeeded`\n3. **下载视频** - 从 `video_url` 字段下载生成的 MP4 文件\n\n## 配额和限制\n\n### 免费额度\n\n所有 Seedance 模型在 **default 模式（在线推理）**下提供：\n- **200万 token** 免费额度\n- flex 模式（离线推理）无免费额度\n\n**注意**：文档中未明确说明 200万 token 能生成多少个视频，消耗取决于视频时长、分辨率和是否使用图片/音频。建议先小批量测试。\n\n### 限流限制\n\n| 模型系列 | RPM（每分钟请求数） | 并发数 | TPD（离线模式每日token） |\n|---------|-------------------|--------|----------------------|\n| Pro 系列 | 600 | 10 | 5000亿 |\n| Lite 系列 | 300 | 5 | 2500亿 |\n\n- **RPM 限流**：账号下同模型每分钟允许创建的任务数量上限\n- **并发数限制**：同一时刻在处理中的任务数量上限\n- **TPD 限流**：flex 模式下一天内对同一模型的总调用 token 上限\n\n### 视频保存时间\n\n⚠️ **重要提醒**：\n- 任务数据（包括视频URL）仅保留 **24 小时**\n- 超时后会被自动清除\n- **务必及时下载保存生成的视频**\n\n## 使用示例\n\n**路径说明**：下面的示例使用 `$SKILLS_ROOT` 环境变量来引用脚本路径。LobsterAI 会自动设置这个变量，指向实际的 SKILLs 目录位置，因此无需手动修改路径。\n\n### 1. 文本生成视频（T2V）\n\n根据文字描述生成视频，适合创意激发和概念验证。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"一只小猫在草地上玩耍，阳光明媚，镜头缓缓推进\" \\\n  --duration 5 \\\n  --output generated_video.mp4\n```\n\n**示例提示词：**\n- \"写实风格，晴朗的蓝天之下，一大片白色的雏菊花田，镜头逐渐拉近，最终定格在一朵雏菊花的特写上，花瓣上有几颗晶莹的露珠\"\n- \"一辆地铁轰隆隆驶过，书页飞扬，镜头开始环绕着女孩360度旋转\"\n- \"海边日落，海浪轻拍沙滩，宁静祥和的氛围\"\n\n### 2. 图片生成视频（I2V）- 首帧引导\n\n基于首帧图片生成动态视频，**支持本地图片和网络URL**。\n\n```bash\n# 使用本地图片\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"女孩睁开眼，温柔地看向镜头，头发被风吹动\" \\\n  --image \"/Users/yourname/Pictures/girl.jpg\" \\\n  --duration 5 \\\n  --output i2v_video.mp4\n\n# 使用网络图片\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"女孩睁开眼，温柔地看向镜头，头发被风吹动\" \\\n  --image \"https://example.com/first_frame.jpg\" \\\n  --duration 5 \\\n  --output i2v_video.mp4\n```\n\n**支持的图片来源：**\n- ✅ 本地文件：`/path/to/image.jpg`\n- ✅ 网络URL：`https://example.com/image.jpg`\n- ✅ file://协议：`file:///path/to/image.jpg`\n\n**支持的图片格式：**\n- jpg, jpeg, png, gif, webp, bmp, tiff, heic\n\n### 3. 图片生成视频（I2V）- 首尾帧引导\n\n提供首帧和尾帧，生成过渡动画。**支持本地图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"360度环绕运镜，流畅过渡\" \\\n  --image \"/Users/yourname/Pictures/first_frame.jpg\" \\\n  --image \"/Users/yourname/Pictures/last_frame.jpg\" \\\n  --duration 5 \\\n  --output transition_video.mp4\n```\n\n### 4. 多参考图生成视频\n\n融合多张参考图的特征生成视频。**支持混合使用本地图片和网络图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"[图1]戴着眼镜穿着蓝色T恤的男生和[图2]的柯基小狗，坐在[图3]的草坪上，视频卡通风格\" \\\n  --image \"/Users/yourname/Pictures/person.jpg\" \\\n  --image \"https://example.com/dog.jpg\" \\\n  --image \"/Users/yourname/Pictures/grass.jpg\" \\\n  --model \"doubao-seedance-1-0-lite-i2v-250428\" \\\n  --duration 5 \\\n  --output multi_ref_video.mp4\n```\n\n### 5. 音画同步视频生成（仅 1.5 pro）\n\n生成包含音频的视频（环境音、动作音、背景音乐等）。**支持本地图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"镜头围绕人物推镜头拉近，特写人物面部，她正在用京剧唱腔唱'月移花影，疑是玉人来'，唱词充满情感\" \\\n  --image \"/Users/yourname/Pictures/actress.jpg\" \\\n  --audio \\\n  --duration 5 \\\n  --model \"doubao-seedance-1-5-pro-251215\" \\\n  --output audio_video.mp4\n```\n\n## 参数说明\n\n### 必需参数\n\n| 参数 | 说明 | 示例 |\n|-----|------|------|\n| `--prompt` | 视频描述提示词（必需） | \"小猫在玩耍\" |\n\n### 可选参数\n\n| 参数 | 说明 | 默认值 | 可选值 |\n|-----|------|-------|--------|\n| `--image` | 参考图片路径或URL（可多次使用） | 无 | 本地文件路径或URL |\n| `--model` | 模型ID | `doubao-seedance-1-5-pro-251215` | 见模型列表 |\n| `--duration` | 视频时长（秒） | 5 | 2-12（不同模型范围不同） |\n| `--ratio` | 宽高比 | `adaptive` | `adaptive`, `16:9`, `9:16`, `1:1` |\n| `--audio` | 生成音频（仅1.5 pro支持） | 否 | 标志参数 |\n| `--no-watermark` | 不添加水印 | 否 | 标志参数 |\n| `--output` | 输出文件路径 | `generated_video.mp4` | 文件路径 |\n| `--poll-interval` | 状态查询间隔（秒） | 5 | 1-10 |\n| `--timeout` | 最大等待时间（秒） | 300 | 60-600 |\n\n## 模型选择\n\n选择合适的模型以平衡质量、速度和成本：\n\n### Seedance 1.5 pro（推荐）\n\n- **模型ID**: `doubao-seedance-1-5-pro-251215`\n- **特点**: 音画同生，最高质量\n- **支持**: 文生视频、图生视频、首尾帧、有声视频\n- **输出**: 480p-1080p，24fps，4-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 pro\n\n- **模型ID**: `doubao-seedance-1-0-pro-250528`\n- **特点**: 高质量标准版本\n- **支持**: 文生视频、图生视频、首尾帧\n- **输出**: 480p-1080p，24fps，2-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 pro fast\n\n- **模型ID**: `doubao-seedance-1-0-pro-fast-251015`\n- **特点**: 快速生成，成本更低\n- **支持**: 文生视频、图生视频\n- **输出**: 480p-1080p，24fps，2-12秒\n- **限流**: RPM 600，并发10\n\n### Seedance 1.0 lite（轻量版）\n\n- **文生视频**: `doubao-seedance-1-0-lite-t2v-250428`\n- **图生视频**: `doubao-seedance-1-0-lite-i2v-250428`\n- **特点**: 更快速度，支持多参考图\n- **限流**: RPM 300，并发5\n\n### Seedance 2.0（即将支持）\n\n- **模型ID**: `doubao-seedance-2-0-260128`\n- **特点**: 下一代视频生成模型，质量和性能全面提升\n- **可用性**: ⏰ 预计 **2026年2月24日18点** 开放 API 调用\n- **当前状态**: 仅在 [控制台体验中心](https://console.volcengine.com/ark/region:ark+cn-beijing/experience/vision?modelId=doubao-seedance-2-0-260128&tab=GenVideo) 可用\n\n**使用方式（2月24日后）：**\n\n```bash\n# 命令行方式\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"你的提示词\" \\\n  --model \"doubao-seedance-2-0-260128\" \\\n  --duration 5\n```\n\n或在 LobsterAI 对话中说：\"用 Seedance 2.0 生成视频...\"\n\n**推荐使用场景：**\n- 追求最高质量 + 音画同步 → 1.5 pro\n- 标准高质量视频 → 1.0 pro\n- 快速生成预览 → 1.0 pro fast\n- 多参考图融合 → 1.0 lite\n- 下一代最新模型（2月24日后）→ 2.0\n\n## 高级选项\n\n### 自定义宽高比\n\n根据使用场景选择合适的宽高比：\n\n```bash\n# 横屏视频（适合 YouTube、B站）\n--ratio \"16:9\"\n\n# 竖屏视频（适合抖音、快手）\n--ratio \"9:16\"\n\n# 正方形视频（适合 Instagram）\n--ratio \"1:1\"\n\n# 自适应（根据内容自动选择）\n--ratio \"adaptive\"\n```\n\n### 自定义视频时长\n\n不同模型支持的时长范围不同：\n\n```bash\n# 短视频（快速生成）\n--duration 2\n\n# 标准时长\n--duration 5\n\n# 长视频（内容更丰富）\n--duration 10\n```\n\n**注意：**\n- Seedance 1.5 pro 支持 4-12 秒\n- Seedance 1.0 系列支持 2-12 秒\n- 时长越长，生成时间越久\n\n### 去除水印\n\n生成无水印视频（用于商业用途）：\n\n```bash\n--no-watermark\n```\n\n### 轮询和超时控制\n\n调整轮询策略以适应不同场景：\n\n```bash\n# 快速查询（适合短视频）\n--poll-interval 3 --timeout 180\n\n# 标准配置\n--poll-interval 5 --timeout 300\n\n# 耐心等待（适合长视频或高峰期）\n--poll-interval 10 --timeout 600\n```\n\n## 状态说明\n\n生成过程中可能出现的任务状态：\n\n| 状态 | 说明 | 操作 |\n|------|------|------|\n| `queued` | 任务排队中 | 继续等待 |\n| `running` | 正在生成视频 | 继续等待 |\n| `succeeded` | 生成成功 | 下载视频 |\n| `failed` | 生成失败 | 查看错误信息 |\n\n## 错误处理\n\n### 常见错误及解决方案\n\n**错误：未设置环境变量 ARK_API_KEY**\n- 原因：未配置 API Key\n- 解决：按照\"如何配置 API Key\"部分的说明进行配置\n\n**错误：任务创建失败 (HTTP 401)**\n- 原因：API Key 无效或已过期\n- 解决：检查 API Key 是否正确，或在控制台重新生成\n\n**错误：任务创建失败 (HTTP 400)**\n- 原因：参数错误（如 duration 超出范围）\n- 解决：检查参数是否符合模型要求\n\n**错误：任务超时**\n- 原因：生成时间过长或 API 繁忙\n- 解决：增加 `--timeout` 值，或稍后重试\n\n**错误：任务失败**\n- 原因：内容违规、提示词不清晰、图片格式错误等\n- 解决：检查提示词内容，确保图片URL可访问\n\n**错误：限流 (HTTP 429)**\n- 原因：超过 RPM 或并发限制\n- 解决：等待1分钟后重试，或升级配额\n\n## 输出格式\n\n生成的视频具有以下特征：\n\n- **格式**: MP4\n- **编码**: H.264\n- **分辨率**: 480p / 720p / 1080p（根据模型自动选择）\n- **帧率**: 24 fps\n- **音频**: AAC（如果启用 `--audio`）\n- **文件大小**: 约 2-5 MB/秒（1080p）\n\n## 提示词最佳实践\n\n### 优秀提示词的特点\n\n1. **清晰的场景描述** - 说明环境、时间、氛围\n2. **具体的动作细节** - 描述物体或人物的具体动作\n3. **镜头运动** - 说明推拉摇移、特写等镜头语言\n4. **风格指定** - 写实、卡通、动漫等风格说明\n\n### 提示词模板\n\n```\n[风格]，[场景描述]，[主体动作]，[镜头运动]，[氛围/情绪]\n```\n\n**示例：**\n```\n写实风格，海边日落，一只海鸥在空中盘旋，镜头从远处缓缓推进到海鸥特写，宁静祥和的氛围\n```\n\n### 提示词注意事项\n\n- ✅ 具体描述：\"小猫追逐蝴蝶\" 而非 \"小猫玩耍\"\n- ✅ 镜头语言：\"镜头360度环绕\" 而非 \"旋转\"\n- ✅ 情绪氛围：\"温暖明亮的阳光\" 而非 \"好天气\"\n- ❌ 避免模糊：过于抽象的描述会导致随机性增加\n- ❌ 避免过长：保持在 200 字以内效果最佳\n- ❌ 避免违规：不要包含暴力、色情等违规内容\n\n## 常见使用场景\n\n### 短视频创作\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"产品展示：智能手表从不同角度旋转展示\" \\\n  --ratio \"9:16\" \\\n  --duration 5\n```\n\n### 动画短片\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"卡通风格，小兔子在森林里蹦蹦跳跳\" \\\n  --ratio \"16:9\" \\\n  --duration 8 \\\n  --model \"doubao-seedance-1-0-pro-250528\"\n```\n\n### 社交媒体内容\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"美食特写：热气腾腾的拉面，筷子夹起面条\" \\\n  --ratio \"1:1\" \\\n  --duration 3\n```\n\n### 教学演示\n```bash\nbash \"$SKILLS_ROOT/seedance/scripts/generate-video.sh\" \\\n  --prompt \"科普动画：地球自转，太阳光照射地球表面\" \\\n  --ratio \"16:9\" \\\n  --duration 10\n```\n\n## 参考资料\n\n- API 参考：https://www.volcengine.com/docs/82379/1520758\n- 控制台：https://console.volcengine.com/ark\n- API Key 管理：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n\n## 技术支持\n\n如遇到问题，可以：\n1. 查看脚本输出的错误信息\n2. 检查 API Key 配置是否正确\n3. 访问火山方舟控制台查看任务详情\n4. 参考官网文档了解更多细节\n","frontmatter":{"name":"seedance","description":"Generate AI videos using Volcengine Seedance model. Supports text-to-video (T2V), image-to-video (I2V), and audio-synced video generation. Use this skill when the user wants to create or generate videos.","official":true,"version":"1.0.1"},"isInternal":false,"tokens":5262,"sizeBytes":14256},{"name":"SKILL.md","path":"SKILLs/seedream/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/seedream/SKILL.md","title":"seedream","category":"anthropic-skill","format":"markdown","content":"---\nname: seedream\ndescription: Generate AI images using Volcengine Seedream model. Supports text-to-image (T2I), image editing (I2I), multi-image fusion, and web-search-based generation. Use this skill when the user wants to create, generate, or edit images.\nofficial: true\nversion: 1.0.1\n---\n\n# Seedream 图片生成\n\n使用火山引擎 Seedream 模型生成高质量 AI 图片，支持文本生成图片（T2I）、图片编辑（I2I）、多图融合、组图生成、联网搜索等多种创作模式。\n\n> ✨ **Node.js 版本**：此脚本使用 Node.js 实现，无需 Python 环境。通过入口脚本自动检测 Node.js 运行时（优先使用系统 node，回退到 LobsterAI 内置运行时），Windows 和 Mac 用户都可以开箱即用。\n\n## 配置\n\n- **Base URL**: `https://ark.cn-beijing.volces.com/api/v3`\n- **API Key**: 从环境变量 `ARK_API_KEY` 读取\n- **认证方式**: `Authorization: Bearer {API_KEY}`\n- **SDK**: 兼容火山方舟 Python SDK\n\n### 快速开始\n\n**第一步：设置 API Key**\n\n```bash\n# macOS / Linux - 当前终端临时生效（立即使用）\nexport ARK_API_KEY=\"你的API密钥\"\n\n# Windows PowerShell - 当前会话临时生效\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 验证设置成功（macOS/Linux）\necho $ARK_API_KEY\n\n# 验证设置成功（Windows）\necho $env:ARK_API_KEY\n```\n\n**第二步：生成你的第一张图片**\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"一只可爱的橘色小猫\"\n```\n\n### 如何配置 API Key\n\n**方式一：通过环境变量配置（推荐）**\n\n在终端中设置环境变量：\n\n```bash\n# macOS/Linux\nexport ARK_API_KEY=\"你的API密钥\"\n\n# 或者添加到 ~/.zshrc 或 ~/.bashrc 以永久生效\necho 'export ARK_API_KEY=\"你的API密钥\"' >> ~/.zshrc\nsource ~/.zshrc\n```\n\n```powershell\n# Windows PowerShell\n$env:ARK_API_KEY=\"你的API密钥\"\n\n# 或者设置系统环境变量以永久生效\n[System.Environment]::SetEnvironmentVariable('ARK_API_KEY', '你的API密钥', 'User')\n```\n\n**方式二：通过 LobsterAI 启动时注入**\n\nLobsterAI 会自动读取系统环境变量，确保在启动 LobsterAI 前已设置 `ARK_API_KEY`。\n\n**如何获取 API Key：**\n1. 访问火山方舟控制台：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n2. 创建新的 API Key\n3. 复制密钥并设置为环境变量\n\n## 前置检查\n\n**无需安装任何依赖！** 该脚本已兼容 Node.js 内置模块。\n\nLobsterAI 已包含 Node.js 运行时，所有必要的依赖已被自动打包。Windows 和 Mac 用户无需额外配置。\n\n## 工作流程\n\nSeedream 图片生成采用**同步模式**，流程简单高效：\n\n1. **提交请求** - 调用 API 提交图片生成请求\n2. **等待生成** - API 直接处理并生成图片（通常 30-60 秒）\n3. **下载图片** - 从返回的 URL 下载生成的图片文件\n\n相比异步模式，同步模式更简单直接，无需轮询任务状态。\n\n## 配额和限制\n\n### 免费额度\n\n所有 Seedream 模型提供免费额度，具体请参见火山方舟控制台。\n\n### 限流限制\n\n- **IPM（每分钟图片数）**: 500 张/分钟（Seedream 4.5, 4.0）\n- 不同模型的限流不同，请参见官方文档\n\n### 图片保存时间\n\n⚠️ **重要提醒**：\n- 任务数据（包括图片URL）仅保留 **24 小时**\n- 超时后会被自动清除\n- **务必及时下载保存生成的图片**\n\n## 使用示例\n\n**路径说明**：下面的示例使用 `$SKILLS_ROOT` 环境变量来引用脚本路径。LobsterAI 会自动设置这个变量，指向实际的 SKILLs 目录位置，因此无需手动修改路径。\n\n### 1. 文本生成图片（T2I）\n\n根据文字描述生成图片，适合创意激发和概念设计。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"充满活力的特写编辑肖像，模特眼神犀利，头戴雕塑感帽子，色彩拼接丰富，景深较浅，Vogue杂志封面美学风格\" \\\n  --output portrait.png\n```\n\n**示例提示词：**\n- \"写实风格，晴朗的蓝天之下，一大片白色的雏菊花田，镜头逐渐拉近，最终定格在一朵雏菊花的特写上\"\n- \"卡通风格，一只橘色小猫坐在窗台上，阳光洒在身上，温暖治愈的氛围\"\n- \"赛博朋克风格，未来城市夜景，霓虹灯闪烁，高楼林立\"\n\n### 2. 图片编辑（I2I）- 单图输入\n\n基于已有图片，结合文字指令进行图像编辑。**支持本地图片和网络URL**。\n\n```bash\n# 使用本地图片\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"保持模特姿势不变，将服装材质改为透明玻璃质感\" \\\n  --image \"/Users/yourname/Pictures/model.jpg\" \\\n  --output edited_model.png\n\n# 使用网络图片\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"将背景改为海边日落场景\" \\\n  --image \"https://example.com/photo.jpg\" \\\n  --output beach_sunset.png\n```\n\n**支持的图片来源：**\n- ✅ 本地文件：`/path/to/image.jpg`\n- ✅ 网络URL：`https://example.com/image.jpg`\n- ✅ file://协议：`file:///path/to/image.jpg`\n\n**支持的图片格式：**\n- jpg, jpeg, png, gif, webp, bmp, tiff, heic\n\n### 3. 多图融合（多图输入单图输出）\n\n融合多张参考图的特征生成新图像。**支持混合使用本地图片和网络图片**。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"将图1的服装换为图2的服装\" \\\n  --image \"/Users/yourname/Pictures/person.jpg\" \\\n  --image \"https://example.com/clothes.jpg\" \\\n  --output fusion_result.png\n```\n\n**常见使用场景：**\n- 服装试穿：人物图 + 服装图 → 穿搭效果图\n- 风格迁移：照片 + 风格参考图 → 风格化作品\n- 场景融合：人物 + 背景 → 合成场景\n\n### 4. 组图生成（多图输出）\n\n生成一组内容关联的图片，适合漫画分镜、品牌视觉等。\n\n#### 文生组图\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"生成一组共4张连贯插画，核心为同一庭院一角的四季变迁，以统一风格展现四季独特色彩、元素与氛围\" \\\n  --sequential \\\n  --max-images 4 \\\n  --output seasons.png\n```\n\n输出文件会自动编号：`seasons_1.png`, `seasons_2.png`, `seasons_3.png`, `seasons_4.png`\n\n#### 单图生组图\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"参考这个LOGO，做一套户外运动品牌视觉设计，品牌名称为'GREEN'，包括包装袋、帽子、卡片、挂绳等\" \\\n  --image \"/Users/yourname/Pictures/logo.png\" \\\n  --sequential \\\n  --max-images 4 \\\n  --output brand_design.png\n```\n\n### 5. 联网搜索增强生成（Seedream 5.0 lite）\n\n启用实时网络搜索，融合最新网络信息。\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"搜索下近期热门的白鸭子单手拿着风车形象，以极具冲击力的视角，设计成巨型装置\" \\\n  --search \\\n  --output search_result.png\n```\n\n**注意**：\n- 联网搜索功能仅限 Seedream 5.0 lite 模型\n- 使用 `--search` 参数会自动切换到 5.0 lite 模型\n- 适合需要融合实时信息的创作场景\n\n## 参数说明\n\n### 必需参数\n\n| 参数 | 说明 | 示例 |\n|-----|------|------|\n| `--prompt` | 图片描述提示词（必需） | \"一只可爱的小猫\" |\n\n### 可选参数\n\n| 参数 | 说明 | 默认值 | 可选值 |\n|-----|------|-------|--------|\n| `--image` | 参考图片路径或URL（可多次使用） | 无 | 本地文件路径或URL |\n| `--model` | 模型ID | `doubao-seedream-4-5-251128` | 见模型列表 |\n| `--size` | 图片尺寸 | `2K` | `1K`, `2K`, `4K` |\n| `--no-watermark` | 不添加水印 | 否 | 标志参数 |\n| `--sequential` | 生成组图 | 否 | 标志参数 |\n| `--max-images` | 组图数量 | 4 | 1-8 |\n| `--search` | 启用联网搜索 | 否 | 标志参数 |\n| `--output` | 输出文件路径 | `generated_image.png` | 文件路径 |\n| `--poll-interval` | 状态查询间隔（秒） | 5 | 1-10 |\n| `--timeout` | 最大等待时间（秒） | 300 | 60-600 |\n\n## 模型选择\n\n选择合适的模型以平衡质量、速度和成本：\n\n### Seedream 4.5（推荐）\n\n- **模型ID**: `doubao-seedream-4-5-251128`\n- **特点**: 最新版本，综合质量最佳\n- **支持**: 文生图、图生图、多图融合、组图生成\n- **输出**: 1K-4K分辨率可选\n- **限流**: IPM 500\n\n### Seedream 4.0\n\n- **模型ID**: `doubao-seedream-4-0-250828`\n- **特点**: 成熟稳定版本\n- **支持**: 文生图、图生图、多图融合、组图生成\n- **输出**: 1K-4K分辨率可选\n- **限流**: IPM 500\n\n### Seedream 5.0 lite（联网搜索专用）\n\n- **模型ID**: `doubao-seedream-5-0-260128`\n- **特点**: 支持联网搜索，融合实时网络信息\n- **使用**: 通过 `--search` 参数自动启用\n- **注意**: 2026年2月24日18点后正式开放 API\n\n**推荐使用场景：**\n- 追求最高质量 → 4.5\n- 稳定生产环境 → 4.0\n- 需要实时信息 → 5.0 lite（使用 `--search`）\n\n## 高级选项\n\n### 自定义图片尺寸\n\n根据使用场景选择合适的尺寸：\n\n```bash\n# 小尺寸（快速预览）\n--size \"1K\"\n\n# 标准尺寸（推荐）\n--size \"2K\"\n\n# 高清晰度\n--size \"4K\"\n```\n\n**注意：**\n- 尺寸越大，生成时间越长\n- 4K 图片可能需要 40-60 秒\n\n### 去除水印\n\n生成无水印图片（用于商业用途）：\n\n```bash\n--no-watermark\n```\n\n### 轮询和超时控制\n\n调整轮询策略以适应不同场景：\n\n```bash\n# 快速查询（适合小图）\n--poll-interval 3 --timeout 180\n\n# 标准配置\n--poll-interval 5 --timeout 300\n\n# 耐心等待（适合4K或组图）\n--poll-interval 10 --timeout 600\n```\n\n## 状态说明\n\n生成过程中可能出现的任务状态：\n\n| 状态 | 说明 | 操作 |\n|------|------|------|\n| `queued` | 任务排队中 | 继续等待 |\n| `running` | 正在生成图片 | 继续等待 |\n| `succeeded` | 生成成功 | 下载图片 |\n| `failed` | 生成失败 | 查看错误信息 |\n\n## 错误处理\n\n### 常见错误及解决方案\n\n**错误：未设置环境变量 ARK_API_KEY**\n- 原因：未配置 API Key\n- 解决：按照\"如何配置 API Key\"部分的说明进行配置\n\n**错误：任务创建失败 (HTTP 401)**\n- 原因：API Key 无效或已过期\n- 解决：检查 API Key 是否正确，或在控制台重新生成\n\n**错误：任务创建失败 (HTTP 400)**\n- 原因：参数错误（如 size 不支持、prompt 为空等）\n- 解决：检查参数是否符合要求\n\n**错误：任务超时**\n- 原因：生成时间过长或 API 繁忙\n- 解决：增加 `--timeout` 值，或稍后重试\n\n**错误：任务失败**\n- 原因：内容违规、提示词不清晰、图片格式错误等\n- 解决：检查提示词内容，确保图片URL可访问\n\n**错误：限流 (HTTP 429)**\n- 原因：超过 IPM 限制\n- 解决：等待1分钟后重试，或升级配额\n\n**错误：图片文件不存在**\n- 原因：本地图片路径错误\n- 解决：检查文件路径是否正确，使用绝对路径\n\n## 输出格式\n\n生成的图片具有以下特征：\n\n- **格式**: PNG, JPEG（根据output参数自动识别）\n- **分辨率**: 1K / 2K / 4K（根据 size 参数）\n- **文件大小**: 约 0.5-10 MB（取决于尺寸和复杂度）\n- **命名规则**:\n  - 单图：指定的文件名\n  - 组图：`文件名_1.png`, `文件名_2.png`, ...\n\n## 提示词最佳实践\n\n### 优秀提示词的特点\n\n1. **清晰的主体描述** - 说明画面的主要内容\n2. **具体的风格指定** - 写实、卡通、赛博朋克等\n3. **细节补充** - 色彩、光线、氛围等\n4. **构图说明** - 特写、全景、俯视等视角\n\n### 提示词模板\n\n```\n[风格]，[主体描述]，[细节补充]，[构图/氛围]\n```\n\n**示例：**\n```\n写实风格，一只橘色小猫坐在木制窗台上，阳光从左侧洒进来，温暖治愈的氛围，特写构图\n```\n\n### 提示词注意事项\n\n- ✅ 具体描述：\"小猫在追逐蝴蝶\" 而非 \"小猫玩耍\"\n- ✅ 风格说明：\"赛博朋克风格\" 而非 \"好看的\"\n- ✅ 细节丰富：\"橘色长毛小猫，蓝色眼睛\" 而非 \"猫\"\n- ❌ 避免模糊：过于抽象的描述会导致随机性增加\n- ❌ 避免过长：保持在 200 字以内效果最佳\n- ❌ 避免违规：不要包含暴力、色情等违规内容\n\n## 常见使用场景\n\n### 产品设计\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"现代简约风格，智能手表产品展示，白色背景，工作室灯光\" \\\n  --size \"4K\"\n```\n\n### 艺术创作\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"超现实主义，漂浮的岛屿，瀑布从天而降，梦幻色彩\" \\\n  --size \"2K\"\n```\n\n### 社交媒体内容\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"美食特写，热气腾腾的拉面，筷子夹起面条，暖色调\" \\\n  --size \"2K\"\n```\n\n### 品牌视觉设计\n\n```bash\nbash \"$SKILLS_ROOT/seedream/scripts/generate-image.sh\" \\\n  --prompt \"参考logo，生成一套完整的品牌视觉系统，包括名片、海报、包装设计\" \\\n  --image brand_logo.png \\\n  --sequential \\\n  --max-images 4\n```\n\n## 参考资料\n\n- API 参考：https://www.volcengine.com/docs/82379/1541523\n- 控制台：https://console.volcengine.com/ark\n- API Key 管理：https://console.volcengine.com/ark/region:ark+cn-beijing/apikey\n- 模型列表：https://www.volcengine.com/docs/82379/1330310\n\n## 技术支持\n\n如遇到问题，可以：\n1. 查看脚本输出的错误信息\n2. 检查 API Key 配置是否正确\n3. 访问火山方舟控制台查看任务详情\n4. 参考官网文档了解更多细节\n","frontmatter":{"name":"seedream","description":"Generate AI images using Volcengine Seedream model. Supports text-to-image (T2I), image editing (I2I), multi-image fusion, and web-search-based generation. Use this skill when the user wants to create, generate, or edit images.","official":true,"version":"1.0.1"},"isInternal":false,"tokens":4947,"sizeBytes":13609},{"name":"schemas.md","path":"SKILLs/skill-creator/references/schemas.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/references/schemas.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `SKILLs/skill-creator/references/schemas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/references/schemas.md)","tokens":300,"sizeBytes":208},{"name":"SKILL.md","path":"SKILLs/skill-creator/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/SKILL.md","title":"skill-creator","category":"anthropic-skill","format":"markdown","content":"---\nname: skill-creator\ndescription: Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, update or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.\nofficial: true\nversion: 1.0.1\n---\n\n# Skill Creator\n\nA skill for creating new skills and iteratively improving them.\n\nAt a high level, the process of creating a skill goes like this:\n\n- Decide what you want the skill to do and roughly how it should do it\n- Write a draft of the skill\n- Create a few test prompts and run claude-with-access-to-the-skill on them\n- Help the user evaluate the results both qualitatively and quantitatively\n  - While the runs happen in the background, draft some quantitative evals if there aren't any (if there are some, you can either use as is or modify if you feel something needs to change about them). Then explain them to the user (or if they already existed, explain the ones that already exist)\n  - Use the `eval-viewer/generate_review.py` script to show the user the results for them to look at, and also let them look at the quantitative metrics\n- Rewrite the skill based on feedback from the user's evaluation of the results (and also if there are any glaring flaws that become apparent from the quantitative benchmarks)\n- Repeat until you're satisfied\n- Expand the test set and try again at larger scale\n\nYour job when using this skill is to figure out where the user is in this process and then jump in and help them progress through these stages. So for instance, maybe they're like \"I want to make a skill for X\". You can help narrow down what they mean, write a draft, write the test cases, figure out how they want to evaluate, run all the prompts, and repeat.\n\nOn the other hand, maybe they already have a draft of the skill. In this case you can go straight to the eval/iterate part of the loop.\n\nOf course, you should always be flexible and if the user is like \"I don't need to run a bunch of evaluations, just vibe with me\", you can do that instead.\n\nThen after the skill is done (but again, the order is flexible), you can also run the skill description improver, which we have a whole separate script for, to optimize the triggering of the skill.\n\nCool? Cool.\n\n## Communicating with the user\n\nThe skill creator is liable to be used by people across a wide range of familiarity with coding jargon. If you haven't heard (and how could you, it's only very recently that it started), there's a trend now where the power of Claude is inspiring plumbers to open up their terminals, parents and grandparents to google \"how to install npm\". On the other hand, the bulk of users are probably fairly computer-literate.\n\nSo please pay attention to context cues to understand how to phrase your communication! In the default case, just to give you some idea:\n\n- \"evaluation\" and \"benchmark\" are borderline, but OK\n- for \"JSON\" and \"assertion\" you want to see serious cues from the user that they know what those things are before using them without explaining them\n\nIt's OK to briefly explain terms if you're in doubt, and feel free to clarify terms with a short definition if you're unsure if the user will get it.\n\n---\n\n## Creating a skill\n\n### Capture Intent\n\nStart by understanding the user's intent. The current conversation might already contain a workflow the user wants to capture (e.g., they say \"turn this into a skill\"). If so, extract answers from the conversation history first — the tools used, the sequence of steps, corrections the user made, input/output formats observed. The user may need to fill the gaps, and should confirm before proceeding to the next step.\n\n1. What should this skill enable Claude to do?\n2. When should this skill trigger? (what user phrases/contexts)\n3. What's the expected output format?\n4. Should we set up test cases to verify the skill works? Skills with objectively verifiable outputs (file transforms, data extraction, code generation, fixed workflow steps) benefit from test cases. Skills with subjective outputs (writing style, art) often don't need them. Suggest the appropriate default based on the skill type, but let the user decide.\n\n### Interview and Research\n\nProactively ask questions about edge cases, input/output formats, example files, success criteria, and dependencies. Wait to write test prompts until you've got this part ironed out.\n\nCheck available MCPs - if useful for research (searching docs, finding similar skills, looking up best practices), research in parallel via subagents if available, otherwise inline. Come prepared with context to reduce burden on the user.\n\n### Write the SKILL.md\n\nBased on the user interview, fill in these components:\n\n- **name**: Skill identifier\n- **description**: When to trigger, what it does. This is the primary triggering mechanism - include both what the skill does AND specific contexts for when to use it. All \"when to use\" info goes here, not in the body. Note: currently Claude has a tendency to \"undertrigger\" skills -- to not use them when they'd be useful. To combat this, please make the skill descriptions a little bit \"pushy\". So for instance, instead of \"How to build a simple fast dashboard to display internal Anthropic data.\", you might write \"How to build a simple fast dashboard to display internal Anthropic data. Make sure to use this skill whenever the user mentions dashboards, data visualization, internal metrics, or wants to display any kind of company data, even if they don't explicitly ask for a 'dashboard.'\"\n- **compatibility**: Required tools, dependencies (optional, rarely needed)\n- **the rest of the skill :)**\n\n### Skill Writing Guide\n\n#### Anatomy of a Skill\n\n```\nskill-name/\n├── SKILL.md (required)\n│   ├── YAML frontmatter (name, description required)\n│   └── Markdown instructions\n└── Bundled Resources (optional)\n    ├── scripts/    - Executable code for deterministic/repetitive tasks\n    ├── references/ - Docs loaded into context as needed\n    └── assets/     - Files used in output (templates, icons, fonts)\n```\n\n#### Progressive Disclosure\n\nSkills use a three-level loading system:\n1. **Metadata** (name + description) - Always in context (~100 words)\n2. **SKILL.md body** - In context whenever skill triggers (<500 lines ideal)\n3. **Bundled resources** - As needed (unlimited, scripts can execute without loading)\n\nThese word counts are approximate and you can feel free to go longer if needed.\n\n**Key patterns:**\n- Keep SKILL.md under 500 lines; if you're approaching this limit, add an additional layer of hierarchy along with clear pointers about where the model using the skill should go next to follow up.\n- Reference files clearly from SKILL.md with guidance on when to read them\n- For large reference files (>300 lines), include a table of contents\n\n**Domain organization**: When a skill supports multiple domains/frameworks, organize by variant:\n```\ncloud-deploy/\n├── SKILL.md (workflow + selection)\n└── references/\n    ├── aws.md\n    ├── gcp.md\n    └── azure.md\n```\nClaude reads only the relevant reference file.\n\n#### Principle of Lack of Surprise\n\nThis goes without saying, but skills must not contain malware, exploit code, or any content that could compromise system security. A skill's contents should not surprise the user in their intent if described. Don't go along with requests to create misleading skills or skills designed to facilitate unauthorized access, data exfiltration, or other malicious activities. Things like a \"roleplay as an XYZ\" are OK though.\n\n#### Writing Patterns\n\nPrefer using the imperative form in instructions.\n\n**Defining output formats** - You can do it like this:\n```markdown\n## Report structure\nALWAYS use this exact template:\n# [Title]\n## Executive summary\n## Key findings\n## Recommendations\n```\n\n**Examples pattern** - It's useful to include examples. You can format them like this (but if \"Input\" and \"Output\" are in the examples you might want to deviate a little):\n```markdown\n## Commit message format\n**Example 1:**\nInput: Added user authentication with JWT tokens\nOutput: feat(auth): implement JWT-based authentication\n```\n\n### Writing Style\n\nTry to explain to the model why things are important in lieu of heavy-handed musty MUSTs. Use theory of mind and try to make the skill general and not super-narrow to specific examples. Start by writing a draft and then look at it with fresh eyes and improve it.\n\n### Test Cases\n\nAfter writing the skill draft, come up with 2-3 realistic test prompts — the kind of thing a real user would actually say. Share them with the user: [you don't have to use this exact language] \"Here are a few test cases I'd like to try. Do these look right, or do you want to add more?\" Then run them.\n\nSave test cases to `evals/evals.json`. Don't write assertions yet — just the prompts. You'll draft assertions in the next step while the runs are in progress.\n\n```json\n{\n  \"skill_name\": \"example-skill\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"prompt\": \"User's task prompt\",\n      \"expected_output\": \"Description of expected result\",\n      \"files\": []\n    }\n  ]\n}\n```\n\nSee `references/schemas.md` for the full schema (including the `assertions` field, which you'll add later).\n\n## Running and evaluating test cases\n\nThis section is one continuous sequence — don't stop partway through. Do NOT use `/skill-test` or any other testing skill.\n\nPut results in `<skill-name>-workspace/` as a sibling to the skill directory. Within the workspace, organize results by iteration (`iteration-1/`, `iteration-2/`, etc.) and within that, each test case gets a directory (`eval-0/`, `eval-1/`, etc.). Don't create all of this upfront — just create directories as you go.\n\n### Step 1: Spawn all runs (with-skill AND baseline) in the same turn\n\nFor each test case, spawn two subagents in the same turn — one with the skill, one without. This is important: don't spawn the with-skill runs first and then come back for baselines later. Launch everything at once so it all finishes around the same time.\n\n**With-skill run:**\n\n```\nExecute this task:\n- Skill path: <path-to-skill>\n- Task: <eval prompt>\n- Input files: <eval files if any, or \"none\">\n- Save outputs to: <workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/\n- Outputs to save: <what the user cares about — e.g., \"the .docx file\", \"the final CSV\">\n```\n\n**Baseline run** (same prompt, but the baseline depends on context):\n- **Creating a new skill**: no skill at all. Same prompt, no skill path, save to `without_skill/outputs/`.\n- **Improving an existing skill**: the old version. Before editing, snapshot the skill (`cp -r <skill-path> <workspace>/skill-snapshot/`), then point the baseline subagent at the snapshot. Save to `old_skill/outputs/`.\n\nWrite an `eval_metadata.json` for each test case (assertions can be empty for now). Give each eval a descriptive name based on what it's testing — not just \"eval-0\". Use this name for the directory too. If this iteration uses new or modified eval prompts, create these files for each new eval directory — don't assume they carry over from previous iterations.\n\n```json\n{\n  \"eval_id\": 0,\n  \"eval_name\": \"descriptive-name-here\",\n  \"prompt\": \"The user's task prompt\",\n  \"assertions\": []\n}\n```\n\n### Step 2: While runs are in progress, draft assertions\n\nDon't just wait for the runs to finish — you can use this time productively. Draft quantitative assertions for each test case and explain them to the user. If assertions already exist in `evals/evals.json`, review them and explain what they check.\n\nGood assertions are objectively verifiable and have descriptive names — they should read clearly in the benchmark viewer so someone glancing at the results immediately understands what each one checks. Subjective skills (writing style, design quality) are better evaluated qualitatively — don't force assertions onto things that need human judgment.\n\nUpdate the `eval_metadata.json` files and `evals/evals.json` with the assertions once drafted. Also explain to the user what they'll see in the viewer — both the qualitative outputs and the quantitative benchmark.\n\n### Step 3: As runs complete, capture timing data\n\nWhen each subagent task completes, you receive a notification containing `total_tokens` and `duration_ms`. Save this data immediately to `timing.json` in the run directory:\n\n```json\n{\n  \"total_tokens\": 84852,\n  \"duration_ms\": 23332,\n  \"total_duration_seconds\": 23.3\n}\n```\n\nThis is the only opportunity to capture this data — it comes through the task notification and isn't persisted elsewhere. Process each notification as it arrives rather than trying to batch them.\n\n### Step 4: Grade, aggregate, and launch the viewer\n\nOnce all runs are done:\n\n1. **Grade each run** — spawn a grader subagent (or grade inline) that reads `agents/grader.md` and evaluates each assertion against the outputs. Save results to `grading.json` in each run directory. The grading.json expectations array must use the fields `text`, `passed`, and `evidence` (not `name`/`met`/`details` or other variants) — the viewer depends on these exact field names. For assertions that can be checked programmatically, write and run a script rather than eyeballing it — scripts are faster, more reliable, and can be reused across iterations.\n\n2. **Aggregate into benchmark** — run the aggregation script from the skill-creator directory:\n   ```bash\n   python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>\n   ```\n   This produces `benchmark.json` and `benchmark.md` with pass_rate, time, and tokens for each configuration, with mean ± stddev and the delta. If generating benchmark.json manually, see `references/schemas.md` for the exact schema the viewer expects.\nPut each with_skill version before its baseline counterpart.\n\n3. **Do an analyst pass** — read the benchmark data and surface patterns the aggregate stats might hide. See `agents/analyzer.md` (the \"Analyzing Benchmark Results\" section) for what to look for — things like assertions that always pass regardless of skill (non-discriminating), high-variance evals (possibly flaky), and time/token tradeoffs.\n\n4. **Launch the viewer** with both qualitative outputs and quantitative data:\n   ```bash\n   nohup python <skill-creator-path>/eval-viewer/generate_review.py \\\n     <workspace>/iteration-N \\\n     --skill-name \"my-skill\" \\\n     --benchmark <workspace>/iteration-N/benchmark.json \\\n     > /dev/null 2>&1 &\n   VIEWER_PID=$!\n   ```\n   For iteration 2+, also pass `--previous-workspace <workspace>/iteration-<N-1>`.\n\n   **Cowork / headless environments:** If `webbrowser.open()` is not available or the environment has no display, use `--static <output_path>` to write a standalone HTML file instead of starting a server. Feedback will be downloaded as a `feedback.json` file when the user clicks \"Submit All Reviews\". After download, copy `feedback.json` into the workspace directory for the next iteration to pick up.\n\nNote: please use generate_review.py to create the viewer; there's no need to write custom HTML.\n\n5. **Tell the user** something like: \"I've opened the results in your browser. There are two tabs — 'Outputs' lets you click through each test case and leave feedback, 'Benchmark' shows the quantitative comparison. When you're done, come back here and let me know.\"\n\n### What the user sees in the viewer\n\nThe \"Outputs\" tab shows one test case at a time:\n- **Prompt**: the task that was given\n- **Output**: the files the skill produced, rendered inline where possible\n- **Previous Output** (iteration 2+): collapsed section showing last iteration's output\n- **Formal Grades** (if grading was run): collapsed section showing assertion pass/fail\n- **Feedback**: a textbox that auto-saves as they type\n- **Previous Feedback** (iteration 2+): their comments from last time, shown below the textbox\n\nThe \"Benchmark\" tab shows the stats summary: pass rates, timing, and token usage for each configuration, with per-eval breakdowns and analyst observations.\n\nNavigation is via prev/next buttons or arrow keys. When done, they click \"Submit All Reviews\" which saves all feedback to `feedback.json`.\n\n### Step 5: Read the feedback\n\nWhen the user tells you they're done, read `feedback.json`:\n\n```json\n{\n  \"reviews\": [\n    {\"run_id\": \"eval-0-with_skill\", \"feedback\": \"the chart is missing axis labels\", \"timestamp\": \"...\"},\n    {\"run_id\": \"eval-1-with_skill\", \"feedback\": \"\", \"timestamp\": \"...\"},\n    {\"run_id\": \"eval-2-with_skill\", \"feedback\": \"perfect, love this\", \"timestamp\": \"...\"}\n  ],\n  \"status\": \"complete\"\n}\n```\n\nEmpty feedback means the user thought it was fine. Focus your improvements on the test cases where the user had specific complaints.\n\nKill the viewer server when you're done with it:\n\n```bash\nkill $VIEWER_PID 2>/dev/null\n```\n\n---\n\n## Improving the skill\n\nThis is the heart of the loop. You've run the test cases, the user has reviewed the results, and now you need to make the skill better based on their feedback.\n\n### How to think about improvements\n\n1. **Generalize from the feedback.** The big picture thing that's happening here is that we're trying to create skills that can be used a million times (maybe literally, maybe even more who knows) across many different prompts. Here you and the user are iterating on only a few examples over and over again because it helps move faster. The user knows these examples in and out and it's quick for them to assess new outputs. But if the skill you and the user are codeveloping works only for those examples, it's useless. Rather than put in fiddly overfitty changes, or oppressively constrictive MUSTs, if there's some stubborn issue, you might try branching out and using different metaphors, or recommending different patterns of working. It's relatively cheap to try and maybe you'll land on something great.\n\n2. **Keep the prompt lean.** Remove things that aren't pulling their weight. Make sure to read the transcripts, not just the final outputs — if it looks like the skill is making the model waste a bunch of time doing things that are unproductive, you can try getting rid of the parts of the skill that are making it do that and seeing what happens.\n\n3. **Explain the why.** Try hard to explain the **why** behind everything you're asking the model to do. Today's LLMs are *smart*. They have good theory of mind and when given a good harness can go beyond rote instructions and really make things happen. Even if the feedback from the user is terse or frustrated, try to actually understand the task and why the user is writing what they wrote, and what they actually wrote, and then transmit this understanding into the instructions. If you find yourself writing ALWAYS or NEVER in all caps, or using super rigid structures, that's a yellow flag — if possible, reframe and explain the reasoning so that the model understands why the thing you're asking for is important. That's a more humane, powerful, and effective approach.\n\n4. **Look for repeated work across test cases.** Read the transcripts from the test runs and notice if the subagents all independently wrote similar helper scripts or took the same multi-step approach to something. If all 3 test cases resulted in the subagent writing a `create_docx.py` or a `build_chart.py`, that's a strong signal the skill should bundle that script. Write it once, put it in `scripts/`, and tell the skill to use it. This saves every future invocation from reinventing the wheel.\n\nThis task is pretty important (we are trying to create billions a year in economic value here!) and your thinking time is not the blocker; take your time and really mull things over. I'd suggest writing a draft revision and then looking at it anew and making improvements. Really do your best to get into the head of the user and understand what they want and need.\n\n### The iteration loop\n\nAfter improving the skill:\n\n1. Apply your improvements to the skill\n2. Rerun all test cases into a new `iteration-<N+1>/` directory, including baseline runs. If you're creating a new skill, the baseline is always `without_skill` (no skill) — that stays the same across iterations. If you're improving an existing skill, use your judgment on what makes sense as the baseline: the original version the user came in with, or the previous iteration.\n3. Launch the reviewer with `--previous-workspace` pointing at the previous iteration\n4. Wait for the user to review and tell you they're done\n5. Read the new feedback, improve again, repeat\n\nKeep going until:\n- The user says they're happy\n- The feedback is all empty (everything looks good)\n- You're not making meaningful progress\n\n---\n\n## Advanced: Blind comparison\n\nFor situations where you want a more rigorous comparison between two versions of a skill (e.g., the user asks \"is the new version actually better?\"), there's a blind comparison system. Read `agents/comparator.md` and `agents/analyzer.md` for the details. The basic idea is: give two outputs to an independent agent without telling it which is which, and let it judge quality. Then analyze why the winner won.\n\nThis is optional, requires subagents, and most users won't need it. The human review loop is usually sufficient.\n\n---\n\n## Description Optimization\n\nThe description field in SKILL.md frontmatter is the primary mechanism that determines whether Claude invokes a skill. After creating or improving a skill, offer to optimize the description for better triggering accuracy.\n\n### Step 1: Generate trigger eval queries\n\nCreate 20 eval queries — a mix of should-trigger and should-not-trigger. Save as JSON:\n\n```json\n[\n  {\"query\": \"the user prompt\", \"should_trigger\": true},\n  {\"query\": \"another prompt\", \"should_trigger\": false}\n]\n```\n\nThe queries must be realistic and something a Claude Code or Claude.ai user would actually type. Not abstract requests, but requests that are concrete and specific and have a good amount of detail. For instance, file paths, personal context about the user's job or situation, column names and values, company names, URLs. A little bit of backstory. Some might be in lowercase or contain abbreviations or typos or casual speech. Use a mix of different lengths, and focus on edge cases rather than making them clear-cut (the user will get a chance to sign off on them).\n\nBad: `\"Format this data\"`, `\"Extract text from PDF\"`, `\"Create a chart\"`\n\nGood: `\"ok so my boss just sent me this xlsx file (its in my downloads, called something like 'Q4 sales final FINAL v2.xlsx') and she wants me to add a column that shows the profit margin as a percentage. The revenue is in column C and costs are in column D i think\"`\n\nFor the **should-trigger** queries (8-10), think about coverage. You want different phrasings of the same intent — some formal, some casual. Include cases where the user doesn't explicitly name the skill or file type but clearly needs it. Throw in some uncommon use cases and cases where this skill competes with another but should win.\n\nFor the **should-not-trigger** queries (8-10), the most valuable ones are the near-misses — queries that share keywords or concepts with the skill but actually need something different. Think adjacent domains, ambiguous phrasing where a naive keyword match would trigger but shouldn't, and cases where the query touches on something the skill does but in a context where another tool is more appropriate.\n\nThe key thing to avoid: don't make should-not-trigger queries obviously irrelevant. \"Write a fibonacci function\" as a negative test for a PDF skill is too easy — it doesn't test anything. The negative cases should be genuinely tricky.\n\n### Step 2: Review with user\n\nPresent the eval set to the user for review using the HTML template:\n\n1. Read the template from `assets/eval_review.html`\n2. Replace the placeholders:\n   - `__EVAL_DATA_PLACEHOLDER__` → the JSON array of eval items (no quotes around it — it's a JS variable assignment)\n   - `__SKILL_NAME_PLACEHOLDER__` → the skill's name\n   - `__SKILL_DESCRIPTION_PLACEHOLDER__` → the skill's current description\n3. Write to a temp file (e.g., `/tmp/eval_review_<skill-name>.html`) and open it: `open /tmp/eval_review_<skill-name>.html`\n4. The user can edit queries, toggle should-trigger, add/remove entries, then click \"Export Eval Set\"\n5. The file downloads to `~/Downloads/eval_set.json` — check the Downloads folder for the most recent version in case there are multiple (e.g., `eval_set (1).json`)\n\nThis step matters — bad eval queries lead to bad descriptions.\n\n### Step 3: Run the optimization loop\n\nTell the user: \"This will take some time — I'll run the optimization loop in the background and check on it periodically.\"\n\nSave the eval set to the workspace, then run in the background:\n\n```bash\npython -m scripts.run_loop \\\n  --eval-set <path-to-trigger-eval.json> \\\n  --skill-path <path-to-skill> \\\n  --model <model-id-powering-this-session> \\\n  --max-iterations 5 \\\n  --verbose\n```\n\nUse the model ID from your system prompt (the one powering the current session) so the triggering test matches what the user actually experiences.\n\nWhile it runs, periodically tail the output to give the user updates on which iteration it's on and what the scores look like.\n\nThis handles the full optimization loop automatically. It splits the eval set into 60% train and 40% held-out test, evaluates the current description (running each query 3 times to get a reliable trigger rate), then calls Claude with extended thinking to propose improvements based on what failed. It re-evaluates each new description on both train and test, iterating up to 5 times. When it's done, it opens an HTML report in the browser showing the results per iteration and returns JSON with `best_description` — selected by test score rather than train score to avoid overfitting.\n\n### How skill triggering works\n\nUnderstanding the triggering mechanism helps design better eval queries. Skills appear in Claude's `available_skills` list with their name + description, and Claude decides whether to consult a skill based on that description. The important thing to know is that Claude only consults skills for tasks it can't easily handle on its own — simple, one-step queries like \"read this PDF\" may not trigger a skill even if the description matches perfectly, because Claude can handle them directly with basic tools. Complex, multi-step, or specialized queries reliably trigger skills when the description matches.\n\nThis means your eval queries should be substantive enough that Claude would actually benefit from consulting a skill. Simple queries like \"read file X\" are poor test cases — they won't trigger skills regardless of description quality.\n\n### Step 4: Apply the result\n\nTake `best_description` from the JSON output and update the skill's SKILL.md frontmatter. Show the user before/after and report the scores.\n\n---\n\n### Package and Present (only if `present_files` tool is available)\n\nCheck whether you have access to the `present_files` tool. If you don't, skip this step. If you do, package the skill and present the .skill file to the user:\n\n```bash\npython -m scripts.package_skill <path/to/skill-folder>\n```\n\nAfter packaging, direct the user to the resulting `.skill` file path so they can install it.\n\n---\n\n## Claude.ai-specific instructions\n\nIn Claude.ai, the core workflow is the same (draft → test → review → improve → repeat), but because Claude.ai doesn't have subagents, some mechanics change. Here's what to adapt:\n\n**Running test cases**: No subagents means no parallel execution. For each test case, read the skill's SKILL.md, then follow its instructions to accomplish the test prompt yourself. Do them one at a time. This is less rigorous than independent subagents (you wrote the skill and you're also running it, so you have full context), but it's a useful sanity check — and the human review step compensates. Skip the baseline runs — just use the skill to complete the task as requested.\n\n**Reviewing results**: If you can't open a browser (e.g., Claude.ai's VM has no display, or you're on a remote server), skip the browser reviewer entirely. Instead, present results directly in the conversation. For each test case, show the prompt and the output. If the output is a file the user needs to see (like a .docx or .xlsx), save it to the filesystem and tell them where it is so they can download and inspect it. Ask for feedback inline: \"How does this look? Anything you'd change?\"\n\n**Benchmarking**: Skip the quantitative benchmarking — it relies on baseline comparisons which aren't meaningful without subagents. Focus on qualitative feedback from the user.\n\n**The iteration loop**: Same as before — improve the skill, rerun the test cases, ask for feedback — just without the browser reviewer in the middle. You can still organize results into iteration directories on the filesystem if you have one.\n\n**Description optimization**: This section requires the `claude` CLI tool (specifically `claude -p`) which is only available in Claude Code. Skip it if you're on Claude.ai.\n\n**Blind comparison**: Requires subagents. Skip it.\n\n**Packaging**: The `package_skill.py` script works anywhere with Python and a filesystem. On Claude.ai, you can run it and the user can download the resulting `.skill` file.\n\n---\n\n## Cowork-Specific Instructions\n\nIf you're in Cowork, the main things to know are:\n\n- You have subagents, so the main workflow (spawn test cases in parallel, run baselines, grade, etc.) all works. (However, if you run into severe problems with timeouts, it's OK to run the test prompts in series rather than parallel.)\n- You don't have a browser or display, so when generating the eval viewer, use `--static <output_path>` to write a standalone HTML file instead of starting a server. Then proffer a link that the user can click to open the HTML in their browser.\n- For whatever reason, the Cowork setup seems to disincline Claude from generating the eval viewer after running the tests, so just to reiterate: whether you're in Cowork or in Claude Code, after running tests, you should always generate the eval viewer for the human to look at examples before revising the skill yourself and trying to make corrections, using `generate_review.py` (not writing your own boutique html code). Sorry in advance but I'm gonna go all caps here: GENERATE THE EVAL VIEWER *BEFORE* evaluating inputs yourself. You want to get them in front of the human ASAP!\n- Feedback works differently: since there's no running server, the viewer's \"Submit All Reviews\" button will download `feedback.json` as a file. You can then read it from there (you may have to request access first).\n- Packaging works — `package_skill.py` just needs Python and a filesystem.\n- Description optimization (`run_loop.py` / `run_eval.py`) should work in Cowork just fine since it uses `claude -p` via subprocess, not a browser, but please save it until you've fully finished making the skill and the user agrees it's in good shape.\n\n---\n\n## Reference files\n\nThe agents/ directory contains instructions for specialized subagents. Read them when you need to spawn the relevant subagent.\n\n- `agents/grader.md` — How to evaluate assertions against outputs\n- `agents/comparator.md` — How to do blind A/B comparison between two outputs\n- `agents/analyzer.md` — How to analyze why one version beat another\n\nThe references/ directory has additional documentation:\n- `references/schemas.md` — JSON structures for evals.json, grading.json, etc.\n\n---\n\nRepeating one more time the core loop here for emphasis:\n\n- Figure out what the skill is about\n- Draft or edit the skill\n- Run claude-with-access-to-the-skill on test prompts\n- With the user, evaluate the outputs:\n  - Create benchmark.json and run `eval-viewer/generate_review.py` to help the user review them\n  - Run quantitative evals\n- Repeat until you and the user are satisfied\n- Package the final skill and return it to the user.\n\nPlease add steps to your TodoList, if you have such a thing, to make sure you don't forget. If you're in Cowork, please specifically put \"Create evals JSON and run `eval-viewer/generate_review.py` so human can review test cases\" in your TodoList to make sure it happens.\n\nGood luck!\n","frontmatter":{"name":"skill-creator","description":"Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, update or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.","official":true,"version":"1.0.1"},"isInternal":false,"tokens":7150,"sizeBytes":32400},{"name":"_meta.json","path":"SKILLs/skill-vetter/_meta.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-vetter/_meta.json","title":"Skill-vetter Skill","category":"anthropic-skill","format":"json","content":"# Skill-vetter Skill\n\nPath: `SKILLs/skill-vetter/_meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-vetter/_meta.json)","tokens":300,"sizeBytes":186},{"name":"SKILL.md","path":"SKILLs/skill-vetter/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-vetter/SKILL.md","title":"skill-vetter","category":"anthropic-skill","format":"markdown","content":"---\nname: skill-vetter\nversion: 1.0.0\ndescription: Security-first skill vetting for AI agents. Use before installing any skill from ClawdHub, GitHub, or other sources. Checks for red flags, permission scope, and suspicious patterns.\n---\n\n# Skill Vetter 🔒\n\nSecurity-first vetting protocol for AI agent skills. **Never install a skill without vetting it first.**\n\n## When to Use\n\n- Before installing any skill from ClawdHub\n- Before running skills from GitHub repos\n- When evaluating skills shared by other agents\n- Anytime you're asked to install unknown code\n\n## Vetting Protocol\n\n### Step 1: Source Check\n\n```\nQuestions to answer:\n- [ ] Where did this skill come from?\n- [ ] Is the author known/reputable?\n- [ ] How many downloads/stars does it have?\n- [ ] When was it last updated?\n- [ ] Are there reviews from other agents?\n```\n\n### Step 2: Code Review (MANDATORY)\n\nRead ALL files in the skill. Check for these **RED FLAGS**:\n\n```\n🚨 REJECT IMMEDIATELY IF YOU SEE:\n─────────────────────────────────────────\n• curl/wget to unknown URLs\n• Sends data to external servers\n• Requests credentials/tokens/API keys\n• Reads ~/.ssh, ~/.aws, ~/.config without clear reason\n• Accesses MEMORY.md, USER.md, SOUL.md, IDENTITY.md\n• Uses base64 decode on anything\n• Uses eval() or exec() with external input\n• Modifies system files outside workspace\n• Installs packages without listing them\n• Network calls to IPs instead of domains\n• Obfuscated code (compressed, encoded, minified)\n• Requests elevated/sudo permissions\n• Accesses browser cookies/sessions\n• Touches credential files\n─────────────────────────────────────────\n```\n\n### Step 3: Permission Scope\n\n```\nEvaluate:\n- [ ] What files does it need to read?\n- [ ] What files does it need to write?\n- [ ] What commands does it run?\n- [ ] Does it need network access? To where?\n- [ ] Is the scope minimal for its stated purpose?\n```\n\n### Step 4: Risk Classification\n\n| Risk Level | Examples | Action |\n|------------|----------|--------|\n| 🟢 LOW | Notes, weather, formatting | Basic review, install OK |\n| 🟡 MEDIUM | File ops, browser, APIs | Full code review required |\n| 🔴 HIGH | Credentials, trading, system | Human approval required |\n| ⛔ EXTREME | Security configs, root access | Do NOT install |\n\n## Output Format\n\nAfter vetting, produce this report:\n\n```\nSKILL VETTING REPORT\n═══════════════════════════════════════\nSkill: [name]\nSource: [ClawdHub / GitHub / other]\nAuthor: [username]\nVersion: [version]\n───────────────────────────────────────\nMETRICS:\n• Downloads/Stars: [count]\n• Last Updated: [date]\n• Files Reviewed: [count]\n───────────────────────────────────────\nRED FLAGS: [None / List them]\n\nPERMISSIONS NEEDED:\n• Files: [list or \"None\"]\n• Network: [list or \"None\"]  \n• Commands: [list or \"None\"]\n───────────────────────────────────────\nRISK LEVEL: [🟢 LOW / 🟡 MEDIUM / 🔴 HIGH / ⛔ EXTREME]\n\nVERDICT: [✅ SAFE TO INSTALL / ⚠️ INSTALL WITH CAUTION / ❌ DO NOT INSTALL]\n\nNOTES: [Any observations]\n═══════════════════════════════════════\n```\n\n## Quick Vet Commands\n\nFor GitHub-hosted skills:\n```bash\n# Check repo stats\ncurl -s \"https://api.github.com/repos/OWNER/REPO\" | jq '{stars: .stargazers_count, forks: .forks_count, updated: .updated_at}'\n\n# List skill files\ncurl -s \"https://api.github.com/repos/OWNER/REPO/contents/skills/SKILL_NAME\" | jq '.[].name'\n\n# Fetch and review SKILL.md\ncurl -s \"https://raw.githubusercontent.com/OWNER/REPO/main/skills/SKILL_NAME/SKILL.md\"\n```\n\n## Trust Hierarchy\n\n1. **Official OpenClaw skills** → Lower scrutiny (still review)\n2. **High-star repos (1000+)** → Moderate scrutiny\n3. **Known authors** → Moderate scrutiny\n4. **New/unknown sources** → Maximum scrutiny\n5. **Skills requesting credentials** → Human approval always\n\n## Remember\n\n- No skill is worth compromising security\n- When in doubt, don't install\n- Ask your human for high-risk decisions\n- Document what you vet for future reference\n\n---\n\n*Paranoia is a feature.* 🔒🦀\n","frontmatter":{"name":"skill-vetter","version":"1.0.0","description":"Security-first skill vetting for AI agents. Use before installing any skill from ClawdHub, GitHub, or other sources. Checks for red flags, permission scope, and suspicious patterns."},"isInternal":false,"tokens":1047,"sizeBytes":4561},{"name":"skills.config.json","path":"SKILLs/skills.config.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skills.config.json","title":"SKILLs Skill","category":"anthropic-skill","format":"json","content":"# SKILLs Skill\n\nPath: `SKILLs/skills.config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skills.config.json)","tokens":300,"sizeBytes":170},{"name":"SKILL.md","path":"SKILLs/stock-analyzer/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-analyzer/SKILL.md","title":"stock-analyzer","category":"anthropic-skill","format":"markdown","content":"# stock-analyzer\n\nPath: `SKILLs/stock-analyzer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-analyzer/SKILL.md)","tokens":300,"sizeBytes":182},{"name":"SKILL.md","path":"SKILLs/stock-announcements/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-announcements/SKILL.md","title":"stock-announcements","category":"anthropic-skill","format":"markdown","content":"# stock-announcements\n\nPath: `SKILLs/stock-announcements/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-announcements/SKILL.md)","tokens":300,"sizeBytes":197},{"name":"SKILL.md","path":"SKILLs/stock-explorer/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-explorer/SKILL.md","title":"stock-explorer","category":"anthropic-skill","format":"markdown","content":"# stock-explorer\n\nPath: `SKILLs/stock-explorer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/stock-explorer/SKILL.md)","tokens":300,"sizeBytes":182},{"name":"sources.json","path":"SKILLs/technology-news-search/references/sources.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/technology-news-search/references/sources.json","title":"References Skill","category":"anthropic-skill","format":"json","content":"# References Skill\n\nPath: `SKILLs/technology-news-search/references/sources.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/technology-news-search/references/sources.json)","tokens":300,"sizeBytes":230},{"name":"SKILL.md","path":"SKILLs/technology-news-search/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/technology-news-search/SKILL.md","title":"technology-news-search","category":"anthropic-skill","format":"markdown","content":"# technology-news-search\n\nPath: `SKILLs/technology-news-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/technology-news-search/SKILL.md)","tokens":300,"sizeBytes":206},{"name":"SKILL.md","path":"SKILLs/weather/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/weather/SKILL.md","title":"weather","category":"anthropic-skill","format":"markdown","content":"# weather\n\nPath: `SKILLs/weather/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/weather/SKILL.md)","tokens":300,"sizeBytes":161},{"name":"DEPLOYMENT.md","path":"SKILLs/web-search/DEPLOYMENT.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/DEPLOYMENT.md","title":"Web-search Skill","category":"anthropic-skill","format":"markdown","content":"# Web-search Skill\n\nPath: `SKILLs/web-search/DEPLOYMENT.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/DEPLOYMENT.md)","tokens":300,"sizeBytes":186},{"name":"basic-search.md","path":"SKILLs/web-search/examples/basic-search.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/examples/basic-search.md","title":"Examples Skill","category":"anthropic-skill","format":"markdown","content":"# Examples Skill\n\nPath: `SKILLs/web-search/examples/basic-search.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/examples/basic-search.md)","tokens":300,"sizeBytes":206},{"name":"IMPLEMENTATION.md","path":"SKILLs/web-search/IMPLEMENTATION.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/IMPLEMENTATION.md","title":"Web-search Skill","category":"anthropic-skill","format":"markdown","content":"# Web-search Skill\n\nPath: `SKILLs/web-search/IMPLEMENTATION.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/IMPLEMENTATION.md)","tokens":300,"sizeBytes":194},{"name":"package.json","path":"SKILLs/web-search/package.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/package.json","title":"Web-search Skill","category":"anthropic-skill","format":"json","content":"# Web-search Skill\n\nPath: `SKILLs/web-search/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/package.json)","tokens":300,"sizeBytes":184},{"name":"README.md","path":"SKILLs/web-search/README.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/README.md","title":"Web-search Skill","category":"anthropic-skill","format":"markdown","content":"# Web-search Skill\n\nPath: `SKILLs/web-search/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/README.md)","tokens":300,"sizeBytes":178},{"name":"SKILL.md","path":"SKILLs/web-search/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/SKILL.md","title":"web-search","category":"anthropic-skill","format":"markdown","content":"# web-search\n\nPath: `SKILLs/web-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/SKILL.md)","tokens":300,"sizeBytes":170},{"name":"TEST.md","path":"SKILLs/web-search/TEST.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/TEST.md","title":"Web-search Skill","category":"anthropic-skill","format":"markdown","content":"# Web-search Skill\n\nPath: `SKILLs/web-search/TEST.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/TEST.md)","tokens":300,"sizeBytes":174},{"name":"tsconfig.json","path":"SKILLs/web-search/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/tsconfig.json","title":"Web-search Skill","category":"anthropic-skill","format":"json","content":"# Web-search Skill\n\nPath: `SKILLs/web-search/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/web-search/tsconfig.json)","tokens":300,"sizeBytes":186},{"name":"SKILL.md","path":"SKILLs/xlsx/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/xlsx/SKILL.md","title":"xlsx","category":"anthropic-skill","format":"markdown","content":"# xlsx\n\nPath: `SKILLs/xlsx/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/xlsx/SKILL.md)","tokens":300,"sizeBytes":152},{"name":"SKILL.md","path":"SKILLs/youdaonote/SKILL.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/youdaonote/SKILL.md","title":"youdaonote","category":"anthropic-skill","format":"markdown","content":"# youdaonote\n\nPath: `SKILLs/youdaonote/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/youdaonote/SKILL.md)","tokens":300,"sizeBytes":170},{"name":"openclaw.plugin.json","path":"openclaw-extensions/ask-user-question/openclaw.plugin.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/openclaw-extensions/ask-user-question/openclaw.plugin.json","title":"ask-user-question Plugin Manifest","category":"plugin-manifest","format":"json","content":"# ask-user-question Plugin Manifest\n\nPath: `openclaw-extensions/ask-user-question/openclaw.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/openclaw-extensions/ask-user-question/openclaw.plugin.json)","tokens":300,"sizeBytes":257},{"name":"openclaw.plugin.json","path":"openclaw-extensions/mcp-bridge/openclaw.plugin.json","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/openclaw-extensions/mcp-bridge/openclaw.plugin.json","title":"mcp-bridge Plugin Manifest","category":"plugin-manifest","format":"json","content":"# mcp-bridge Plugin Manifest\n\nPath: `openclaw-extensions/mcp-bridge/openclaw.plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/openclaw-extensions/mcp-bridge/openclaw.plugin.json)","tokens":300,"sizeBytes":236},{"name":"analyzer.md","path":"SKILLs/skill-creator/agents/analyzer.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/analyzer.md","title":"Subagent: analyzer","category":"subagent-persona","format":"markdown","content":"# Subagent: analyzer\n\nPath: `SKILLs/skill-creator/agents/analyzer.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/analyzer.md)","tokens":300,"sizeBytes":204},{"name":"comparator.md","path":"SKILLs/skill-creator/agents/comparator.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/comparator.md","title":"Subagent: comparator","category":"subagent-persona","format":"markdown","content":"# Subagent: comparator\n\nPath: `SKILLs/skill-creator/agents/comparator.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/comparator.md)","tokens":300,"sizeBytes":210},{"name":"grader.md","path":"SKILLs/skill-creator/agents/grader.md","rawUrl":"https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/grader.md","title":"Subagent: grader","category":"subagent-persona","format":"markdown","content":"# Subagent: grader\n\nPath: `SKILLs/skill-creator/agents/grader.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/skill-creator/agents/grader.md)","tokens":300,"sizeBytes":198}],"systemPromptSnippet":"<yakaai_skills repo=\"netease-youdao/LobsterAI\">\n<!-- File: AGENTS.md (Tokens: ~300 | Category: root-instruction) -->\n# AI Agent Protocol & Instructions\n\nPath: `AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/AGENTS.md)\n\n<!-- File: SKILLs/article-writer/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# article-writer\n\nPath: `SKILLs/article-writer/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/article-writer/SKILL.md)\n\n<!-- File: SKILLs/canvas-design/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# canvas-design\n\nPath: `SKILLs/canvas-design/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/canvas-design/SKILL.md)\n\n<!-- File: SKILLs/content-planner/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# content-planner\n\nPath: `SKILLs/content-planner/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/content-planner/SKILL.md)\n\n<!-- File: SKILLs/create-plan/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# create-plan\n\nPath: `SKILLs/create-plan/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/create-plan/SKILL.md)\n\n<!-- File: SKILLs/daily-trending/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# daily-trending\n\nPath: `SKILLs/daily-trending/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/daily-trending/SKILL.md)\n\n<!-- File: SKILLs/develop-web-game/agents/openai.yaml (Tokens: ~300 | Category: anthropic-skill) -->\n# Agents Skill\n\nPath: `SKILLs/develop-web-game/agents/openai.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/agents/openai.yaml)\n\n<!-- File: SKILLs/develop-web-game/references/action_payloads.json (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `SKILLs/develop-web-game/references/action_payloads.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/references/action_payloads.json)\n\n<!-- File: SKILLs/develop-web-game/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# develop-web-game\n\nPath: `SKILLs/develop-web-game/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/develop-web-game/SKILL.md)\n\n<!-- File: SKILLs/docx/docx-js.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Docx Skill\n\nPath: `SKILLs/docx/docx-js.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/docx-js.md)\n\n<!-- File: SKILLs/docx/ooxml.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Docx Skill\n\nPath: `SKILLs/docx/ooxml.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/ooxml.md)\n\n<!-- File: SKILLs/docx/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# docx\n\nPath: `SKILLs/docx/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/docx/SKILL.md)\n\n<!-- File: SKILLs/films-search/SKILL.md (Tokens: ~300 | Category: anthropic-skill) -->\n# films-search\n\nPath: `SKILLs/films-search/SKILL.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/films-search/SKILL.md)\n\n<!-- File: SKILLs/frontend-design/SKILL.md (Tokens: ~862 | Category: anthropic-skill) -->\n---\nname: frontend-design\ndescription: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.\nlicense: Complete terms in LICENSE.txt\nofficial: true\n---\n\nThis skill guides creation of distinctive, production-grade frontend interfaces that avoid generic \"AI slop\" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.\n\nThe user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.\n\n## Design Thinking\n\nBefore coding, understand the context and commit to a BOLD aesthetic direction:\n- **Purpose**: What problem does this interface solve? Who uses it?\n- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.\n- **Constraints**: Technical requirements (framework, performance, accessibility).\n- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?\n\n**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.\n\nThen implement working code (HTML/CSS/JS, React, Vue, etc.) that is:\n- Production-grade and functional\n- Visually striking and memorable\n- Cohesive with a clear aesthetic point-of-view\n- Meticulously refined in every detail\n\n## Frontend Aesthetics Guidelines\n\nFocus on:\n- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.\n- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.\n- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.\n- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.\n- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.\n\nNEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.\n\nInterpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.\n\n**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.\n\nRemember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.\n\n<!-- File: SKILLs/imap-smtp-email/_meta.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/_meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/_meta.json)\n\n<!-- File: SKILLs/imap-smtp-email/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/package.json)\n\n<!-- File: SKILLs/imap-smtp-email/README.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Imap-smtp-email Skill\n\nPath: `SKILLs/imap-smtp-email/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/imap-smtp-email/README.md)\n\n<!-- File: SKILLs/imap-smtp-email/SKILL.md (Tokens: ~2695 | Category: anthropic-skill) -->\n---\nname: imap-smtp-email\ndescription: Read and send email via IMAP/SMTP. Check for new/unread messages, fetch content, search mailboxes, mark as read/unread, and send emails with attachments. Works with any IMAP/SMTP server including Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, and vip.188.com.\nofficial: true\nversion: 1.0.7\n---\n\n# IMAP/SMTP Email Tool\n\nRead, search, and manage email via IMAP protocol. Send email via SMTP. Supports Gmail, Outlook, 163.com, vip.163.com, 126.com, vip.126.com, 188.com, vip.188.com, and any standard IMAP/SMTP server.\n\n## Important: Configuration is Pre-configured\n\nThe `accounts.json` configuration file is automatically managed by LobsterAI Settings (邮箱设置). Legacy `.env` configuration is still supported as a fallback for older users. **Do NOT ask the user to create or edit these files — just run the commands directly.** If credentials are wrong, the scripts will return a clear error message; only then should you inform the user to check their email settings.\n\nThe configuration files are located in this skill's directory (same folder as this SKILL.md file). The scripts load them automatically via absolute paths, regardless of the current working directory.\n\nUse the provided scripts as the only email transport interface. Do not write temporary IMAP/SMTP scripts, do not use raw sockets, OpenSSL, `net`, `tls`, or alternate mail clients, and do not inspect `.env`, `accounts.json`, or script source unless the official command output explicitly reports missing configuration and the user asks you to diagnose it. If an official command fails or times out, report that command result and suggest checking LobsterAI Settings; do not implement a fallback protocol client.\n\nDo not claim that `node-imap`, `nodemailer`, or another dependency is broken unless an official script or verified stack trace proves it. A successful command means the configured email account works; a timeout means the current command timed out, not that the dependency is defective.\n\nCommand results intentionally redact account metadata. In user-facing replies, use the redacted account label/email from the JSON result and do not repeat full configured email addresses unless the user explicitly asks for the exact address. Email content fields such as sender, subject, and message body may still be shown when they are the requested result.\n\nNever ask the user to send an email authorization code, app password, account password, or other credential in chat. If an account is disabled, incomplete, or has invalid credentials, ask the user to enable or update it in LobsterAI Settings > Email Settings, then rerun the official command.\n\nFor multi-account setups:\n- Run `node scripts/imap.js accounts` or `node scripts/smtp.js accounts` to list configured account IDs without exposing secrets.\n- Omit `--account` to use the default enabled account.\n- Pass `--account <id>` to use a specific account.\n- Pass `--all-accounts` only for read/list commands that support fan-out (`check`, `search`, `list-mailboxes`).\n- JSON results for read/list commands include `success`, redacted account metadata, `command`, `count`, and result arrays such as `messages` or `mailboxes`.\n\nFor sending email, always review recipient, subject, sender account, and body with the user first. Sending is blocked unless `--confirmed` is passed.\n\nFor SMTP send results, `success: true` means the sending SMTP server accepted the message for processing. Do not claim final delivery or inbox receipt. Report it as \"submitted to the SMTP server\" and mention that the recipient provider may still reject it later via a bounce message. If `rejected` or `pending` recipients are present, call them out explicitly.\n\nNever use a redacted account email such as `ab***@example.com` as a recipient address. If the user asks to send to another configured email account, use that account's `id` with `--to-account <id>` so the script resolves the real address internally without exposing it.\n\n## Configuration Reference\n\nCreate `.env` in the skill folder or set environment variables:\n\n```bash\n# IMAP Configuration (receiving email)\nIMAP_HOST=imap.gmail.com          # Server hostname\nIMAP_PORT=993                     # Server port\nIMAP_USER=your@email.com\nIMAP_PASS=your_password\nIMAP_TLS=true                     # Use TLS/SSL connection\nIMAP_REJECT_UNAUTHORIZED=true     # Set to false for self-signed certs\nIMAP_MAILBOX=INBOX                # Default mailbox\n\n# SMTP Configuration (sending email)\nSMTP_HOST=smtp.gmail.com          # SMTP server hostname\nSMTP_PORT=587                     # SMTP port (587 for STARTTLS, 465 for SSL)\nSMTP_SECURE=false                 # true for SSL (465), false for STARTTLS (587)\nSMTP_USER=your@gmail.com          # Your email address\nSMTP_PASS=your_password           # Your password or app password\nSMTP_FROM=your@gmail.com          # Default sender email (optional)\nSMTP_REJECT_UNAUTHORIZED=true     # Set to false for self-signed certs\n```\n\n## Common Email Servers\n\n| Provider | IMAP Host | IMAP Port | SMTP Host | SMTP Port |\n|----------|-----------|-----------|-----------|-----------|\n| 163.com | imap.163.com | 993 | smtp.163.com | 465 |\n| vip.163.com | imap.vip.163.com | 993 | smtp.vip.163.com | 465 |\n| 126.com | imap.126.com | 993 | smtp.126.com | 465 |\n| vip.126.com | imap.vip.126.com | 993 | smtp.vip.126.com | 465 |\n| 188.com | imap.188.com | 993 | smtp.188.com | 465 |\n| vip.188.com | imap.vip.188.com | 993 | smtp.vip.188.com | 465 |\n| yeah.net | imap.yeah.net | 993 | smtp.yeah.net | 465 |\n| Gmail | imap.gmail.com | 993 | smtp.gmail.com | 587 |\n| Outlook | outlook.office365.com | 993 | smtp.office365.com | 587 |\n| QQ Mail | imap.qq.com | 993 | smtp.qq.com | 587 |\n\n**Important for 163.com:**\n- Use **authorization code** (授权码), not account password\n- Enable IMAP/SMTP in web settings first\n\n## IMAP Commands (Receiving Email)\n\n### accounts\nList configured email accounts without exposing passwords.\n\n```bash\nnode scripts/imap.js accounts\n```\n\n### check\nCheck for new/unread emails.\n\n```bash\nnode scripts/imap.js check [--limit 10] [--mailbox INBOX] [--recent 2h]\nnode scripts/imap.js check --all-accounts [--limit 10]\n```\n\nOptions:\n- `--account <id>`: Use a specific configured account\n- `--all-accounts`: Check every enabled account\n- `--limit <n>`: Max results (default: 10)\n- `--mailbox <name>`: Mailbox to check (default: INBOX)\n- `--recent <time>`: Only show emails from last X time (e.g., 30m, 2h, 7d)\n\n### fetch\nFetch full email content by UID.\n\n```bash\nnode scripts/imap.js fetch <uid> [--mailbox INBOX]\nnode scripts/imap.js fetch <uid> --account <id> [--mailbox INBOX]\n```\n\n### download\nDownload all attachments from an email, or a specific attachment.\n\n```bash\nnode scripts/imap.js download <uid> [--mailbox INBOX] [--dir <path>] [--file <filename>]\nnode scripts/imap.js download <uid> --account <id> [--mailbox INBOX] [--dir <path>] [--file <filename>]\n```\n\nOptions:\n- `--mailbox <name>`: Mailbox (default: INBOX)\n- `--dir <path>`: Output directory (default: current directory)\n- `--file <filename>`: Download only the specified attachment (default: download all)\n\n### search\nSearch emails with filters.\n\n```bash\nnode scripts/imap.js search [options]\n\nOptions:\n  --unseen           Only unread messages\n  --seen             Only read messages\n  --from <email>     From address contains\n  --subject <text>   Subject contains\n  --recent <time>    From last X time (e.g., 30m, 2h, 7d)\n  --since <date>     After date (YYYY-MM-DD)\n  --before <date>    Before date (YYYY-MM-DD)\n  --limit <n>        Max results (default: 20)\n  --mailbox <name>   Mailbox to search (default: INBOX)\n  --account <id>     Use a specific configured account\n  --all-accounts     Search every enabled account\n```\n\n### mark-read / mark-unread\nMark message(s) as read or unread.\n\n```bash\nnode scripts/imap.js mark-read <uid> [uid2 uid3...]\nnode scripts/imap.js mark-unread <uid> [uid2 uid3...]\nnode scripts/imap.js mark-read --account <id> <uid> [uid2 uid3...]\n```\n\n### list-mailboxes\nList all available mailboxes/folders.\n\n```bash\nnode scripts/imap.js list-mailboxes\nnode scripts/imap.js list-mailboxes --all-accounts\n```\n\n## SMTP Commands (Sending Email)\n\n### accounts\nList configured email accounts without exposing passwords.\n\n```bash\nnode scripts/smtp.js accounts\n```\n\n### send\nSubmit email via SMTP. A successful command means the SMTP server accepted the message for processing, not that the recipient inbox has received it.\n\n```bash\nnode scripts/smtp.js send --to <email> --subject <text> --confirmed [options]\n```\n\n**Required:**\n- `--to <email>`: Recipient (comma-separated for multiple)\n- `--subject <text>`: Email subject, or `--subject-file <file>`\n\n**Optional:**\n- `--body <text>`: Plain text body\n- `--html`: Send body as HTML\n- `--body-file <file>`: Read body from file\n- `--html-file <file>`: Read HTML from file\n- `--cc <email>`: CC recipients\n- `--bcc <email>`: BCC recipients\n- `--attach <file>`: Attachments (comma-separated)\n- `--from <email>`: Override default sender\n- `--account <id>`: Send from a specific configured account\n- `--to-account <id>`: Send to a configured account by ID without exposing its full email address\n- `--confirmed`: Required after the user confirms the email details\n\n**Examples:**\n```bash\n# Simple text email\nnode scripts/smtp.js send --to recipient@example.com --subject \"Hello\" --body \"World\"\n\n# HTML email\nnode scripts/smtp.js send --to recipient@example.com --subject \"Newsletter\" --html --body \"<h1>Welcome</h1>\"\n\n# Email with attachment\nnode scripts/smtp.js send --to recipient@example.com --subject \"Report\" --body \"Please find attached\" --attach report.pdf\n\n# Multiple recipients\nnode scripts/smtp.js send --to \"a@example.com,b@example.com\" --cc \"c@example.com\" --subject \"Update\" --body \"Team update\"\n\n# Send to another configured account by ID\nnode scripts/smtp.js send --account default --to-account account-2 --subject \"Hello\" --body \"World\"\n```\n\n### test\nTest SMTP connection by sending a test email to yourself.\n\n```bash\nnode scripts/smtp.js test\n```\n\n## Dependencies\n\n```bash\nnpm install\n```\n\n## Security Notes\n\n- Store credentials in `.env` (add to `.gitignore`)\n- For Gmail: use App Password if 2FA is enabled\n- For 163.com: use authorization code (授权码), not account password\n- Downloaded attachment filenames are normalized to a safe local filename and cannot create directories outside the account/UID download folder.\n\n## Troubleshooting\n\n**Connection timeout:**\n- Verify server is running and accessible\n- Check host/port configuration\n\n**Authentication failed:**\n- Verify username (usually full email address)\n- Check password is correct\n- For 163.com: use authorization code, not account password\n- For Gmail: use App Password if 2FA enabled\n\n**TLS/SSL errors:**\n- Match `IMAP_TLS`/`SMTP_SECURE` setting to server requirements\n- For self-signed certs: set `IMAP_REJECT_UNAUTHORIZED=false` or `SMTP_REJECT_UNAUTHORIZED=false`\n\n<!-- File: SKILLs/local-tools/SKILL.md (Tokens: ~3538 | Category: anthropic-skill) -->\n---\nname: local-tools\ndescription: Access local system resources including Calendar on macOS and Windows. Use this skill when you need to manage user's schedule directly on their device.\nofficial: true\n---\n\n# Local Tools Skill\n\n## When to Use This Skill\n\nUse the local-tools skill when you need to:\n\n- **Calendar Management** - View, create, update, or delete calendar events\n\n**Examples of when to use:**\n- User: \"Show me my schedule for tomorrow\"\n- User: \"Create a meeting at 3 PM\"\n- User: \"Search for calendar events containing 'project'\"\n- User: \"Delete tomorrow's meeting\"\n\n## How It Works\n\n```\n┌──────────┐    Bash/PowerShell    ┌─────────────────────────────────────────────────────────────┐\n│  Claude  │──────────────────────▶│  calendar.sh / calendar.ps1                                 │\n│          │                       │  ├─ macOS: osascript -l JavaScript (JXA) ──▶ Calendar.app   │\n│          │                       │  └─ Windows: PowerShell ──▶ Outlook COM API                 │\n└──────────┘                       └─────────────────────────────────────────────────────────────┘\n```\n\n**Architecture:**\n1. **CLI Scripts** - Platform-specific scripts, no HTTP server needed\n   - `calendar.sh` - Bash script for macOS\n   - `calendar.ps1` - PowerShell script for Windows\n\n2. **Local Calendar Access** - Direct access to system calendar\n   - macOS: Uses JXA (JavaScript for Automation) to control Calendar.app\n   - Windows: Uses PowerShell COM API to control Microsoft Outlook\n\n3. **JSON Output** - Structured data format for easy parsing\n\n## Platform Support\n\n| Platform | Implementation | Calendar App | Status |\n|----------|---------------|--------------|--------|\n| **macOS 10.10+** | JXA + Calendar.app | Calendar.app | ✅ Fully Supported |\n| **Windows 7+** | PowerShell + COM | Microsoft Outlook | ✅ Fully Supported |\n| **Linux** | - | - | ❌ Not Supported |\n\n## Permissions\n\n### macOS\n- Requires \"Calendar\" access permission\n- User will be prompted on first use\n- Can be managed in: System Settings > Privacy & Security > Calendar\n\n### Windows\n- Requires Microsoft Outlook to be installed\n- May require administrative privileges for COM access\n\n## Calendar Operations\n\n**IMPORTANT: How to Locate the Script**\n\nWhen you read this SKILL.md file using the Read tool, you receive its absolute path (e.g., `/Users/username/.../SKILLs/local-tools/SKILL.md`).\n\n**To construct the script path:**\n1. Take the directory of this SKILL.md file\n2. Append `/scripts/calendar.sh` (macOS) or `/scripts/calendar.ps1` (Windows)\n\n**Example:**\n```bash\n# If SKILL.md is at: /Users/username/path/to/SKILLs/local-tools/SKILL.md\n# Then the script is: /Users/username/path/to/SKILLs/local-tools/scripts/calendar.sh\n\nbash \"/Users/username/path/to/SKILLs/local-tools/scripts/calendar.sh\" <operation> [options]\n```\n\nIn all examples below, `<skill-dir>/scripts/calendar.sh` is a placeholder. Replace it with the actual absolute path.\n\n### Best Practices for AI Assistant\n\n**DO:**\n- ✅ Execute commands directly without showing trial-and-error process\n- ✅ If command fails, inform user about permission issues without showing technical errors\n- ✅ Use `search` command for searching birthdays/anniversaries\n- ✅ If no calendar name specified, script will automatically use first available calendar\n\n**DON'T:**\n- ❌ Don't repeatedly try different command combinations\n- ❌ Don't show error stacks or technical details to users\n- ❌ Don't read script source code to analyze issues\n- ❌ Don't ask users for calendar name, use default behavior\n\n**Example - Searching for birthdays:**\n```bash\n# Correct approach: Search directly, don't trial-and-error\nbash \"<skill-dir>/scripts/calendar.sh\" search --query \"birthday\"\n\n# If permission error returned, directly tell user:\n# \"Calendar access permission is required. Please open System Settings > Privacy & Security > Calendar, and authorize Terminal or LobsterAI\"\n```\n\n### List Events\n\n```bash\n# List events for next 7 days (default)\nbash \"<skill-dir>/scripts/calendar.sh\" list\n\n# List events for specific date range\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-12T00:00:00\" \\\n  --end \"2026-02-19T23:59:59\"\n\n# List events from specific calendar (macOS)\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --calendar \"Work\"\n```\n\n### Create Event\n\n```bash\n# Create a simple event\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Team Meeting\" \\\n  --start \"2026-02-13T14:00:00\" \\\n  --end \"2026-02-13T15:00:00\"\n\n# Create event with location and notes\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Client Call\" \\\n  --start \"2026-02-14T10:00:00\" \\\n  --end \"2026-02-14T11:00:00\" \\\n  --calendar \"Work\" \\\n  --location \"Conference Room A\" \\\n  --notes \"Discuss Q1 roadmap\"\n```\n\n### Update Event\n\n```bash\n# Update event title\nbash \"<skill-dir>/scripts/calendar.sh\" update \\\n  --id \"EVENT-ID\" \\\n  --title \"Updated Meeting Title\"\n\n# Update event time\nbash \"<skill-dir>/scripts/calendar.sh\" update \\\n  --id \"EVENT-ID\" \\\n  --start \"2026-02-13T15:00:00\" \\\n  --end \"2026-02-13T16:00:00\"\n```\n\n### Delete Event\n\n```bash\nbash \"<skill-dir>/scripts/calendar.sh\" delete \\\n  --id \"EVENT-ID\"\n```\n\n### Search Events\n\n```bash\n# Search for events containing keyword (searches ALL calendars)\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"meeting\"\n\n# Search in specific calendar only\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"project\" \\\n  --calendar \"Work\"\n```\n\n**Note:** When `--calendar` is not specified, the search operation will look through **all available calendars** on both macOS and Windows.\n\n## Output Format\n\nAll commands return JSON with the following structure:\n\n### Success Response\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"events\": [\n      {\n        \"eventId\": \"E621F8C4-...\",\n        \"title\": \"Team Meeting\",\n        \"startTime\": \"2026-02-13T14:00:00.000Z\",\n        \"endTime\": \"2026-02-13T15:00:00.000Z\",\n        \"location\": \"Conference Room\",\n        \"notes\": \"Weekly sync\",\n        \"calendar\": \"Work\",\n        \"allDay\": false\n      }\n    ],\n    \"count\": 1\n  }\n}\n```\n\n### Error Response\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"CALENDAR_ACCESS_ERROR\",\n    \"message\": \"Calendar access permission is required...\",\n    \"recoverable\": true,\n    \"permissionRequired\": true\n  }\n}\n```\n\n### Error Codes\n\n| Code | Meaning | Recoverable |\n|------|---------|-------------|\n| `CALENDAR_ACCESS_ERROR` | Permission denied or calendar not accessible | Yes |\n| `INVALID_INPUT` | Missing required parameters | No |\n| `EVENT_NOT_FOUND` | Event ID not found | No |\n| `OUTLOOK_NOT_AVAILABLE` | Microsoft Outlook not installed (Windows) | Yes |\n\n## Date Format Guidelines\n\n### Important: Date Format Guidelines\n\nWhen using the `list` command with time ranges:\n\n1. **Always use ISO 8601 format**: `YYYY-MM-DDTHH:mm:ss`\n2. **Use local timezone**: Do NOT use UTC or timezone suffixes (like +08:00 or Z)\n3. **Calculate dates yourself**: Do NOT use shell command substitution like `$(date ...)`\n4. **Claude should compute dates**: Based on current date, calculate target dates directly\n5. **Examples**:\n   - Today at midnight: `2026-02-13T00:00:00`\n   - Today at end of day: `2026-02-13T23:59:59`\n   - Tomorrow morning: `2026-02-14T09:00:00`\n   - Next week Monday: `2026-02-16T00:00:00`\n\n**Why**: The script expects local time strings that match your system timezone. Shell substitutions may not execute correctly in all environments.\n\n## Common Patterns\n\n### Pattern 1: Schedule Management\n\n```bash\n# User asks: \"What meetings do I have today?\"\n# Claude's approach: Calculate today's date and query full day from 00:00 to 23:59\n# IMPORTANT: Claude should replace 2026-02-13 with the actual current date\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-13T00:00:00\" \\\n  --end \"2026-02-13T23:59:59\"\n\n# User asks: \"What's on my schedule tomorrow?\"\n# Claude should calculate tomorrow's date (e.g., if today is 2026-02-13, tomorrow is 2026-02-14)\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-14T00:00:00\" \\\n  --end \"2026-02-14T23:59:59\"\n```\n\n### Pattern 2: Meeting Scheduling\n\n```bash\n# User asks: \"Schedule a meeting for tomorrow at 3 PM\"\n# Claude's approach:\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Meeting\" \\\n  --start \"2026-02-13T15:00:00\" \\\n  --end \"2026-02-13T16:00:00\" \\\n  --calendar \"Work\"\n```\n\n### Pattern 3: Event Search\n\n```bash\n# User asks: \"Find all meetings about the project\"\n# Claude's approach:\nbash \"<skill-dir>/scripts/calendar.sh\" search \\\n  --query \"project\" \\\n  --calendar \"Work\"\n```\n\n### Pattern 4: Availability Check\n\n```bash\n# User asks: \"Am I free tomorrow afternoon?\"\n# Claude's approach:\n# 1. List tomorrow's events\n# 2. Analyze time slots\n# 3. Report availability\nbash \"<skill-dir>/scripts/calendar.sh\" list \\\n  --start \"2026-02-14T00:00:00\" \\\n  --end \"2026-02-14T23:59:59\"\n```\n\n## Known Behaviors\n\n### Time Range Matching\n\nThe `list` command uses **interval overlap detection**:\n- Returns events that have **any overlap** with the query time range\n- Does NOT require events to be fully contained within the range\n\n**Examples:**\n- Query: 2026-02-13 00:00:00 to 23:59:59\n- Returns:\n  - ✅ Events fully on Feb 13 (e.g., 10:00-11:00)\n  - ✅ Multi-day events spanning Feb 13 (e.g., Feb 12 10:00 - Feb 14 10:00)\n  - ✅ Events crossing midnight (e.g., Feb 13 23:30 - Feb 14 00:30)\n  - ❌ Events entirely before Feb 13 (e.g., Feb 12 10:00-11:00)\n  - ❌ Events entirely after Feb 13 (e.g., Feb 14 10:00-11:00)\n\n### All-Day Events\n\n- Treated as spanning from 00:00:00 to 23:59:59 on their date(s)\n- Multi-day all-day events (e.g., Feb 12-14) will appear when querying any date within that range\n\n### Time Precision\n\n- Comparisons use second-level precision\n- Milliseconds are ignored in date comparisons\n\n### Recurring Events\n\n- Each occurrence is treated as a separate event instance\n- The script returns individual occurrences within the queried time range\n\n## Best Practices\n\n### 1. Always Check Before Creating\n\nBefore creating an event, list existing events to avoid conflicts:\n\n```bash\n# First check existing events\nbash \"<skill-dir>/scripts/calendar.sh\" list\n\n# Then create if no conflict\nbash \"<skill-dir>/scripts/calendar.sh\" create ...\n```\n\n### 2. Use Specific Calendars (macOS)\n\nSpecify the calendar to keep events organized:\n\n```bash\nbash \"<skill-dir>/scripts/calendar.sh\" create \\\n  --title \"Team Meeting\" \\\n  --calendar \"Work\" \\\n  ...\n```\n\n### 3. Search Before Updating/Deleting\n\nAlways search first to get the correct event ID:\n\n```bash\n# Search to find event ID\nbash \"<skill-dir>/scripts/calendar.sh\" search --query \"meeting\"\n\n# Then update or delete\nbash \"<skill-dir>/scripts/calendar.sh\" update --id \"FOUND-ID\" ...\n```\n\n### 4. Handle Errors Gracefully\n\nParse the response and handle errors:\n\n```bash\nresult=$(bash \"<skill-dir>/scripts/calendar.sh\" list)\nif echo \"$result\" | grep -q '\"success\":true'; then\n  # Process events\n  events=$(echo \"$result\" | jq '.data.events')\nelse\n  # Handle error\n  error=$(echo \"$result\" | jq '.error.message')\n  echo \"Failed: $error\"\nfi\n```\n\n## Limitations\n\n### macOS\n- Requires macOS 10.10 Yosemite or later (for JXA support)\n- Requires Calendar access permission\n- Does not support advanced recurring event queries\n- Cannot modify recurring event rules\n\n### Windows\n- Requires Microsoft Outlook to be installed\n- Does not support other calendar applications (Windows Calendar, Google Calendar, etc.)\n- May require COM access permissions in corporate environments\n- Folder enumeration may skip restricted calendars\n\n### General\n- All dates must be in ISO 8601 format (`YYYY-MM-DDTHH:mm:ss`)\n- Uses local timezone for all operations\n- Return values are converted to UTC (ISO 8601 with Z suffix)\n- No support for attendees or meeting invitations\n\n## Troubleshooting\n\n### macOS\n\n**Permission Denied:**\n```\nError: Calendar access permission is required\n```\n**Solution:** Open System Settings > Privacy & Security > Calendar, authorize Terminal or LobsterAI\n\n**Script Not Found:**\n```\nbash: calendar.sh: No such file or directory\n```\n**Solution:** Ensure you're using the absolute path from SKILL.md's directory + `/scripts/calendar.sh`\n\n### Windows\n\n**Outlook Not Found:**\n```\nError: Microsoft Outlook is not installed or not accessible\n```\n**Solution:** Install Microsoft Outlook and ensure it's properly configured\n\n**PowerShell Execution Policy:**\n```\nError: Execution of scripts is disabled on this system\n```\n**Solution:** Run PowerShell as Administrator and execute:\n```powershell\nSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser\n```\n\n## Technical Details\n\n### macOS Implementation\n\n**JXA (JavaScript for Automation):**\n- Uses `osascript -l JavaScript` to execute JXA code\n- Controls Calendar.app via Apple Events\n- Works on both Intel and Apple Silicon Macs\n- Requires user permission for Calendar access\n\n**Date Handling:**\n- Uses BSD date command (macOS native)\n- Format: `date +%Y-%m-%dT%H:%M:%S` (local timezone)\n- Relative dates: `date -v+7d` (7 days from now)\n\n### Windows Implementation\n\n**PowerShell + COM:**\n- Uses Outlook COM API via PowerShell\n- Requires Outlook to be installed and configured\n- Works with all Outlook-compatible calendars\n\n**Date Handling:**\n- Uses PowerShell `[DateTime]::Parse()` for date parsing\n- Automatically handles local timezone\n\n### Cross-Platform Consistency\n\nBoth implementations:\n- Use identical JSON output format\n- Support the same operations (list, create, update, delete, search)\n- Handle dates in local timezone\n- Return UTC timestamps in ISO 8601 format\n\n## Related Skills\n\n- **imap-smtp-email** - For email-based meeting invitations\n\n<!-- File: SKILLs/pdf/forms.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Pdf Skill\n\nPath: `SKILLs/pdf/forms.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/forms.md)\n\n<!-- File: SKILLs/pdf/reference.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Pdf Skill\n\nPath: `SKILLs/pdf/reference.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pdf/reference.md)\n\n<!-- File: SKILLs/pdf/SKILL.md (Tokens: ~1808 | Category: anthropic-skill) -->\n---\nname: pdf\ndescription: Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.\nlicense: Proprietary. LICENSE.txt has complete terms\nofficial: true\n---\n\n# PDF Processing Guide\n\n## Overview\n\nThis guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see reference.md. If you need to fill out a PDF form, read forms.md and follow its instructions.\n\n## Quick Start\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Read a PDF\nreader = PdfReader(\"document.pdf\")\nprint(f\"Pages: {len(reader.pages)}\")\n\n# Extract text\ntext = \"\"\nfor page in reader.pages:\n    text += page.extract_text()\n```\n\n## Python Libraries\n\n### pypdf - Basic Operations\n\n#### Merge PDFs\n```python\nfrom pypdf import PdfWriter, PdfReader\n\nwriter = PdfWriter()\nfor pdf_file in [\"doc1.pdf\", \"doc2.pdf\", \"doc3.pdf\"]:\n    reader = PdfReader(pdf_file)\n    for page in reader.pages:\n        writer.add_page(page)\n\nwith open(\"merged.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n#### Split PDF\n```python\nreader = PdfReader(\"input.pdf\")\nfor i, page in enumerate(reader.pages):\n    writer = PdfWriter()\n    writer.add_page(page)\n    with open(f\"page_{i+1}.pdf\", \"wb\") as output:\n        writer.write(output)\n```\n\n#### Extract Metadata\n```python\nreader = PdfReader(\"document.pdf\")\nmeta = reader.metadata\nprint(f\"Title: {meta.title}\")\nprint(f\"Author: {meta.author}\")\nprint(f\"Subject: {meta.subject}\")\nprint(f\"Creator: {meta.creator}\")\n```\n\n#### Rotate Pages\n```python\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\npage = reader.pages[0]\npage.rotate(90)  # Rotate 90 degrees clockwise\nwriter.add_page(page)\n\nwith open(\"rotated.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### pdfplumber - Text and Table Extraction\n\n#### Extract Text with Layout\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for page in pdf.pages:\n        text = page.extract_text()\n        print(text)\n```\n\n#### Extract Tables\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    for i, page in enumerate(pdf.pages):\n        tables = page.extract_tables()\n        for j, table in enumerate(tables):\n            print(f\"Table {j+1} on page {i+1}:\")\n            for row in table:\n                print(row)\n```\n\n#### Advanced Table Extraction\n```python\nimport pandas as pd\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n    all_tables = []\n    for page in pdf.pages:\n        tables = page.extract_tables()\n        for table in tables:\n            if table:  # Check if table is not empty\n                df = pd.DataFrame(table[1:], columns=table[0])\n                all_tables.append(df)\n\n# Combine all tables\nif all_tables:\n    combined_df = pd.concat(all_tables, ignore_index=True)\n    combined_df.to_excel(\"extracted_tables.xlsx\", index=False)\n```\n\n### reportlab - Create PDFs\n\n#### Basic PDF Creation\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.pdfgen import canvas\n\nc = canvas.Canvas(\"hello.pdf\", pagesize=letter)\nwidth, height = letter\n\n# Add text\nc.drawString(100, height - 100, \"Hello World!\")\nc.drawString(100, height - 120, \"This is a PDF created with reportlab\")\n\n# Add a line\nc.line(100, height - 140, 400, height - 140)\n\n# Save\nc.save()\n```\n\n#### Create PDF with Multiple Pages\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak\nfrom reportlab.lib.styles import getSampleStyleSheet\n\ndoc = SimpleDocTemplate(\"report.pdf\", pagesize=letter)\nstyles = getSampleStyleSheet()\nstory = []\n\n# Add content\ntitle = Paragraph(\"Report Title\", styles['Title'])\nstory.append(title)\nstory.append(Spacer(1, 12))\n\nbody = Paragraph(\"This is the body of the report. \" * 20, styles['Normal'])\nstory.append(body)\nstory.append(PageBreak())\n\n# Page 2\nstory.append(Paragraph(\"Page 2\", styles['Heading1']))\nstory.append(Paragraph(\"Content for page 2\", styles['Normal']))\n\n# Build PDF\ndoc.build(story)\n```\n\n## Command-Line Tools\n\n### pdftotext (poppler-utils)\n```bash\n# Extract text\npdftotext input.pdf output.txt\n\n# Extract text preserving layout\npdftotext -layout input.pdf output.txt\n\n# Extract specific pages\npdftotext -f 1 -l 5 input.pdf output.txt  # Pages 1-5\n```\n\n### qpdf\n```bash\n# Merge PDFs\nqpdf --empty --pages file1.pdf file2.pdf -- merged.pdf\n\n# Split pages\nqpdf input.pdf --pages . 1-5 -- pages1-5.pdf\nqpdf input.pdf --pages . 6-10 -- pages6-10.pdf\n\n# Rotate pages\nqpdf input.pdf output.pdf --rotate=+90:1  # Rotate page 1 by 90 degrees\n\n# Remove password\nqpdf --password=mypassword --decrypt encrypted.pdf decrypted.pdf\n```\n\n### pdftk (if available)\n```bash\n# Merge\npdftk file1.pdf file2.pdf cat output merged.pdf\n\n# Split\npdftk input.pdf burst\n\n# Rotate\npdftk input.pdf rotate 1east output rotated.pdf\n```\n\n## Common Tasks\n\n### Extract Text from Scanned PDFs\n```python\n# Requires: pip install pytesseract pdf2image\nimport pytesseract\nfrom pdf2image import convert_from_path\n\n# Convert PDF to images\nimages = convert_from_path('scanned.pdf')\n\n# OCR each page\ntext = \"\"\nfor i, image in enumerate(images):\n    text += f\"Page {i+1}:\\n\"\n    text += pytesseract.image_to_string(image)\n    text += \"\\n\\n\"\n\nprint(text)\n```\n\n### Add Watermark\n```python\nfrom pypdf import PdfReader, PdfWriter\n\n# Create watermark (or load existing)\nwatermark = PdfReader(\"watermark.pdf\").pages[0]\n\n# Apply to all pages\nreader = PdfReader(\"document.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    page.merge_page(watermark)\n    writer.add_page(page)\n\nwith open(\"watermarked.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n### Extract Images\n```bash\n# Using pdfimages (poppler-utils)\npdfimages -j input.pdf output_prefix\n\n# This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc.\n```\n\n### Password Protection\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n    writer.add_page(page)\n\n# Add password\nwriter.encrypt(\"userpassword\", \"ownerpassword\")\n\nwith open(\"encrypted.pdf\", \"wb\") as output:\n    writer.write(output)\n```\n\n## Quick Reference\n\n| Task | Best Tool | Command/Code |\n|------|-----------|--------------|\n| Merge PDFs | pypdf | `writer.add_page(page)` |\n| Split PDFs | pypdf | One page per file |\n| Extract text | pdfplumber | `page.extract_text()` |\n| Extract tables | pdfplumber | `page.extract_tables()` |\n| Create PDFs | reportlab | Canvas or Platypus |\n| Command line merge | qpdf | `qpdf --empty --pages ...` |\n| OCR scanned PDFs | pytesseract | Convert to image first |\n| Fill PDF forms | pdf-lib or pypdf (see forms.md) | See forms.md |\n\n## Next Steps\n\n- For advanced pypdfium2 usage, see reference.md\n- For JavaScript libraries (pdf-lib), see reference.md\n- If you need to fill out a PDF form, follow the instructions in forms.md\n- For troubleshooting guides, see reference.md\n\n<!-- File: SKILLs/playwright/agents/openai.yaml (Tokens: ~300 | Category: anthropic-skill) -->\n# Agents Skill\n\nPath: `SKILLs/playwright/agents/openai.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/agents/openai.yaml)\n\n<!-- File: SKILLs/playwright/references/cli.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `SKILLs/playwright/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/cli.md)\n\n<!-- File: SKILLs/playwright/references/workflows.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `SKILLs/playwright/references/workflows.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/playwright/references/workflows.md)\n\n<!-- File: SKILLs/playwright/SKILL.md (Tokens: ~990 | Category: anthropic-skill) -->\n---\nname: \"playwright\"\ndescription: \"Use when the task requires automating a real browser from the terminal (navigation, form filling, snapshots, screenshots, data extraction, UI-flow debugging) via `playwright-cli` or the bundled wrapper script.\"\nofficial: true\n---\n\n\n# Playwright CLI Skill\n\nDrive a real browser from the terminal using `playwright-cli`. Prefer the bundled wrapper script so the CLI works even when it is not globally installed.\nTreat this skill as CLI-first automation. Do not pivot to `@playwright/test` unless the user explicitly asks for test files.\n\n## Prerequisite check (required)\n\nBefore proposing commands, check whether `npx` is available (the wrapper depends on it):\n\n```bash\ncommand -v npx >/dev/null 2>&1\n```\n\nIf it is not available, pause and ask the user to install Node.js/npm (which provides `npx`). Provide these steps verbatim:\n\n```bash\n# Verify Node/npm are installed\nnode --version\nnpm --version\n\n# If missing, install Node.js/npm, then:\nnpm install -g @playwright/mcp@latest\nplaywright-cli --help\n```\n\nOnce `npx` is present, proceed with the wrapper script. A global install of `playwright-cli` is optional.\n\n## Skill path (set once)\n\n```bash\nexport SKILLS_ROOT=\"${LOBSTERAI_SKILLS_ROOT:-${SKILLS_ROOT:-$HOME/Library/Application Support/LobsterAI/SKILLs}}\"\nexport PWCLI=\"$SKILLS_ROOT/playwright/scripts/playwright_cli.sh\"\n```\n\nInstalled skills resolve from `$LOBSTERAI_SKILLS_ROOT` / `$SKILLS_ROOT` (production default: app `userData/SKILLs`, macOS usually `~/Library/Application Support/LobsterAI/SKILLs`).\n\n## Quick start\n\nUse the wrapper script:\n\n```bash\n\"$PWCLI\" open https://playwright.dev --headed\n\"$PWCLI\" snapshot\n\"$PWCLI\" click e15\n\"$PWCLI\" type \"Playwright\"\n\"$PWCLI\" press Enter\n\"$PWCLI\" screenshot\n```\n\nIf the user prefers a global install, this is also valid:\n\n```bash\nnpm install -g @playwright/mcp@latest\nplaywright-cli --help\n```\n\n## Core workflow\n\n1. Open the page.\n2. Snapshot to get stable element refs.\n3. Interact using refs from the latest snapshot.\n4. Re-snapshot after navigation or significant DOM changes.\n5. Capture artifacts (screenshot, pdf, traces) when useful.\n\nMinimal loop:\n\n```bash\n\"$PWCLI\" open https://example.com\n\"$PWCLI\" snapshot\n\"$PWCLI\" click e3\n\"$PWCLI\" snapshot\n```\n\n## When to snapshot again\n\nSnapshot again after:\n\n- navigation\n- clicking elements that change the UI substantially\n- opening/closing modals or menus\n- tab switches\n\nRefs can go stale. When a command fails due to a missing ref, snapshot again.\n\n## Recommended patterns\n\n### Form fill and submit\n\n```bash\n\"$PWCLI\" open https://example.com/form\n\"$PWCLI\" snapshot\n\"$PWCLI\" fill e1 \"user@example.com\"\n\"$PWCLI\" fill e2 \"password123\"\n\"$PWCLI\" click e3\n\"$PWCLI\" snapshot\n```\n\n### Debug a UI flow with traces\n\n```bash\n\"$PWCLI\" open https://example.com --headed\n\"$PWCLI\" tracing-start\n# ...interactions...\n\"$PWCLI\" tracing-stop\n```\n\n### Multi-tab work\n\n```bash\n\"$PWCLI\" tab-new https://example.com\n\"$PWCLI\" tab-list\n\"$PWCLI\" tab-select 0\n\"$PWCLI\" snapshot\n```\n\n## Wrapper script\n\nThe wrapper script uses `npx --package @playwright/mcp playwright-cli` so the CLI can run without a global install:\n\n```bash\n\"$PWCLI\" --help\n```\n\nPrefer the wrapper unless the repository already standardizes on a global install.\n\n## References\n\nOpen only what you need:\n\n- CLI command reference: `references/cli.md`\n- Practical workflows and troubleshooting: `references/workflows.md`\n\n## Guardrails\n\n- Always snapshot before referencing element ids like `e12`.\n- Re-snapshot when refs seem stale.\n- Prefer explicit commands over `eval` and `run-code` unless needed.\n- When you do not have a fresh snapshot, use placeholder refs like `eX` and say why; do not bypass refs with `run-code`.\n- Use `--headed` when a visual check will help.\n- When capturing artifacts in this repo, use `output/playwright/` and avoid introducing new top-level artifact folders.\n- Default to CLI commands and workflows, not Playwright test specs.\n\n<!-- File: SKILLs/pptx/html2pptx.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Pptx Skill\n\nPath: `SKILLs/pptx/html2pptx.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/html2pptx.md)\n\n<!-- File: SKILLs/pptx/ooxml.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Pptx Skill\n\nPath: `SKILLs/pptx/ooxml.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/ooxml.md)\n\n<!-- File: SKILLs/pptx/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Pptx Skill\n\nPath: `SKILLs/pptx/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/netease-youdao/LobsterAI/HEAD/SKILLs/pptx/package.json)\n\n<!-- File: SKILLs/pptx/SKILL.md (Tokens: ~6804 | Category: anthropic-skill) -->\n---\nname: pptx\ndescription: \"Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks\"\nlicense: Proprietary. LICENSE.txt has complete terms\nofficial: true\n---\n\n# PPTX creation, editing, and analysis\n\n## Overview\n\nA user may ask you to create, edit, or analyze the contents of a .pptx file. A .pptx file is essentially a ZIP archive containing XML files and other resources that you can read or edit. You have different tools and workflows available for different tasks.\n\n## Reading and analyzing content\n\n### Text extraction\nIf you just need to read the text contents of a presentation, you should convert the document to markdown:\n\n```bash\n# Convert document to markdown\npython -m markitdown path-to-file.pptx\n```\n\n### Raw XML access\nYou need raw XML access for: comments, speaker notes, slide layouts, animations, design elements, and complex formatting. For any of these features, you'll need to unpack a presentation and read its raw XML contents.\n\n#### Unpacking a file\n`python ooxml/scripts/unpack.py <office_file> <output_dir>`\n\n**Note**: Resolve script paths from this skill directory. Prefer `$SKILLS_ROOT/pptx/ooxml/scripts/unpack.py` when `$SKILLS_ROOT` is available; otherwise resolve `ooxml/scripts/unpack.py` relative to this `SKILL.md` file's directory. Do not assume a workspace-relative `skills/pptx/...` path.\n\n#### Key file structures\n* `ppt/presentation.xml` - Main presentation metadata and slide references\n* `ppt/slides/slide{N}.xml` - Individual slide contents (slide1.xml, slide2.xml, etc.)\n* `ppt/notesSlides/notesSlide{N}.xml` - Speaker notes for each slide\n* `ppt/comments/modernComment_*.xml` - Comments for specific slides\n* `ppt/slideLayouts/` - Layout templates for slides\n* `ppt/slideMasters/` - Master slide templates\n* `ppt/theme/` - Theme and styling information\n* `ppt/media/` - Images and other media files\n\n#### Typography and color extraction\n**When given an example design to emulate**: Always analyze the presentation's typography and colors first using the methods below:\n1. **Read theme file**: Check `ppt/theme/theme1.xml` for colors (`<a:clrScheme>`) and fonts (`<a:fontScheme>`)\n2. **Sample slide content**: Examine `ppt/slides/slide1.xml` for actual font usage (`<a:rPr>`) and colors\n3. **Search for patterns**: Use grep to find color (`<a:solidFill>`, `<a:srgbClr>`) and font references across all XML files\n\n## Creating a new PowerPoint presentation **without a template**\n\nWhen creating a new PowerPoint presentation from scratch, use the **html2pptx** workflow to convert HTML slides to PowerPoint with accurate positioning.\n\n### Design Principles\n\n**CRITICAL**: Before creating any presentation, analyze the content and choose appropriate design elements:\n1. **Consider the subject matter**: What is this presentation about? What tone, industry, or mood does it suggest?\n2. **Check for branding**: If the user mentions a company/organization, consider their brand colors and identity\n3. **Match palette to content**: Select colors that reflect the subject\n4. **State your approach**: Explain your design choices before writing code\n\n**Requirements**:\n- ✅ State your content-informed design approach BEFORE writing code\n- ✅ Use web-safe fonts only: Arial, Helvetica, Times New Roman, Georgia, Courier New, Verdana, Tahoma, Trebuchet MS, Impact\n- ✅ Create clear visual hierarchy through size, weight, and color\n- ✅ Ensure readability: strong contrast, appropriately sized text, clean alignment\n- ✅ Be consistent: repeat patterns, spacing, and visual language across slides\n\n#### Color Palette Selection\n\n**Choosing colors creatively**:\n- **Think beyond defaults**: What colors genuinely match this specific topic? Avoid autopilot choices.\n- **Consider multiple angles**: Topic, industry, mood, energy level, target audience, brand identity (if mentioned)\n- **Be adventurous**: Try unexpected combinations - a healthcare presentation doesn't have to be green, finance doesn't have to be navy\n- **Build your palette**: Pick 3-5 colors that work together (dominant colors + supporting tones + accent)\n- **Ensure contrast**: Text must be clearly readable on backgrounds\n\n**Example color palettes** (use these to spark creativity - choose one, adapt it, or create your own):\n\n1. **Classic Blue**: Deep navy (#1C2833), slate gray (#2E4053), silver (#AAB7B8), off-white (#F4F6F6)\n2. **Teal & Coral**: Teal (#5EA8A7), deep teal (#277884), coral (#FE4447), white (#FFFFFF)\n3. **Bold Red**: Red (#C0392B), bright red (#E74C3C), orange (#F39C12), yellow (#F1C40F), green (#2ECC71)\n4. **Warm Blush**: Mauve (#A49393), blush (#EED6D3), rose (#E8B4B8), cream (#FAF7F2)\n5. **Burgundy Luxury**: Burgundy (#5D1D2E), crimson (#951233), rust (#C15937), gold (#997929)\n6. **Deep Purple & Emerald**: Purple (#B165FB), dark blue (#181B24), emerald (#40695B), white (#FFFFFF)\n7. **Cream & Forest Green**: Cream (#FFE1C7), forest green (#40695B), white (#FCFCFC)\n8. **Pink & Purple**: Pink (#F8275B), coral (#FF574A), rose (#FF737D), purple (#3D2F68)\n9. **Lime & Plum**: Lime (#C5DE82), plum (#7C3A5F), coral (#FD8C6E), blue-gray (#98ACB5)\n10. **Black & Gold**: Gold (#BF9A4A), black (#000000), cream (#F4F6F6)\n11. **Sage & Terracotta**: Sage (#87A96B), terracotta (#E07A5F), cream (#F4F1DE), charcoal (#2C2C2C)\n12. **Charcoal & Red**: Charcoal (#292929), red (#E33737), light gray (#CCCBCB)\n13. **Vibrant Orange**: Orange (#F96D00), light gray (#F2F2F2), charcoal (#222831)\n14. **Forest Green**: Black (#191A19), green (#4E9F3D), dark green (#1E5128), white (#FFFFFF)\n15. **Retro Rainbow**: Purple (#722880), pink (#D72D51), orange (#EB5C18), amber (#F08800), gold (#DEB600)\n16. **Vintage Earthy**: Mustard (#E3B448), sage (#CBD18F), forest green (#3A6B35), cream (#F4F1DE)\n17. **Coastal Rose**: Old rose (#AD7670), beaver (#B49886), eggshell (#F3ECDC), ash gray (#BFD5BE)\n18. **Orange & Turquoise**: Light orange (#FC993E), grayish turquoise (#667C6F), white (#FCFCFC)\n\n#### Visual Details Options\n\n**Geometric Patterns**:\n- Diagonal section dividers instead of horizontal\n- Asymmetric column widths (30/70, 40/60, 25/75)\n- Rotated text headers at 90° or 270°\n- Circular/hexagonal frames for images\n- Triangular accent shapes in corners\n- Overlapping shapes for depth\n\n**Border & Frame Treatments**:\n- Thick single-color borders (10-20pt) on one side only\n- Double-line borders with contrasting colors\n- Corner brackets instead of full frames\n- L-shaped borders (top+left or bottom+right)\n- Underline accents beneath headers (3-5pt thick)\n\n**Typography Treatments**:\n- Extreme size contrast (72pt headlines vs 11pt body)\n- All-caps headers with wide letter spacing\n- Numbered sections in oversized display type\n- Monospace (Courier New) for data/stats/technical content\n- Condensed fonts (Arial Narrow) for dense information\n- Outlined text for emphasis\n\n**Chart & Data Styling**:\n- Monochrome charts with single accent color for key data\n- Horizontal bar charts instead of vertical\n- Dot plots instead of bar charts\n- Minimal gridlines or none at all\n- Data labels directly on elements (no legends)\n- Oversized numbers for key metrics\n\n**Layout Innovations**:\n- Full-bleed images with text overlays\n- Sidebar column (20-30% width) for navigation/context\n- Modular grid systems (3×3, 4×4 blocks)\n- Z-pattern or F-pattern content flow\n- Floating text boxes over colored shapes\n- Magazine-style multi-column layouts\n\n**Background Treatments**:\n- Solid color blocks occupying 40-60% of slide\n- Gradient fills (vertical or diagonal only)\n- Split backgrounds (two colors, diagonal or vertical)\n- Edge-to-edge color bands\n- Negative space as a design element\n\n### Layout Tips\n**When creating slides with charts or tables:**\n- **Two-column layout (PREFERRED)**: Use a header spanning the full width, then two columns below - text/bullets in one column and the featured content in the other. This provides better balance and makes charts/tables more readable. Use flexbox with unequal column widths (e.g., 40%/60% split) to optimize space for each content type.\n- **Full-slide layout**: Let the featured content (chart/table) take up the entire slide for maximum impact and readability\n- **NEVER vertically stack**: Do not place charts/tables below text in a single column - this causes poor readability and layout issues\n\n### Workflow\n1. **MANDATORY - READ ENTIRE FILE**: Read `html2pptx.md` from the same directory as this `SKILL.md` (installed default: `$SKILLS_ROOT/pptx/html2pptx.md`) completely from start to finish. **NEVER set any range limits when reading this file.** Read the full file content for detailed syntax, critical formatting rules, and best practices before proceeding with presentation creation.\n2. Create an HTML file for each slide with proper dimensions (e.g., 720pt × 405pt for 16:9)\n   - Use `<p>`, `<h1>`-`<h6>`, `<ul>`, `<ol>` for all text content\n   - Use `class=\"placeholder\"` for areas where charts/tables will be added (render with gray background for visibility)\n   - **CRITICAL**: Rasterize gradients and icons as PNG images FIRST using Sharp, then reference in HTML\n   - **LAYOUT**: For slides with charts/tables/images, use either full-slide layout or two-column layout for better readability\n3. Create and run a JavaScript file using the [`html2pptx.js`](scripts/html2pptx.js) library to convert HTML slides to PowerPoint and save the presentation\n   - Use the `html2pptx()` function to process each HTML file\n   - Add charts and tables to placeholder areas using PptxGenJS API\n   - Save the presentation using `pptx.writeFile()`\n4. **Visual validation**: Generate thumbnails and inspect for layout issues\n   - Create thumbnail grid: `python scripts/thumbnail.py output.pptx workspace/thumbnails --cols 4`\n   - Read and carefully examine the thumbnail image for:\n     - **Text cutoff**: Text being cut off by header bars, shapes, or slide edges\n     - **Text overlap**: Text overlapping with other text or shapes\n     - **Positioning issues**: Content too close to slide boundaries or other elements\n     - **Contrast issues**: Insufficient contrast between text and backgrounds\n   - If issues found, adjust HTML margins/spacing/colors and regenerate the presentation\n   - Repeat until all slides are visually correct\n\n## Live editing in LobsterAI\n\nWhen the `ppt_read` and `ppt_edit` tools exist, change existing presentations through them instead of unpacking and repacking the file. The presentation opens in LobsterAI's right-side PowerPoint editor, edits appear there immediately, the theme, layouts, animations and everything the tools do not touch are preserved, and the file saves automatically.\n\n1. Call `ppt_read` with the absolute `path` (and `slides` such as `\"2-4\"` for long decks). It returns `revision`, the layout names, and for each slide its number, layout, speaker notes and shapes: `id`, `name`, `kind`, placeholder role, position and size in points, `text` (one line per paragraph, leading tabs give the bullet level) and table cells. It also returns the user's current `selection` (\"改这里\" means that slide and shape).\n2. Call `ppt_edit` with the same `path`, `expectedRevision` from the read, and a list of `edits`; slides are numbered from 1 and shapes are addressed by their `id`:\n   - `replace_text` `{slide?, shape?, find, replace, occurrence?}` for wording changes; it keeps the formatting around the phrase.\n   - `set_text` `{slide, shape, text}` rewrites a shape's text and keeps its formatting; `set_table_cell` `{slide, shape, row, column, text}`.\n   - `format_text` (bold, italic, underline, strike, color, size in pt, font) on a `find` phrase, a `paragraph` or the whole shape; `format_paragraph` (alignment, bullet `level`).\n   - `set_bounds` `{slide, shape, x?, y?, width?, height?}` in points, `delete_shape`, `add_text_box`.\n   - `add_slide` `{after?, layout?, title?, body?}` with a layout name from the read, `duplicate_slide`, `move_slide` `{slide, position}`, `delete_slide`, `set_notes`.\n3. Edits in one call apply in order as one undoable step, and slide numbers in later edits refer to the deck after the earlier ones. If the call is refused because the revision changed, the user edited the presentation meanwhile: read again and redo the edit. If any edit fails, nothing is applied; fix the reported edit and retry.\n\nUse the OOXML workflow below only for what these tools cannot do: pictures, charts, SmartArt, new designs, or presentations LobsterAI reports as read-only.\n\n## Editing an existing PowerPoint presentation\n\nWhen edit slides in an existing PowerPoint presentation, you need to work with the raw Office Open XML (OOXML) format. This involves unpacking the .pptx file, editing the XML content, and repacking it.\n\n### Workflow\n1. **MANDATORY - READ ENTIRE FILE**: Read `ooxml.md` from the same directory as this `SKILL.md` (installed default: `$SKILLS_ROOT/pptx/ooxml.md`) (~500 lines) completely from start to finish.  **NEVER set any range limits when reading this file.**  Read the full file content for detailed guidance on OOXML structure and editing workflows before any presentation editing.\n2. Unpack the presentation: `python ooxml/scripts/unpack.py <office_file> <output_dir>`\n3. Edit the XML files (primarily `ppt/slides/slide{N}.xml` and related files)\n4. **CRITICAL**: Validate immediately after each edit and fix any validation errors before proceeding: `python ooxml/scripts/validate.py <dir> --original <file>`\n5. Pack the final presentation: `python ooxml/scripts/pack.py <input_directory> <office_file>`\n\n## Creating a new PowerPoint presentation **using a template**\n\nWhen you need to create a presentation that follows an existing template's design, you'll need to duplicate and re-arrange template slides before then replacing placeholder context.\n\n### Workflow\n1. **Extract template text AND create visual thumbnail grid**:\n   * Extract text: `python -m markitdown template.pptx > template-content.md`\n   * Read `template-content.md`: Read the entire file to understand the contents of the template presentation. **NEVER set any range limits when reading this file.**\n   * Create thumbnail grids: `python scripts/thumbnail.py template.pptx`\n   * See [Creating Thumbnail Grids](#creating-thumbnail-grids) section for more details\n\n2. **Analyze template and save inventory to a file**:\n   * **Visual Analysis**: Review thumbnail grid(s) to understand slide layouts, design patterns, and visual structure\n   * Create and save a template inventory file at `template-inventory.md` containing:\n     ```markdown\n     # Template Inventory Analysis\n     **Total Slides: [count]**\n     **IMPORTANT: Slides are 0-indexed (first slide = 0, last slide = count-1)**\n\n     ## [Category Name]\n     - Slide 0: [Layout code if available] - Description/purpose\n     - Slide 1: [Layout code] - Description/purpose\n     - Slide 2: [Layout code] - Description/purpose\n     [... EVERY slide must be listed individually with its index ...]\n     ```\n   * **Using the thumbnail grid**: Reference the visual thumbnails to identify:\n     - Layout patterns (title slides, content layouts, section dividers)\n     - Image placeholder locations and counts\n     - Design consistency across slide groups\n     - Visual hierarchy and structure\n   * This inventory file is REQUIRED for selecting appropriate templates in the next step\n\n3. **Create presentation outline based on template inventory**:\n   * Review available templates from step 2.\n   * Choose an intro or title template for the first slide. This should be one of the first templates.\n   * Choose safe, text-based layouts for the other slides.\n   * **CRITICAL: Match layout structure to actual content**:\n     - Single-column layouts: Use for unified narrative or single topic\n     - Two-column layouts: Use ONLY when you have exactly 2 distinct items/concepts\n     - Three-column layouts: Use ONLY when you have exactly 3 distinct items/concepts\n     - Image + text layouts: Use ONLY when you have actual images to insert\n     - Quote layouts: Use ONLY for actual quotes from people (with attribution), never for emphasis\n     - Never use layouts with more placeholders than you have content\n     - If you have 2 items, don't force them into a 3-column layout\n     - If you have 4+ items, consider breaking into multiple slides or using a list format\n   * Count your actual content pieces BEFORE selecting the layout\n   * Verify each placeholder in the chosen layout will be filled with meaningful content\n   * Select one option representing the **best** layout for each content section.\n   * Save `outline.md` with content AND template mapping that leverages available designs\n   * Example template mapping:\n      ```\n      # Template slides to use (0-based indexing)\n      # WARNING: Verify indices are within range! Template with 73 slides has indices 0-72\n      # Mapping: slide numbers from outline -> template slide indices\n      template_mapping = [\n          0,   # Use slide 0 (Title/Cover)\n          34,  # Use slide 34 (B1: Title and body)\n          34,  # Use slide 34 again (duplicate for second B1)\n          50,  # Use slide 50 (E1: Quote)\n          54,  # Use slide 54 (F2: Closing + Text)\n      ]\n      ```\n\n4. **Duplicate, reorder, and delete slides using `rearrange.py`**:\n   * Use the `scripts/rearrange.py` script to create a new presentation with slides in the desired order:\n     ```bash\n     python scripts/rearrange.py template.pptx working.pptx 0,34,34,50,52\n     ```\n   * The script handles duplicating repeated slides, deleting unused slides, and reordering automatically\n   * Slide indices are 0-based (first slide is 0, second is 1, etc.)\n   * The same slide index can appear multiple times to duplicate that slide\n\n5. **Extract ALL text using the `inventory.py` script**:\n   * **Run inventory extraction**:\n     ```bash\n     python scripts/inventory.py working.pptx text-inventory.json\n     ```\n   * **Read text-inventory.json**: Read the entire text-inventory.json file to understand all shapes and their properties. **NEVER set any range limits when reading this file.**\n\n   * The inventory JSON structure:\n      ```json\n        {\n          \"slide-0\": {\n            \"shape-0\": {\n              \"placeholder_type\": \"TITLE\",  // or null for non-placeholders\n              \"left\": 1.5,                  // position in inches\n              \"top\": 2.0,\n              \"width\": 7.5,\n              \"height\": 1.2,\n              \"paragraphs\": [\n                {\n                  \"text\": \"Paragraph text\",\n                  // Optional properties (only included when non-default):\n                  \"bullet\": true,           // explicit bullet detected\n                  \"level\": 0,               // only included when bullet is true\n                  \"alignment\": \"CENTER\",    // CENTER, RIGHT (not LEFT)\n                  \"space_before\": 10.0,     // space before paragraph in points\n                  \"space_after\": 6.0,       // space after paragraph in points\n                  \"line_spacing\": 22.4,     // line spacing in points\n                  \"font_name\": \"Arial\",     // from first run\n                  \"font_size\": 14.0,        // in points\n                  \"bold\": true,\n                  \"italic\": false,\n                  \"underline\": false,\n                  \"color\": \"FF0000\"         // RGB color\n                }\n              ]\n            }\n          }\n        }\n      ```\n\n   * Key features:\n     - **Slides**: Named as \"slide-0\", \"slide-1\", etc.\n     - **Shapes**: Ordered by visual position (top-to-bottom, left-to-right) as \"shape-0\", \"shape-1\", etc.\n     - **Placeholder types**: TITLE, CENTER_TITLE, SUBTITLE, BODY, OBJECT, or null\n     - **Default font size**: `default_font_size` in points extracted from layout placeholders (when available)\n     - **Slide numbers are filtered**: Shapes with SLIDE_NUMBER placeholder type are automatically excluded from inventory\n     - **Bullets**: When `bullet: true`, `level` is always included (even if 0)\n     - **Spacing**: `space_before`, `space_after`, and `line_spacing` in points (only included when set)\n     - **Colors**: `color` for RGB (e.g., \"FF0000\"), `theme_color` for theme colors (e.g., \"DARK_1\")\n     - **Properties**: Only non-default values are included in the output\n\n6. **Generate replacement text and save the data to a JSON file**\n   Based on the text inventory from the previous step:\n   - **CRITICAL**: First verify which shapes exist in the inventory - only reference shapes that are actually present\n   - **VALIDATION**: The replace.py script will validate that all shapes in your replacement JSON exist in the inventory\n     - If you reference a non-existent shape, you'll get an error showing available shapes\n     - If you reference a non-existent slide, you'll get an error indicating the slide doesn't exist\n     - All validation errors are shown at once before the script exits\n   - **IMPORTANT**: The replace.py script uses inventory.py internally to identify ALL text shapes\n   - **AUTOMATIC CLEARING**: ALL text shapes from the inventory will be cleared unless you provide \"paragraphs\" for them\n   - Add a \"paragraphs\" field to shapes that need content (not \"replacement_paragraphs\")\n   - Shapes without \"paragraphs\" in the replacement JSON will have their text cleared automatically\n   - Paragraphs with bullets will be automatically left aligned. Don't set the `alignment` property on when `\"bullet\": true`\n   - Generate appropriate replacement content for placeholder text\n   - Use shape size to determine appropriate content length\n   - **CRITICAL**: Include paragraph properties from the original inventory - don't just provide text\n   - **IMPORTANT**: When bullet: true, do NOT include bullet symbols (•, -, *) in text - they're added automatically\n   - **ESSENTIAL FORMATTING RULES**:\n     - Headers/titles should typically have `\"bold\": true`\n     - List items should have `\"bullet\": true, \"level\": 0` (level is required when bullet is true)\n     - Preserve any alignment properties (e.g., `\"alignment\": \"CENTER\"` for centered text)\n     - Include font properties when different from default (e.g., `\"font_size\": 14.0`, `\"font_name\": \"Lora\"`)\n     - Colors: Use `\"color\": \"FF0000\"` for RGB or `\"theme_color\": \"DARK_1\"` for theme colors\n     - The replacement script expects **properly formatted paragraphs**, not just text strings\n     - **Overlapping shapes**: Prefer shapes with larger default_font_size or more appropriate placeholder_type\n   - Save the updated inventory with replacements to `replacement-text.json`\n   - **WARNING**: Different template layouts have different shape counts - always check the actual inventory before creating replacements\n\n   Example paragraphs field showing proper formatting:\n   ```json\n   \"paragraphs\": [\n     {\n       \"text\": \"New presentation title text\",\n       \"alignment\": \"CENTER\",\n       \"bold\": true\n     },\n     {\n       \"text\": \"Section Header\",\n       \"bold\": true\n     },\n     {\n       \"text\": \"First bullet point without bullet symbol\",\n       \"bullet\": true,\n       \"level\": 0\n     },\n     {\n       \"text\": \"Red colored text\",\n       \"color\": \"FF0000\"\n     },\n     {\n       \"text\": \"Theme colored text\",\n       \"theme_color\": \"DARK_1\"\n     },\n     {\n       \"text\": \"Regular paragraph text without special formatting\"\n     }\n   ]\n   ```\n\n   **Shapes not listed in the replacement JSON are automatically cleared**:\n   ```json\n   {\n     \"slide-0\": {\n       \"shape-0\": {\n         \"paragraphs\": [...] // This shape gets new text\n       }\n       // shape-1 and shape-2 from inventory will be cleared automatically\n     }\n   }\n   ```\n\n   **Common formatting patterns for presentations**:\n   - Title slides: Bold text, sometimes centered\n   - Section headers within slides: Bold text\n   - Bullet lists: Each item needs `\"bullet\": true, \"level\": 0`\n   - Body text: Usually no special properties needed\n   - Quotes: May have special alignment or font properties\n\n7. **Apply replacements using the `replace.py` script**\n   ```bash\n   python scripts/replace.py working.pptx replacement-text.json output.pptx\n   ```\n\n   The script will:\n   - First extract the inventory of ALL text shapes using functions from inventory.py\n   - Validate that all shapes in the replacement JSON exist in the inventory\n   - Clear text from ALL shapes identified in the inventory\n   - Apply new text only to shapes with \"paragraphs\" defined in the replacement JSON\n   - Preserve formatting by applying paragraph properties from the JSON\n   - Handle bullets, alignment, font properties, and colors automatically\n   - Save the updated presentation\n\n   Example validation errors:\n   ```\n   ERROR: Invalid shapes in replacement JSON:\n     - Shape 'shape-99' not found on 'slide-0'. Available shapes: shape-0, shape-1, shape-4\n     - Slide 'slide-999' not found in inventory\n   ```\n\n   ```\n   ERROR: Replacement text made overflow worse in these shapes:\n     - slide-0/shape-2: overflow worsened by 1.25\" (was 0.00\", now 1.25\")\n   ```\n\n## Creating Thumbnail Grids\n\nTo create visual thumbnail grids of PowerPoint slides for quick analysis and reference:\n\n```bash\npython scripts/thumbnail.py template.pptx [output_prefix]\n```\n\n**Features**:\n- Creates: `thumbnails.jpg` (or `thumbnails-1.jpg`, `thumbnails-2.jpg`, etc. for large decks)\n- Default: 5 columns, max 30 slides per grid (5×6)\n- Custom prefix: `python scripts/thumbnail.py template.pptx my-grid`\n  - Note: The output prefix should include the path if you want output in a specific directory (e.g., `workspace/my-grid`)\n- Adjust columns: `--cols 4` (range: 3-6, affects slides per grid)\n- Grid limits: 3 cols = 12 slides/grid, 4 cols = 20, 5 cols = 30, 6 cols = 42\n- Slides are zero-indexed (Slide 0, Slide 1, etc.)\n\n**Use cases**:\n- Template analysis: Quickly understand slide layouts and design patterns\n- Content review: Visual overview of entire presentation\n- Navigation reference: Find specific slides by their visual appearance\n- Quality check: Verify all slides are properly formatted\n\n**Examples**:\n```bash\n# Basic usage\npython scripts/thumbnail.py presentation.pptx\n\n# Combine options: custom name, columns\npython scripts/thumbnail.py template.pptx analysis --cols 4\n```\n\n## Converting Slides to Images\n\nTo visually analyze PowerPoint slides, convert them to images using a two-step process:\n\n1. **Convert PPTX to PDF**:\n   ```bash\n   soffice --headless --convert-to pdf template.pptx\n   ```\n\n2. **Convert PDF pages to JPEG images**:\n   ```bash\n   pdftoppm -jpeg -r 150 template.pdf slide\n   ```\n   This creates files like `slide-1.jpg`, `slide-2.jpg`, etc.\n\nOptions:\n- `-r 150`: Sets resolution to 150 DPI (adjust for quality/size balance)\n- `-jpeg`: Output JPEG format (use `-png` for PNG if preferred)\n- `-f N`: First page to convert (e.g., `-f 2` starts from page 2)\n- `-l N`: Last page to convert (e.g., `-l 5` stops at page 5)\n- `slide`: Prefix for output files\n\nExample for specific range:\n```bash\npdftoppm -jpeg -r 150 -f 2 -l 5 template.pdf slide  # Converts only pages 2-5\n```\n\n## Code Style Guidelines\n**IMPORTANT**: When generating code for PPTX operations:\n- Write concise code\n- Avoid verbose variable names and redundant operations\n- Avoid unnecessary print statements\n\n## Dependencies\n\nRequired dependencies (should already be installed):\n\n- **markitdown**: `pip install \"markitdown[pptx]\"` (for text extraction from presentations)\n- **pptxgenjs**: `npm install -g pptxgenjs` (for creating presentations via html2pptx)\n- **playwright**: `npm install -g playwright` (for HTML rendering in html2pptx)\n- **react-icons**: `npm install -g react-icons react react-dom` (for icons)\n- **sharp**: `npm install -g sharp` (for SVG rasterization and image processing)\n- **LibreOffice**: `sudo apt-get install libreoffice` (for PDF conversion)\n- **Poppler**: `sudo apt-get install poppler-utils` (for pdftoppm to convert PDF to images)\n- **defusedxml**: `pip install defusedxml` (for secure XML parsing)\n\n<!-- ... +62 more modular skills available via /api/skills/netease-youdao/LobsterAI?path={path} -->\n</yakaai_skills>"}