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

ai-skills-manager

v1.8.0

Published

AI Skills Manager - CLI tool for managing Claude Code Agent Skills

Readme

AI Skills Manager

npm version npm downloads license

AI Skills Manager (ASM) enables team members to create, test, distribute, install, update, and remove skills. It focuses on the Claude Code Agent Skills system developed by Anthropic.

Installation

Prerequisites

From NPM

Global Install

npm install -g ai-skills-manager

As a Project Dependency

npm install ai-skills-manager

From Source

# Clone the repository
git clone https://github.com/lwndev/ai-skills-manager.git
cd ai-skills-manager

# Install dependencies
npm install

# Build the project
npm run build

# Link the CLI globally (optional)
npm link

Usage

Create a New Skill

Use the scaffold command to create a new Claude Code skill:

# Create a basic skill in .claude/skills/ (project scope)
asm scaffold my-skill

# Create a skill with a description
asm scaffold my-skill --description "A helpful skill for code reviews"

# Create a personal skill in ~/.claude/skills/
asm scaffold my-skill --personal

# Create a skill in a custom location
asm scaffold my-skill --output ./custom/path

# Specify allowed tools
asm scaffold my-skill --allowed-tools "Read,Write,Bash"

# Overwrite existing directory without prompting
asm scaffold my-skill --force

Template Options

Choose a template variant to generate skill-specific frontmatter and guidance:

# Default template with general guidance
asm scaffold my-skill --template basic

# Isolated context with read-only tools
asm scaffold my-skill --template forked

# Includes hook configuration examples
asm scaffold my-skill --template with-hooks

# Non-user-invocable helper skill
asm scaffold my-skill --template internal

Individual frontmatter flags can be combined with any template:

# Set context, agent, and hooks independently
asm scaffold my-skill --context fork --hooks
asm scaffold my-skill --agent Explore --no-user-invocable

# agentskills.io spec fields
asm scaffold my-skill --license MIT --compatibility "Claude Code 2.x"
asm scaffold my-skill --metadata author="Jane Doe" --metadata version="1.0"
asm scaffold search-helper --template forked --argument-hint "<query> [--deep]"

Minimal Mode

Generate shorter templates without educational guidance text:

asm scaffold my-skill --minimal
asm scaffold my-skill --template with-hooks --minimal

Interactive Mode

Launch a guided prompt-driven workflow that walks through template selection and configuration step by step:

asm scaffold my-skill --interactive
asm scaffold my-skill -i
asm scaffold my-skill --interactive --project

Interactive mode requires a TTY (interactive terminal). Template-content flags (--template, --context, etc.) are ignored when --interactive is set. Output-location flags (--output, --project, --personal, --force) are still respected.

Scaffold Options

| Option | Description | |--------|-------------| | -d, --description <text> | Short description of the skill | | -o, --output <path> | Output directory path (overrides --project and --personal) | | -p, --project | Create as a project skill in .claude/skills/ (default) | | --personal | Create as a personal skill in ~/.claude/skills/ | | -a, --allowed-tools <tools> | Comma-separated list of allowed tools | | -f, --force | Overwrite existing directory without prompting | | -t, --template <type> | Template variant: basic, forked, with-hooks, internal | | --context <context> | Set context in frontmatter (fork) | | --agent <name> | Set agent field in frontmatter | | --no-user-invocable | Set user-invocable: false in frontmatter | | --hooks | Include commented hook examples in frontmatter | | --minimal | Generate shorter templates without educational guidance text | | --license <text> | Set license field in frontmatter (e.g., MIT, Apache-2.0) | | --compatibility <text> | Set compatibility field in frontmatter (max 500 chars) | | --metadata <key=value> | Set metadata key-value pair (repeatable) | | --argument-hint <hint> | Set argument hint for skill invocation (max 200 chars) | | -i, --interactive | Launch guided prompt-driven scaffold workflow |

Template Types

| Template | Description | |----------|-------------| | basic | Default template with general guidance | | forked | For skills running in isolated (forked) context | | with-hooks | Template demonstrating hook configuration | | internal | For non-user-invocable helper skills |

Skill Name Requirements

  • Lowercase letters, numbers, and hyphens only
  • Cannot start or end with a hyphen
  • Cannot contain consecutive hyphens
  • Maximum 64 characters
  • Cannot use reserved words: "anthropic", "claude"

Generated Structure

my-skill/
  SKILL.md        # Skill instructions and metadata
  scripts/        # Directory for skill scripts
    .gitkeep

Validate a Skill

Use the validate command to check that a skill conforms to the Claude Code specification:

# Validate a skill directory
asm validate ./my-skill

# Validate a project skill
asm validate .claude/skills/my-skill

# Validate using direct path to SKILL.md
asm validate ./my-skill/SKILL.md

# Quiet mode - show only pass/fail (for CI/CD)
asm validate ./my-skill --quiet

# JSON output (for programmatic use)
asm validate ./my-skill --json

Validate Options

| Option | Description | |--------|-------------| | -q, --quiet | Minimal output - show only pass/fail result | | -j, --json | Output validation result as JSON |

Validation Checks

The validate command performs these checks in order:

  1. File existence - Verifies SKILL.md exists at the specified path
  2. Frontmatter validity - Checks YAML frontmatter structure and syntax
  3. Required fields - Validates name and description are present and non-empty
  4. Allowed properties - Ensures only permitted frontmatter keys are used
  5. Name format - Validates hyphen-case format, max 64 characters
  6. Description format - Validates no angle brackets, max 1024 characters
  7. Compatibility format - Validates optional compatibility field (max 500 characters)
  8. Context format - Validates optional context field (must be "fork" if present)
  9. Agent format - Validates optional agent field (must be non-empty string if present)
  10. Hooks format - Validates optional hooks object structure; unknown hook keys produce warnings
  11. User-invocable format - Validates optional user-invocable field (must be boolean if present)
  12. Argument hint format - Validates optional argument-hint field (max 200 characters)
  13. Keep-coding-instructions format - Validates optional keep-coding-instructions field (boolean)
  14. Tools format - Validates optional tools field (string or string array)
  15. Color format - Validates optional color field (blue, cyan, green, yellow, magenta, red)
  16. Disable-model-invocation format - Validates optional disable-model-invocation field (boolean)
  17. Version format - Validates optional version field (non-empty string)
  18. Allowed tools format - Validates optional allowed-tools field (supports Task(AgentName), mcp__server__*, ${CLAUDE_PLUGIN_ROOT} patterns)
  19. Name matches directory - Validates frontmatter name matches parent directory name
  20. File size - Warns when skill body exceeds recommended size budget

Exit Codes

  • 0 - Skill is valid
  • 1 - Skill is invalid or an error occurred

Output Examples

Normal output (valid skill):

Validating skill at: ./my-skill/SKILL.md
Skill name: my-skill

✓ File existence
✓ Frontmatter validity
✓ Required fields
✓ Allowed properties
✓ Name format
✓ Description format

✓ Skill is valid!

Quiet output:

PASS

JSON output:

{
  "valid": true,
  "skillPath": "./my-skill/SKILL.md",
  "skillName": "my-skill",
  "checks": {
    "fileExists": { "passed": true },
    "frontmatterValid": { "passed": true },
    "requiredFields": { "passed": true },
    "allowedProperties": { "passed": true },
    "nameFormat": { "passed": true },
    "descriptionFormat": { "passed": true },
    "compatibilityFormat": { "passed": true },
    "contextFormat": { "passed": true },
    "agentFormat": { "passed": true },
    "hooksFormat": { "passed": true },
    "userInvocableFormat": { "passed": true },
    "argumentHintFormat": { "passed": true },
    "keepCodingInstructionsFormat": { "passed": true },
    "toolsFormat": { "passed": true },
    "colorFormat": { "passed": true },
    "disableModelInvocationFormat": { "passed": true },
    "versionFormat": { "passed": true },
    "allowedToolsFormat": { "passed": true },
    "nameMatchesDirectory": { "passed": true },
    "fileSize": { "passed": true }
  },
  "errors": [],
  "warnings": []
}

