Creating Capabilities
This guide walks you through creating a new capability from scratch, including all the files you might need and best practices for structuring your capability.
Quick start with capability new
Section titled “Quick start with capability new”The fastest way to create a capability is with the CLI:
omnidev capability new my-capabilityThe capability ID must be lowercase kebab-case (e.g., my-capability, api-client, tasks).
Output location
Section titled “Output location”By default, capabilities are created at capabilities/<id>. You can specify a custom path:
omnidev capability new my-cap --path ./custom/locationGenerated files
Section titled “Generated files”capabilities/my-capability/├── capability.toml # Capability metadata├── skills/│ └── getting-started/│ └── SKILL.md # Skill template├── rules/│ └── coding-standards.md # Rule template└── hooks/ ├── hooks.toml # Hook configuration └── example-hook.sh # Example hook scriptDelete any files you don’t need after creation.
Example output
Section titled “Example output”omnidev capability new api-client✓ Created capability: Api Client Location: capabilities/api-client
Files created: - capability.toml - skills/getting-started/SKILL.md - rules/coding-standards.md - hooks/hooks.toml - hooks/example-hook.sh
💡 To add this capability as a local source, run: omnidev add cap --local ./capabilities/api-clientWorkflow: Creating and using local capabilities
Section titled “Workflow: Creating and using local capabilities”-
Create a new capability:
Terminal window omnidev capability new my-cap -
Add it as a local source:
Terminal window omnidev add cap --local ./capabilities/my-cap -
The capability is now tracked in
omni.tomland synced to your agents.
Manual setup
Section titled “Manual setup”If you prefer to create capabilities manually, here’s what you need.
Required: capability.toml
Section titled “Required: capability.toml”Every capability needs a capability.toml file at its root:
[capability]id = "my-capability"name = "My Capability"version = "1.0.0"description = "A short description of what this capability does."Field notes:
- id: unique, kebab-case identifier. Avoid reserved names like
fs,path,react, ortypescript. - name: human-readable title.
- version: semantic version string.
- description: short summary shown in listings.
Optional: Programmatic exports (index.ts)
Section titled “Optional: Programmatic exports (index.ts)”For dynamic content, create an index.ts file:
import type { CapabilityExport } from "@omnidev-ai/core";
export default { cliCommands: { /* routes */ }, docs: [/* DocExport */], rules: [/* markdown strings */], skills: [/* SkillExport */], gitignore: ["mycap/"], sync: async () => { /* setup */ }} satisfies CapabilityExport;JavaScript with JSDoc
Section titled “JavaScript with JSDoc”If you prefer JavaScript:
/** * @type {import("@omnidev-ai/core").CapabilityExport} */export default { gitignore: ["mycap/"]};TypeScript types
Section titled “TypeScript types”OmniDev exports types from @omnidev-ai/core for type-checking your capabilities:
import type { CapabilityExport, SkillExport, DocExport, FileContent} from "@omnidev-ai/core";Best practices
Section titled “Best practices”Naming
Section titled “Naming”- Use kebab-case for capability IDs (
my-capability). - Use lowercase command names (
deploy,status). - Avoid reserved names like
fs,path,react,typescript.
Structure
Section titled “Structure”- Keep CLI routes in
cli.tsand export them fromindex.ts. - Group related rules/docs/skills into focused subfolders.
- Use sync hooks sparingly and keep them idempotent.
Static vs programmatic
Section titled “Static vs programmatic”- Prefer static files for stable content.
- Use programmatic exports for dynamic or generated content.
- When both are used, ensure output is deterministic.
Gitignore patterns
Section titled “Gitignore patterns”Add patterns via programmatic export so OmniDev can manage them:
export default { gitignore: ["mycap/", "*.mycap.log"]} satisfies CapabilityExport;Sync hooks
Section titled “Sync hooks”Use a sync hook for one-time setup (create directories, seed config). Keep it safe to run multiple times.
export default { sync: async () => { // create folders, write defaults, etc. }} satisfies CapabilityExport;Testing your capability
Section titled “Testing your capability”omnidev capability enable my-capabilityomnidev syncomnidev mycap --help # if you added CLI commandsPublishing your capability
Section titled “Publishing your capability”Once your capability is ready, you can share it by:
- Pushing to GitHub: Others can reference it with
github:user/repo - Sharing the directory: For local team use via
file://sources
See Capability Sources for how others can add your capability.