Documentation Index
Fetch the complete documentation index at: https://mintlify.com/nearai/ironclaw/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Skills are SKILL.md files (YAML frontmatter + markdown prompt) that extend the agent’s behavior through prompt-level instructions. Unlike code-level tools (WASM/MCP), skills operate in the LLM context and are subject to trust-based authority attenuation.
Trust Model
Skills have two trust states that determine their authority:
- Trusted: User-placed skills (local/workspace) with full tool access
- Installed: Registry/external skills, restricted to read-only tools
The effective tool ceiling is determined by the lowest-trust active skill, preventing privilege escalation through skill mixing.
Trust Assignment
Skill trust is determined by location:
┌─────────────────────────────────────┬─────────┐
│ Location │ Trust │
├─────────────────────────────────────┼─────────┤
│ <workspace>/skills/ │ Trusted │
│ ~/.ironclaw/skills/ │ Trusted │
│ ~/.ironclaw/installed_skills/ │ Installed│
│ Bundled with application │ Trusted │
└─────────────────────────────────────┴─────────┘
Structure
---
name: writing-assistant
version: "1.0.0"
description: Professional writing and editing
activation:
keywords: ["write", "edit", "proofread"]
patterns: ["(?i)\\b(write|draft)\\b.*\\b(email|letter)\\b"]
tags: ["writing", "editing"]
max_context_tokens: 2000
metadata:
openclaw:
requires:
bins: ["vale"] # Required binaries
env: ["VALE_CONFIG"] # Required env vars
config: ["/etc/vale.ini"] # Required files
---
# Skill Prompt
You are a professional writing assistant. Help the user with:
- Writing and editing professional documents
- Grammar and style improvements
- Tone and clarity adjustments
Use the `vale` tool for automated style checking when available.
Frontmatter Fields
Required
name: Alphanumeric, hyphens, underscores, dots. Max 64 chars. Pattern: ^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$
Optional
version: Semantic version (default: "0.0.0")
description: Short summary
activation: When to activate this skill
metadata: OpenClaw-specific metadata (gating requirements)
Activation Criteria
activation:
keywords: ["write", "edit"] # Max 20, min 3 chars each
patterns: ["(?i)write.*email"] # Max 5 regex patterns
tags: ["writing", "email"] # Max 10, min 3 chars each
max_context_tokens: 2000 # Token budget
Limits (enforced at load time):
- Keywords: Max 20, min length 3 chars
- Patterns: Max 5 regex patterns
- Tags: Max 10, min length 3 chars
- Token budget: Max 2x declared
max_context_tokens
Gating Requirements
Skills can declare dependencies:
metadata:
openclaw:
requires:
bins: ["vale", "aspell"] # Must be on PATH
env: ["VALE_CONFIG"] # Must be set
config: ["/etc/vale.ini"] # Must exist
Skills failing gating checks are skipped during discovery.
Discovery and Loading
Directory Layouts
Two layouts are supported:
Flat Layout
Subdirectory Layout
skills/
writing-assistant/
SKILL.md
code-review/
SKILL.md
Discovery Order
Earlier locations win on name collision:
- Workspace skills (
<workspace>/skills/) - Trusted
- User skills (
~/.ironclaw/skills/) - Trusted
- Installed skills (
~/.ironclaw/installed_skills/) - Installed
Load-Time Validation
- File size: Max 64 KiB
- Name validation: Matches
^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$
- Frontmatter parsing: Valid YAML
- Activation limits: Keywords/patterns/tags within caps
- Token budget: Prompt size < 2x declared
max_context_tokens
- Gating checks: Required bins/env/config present
- Symlink rejection: No symlinks allowed
- Line ending normalization: CRLF → LF
Loading Pipeline
// Load and validate skill
let raw_bytes = tokio::fs::read(path).await?;
let raw_content = String::from_utf8(raw_bytes)?;
let normalized = normalize_line_endings(&raw_content);
let parsed = parse_skill_md(&normalized)?;
// Check gating
let result = check_requirements(&parsed.manifest.metadata).await;
if !result.passed {
return Err(GatingFailed);
}
// Compute hash
let content_hash = compute_hash(&parsed.prompt_content);
// Compile patterns
let compiled_patterns = LoadedSkill::compile_patterns(
&parsed.manifest.activation.patterns
);
// Build loaded skill
LoadedSkill {
manifest: parsed.manifest,
prompt_content: parsed.prompt_content,
trust,
source,
content_hash,
compiled_patterns,
lowercased_keywords,
lowercased_tags,
}
Activation and Selection
Scoring Algorithm
pub fn score_skill(skill: &LoadedSkill, message: &str) -> f64 {
let msg_lower = message.to_lowercase();
let mut score = 0.0;
// Exact keyword matches (weight: 10.0)
for keyword in &skill.lowercased_keywords {
if msg_lower == keyword {
score += 10.0;
} else if msg_lower.contains(keyword) {
score += 5.0; // Substring match
}
}
// Regex pattern matches (weight: 15.0)
for pattern in &skill.compiled_patterns {
if pattern.is_match(message) {
score += 15.0;
}
}
// Tag matches (weight: 2.0)
for tag in &skill.lowercased_tags {
if msg_lower.contains(tag) {
score += 2.0;
}
}
score
}
Selection Process
- Score all skills against incoming message
- Filter skills with score > 0
- Sort by score (descending)
- Take top N skills (default: 3)
- Check total token budget
- Return selected skills
When skills are active, tool access is restricted:
pub fn attenuate_tools(
tools: &[Tool],
lowest_trust: SkillTrust,
) -> Vec<Tool> {
match lowest_trust {
SkillTrust::Trusted => tools.to_vec(), // Full access
SkillTrust::Installed => {
// Only read-only tools
tools.iter()
.filter(|t| is_read_only_tool(t.name()))
.cloned()
.collect()
}
}
}
Read-only tools:
Read
Glob
Grep
WebFetch
SkillCatalog
Write tools (blocked for Installed skills):
Write
Edit
Bash
Task
- All other tools
Skill Injection
Skills are injected into the LLM context:
<skill name="writing-assistant" version="1.0.0" trust="trusted">
You are a professional writing assistant. Help the user with:
- Writing and editing professional documents
- Grammar and style improvements
- Tone and clarity adjustments
</skill>
<skill name="code-review" version="2.3.1" trust="installed">
You are a code reviewer. Analyze code for:
- Style and best practices
- Potential bugs
- Performance issues
</skill>
Security: Tag Breakout Prevention
Skill content is escaped to prevent tag injection:
pub fn escape_skill_content(content: &str) -> String {
static SKILL_TAG_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"(?i)</?[\s\x00]*skill").unwrap()
});
SKILL_TAG_RE.replace_all(content, |caps: &Captures| {
let matched = caps.get(0).unwrap().as_str();
format!("<{}", &matched[1..])
}).into_owned()
}
This prevents skills from:
- Closing their own
</skill> tag prematurely
- Injecting fake
<skill trust="trusted"> blocks
- Breaking out via mixed case, whitespace, or null bytes
Managing Skills
Via CLI
# List loaded skills
ironclaw skill list
# Show skill details
ironclaw skill show writing-assistant
# Install from file
ironclaw skill install --file ~/Downloads/skill.md
# Install from ClawHub
ironclaw skill install writing-assistant
# Remove skill
ironclaw skill remove writing-assistant
# Reload all skills
ironclaw skill reload
The agent can manage skills:
<SkillInstall>
<content>
---
name: custom-skill
description: My custom skill
---
You are a helpful assistant.
</content>
</SkillInstall>
<SkillRemove name="custom-skill" />
Programmatic API
use ironclaw::skills::SkillRegistry;
// Create registry
let mut registry = SkillRegistry::new(user_dir)
.with_workspace_dir(workspace_dir)
.with_installed_dir(installed_dir);
// Discover all skills
let loaded = registry.discover_all().await;
println!("Loaded {} skills", loaded.len());
// Install skill
let content = std::fs::read_to_string("skill.md")?;
registry.install_skill(&content).await?;
// Remove skill
registry.remove_skill("skill-name").await?;
// Find skill
if let Some(skill) = registry.find_by_name("writing-assistant") {
println!("Found: {} v{}", skill.name(), skill.version());
}
Creating Skills
Simple Skill
---
name: my-skill
description: A simple skill
activation:
keywords: ["help", "assist"]
---
You are a helpful assistant.
Advanced Skill
---
name: deployment-helper
version: "1.2.0"
description: Deployment planning and execution
activation:
keywords: ["deploy", "release", "ship"]
patterns:
- "(?i)\\bdeploy\\b.*\\b(production|staging)\\b"
- "(?i)\\brelease\\b.*\\bv?\\d+"
tags: ["devops", "deployment"]
max_context_tokens: 3000
metadata:
openclaw:
requires:
bins: ["kubectl", "helm"]
env: ["KUBECONFIG"]
---
# Deployment Helper
You are a DevOps expert specializing in Kubernetes deployments.
## Capabilities
- Plan deployment strategies
- Review manifests for issues
- Generate helm commands
- Troubleshoot deployment failures
## Guidelines
1. Always check `kubectl` version compatibility
2. Verify namespace before deploying
3. Use `--dry-run=client` for validation
4. Include rollback instructions
## Tools
Use `Bash` to run kubectl/helm commands when needed.
ClawHub Integration
Skills can be published to and installed from ClawHub:
# Search for skills
ironclaw skill search writing
# Install from ClawHub
ironclaw skill install writing-assistant
# Publish skill
ironclaw skill publish --file my-skill.md
Published skills are installed to ~/.ironclaw/installed_skills/ with Installed trust.
Best Practices
Skill Design
- Focused scope: One skill per domain (writing, code review, etc.)
- Clear activation: Use specific keywords and patterns
- Token budget: Keep prompts under 2000 tokens
- Gating: Declare binary/config dependencies
- Examples: Include example interactions in the prompt
Security
- Trust isolation: Don’t mix trusted and installed skills for sensitive tasks
- Review installed skills: Always review skill content before installing
- Workspace override: Place custom versions in workspace to override installed skills
- Symlink prohibition: Never use symlinks in skills directories
- Keyword limits: Use < 10 keywords per skill
- Pattern complexity: Avoid complex regex (max 64 KiB compiled size)
- Token budget: Larger prompts consume more context window
- Selective activation: Use precise patterns to avoid activating unnecessarily
Troubleshooting
Skill Not Loading
# Check logs
export RUST_LOG=ironclaw::skills=debug
ironclaw run
# Common issues:
# 1. Invalid YAML frontmatter
# 2. Name doesn't match pattern
# 3. File too large (> 64 KiB)
# 4. Failed gating checks
# 5. Symlink detected
Skill Not Activating
# Check activation criteria
ironclaw skill show my-skill
# Test scoring
export RUST_LOG=ironclaw::skills::selector=debug
ironclaw run
# Common issues:
# 1. Keywords too short (< 3 chars)
# 2. Pattern doesn't match message
# 3. Score too low (< threshold)
Error: Tool 'Bash' not available (installed skill active)
Cause: Installed skill is active, restricting tools to read-only.
Solution:
- Override the skill by placing a trusted version in workspace/user dir
- Remove the installed skill
- Use read-only tools only
Source Code
Key files:
src/skills/mod.rs - Module overview, types, escaping
src/skills/registry.rs - Discovery, loading, management
src/skills/parser.rs - SKILL.md parsing
src/skills/selector.rs - Activation scoring and selection
src/skills/attenuation.rs - Tool restriction based on trust
src/skills/gating.rs - Dependency checks (bins/env/config)
src/skills/catalog.rs - ClawHub integration