List Installed Skills

Use the list command (alias ls) to view installed Claude Code skills:

# List all installed skills (project + personal)
asm list

# List only project skills
asm list --scope project

# List only personal skills
asm list --scope personal

# JSON output (for programmatic use)
asm list --json

# Quiet mode - one name per line
asm list --quiet

# Shorthand alias
asm ls

Recursive Discovery

Discover skills in nested .claude/skills directories (useful for monorepos and workspaces):

# Scan nested directories for skills
asm list --recursive

# Limit search depth (default: 3)
asm list --recursive --depth 2

# Recursive with JSON output
asm list --recursive --json

List Options

| Option | Description | |--------|-------------| | -s, --scope <scope> | Scope filter: all (default), project, or personal | | -j, --json | Output as JSON | | -q, --quiet | Quiet mode - show only skill names | | -r, --recursive | Discover skills in nested .claude/skills directories | | -d, --depth <number> | Maximum depth for recursive discovery (0-10, default: 3) |

Output Formats

Normal output (default):

Project skills (.claude/skills/):
  my-skill        A helpful skill for code reviews
  git-workflow    Manages git operations with validation

Personal skills (~/.claude/skills/):
  code-reviewer   Reviews code and suggests improvements

JSON output:

[
  {
    "name": "my-skill",
    "scope": "project",
    "path": ".claude/skills/my-skill",
    "description": "A helpful skill for code reviews"
  }
]

Quiet output:

my-skill
git-workflow
code-reviewer

Exit Codes

  • 0 - Success (even if no skills found)
  • 1 - File system error (permission denied, etc.)

Package a Skill

Use the package command to create a distributable .skill package from a skill directory:

# Package a skill from the current project
asm package .claude/skills/my-skill

# Specify output directory
asm package ./my-skill --output ./dist

# Force overwrite existing package
asm package ./my-skill --force

# Skip validation (use with caution)
asm package ./my-skill --skip-validation

# Quiet mode for CI/CD
asm package ./my-skill --quiet

Package Options

| Option | Description | |--------|-------------| | -o, --output <path> | Output directory for the package file | | -f, --force | Overwrite existing package without prompting | | -s, --skip-validation | Skip pre-package validation | | -q, --quiet | Quiet mode - minimal output |

Packaging Process

  1. Validates the skill (unless --skip-validation is used)
  2. Creates a ZIP archive with .skill extension
  3. Includes all skill files (SKILL.md, scripts/, etc.)
  4. Excludes common development artifacts (.git, node_modules, .DS_Store, etc.)

Exit Codes

  • 0 - Package created successfully
  • 1 - Skill validation failed
  • 2 - File system error (path not found, permission denied)
  • 3 - Package creation error

Install a Skill

Use the install command to install a Claude Code skill from a .skill package file:

# Install to project scope (default: .claude/skills/)
asm install my-skill.skill

# Install to personal scope (~/.claude/skills/)
asm install my-skill.skill --scope personal

# Install to a custom directory
asm install my-skill.skill --scope ~/.claude/skills

# Force overwrite existing skill
asm install my-skill.skill --force

# Preview what would be installed (dry run)
asm install my-skill.skill --dry-run

# Quiet mode for CI/CD
asm install my-skill.skill --quiet

Install Options

| Option | Description | |--------|-------------| | -s, --scope <scope> | Installation scope: "project", "personal", or custom path | | -f, --force | Overwrite existing skill without prompting | | -n, --dry-run | Show what would be installed without making changes | | -q, --quiet | Quiet mode - minimal output | | -t, --thorough | Use content hashing for accurate file comparison (slower) |

Installation Scopes

| Scope | Directory | Description | |-------|-----------|-------------| | project (default) | .claude/skills/ | Skills for current project only | | personal | ~/.claude/skills/ | Skills available across all projects | | Custom path | Any valid path | Install to a specific directory |

Installation Process

  1. Validates the package file (exists, valid ZIP, correct structure)
  2. Validates package contents (SKILL.md, metadata)
  3. Checks for existing skill at target location
  4. Prompts for confirmation if overwriting (unless --force)
  5. Extracts files to target directory
  6. Validates installed skill
  7. Rolls back on validation failure

