GenerateSaaS

AI skills

One folder where you write your product's skills - instructions your AI loads on demand - reaching the assistant, external MCP clients, and Mastra Studio with no wiring.

A skill is prose your AI reads when it judges the skill relevant: a refund policy, a house style guide, the steps a support agent must follow. Instructions you would otherwise paste into every prompt live once in packages/ai/skills.

The folder ships empty. Everything in it is yours, and generatesaas update never merges into a folder it did not create.

Write one

Create packages/ai/skills/<name>/SKILL.md. The folder name and the name field must match.

---
name: refund-policy
description: Use when a customer asks about a refund, a chargeback, or a downgrade mid-term.
---

Refunds inside 30 days are approved automatically. Past 30 days, check whether the
workspace used metered credits this period before offering a partial refund.

Never promise a specific refund date. Say "within 5 to 10 business days".
FieldRequiredRule
nameyes1-64 characters, lowercase letters, digits and hyphens. Must equal the folder name.
descriptionyes1-1024 characters. Say what it does and when to use it - this is all the model sees when deciding whether to read it.
licensenoAn SPDX identifier, for a skill you publish.
compatibilitynoFree-form notes about what the skill assumes.
user-invocablenofalse keeps it out of direct user invocation. Defaults to true.
metadatanoAnything else you want to carry, nested freely.

Everything below the frontmatter is the body. Keep it under ~500 lines: it rides in a prompt, so length costs tokens on every run that reads it.

Build after every change

pnpm --filter @repo/ai skills:build

This validates each skill and inlines them all into packages/ai/src/skills/skills.generated.ts, which is committed. A test fails when the folder and that module disagree, so a forgotten build is caught in CI rather than in production.

Nothing reads the folder at runtime. A bundled server and Next's output tracing both drop adjacent markdown, so a skill referenced by path resolves in development and throws in production. Inlining at build time is what makes a skill behave identically in both.

Where your skills appear

SurfaceWhat it gets
The in-app assistantThe skills themselves, loaded on demand. With at least one skill it also gains Mastra's skill, skill_search and skill_read tools - see Agents.
Automations and dispatched runsThe skills_list and skill_get tools.
External MCP clientsThe same two tools, plus each skill as a prompt a person can pick by name.
Mastra StudioA read-only listing of the folder, read from disk so a skill you just wrote shows up without a build.

The two tools are registered on every build, even with no skills, so the tool surface never changes shape with your content. With none, skills_list answers that the product has none.

The MCP server does not consult config.ai.enabled, exactly as its existing toolset behaves: a project generated with ai false and mcpServer true still serves these tools.

Not to be confused with

The skills the CLI installs into .claude/skills steer your coding agent while it works on this repository. These steer your product's AI while it serves your users. Never write a product skill into .claude/skills.

On this page