This document describes all skills available in the .opencode system.
Skills are reusable knowledge modules loaded on-demand via the skill() tool. Each skill contains domain-specific patterns, examples, and best practices.
CRITICAL: Skills must be explicitly invoked. There is no auto-loading.
skill(name="python-fastapi")Each skill is located in .opencode/skills/<name>/SKILL.md:
skills/
└── python-fastapi/
├── SKILL.md # Skill definition
└── references/ # Optional additional content
└── dependency-injection-patterns.md
---
name: python-fastapi # Required: must match folder name
description: "Description here" # Required: 1-1024 characters
license: MIT # Optional
compatibility: opencode # Optional
metadata: # Optional: string-to-string map
audience: developers
workflow: api
---
# Skill Content
...| Skill | Triggers | When to Use |
|---|---|---|
| python-fundamentals | *.py, python, dataclass, async |
Core Python patterns |
| python-fastapi | fastapi, pydantic, endpoint, api |
API development |
| python-backend | sqlalchemy, database, orm, migration |
Database work |
| python-testing-general | pytest, test, mock, fixture |
Testing patterns |
| python-testing-deep | hypothesis, property-based, snapshot |
Advanced testing |
| python-asyncio | async, await, asyncio, concurrent |
Async programming |
| python-type-hints | typing, mypy, pyright, Protocol |
Type system |
| python-package-management | uv, pip, package, pyproject |
Dependencies |
| python-tooling | docker, ci, cd, github, profile |
DevOps tooling |
| python-fundamentals-313 | 3.13, jit, free-threading |
Python 3.13+ features |
Location: .opencode/skills/python-fundamentals/SKILL.md
*.pyfilespython,dataclass,asynctype hint
- Writing new Python code
- Applying type annotations
- Working with dataclasses, enums, or Pydantic
- Implementing error handling patterns
- Using async/await
- Handling file I/O with pathlib
- Following naming conventions
# Built-in generics
items: list[str]
mapping: dict[str, int]
optional: str | None
# Union syntax
def fetch(url: str) -> dict | None:
...
# Type parameter syntax (3.12+)
def first[T](items: list[T]) -> T:
return items[0]from dataclasses import dataclass, field
@dataclass(slots=True)
class User:
name: str
email: str
tags: list[str] = field(default_factory=list)try:
config = parse_config(path)
except FileNotFoundError:
config = default_config()
except json.JSONDecodeError as e:
raise ConfigError(f"Invalid JSON in {path}") from e# Concurrent execution
results = await asyncio.gather(
fetch("url1"),
fetch("url2"),
)
# Task groups (3.11+)
async with asyncio.TaskGroup() as tg:
for item in items:
tg.create_task(process_item(item))def process_command(command: dict) -> str:
match command:
case {"action": "create", "name": str(name)}:
return f"Creating {name}"
case {"action": "delete", "id": int(id_)}:
return f"Deleting item {id_}"
case _:
return "Unknown command"Location: .opencode/skills/python-fastapi/SKILL.md
fastapi,pydantic,uvicornendpoint,api,router
- Setting up FastAPI project structure
- Creating Pydantic schemas with validation
- Implementing dependency injection
- JWT authentication setup
- Docker deployment configuration
- Production deployment
src/
├── app/
│ ├── main.py # Application factory
│ ├── config.py # Settings management
│ ├── api/v1/
│ │ ├── router.py # API router
│ │ └── endpoints/ # Endpoint handlers
│ ├── models/ # SQLAlchemy models
│ ├── schemas/ # Pydantic schemas
│ └── services/ # Business logic
# Base schema with shared fields
class UserBase(BaseModel):
email: EmailStr
full_name: str | None = None
# Input schema for creation
class UserCreate(UserBase):
password: str = Field(min_length=8)
# Input schema for updates
class UserUpdate(BaseModel):
email: EmailStr | None = None
full_name: str | None = None
# Output schema (what API returns)
class UserResponse(UserBase):
id: int
is_active: bool
created_at: datetime
model_config = {"from_attributes": True}from typing import Annotated
from fastapi import Depends
# Type aliases for cleaner signatures
CurrentUser = Annotated[User, Depends(get_current_active_user)]
DbSession = Annotated[AsyncSession, Depends(get_db)]
@router.get("/me", response_model=UserResponse)
async def read_current_user(current_user: CurrentUser):
return current_userfrom pydantic_settings import BaseSettings
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env")
app_name: str = "My API"
database_url: str
secret_key: str# Gunicorn with Uvicorn workers
gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorkerreferences/dependency-injection-patterns.md- Advanced DI patterns
Location: .opencode/skills/python-backend/SKILL.md
sqlalchemy,database,ormmigration,alembic,model
- Creating SQLAlchemy models
- Working with async sessions
- Database migrations with Alembic
- Setting up database connections
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/db",
echo=False,
pool_size=5,
max_overflow=10,
)
async_session = sessionmaker(
engine, class_=AsyncSession, expire_on_commit=False
)from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
email = Column(String, unique=True, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)from sqlalchemy import select
async def get_user(db: AsyncSession, user_id: int) -> User | None:
result = await db.execute(
select(User).where(User.id == user_id)
)
return result.scalar_one_or_none()# Create migration
alembic revision --autogenerate -m "Add user table"
# Apply migrations
alembic upgrade headLocation: .opencode/skills/python-testing-general/SKILL.md
pytest,test,mockfixture,coverage
- Writing unit tests
- Creating test fixtures
- Mocking dependencies
- Setting up test coverage
# tests/auth/test_service.py
import pytest
from unittest.mock import Mock
class TestUserService:
def test_create_user_success(self):
# Arrange
user_data = {"email": "test@example.com"}
mock_db = Mock()
# Act
result = create_user(user_data, mock_db)
# Assert
assert result.email == "test@example.com"# conftest.py
@pytest.fixture
def mock_db():
db = Mock()
yield db
db.reset_mock()
@pytest.fixture
def sample_user():
return User(id=1, email="test@example.com")@pytest.mark.parametrize("input,expected", [
("valid@email.com", True),
("invalid", False),
("", False),
])
def test_validate_email(input, expected):
assert validate_email(input) == expected@pytest.mark.asyncio
async def test_async_fetch():
result = await fetch_data("https://api.example.com")
assert result is not NoneLocation: .opencode/skills/python-testing-deep/SKILL.md
hypothesis,property-basedsnapshot,mutation
- Property-based testing
- Snapshot testing
- Advanced test scenarios
- Comprehensive coverage
from hypothesis import given, strategies as st
@given(st.text(), st.integers())
def test_process_never_crashes(text, number):
result = process(text, number)
assert result is not Nonedef test_api_response(snapshot):
response = client.get("/api/users")
snapshot.assert_match(response.json())Location: .opencode/skills/python-asyncio/SKILL.md
async,await,asyncioconcurrent,gather,TaskGroup
- Writing async code
- Concurrent execution
- Rate limiting with semaphores
- Timeout handling
# Sequential (slow)
result1 = await fetch("url1")
result2 = await fetch("url2")
# Concurrent (fast)
results = await asyncio.gather(
fetch("url1"),
fetch("url2"),
)async def process_all(items: list[Item]):
async with asyncio.TaskGroup() as tg:
for item in items:
tg.create_task(process_item(item))async def fetch_all(urls: list[str], max_concurrent: int = 10):
semaphore = asyncio.Semaphore(max_concurrent)
async def fetch_one(url: str):
async with semaphore:
return await fetch(url)
return await asyncio.gather(*[fetch_one(url) for url in urls])async def fetch_with_timeout(url: str, timeout: float = 5.0):
async with asyncio.timeout(timeout):
return await fetch(url)Location: .opencode/skills/python-type-hints/SKILL.md
typing,mypy,pyrightProtocol,TypedDict
- Adding type hints
- Using Protocol for structural typing
- Creating TypedDict schemas
- Configuring mypy/pyright
from typing import Protocol
class Readable(Protocol):
def read(self) -> str: ...
def process(source: Readable) -> None:
content = source.read()from typing import TypedDict, NotRequired
class UserData(TypedDict):
name: str
email: str
age: NotRequired[int]type Point = tuple[float, float]
type Vector[T] = list[T]
class Stack[T]:
def __init__(self) -> None:
self._items: list[T] = []references/advanced-typing-patterns.md- Advanced patterns
Location: .opencode/skills/python-package-management/SKILL.md
uv,pip,packagepyproject,dependency,venv
- Managing dependencies with UV
- Configuring pyproject.toml
- Setting up virtual environments
- Publishing packages
uv sync # Install dependencies
uv add fastapi # Add dependency
uv add --dev pytest # Add dev dependency
uv remove package # Remove dependency
uv run command # Run in virtual environment[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.115.0",
"pydantic>=2.7.0",
]
[project.optional-dependencies]
dev = ["pytest", "mypy", "ruff"]Location: .opencode/skills/python-tooling/SKILL.md
docker,ci,cdgithub,profile,optimize
- Docker configuration
- CI/CD pipeline setup
- Performance profiling
- Build optimization
FROM python:3.12-slim
WORKDIR /app
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
COPY src/ ./src/
CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0"]# .github/workflows/test.yml
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: uv sync
- run: uv run pytest
- run: uv run mypy src/Location: .opencode/skills/python-fundamentals-313/SKILL.md
3.13,free-threading,jitpattern matching,no-gil
- Using Python 3.13+ specific features
- Free-threaded mode (no-GIL)
- JIT compiler
- New pattern matching features
# python3.13t - Free-threaded build
import threading
def cpu_bound_task(n):
total = 0
for i in range(n):
total += i * i
return total
# True parallelism with free-threading
threads = []
for _ in range(4):
t = threading.Thread(target=cpu_bound_task, args=(10_000_000,))
threads.append(t)
t.start()# Enable JIT
PYTHON_JIT=1 python3.13 script.py
# Or use -X flag
python3.13 -X jit script.pyControl which skills agents can access in opencode.json:
{
"permission": {
"skill": {
"*": "allow",
"internal-*": "deny",
"experimental-*": "ask"
}
}
}| Permission | Behavior |
|---|---|
allow |
Skill loads immediately |
deny |
Skill hidden from agent |
ask |
User prompted before loading |
If a skill doesn't appear:
- Verify
SKILL.mdis spelled in all caps - Check frontmatter includes
nameanddescription - Ensure skill names are unique
- Check permissions - skills with
denyare hidden
- Overview - System introduction
- Architecture - Component relationships
- Agents - python-expert agent details
- Subagents - All subagent workflows
- Workflow - Development patterns
- Configuration - Customization guide