Security Note

Skills can execute code and access files. Only install packages from trusted sources. The SKILL.md file describes what the skill does - review it before using the skill.

Exit Codes

  • 0 - Skill installed successfully
  • 1 - Validation failed (package or post-installation)
  • 2 - File system error (path not found, permission denied)
  • 3 - Package extraction error
  • 4 - User cancelled installation

Update a Skill

Use the update command to update an installed skill to a newer version from a .skill package:

# Update a skill in project scope (default)
asm update my-skill ./my-skill-v2.skill

# Update a skill in personal scope
asm update my-skill ./my-skill-v2.skill --scope personal

# Preview update without making changes
asm update my-skill ./my-skill-v2.skill --dry-run

# Force update without confirmation
asm update my-skill ./my-skill-v2.skill --force

# Update without creating backup (not recommended)
asm update my-skill ./my-skill-v2.skill --no-backup

# Keep backup after successful update
asm update my-skill ./my-skill-v2.skill --keep-backup

# Quiet mode for CI/CD
asm update my-skill ./my-skill-v2.skill --quiet --force

Update Options

| Option | Description | |--------|-------------| | -s, --scope <scope> | Target scope: "project" or "personal" (default: project) | | -f, --force | Skip confirmation prompt | | -n, --dry-run | Preview update without making changes | | -q, --quiet | Quiet mode - minimal output | | --no-backup | Skip backup creation (not recommended) | | --keep-backup | Keep backup after successful update |

Update Process

  1. Validates the skill name and locates the installed skill
  2. Validates the new .skill package (structure, contents, security)
  3. Compares versions and shows diff summary (files added/removed/modified)
  4. Creates a backup in ~/.asm/backups/ (unless --no-backup)
  5. Prompts for confirmation (unless --force)
  6. Replaces the installed skill with the new version atomically
  7. Validates the updated skill
  8. Removes backup on success (unless --keep-backup)
  9. Rolls back automatically if any step fails

Backup and Restore

Backups are stored in ~/.asm/backups/ with the format <skill-name>-<timestamp>-<random>.skill. By default, backups are automatically deleted after a successful update. Use --keep-backup to preserve them.

To manually restore from a backup:

# Uninstall the current version
asm uninstall my-skill

# Reinstall from backup
asm install ~/.asm/backups/my-skill-20250103-143022-a1b2c3d4.skill

Rollback Behavior

If an update fails at any point, ASM automatically rolls back to the previous version:

  • Before extraction: No changes made, backup deleted
  • During extraction: Partial extraction removed, original restored
  • After validation failure: New version removed, original restored

If rollback also fails (exit code 7), the backup file is preserved for manual recovery.

Exit Codes

| Code | Description | |------|-------------| | 0 | Skill updated successfully | | 1 | Skill not found | | 2 | File system error (permission denied, disk full, etc.) | | 3 | User cancelled update | | 4 | Invalid new package | | 5 | Security error (path traversal, invalid name, etc.) | | 6 | Rollback performed (update failed but rollback succeeded) | | 7 | Rollback failed (critical error - check backup) |

Output Examples

Normal output:

Updating skill 'my-skill' in .claude/skills/

Current version:
  Name: my-skill
  Files: 3 (2.1 KB)

New version:
  Package: ./my-skill-v2.skill
  Files: 4 (2.8 KB)

Changes:
  + scripts/new-helper.sh (added)
  ~ SKILL.md (modified, +200 bytes)

Backup created: ~/.asm/backups/my-skill-20250103-143022-a1b2c3d4.skill

Proceed with update? [y/N] y

Updating skill...
✓ Skill 'my-skill' updated successfully
  Added: 1 file
  Modified: 1 file
  Backup removed

Dry run output:

[DRY RUN] Would update skill 'my-skill' in .claude/skills/

Current version:
  Name: my-skill
  Files: 3 (2.1 KB)

New version:
  Package: ./my-skill-v2.skill
  Files: 4 (2.8 KB)

