AI Agent Skill Format Specification¶
An AI agent skill is a self-contained directory that teaches an AI coding assistant how to use a specific tool, API, or workflow. The assistant discovers installed skills at startup and loads their instructions alongside its built-in knowledge.
This document specifies the portable skill format used by Claude Code, Codex CLI, Gemini CLI, OpenClaw, and any agent platform that adopts this convention.
Overview¶
Skills bridge the gap between what an AI assistant knows by default and what it needs to know to operate your specific tool. A skill for a CLI tool might teach the agent which commands exist, which flags are required, and how to chain commands together for common workflows. A skill for an API might explain authentication, rate limits, and error handling patterns.
Skills are plain text — a directory of Markdown files — so they are portable, diff-friendly, and trivial to distribute alongside a binary or publish to a package registry.
Ecosystem Support¶
The following platforms read skills from skills/ subdirectories within their config directories:
| Platform | Config Directory |
|---|---|
| Claude Code | ~/.claude/ |
| Codex CLI | ~/.codex/ |
| Gemini CLI | ~/.gemini/ |
| OpenClaw | ~/.openclaw/ |
| Cross-tool standard | ~/.agents/ |
File Structure¶
my-skill/
SKILL.md # Required: frontmatter metadata + instructions
references/ # Optional: topic-specific deep dives
scripts/ # Optional: executable helper scripts
assets/ # Optional: templates, data files, schemas
The only required file is SKILL.md. Everything else is optional and referenced from the main file as needed.
The directory name is the skill name. A skill installed at ~/.claude/skills/bullpen-cli/ has name bullpen-cli.
SKILL.md Format¶
SKILL.md is a Markdown file with YAML frontmatter. The frontmatter provides metadata for discovery and version management. The Markdown body contains the instructions the agent reads.
Frontmatter¶
The file must begin with a YAML frontmatter block delimited by ---:
---
name: my-skill
description: "When and why to use this skill."
version: "1.0.0"
license: MIT
metadata:
author: Your Name or Organization
tags: [tag1, tag2, tag3]
docs-url: docs.example.com
allowed-tools: [Bash, Read]
---
Required Fields¶
| Field | Type | Description |
|---|---|---|
name |
string | Unique identifier. Should match the directory name. The directory name is the authoritative identifier; this field is used for display and verification. |
description |
string | One or two sentences describing when the agent should activate this skill. This is the primary signal the agent uses to decide whether to consult the skill for a given user request. |
Optional Fields¶
| Field | Type | Description |
|---|---|---|
version |
string (semver) | Skill version for update tracking. Use "0.0.0" as a placeholder that the installer stamps at install time. |
license |
string (SPDX) | License identifier, e.g. MIT, Apache-2.0. |
metadata.author |
string | Human-readable author or organization name. |
metadata.tags |
string[] | Discovery tags for search and categorization. |
metadata.docs-url |
string | URL to full documentation (without https:// prefix is fine). |
allowed-tools |
string[] | Platform-specific tool allowlist (Claude Code). Restricts which tools the agent may invoke when operating under this skill. Omit to allow all tools. |
Writing a Good description¶
The description field is critical — it is what the agent reads to decide whether a skill is relevant to the current task. Write it as an explicit activation condition:
# Good: specific, scannable activation conditions
description: "Use the Bullpen CLI to trade Polymarket prediction markets,
discover events, manage portfolios, and automate trading workflows.
Use when the user asks about prediction markets, Polymarket, buying/selling
shares, checking positions, market discovery, orderbooks, or scripting
prediction market operations."
# Poor: vague, no activation signal
description: "Bullpen CLI skill for trading."
Markdown Body¶
The body after the frontmatter --- is free-form Markdown. The sections below are recommended but not required.
Recommended Sections¶
1. Instructions / Decision Tree
A routing section that tells the agent where to go for each type of user intent. For simple skills, this can be a short paragraph. For complex tools with many commands, use a table or decision tree:
## Instructions
Route to the right reference based on the user's intent:
| User Intent | Reference |
|-------------|-----------|
| Install or authenticate | `references/getting-started.md` |
| Execute a trade | `references/trading.md` |
| Check portfolio | `references/portfolio-and-orders.md` |
2. Quick Command Map
An intent-to-command table for common operations the agent can use without loading full references:
## Quick Command Map
| Intent | Command |
|--------|---------|
| Log in | `mytool login` |
| Check status | `mytool status` |
| List items | `mytool list` |
3. Examples
Multi-step workflows showing how commands chain together. Examples are especially useful for non-obvious sequences:
## Examples
### Research and Trade
User says: "Buy Yes shares on the Bitcoin market"
1. Search: `bullpen polymarket search "bitcoin"`
2. Check price: `bullpen polymarket price <SLUG>`
3. Buy: `bullpen polymarket buy <SLUG> Yes 10 --yes`
4. Verify: `bullpen polymarket positions`
4. Troubleshooting
An error-to-fix table for the most common failure modes:
## Troubleshooting
| Error | Fix |
|-------|-----|
| "Not authenticated" | Run `mytool login` |
| "Rate limited" | Wait 30 seconds; reduce request frequency in scripts |
| Command not found | Run `mytool upgrade` to get the latest version |
5. Resources
Links to documentation, issue tracker, and support channels.
Install Locations¶
Skills are installed as subdirectories under a skills/ folder within a platform's config directory. Each platform looks in its own directory, and most platforms also support a cross-tool standard path under ~/.agents/.
Personal Skills (User-Scoped)¶
Personal skills apply to all projects for that user.
| Platform | Path |
|---|---|
| Claude Code | ~/.claude/skills/{name}/ |
| Codex CLI | ~/.codex/skills/{name}/ |
| Gemini CLI | ~/.gemini/skills/{name}/ |
| OpenClaw | ~/.openclaw/skills/{name}/ |
| Cross-tool standard | ~/.agents/skills/{name}/ |
The cross-tool path (~/.agents/skills/) is a platform-neutral location that non-Claude platforms read in addition to their own directories. Installing to this path makes a skill available across all tools without platform-specific installs.
Sibling skills: When a skill is distributed with companion skills, the installer may write sibling directories automatically. For example,
bullpen skill installwrites bothbullpen-cli/andbullpen-bracket/under the same skills directory in a single command.
Project Skills (Repository-Scoped)¶
Project skills are checked in to a repository and apply only when the agent is working within that project.
| Platform | Path |
|---|---|
| Claude Code | .claude/skills/{name}/ (in repo root) |
| Other platforms | .agents/skills/{name}/ (in repo root) |
Both project and personal skills are loaded. If both exist for the same name, behavior depends on the platform. The directory name is the authoritative identifier.
Discovery Algorithm¶
At startup, each platform scans its skills/ directories for subdirectories containing SKILL.md:
for each skills_dir in [personal_dir, project_dir, cross_tool_dir]:
for each entry in skills_dir:
if entry is a directory and entry/SKILL.md exists:
load skill with name = entry.directory_name
The directory name is the authoritative skill name — not the name field in the frontmatter — because the directory name is what the file system enforces as unique. The name field in frontmatter should match the directory name and is used for display and version reporting.
Parsing Contract¶
Platforms parse the SKILL.md frontmatter without a full YAML library, using simple line-by-line extraction. This keeps the parser dependency-free and guarantees that all platforms parse identically.
Algorithm¶
state = BEFORE_FRONTMATTER
for each line in file:
if line.trim() == "---":
if state == BEFORE_FRONTMATTER:
state = IN_FRONTMATTER
elif state == IN_FRONTMATTER:
state = AFTER_FRONTMATTER (stop parsing)
continue
if state == IN_FRONTMATTER:
# Split on first colon
if line contains ":":
key, value = line.split(":", maxsplit=1)
key = key.trim()
value = value.trim().strip_quotes()
store key -> value
Rules¶
- Only top-level keys are extracted by default. Nested keys (e.g.
metadata.author) require additional logic to track nesting depth. - Values are stripped of surrounding double quotes.
- Array values (e.g.
tags: [a, b, c]) are parsed by stripping[and]and splitting on,. - Lines that do not contain
:are ignored. - The frontmatter ends at the second
---line.
Example (Rust)¶
fn parse_frontmatter_field(content: &str, field: &str) -> Option<String> {
let mut in_frontmatter = false;
for line in content.lines() {
if line.trim() == "---" {
if in_frontmatter { break; }
in_frontmatter = true;
continue;
}
if in_frontmatter {
let trimmed = line.trim();
if let Some(rest) = trimmed.strip_prefix(field) {
if let Some(value) = rest.strip_prefix(':') {
return Some(value.trim().trim_matches('"').to_string());
}
}
}
}
None
}
This approach is intentionally minimal. For skills that need richer metadata, place additional structured data in a separate file under assets/ and parse it independently.
Version Management¶
Skills use semantic versioning (major.minor.patch). The version field enables tools that install skills to detect when an installed skill is outdated relative to the version shipped with the latest binary.
Version Placement¶
The version field can appear in two locations within the frontmatter:
- Top-level (preferred for new skills):
- Under
metadata(legacy, supported by Bullpen CLI):
Both placements are supported. Bullpen's stamp_version() implementation searches for version: at any indentation level within the frontmatter, so it handles both top-level and nested metadata.version fields. New skills should prefer the top-level placement for consistency with the rest of the spec.
Placeholder Stamping¶
Skills distributed with a CLI tool should use "0.0.0" as a placeholder version in the source file:
At install time, the CLI replaces this placeholder with the actual binary version:
fn stamp_version(content: &str, version: &str) -> String {
// Replace `version: "0.0.0"` with `version: "1.2.3"` in frontmatter
// Searches for `version:` at any indentation level
// ...
}
This ensures the installed skill version always matches the CLI version without requiring the skill file to be manually updated on every release.
Checking for Updates¶
When listing installed skills, a tool can compare the installed version field against the current binary version to report outdated skills:
bullpen skill list
bullpen-cli v0.1.10 (outdated, latest: 0.1.17) [Claude Code personal]
bullpen-bracket v0.1.17 (up to date) [Claude Code personal]
Examples¶
Minimal Skill¶
The smallest valid skill — only the two required fields:
---
name: my-tool
description: "Use my-tool CLI to manage widgets and automations. Use when the user asks about widgets, querying the widget catalog, or running widget automations."
---
# My Tool
Run `my-tool --help` to see available commands.
Full-Featured Skill¶
A skill using all available fields and the recommended section structure:
---
name: bullpen-cli
description: "Use the Bullpen CLI to trade Polymarket prediction markets, discover events, manage portfolios, and automate trading workflows. Use when the user asks about prediction markets, Polymarket, buying/selling shares, checking positions, market discovery, orderbooks, tracking traders, or scripting prediction market operations."
version: "0.0.0"
license: MIT
metadata:
author: BullpenFi
tags: [prediction-markets, polymarket, trading, cli, portfolio]
docs-url: cli.bullpen.fi
allowed-tools: [Bash, Read]
---
# Bullpen CLI Skill
## Instructions
Route to the right reference based on the user's intent:
| User Intent | Reference |
|-------------|-----------|
| Install or authenticate | `references/getting-started.md` |
| Discover and research markets | `references/discovery-and-research.md` |
| Execute trades | `references/trading.md` |
| Manage portfolio and orders | `references/portfolio-and-orders.md` |
## Quick Command Map
| Intent | Command |
|--------|---------|
| Log in | `bullpen login` |
| Check status | `bullpen status` |
| Discover markets | `bullpen polymarket discover` |
| Buy shares | `bullpen polymarket buy <SLUG> <OUTCOME> <USD>` |
## Troubleshooting
| Error | Fix |
|-------|-----|
| "Not authenticated" | Run `bullpen login` |
| "Market not found" | Use `bullpen polymarket search` to find the correct slug |
## Resources
- Docs: [cli.bullpen.fi](https://cli.bullpen.fi)
- Issues: [github.com/BullpenFi/bullpen-cli-releases/issues](https://github.com/BullpenFi/bullpen-cli-releases/issues)
Skill with References Directory¶
For large tools with many commands, split the instructions across topic-specific reference files and load them on demand:
bullpen-cli/
SKILL.md # Router: identifies user intent and points to references
references/
getting-started.md # Install, auth, first-time setup
trading.md # Buy, sell, limit orders, CTF split/merge
portfolio-and-orders.md # Positions, open orders, watchlist
discovery-and-research.md # Discover, search, event details, price history
scripting-and-automation.md # JSON output, jq pipelines, batch workflows
The main SKILL.md acts as a router. It reads the user intent and directs the agent to load the appropriate reference file before acting:
## Instructions
### Step 1: Identify the user's intent
**Trading** (buy, sell, limit orders):
- Read `references/trading.md`
**Discovery** (find markets, prices, events):
- Read `references/discovery-and-research.md`
**Portfolio** (positions, orders, watchlist):
- Read `references/portfolio-and-orders.md`
This pattern keeps the main file concise while making deep documentation available on demand without loading everything upfront.
Platform Compatibility Matrix¶
Not all platforms support all frontmatter fields. The table below shows which fields each platform reads as of the current specification version.
| Field | Claude Code | Codex CLI | Gemini CLI | OpenClaw |
|---|---|---|---|---|
name |
Yes | Yes | Yes | Yes |
description |
Yes | Yes | Yes | Yes |
version |
Yes | Yes | Yes | Yes |
license |
display only | display only | display only | display only |
metadata.author |
display only | display only | display only | display only |
metadata.tags |
display only | display only | display only | display only |
metadata.docs-url |
display only | display only | display only | display only |
allowed-tools |
Yes | No | No | No |
"Yes" means the platform uses the field to affect agent behavior. "display only" means the field is read and shown in skill listings but does not change how the agent operates. "No" means the field is ignored.
The allowed-tools field is Claude Code-specific. On other platforms, the agent uses its default tool allowlist regardless of what this field contains.
Note: This matrix describes Bullpen CLI's implementation of the skill format. Support for other platforms reflects the intended behavior of the emerging standard. Verify specific platform documentation for authoritative compatibility information.
Distributing Skills with a CLI Tool¶
The recommended pattern for CLI tools is to embed skill files directly in the binary and write them to disk via an install command:
# Install skills to all detected AI agent platforms
mytool skill install
# Install to a specific platform
mytool skill install --claude
mytool skill install --codex
# Install to a specific path
mytool skill install --path /custom/path/
# Uninstall
mytool skill uninstall
Embedding skill files in the binary (using include_str!() in Rust or equivalent) means the skill is always in sync with the binary version, works offline, and requires no network access at install time.
When the binary is upgraded, the skills should be re-written automatically so the installed skill version tracks the binary version.
See Also¶
- Bullpen CLI Skill — live example skill for the Bullpen CLI tool
- Bullpen Bracket Skill — live example skill for the bracket contest feature