Extend your agent with custom skills and tools using the plugin architecture
The skills system is a plugin architecture that lets you extend your agent with custom tools without modifying core code. Skills work with both Pi and Claude Code backends, sharing the same activation mechanism.
At startup, the agent scans skill directories and loads only the name + description from SKILL.md frontmatter into the system prompt. Full instructions are NOT loaded until the agent decides the skill is relevant.
1
Startup: Agent scans skills
Reads frontmatter from all skills/active/*/SKILL.md files:
---name: brave-searchdescription: Web search and content extraction via Brave Search API. Use for searching documentation, facts, or any web content.---
2
System prompt includes descriptions
# Active Skills- **brave-search** - Web search and content extraction via Brave Search API- **browser-tools** - Interactive browser automation via Chrome DevTools Protocol- **modify-self** - Modify agent code, configuration, personality, cron jobs, skills
3
User requests relevant task
User: "Search for python async tutorials"
4
Agent reads full SKILL.md
Agent sees brave-search description, decides it’s relevant, reads the full instructions:
Allows the agent to modify its own code, configuration, personality, cron jobs, and skills.
---name: modify-selfdescription: Use when a job requires modifying the agent's own code, configuration, personality, cron jobs, skills, or operating system files.---# Modify SelfBefore making any changes, read the project documentation:```bashcat CLAUDE.md
---name: my-skilldescription: Short description of what the skill does and when to use it.---# My Skill## Setup```bashcd skills/my-skill && npm install
Every skill must have a SKILL.md file with YAML frontmatter:
---name: skill-name-in-kebab-casedescription: One sentence describing what the skill does and when to use it.---# Skill Name## SetupAny setup instructions (API keys, dependencies, etc.)## Usage```bashskills/skill-name/script.sh <args>
Detailed usage instructions, examples, flags, etc.
<AccordionGroup> <Accordion title="Frontmatter fields"> - **`name`** - Kebab-case, matches folder name - **`description`** - Single sentence, appears in system prompt under "Active skills" </Accordion> <Accordion title="Body content"> Full usage instructions the agent reads on-demand. Use project-root-relative paths (e.g., `skills/skill-name/script.sh`). </Accordion></AccordionGroup>## Credential SetupSkills that need API keys use LLM-accessible secrets (`AGENT_LLM_*` prefix):```bashnpx thepopebot set-agent-llm-secret BRAVE_API_KEY# Paste API key when prompted# Also add to .env for local development
For multi-line secrets like JSON or PEM files:
npx thepopebot set-agent-llm-secret GOOGLE_CREDENTIALS < credentials.json# Avoid $(cat credentials.json) - breaks on special characters
Security note: LLM-accessible secrets (AGENT_LLM_*) are NOT filtered from the bash environment. The agent can read these values. Only use this prefix for credentials the agent needs to access (skill API keys, browser passwords, etc.).Protected secrets (AGENT_* prefix without LLM_) are filtered by the env-sanitizer extension.
The description appears in the system prompt for every request. Keep it to one sentence:
# Gooddescription: Web search and content extraction via Brave Search API# Bad (too long)description: This skill provides comprehensive web search capabilities using the Brave Search API, including content extraction, freshness filtering, and result pagination
Print results to stdout
Scripts should print results to stdout, not stderr. The agent reads stdout:
# Goodecho "Result: $value"# Bad (agent won't see this)echo "Result: $value" >&2
Handle missing credentials gracefully
Check for required environment variables and provide helpful error messages:
if [ -z "$BRAVE_API_KEY" ]; then echo "Error: BRAVE_API_KEY not set" echo "Set it with: npx thepopebot set-agent-llm-secret BRAVE_API_KEY" exit 1fi