Skip to main content

faskill

Fork of maxvaega/skillkit
Extensively refactored with bug fixes, security hardening, and new abstractions.
Maintained by AmritaConstant.

Python License PyPI GitHub release

faskill is a Python library that brings Anthropic's Agent Skills to any LLM-powered agent. It discovers, loads, and invokes packaged expertise — defined in standard SKILL.md files — with progressive disclosure for token efficiency.

Features

  • SKILL.md compatible — works with any existing skill, drop-in ready
  • Framework-agnostic — use standalone, with LangChain, or with AmritaCore agents
  • Model-agnostic — works with any LLM
  • Multi-source discovery — custom directories, plugins with priority-based conflict resolution
  • Progressive disclosure — metadata-first loading, 80% memory reduction, LRU caching; scripts loaded on demand
  • Script execution — Python, Shell, JavaScript, Ruby, Perl with security validation and timeout enforcement
  • Pluggable runner — Runner abstraction with HostRunner default; swap in Docker, Firecracker, etc.
  • Plugin ecosystem — supports plugin manifests (.claude-plugin/plugin.json) with namespaced skill access
  • Comprehensive error hierarchy — 20+ typed exceptions for precise error handling

Notable Improvements Over Upstream (skillkit)

This fork contains significant refactoring and bug fixes beyond the original:

Area Improvement
Bug fix PRIORITY_CUSTOM no longer decrements — ≥5 sources won't trigger ValueError: Priority must be positive
Bug fix create_langchain_tools() no longer eagerly loads all scripts — respects progressive disclosure (L1→L2→L3)
New create_amrita_tools(mode="progressive") — a two-tool pool (skill_open / skill_read) instead of one tool per skill
New InvalidSkillNameError — names with spaces are rejected (bypass with NO_FAIL_ON_SPACE=1)
New Runner abstraction — HostRunner (default, warns once about bare host security) with swappable backends
New ArgumentSerializationError / ArgumentSizeError / ToolIDValidationError — fine-grained script errors
New ConfigurationError / AsyncStateError / PluginError — better error reporting
Refactor SkillManager → SkillContext with create_context() factory; modular architecture (discovery, parser, registry, invoker, processors, scripts, runner)
Refactor Complete test suite (425 tests), 70%+ coverage, comprehensive fixtures

Installation

pip install faskill              # Core library
pip install faskill[langchain]   # With LangChain integration
pip install faskill[all]         # All extras

Quick Start

1. Create a skill

.claude/skills/code-reviewer/SKILL.md
---
name: code-reviewer
description: Review code for best practices and potential issues
allowed-tools: Read, Grep
---

# Code Reviewer

Analyze the provided code for:

- Best practices violations
- Potential bugs
- Security vulnerabilities

Use $ARGUMENTS to access user input.

2. Use standalone

from faskill import create_context

ctx = create_context(skill_dirs=["./.claude/skills"])
ctx.discover()

# List available skills
for skill in ctx.list_skills():
    print(f"{skill.name}: {skill.description}")

# Invoke a skill
result = ctx.invoke_skill("code-reviewer", "Review function calculate_total()")
print(result)

3. Use with LangChain

from faskill import create_context
from faskill.integrations.langchain import create_langchain_tools
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI

ctx = create_context(skill_dirs=["./.claude/skills"])
ctx.discover()

tools = create_langchain_tools(ctx)

llm = ChatOpenAI(model="gpt-4o")
agent = create_agent(llm, tools, system_prompt="You are a helpful assistant.")
result = agent.invoke({"messages": [{"role": "user", "content": "Review my code"}]})

SKILL.md Format

---
name: my-skill # Required: unique identifier
description: ... # Required: human-readable description
allowed-tools: Bash, Read # Optional: tool allowlist
version: "1.0" # Optional: semantic version
---
# Skill content with $ARGUMENTS placeholder
  • Argument substitution: $ARGUMENTS → user input; $$ARGUMENTS → literal $ARGUMENTS
  • No placeholder: arguments are appended to the end

Script Execution

Skills can bundle executable scripts for deterministic operations:

my-skill/
├── SKILL.md
└── scripts/
    └── extract.py
result = ctx.execute_skill_script(
    skill_name="my-skill",
    script_name="extract",
    arguments={"file": "doc.pdf", "pages": "all"},
    timeout=30,
)

if result.success:
    print(result.stdout)
else:
    print(f"Error ({result.exit_code}): {result.stderr}")

Supported types: .py, .sh, .js, .rb, .pl, .bat, .cmd, .ps1.

Script runner (pluggable)

ScriptExecutor accepts a runner parameter — swap in sandboxed backends:

from faskill.core.scripts import ScriptExecutor
from faskill.core.runner import HostRunner  # default (warns once about security)

# Default: bare host
executor = ScriptExecutor(runner=HostRunner())

# Future: Docker, Firecracker, gVisor...
# executor = ScriptExecutor(runner=DockerRunner(image="python:3.12"))

API Reference

create_context()

from faskill import create_context

ctx = create_context(
    skill_dirs=["./skills", "./plugins"],  # Directory list; directories with
    # .claude-plugin/plugin.json are
    # detected as plugins
    default_script_timeout=30,  # seconds (1-600)
    max_cache_size=100,  # LRU cache entries
)

SkillContext

Method Description
discover() Sync skill discovery
adiscover() Async skill discovery
list_skills() List all discovered skill metadata
list_skills(include_qualified=True) List names including plugin:skill
get_skill(name) Get metadata by name; raises SkillNotFoundError
invoke_skill(name, args) Sync invocation with caching
ainvoke_skill(name, args) Async invocation with caching
execute_skill_script(...) Execute a bundled script
get_cache_stats() Cache hit/miss statistics
clear_cache(name?) Clear cache entries
add_source(path) Add a skill directory after construction

Key types

Type Description
SkillMetadata Name, description, path, allowed tools, priority
Skill Full skill: metadata + content + scripts
SkillSource Source directory with type and priority
ScriptMetadata Detected script name, path, language, description
ScriptExecutionResult exit_code, stdout, stderr, execution_time_ms, etc.
CacheStats size, max_size, hits, misses, hit_rate
Runner Abstract base for script execution backends
HostRunner Default runner — bare host subprocess (warns once)

Exception hierarchy

SkillsUseError
├── SkillParsingError
│   ├── InvalidYAMLError
│   ├── MissingRequiredFieldError
│   ├── InvalidSkillNameError          # name contains spaces (bypass: NO_FAIL_ON_SPACE=1)
│   └── InvalidFrontmatterError
├── SkillNotFoundError
├── SkillInvocationError
│   ├── ArgumentProcessingError
│   ├── ArgumentSerializationError
│   ├── ArgumentSizeError
│   └── ContentLoadError
├── ConfigurationError
├── AsyncStateError
├── PluginError
│   ├── ManifestNotFoundError
│   ├── ManifestParseError
│   └── ManifestValidationError
├── ScriptError
│   ├── InterpreterNotFoundError
│   ├── ScriptNotFoundError
│   ├── ScriptPermissionError
│   ├── ArgumentSerializationError
│   ├── ArgumentSizeError
│   └── ToolIDValidationError
├── SkillSecurityError
│   ├── SuspiciousInputError
│   ├── SizeLimitExceededError
│   └── PathSecurityError

Examples

See examples/ directory:

File What it demonstrates
basic_usage.py Sync and async standalone usage
async_usage.py Async usage with FastAPI
langchain_agent.py LangChain agent integration
amrita_agent.py AmritaCore agent integration
multi_source.py Multi-source discovery and conflict resolution
file_references.py Secure file path resolution
caching_demo.py Cache performance demonstration
script_execution.py Script execution with error handling

Documentation


Where to find skills


Contributing

  1. Fork → branch → make changes → add tests
  2. Ensure uv run pytest passes (≥70% coverage)
  3. Ensure uv run ruff check src/ and uv run pyright src/ pass
  4. Submit a pull request

See CONTRIBUTING.md for detailed guidelines.


License

MIT — see LICENSE for details.

Metadata

Release files for faskill 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for faskill 0.4.0
File Size Uploaded Provenance Actions
faskill-0.4.0.tar.gz 131.7 kB Without provenance Details for faskill-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for faskill 0.4.0
File Interpreter ABI Platform Actions
faskill-0.4.0-py3-none-any.whl Python 3 none any Details for faskill-0.4.0-py3-none-any.whl

Total release size: 201.9 kB

Release files / faskill-0.4.0.tar.gz

Download URL faskill-0.4.0.tar.gz
Size 131.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c34a3d172e798ba98251595a4f7800066a42c36a2befac78515702d379b4e375
BLAKE2b-256 checksum
How to use checksums
dbdd82d6fa2284d8b3849affdfe697dd0ef432031a4f442a83ecaa01c7050843
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / faskill-0.4.0-py3-none-any.whl

Download URL faskill-0.4.0-py3-none-any.whl
Size 70.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4305662d6f157265570cada2ff4d96d48d3fbe86df68ea9c99023514878815dc
BLAKE2b-256 checksum
How to use checksums
1a793b24e1461d67288a05772d148144fd89e77206a9a7b43667a733d3b1fee6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for faskill 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page