| Crates.io | turboclaude-skills |
| lib.rs | turboclaude-skills |
| version | 0.3.0 |
| created_at | 2025-11-02 05:34:48.068817+00 |
| updated_at | 2026-01-08 03:21:59.159258+00 |
| description | Skills support for TurboClaude - modular capability packages for Claude agents |
| homepage | |
| repository | https://github.com/epistates/turboclaude |
| max_upload_size | |
| id | 1912699 |
| size | 186,796 |
A Rust library for managing and executing skills in Claude agents. This crate provides the core infrastructure for loading, validating, and executing skills that follow the Agent Skills Spec v1.0.
Add to your Cargo.toml:
[dependencies]
turboclaude-skills = "0.1.0"
use turboclaude_skills::Skill;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Load skill from SKILL.md file
let skill = Skill::from_file("path/to/skill/SKILL.md").await?;
println!("Skill: {}", skill.metadata.name);
println!("Description: {}", skill.metadata.description);
// Check tool permissions
if skill.metadata.allows_tool("bash") {
println!("Skill can use bash");
}
Ok(())
}
use turboclaude_skills::SkillRegistry;
use std::path::PathBuf;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create registry with skill directories
let mut registry = SkillRegistry::builder()
.skill_dir(PathBuf::from("./skills"))
.skill_dir(PathBuf::from("/path/to/more/skills"))
.build()?;
// Discover all skills
let report = registry.discover().await?;
println!("Loaded {} skills", report.loaded);
// List all skills
let skills = registry.list().await;
for skill in skills {
println!("• {} - {}", skill.name, skill.description);
}
// Find skills by keyword
let matches = registry.find("git").await?;
// Get specific skill
let skill = registry.get("git-helper").await?;
Ok(())
}
use turboclaude_skills::Skill;
use std::time::Duration;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let skill = Skill::from_file("skills/git-helper/SKILL.md").await?;
// Execute script with arguments and timeout
let output = skill.execute_script(
"analyze_branches", // script name (without extension)
&["--days=30"], // arguments
Some(Duration::from_secs(60)) // timeout
).await?;
if output.success() {
println!("Output: {}", output.stdout);
} else if output.timed_out {
eprintln!("Script timed out");
} else {
eprintln!("Error: {}", output.stderr);
}
Ok(())
}
Skills follow this directory structure:
my-skill/
├── SKILL.md # Required: Main skill definition
├── reference/ # Optional: Additional documentation
│ ├── guide.md
│ └── advanced.md
└── scripts/ # Optional: Executable utilities
├── process.py # Python scripts
└── analyze.sh # Bash scripts
---
name: my-skill
description: What this skill does and when to use it
license: MIT
allowed-tools:
- bash
- read
- write
metadata:
author: Your Name
version: "1.0.0"
tags:
- category
- keywords
---
# Skill Title
Your skill documentation in Markdown format...
## Usage
Instructions for using this skill...
Required Fields:
name: Skill identifier (hyphen-case: lowercase + hyphens only)description: Clear description for semantic matchingOptional Fields:
license: License typeallowed-tools: Tool whitelist (empty = no tools, missing = all tools)metadata: Custom key-value pairsSkill names must be in hyphen-case:
// Valid names
"my-skill"
"git-helper"
"pdf-processor"
// Invalid names
"MySkill" // uppercase
"my_skill" // underscores
"-skill" // leading hyphen
"skill-" // trailing hyphen
See the examples/ directory for complete examples:
../../examples/skills_demo.rs for a comprehensive demonstrationThe skills/ directory contains example skills:
Skill: Main skill object with metadata, content, and resourcesSkillMetadata: Parsed YAML frontmatterSkillRegistry: Discovery and management systemReference: Additional documentation filesScriptOutput: Script execution results// Load from file
let skill = Skill::from_file(path).await?;
// Access metadata
let name = &skill.metadata.name;
let description = &skill.metadata.description;
// Check tool permissions
skill.metadata.allows_tool("bash");
// Get skill context (full SKILL.md content)
let context = skill.context();
// Lazy load references
let references = skill.references().await?;
// Lazy load scripts
let scripts = skill.scripts().await?;
// Execute script
let output = skill.execute_script(name, args, timeout).await?;
// Build registry
let registry = SkillRegistry::builder()
.skill_dir(path)
.build()?;
// Discover skills
let report = registry.discover().await?;
// List all skills
let skills = registry.list().await;
// Find by keyword
let matches = registry.find("query").await?;
// Get specific skill
let skill = registry.get("skill-name").await?;
The library validates:
name fieldSupports Python (.py) and Bash (.sh) scripts:
// Automatic executor selection based on extension
let output = skill.execute_script("process", &[], None).await?;
// Check results
if output.success() {
// exit_code == 0 && !timed_out
}
ScriptOutput fields:
exit_code: Process exit codestdout: Standard outputstderr: Standard errorduration: Execution timetimed_out: Whether timeout occurredAll errors use the SkillError enum:
use turboclaude_skills::SkillError;
match skill.execute_script("test", &[], None).await {
Ok(output) => println!("{}", output.stdout),
Err(SkillError::ScriptNotFound(name)) => {
eprintln!("Script {} not found", name);
}
Err(SkillError::ScriptTimeout) => {
eprintln!("Script timed out");
}
Err(e) => eprintln!("Error: {}", e),
}
Run tests:
# All tests
cargo test
# With output
cargo test -- --nocapture
# Specific test
cargo test test_skill_loading
Run examples:
# Basic example
cargo run --example basic
# With example skills
cd crates/turboclaude-skills
cargo run --example basic
Generate and view API documentation:
cargo doc --open
All types are thread-safe:
SkillRegistry uses Arc<RwLock<SkillRegistryInner>>Arc internally)This library implements the Agent Skills Spec v1.0:
turboclaude: Claude API client with Skills API supportturboclaudeagent: Agent framework with skill integrationSee LICENSE file in the repository root.
Contributions welcome! Please see CONTRIBUTING.md for guidelines.