A TypeScript framework for managing AI agent skill packages — install, load, and bind tools for LLM function calling.
Agent SKILL framework — a skill package management, three-level progressive loading, and tool binding engine aligned with the Agent Skills Specification.
Building AI agents that use tools (function calling) often means writing glue code for every new capability. agent-skills solves this by providing a standardised skill package format and a runtime engine that handles the full lifecycle:
| Pain Point | How agent-skills Helps |
|---|---|
| Manual tool registration for each LLM | Declare tools once in manifest.json, bind to any model |
| Monolithic prompt files grow unmanageable | Three-level progressive loading (L0 → L1 → L2) keeps context minimal |
| No standard for packaging agent capabilities | Follows the open Agent Skills Specification |
| Dependency hell across languages | Built-in npm & pip installers; extensible to Cargo, Go modules, etc. |
| Security risks with zip / path inputs | Zip-slip detection, path traversal prevention, name-directory validation |
- Copilot / ChatGPT plugin authors: Package tools as skill packages and distribute them via npm or zip.
- AI agent developers: Dynamically install and bind new capabilities at runtime without redeployment.
- Enterprise teams: Maintain a curated skill registry with security-hardened installation.
- LLM application builders: Expose function-call tools to OpenAI, Claude, Gemini, or any model that supports tool use.
- Skill lifecycle management — Install / uninstall skill packages from directories,
.ziparchives, GitHub repos, or ClawHub registry - Network search & install — Search skills across GitHub and ClawHub, install by
owner/repoor slug - Three-level progressive loading — L0 (index summary) → L1 (full body) → L2 (reference documents)
- Pre-install preview — Stage to a temp directory, inspect before deciding to install or cancel
- Automatic dependency installation — Built-in npm / pip, extensible to any language via
IDependencyInstaller - manifest.json tool declarations — Parsed and exposed as function-call format tool definitions
- Script execution — Execute skill tools via
runScript()with JSON Schema validation - CLI support —
skillcommand for skill management, search, and tool execution - Security hardening — Zip-slip detection, path traversal prevention, auto-rename to match skill name
- JSON persistent registry — Tracks installed skill status
- Automatic temp cleanup — Download and preview directories are cleaned up after install
src/
├── index.ts # SkillFramework unified entry point
├── types/ # Type definitions and error classes
├── parsers/ # SKILL.md / manifest.json parsers
├── dependencies/ # Dependency installer abstraction (npm, pip, custom)
├── finder/ # Network search (GitHub + ClawHub) and download
├── registry/ # JSON file persistent registry
├── installer/ # Install / uninstall / preview staging
└── tools/ # Framework-level tool declarations (exposed to model)
npm install agent-skillsimport { SkillFramework } from 'agent-skills';
// Initialize (point to skills storage directory)
const sf = SkillFramework.init('./skills');
// Install a skill
await sf.install('./my-skill'); // From directory
await sf.install('./my-skill.zip'); // From zip
// Search for skills across GitHub and ClawHub
const results = await SkillFramework.searchSkills('stock');
// Install from network (GitHub owner/repo or ClawHub slug)
await sf.installFromNetwork('owner/repo'); // From GitHub
await sf.installFromNetwork('my-skill-slug'); // From ClawHub
// List installed skills (L0 summaries)
const { skills } = sf.listSkills();
// Load skill body (L0 → L1)
const main = sf.loadMain('my-skill');
console.log(main.body);
// Load reference document on demand (L1 → L2)
const ref = sf.loadReference('my-skill', 'references/guide.md');
// List tools declared by a skill
const tools = sf.listTools('my-skill');
// Uninstall
await sf.uninstall('my-skill');After installing the package globally (npm link or npm install -g agent-skills), you can use the skill command:
# List installed skills
skill list
# Show detailed content of one installed skill
skill show my-skill
# Search for skills (GitHub + ClawHub)
skill find stock-analysis
# Install a skill
skill install ./my-skill # From local directory
skill install ./my-skill.zip # From zip
skill install owner/repo # From GitHub
skill install my-skill-slug # From ClawHub
# Preview a skill before installing
skill preview owner/repo
# Uninstall a skill
skill uninstall my-skill
# Run a skill tool (args as JSON string)
skill run my-skill search '{"keyword":"茅台"}'
skill run my-skill kline '{"code":"600519","period":"daily","limit":60}'
# Show help
skill helpEnvironment variables:
SKILL_HOME— Override the skills storage directory (default:./skillsin package root)
SKILL_HOME=~/.skills skill listProject-level configuration:
- Set a project-specific skills directory (saved to
.skillrcin current working directory):
skill --set-skills-dir ./my-skillsAfter setting, subsequent skill commands in the same project will automatically use ./my-skills. The config is stored in .skillrc in the project root.
Execute skill tool scripts programmatically with JSON Schema validation:
// Execute a tool with validated arguments
const result = await sf.runScript({
name: 'my-skill',
toolName: 'search',
args: '{"keyword":"茅台"}' // JSON string from LLM
});
console.log(result.stdout); // Script output
console.log(result.stderr); // Error output
console.log(result.exitCode); // Exit codeThe args parameter accepts a JSON string that will be validated against the tool's manifest.json parameters schema:
- Required fields are checked
- Types are validated (string, number, boolean, etc.)
- Enum values are enforced
// Stage to temp directory, get L0 summary and tool list
const preview = sf.previewSkill('./new-skill');
console.log(preview.name, preview.tools);
// Confirm installation
await sf.installPreviewed(preview.tempDir);
// Or cancel
sf.cancelPreview(preview.tempDir);The framework includes built-in npm and pip installers. Add support for any language by implementing IDependencyInstaller:
import { SkillFramework, IDependencyInstaller } from 'agent-skills';
const cargoInstaller: IDependencyInstaller = {
type: 'cargo',
detect: (root) => fs.existsSync(path.join(root, 'Cargo.toml')),
install: async (root, timeoutMs) => {
// Run cargo build ...
return { type: 'cargo', success: true, output: '' };
},
};
const sf = SkillFramework.init('./skills', {
dependencyInstallers: [cargoInstaller],
});// Framework-level tools (skill_list, skill_install, etc.)
const frameworkTools = sf.getFrameworkToolDeclarations();
// Business tools declared by a specific skill (namespaced as skill__{name}__{tool})
const skillTools = sf.getSkillToolDeclarations('my-skill');
// All business tools across all skills
const allTools = sf.getAllSkillToolDeclarations();
// Parse namespaced business tool name
const parsed = sf.parseNamespacedToolName('skill__my-skill__search');
// -> { skillName: 'my-skill', toolName: 'search' }The framework exposes 10 tools via getFrameworkToolDeclarations() that can be injected directly into an LLM's tools/functions list:
List L0 summaries (name + description) of all installed skills.
{
"name": "skill_list",
"description": "List L0 summaries (name + description) of all installed skills",
"parameters": { "type": "object", "properties": {}, "required": [] }
}Install a skill package (directory or zip). Sensitive operation, requires confirmation.
{
"name": "skill_install",
"description": "Install a skill package (directory or zip). Sensitive operation, requires confirmation.",
"parameters": {
"type": "object",
"properties": {
"source": { "type": "string", "description": "Path to the skill package (directory or .zip file)" }
},
"required": ["source"]
}
}Uninstall an installed skill. Sensitive operation, requires confirmation.
{
"name": "skill_uninstall",
"description": "Uninstall an installed skill. Sensitive operation, requires confirmation.",
"parameters": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Skill name" }
},
"required": ["name"]
}
}Load the full SKILL.md body of a skill (L0 → L1 progressive loading).
{
"name": "skill_load_main",
"description": "Load the full SKILL.md body of a skill (L0 to L1 progressive loading)",
"parameters": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Skill name" }
},
"required": ["name"]
}
}Load a reference document from a skill by relative path (L1 → L2 progressive loading).
{
"name": "skill_load_reference",
"description": "Load a reference document from a skill by relative path (L1 to L2 progressive loading)",
"parameters": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Skill name" },
"referencePath": { "type": "string", "description": "Relative path of the reference file" }
},
"required": ["name", "referencePath"]
}
}List all tools declared by a skill (name, description, parameters schema).
{
"name": "skill_list_tools",
"description": "List all tools declared by a skill (name, description, parameters)",
"parameters": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Skill name" }
},
"required": ["name"]
}
}Execute a skill tool script. Validates args against the tool's JSON Schema and runs the script with provided parameters.
{
"name": "skill_run_script",
"description": "Execute a skill tool script. Returns stdout/stderr as JSON strings.",
"parameters": {
"type": "object",
"properties": {
"name": { "type": "string", "description": "Skill name" },
"toolName": { "type": "string", "description": "Tool name declared in manifest.json" },
"args": { "type": "string", "description": "Tool arguments as json string" }
},
"required": ["name", "toolName"]
}
}Search for skills across all sources (GitHub and ClawHub). Returns results sorted by popularity.
{
"name": "skill_search",
"description": "Search for skills across all sources (GitHub and ClawHub). Returns a list sorted by popularity.",
"parameters": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "Search query string" }
},
"required": ["query"]
}
}Install a skill from the network. Accepts GitHub owner/repo or a ClawHub slug. Sensitive operation, requires confirmation.
{
"name": "skill_install_from_network",
"description": "Install a skill from the network. Accepts GitHub owner/repo (e.g. \"owner/repo\") or a ClawHub slug (e.g. \"my-skill\"). Sensitive operation, requires confirmation.",
"parameters": {
"type": "object",
"properties": {
"source": { "type": "string", "description": "GitHub owner/repo or ClawHub slug" }
},
"required": ["source"]
}
}Preview a skill from the network before installation. Accepts GitHub owner/repo or ClawHub slug.
{
"name": "skill_preview_from_network",
"description": "Preview a skill from the network before installation. Accepts GitHub owner/repo or ClawHub slug.",
"parameters": {
"type": "object",
"properties": {
"source": { "type": "string", "description": "GitHub owner/repo or ClawHub slug" }
},
"required": ["source"]
}
}Business tools declared in a skill's manifest.json are automatically prefixed with skill__{skillName}__{toolName} to avoid cross-skill name collisions and model truncation on dotted names. Call getAllSkillToolDeclarations() to retrieve all business tool definitions at once.
| Method | Description |
|---|---|
SkillFramework.init(folder, options?) |
Static factory, initializes the framework |
install(source) |
Install a skill from directory or zip |
uninstall(name) |
Uninstall a skill |
listSkills() |
Return L0 summaries of all installed skills |
hasSkill(name) |
Check if a skill is installed |
getSkill(name) |
Get full registry entry |
loadMain(name) |
Load full skill body (L1) |
loadReference(name, path) |
Load reference document (L2) |
previewSkill(source) |
Preview a skill (stage to temp directory) |
installPreviewed(tempDir) |
Install a previously previewed skill |
cancelPreview(tempDir) |
Cancel preview and clean up |
SkillFramework.searchSkills(query) |
Search for skills across GitHub and ClawHub |
installFromNetwork(source) |
Install from GitHub owner/repo or ClawHub slug |
previewSkillFromNetwork(source) |
Preview from GitHub owner/repo or ClawHub slug |
listTools(name) |
List tools declared by a skill |
runScript(params) |
Execute a skill tool script with JSON Schema validation |
getFrameworkToolDeclarations() |
Get framework-level tool declarations |
getSkillToolDeclarations(name) |
Get namespaced tool declarations for a skill |
getAllSkillToolDeclarations() |
Get all skill tool declarations |
parseNamespacedToolName(name) |
Parse namespaced tool name into { skillName, toolName } |
{skill-name}/
├── SKILL.md # Required: YAML frontmatter + Markdown body
├── manifest.json # Optional: Tool declarations (function call schema)
├── package.json # Optional: Node.js dependencies
├── requirements.txt # Optional: Python dependencies
├── scripts/ # Optional: Executable code
├── references/ # Optional: On-demand reference documents
└── assets/ # Optional: Templates, static resources
---
name: stock-assistant
description: Query and analyze public stock market information.
license: MIT
compatibility: Requires outbound HTTPS; recommend Node 18+ for hosted scripts.
metadata:
author: acme
version: "1.0.0"
---# Install dependencies
npm install
# Build
npm run build
# Test (100% line coverage)
npm testIf you are exploring the AI agent tooling ecosystem, you might also be interested in:
- LangChain — LLM application framework with tool/agent abstractions
- Semantic Kernel — Microsoft's SDK for integrating LLMs with plugins
- AutoGPT — Autonomous AI agent experiment
- Model Context Protocol (MCP) — Open protocol for connecting AI models to external tools
agent-skills is focused specifically on skill package management and tool binding — it complements these frameworks rather than replacing them.
When starring or forking this repo, consider adding these topics to your fork for better discoverability:
ai-agent · agent-framework · llm-tools · function-calling · tool-use · skill-framework · typescript · ai · chatgpt · copilot · openai · claude · mcp · plugin-system · agent-skills