Naming Conventions
All FrootAI primitives follow strict naming conventions enforced by npm run validate:primitives. The golden rule: lowercase-hyphen for everything.
General Rules
- All files and folders use lowercase-hyphen (kebab-case)
- No underscores, no camelCase, no PascalCase
- No spaces in file or folder names
- UTF-8 encoding (no BOM) on all files
Primitives by Type
Agents (.agent.md)
agents/
├── fai-rag-architect.agent.md ✅ lowercase-hyphen
├── fai-security-reviewer.agent.md ✅ lowercase-hyphen
├── fai-play-01-builder.agent.md ✅ play-specific agent
├── RagArchitect.agent.md ❌ PascalCase
└── rag_architect.agent.md ❌ underscoreNaming pattern: fai-{name}.agent.md
Frontmatter requirements:
---
description: "10+ character description" # Required
tools: ["codebase", "terminal"] # Optional
model: ["gpt-4o", "gpt-4o-mini"] # Optional (array)
waf: ["security", "reliability"] # Optional
plays: ["01-enterprise-rag"] # Optional
---Instructions (.instructions.md)
instructions/
├── waf-security.instructions.md ✅
├── python-coding.instructions.md ✅
├── rag-patterns.instructions.md ✅
├── WAF_Security.instructions.md ❌ PascalCase + underscore
└── security.md ❌ missing .instructions suffixNaming pattern: {name}.instructions.md
Frontmatter requirements:
---
description: "10+ character description" # Required
applyTo: "**/*.{ts,js,py}" # Required — glob pattern
waf: ["security"] # Optional
---Skills (SKILL.md in folder)
skills/
├── fai-play-initializer/
│ └── SKILL.md ✅ name matches folder
├── fai-rag-indexer/
│ ├── SKILL.md ✅
│ └── index.sh ✅ optional bundled assets
├── PlayInitializer/
│ └── SKILL.md ❌ PascalCase folder
└── fai-play-initializer.md ❌ not in a folderNaming pattern: fai-{name}/SKILL.md (folder name = skill name)
Frontmatter requirements:
---
name: fai-play-initializer # Required — must match folder
description: "10-1024 char description" # Required
---The name field in SKILL.md frontmatter must exactly match the parent folder name. This is validated by CI.
Hooks (hooks.json in folder)
hooks/
├── frootai-secrets-scanner/
│ ├── hooks.json ✅
│ └── scan-secrets.sh ✅ referenced script
├── frootai-tool-guardian/
│ ├── hooks.json ✅
│ └── guard-tools.sh ✅
└── SecretsScanner/
└── hooks.json ❌ PascalCase folderNaming pattern: {name}/hooks.json
Required fields:
{
"version": 1,
"hooks": [
{
"event": "SessionStart",
"steps": [
{
"type": "shell",
"command": "bash ${__dirname}/scan-secrets.sh"
}
]
}
]
}Plugins (plugin.json in folder)
plugins/
├── enterprise-rag/
│ ├── plugin.json ✅
│ └── README.md ✅ recommended
├── EnterpriseRAG/
│ └── plugin.json ❌ PascalCase folder
└── enterprise_rag/
└── plugin.json ❌ underscoreNaming pattern: {name}/plugin.json (folder name = plugin name)
Required fields:
{
"name": "enterprise-rag",
"description": "Complete RAG pipeline with security hooks",
"version": "1.0.0",
"author": { "name": "Your Name" },
"license": "MIT"
}The name field in plugin.json must match the parent folder name.
FAI Manifest (fai-manifest.json)
{
"play": "01-enterprise-rag",
"version": "1.0.0"
}playfield must match the folder name:NN-kebab-caseversionmust be valid semver:X.Y.Z
FAI Context (fai-context.json)
Placed as a sibling to standalone primitives:
agents/
├── fai-rag-architect.agent.md
└── fai-rag-architect/
└── fai-context.jsonSolution Play Folders
solution-plays/
├── 01-enterprise-rag/ ✅ NN-kebab-case
├── 02-ai-landing-zone/ ✅
├── enterprise-rag/ ❌ missing number prefix
└── 01_enterprise_rag/ ❌ underscorePattern: NN-kebab-case where NN is a two-digit number (01–99).
Validation
Run the validation script to check all naming conventions:
npm run validate:primitivesThis checks every primitive file in the repository for:
- Correct file extensions and naming patterns
- Required frontmatter fields
- Name-to-folder matching for skills and plugins
- Valid lifecycle events for hooks
Next Steps
- PR Checklist — full validation requirements for PRs
- How to Contribute — the contribution workflow