---
title: "Chapter 10: Skills System"
description: "Build an extensible skill system where capabilities are loaded on-demand from SKILL.md files. Add image and video generation."
type: lesson
order: 10
chapter: "03-advanced"
---

# Chapter 10: Skills System

## What We're Building

Skills are self-contained capabilities that the agent loads on-demand. Unlike tools (which are always available as function definitions), skills are documented instructions that the agent reads when needed. This keeps the context window lean — skill instructions only take up tokens when relevant.

Skills have:

- **Frontmatter**: Name, description, and metadata that's always visible to the agent
- **Body**: Full instructions, examples, and command references — only loaded when needed

## Step 1: Build the Skill System

Paste this prompt:

> We want to add "skills" to the system. Create a skills directory, and inside of that have a bunch of directories with skills in them. Each will have a SKILL.md file, and there's frontmatter that describes how to use it. Have all the system prompts include that frontmatter in them with instructions that when you need to do a task, load in the rest of the SKILL.md that explains how to do it. This system should also load in all the frontmatter of the agents, so that each agent will have access to all of them. Have an example skill called big_text that uses figlet to make a banner.

### The Skill Loader

The `loadSkills` function in `src/prompts/index.ts` scans the `skills/` directory:

```typescript
function loadSkills(): string {
  const skillsDir = path.join(process.cwd(), "skills");
  if (!fs.existsSync(skillsDir)) return "";

  const skills = fs
    .readdirSync(skillsDir)
    .map((dir) => {
      const skillPath = path.join(skillsDir, dir, "SKILL.md");
      if (fs.existsSync(skillPath)) {
        const content = fs.readFileSync(skillPath, "utf-8");
        const { metadata } = parseFrontMatter(content);
        return { dir, ...metadata };
      }
      return null;
    })
    .filter((s): s is Record<string, any> => s !== null);

  let output = "\n\n# Available Skills\n";
  output +=
    "The following skills are available. If you need to perform a task " +
    "related to one of these skills, you MUST read the full instruction file at " +
    "`skills/<skill_directory>/SKILL.md` using the `read_file` tool.\n\n";

  skills.forEach((s) => {
    output += `- Name: ${s.name || s.dir}\n`;
    if (s.description) output += `  Description: ${s.description}\n`;
    output += `  Path: skills/${s.dir}/SKILL.md\n`;
  });

  return output;
}
```

This gets injected into every agent's system prompt. The agent sees the skill names, descriptions, and instructions to load the full file when needed.

## Step 2: Create the big_text Skill

The agent creates `skills/big_text/SKILL.md`:

```markdown
---
name: big_text
description: Create ASCII art banners using figlet
---

# Big Text Skill

## Basic Usage

figlet "Hello World"

## Specifying Fonts

figlet -f slant "Hello"

## Font Showcase

### Standard & Clean

- standard: Default font
- big: Larger version
- slant: Slanted/italic
- small: Compact

### 3D & Shadows

- shadow: Drop shadow effect
- larry3d: 3D block letters
- block: Heavy block letters

### Script & Cursive

- script: Connected cursive
- cursive: Cursive variant
```

> update the big_text SKILL to use examples of each of the different fonts and make sure that you are extremely complete

## Step 3: Add Image Generation

First, get a Gemini API key (from [Google AI Studio](https://aistudio.google.com/)) and add it to `.env`:

```bash
echo 'GEMINI_API_KEY=your-gemini-key-here' >> .env
```

Paste:

> Add 2 skills, one to generate images and the other to generate videos. Use the "npx @the-focus-ai/nano-banana" command, and look through how it works before writing out the skill. do some research first on the best ways to prompt these models, and incorporate your findings in the skill.

### The Image Generation Skill

`skills/generate_image/SKILL.md`:

```markdown
---
name: generate_image
description: Generate or edit images using Gemini via @the-focus-ai/nano-banana
---

## Requirements

- npx must be installed
- GEMINI_API_KEY must be set

## Prompt Structure (Imagen 3)

**Subject** → **Context/Background** → **Style/Medium** → **Technical Specs**

### Examples

# Generate new image

npx @the-focus-ai/nano-banana "A futuristic city at sunset, cyberpunk style" --output "images/city.png"

# Edit existing image

npx @the-focus-ai/nano-banana "Make the sky purple" --file "original.png" --output "edited.png"

# Fast generation

npx @the-focus-ai/nano-banana "A cute cartoon cat" --flash --output "images/cat.png"
```

### The Video Generation Skill

`skills/generate_video/SKILL.md`:

```markdown
---
name: generate_video
description: Generate videos using Veo via @the-focus-ai/nano-banana
---

## Prompt Structure (Veo)

**Camera Movement** → **Subject** → **Action** → **Setting** → **Aesthetics** → **Audio**

## Parameters

- --video prompt: Description of the video
- --output path: Output file (.mp4)
- --resolution: "1080p" or "720p"
- --duration: 4, 6, or 8 seconds
- --video-fast: Use faster, cheaper model
- --file: Animate a static image
- --reference: Character consistency

### Examples

# Image-to-Video

npx @the-focus-ai/nano-banana --video "The character smiles" --file "image.png" --output "smile.mp4"

# Fast mode

npx @the-focus-ai/nano-banana --video "Robot dancing" --video-fast --duration 4 --output "dance.mp4"
```

## Step 4: Test the Skills

```
make a banner that says HELLO WORLD in big letters
```

The agent should: see "big_text" in the available skills → read `skills/big_text/SKILL.md` → run `figlet "HELLO WORLD"`.

```
generate an image of a diagram of the STEPS.md file
```

You should get an image visualizing the steps from your `STEPS.md` file as a flow diagram.

```
make a 720p 8 second video animating that image
```

## Step 5: Ensure Dynamic Loading

Paste:

> i want to make sure that no tools, agents, or skills are hard coded inside of the agent prompt and are driven by metadata

The agent verifies that everything is loaded dynamically:

- Tools: defined in `src/tools/index.ts`
- Agents: discovered from `src/prompts/*.md` with frontmatter
- Skills: discovered from `skills/*/SKILL.md` with frontmatter

No hardcoded lists. Add a new `.md` file to `src/prompts/`, restart, and it appears. Add a new directory to `skills/`, restart, available.

## Step 6: The Full Skills Directory

```
skills/
├── big_text/
│   └── SKILL.md          # figlet ASCII art banners
├── generate_image/
│   └── SKILL.md          # Image generation via nano-banana (Imagen)
└── generate_video/
    └── SKILL.md          # Video generation via nano-banana (Veo)
```

## Why Skills Are Different from Tools

|              | Tools                                   | Skills                                       |
| ------------ | --------------------------------------- | -------------------------------------------- |
| **Cost**     | Always in context (small definitions)   | Only loaded when needed (large instructions) |
| **Usage**    | Model selects via function calling      | Model reads SKILL.md then uses bash          |
| **Content**  | JSON schema parameters                  | Markdown documentation with examples         |
| **Best for** | Atomic operations (read, write, search) | Complex workflows (generate image, deploy)   |

Skills are documentation that makes the agent self-extending. Add a new SKILL.md, and the agent learns a new capability without any code changes.

---

[← Chapter 09](/build-ai-coding-agent/03-advanced/09-subagents/) · [Next: Chapter 11 →](/build-ai-coding-agent/03-advanced/11-polish/)
