Skip to content

Feature: Implement ClaudeSkill Multiplatform Support for mpp-ui, mpp-vscode, and CLI #533

@phodal

Description

@phodal

Feature Proposal: ClaudeSkill Multiplatform Support

Description

Implement Claude Skills support across all multiplatform targets (mpp-ui, mpp-vscode, CLI) to enable users to use organized folders of instructions, scripts, and resources that agents can discover and load dynamically.

Motivation

Claude Skills are currently only implemented in mpp-idea (IntelliJ IDEA plugin). To provide a consistent experience across all platforms (CLI, VSCode, Desktop Compose, Web), we need to port this functionality to the multiplatform codebase.

Claude Skills allow users to:

  • Create reusable prompt templates with YAML frontmatter
  • Define variables that can be resolved at runtime
  • Organize skills in project directories or user home (~/.claude/skills/)
  • Execute skills via /skill.<skillname> commands

Current Implementation Analysis (mpp-idea)

Key Components

  1. ClaudeSkillCommand (mpp-idea-core/.../ClaudeSkillCommand.kt)

    • Data class representing a loaded skill
    • Properties: skillName, description, template, skillPath, icon
    • Methods:
      • executeWithCompiler() - Uses SpecKitTemplateCompiler for variable resolution
      • toCustomCommand() - Converts to DevIns custom command
    • Companion object methods:
      • all(project) - Load all skills from project root and user home
      • loadFromProjectRoot() - Scan project directories for SKILL.md
      • loadFromUserSkillsDir() - Scan ~/.claude/skills/
      • fromSkillName() / fromFullName() - Find specific skill
  2. SkillFrontmatter (mpp-idea-core/.../SpecKitFrontmatter.kt)

    • Parses YAML frontmatter from SKILL.md files
    • Extracts: name, description, variables, additionalFields
  3. SpecKitTemplateCompiler (mpp-idea-core/.../SpecKitTemplateCompiler.kt)

    • Compiles templates with Velocity engine
    • Resolves variables from frontmatter
    • Adds project-level variables
  4. ClaudeSkillInsCommand (devins-lang/.../ClaudeSkillInsCommand.kt)

    • DevIns command implementation for /skill.<name>
    • Parses skill name from command prop
    • Executes skill with compiler
  5. BuiltinCommand.CLAUDE_SKILL - Enum entry for the skill command

Proposed Solution

Phase 1: Core Implementation (mpp-core)

1.1 Create ClaudeSkillCommand in mpp-core

// mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/command/ClaudeSkillCommand.kt
data class ClaudeSkillCommand(
    val skillName: String,
    val description: String,
    val template: String,
    val skillPath: String  // Use String instead of Path for multiplatform
) {
    val fullCommandName: String get() = "skill.$skillName"
    
    companion object {
        private const val SKILL_FILE = "SKILL.md"
        private const val USER_SKILLS_DIR = ".claude/skills"
        
        fun loadAll(fileSystem: ProjectFileSystem): List<ClaudeSkillCommand>
        fun loadFromProjectRoot(fileSystem: ProjectFileSystem): List<ClaudeSkillCommand>
        fun loadFromUserSkillsDir(fileSystem: ProjectFileSystem): List<ClaudeSkillCommand>
        fun findBySkillName(skills: List<ClaudeSkillCommand>, name: String): ClaudeSkillCommand?
        fun findByFullName(skills: List<ClaudeSkillCommand>, name: String): ClaudeSkillCommand?
    }
}

1.2 Extend SkillFrontmatter (already exists, may need updates)

The existing SkillFrontmatter parsing in mpp-core can be reused.

1.3 Update CommandProcessor

Add skill command handling to mpp-core/.../processor/CommandProcessor.kt:

private suspend fun processSkillCommand(
    commandName: String,
    arguments: String,
    context: CompilerContext
): ProcessResult {
    // Similar to processSpecKitCommand but for Claude Skills
}

1.4 Platform-specific User Home Resolution

Add expect/actual for getting user home directory:

// commonMain
expect fun getUserHomeDirectory(): String?

// jvmMain
actual fun getUserHomeDirectory(): String? = System.getProperty("user.home")

// jsMain (Node.js)
actual fun getUserHomeDirectory(): String? = js("require('os').homedir()")

// wasmJsMain
actual fun getUserHomeDirectory(): String? = null  // Not supported in browser

// iosMain
actual fun getUserHomeDirectory(): String? = NSHomeDirectory()

Phase 2: CLI Support (mpp-ui TypeScript)

2.1 Add SkillCommandProcessor

// mpp-ui/src/jsMain/typescript/processors/SkillCommandProcessor.ts
export class SkillCommandProcessor implements InputProcessor {
  name = 'SkillCommandProcessor';
  
  canHandle(input: string): boolean {
    return input.startsWith('/skill.');
  }
  