Changes:
  + scripts/new-helper.sh (added)
  ~ SKILL.md (modified, +200 bytes)

Backup would be created: ~/.asm/backups/my-skill-<timestamp>.skill

No changes were made.

Quiet output:

✓ my-skill updated in project (4 files, 2.8 KB)

Uninstall a Skill

Use the uninstall command to remove installed Claude Code skills:

# Uninstall from project scope (default: .claude/skills/)
asm uninstall my-skill

# Uninstall from personal scope (~/.claude/skills/)
asm uninstall my-skill --scope personal

# Force uninstall without confirmation
asm uninstall my-skill --force

# Preview what would be removed (dry run)
asm uninstall my-skill --dry-run

# Uninstall multiple skills
asm uninstall skill1 skill2 skill3

# Quiet mode for CI/CD
asm uninstall my-skill --quiet --force

Uninstall Options

| Option | Description | |--------|-------------| | -s, --scope <scope> | Skill location: "project" or "personal" (default: project) | | -f, --force | Remove without confirmation prompt | | -n, --dry-run | Preview what would be removed without making changes | | -q, --quiet | Quiet mode - minimal output |

Security Restrictions

For safety, the uninstall command only supports the two official Claude Code skill locations:

| Scope | Directory | Description | |-------|-----------|-------------| | project | .claude/skills/ | Skills for current project only | | personal | ~/.claude/skills/ | Skills available across all projects |

Custom paths are not allowed for uninstall operations to prevent accidental deletion of important files.

Skill Name Validation

Skill names are validated to prevent path traversal attacks:

  • Contain only lowercase letters, numbers, and hyphens
  • Cannot start or end with a hyphen
  • Cannot contain consecutive hyphens
  • No path separators (/ or \)
  • 1-64 characters long

Note: Unlike the scaffold command, uninstall does not block reserved words ("anthropic", "claude") to allow uninstalling skills created before that restriction was added.

Exit Codes

| Code | Description | |------|-------------| | 0 | Skill(s) uninstalled successfully | | 1 | Skill not found | | 2 | File system error (permission denied, etc.) | | 3 | User cancelled uninstallation | | 4 | Partial failure (some skills removed, some failed) | | 5 | Security error (invalid name, symlink escape, etc.) |

Bulk Uninstall Safety

When uninstalling 3 or more skills with --force, you will be prompted to type "yes" to confirm. This is an additional safety measure for bulk operations.

Output Examples

Normal output (single skill):

Locating skill 'my-skill' in .claude/skills/...
Found: .claude/skills/my-skill

Files to be removed:
  SKILL.md (1.2 KB)
  scripts/helper.sh (500 B)

Total: 2 files, 1.7 KB

This action cannot be undone.
Proceed with uninstall? [y/N] y

Removing files...
  ✓ scripts/helper.sh
  ✓ SKILL.md
  ✓ scripts/
  ✓ my-skill/

✓ Successfully uninstalled 'my-skill'
  Removed: 4 items (1.7 KB)

Quiet output:

✓ my-skill uninstalled from project (4 files, 1.7 KB)

Dry run output:

[DRY RUN] Would remove skill 'my-skill' from .claude/skills/

Files that would be removed:
  SKILL.md (1.2 KB)
  scripts/helper.sh (500 B)

Total: 2 files, 1.7 KB

No changes were made.

Programmatic API

AI Skills Manager can be used programmatically in Node.js applications. All CLI functionality is available as importable functions.

Installation

npm install ai-skills-manager

Quick Example

import {
  scaffold,
  validate,
  createPackage,
  install,
  update,
  uninstall,
  list,
} from 'ai-skills-manager';

// Create a new skill
const result = await scaffold({
  name: 'my-skill',
  description: 'A helpful skill',
  scope: 'project',
});
console.log(`Created skill at: ${result.path}`);

// Validate the skill
const validation = await validate(result.path);
if (validation.valid) {
  console.log('Skill is valid!');
}

API Functions

scaffold(options)

Creates a new skill directory with the standard structure.

