一键导入
Scaffold a new skill in an existing app (BaseSkill, schemas, app.yml, i18n)
npx skills add https://github.com/glowingkitty/OpenMates --skill add-app-skill复制此命令并粘贴到 Claude Code 中以安装该技能
Scaffold a new skill in an existing app (BaseSkill, schemas, app.yml, i18n)
npx skills add https://github.com/glowingkitty/OpenMates --skill add-app-skill复制此命令并粘贴到 Claude Code 中以安装该技能
Create OpenMates marketing videos from script notes using the external Remotion workspace, product-accurate UI rebuilds, optional Playwright recordings, renders, and review uploads.
Integrate a new external API provider (research, wrapper, test script, docs)
Scaffold and register a new embed type (components, theme, icons, i18n, renderer)
Create a new hardcoded example chat from a shared chat URL with encryption key
Run a structured 5-round Q&A to fully understand a bug or feature request before writing any code. Outputs a Task Brief with user flow, acceptance criteria, scope, edge cases, affected areas, and open questions. Use at the start of any non-trivial session.
Create a pull request from dev to main with proper formatting and draft release
| name | add-app-skill |
| description | Scaffold a new skill in an existing app (BaseSkill, schemas, app.yml, i18n) |
| user-invocable | true |
| argument-hint | <appId> <skillId> <SkillClassName> |
Parse $ARGUMENTS into three parts:
appId — app directory name (e.g., web, news, travel)skillId — kebab-case skill identifier (e.g., deep-research)SkillClassName — PascalCase class name (e.g., DeepResearchSkill)If any are missing, ask the user before proceeding.
You are adding a new skill to an existing app microservice. This touches backend Python code, YAML config, and i18n.
Read these files to understand the app's patterns:
backend/apps/{appId}/app.yml — existing skills, embed types, categoriesbackend/apps/base_skill.py (lines 1-145) — BaseSkill interfacebackend/apps/{appId}/skills/ — use as templatebackend/shared/python_schemas/app_metadata_schemas.py — AppYAML schema (for valid field names)Create backend/apps/{appId}/skills/{skill_file}.py where skill_file is skillId with hyphens replaced by underscores.
Follow this structure exactly:
"""
{SkillClassName} — {brief description}.
Architecture: docs/architecture/app_skills.md
"""
import logging
from typing import Dict, Any, Optional
from pydantic import BaseModel, Field
from backend.apps.base_skill import BaseSkill
logger = logging.getLogger(__name__)
class {SkillName}Request(BaseModel):
"""{description}."""
# Define input fields from tool_schema
class {SkillName}Response(BaseModel):
"""{description}."""
success: bool = Field(default=False)
# Define output fields
class {SkillClassName}(BaseSkill):
"""
{Description of what this skill does}.
"""
async def execute(
self,
# Skill-specific params (must match tool_schema properties)
secrets_manager=None,
cache_service=None,
encryption_service=None,
directus_service=None,
user_id: Optional[str] = None,
chat_id: Optional[str] = None,
**kwargs
) -> {SkillName}Response:
"""Execute the skill."""
try:
# Implementation here
return {SkillName}Response(success=True)
except Exception as e:
logger.error(f"{SkillClassName} error: {e}", exc_info=True)
return {SkillName}Response(success=False, error=str(e))
Add to the skills: list in backend/apps/{appId}/app.yml:
- id: {skillId}
name_translation_key: {appId}.{skill_id_underscored}
description_translation_key: {appId}.{skill_id_underscored}.description
icon_image: {icon}.svg
preprocessor_hint: >
Natural language description for AI model routing
stage: development
providers:
- name: OpenMates
no_api_key: true
class_path: backend.apps.{appId}.skills.{skill_file}.{SkillClassName}
tool_schema:
type: object
properties:
# Define input parameters
required:
# List required params
If the skill produces embeds, also add an embed_types: entry.
Add skill name and description to frontend/packages/ui/src/i18n/sources/skills.yml (all 20 locales).
Then rebuild:
cd frontend/packages/ui && npm run build:translations
If scripts/test_skills/ exists, create test_{skill_id_underscored}.py following the pattern of other test scripts in that directory.
Ask the user: "Does this skill produce embeds that need a frontend component?"
If yes, suggest running /add-embed-type {appId} {skillId} {SkillName} next.
BaseSkill or backend/shared/execute() params must match tool_schema.properties names exactlylogger = logging.getLogger(__name__) — never print()PascalCase — end request models with Request, response with Responsestage should be development until tested