Skill files are modular Markdown documents that teach agents how to perform specific recurring tasks correctly in your codebase. Where AGENTS.md describes the whole project and its boundaries, a skill describes how to do one particular job — and is only injected into context when it is relevant.

What a skill file is

A skill is a self-contained how-to document written for your AI agents. It captures institutional knowledge that would otherwise live in a Confluence page, a Slack thread, or a senior engineer's head: the exact steps, pitfalls, and conventions for a specific type of work in your repository.

AGENTS.md sets the scope and rules for all agents. Skills are the playbooks agents consult when they encounter a known pattern.

When to write a skill

Write a skill when any of these apply:

  • Repeated patterns — The same multi-step operation comes up often (database migrations, adding a new API endpoint, cutting a release).
  • Codebase-specific conventions — The "right way" diverges from public documentation or common defaults (a custom ORM, a non-standard branching model).
  • Pitfall prevention — An agent has made the same class of mistake more than once. A skill codifies the correction.
  • Onboarding acceleration — Human teams document these things for new engineers. Agents benefit from the same documentation.

File format and naming

Skill files live under skills/ in your project root. Use a descriptive, kebab-case filename:

skills/
  db-migration.md
  api-contract-change.md
  pr-workflow.md
  data-backfill.md

Each file begins with YAML frontmatter:

---
title: "Database Migrations"
tags: ["database", "migrations", "postgres"]
applies_to: ["*.py", "alembic/**"]
---

...skill body...
Frontmatter key Purpose
title Human-readable name shown in The Station and command menu
tags Keywords used by qmd vsearch for semantic matching
applies_to Glob patterns — files that, when mentioned in a task, increase the relevance score

How ChooChoo selects skills

When an agent starts a task, ChooChoo uses qmd vsearch — a semantic vector search over your skill files — to find the most relevant skills for the current task description and inject only those into the context window.

To write skills that surface reliably:

  • Start the body with a one-sentence summary. qmd vsearch uses the opening text heavily for matching. "How to write and run a database migration using Alembic in this app" beats "Database stuff".
  • Use the same vocabulary as task descriptions. If engineers say "cut a release", write "cut a release" in the skill — not "create a release tag".
  • Tag accurately. Tags are used for exact-match boosting in addition to semantic search.
  • Keep skills focused. One skill per distinct task type. Broad skills surface for the wrong tasks; narrow skills surface for the right ones.

Full example

skills/db-migration.md:

---
title: "Database Migrations"
tags: ["database", "migrations", "postgres", "alembic"]
applies_to: ["alembic/**", "app/models/**"]
---

How to write and run a database migration using Alembic in this app.

## Context

This app uses PostgreSQL with Alembic for schema migrations. All migrations
live under `alembic/versions/`. The Alembic config is in `alembic.ini`.
Never edit migration files after they have been merged to main.

## Steps

1. **Generate the migration file:**

alembic revision --autogenerate -m "describe_your_change"

This creates a new file in `alembic/versions/`. Review it before proceeding.

2. **Edit the generated file** if autogenerate missed anything (e.g. index
additions, custom types). Check both `upgrade()` and `downgrade()`.

3. **Apply locally:**

alembic upgrade head


4. **Run the test suite** to confirm nothing is broken:

mise run test


5. **Commit the migration file** together with any model changes in the same
commit. Never commit them separately.

## Pitfalls

- **Do not use `--autogenerate` alone for column renames.** Alembic treats a
rename as drop + add, which destroys data. Write the migration by hand.
- **Check for circular imports.** Alembic imports your models at migration
time; circular imports cause `sqlalchemy.exc.InvalidRequestError`.
- **Do not backfill large tables in the migration.** Write a separate backfill
script and run it asynchronously after the migration.

Registering skills in choochoo.toml

Point ChooChoo at your skills directory:

[context.skills]
sources = ["skills/**/*.md"]

Multiple globs are supported — you can pull skills from subdirectories or from a shared monorepo skills library:

[context.skills]
sources = [
  "skills/**/*.md",
  "../shared-skills/**/*.md",
]

ChooChoo discovers all matching files at startup. Skills are not injected all at once — qmd vsearch selects the relevant subset per task.

See also

  • Context Compilation — How skills integrate with AGENTS.md and JIT context injection.
  • Configuration — Full choochoo.toml key reference including context.skills.