npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kubiya/skill-engine-sdk

v0.1.0

Published

JavaScript/TypeScript SDK for creating Skill Engine skills

Readme

Skill Engine JavaScript/TypeScript SDK

Build portable, secure skills for the Skill Engine using JavaScript or TypeScript. Skills compile to WebAssembly Components and run in a sandboxed environment with WASI Preview 2.

Features

  • 🚀 Zero Config - Just write JavaScript/TypeScript, no build setup needed
  • 🔒 Secure - Sandboxed execution with capability-based security
  • 📦 Portable - Compile to WASM Components that run anywhere
  • 🎯 Type Safe - Full TypeScript support with type definitions
  • 🔧 Simple API - Intuitive skill definition with defineSkill()
  • 🌐 Multi-Language - Interoperate with skills written in Rust, Go, Python

Installation

npm install @kubiya/skill-engine-sdk

Quick Start

1. Create a Skill

Create skill.ts:

import { defineSkill, getConfig } from '@skill-engine/sdk';

export default defineSkill({
  metadata: {
    name: 'my-skill',
    version: '1.0.0',
    description: 'My awesome skill',
    author: 'Your Name'
  },
  tools: [
    {
      name: 'greet',
      description: 'Greet someone by name',
      parameters: [
        {
          name: 'name',
          paramType: 'string',
          description: 'Name to greet',
          required: true
        }
      ],
      handler: async (args) => {
        return {
          success: true,
          output: `Hello, ${args.name}!`,
          errorMessage: null
        };
      }
    }
  ]
});

2. Build and Compile

# Install dependencies
npm install

# Build TypeScript to JavaScript
npm run build

# Compile to WASM Component
npx skill-sdk componentize dist/skill.js -o skill.wasm

3. Run with Skill Engine

# Install the skill
skill install ./skill.wasm --instance my-instance

# Run a tool
skill run my-skill greet name=World
# Output: Hello, World!

API Reference

defineSkill(config)

Define a skill with metadata, tools, and optional configuration validation.

import { defineSkill, type SkillConfig } from '@skill-engine/sdk';

const skill = defineSkill({
  metadata: {
    name: 'example-skill',
    version: '1.0.0',
    description: 'Example skill',
    author: 'Your Name'
  },
  tools: [
    // Tool definitions...
  ],
  validateConfig: (config) => {
    // Optional: validate configuration
    if (!config.API_KEY) {
      return { err: 'API_KEY is required' };
    }
    return { ok: null };
  }
});

Parameters

  • metadata (required): Skill metadata

    • name: Unique identifier (kebab-case)
    • version: Semantic version (e.g., "1.0.0")
    • description: Brief description
    • author: Author name or organization
  • tools (required): Array of tool definitions

    • name: Tool identifier (kebab-case)
    • description: What the tool does
    • parameters: Array of parameter definitions
    • handler: Async function that executes the tool
  • validateConfig (optional): Configuration validator function

    • Receives config object with environment variables
    • Returns { ok: null } on success or { err: string } on failure

getConfig<T>()

Get type-safe access to configuration from environment variables. The Skill Engine passes configuration as SKILL_* environment variables.

import { getConfig, type EnvironmentConfig } from '@skill-engine/sdk';

interface MyConfig extends EnvironmentConfig {
  API_KEY: string;
  REGION: string;
  DEBUG: string;
}

const config = getConfig<MyConfig>();
console.log(config.API_KEY);    // Type-safe access
console.log(config.REGION);     // Type-safe access
console.log(config.DEBUG);      // Type-safe access

Tool Handlers

Tool handlers receive parsed arguments and return execution results:

{
  name: 'process-data',
  description: 'Process data with options',
  parameters: [
    {
      name: 'input',
      paramType: 'string',
      description: 'Input data',
      required: true
    },
    {
      name: 'format',
      paramType: 'string',
      description: 'Output format',
      required: false,
      defaultValue: 'json'
    }
  ],
  handler: async (args) => {
    try {
      // Access arguments
      const input = args.input;
      const format = args.format; // Uses default if not provided

      // Do work...
      const result = processData(input, format);

      // Return success
      return {
        success: true,
        output: JSON.stringify(result),
        errorMessage: null
      };
    } catch (error) {
      // Return error
      return {
        success: false,
        output: '',
        errorMessage: error.message
      };
    }
  }
}

Parameter Types

  • string: Text value
  • number: Numeric value
  • boolean: True/false value
  • file: File path (pre-opened by host)

Configuration

Skills can access configuration through environment variables prefixed with SKILL_:

import { getConfig } from '@skill-engine/sdk';

// User configures: skill config my-skill --set API_KEY=abc123
// Skill receives: SKILL_API_KEY=abc123

const config = getConfig();
const apiKey = config.API_KEY; // "abc123"

Configuration Validation

Validate configuration before execution:

defineSkill({
  // ...
  validateConfig: (config) => {
    // Check required values
    if (!config.API_KEY) {
      return { err: 'API_KEY is required' };
    }

    // Validate format
    if (!config.API_KEY.startsWith('sk-')) {
      return { err: 'Invalid API_KEY format' };
    }

    // Check dependencies
    if (config.ENABLE_FEATURE && !config.FEATURE_KEY) {
      return { err: 'FEATURE_KEY required when ENABLE_FEATURE is true' };
    }

    return { ok: null };
  }
});

