Provides Typer templates, handles registration, and ensures consistency. ALWAYS use this skill when adding or modifying CLI commands. Use when user requests to add/create/implement/build/write a new command (e.g., "add edit command", "create search feature") OR update/modify/change/edit an existing command.
Templates and workflow for adding or updating Typer CLI commands.
<cli_app> refers to the name of your CLI application (e.g., task, myapp, todo).
src/<cli_app>/commands/<command>.pysrc/<cli_app>/commands/__init__.pyFor commands taking arguments directly (<cli_app> add "item").
import typer
from typing import Annotated
from <cli_app>.storage import add_task
from <cli_app>.display import display
from <cli_app>.constants import EXIT_INVALID_INPUT
app = typer.Typer()
@app.command()
def add(
title: Annotated[str, typer.Argument(help="task title")],
priority: Annotated[str, typer.Option("--priority", "-p", help="priority level")] = "low",
):
"""Add a new task."""
if not title.strip():
display.error("Title cannot be empty")
raise typer.Exit(EXIT_INVALID_INPUT)
task = add_task(title=title, priority=priority)
display.success(f"Added '{task.title}'")
For commands with subcommands (<cli_app> db migrate, <cli_app> db status).
import typer
from <cli_app>.storage import storage
from <cli_app>.display import display
app = typer.Typer(help="Database operations.")
@app.command()
def migrate():
"""Run database migrations."""
storage.migrate()
display.success("Migrations complete")
@app.command()
def status():
"""Show database status."""
info = storage.get_status()
display.info(f"Version: {info.version}")
For deletion with confirmation.
import typer
from typing import Annotated
from <cli_app>.storage import get_task, delete_task
from <cli_app>.display import display
from <cli_app>.constants import EXIT_ERROR
app = typer.Typer()
@app.command()
def clear(
task_id: Annotated[int, typer.Argument(help="task ID to delete")],
force: Annotated[bool, typer.Option("--force", "-f", help="skip confirmation")] = False,
):
"""Delete a task permanently."""
task = get_task(task_id)
if not task:
display.error(f"Task {task_id} not found")
raise typer.Exit(EXIT_ERROR)
if not force:
confirm = typer.confirm(f"Delete '{task.title}'?", default=False)
if not confirm:
display.info("Cancelled")
raise typer.Abort()
delete_task(task_id)
display.success(f"Deleted '{task.title}'")
Register in commands/__init__.py:
import typer
from .add import app as add_app
from .clear import app as clear_app
app = typer.Typer(help="<cli_app> CLI.", no_args_is_help=True)
# Single commands - add WITHOUT name
app.add_typer(add_app)
app.add_typer(clear_app)
# Command groups - add WITH name
# app.add_typer(db_app, name="db")
| Rule | Example |
|------|---------|
| Arguments | Annotated[str, typer.Argument(help="...")] |
| Options | Annotated[str, typer.Option("--name", "-n", help="...")] |
| Docstrings | Imperative mood, < 60 chars |
| Output | Always via display module |
| Exit codes | 0=success, 1=error, 2=invalid |
| Destructive | Must have --force flag, default=False confirmation |
npx skills add https-deeplearning-ai/adding-cli-command下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer