Skip to Content

cmdop-skill

Build and publish CMDOP skills β€” self-contained packages that extend the CMDOP agent with new capabilities.

Install

pip install cmdop-skill

Quick Start

Scaffold a new skill

cmdop-skill init

Interactive wizard: name (with PyPI availability check), description, author. Category, tags, and visibility are determined automatically by the server during publish.

Or write one from scratch

from cmdop_skill import Skill, Arg skill = Skill() # name, version, description from pyproject.toml @skill.command async def greet(name: str = Arg(help="Who to greet", required=True)) -> dict: """Say hello.""" return {"message": f"Hello, {name}!"} if __name__ == "__main__": skill.run()

Skill() auto-resolves name, version, description from the nearest pyproject.toml.

Framework Features

  • @skill.command β€” turn async/sync functions into CLI subcommands
  • Arg() β€” declarative arguments with help, required, default, choices, nargs, action
  • @skill.setup / @skill.teardown β€” lifecycle hooks (async)
  • TestClient β€” test harness (client.run() and client.run_cli())
  • pyproject.toml as single source of truth β€” no metadata duplication
  • Auto src/ path β€” src/ is added to sys.path automatically
  • JSON output β€” all commands return {"ok": true, ...} by default

CLI Commands

CommandDescription
init [path]Scaffold a new skill project (interactive wizard)
install <path>Symlink skill into system skills directory
uninstall <name>Remove skill from system skills directory
run <path> <prompt>Run skill via CMDOP SDK
test <path>Run pytest in skill directory
bump [path]Bump version in pyproject.toml (semver)
check-name <name>Check if package name is available on PyPI
release [path]Bump + build + upload to PyPI + publish to CMDOP
publishPublish skill to the CMDOP marketplace
listList your published skills
config set-keySave API key globally
config showShow saved config (key masked)
config resetRemove saved API key

init

cmdop-skill init # scaffold in current directory cmdop-skill init ./skills # scaffold in ./skills/

Also available programmatically:

from cmdop_skill.scaffold import ScaffoldConfig, scaffold_skill from pathlib import Path config = ScaffoldConfig(name="my-skill", description="Does things") files = scaffold_skill(config, target_dir=Path("."))

config

API key is resolved in order: --api-key flag > CMDOP_API_KEY env > saved config > interactive prompt.

cmdop-skill config set-key # interactive (masked input) cmdop-skill config set-key cmdop_xxx # direct cmdop-skill config show cmdop-skill config reset

install / uninstall

cmdop-skill install ./skills/my-skill # Installed my-skill -> ~/Library/Application Support/cmdop/skills/my-skill (symlink) cmdop-skill uninstall my-skill

bump

cmdop-skill bump # patch: 0.1.0 -> 0.1.1 cmdop-skill bump --minor # minor: 0.1.1 -> 0.2.0 cmdop-skill bump --major # major: 0.2.0 -> 1.0.0

check-name

cmdop-skill check-name my-cool-skill # my-cool-skill is available on PyPI cmdop-skill check-name requests # requests is taken on PyPI

release

Full pipeline β€” bump, build, publish to CMDOP marketplace, upload to PyPI:

cmdop-skill release # bump patch + build + PyPI + CMDOP cmdop-skill release -b minor # bump minor cmdop-skill release --no-bump # current version cmdop-skill release --test-pypi # TestPyPI only (skips CMDOP) cmdop-skill release --no-publish # PyPI only (skips CMDOP)

Publish

Only the skill name is required to create a skill on the marketplace. Everything else is automatic:

  • Category β€” determined by the server from manifest keywords
  • Tags β€” extracted from pyproject.toml keywords
  • Description β€” from README / pyproject.toml
  • Visibility β€” public by default
  • Translations β€” generated server-side via LLM (17 languages)
cmdop-skill publish --path . # publish to prod cmdop-skill publish --json # CI mode (no interactive prompts)

Skill Structure

my-skill/ β”œβ”€β”€ pyproject.toml # Package metadata, deps, build config β”œβ”€β”€ Makefile # Dev shortcuts β”œβ”€β”€ README.md β”œβ”€β”€ .gitignore β”œβ”€β”€ skill/ β”‚ β”œβ”€β”€ config.py # SkillConfig manifest (required) β”‚ └── readme.md # LLM system prompt β”œβ”€β”€ src/my_skill/ β”‚ β”œβ”€β”€ __init__.py β”‚ └── _skill.py # Skill commands └── tests/ β”œβ”€β”€ conftest.py └── test_my_skill.py

skill/config.py

Minimal β€” everything is auto-resolved from pyproject.toml:

from cmdop_skill import SkillConfig config = SkillConfig()

Optional fields:

config = SkillConfig( changelog="Fixed timeout handling.", short_description="Brief summary (max 300 chars).", )

Testing

from cmdop_skill import TestClient from my_skill._skill import skill client = TestClient(skill) # Keyword invocation result = await client.run("greet", name="World") assert result["ok"] is True # CLI-style invocation result = await client.run_cli("greet", "--name", "World") assert result["ok"] is True

Python API

ExportDescription
SkillMain class β€” registers commands, runs CLI
ArgArgument descriptor with metadata
SkillConfigTyped skill manifest (pydantic model)
TestClientTest harness
resolve_project_metaResolve metadata from nearest pyproject.toml
generate_manifestGenerate skill/config.py content
publish_skillProgrammatic publish to marketplace
json_output / wrap_result / format_errorOutput formatting helpers
scaffold.ScaffoldConfigPydantic model for scaffold parameters
scaffold.scaffold_skillGenerate a complete skill directory

Example Skills

The cmdop-skills-labΒ  repository contains production-ready example skills:

SkillDescription
ssl-cert-checkerCheck SSL certificate expiry dates for domains
cmdop-coderCode analysis with tree-sitter AST parsing (40+ languages)
cmdop-sdkrouterUnified AI services SDK (14 service groups)
llm-emailSend emails via macOS Mail.app with AppleScript
llm-htmlLLM-optimized HTML cleaning and extraction
tg-notifyRate-limited Telegram notifications with priority queue

Each skill follows the same structure: skill/config.py, skill/readme.md, src/<pkg>/, tests/, Makefile.

# Clone and explore git clone https://github.com/commandoperator/cmdop-skills-lab cd cmdop-skills-lab/libs/ssl-cert-checker pip install -e '.[dev]' make test
Last updated on