Skip to main content

Skill Development Guide

This document provides technical implementation details for the Skill system, including architecture, Provider development, and API reference.

Basic Concepts: Please read Skill System Concepts first to understand the basic concepts.


Skill Implementation by Shell Type​

The Skill system has different implementations for different Shell types:

Shell TypeSkill Loading MethodCharacteristics
ChatDynamic loading (load_skill tool)LLM calls on-demand, prompt injection
ClaudeCodePre-deployed to filesystemDownloaded to ~/.claude/skills/ at task startup

Chat Shell Skill Flow​

Loading Flow​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Task Start - ChatConfigBuilder builds configuration β”‚
β”‚ β†’ Extract skill metadata from Ghost.spec.skills β”‚
β”‚ β†’ Inject skill summaries into system prompt β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. System Prompt Contains: β”‚
β”‚ "## Available Skills β”‚
β”‚ - **skill_name**: description (call load_skill to use)" β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. LLM Decides to Load Skill β”‚
β”‚ β†’ Calls load_skill(skill_name="xxx") tool β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. LoadSkillTool Executes β”‚
β”‚ a. Find Skill (user private first, then public) β”‚
β”‚ b. Extract full prompt from SKILL.md β”‚
β”‚ c. Load Provider dynamically (public skills only) β”‚
β”‚ d. Register tools with SkillToolRegistry β”‚
β”‚ e. Cache loaded skill for session β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Implementation Details​

  1. ChatConfigBuilder (chat_shell/chat_shell/services/chat_service.py)

    • Extracts skill metadata from Ghost configuration
    • Builds skill_names and skill_configs for the session
  2. System Prompt Injection

    • append_skill_metadata_prompt() injects skill summaries
    • Format: - **{skill_name}**: {description}
  3. LoadSkillTool

    • Built-in tool called by LLM
    • Session-level caching prevents duplicate loading
    • Dynamic Provider loading for public skills only

Claude Code Skill Flow​

Loading Flow​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Task Start - ClaudeCodeAgent Initialization β”‚
β”‚ β†’ Get skills list from bot_config β”‚
β”‚ β†’ Call _download_and_deploy_skills() β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. SkillDownloader Downloads Skills β”‚
β”‚ a. Call Backend API to query skill info β”‚
β”‚ GET /api/v1/kinds/skills?name={skill_name} β”‚
β”‚ b. Download skill ZIP package β”‚
β”‚ GET /api/v1/kinds/skills/{skill_id}/download β”‚
β”‚ c. Extract to skills directory β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. Skills Deployment Complete β”‚
β”‚ - Docker mode: ~/.claude/skills/ β”‚
β”‚ - Local mode: {task_config_dir}/skills/ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. Claude Code SDK Uses Skills β”‚
β”‚ - SDK automatically reads SKILL.md from skills directory β”‚
β”‚ - User-selected skills get emphasis prompt added β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Mode Differences​

FeatureDocker ModeLocal Mode
Skills Directory~/.claude/skills/{task_config_dir}/skills/
Cache StrategyClear and redeploy each timePreserve existing, only download new
clear_cachetruefalse
skip_existingfalsetrue

Key Components​

  1. SkillDownloader (executor/services/api_client.py)

    • Downloads skill ZIP packages from Backend API
    • Extracts to specified directory
    • Supports cache strategy configuration
  2. ModeStrategy (executor/agents/claude_code/mode_strategy.py)

    • Defines get_skills_directory() to get skills directory
    • Defines get_skills_deployment_options() to get deployment options
  3. User-Selected Skills Emphasis (executor/agents/claude_code/claude_code_agent.py)

    • _build_skill_emphasis_prompt() generates emphasis prompt for user-selected skills
    • Prompt prefix encourages model to prioritize using these skills

Skill Provider System​

Providers allow Skills to define custom tools that are dynamically loaded at runtime (Chat Shell only).

Provider Interface​

from abc import ABC, abstractmethod
from typing import Any, Optional
from langchain_core.tools import BaseTool

class SkillToolProvider(ABC):
"""Base class for Skill tool providers."""

@property
@abstractmethod
def provider_name(self) -> str:
"""Unique identifier for the provider."""
pass

@property
@abstractmethod
def supported_tools(self) -> list[str]:
"""List of tool names this provider supports."""
pass

@abstractmethod
def create_tool(
self,
tool_name: str,
context: SkillToolContext,
tool_config: Optional[dict[str, Any]] = None,
) -> BaseTool:
"""Create a tool instance."""
pass

Example Provider Implementation​

from chat_shell.chat_shell.skills.provider import SkillToolProvider
from chat_shell.chat_shell.skills.context import SkillToolContext

class MermaidToolProvider(SkillToolProvider):
@property
def provider_name(self) -> str:
return "mermaid"

@property
def supported_tools(self) -> list[str]:
return ["render_mermaid"]

def create_tool(
self,
tool_name: str,
context: SkillToolContext,
tool_config: Optional[dict[str, Any]] = None,
) -> BaseTool:
config = tool_config or {}
from .render_mermaid import RenderMermaidTool
return RenderMermaidTool(
task_id=context.task_id,
subtask_id=context.subtask_id,
ws_emitter=context.ws_emitter,
render_timeout=config.get("timeout", 30.0),
)

