Pi has four layers of customization, each serving a different purpose:
```
┌─────────────────────────────────────┐
│ Extensions │ ← TypeScript code. Full runtime access.
│ Custom tools, events, UI, │ Can do anything.
│ commands, providers │
├─────────────────────────────────────┤
│ Skills │ ← Markdown instructions + scripts.
│ On-demand capability packages │ Loaded when the task matches.
│ loaded by the agent │
├─────────────────────────────────────┤
│ Prompt Templates │ ← Markdown snippets.
│ Reusable prompts expanded │ Quick text expansion via /name.
│ via /templatename │
├─────────────────────────────────────┤
│ Themes │ ← JSON color definitions.
│ Visual appearance │ Hot-reload on change.
└─────────────────────────────────────┘
```
### Extensions
TypeScript modules with full runtime access. They can hook into every event, register tools the LLM can call, add commands, render custom UI, override built-in behavior, and register model providers. Extensions are the most powerful customization mechanism.
See the companion doc **Pi-Extensions-Complete-Guide.md** for the full 50KB reference.
### Skills
On-demand capability packages following the [Agent Skills standard](https://agentskills.io). A skill is a directory with a `SKILL.md` file containing instructions the agent follows. Skills are progressive: only their names and descriptions are in the system prompt. The agent reads the full SKILL.md only when the task matches.
**How skills work:**
1. At startup, pi scans for skills and extracts names + descriptions
2. Descriptions are listed in the system prompt
3. When a task matches, the agent uses `read` to load the full SKILL.md
4. The agent follows the instructions, using relative paths for scripts/assets
**Invocation:**
```
/skill:brave-search # Explicit invocation
/skill:pdf-tools extract file.pdf # With arguments
```
**Placement:**
-`~/.agents/skills/` (global — shared across all agents)
-`.agents/skills/` (project, searched up to git root)