const result = await scaffold({
  name: 'my-skill',           // Required: skill name
  description: 'Description', // Optional: skill description
  scope: 'project',           // Optional: 'project' | 'personal'
  output: './custom/path',    // Optional: custom output directory
  allowedTools: ['Bash'],     // Optional: allowed tools list
  force: false,               // Optional: overwrite existing
  template: {                 // Optional: template configuration
    templateType: 'basic',    //   'basic' | 'forked' | 'with-hooks' | 'internal'
    context: 'fork',          //   Optional: set context field
    agent: 'Explore',         //   Optional: set agent field
    userInvocable: false,     //   Optional: set user-invocable field
    includeHooks: true,       //   Optional: include hook examples
    minimal: false,           //   Optional: shorter templates without guidance
    license: 'MIT',           //   Optional: license identifier
    compatibility: 'Claude Code 2.x', // Optional: compatibility info
    metadata: { author: 'Jane' },     // Optional: key-value metadata
    argumentHint: '<query>',  //   Optional: argument hint (max 200 chars)
  },
});

// Result: { path: string, files: string[] }

validate(path)

Validates a skill at the specified path. Returns a result object (never throws for validation failures).

const result = await validate('./my-skill');

if (result.valid) {
  console.log('Valid!');
} else {
  for (const error of result.errors) {
    console.error(`[${error.code}] ${error.message}`);
  }
}

// Also check warnings
for (const warning of result.warnings) {
  console.warn(`[${warning.code}] ${warning.message}`);
}

createPackage(options)

Creates a .skill package file from a skill directory.

const result = await createPackage({
  path: './my-skill',       // Required: skill directory path
  output: './dist',         // Optional: output directory
  skipValidation: false,    // Optional: skip validation
  force: false,             // Optional: overwrite existing
  signal: controller.signal // Optional: AbortSignal for cancellation
});

// Result: { packagePath: string, size: number, fileCount: number }

install(options)

Installs a skill from a .skill package file.

const result = await install({
  file: './my-skill.skill', // Required: package file path
  scope: 'project',         // Optional: 'project' | 'personal'
  targetPath: '/custom',    // Optional: custom install path
  force: false,             // Optional: overwrite existing
  dryRun: false,            // Optional: preview only
  signal: controller.signal // Optional: AbortSignal for cancellation
});

// Result: { installedPath: string, skillName: string, version?: string, dryRun: boolean }

update(options)

Updates an installed skill from a new .skill package.

const result = await update({
  name: 'my-skill',              // Required: installed skill name
  file: './my-skill-v2.skill',   // Required: new package file
  scope: 'project',              // Optional: 'project' | 'personal'
  force: false,                  // Optional: skip confirmation
  dryRun: false,                 // Optional: preview only
  keepBackup: false,             // Optional: keep backup after success
  signal: controller.signal      // Optional: AbortSignal for cancellation
});

// Result: { updatedPath: string, previousVersion?: string, newVersion?: string, backupPath?: string, dryRun: boolean }

uninstall(options)

Uninstalls one or more skills.

const result = await uninstall({
  names: ['skill-a', 'skill-b'], // Required: skill names to remove
  scope: 'project',              // Optional: 'project' | 'personal'
  force: true,                   // Required for programmatic use
  dryRun: false,                 // Optional: preview only
  signal: controller.signal      // Optional: AbortSignal for cancellation
});

// Result: { removed: string[], notFound: string[], dryRun: boolean }

list(options)

Lists installed skills.

// List all skills
const { skills } = await list();

// List only project skills
const { skills: projectSkills } = await list({ scope: 'project' });

// List only personal skills
const { skills: personalSkills } = await list({ scope: 'personal' });

// List skills in custom directory
const { skills: customSkills } = await list({ targetPath: '/custom/path' });

// Recursive discovery for monorepos
const result = await list({ recursive: true, depth: 2 });
if (result.depthLimitReached) {
  console.log('Some directories were not scanned');
}

// Result: ListResult
// { skills: InstalledSkill[], depthLimitReached?: boolean }
// Each skill: { name: string, path: string, scope: string, version?: string, description?: string, location?: string }

Error Handling

All API functions throw typed errors that can be caught with instanceof:

