Skip to main content
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.

What is a Skill?

A skill is a folder containing:
  • SKILL.md - Instructions for the agent (YAML frontmatter + markdown)
  • Script files - Bash, Node.js, Python, or any executable
  • package.json (optional) - npm dependencies for Node.js skills
No new tools are registered. No TypeScript. No build step. The agent teaches itself by reading SKILL.md, then runs scripts via bash.

How Skills Work

Progressive Disclosure (On-Demand Loading)

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-search
description: 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:
cat skills/active/brave-search/SKILL.md
5

Agent executes skill

skills/brave-search/search.js "python async tutorials"

Skill Directory Structure

skills/
├── brave-search/           # Available skill
│   ├── SKILL.md
│   ├── package.json
│   ├── search.js
│   └── content.js
├── browser-tools/          # Available skill
│   ├── SKILL.md
│   ├── package.json
│   ├── browser-nav.js
│   ├── browser-eval.js
│   └── ...
└── active/                 # Activated skills (symlinks)
    ├── brave-search -> ../brave-search
    ├── browser-tools -> ../browser-tools
    ├── modify-self -> ../modify-self
    └── llm-secrets -> ../llm-secrets
Both .pi/skills and .claude/skills symlink to skills/active/, so one activation controls both agent backends.

Built-in Skills

The Pope Bot includes several default skills:

browser-tools

Interactive browser automation via Chrome DevTools Protocol (CDP).
  • Navigate to URLs (new tabs or current tab)
  • Execute JavaScript in active tab
  • Take screenshots
  • Interactive element picker (user selects elements visually)
  • Extract page content as markdown
  • Inspect cookies and session state
skills/browser-tools/browser-start.js              # Fresh profile
skills/browser-tools/browser-start.js --profile    # Copy user's profile
Web search and content extraction via Brave Search API.
skills/brave-search/search.js "python async tutorials"              # 5 results
skills/brave-search/search.js "python async tutorials" -n 10        # More results
skills/brave-search/search.js "python async tutorials" --content    # Include page content
skills/brave-search/search.js "python async tutorials" --freshness pw  # Last week
Requires Brave Search API key:
npx thepopebot set-agent-llm-secret BRAVE_API_KEY
# Paste API key when prompted

modify-self

Allows the agent to modify its own code, configuration, personality, cron jobs, and skills.
---
name: modify-self
description: Use when a job requires modifying the agent's own code, configuration, personality, cron jobs, skills, or operating system files.
---

# Modify Self

Before making any changes, read the project documentation:

```bash
cat CLAUDE.md

Activating Skills

Skills are activated by symlinking into skills/active/:
ln -s ../brave-search skills/active/brave-search
Skill activation is immediate for new jobs. Existing jobs use the skills active when the job branch was created.

Building a New Skill

Simple Bash Skill

Most common pattern - single script, no dependencies.
1

Create skill directory

mkdir -p skills/transcribe
2

Write SKILL.md

skills/transcribe/SKILL.md
---
name: transcribe
description: Speech-to-text transcription using Groq Whisper API. Supports m4a, mp3, wav, ogg, flac, webm.
---

# Transcribe

Speech-to-text using Groq Whisper API.

## Setup
Requires GROQ_API_KEY environment variable.

## Usage
```bash
skills/transcribe/transcribe.sh <audio-file>
</Step>

<Step title="Write script">
```bash skills/transcribe/transcribe.sh
#!/bin/bash
if [ -z "$1" ]; then echo "Usage: transcribe.sh <audio-file>"; exit 1; fi
if [ -z "$GROQ_API_KEY" ]; then echo "Error: GROQ_API_KEY not set"; exit 1; fi
curl -s -X POST "https://api.groq.com/openai/v1/audio/transcriptions" \
  -H "Authorization: Bearer $GROQ_API_KEY" \
  -F "file=@${1}" \
  -F "model=whisper-large-v3-turbo" \
  -F "response_format=text"
3

Make executable

chmod +x skills/transcribe/transcribe.sh
4

Activate

ln -s ../transcribe skills/active/transcribe

Node.js Skill with Dependencies

Use when bash + curl isn’t sufficient (HTML parsing, API clients, etc.).
1

Create skill directory

mkdir -p skills/my-skill
2

Write package.json

skills/my-skill/package.json
{
  "name": "my-skill",
  "version": "1.0.0",
  "type": "module",
  "dependencies": {
    "axios": "^1.6.0",
    "cheerio": "^1.0.0"
  }
}
3

Write SKILL.md

skills/my-skill/SKILL.md
---
name: my-skill
description: Short description of what the skill does and when to use it.
---

# My Skill

## Setup
```bash
cd skills/my-skill && npm install

Usage

skills/my-skill/script.js <args>
</Step>

<Step title="Write script">
```javascript skills/my-skill/script.js
#!/usr/bin/env node
import axios from 'axios';
import * as cheerio from 'cheerio';

const url = process.argv[2];
if (!url) {
  console.error('Usage: script.js <url>');
  process.exit(1);
}

const response = await axios.get(url);
const $ = cheerio.load(response.data);
const title = $('title').text();
console.log(title);
4

Make executable and activate

chmod +x skills/my-skill/script.js
ln -s ../my-skill skills/active/my-skill
In Docker, skill dependencies are installed automatically by the entrypoint script. Locally, run npm install once in the skill directory.

SKILL.md Format

Every skill must have a SKILL.md file with YAML frontmatter:
---
name: skill-name-in-kebab-case
description: One sentence describing what the skill does and when to use it.
---

# Skill Name

## Setup

Any setup instructions (API keys, dependencies, etc.)

## Usage

```bash
skills/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 Setup

Skills that need API keys use LLM-accessible secrets (`AGENT_LLM_*` prefix):

```bash
npx 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.

External Skills Repository

The pi-skills repository contains additional skills compatible with Pi, Claude Code, Codex CLI, Amp, and Droid:
SkillDescription
brave-searchWeb search and content extraction via Brave Search
browser-toolsInteractive browser automation via Chrome DevTools Protocol
gccliGoogle Calendar CLI for events and availability
gdcliGoogle Drive CLI for file management and sharing
gmcliGmail CLI for email, drafts, and labels
transcribeSpeech-to-text transcription via Groq Whisper API
vscodeVS Code integration for diffs and file comparison
youtube-transcriptFetch YouTube video transcripts
git clone https://github.com/badlogic/pi-skills ~/pi-skills

Runtime Flow Example

Complete runtime flow using brave-search:
1

Agent starts, scans skills

Reads frontmatter from skills/active/brave-search/SKILL.md:
name: brave-search
description: Web search and content extraction via Brave Search API
2

Description added to system prompt

# Active Skills
- **brave-search** - Web search and content extraction via Brave Search API
3

User requests search

User: "Search for python async tutorials"
4

Agent reads full SKILL.md

Agent decides brave-search is relevant, reads complete instructions:
cat skills/active/brave-search/SKILL.md
5

Agent runs search script

skills/brave-search/search.js "python async tutorials"
6

Script executes

Script reads $BRAVE_API_KEY from environment, calls Brave Search API, prints results to stdout.
7

Agent reads results

Agent processes search results and responds to user.

Best Practices

Always use paths relative to project root in SKILL.md examples:
# Good
skills/brave-search/search.js "query"

# Bad
./search.js "query"
cd skills/brave-search && ./search.js "query"
The description appears in the system prompt for every request. Keep it to one sentence:
# Good
description: 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
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 1
fi

Next Steps

Docker Agent

Learn how skills run inside job containers

Architecture

Review the complete system architecture

Build docs developers (and LLMs) love