Plain CLI Tools

Development guide for stateless, one-shot CLI tools — the most common and simplest type in the WinClaw CLI Tool ecosystem.

Plain CLI is the most common type, suitable for one-shot, stateless operations. Each invocation is independent: receive input, execute the operation, return the result, then exit.

Before reading this page, review the Common Standards that apply to all tool types.

Use Cases

  • Sending messages (agent_feishu)
  • File format conversion (markdown2word, markdown2ppt)
  • Data export (mysql_meta_exporter, pg_meta_exporter)
  • Document operations (agent_excel, agent_word)
  • Search queries (redis_cli)

Architecture

┌─────────┐    Args    ┌───────────┐    Result    ┌─────────┐
│  Caller  │  ──────►  │  CLI Tool  │  ──────►   │  Output │
│ (AI/User)│           │ Execute &  │             │ (JSON)  │
│          │           │   Exit     │             │         │
└─────────┘           └───────────┘             └─────────┘

Each invocation is completely independent — no process lifecycle or state to manage. This is the simplest and most composable tool type.

Project Structure

agent_feishu/
├── main.go
├── go.mod
├── cmd/
│   ├── root.go           # Root command
│   ├── skill.go          # --skill output
│   ├── send_text.go      # Send text subcommand
│   ├── send_image.go     # Send image subcommand
│   ├── search_users.go   # Search users subcommand
│   └── initapi.go        # Initialize credentials subcommand
└── internal/
    └── output/
        └── output.go     # Unified output

Example: agent_feishu

var rootCmd = &cobra.Command{
    Use:   "agent_feishu",
    Short: "A CLI tool for Feishu bot operations, designed for AI agents",
    Long: `agent_feishu is a command-line tool that provides Feishu (Lark) bot operations...

Quick Start:
  agent_feishu initapi --app-id "cli_xxx" --app-secret "xxx"
  agent_feishu send-text --receive-id "ou_xxx" --receive-type "open_id" --text "Hello!"

Use 'agent_feishu --skill' or 'agent_feishu skill' for detailed command specifications.`,
    Version: version,
    Run: func(cmd *cobra.Command, args []string) {
        if showSkill {
            fmt.Print(skillSpec)
            return
        }
        cmd.Help()
    },
}

func init() {
    rootCmd.CompletionOptions.DisableDefaultCmd = true
    rootCmd.PersistentFlags().BoolVar(&jsonOutput, "json", false,
        "Output in JSON format: {success, data, error}")
    rootCmd.Flags().BoolVar(&showSkill, "skill", false,
        "Show the detailed command specification for agent_feishu")
}

Development Checklist

  • Root command has --help (Long description with feature overview, Quick Start, command list)
  • Root command has --skill flag and skill subcommand
  • Every subcommand has proper --help (with parameter descriptions and examples)
  • Global --json flag is supported
  • Output format follows {success, data, error} spec
  • Has version subcommand or --version flag