Provider Configuration in SKILL.md​

---
description: "Diagram visualization"
provider:
module: provider # Python module name (without .py)
class: MyToolProvider # Provider class name
tools:
- name: tool_name
provider: provider_name
config:
timeout: 30
dependencies:
- chat_shell.chat_shell.tools.pending_requests
---

SkillToolRegistry​

The SkillToolRegistry (chat_shell/chat_shell/skills/registry.py) manages:

  • Provider registration and lookup (singleton, thread-safe)
  • Dynamic Provider loading from ZIP packages
  • Tool instance creation for skills

Security Considerations​

⚠️ Important: Only public Skills (user_id=0) can load dynamic code from providers. User-uploaded Skills can only provide prompt content. This prevents malicious code execution from user uploads.


Database Storage​

Tables​

TablePurpose
kindsSkill CRD metadata (like other CRDs)
skill_binariesZIP package binary storage

skill_binaries Schema​

CREATE TABLE skill_binaries (
id INT PRIMARY KEY AUTO_INCREMENT,
kind_id INT NOT NULL, -- References kinds.id
binary_data LONGBLOB NOT NULL, -- ZIP package content
file_size INT NOT NULL, -- File size in bytes
file_hash VARCHAR(64) NOT NULL, -- SHA256 hash
created_at DATETIME,
FOREIGN KEY (kind_id) REFERENCES kinds(id) ON DELETE CASCADE
);

API Endpoints​

EndpointMethodDescription
/skills/uploadPOSTUpload Skill ZIP package
/skillsGETList current user's Skills
/skills/unifiedGETList user + public Skills
/skills/public/listGETList public Skills
/skills/publicPOSTCreate public Skill (admin only)
/skills/invokePOSTGet Skill prompt content
/skills/{skill_id}GETGet Skill details
/skills/{skill_id}/downloadGETDownload Skill ZIP package
/skills/{skill_id}PUTUpdate Skill
/skills/{skill_id}DELETEDelete Skill (checks references)
/api/tasks/{task_id}/skillsGETGet task-associated Skills (used by Claude Code)

Key Source Files​

Chat Shell​

FilePurpose
chat_shell/chat_shell/skills/registry.pySkillToolRegistry singleton
chat_shell/chat_shell/skills/provider.pySkillToolProvider base class
chat_shell/chat_shell/skills/context.pySkillToolContext for tool creation
chat_shell/chat_shell/tools/skill_factory.pySkill tool factory

Executor (Claude Code)​

FilePurpose
executor/services/api_client.pySkillDownloader and fetch_task_skills
executor/agents/claude_code/claude_code_agent.py_download_and_deploy_skills implementation
executor/agents/claude_code/mode_strategy.pyModeStrategy base class
executor/agents/claude_code/docker_mode_strategy.pyDocker mode strategy
executor/agents/claude_code/local_mode_strategy.pyLocal mode strategy

Backend​

FilePurpose
backend/app/schemas/kind.pySkill CRD schema definition
backend/app/models/skill_binary.pySkillBinary SQLAlchemy model
backend/app/api/endpoints/kind/skills.pyREST API routes
backend/app/services/skill_service.pySkillValidator for ZIP validation

Frontend​

FilePurpose
frontend/src/apis/skills.tsAPI client functions
frontend/src/features/settings/components/SkillListWithScope.tsxSkill list with scope selector
frontend/src/features/settings/components/skills/SkillManagementModal.tsxSkill management dialog
frontend/src/features/settings/components/skills/SkillUploadModal.tsxSkill upload dialog

Built-in Skills​

Located in backend/init_data/skills/:

SkillDescription
mermaid-diagramDiagram visualization using Mermaid.js
wiki_submitWiki submission capability

Skill Lifecycle​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Create Skill β”‚
β”‚ - User uploads ZIP package β”‚
β”‚ - Validate SKILL.md format and extract metadata β”‚
β”‚ - Store in kinds table and skill_binaries table β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. Configure Association β”‚
β”‚ - Add skill name to Ghost.spec.skills[] β”‚
β”‚ - Ghost is referenced by Bot β”‚
β”‚ - Bot is referenced by Team β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. Runtime Loading β”‚
β”‚ Chat Shell: β”‚
β”‚ - Skill metadata injected into system prompt β”‚
β”‚ - LLM calls load_skill() on demand β”‚
β”‚ - Provider loaded and tools registered β”‚
β”‚ β”‚
β”‚ Claude Code: β”‚
β”‚ - Download skill ZIP packages at task startup β”‚
β”‚ - Extract to skills directory β”‚
β”‚ - Claude Code SDK automatically reads and uses β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. Update/Delete β”‚
β”‚ - Update: Upload new ZIP, metadata updated β”‚
β”‚ - Delete: Check Ghost references first, reject if referenced β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Provider Development Best Practices​

  1. Follow the interface - Implement all abstract methods
  2. Handle errors gracefully - Return meaningful error messages
  3. Use context properly - Access task_id, subtask_id, ws_emitter from context
  4. Configure timeouts - Set reasonable timeouts in tool_config