import {
  install,
  AsmError,
  ValidationError,
  FileSystemError,
  PackageError,
  SecurityError,
  CancellationError,
} from 'ai-skills-manager';

try {
  await install({ file: 'skill.skill' });
} catch (e) {
  if (e instanceof ValidationError) {
    // Validation failed - check e.issues for details
    for (const issue of e.issues) {
      console.error(`[${issue.code}] ${issue.message}`);
    }
  } else if (e instanceof FileSystemError) {
    // Filesystem error - check e.path for location
    console.error(`File error at ${e.path}: ${e.message}`);
  } else if (e instanceof PackageError) {
    // Invalid or corrupted package
    console.error('Package error:', e.message);
  } else if (e instanceof SecurityError) {
    // Security violation (path traversal, invalid name)
    console.error('Security error:', e.message);
  } else if (e instanceof CancellationError) {
    // Operation was cancelled via AbortSignal
    console.log('Operation cancelled');
  } else if (e instanceof AsmError) {
    // Catch-all for any ASM error
    console.error(`ASM Error [${e.code}]: ${e.message}`);
  }
}

Cancellation with AbortSignal

Long-running operations support cancellation via AbortSignal:

const controller = new AbortController();

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
  await install({
    file: 'large-skill.skill',
    signal: controller.signal
  });
} catch (e) {
  if (e instanceof CancellationError) {
    console.log('Installation was cancelled');
  }
}

TypeScript Support

All types are exported for TypeScript users:

import type {
  // Options types
  ScaffoldOptions,
  CreatePackageOptions,
  InstallOptions,
  UpdateOptions,
  UninstallOptions,
  ListOptions,
  RecursiveListOptions,

  // Result types
  ScaffoldResult,
  ValidateResult,
  CreatePackageResult,
  InstallResult,
  UpdateResult,
  UninstallResult,
  InstalledSkill,
  ListResult,

  // Common types
  ApiScope,
  ApiListScope,
  ValidationIssue,
  ValidationWarning,
} from 'ai-skills-manager';

Development

Commands

# Install dependencies
npm install

# Build the project
npm run build

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run linting
npm run lint

# Run all quality checks
npm run quality

Project Structure

src/
  cli.ts              # CLI entry point
  index.ts            # Main library entry point
  commands/           # Command implementations (scaffold, validate, package, install)
  formatters/         # Output formatting for commands
  generators/         # File/directory generation and business logic
  templates/          # Template generation
  types/              # TypeScript type definitions
  utils/              # Shared utilities
  validators/         # Input validation

tests/
  unit/               # Unit tests (mirrors src/ structure)
    edge-cases/       # Edge case tests
    formatters/
    generators/
    templates/
    utils/
    validators/
  integration/        # Integration tests (direct API calls)
  e2e/                # End-to-end tests (invoke CLI binary directly)
  security/           # Security-focused tests
  fixtures/           # Test fixtures and sample skills

Contributing

Contributions are welcome! Please ensure:

  1. Tests pass: npm test
  2. Code is linted: npm run lint
  3. Coverage is maintained above 80%

FAQs

Q: Where are project skills stored? A: In .claude/skills/ within your project directory.

Q: Where are personal skills stored? A: In ~/.claude/skills/ in your home directory.

Q: What's the difference between project and personal scopes? A: Project skills (.claude/skills/) are specific to one project and typically checked into version control. Personal skills (~/.claude/skills/) are available across all your projects.

Q: What is a .skill package? A: A .skill file is a ZIP archive containing the skill directory structure (SKILL.md, scripts/, etc.). It's the distribution format for sharing skills.

Q: Can I share skills with my team? A: Yes. Use asm package ./my-skill to create a .skill file, then share it with your team. Recipients use asm install my-skill.skill to install it.

Q: How do I see what skills are installed? A: List the contents of .claude/skills/ (project scope) or ~/.claude/skills/ (personal scope). Each subdirectory is an installed skill.

Q: What happens if I install a skill that already exists? A: ASM will prompt for confirmation before overwriting. Use --force to skip the prompt, or --dry-run to preview what would be installed without making changes.