  async process(input: string, context: ProcessorContext): Promise<ProcessorResult> {
    // Parse skill name and arguments
    // Load skill from filesystem
    // Compile template
    // Return compiled result
  }
}

2.2 Register in InputRouter

Update mpp-ui/src/jsMain/typescript/ui/App.tsx to register the skill processor.

2.3 Add Skill Completion Support

Update completion providers to suggest available skills.

Phase 3: VSCode Support (mpp-vscode)

3.1 Update mpp-core.ts Bridge

// mpp-vscode/src/bridge/mpp-core.ts
export class SkillManager {
  private skills: ClaudeSkillCommand[] = [];
  
  async loadSkills(projectPath: string): Promise<void>;
  getSkills(): ClaudeSkillCommand[];
  findSkill(name: string): ClaudeSkillCommand | null;
  async executeSkill(name: string, args: string): Promise<string>;
}

3.2 Add Skill Command Handler

Update mpp-vscode/src/commands/ to handle /skill.* commands.

3.3 Add Skill Completion Provider

Provide IntelliSense for skill commands in the chat input.

Phase 4: Desktop Compose Support (mpp-ui Kotlin)

4.1 Integrate with Existing Command System

The Compose desktop app uses the same mpp-core, so it should work automatically once Phase 1 is complete.

4.2 Add UI for Skill Management (Optional)

Consider adding a skill browser/manager UI component.

Implementation Tasks

mpp-core

  • Create ClaudeSkillCommand.kt in mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/command/
  • Add getUserHomeDirectory() expect/actual declarations
  • Update CommandProcessor.kt to handle skill commands
  • Add skill command to completion providers
  • Export skill-related classes for JS (@JsExport)
  • Write unit tests for skill loading and execution

mpp-ui (CLI/TypeScript)

  • Create SkillCommandProcessor.ts
  • Register processor in InputRouter
  • Add skill completion support
  • Update CLI help to document skill commands
  • Write integration tests

mpp-vscode

  • Update mpp-core.ts with SkillManager class
  • Add skill command handling in chat provider
  • Add completion provider for skills
  • Update webview to display skill execution results
  • Write tests

Documentation

  • Document skill file format (SKILL.md)
  • Document skill locations (project root, ~/.claude/skills/)
  • Add examples of skill usage

Technical Considerations

File System Abstraction

The existing ProjectFileSystem interface in mpp-core provides the necessary abstraction:

  • readFile(path) - Read SKILL.md content
  • listFiles(path, pattern) - List skill directories
  • exists(path) - Check if skill exists
  • isDirectory(path) - Verify skill directory

Platform Differences

Platform User Home Project Root Notes
JVM (Desktop) System.getProperty("user.home") From workspace Full support
Node.js (CLI) os.homedir() process.cwd() Full support
VSCode os.homedir() Workspace folder Full support
WASM (Browser) N/A Virtual FS Limited - no user home
iOS NSHomeDirectory() App sandbox Limited
Android Context-based App storage Limited

Template Compilation

Reuse existing SpecKitTemplateCompiler in mpp-core which already handles:

  • Frontmatter parsing
  • Variable resolution
  • Template compilation (simple string replacement, not Velocity in mpp-core)

Alternatives Considered

  1. Keep skills IDEA-only: Rejected because it limits the usefulness of skills to only IntelliJ users.

  2. Use a separate skills service: Rejected because it adds unnecessary complexity. The file-based approach is simpler and works offline.

  3. Different skill format per platform: Rejected to maintain consistency. SKILL.md format works everywhere.

Additional Context

Related Files

  • mpp-idea/mpp-idea-core/src/main/kotlin/cc/unitmesh/devti/command/dataprovider/ClaudeSkillCommand.kt
  • mpp-idea/mpp-idea-core/src/main/kotlin/cc/unitmesh/devti/command/dataprovider/SpecKitFrontmatter.kt
  • mpp-idea/mpp-idea-core/src/main/kotlin/cc/unitmesh/devti/command/dataprovider/SpecKitTemplateCompiler.kt
  • mpp-idea/mpp-idea-exts/devins-lang/src/main/kotlin/cc/unitmesh/devti/language/compiler/exec/claudeskill/ClaudeSkillInsCommand.kt
  • mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/command/SpecKitCommand.kt (similar pattern)
  • mpp-core/src/commonMain/kotlin/cc/unitmesh/devins/filesystem/ProjectFileSystem.kt

Example SKILL.md Format

---
name: pdf
description: Handle PDF document operations
variables:
  DOCUMENT_PATH: "path/to/document.pdf"
---

## Instructions

Process the PDF document at $DOCUMENT_PATH with the following requirements:

$ARGUMENTS

Example Usage

/skill.pdf Extract all tables from the quarterly report
/skill.code-review Review the changes in src/main.ts

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions