Creating Recipes
A recipe is a directory with a ra.config.yaml and optional skills, middleware, and documentation. This guide covers the layout, authoring, and sharing of recipes.
Directory layout
my-recipe/
ra.config.yaml # Required: agent configuration
skills/ # Optional: skill definitions
my-skill/
SKILL.md # Skill prompt with YAML frontmatter
references/ # Optional: files the model can consult
scripts/ # Optional: scripts the model can run
middleware/ # Optional: middleware hooks
token-budget.ts
README.md # Optional: usage instructionsThe only required file is ra.config.yaml. Everything else is optional.
Config file
A recipe config uses the same format as any ra.config.yaml:
agent:
provider: anthropic
model: claude-sonnet-4-6
systemPrompt: |
You are a helpful coding assistant.
tools:
builtin: true
skillDirs:
- ./skills
middleware:
afterModelResponse:
- ./middleware/token-budget.ts
maxIterations: 50
thinking: medium
compaction:
enabled: true
threshold: 0.8Paths in skillDirs, middleware, and systemPrompt (when pointing to a file) are resolved relative to the recipe directory, not the working directory. This means recipes are portable.
Environment variable interpolation
Use ${} syntax for configurable values:
agent:
provider: ${PROVIDER:-anthropic}
model: ${MODEL:-claude-sonnet-4-6}
app:
mcpServers:
- name: github
transport: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-github"]
env:
GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN:-}"${VAR:-default} uses the default when unset or empty. ${VAR} errors if unset.
Adding skills
Create a SKILL.md file inside a subdirectory of skills/:
---
name: code-review
description: Reviews code for bugs, style, and correctness
---
You are a senior code reviewer. Analyze the provided code for:
1. **Correctness** — logic errors, edge cases, off-by-one
2. **Security** — injection, XSS, unsafe operations
3. **Performance** — unnecessary allocations, O(n²) loops
4. **Readability** — naming, structure, comments
Output findings grouped by severity: critical, warning, suggestion, nitpick.The YAML frontmatter (name, description) is required. The body is the skill prompt injected into the conversation.
References
Add files to skills/<name>/references/ that the model can consult on demand. These aren't injected automatically — the model reads them when relevant.
skills/code-review/
SKILL.md
references/
review-guide.md # Detailed checklist
style-rules.md # Project conventionsScripts
Add executable scripts to skills/<name>/scripts/ for the model to run via the Bash tool:
skills/debugger/
SKILL.md
scripts/
collect-logs.sh # Gather diagnostic infoAdding middleware
Create TypeScript files in middleware/ and reference them in your config:
// middleware/token-budget.ts
export default async (ctx) => {
const budget = parseInt(process.env.RA_TOKEN_BUDGET || '200000', 10)
const used = (ctx.loop.usage.inputTokens + ctx.loop.usage.outputTokens)
if (used > budget) {
ctx.stop(`Token budget exceeded: ${used} / ${budget}`)
}
}agent:
middleware:
afterModelResponse:
- ./middleware/token-budget.tsSee Middleware for all available hooks and the context object shape.
Publishing recipes
Repository layout
For a repo with a single recipe, put ra.config.yaml at the root:
my-recipe-repo/
ra.config.yaml
skills/
README.mdFor a repo with multiple recipes, use a recipes/ directory:
my-recipes-repo/
recipes/
coding-agent/
ra.config.yaml
skills/
review-agent/
ra.config.yaml
skills/
README.mdThe installer auto-detects both layouts. Multi-recipe repos install each recipe as owner/recipe-name.
GitHub
Push your repo to GitHub. Users install with:
ra recipe install user/my-recipe-repoFor multi-recipe repos, all recipes are installed at once under user/recipe-name.
npm
Publish as an npm package. Users install with:
ra recipe install npm:my-recipe@1.0URL
Host a .tar.gz archive anywhere. Users install with:
ra recipe install https://example.com/my-recipe.tar.gzTesting locally
Run a recipe directly without installing:
# Point --config at the recipe config
ra --config ./my-recipe/ra.config.yaml
# Or use --recipe with a local path
ra --recipe ./my-recipe "test prompt"Verify skills load correctly:
ra --config ./my-recipe/ra.config.yaml --show-configExample: minimal recipe
A recipe that reviews code with a token budget:
mini-reviewer/
ra.config.yaml
skills/
review/
SKILL.md
middleware/
token-budget.tsra.config.yaml:
agent:
provider: ${PROVIDER:-anthropic}
model: ${MODEL:-claude-sonnet-4-6}
skillDirs:
- ./skills
middleware:
afterModelResponse:
- ./middleware/token-budget.ts
maxIterations: 10
compaction:
enabled: true
threshold: 0.8skills/review/SKILL.md:
---
name: review
description: Concise code review
---
Review the provided code. For each issue found, output:
- **Severity**: critical | warning | suggestion
- **Location**: file and line
- **Issue**: what's wrong
- **Fix**: how to fix itmiddleware/token-budget.ts:
export default async (ctx) => {
const budget = parseInt(process.env.RA_TOKEN_BUDGET || '200000', 10)
const used = (ctx.loop.usage.inputTokens + ctx.loop.usage.outputTokens)
if (used > budget) ctx.stop(`Token budget exceeded: ${used} / ${budget}`)
}Usage:
git diff | ra --config mini-reviewer/ra.config.yaml "Review this diff"See also
- Recipes — pre-built recipes and usage patterns
- Skills — skill format and loading
- Middleware — hook types and context
- Configuration — all config fields