Metadata & Frontmatter
Configure your Spryfile with structured metadata using YAML frontmatter and code cell attributes
Purpose
This guide establishes how to configure Spryfiles using structured metadata at both the document and code cell level. Proper metadata configuration enables environment variable interpolation, dependency management, execution control, and semantic document classification.
Core Principles
- Document frontmatter for global configuration. Environment, versions, and project-level settings.
- Code cell metadata for execution behavior. Dependencies, timeouts, capture settings, and descriptions.
- Environment variables for secrets. Never hardcode sensitive values—always interpolate from
${env.*}. - Semantic classification for structure. Use
doc-classifyto add meaning to document hierarchy. - Keep metadata simple and readable. Avoid deeply nested structures that create cognitive overhead.
Document Frontmatter
Overview
YAML block at the document start, delimited by ---:
---
project: My Application
version: 1.0.0
environment: production
---
# My Application Runbook
...Basic Properties
Common frontmatter properties for project identification and configuration:
---
# Project identification
project: Customer Portal
version: 2.3.1
author: DevOps Team
# Environment configuration
environment: ${env.DEPLOY_ENV}
database_url: ${env.DATABASE_URL}
# Execution settings
timeout: 300
parallel: true
---Environment Variable Interpolation
Reference environment variables using ${env.VAR_NAME} syntax:
---
api_key: ${env.API_KEY}
database: ${env.DB_NAME}
region: ${env.AWS_REGION}
deployment_env: ${env.DEPLOY_ENV}
---At runtime, Spry replaces ${env.VAR_NAME} with the actual environment variable value.
Security: Always use environment variable interpolation for secrets. Never commit sensitive values directly to frontmatter.
Nested Configuration
Complex structures are supported for organizing related settings:
---
database:
host: ${env.DB_HOST}
port: 5432
name: production
pool_size: 10
deployment:
strategy: rolling
replicas: 3
timeout: 300
notifications:
slack: "#deployments"
email: ops@example.com
---Access nested values with dot notation: ${config.database.host}
Code Cell Metadata
Structure
Metadata in the fence info string follows this pattern:
```language identity --flags { json5-attributes }
code
```Parsing Order
The info string is parsed in this sequence:
- Language — First token (e.g.,
bash,sql,python) - Identity — Second token if not a flag (e.g.,
my-task,setup-db) - Flags — POSIX-style options (e.g.,
--dep,--descr) - Attributes — JSON5 object at the end (e.g.,
{ timeout: 60 })
Examples by Complexity
# Minimal: Just language
```bash
echo "anonymous task"
```
# With identity
```bash my-task
echo "named task"
```
# With flags
```bash my-task --descr "Deploy application" --dep build-step
echo "with options"
```
# Full metadata
```bash deploy-app --descr "Deploy to prod" --dep build { timeout: 300, retry: 3 }
./deploy.sh
```Common Flags Reference
| Flag | Alias | Description | Example |
|---|---|---|---|
--descr | -d | Task description | --descr "Build Docker image" |
--dep | Dependency on another task | --dep build-step | |
--capture | Output capture path | --capture results.txt | |
--interpolate | -I | Enable template interpolation | --interpolate |
--injectable | Mark as injectable for PARTIALs | --injectable |
Flag Examples
# Task with description
```bash build-image -d "Build production Docker image"
docker build -t myapp:latest .
```
# Task with dependency
```bash deploy --dep build-image
kubectl apply -f deployment.yaml
```
# Task with output capture
```bash check-status --capture status.log
curl -s https://api.example.com/health
```
# Task with interpolation enabled
```bash show-config -I
echo "Database: ${config.database.host}"
echo "Version: ${config.version}"
```JSON5 Attributes
Extended configuration using JSON5 format for complex execution parameters:
```bash long-task {
timeout: 300,
retry: 3,
retryDelay: 10,
env: {
VERBOSE: "true",
LOG_LEVEL: "debug"
}
}
./long-running-script.sh
```JSON5 Features
JSON5 allows more readable configuration:
- Unquoted keys —
timeout: 60instead of"timeout": 60 - Single-line comments —
// This is a comment - Trailing commas —
{ a: 1, b: 2, }is valid - Single-quoted strings —
'string'or"string"
Common Attributes
| Attribute | Type | Description | Example |
|---|---|---|---|
timeout | number | Max execution time (seconds) | timeout: 300 |
retry | number | Number of retry attempts | retry: 3 |
retryDelay | number | Delay between retries (seconds) | retryDelay: 10 |
env | object | Additional environment variables | env: { DEBUG: "1" } |
Section Classification
Add semantic meaning to document structure using doc-classify:
---
doc-classify:
- select: heading[depth="1"]
role: project
- select: heading[depth="2"]
role: phase
- select: heading[depth="3"]
role: task
---Purpose: This classifies document sections semantically, enabling better tooling and automation based on document structure.
Classification Example
---
doc-classify:
- select: heading[depth="1"]
role: application
- select: heading[depth="2"]
role: deployment_stage
- select: heading[depth="3"]
role: operation
---
# Customer Portal
## Build Phase
### Compile Assets
### Run Tests
## Deploy Phase
### Push to Registry
### Update KubernetesSQLPage Configuration
For SQLPage playbooks, configure database and server settings:
---
sqlpage-conf:
database_url: ${env.SPRY_DB}
port: 9628
site_prefix: /app
max_database_pool_connections: 10
listen_on: 0.0.0.0
---Accessing Metadata
In Shell Tasks
Access frontmatter values via environment variables with --interpolate flag:
---
version: 1.2.3
app_name: MyApp
---
```bash show-version --interpolate
echo "Application: ${config.app_name}"
echo "Version: ${config.version}"
```In Materializable Cells
Interpolation is enabled by default in materializable cells (HTML, SQL, etc.):
---
app_name: MyApp
company: Acme Corp
---
```html header
<html>
<head>
<title>${config.app_name} - ${config.company}</title>
</head>
</html>
```Accessing Nested Values
Use dot notation for nested configuration:
---
database:
host: localhost
port: 5432
name: production
---
```bash connect -I
psql -h ${config.database.host} \
-p ${config.database.port} \
-d ${config.database.name}
```Code DEFAULTS Directive
Set default flags for multiple cells using pattern matching:
```code DEFAULTS
sql * --interpolate --injectable
bash * --descr "Automated task"
python * --interpolate { timeout: 60 }
```Pattern syntax:
sql *— Matches all SQL cellsbash setup-*— Matches bash cells starting with "setup-"* test-*— Matches any language with identity starting with "test-"
DEFAULTS Example
```code DEFAULTS
sql * --interpolate --injectable
bash deploy-* --descr "Deployment task" { timeout: 300, retry: 2 }
```
```sql get-users
SELECT * FROM user WHERE active = true;
```
```bash deploy-frontend
npm run deploy
```
```bash deploy-backend
docker-compose up -d
```Best Practices
Configuration Organization
- Use frontmatter for configuration — Environment variables, versions, project settings
- Use cell metadata for behavior — Dependencies, execution control, descriptions
- Interpolate secrets from environment — Never hardcode API keys, passwords, or tokens
- Keep frontmatter simple — Avoid deeply nested structures (3+ levels)
- Document every task — Use
--descrto explain what each cell does
Naming Conventions
| Context | Convention | Example |
|---|---|---|
| Task identities | Kebab-case | build-image, deploy-app |
| Frontmatter keys | Snake_case | database_url, app_name |
| Environment variables | UPPER_SNAKE | DATABASE_URL, API_KEY |
Security Guidelines
Never commit secrets to frontmatter:
api_key: abc123xyzapi_key: ${env.API_KEY}
Always use environment variable interpolation for:
- API keys and tokens
- Database passwords
- Service credentials
- Private URLs or endpoints
Validation and Debugging
Inspect Parsed Metadata
Validate your Spryfile's metadata structure:
spry axiom inspect myfile.mdOutput shows:
- Parsed frontmatter structure
- All code cell metadata
- Applied DEFAULTS
- Section classifications
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Interpolation not working | Missing --interpolate flag | Add -I or --interpolate |
| Invalid JSON5 | Syntax error in attributes | Validate JSON5 syntax |
| Environment variable empty | Variable not set | Export variable before running |
| Flag not recognized | Typo in flag name | Check flag reference table |
Complete Example
---
# Project metadata
project: Customer Portal
version: 2.1.0
author: DevOps Team
# Environment configuration
environment: ${env.DEPLOY_ENV}
api_key: ${env.API_KEY}
# Database settings
database:
host: ${env.DB_HOST}
port: 5432
name: customer_portal
# Deployment settings
deployment:
strategy: rolling
replicas: 3
timeout: 300
# Section classification
doc-classify:
- select: heading[depth="1"]
role: project
- select: heading[depth="2"]
role: phase
---
# Customer Portal Deployment
## Build Phase
```code DEFAULTS
bash * { timeout: 300, retry: 2 }
```
```bash install-deps --descr "Install application dependencies"
npm ci
```
```bash build-app --descr "Build production bundle" --dep install-deps
npm run build
```
```bash build-image --descr "Build Docker image" --dep build-app
docker build -t customer-portal:${config.version} .
```
## Deploy Phase
```bash push-image --descr "Push to registry" --dep build-image
docker push customer-portal:${config.version}
```
```bash deploy-k8s --descr "Deploy to Kubernetes" --dep push-image -I {
timeout: 600,
env: { KUBECONFIG: "${env.KUBECONFIG}" }
}
kubectl set image deployment/customer-portal \
app=customer-portal:${config.version}
kubectl rollout status deployment/customer-portal
```
```bash verify-health --descr "Verify deployment health" --dep deploy-k8s
curl -f https://portal.example.com/health || exit 1
```Quick Reference
Frontmatter Structure
---
key: value
nested:
key: value
env_var: ${env.VAR_NAME}
---Code Cell Structure
```language identity --flag value { json5: "attributes" }
code
```Common Patterns
- Named task:
bash task-name - With description:
bash task --descr "Description" - With dependency:
bash task --dep other-task - With interpolation:
bash task -I - With timeout:
bash task { timeout: 60 } - Full metadata:
bash task -d "Desc" --dep other { timeout: 300 }
How is this guide?
Last updated on