Skip to content

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.

The fastest way to create a capability is with the CLI:

Terminal window
omnidev capability new my-capability

The capability ID must be lowercase kebab-case (e.g., my-capability, api-client, tasks).

By default, capabilities are created at capabilities/<id>. You can specify a custom path:

Terminal window
omnidev capability new my-cap --path ./custom/location
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 script

Delete any files you don’t need after creation.

Terminal window
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-client

Workflow: Creating and using local capabilities

Section titled “Workflow: Creating and using local capabilities”
  1. Create a new capability:

    Terminal window
    omnidev capability new my-cap
  2. Add it as a local source:

    Terminal window
    omnidev add cap --local ./capabilities/my-cap
  3. The capability is now tracked in omni.toml and synced to your agents.

If you prefer to create capabilities manually, here’s what you need.

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, or typescript.
  • name: human-readable title.
  • version: semantic version string.
  • description: short summary shown in listings.

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;

If you prefer JavaScript:

/**
* @type {import("@omnidev-ai/core").CapabilityExport}
*/
export default {
gitignore: ["mycap/"]
};

OmniDev exports types from @omnidev-ai/core for type-checking your capabilities:

import type {
CapabilityExport,
SkillExport,
DocExport,
FileContent
} from "@omnidev-ai/core";
  • Use kebab-case for capability IDs (my-capability).
  • Use lowercase command names (deploy, status).
  • Avoid reserved names like fs, path, react, typescript.
  • Keep CLI routes in cli.ts and export them from index.ts.
  • Group related rules/docs/skills into focused subfolders.
  • Use sync hooks sparingly and keep them idempotent.
  • Prefer static files for stable content.
  • Use programmatic exports for dynamic or generated content.
  • When both are used, ensure output is deterministic.

Add patterns via programmatic export so OmniDev can manage them:

export default {
gitignore: ["mycap/", "*.mycap.log"]
} satisfies CapabilityExport;

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;
Terminal window
omnidev capability enable my-capability
omnidev sync
omnidev mycap --help # if you added CLI commands

Once your capability is ready, you can share it by:

  1. Pushing to GitHub: Others can reference it with github:user/repo
  2. Sharing the directory: For local team use via file:// sources

See Capability Sources for how others can add your capability.