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>"
Arguments
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.
Instructions
You are adding a new skill to an existing app microservice. This touches backend Python code, YAML config, and i18n.
Step 1: Understand the Target App
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 interface- An existing skill in
backend/apps/{appId}/skills/— use as template backend/shared/python_schemas/app_metadata_schemas.py— AppYAML schema (for valid field names)
Step 1b: Create Skill Behavior Spec
Before scaffolding a new app skill, run specify or create an inline spec using
docs/contributing/guides/spec-driven-development.md.
New app skills usually require a full spec because they define user-facing AI behavior, tool contracts, provider behavior, and often embed behavior. The spec must include:
- Sample user prompts
- Expected tool input parameters
- Expected skill output shape
- No-results behavior
- Provider-error behavior
- Permission, privacy, and API-key behavior
- Embed preview/fullscreen behavior if the skill produces embeds
- App-store examples that double as executable examples
Step 2: Create the Skill File
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))
Step 3: Register in app.yml
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.
Step 4: Add i18n Entries
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
Step 5: Add App-Store Examples
Every new app skill must include app-store examples so the skill details page can show realistic preview cards.
If the skill produces embeds:
- Run or script at least two real skill requests that cover the main provider/result shapes.
- Create
frontend/packages/ui/src/components/embeds/{appId}/{SkillName}EmbedPreview.examples.tsnext to the preview component. - Export an array of flat preview props matching the preview component, with
query_translation_keyvalues undersettings.app_store_examples.{appId}.{skill_id_underscored}.<n>. - Add those query labels to
frontend/packages/ui/src/i18n/sources/settings/app_store_examples.yml.
If the skill does not produce embeds, add equivalent user-facing examples in backend/apps/{appId}/app.yml using the existing example_entries or example_translation_keys pattern for that app.
Step 6: Create Test Script (Optional)
If scripts/test_skills/ exists, create test_{skill_id_underscored}.py following the pattern of other test scripts in that directory.
Step 7: Check for Embed Need
Ask the user: "Does this skill produce embeds that need a frontend component?"
If yes, suggest running /add-embed-type {appId} {skillId} {SkillName} next.
Rules
- Skills must NOT import from other skills — shared logic goes to
BaseSkillorbackend/shared/ - All
execute()params must matchtool_schema.propertiesnames exactly - Use
logger = logging.getLogger(__name__)— neverprint() - Type hints on all function parameters and return values
- Pydantic models use
PascalCase— end request models withRequest, response withResponse - Do not add
stage; implemented skills are enabled by default unlessdefault_enabled: falseis explicitly needed - App-store examples are required for every new skill; do not ship a skill with an empty examples section
Expert Next.js App Router
Developpement
Un skill qui transforme Claude en expert Next.js App Router.
Générateur de README
Developpement
Crée des README.md professionnels et complets pour vos projets.
Rédacteur de Documentation API
Developpement
Génère de la documentation API complète au format OpenAPI/Swagger.