Advanced Examples

External API Integration

import { defineSkill, getConfig } from '@skill-engine/sdk';
import fetch from 'node-fetch';

interface Config {
  API_KEY: string;
  BASE_URL: string;
}

export default defineSkill({
  metadata: {
    name: 'api-skill',
    version: '1.0.0',
    description: 'Call external API',
    author: 'Your Name'
  },
  tools: [
    {
      name: 'fetch-data',
      description: 'Fetch data from API',
      parameters: [
        {
          name: 'endpoint',
          paramType: 'string',
          description: 'API endpoint path',
          required: true
        }
      ],
      handler: async (args) => {
        const config = getConfig<Config>();

        try {
          const response = await fetch(
            `${config.BASE_URL}${args.endpoint}`,
            {
              headers: {
                'Authorization': `Bearer ${config.API_KEY}`
              }
            }
          );

          const data = await response.json();

          return {
            success: true,
            output: JSON.stringify(data, null, 2),
            errorMessage: null
          };
        } catch (error) {
          return {
            success: false,
            output: '',
            errorMessage: error.message
          };
        }
      }
    }
  ],
  validateConfig: (config) => {
    if (!config.API_KEY) {
      return { err: 'API_KEY is required' };
    }
    if (!config.BASE_URL) {
      return { err: 'BASE_URL is required' };
    }
    return { ok: null };
  }
});

File Operations

import { defineSkill } from '@skill-engine/sdk';
import { readFile, writeFile } from 'fs/promises';

export default defineSkill({
  metadata: {
    name: 'file-skill',
    version: '1.0.0',
    description: 'File operations skill',
    author: 'Your Name'
  },
  tools: [
    {
      name: 'read-file',
      description: 'Read file contents',
      parameters: [
        {
          name: 'path',
          paramType: 'file',
          description: 'File path to read',
          required: true
        }
      ],
      handler: async (args) => {
        try {
          const content = await readFile(args.path, 'utf-8');
          return {
            success: true,
            output: content,
            errorMessage: null
          };
        } catch (error) {
          return {
            success: false,
            output: '',
            errorMessage: `Failed to read file: ${error.message}`
          };
        }
      }
    },
    {
      name: 'write-file',
      description: 'Write content to file',
      parameters: [
        {
          name: 'path',
          paramType: 'file',
          description: 'File path to write',
          required: true
        },
        {
          name: 'content',
          paramType: 'string',
          description: 'Content to write',
          required: true
        }
      ],
      handler: async (args) => {
        try {
          await writeFile(args.path, args.content, 'utf-8');
          return {
            success: true,
            output: `Wrote ${args.content.length} bytes to ${args.path}`,
            errorMessage: null
          };
        } catch (error) {
          return {
            success: false,
            output: '',
            errorMessage: `Failed to write file: ${error.message}`
          };
        }
      }
    }
  ]
});

CLI Tool: skill-sdk

The SDK includes a CLI tool for development tasks:

Componentize

Compile JavaScript skill to WASM Component:

npx skill-sdk componentize dist/skill.js -o skill.wasm

Options:

  • -o, --output <file>: Output WASM file (required)
  • --wit <dir>: WIT directory path (default: ../../../wit)
  • --world <name>: WIT world name (default: skill)
  • --debug: Enable debug output

Validate

Validate skill structure and exports:

npx skill-sdk validate dist/skill.js

This checks:

  • Required exports exist (getMetadata, getTools, executeTool, validateConfig)
  • Metadata is complete
  • Tools are properly defined
  • Parameters are valid

TypeScript Configuration

Recommended tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "bundler",
    "declaration": true,
    "strict": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*"]
}

Package Structure

my-skill/
├── package.json
├── tsconfig.json
├── src/
│   └── skill.ts          # Main skill definition
├── dist/                 # Compiled JavaScript (generated)
│   └── skill.js
└── skill.wasm           # WASM Component (generated)

Best Practices

  1. Use TypeScript for type safety and better IDE support
  2. Validate configuration to fail fast on missing/invalid config
  3. Handle errors gracefully and return descriptive error messages
  4. Keep tools focused - one tool should do one thing well
  5. Use semantic versioning for your skill versions
  6. Document parameters with clear descriptions
  7. Test locally before deploying to production

Troubleshooting

"Module not found" errors

Make sure to install all dependencies:

npm install @skill-engine/sdk
npm install  # Install other dependencies from package.json

Componentization fails

Check that:

  • Your skill exports default from defineSkill()
  • All required exports are present (getMetadata, getTools, executeTool, validateConfig)
  • The WIT directory exists at wit/skill-interface.wit
  • You have @bytecodealliance/jco installed

Configuration not available

Configuration is passed as environment variables with SKILL_ prefix:

  • User sets: skill config my-skill --set API_KEY=value
  • Skill receives: process.env.SKILL_API_KEY
  • Access via: getConfig().API_KEY

Examples

See the examples/ directory for complete working examples:

  • simple-skill: Basic "Hello World" skill
  • aws-skill: AWS integration with S3, EC2, Lambda
  • github-skill: GitHub API integration

License

MIT

Contributing

Contributions welcome! Please open an issue or PR on GitHub.

Links