Q: How do I update a skill to a newer version? A: Use asm update <skill-name> <new-package.skill>. This safely replaces the installed skill with automatic backup and rollback capabilities.

Q: Where are skill backups stored? A: Backups are stored in ~/.asm/backups/. By default, they're removed after a successful update. Use --keep-backup to preserve them.

Q: What happens if an update fails? A: ASM automatically rolls back to the previous version. The backup file is preserved for manual recovery if the rollback also fails.

Q: How do I test my skill? A: After creating a skill, invoke it in Claude Code by name. Claude will discover skills in the standard locations.

Troubleshooting

Error: Invalid skill name Ensure your skill name uses only lowercase letters, numbers, and hyphens. It cannot start or end with a hyphen.

Error: Directory already exists Use the --force flag to overwrite, or choose a different name.

Error: SKILL.md not found Make sure the path points to a skill directory containing a SKILL.md file, or directly to the SKILL.md file itself.

Error: Missing YAML frontmatter Ensure your SKILL.md file starts with --- followed by YAML content and ends with another --- on its own line.

Error: Unknown frontmatter property Only these top-level keys are allowed in frontmatter: name, description, license, compatibility, allowed-tools, metadata, context, agent, hooks, user-invocable, argument-hint, keep-coding-instructions, tools, color, disable-model-invocation, version. Remove any other keys.

Command not found: asm Run npm link after building, or use node dist/cli.js directly.

Error: Invalid package file The file must be a valid .skill package created by asm package. Ensure the file hasn't been corrupted during transfer.

Error: Package extraction failed Check that the .skill file is not corrupted and you have write permissions to the target directory.

Error: Installation validation failed The skill was extracted but failed post-installation validation. ASM automatically rolls back the installation. Check the error message for specific validation failures.

Error: Permission denied Ensure you have write permissions to the target directory. For personal skills, check permissions on ~/.claude/skills/.

Error: Description too long Skill descriptions must be 1024 characters or less. Shorten your description in SKILL.md.

Error: Name contains reserved word Skill names cannot contain "anthropic" or "claude". Choose a different name.

Error: Skill not found The specified skill does not exist in the target scope. Check the skill name and use --scope personal if the skill is in your personal directory.

Error: Skill is currently being uninstalled Another uninstall operation is in progress for this skill. Wait for it to complete or check if a stale lock file exists.

Error: Security error - symlink escape The skill directory or its contents contain symlinks pointing outside the allowed scope. This is blocked for security. Review the skill directory contents and remove any symlinks pointing to external locations.

Error: SKILL.md not found (use --force) The directory exists but doesn't contain a SKILL.md file, suggesting it may not be a valid skill. Use --force if you're sure you want to remove it.

Error: Hard links detected (use --force) Files in the skill directory have hard links to other locations. Deleting them will leave the data accessible elsewhere. Use --force if this is acceptable.

Error: Update failed - rolled back to previous version The update encountered an error after backup was created. ASM automatically restored the previous version. Check the specific error message for details on what failed.

Error: Rollback failed - skill may be in inconsistent state Both the update and the automatic rollback failed. Your skill may be in an inconsistent state. The backup file has been preserved for manual recovery. Use asm install <backup-path> to restore from the backup.

Error: Package skill name mismatch The skill name in the new package does not match the installed skill. You cannot update a skill with a package containing a different skill. Use asm uninstall and asm install instead.

Error: Cannot create backup directory ASM could not create the backup directory at ~/.asm/backups/. Check permissions on your home directory. Use --no-backup to skip backup creation (not recommended).

Error: Skill is currently being updated Another update operation is in progress for this skill. Wait for it to complete or check if a stale lock file exists.

Debug Mode

For troubleshooting, you can enable debug logging by setting the ASM_DEBUG environment variable:

# Enable debug output
ASM_DEBUG=1 asm install my-skill.skill

# Alternative: use DEBUG variable
DEBUG=asm asm install my-skill.skill

Debug mode shows detailed information about internal operations, which can help diagnose issues with package installation, validation, or extraction.

License

MIT